The answer to this question discussed a technique on the Apple IIgs for copying memory onto itself. The motivation for the technique was to maximize use of "fast" (2.8MHz) RAM over "slow" (1MHz) RAM shared with the display hardware. Writes to the "fast" memory were shadow-written to "slow" graphics memory.

I vaguely remember someone at the 1993 KansasFest using an oscilloscope to demonstrate that inserting NOP (no operation) instructions would make things faster. I've found a couple of references (article1, article2) that indicate a NOP should be placed between every 13 PEI instructions. This seems to have something to do with bus timing -- alignment would not make a difference here.

How does adding delays improve efficiency?


2 Answers 2



With 2021 knowledge of how the FPI/CYA work, this simply didn't make sense. So I plugged in a logic analyser and timed the Wolfenstein 3D code (NOP every 8 PEI's). I then modified the code to change it to a NOP every 13 PEI's, and finally to remove the NOPs altogether.

These are the results:

  1. NOP every 8 PEI's - 40 PEI's takes 0.179005ms (4.475125µs/PEI)
  2. NOP every 13 PEI's - 39 PEI's takes 0.17446ms (4.473333µs/PEI)
  3. 39 PEI's (No NOPs) takes 0.173758ms (4.445533µs/PEI)

As you can see it is faster to simply issue PEI's without any NOP's.

  • 2
    Your findings are perfectly intuitive, so why did people believe any different? Commented Sep 8, 2021 at 10:31
  • What did the code look like from the beginning?
    – UncleBod
    Commented Sep 8, 2021 at 14:42
  • 2
    Was this on a ROM01 or ROM03? (I have no reason to believe the behavior would change, but I'd like to get the test environment fully characterized for anybody who wants to confirm.)
    – fadden
    Commented Sep 8, 2021 at 16:35
  • 2
    @fadden This was measured on a ROM01.
    – Ian Brumby
    Commented Sep 9, 2021 at 1:24
  • @UncleBod The original code was: pei $5E, pei $5c, pei $5a, pei $58, pei $56, pei $54, pei $52, pei $50, nop, pei $4e, pei $4c, ...
    – Ian Brumby
    Commented Sep 9, 2021 at 1:26

Keep in mind that because the memory in banks $E0 and $E1 are used as the 128K of memory in 8-bit mode (yeah, it's counterintuitive), they are controlled by the MEGA II chip, which is in essence an Apple IIe on a single chip (aside from processor and a few other support circuits). Any time access happens within the MEGA II's domain, the system has to slow to 1 MHz. That's why shadowing and such is such a big win for graphics.

So there are two main data buses in the Apple IIgs (ignoring the slot I/O bus, which doesn't matter for this context): the MEGA II data bus, which operates at 1 MHz to support 8-bit emulation (and the bank $E0 and $E1 memory space), and the FPI (Fast Processor Interface) bus, which handles the 16-bit realm and all the rest of memory.

The two sides of the system operate largely independently; in fact, they even have their own memory refresh cycles for the areas of memory they're responsible for (the FPI side's refresh cycle causes an 8% loss of performance, which is why you often hear a 2.6 MHz speed for the IIgs).

Because of that independence, there's a need to synchronize between the two sides whenever data is transferred from one side to the other. Synchronization performs by the FPI basically stopping the FPI side's clock (thereby halting execution) and waiting until the MEGA II is in the right part of its cycle, then it starts running again, but synchronized to the MEGA II clock (and therefore temporarily running at 1 MHz for the duration of the operation).

I presume that adding the NOP at appropriate intervals reduces the length of time spent waiting for synchronization to occur. I have not had time to sit down and do that math and would prefer not to. :)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .