Radeon R100 CP Engine Microcode
Chad Jablonski - 2026-11-06
The CP engine1 is a packet processor used by ATI GPUs beginning with the Rage 128 and continuing through the Radeon X1000 (R500)2, roughly from 1998-2005. It processes command packets fed to it from a queue (FIFO) usually bus mastered via AGP or PCI GART.
These command packets replaced programming the chip directly using memory mapped registers (MMIO). The job of the CP engine is pretty simple. Read command packets from the FIFO and translate them into a series of register writes as quickly as possible.
The primary benefit of replacing direct MMIO programming with the CP engine was that it allowed commands to be quickly written to buffers in memory and then asynchronously drained and processed without involvement of the CPU. But a secondary benefit was that ATI was able to encode some common usage patterns into the packet format, which made life at least a little easier for driver authors. For this reason, the CP engine itself is a bit more complicated than “just copy data from memory into registers”. The contents of the packets often need to be broken apart and operated on before the actual register writes make it out the other side.
Because the internal operations of the CP engine itself aren’t trivial, ATI’s design included a replaceable microcode that defines the processing of packets. Presumably this was done so that the engine could be reused and bugs could be fixed if they were later found. This microcode is what I’m aiming to understand.
The Packets¶ ↑
A packet is just a series of 32-bit dwords that the CP engine picks off of the FIFO one at a time and processes. Each packet has a header word followed in most cases by a number of data words.
There are 4 types of packets that can be sent to the CP engine. And two of those types have sub-types of their own. Just a quick rundown of what these look like at a high level.
Type-0¶ ↑
Type-0 packets write Count values to registers.
There are two sub-types of this packet determined by the a flag. When a is unset, data words are written to consecutive registers starting with Base Index. When a is set, each data word is written to Base Index. This second variant is useful for registers that increment an internal index on write, like PALETTE_DATA.
Type-1¶ ↑
Type-1 packets write values to two registers. From the drivers I’ve seen this goes unused.
Type-2¶ ↑
Type-2 packets are NOPs used for filler and alignment.
Type-3¶ ↑
Type-3 packets are much more complex than the others. They are used to execute an operation determined by the IT_OPCODE field.
There are around 26 IT_OPCODEs for the R100, although many of them overlap and are essentially aliases. The opcode determines the layout of the data that follows. One of the simpler examples is HOSTDATA_BLT (opcode 0x14). This op is used to copy bitmaps into video memory. Most often this means copying characters of text to the framebuffer for display. The following dwords are placed in the data slots shown above:
This is simplified in that Char 1-M are themselves data blocks that contain multiple dwords describing the character to be copied. But this should at least illustrate how these packets are constructed.
The Microcode¶ ↑
The CP engine is controlled by a 256-qword microcode, loaded by the driver. Each qword is an instruction numbered from 0x00 to 0xff and is displayed split into two dwords (high and low). The format of an instruction changed slightly over the chip’s lifetime but the changes appear to have been pretty minor3. All of my testing and reverse engineering work was done using the CP engine of the R100. This means we’ll be looking at R100_cp.bin.
The Encoding¶ ↑
This being my first experience reversing something of this sort, I made a lot of bad assumptions. The biggest one was that the microcode was encoded roughly in the way an assembly language would be. I spent a lot of time trying to figure out what the “opcode” for a given instruction could be.
One of the first steps was to look at the frequency of values in the bottom byte of the high dword. Most of the values were 0x02, with 0x00 coming in distant second.
The 0x00 instructions looked suspiciously like data:
| Instruction | High Dword | Low Dword |
|---|---|---|
| ⋮ | ||
| 0x04 | 0x00000000 | 0x6f5b4d4c |
| 0x05 | 0x00000000 | 0x4c4c427f |
| 0x06 | 0x00000000 | 0x5b568a92 |
| 0x07 | 0x00000000 | 0x4ca09c6d |
| 0x08 | 0x00000000 | 0xad4c4c4c |
| 0x09 | 0x00000000 | 0x4ce1af3d |
| 0x0a | 0x00000000 | 0xd8afafaf |
| 0x0b | 0x00000000 | 0xd64c4cdc |
| 0x0c | 0x00000000 | 0x4cd10d10 |
| ⋮ |
On the other hand, 0x02 instructions looked a lot more like instructions:
| Instruction | High Dword | Low Dword |
|---|---|---|
| ⋮ | ||
| 0x7f | 0x00000002 | 0x000380e6 |
| 0x80 | 0x00000002 | 0x040025c5 |
| 0x81 | 0x00000002 | 0x00007576 |
| 0x82 | 0x00000002 | 0x00007577 |
| 0x83 | 0x00000002 | 0x0000750e |
| 0x84 | 0x00000002 | 0x0000750f |
| 0x85 | 0x00000002 | 0x00a05000 |
| ⋮ |
The frequency of 0x02, combined with another early discovery, led me to believe that 0x02 had to be an opcode. Many of the instructions beginning with 0x02 ended with a field that encoded an MMIO register address. Instructions 0x81 and 0x82 above are a perfect example of this. The bottom 12 bits contain 0x576 and 0x577 respectively. These didn’t immediately look like register addresses. But then I realized that when register addresses are present in a packet header (specifically Base Index and Register Index 1/2 fields above) they are always in units of dwords (not bytes).
Just like the packet headers, this 12-bit field is a register address in dwords. 0x576 << 2 becomes 0x15d8 or DP_SRC_FRGD_CLR. And 0x577 << 2 becomes 0x15dc or DP_SRC_BKGD_CLR. Foreground and background color, two registers that are very likely to be written together. And in fact, if you remember, the packet definition of HOSTDATA_BLT shown above includes values for these two registers back-to-back in its data block. Definitely not a coincidence. So the thinking was that these are obviously instructions that write to these registers. This must be a MOV instruction of some sort and 0x02 is the opcode.
After the address field discovery I was able to start seeing regions that seemed to belong to specific packet types. But before I could really start to isolate fields and understand the encoding more fully, I needed to be able to write my own microcode.
Writing my own microcode¶ ↑
Fortunately, it’s incredibly easy to load new microcode into the CP engine. Without getting too much into the weeds, this is done with a series of MMIO writes to indexed registers. It can even be done while the CP engine itself is running. The engine also implements a mode that allows packets to be sent via register writes instead of the more typical asynchronous bus mastering mode. All of this means that the feedback loop for testing can be very quick.
I may eventually write a bit more about the test environment and how the hardware is set up. But for now, the specific card I am testing on is the Radeon QY (RV100), PCI ID 0x5159. And tests are run via a baremetal test environment implemented in the ati-tests repo.
My first step was to try zeroing out whole sections of the stock microcode just to see if I could break things. The goal being to find a minimal microcode to start from when writing my own.
From this I learned that the microcode has multiple entrypoints. And these entrypoints are determined by the packet type. For example, Type-0 packets will execute with a single non-zero instruction (instruction 0x00). I could zero the rest of the microcode and the engine would happily continue to process Type-0 packets while hanging on any other type. These are the entrypoints I was able to find:
| Packet Type | Entrypoint Instruction |
|---|---|
| Type-0 | 0x00 |
| Type-0 (“a” flag set) | 0x01 |
| Type-1 | 0x02 |
| Type-2 | None |
| Type-3 (“c” flag set) | 0x03 |
| Type-3 | 0x04* |
*Sort of, it’s complicated
Type-2 packets have no entrypoint. Given that these are NOPs I have to assume that the engine handles these in hardware and never dispatches them to the microcode. But the really interesting packet is Type-3.
Type-3 entrypoints¶ ↑
I found that there are two flavors of Type-3 packet. Bit 15, or the c flag of the Type-3 header is what differentiates these two types. The “Rage 128 Software Development Guide” calls these packets “2D Packets”. When this bit is set the packet is required to include a settings block before any IT_OPCODE specific data blocks. The settings block is closely related to the DP_GUI_MASTER_CNTL register and allows the setting of many of the parameters commonly used for 2D operations.
The interesting, undocumented, part is that all of the “2D Packets” can also can be constructed with the c flag unset. In that case no settings block is present in the packet and just the IT_OPCODE specific parts are executed.
The way this works as far as entrypoints is that a c flag packet enters at instruction 0x03. In the stock microcode this handler immediately jumps to a subroutine that parses and processes the settings block. Without getting too deep into the mechanism here, the settings block subroutine eventually returns and the packet is re-dispatched using a jump table beginning at instruction 0x04. The non-c variant just immediately dispatches to the jump table, skipping the instruction 0x03 entry and settings subroutine entirely.
The jump table¶ ↑
The jump table in the stock microcode begins at instruction 0x04 and continues through instruction 0xc. At least in theory though it could be a larger region as you’ll see.
Each instruction in the table contains 4 destinations, 1 byte each, all in the low dword. This means each entry has an addressable range matching the size of the microcode RAM. The table is byte indexed using the 7-bit IT_OPCODE field of the Type-3 packet. The indexing begins at instruction 0x00 not 0x04, and bytes are packed little endian. So for example a NOP packet has an IT_OPCODE of 0x10. This means instructions 0x00-0x03 containing bytes 0-15 are skipped entirely and we land on the lowest byte of instruction 0x04 with a destination of 0x4c, an immediate jump to the subroutine at instruction 0x4c.
| Instruction | High Dword | Low Dword |
|---|---|---|
| 0x00 | 0x00000000 | 0x21007000 |
| 0x01 | 0x00000000 | 0x20007000 |
| 0x02 | 0x00000004 | 0x000000b4 |
| 0x03 | 0x00000004 | 0x000000b8 |
| 0x04 | 0x00000000 | 0x6f5b4d4c |
| ⋮ |
Once I knew that 0x00 was the entrypoint for Type-0 packets it should have been obvious that the low byte of the high dword couldn’t be an opcode. The “opcode” for that instruction in the stock microcode is 0x00, which is what I thought data looked like. I admit for a while I convinced myself that this may not be the entrypoint at all and may just be configuration of some sort for Type-0 packets. It was hard to believe that a single instruction could cover the entirety of Type-0 packet processing.
Experiments¶ ↑
With the discovery of entrypoints and the jump table the structure of the microprogram started to emerge. The jump table gave me labels for Type-3 handlers. That combined with the knowledge that some instructions contained register offsets meant that it was pretty easy to pull out an instruction that was clearly just writing the value of the current packet word through to a register. The previously mentioned instruction 0x81 is an example of this:
| Instruction | High Dword | Low Dword |
|---|---|---|
| ⋮ | ||
| 0x81 | 0x00000002 | 0x00007576 |
| ⋮ |
So I copied this instruction into instruction 0x00:
| Instruction | High Dword | Low Dword |
|---|---|---|
| 0x00 | 0x00000002 | 0x00007576 |
| ⋮ |
and sent a minimal Type-0 packet:
0x00000000 0xdeadbeef
Two packet words, the first being a Type-0 header and the second data. A Type-0 packet must have at least one dword of data.
And after execution, sure enough, 0xdeadbeef was written to register 0x15d8 (0x576 << 2). This meant that instruction 0x00 was without question an entrypoint and not just configuration. Kind of amazing in that this single instruction must then fully process a Type-0 packet.
So what’s the deal with the 0x00000000 in the high dword of the original 0x00 instruction? I tried zeroing it for the replacement:
| Instruction | High Dword | Low Dword |
|---|---|---|
| 0x00 | 0x00000000 | 0x00007576 |
| ⋮ |
and I sent the same packet.
0x00000000 0xdeadbeef
To my surprise the result was exactly the same4. At this point I had to let go of the opcode theory altogether, 0x2 isn’t a MOV. As I understood more and more of the instruction fields it became clear that all instructions shared the same encoding and there was no overall opcode. And at right around this time I also stumbled across a description of horizontal microcode 5.
Horizontal Microcode¶ ↑
And so, it turns out that this is a horizontal microcode, which largely avoids the sort of decoding that a machine code for a more traditional CPU would require. In general machine code encodes an instruction with an opcode and operands and then a decoder determines how the functional units of the processor executes the instruction. A horizontal microinstruction is composed of bits that control those functional units directly, sans-decoder6.
For example, an encoded x86 instruction may look like:
b8 ef be ad de
b8 is the opcode which encodes “move 32-bit immediate into EAX” and is followed by the immediate value 0xdeadbeef (little endian, hence the backwardsness.)
A microinstruction for the CP engine on the other hand:
00 00 00 02 00 00 75 76
There is no single opcode telling us what the operation is here. In fact, multiple things may be happening at the same time. It’s easiest to view this broken down by field:
63-40 39-32 31-15 14 13 12 11-0 ┌───────┬───────┬───────┬───────────┬───────┬──────────┬────────┐ │ … │ ??? │ … │ advance │ write │ latchpkt │ addr │ │ 0 │ 0x02 │ 0 │ 1 │ 1 │ 1 │ 0x576 │ └───────┴───────┴───────┴───────────┴───────┴──────────┴────────┘
advance fetches the next packet word in the packet FIFO, latchpkt stores it in the pkt register and write writes the packet out to the register in addr.
Our 0x02 “opcode” turns out to be something else entirely. Even when I thought this was an opcode, it was a bit odd that the values tended to be mostly even.
| “opcode” | Instruction Count |
|---|---|
| 0x00 | 60 |
| 0x02 | 128 |
| 0x04 | 18 |
| 0x06 | 13 |
| 0x08 | 2 |
| 0x0c | 4 |
| 0x12 | 2 |
| 0x14 | 1 |
| 0x16 | 4 |
| 0x18 | 12 |
| 0x1a | 3 |
| 0x1c | 2 |
| 0x1e | 3 |
| 0x20 | 2 |
| 0x21 | 2 |
If the entire byte was an opcode you would expect to see both even and odd values in use without a lot of gaps. Now, it could have been that the odd opcodes were used less frequently or not at all in the stock microcode. But the easier explanation was that my idea of the size of this field was just wrong. My assumption was that the field was the bottom byte. But it turned out to make much more sense if the bottom bit was instead either a flag or part of a different field. Once you do that the “holes” in the opcodes (for the most part) disappear.
| Unknown Field | Instruction Count |
|---|---|
| 0x00 | 60 |
| 0x01 | 128 |
| 0x02 | 18 |
| 0x03 | 13 |
| 0x04 | 2 |
| 0x06 | 4 |
| 0x09 | 2 |
| 0x0a | 1 |
| 0x0b | 4 |
| 0x0c | 12 |
| 0x0d | 3 |
| 0x0e | 2 |
| 0x0f | 3 |
| 0x10 | 4 |
So the previous value of 0x02 becomes 0x01 in this interpretation of the field. And based on the observed values, the highest being 0x10, it’s not crazy to make the assumption that this is a 5-bit field:
63-38 37-33 32-15 14 13 12 11-0 ┌───────┬───────┬───────┬───────────┬───────┬──────────┬────────┐ │ … │ ??? │ … │ advance │ write │ latchpkt │ addr │ │ 0 │ 0x01 │ 0 │ 1 │ 1 │ 1 │ 0x576 │ └───────┴───────┴───────┴───────────┴───────┴──────────┴────────┘
What is the field?¶ ↑
Then what is the field? The packet entrypoint instructions offer some pretty big clues. Let’s look at the Type-0 and Type-1 entrypoints.
Type-0 with “a” flag set (entrypoint 0x01)¶ ↑
Instruction¶ ↑
0x00000000 0x20007000
Fields¶ ↑
63-38 37-33 32-15 14 13 12 11-0 ┌───────┬───────┬────────┬───────────┬───────┬──────────┬────────┐ │ … │ ??? │ … │ advance │ write │ latchpkt │ addr │ │ 0 │ 0x00 │ 0x2000 │ 1 │ 1 │ 1 │ 0x000 │ └───────┴───────┴────────┴───────────┴───────┴──────────┴────────┘
Type-1 (entrypoint 0x02)¶ ↑
Instruction¶ ↑
0x00000004 0x000000b4
Fields¶ ↑
63-38 37-33 32-15 14 13 12 11-0 ┌───────┬───────┬────────┬───────────┬───────┬──────────┬────────┐ │ … │ ??? │ … │ advance │ write │ latchpkt │ addr │ │ 0 │ 0x02 │ 0 │ 0 │ 0 │ 0 │ 0x0b4 │ └───────┴───────┴────────┴───────────┴───────┴──────────┴────────┘
Let’s start by looking at the Type-1 instruction, there’s a bit less going on. In fact there are really only two non-zero fields in the instruction, our ??? field and a value in the addr field. Up until this point values in the addr field have been registers targeted for a write. But the value doesn’t really make sense as a card register 0xb4 << 2 = 0x2d0 = LVDS_GEN_CNTL which has something to do with an interface for a flat panel. Clearly not something that makes sense for a generic Type-1 packet handler. And on top of that the write flag isn’t even set. The value is small though. Small enough to be the address of an instruction in the microcode itself. This almost has to be a jump instruction. The instructions located at 0xb4 look like this:
| Instruction | High Dword | Low Dword |
|---|---|---|
| ⋮ | ||
| 0xb4 | 0x00000002 | 0x01200000 |
| 0xb5 | 0x00000002 | 0x20077000 |
| 0xb6 | 0x00000002 | 0x01200000 |
| 0xb7 | 0x00000002 | 0x20007000 |
| ⋮ |
These at least plausibly look like an instruction handler. In fact 0xb7 is nearly identical to the instruction at the Type-0 (with a flag) entry point. Which would make sense. Both of these packet types are just copying values from the packet into registers specified in the packet header.
There is one big difference between the two packet types though. Type-1 packets are really simple in that they always just write to two registers. The packet has two data dwords that contain the values to be written to those registers. So you would need to read each of those dwords and write them out. Even though we don’t understand all of the fields in these instructions yet you can see that this handler is advancing the packet FIFO twice, meaning it is stepping through the data dwords in the packet. This can be seen in instructions 0xb5 and 0xb7.
63-38 37-33 32-15 14 13 12 11-0
┌───────┬───────┬────────┬───────────┬───────┬──────────┬────────┐
│ … │ ??? │ … │ advance │ write │ latchpkt │ addr │
0xb5 │ 0 │ 0x01 │ 0x2007 │ 1 │ 1 │ 1 │ 0x000 │
├───────┴───────┴────────┴───────────┴───────┴──────────┴────────┤
0xb6 │ … │
├───────┬───────┬────────┬───────────┬───────┬──────────┬────────┤
0xb7 │ … │ ??? │ … │ advance │ write │ latchpkt │ addr │
│ 0 │ 0x01 │ 0x2000 │ 1 │ 1 │ 1 │ 0x000 │
└───────┴───────┴────────┴───────────┴───────┴──────────┴────────┘
Unfortunately, it isn’t really easy/possible to prove this bit through static analysis. But I found in testing that a program will run until the packet FIFO is exhausted and then halt and wait for a new packet. Given that we know that Type-1 packets always have two dwords of data and we see two advance instructions execution will halt after 0xb7.
Type-0 packets on the other hand need to do a variable number of writes based on the count in their packet header. This alone implies some sort of loop. But let’s look at the entry point:
63-38 37-33 32-15 14 13 12 11-0
┌───────┬───────┬────────┬───────────┬───────┬──────────┬────────┐
│ … │ ??? │ … │ advance │ write │ latchpkt │ addr │
0x01 │ 0 │ 0x00 │ 0x2000 │ 1 │ 1 │ 1 │ 0x000 │
└───────┴───────┴────────┴───────────┴───────┴──────────┴────────┘
Notice that the only difference here is the 0x00 value in the ??? field. Otherwise this is the 0xb7 instruction again. What this entry point isn’t is another jump. It also wouldn’t exhaust the packet FIFO in most cases.7
These three examples combined point to ??? actually being a sequencer field or seq. Or more simply a field that controls the program counter in the program. A seq of 0x2 set the program counter to 0xb4 in the Type-1 entry point, this is a jmp. Next, a seq of 0x01, the most common, is used in every single instruction of the Type-1 handler after the jump. This just increments the program counter. It’s a next instruction or nxt. And finally the most surprising, and what proved me wrong about a single instruction being able to implement a whole handler: 0x00 is a repeat or rpt. The program counter is untouched and the program continues executing the same instruction until being parked by exhausting the packet FIFO. In other words the instruction at 0x01 will run repeatedly each time advancing the packet FIFO and finally halting.
What now?¶ ↑
This doesn’t cover all that is known about the CP engine but I hope that it gives a decent feel for how the machine works conceptually. With the general outline of the machine in place a lot of the remaining work was (and is) filling in the unknown fields/control lines and decoding ops for the individual units like the alu and sequencer. The very rough documentation thus far from that process is below. Right now my biggest focus is on trying to understand the block of bits b21-b25 and the remaining sequencer ops. There are notes on this and I have some theories about the remaining bits. Some of which even hold up well in isolation but feel fuzzy when viewed as a whole.
1 It’s called the CCE engine by Rage 128 docs and CP engine by subsequent GPUs
2 This is based on the firmware in the linux-firmware repo.
3 More investigation is needed but initially it appears that the addr field increased width by one bit from R128 -> R100 and then again from R100 -> R200. Which makes some sense in that the register space grew. Semantics are another thing entirely and will require testing on actual hardware.
4 Well, roughly the same. At least from what I could tell at this point.
5 The best coverage of this that I found was Chapter 4 of an old version of Tanenbaum’s Structured Computer Organization (archive.org/details/structuredcomput0000tane). But sadly, it’s not borrowable on archive.org.
6 That’s not to say that there’s no decoding going on but the overall instruction isn’t decoded. Cases where fields are decoded are owned by their functional units (the sequencer and ALU for example).
7 save for count = 0, meaning a single write
Documentation
Microinstruction Encoding
seq [37:33]
The SEQ field controls the program counter and the flow of the program.
Values
- 0x00 rpt
-
Do not increment the program counter. Execute this instruction repeatedly. Often used with the
advancefield to drain the pkt FIFO.Evidence
-
seq-rpt-drain-fifo
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0xa1 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 94 times PacketState After ExecutionHeader 0x00010000 Data0 0xdeadbeef Data1 0x1337fee7 NotesGUI_SCRATCH_REG0: 0x1337fee7 GUI_SCRATCH_REG1: 0x00000000 advanceis set to advance the packet FIFO and decrement the packet word count.latchpktis set to latch the current packet word into thepktregister. -
seq-rpt-does-not-inc-pc
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x01 jmp • • • • • pkt • • • • • 0x000 • • • 0xa1 0x0 158 times 0xa0 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0xa1 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 94 times PacketState After ExecutionHeader 0x00000000 Data0 0xdeadbeef NotesGUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000 latchpktandadvanceare not set so the pktfifo is not drained and the packet word counter is not decremented. This appears to wedge the CP engine. If a second packet with an entrypoint at0x01is sent it also never writes toGUI_SCRATCH_REG1. My read is that withoutadvancedecrementing the packet word count and without an advancing PC, instruction0xa0enters an infinite loop.
-
- 0x01 nxt
-
Increment the program counter.
- 0x02 jmp
-
Set the program counter to the value in the ADDR field. An unconditional jump.
Evidence
-
seq-jmp-unconditional
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x01 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 158 times 0xa0 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 95 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef NotesGUI_SCRATCH_REG0: 0x00000000 GUI_SCRATCH_REG1: 0x00000001 GUI_SCRATCH_REG1is written to butGUI_SCRATCH_REG0is jumped over and is not written to. -
seq-jmp-loop-wedge
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0x00 0x01 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 254 times PacketState After ExecutionHeader 0x00000000 Data0 0xdeadbeef Data1 0x00008000 Data2 0x1337fee7 NotesGUI_SCRATCH_REG0: 0x00000000 GUI_SCRATCH_REG1: 0x00000000 This creates an infinite loop using a self-referential jump instruction. The second packet is never processed showing that the CP engine is wedged.
-
- 0x03 ret
-
Pop the last address off of the (2 slot) stack and jump to it.
reton an empty stack halts.This is used by the
cvariant of type-3 packets. The hardware places the address found in the jump table for the packet type on the stack. After the common settings are processedretis called, popping theIT_OPCODE-specific handler address off the stack and jumping to it.Evidence
-
seq-ret-dispatches-to-jump-table
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr 0x0 3 times entry: 0x03 jmp • • • • • pkt • • • • • 0x000 • • • 0xf0 0x04 0x00000000 0x00aa0000 0x0 165 times 0xaa rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 69 times 0xf0 ret • • • • • pkt • • • • • 0x000 • • • 0x000 0x0 15 times PacketState After ExecutionHeader 0xc0009200 Data0 0xdeadbeef NotesGUI_SCRATCH_REG0: 0xdeadbeef A type-3 packet with the
cflag enters at0x03. The hardware must also look up theIT_OPCODEin the jump table and place the address found on the stack. Aretthen pops the handler address off the stack and jumps to it. -
seq-ret-will-not-dispatch-type-0-packets
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xf0 0x0 3 times 0x04 0x00000000 0x00aa0000 0x0 165 times 0xaa rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 69 times 0xf0 ret • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0xf1 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG2 0x0 14 times PacketState After ExecutionHeader 0x00001200 Data0 0xdeadbeef NotesGUI_SCRATCH_REG0: 0x00000000 GUI_SCRATCH_REG1: 0xdeadbeef GUI_SCRATCH_REG2: 0x00000000 retwill not dispatch for type-0 packets. It also does not advance the PC. Type-0 packets don’t require a jump table, so it makes sense that they wouldn’t place anything on the stack leading to a stack underflow (and a halt). -
seq-call-and-return
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr 0x0 4 times 0x04 0x00000000 0x00a00000 0x0 155 times entry: 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 call • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 nxt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG0 0xa3 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG2 0xa4 nxt • • • • • pkt • • • • • ld #addr • • • 0xf1 0xa5 call • • • • • pkt • • • • • 0x000 • • • 0xc0 0xa6 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG3 0xa7 rpt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 8 times 0xb0 ret • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 15 times 0xc0 ret • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 47 times 0xf0 0x00000000 0xaaaaaaaa 0xf1 0x00000000 0xbbbbbbbb 0x0 14 times PacketState After ExecutionHeader 0xc0011200 Data0 0xdeadbeef Data1 0xcafebeef GUI_SCRATCH_REG0: 0xaaaaaaaa GUI_SCRATCH_REG1: 0xbbbbbbbb GUI_SCRATCH_REG2: 0xdeadbeef GUI_SCRATCH_REG3: 0xcafebeef -
seq-call-and-return-has-two-entry-stack
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr 0x00 rpt • • • • • pkt • • • • • 0x000 • • • BIOS_1_SCRATCH 0x0 3 times 0x04 0x00000000 0x00a00000 0x0 155 times entry: 0xa0 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG5 0xa1 call • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa3 rpt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 12 times 0xb0 call • • • • • pkt • • • • • 0x000 • • • 0xc0 0xb1 nxt • • • • • pkt • • • • • ld #addr • • • 0xf1 0xb2 ret • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 13 times 0xc0 call • • • • • pkt • • • • • 0x000 • • • 0xd0 0xc1 nxt • • • • • pkt • • • • • ld #addr • • • 0xf2 0xc2 ret • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG2 0xc3 rpt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG5 0x0 12 times 0xd0 call • • • • • pkt • • • • • 0x000 • • • 0xe0 0xd1 nxt • • • • • pkt • • • • • ld #addr • • • 0xf3 0xd2 ret • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG3 0x0 13 times 0xe0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf4 0xe1 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0xe2 nxt • • • • • pkt • • • • • 0x000 • • • BIOS_0_SCRATCH 0xe3 ret • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG4 0x0 12 times 0xf0 0x00000000 0xaaaaaaaa 0xf1 0x00000000 0xbbbbbbbb 0xf2 0x00000000 0xcccccccc 0xf3 0x00000000 0xdddddddd 0xf4 0x00000000 0xeeeeeeee 0x0 11 times PacketState After ExecutionHeader 0xc0031200 Data0 0xdeadbeef Data1 0xcafebeef Data2 0x1337beef Data3 0x1337fee7 NotesGUI_SCRATCH_REG0: 0x00000000 GUI_SCRATCH_REG1: 0x00000000 GUI_SCRATCH_REG2: 0xcccccccc GUI_SCRATCH_REG3: 0xdddddddd GUI_SCRATCH_REG4: 0xeeeeeeee GUI_SCRATCH_REG5: 0xdeadbeef BIOS_0_SCRATCH: 0xcafebeef BIOS_1_SCRATCH: 0x00000000 I suspected for a while that
reton an empty stack would return to the type-3 jump table. This no longer appears to be the case. There is an advance at0xe1, which means that we are making progress through the pktfifo when this call chain executes.If the whole chain ran more than once we would expect to see different values in REG5 and BIOS0. The test shows that REG5 gets the first data packet word, BIOS0 gets the second. If the
retstack underflow on0xc2dispatched to the jump table the entire chain will run again and we would see later packet words. I believe it would settle on REG5=0x1337beef and BIOS0=0x1337fee7. It does not.So on underflow it looks like execution stops, either wedging or waiting for the next packet.
-
- 0x04–0x05 ?
- 0x06 jcz.l
-
This is a bit of a work in progress. The theory is that there is a
countregister of some sort that is selected and written to viab21-b23.jcz.ljumps when the low word of that register is zero. This needs more investigation.Evidence
-
jcz.l-jumps-when-count.l-is-zero
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0xa1 jcz.l • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa3 rpt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 12 times 0xb0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf1 0xb1 rpt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 62 times 0xf0 0x00000000 0xdeadbeef 0xf1 0x00000000 0xcafebeef 0x0 14 times PacketState After ExecutionHeader 0x00000001 Data0 0xffff0000 GUI_SCRATCH_REG0: 0x00000000 GUI_SCRATCH_REG1: 0xcafebeef -
jcz.l-does-not-jump-when-count.l-is-nonzero
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0xa1 jcz.l • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa3 rpt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 12 times 0xb0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf1 0xb1 rpt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 62 times 0xf0 0x00000000 0xdeadbeef 0xf1 rpt • • • • • alu.h • • • • • 0x03d • • • 0xeef 0x0 14 times PacketState After ExecutionHeader 0x00000001 Data0 0xffff0001 GUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000
-
- 0x07–0x08 ?
- 0x09 jn.h
-
If the high word of the value stored in the ALU register is negative set the program counter to the value in the
addrfield.Evidence
-
seq-jn.h-jumps-when-aluh-negative
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jn.h • • • • • pkt • • • • • 0x000 • • • 0xf1 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 77 times 0xf0 0x00000000 0xffff1111 0xf1 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 14 times PacketState After ExecutionHeader 0x00000000 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0x00000000 GUI_SCRATCH_REG1: 0xdeadbeef -
seq-jn.h-continues-when-aluh-positive
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jn.h • • • • • pkt • • • • • 0x000 • • • 0xf1 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 77 times 0xf0 0x00000000 0x1111ffff 0xf1 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 14 times PacketState After ExecutionHeader 0x00000000 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000
-
- 0x0a jn.l
-
If the low word of the value stored in the ALU is negative set the program counter to the value in the
addrfield.Evidence
-
seq-jn.l-jumps-when-alul-negative
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jn.l • • • • • pkt • • • • • 0x000 • • • 0xf1 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 77 times 0xf0 0x00000000 0x1111ffff 0xf1 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 14 times PacketState After ExecutionHeader 0x00000000 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0x00000000 GUI_SCRATCH_REG1: 0xdeadbeef -
seq-jn.l-continues-when-alul-positive
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jn.l • • • • • pkt • • • • • 0x000 • • • 0xf1 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 77 times 0xf0 0x00000000 0xffff1111 0xf1 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 14 times PacketState After ExecutionHeader 0x00000000 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000
-
- 0x0b skp
-
Unconditionally increment the program counter by two. In other words, skip the next instruction.
Evidence
-
seq-skp-skips-next-instruction
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 skp • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0xa1 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG2 0x0 93 times PacketState After ExecutionHeader 0x00000000 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000 GUI_SCRATCH_REG2: 0xdeadbeef
-
- 0x0c call
-
Used in conjunction with
ret. Jump toaddrand push PC+1 onto a stack. Onretpop the stack. The stack has a max depth of 2. Further calls evict the oldest.Evidence
-
seq-call-and-return
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr 0x0 4 times 0x04 0x00000000 0x00a00000 0x0 155 times entry: 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 call • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 nxt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG0 0xa3 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG2 0xa4 nxt • • • • • pkt • • • • • ld #addr • • • 0xf1 0xa5 call • • • • • pkt • • • • • 0x000 • • • 0xc0 0xa6 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG3 0xa7 rpt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 8 times 0xb0 ret • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 15 times 0xc0 ret • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 47 times 0xf0 0x00000000 0xaaaaaaaa 0xf1 0x00000000 0xbbbbbbbb 0x0 14 times PacketState After ExecutionHeader 0xc0011200 Data0 0xdeadbeef Data1 0xcafebeef GUI_SCRATCH_REG0: 0xaaaaaaaa GUI_SCRATCH_REG1: 0xbbbbbbbb GUI_SCRATCH_REG2: 0xdeadbeef GUI_SCRATCH_REG3: 0xcafebeef -
seq-call-and-return-has-two-entry-stack
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr 0x00 rpt • • • • • pkt • • • • • 0x000 • • • BIOS_1_SCRATCH 0x0 3 times 0x04 0x00000000 0x00a00000 0x0 155 times entry: 0xa0 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG5 0xa1 call • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa3 rpt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 12 times 0xb0 call • • • • • pkt • • • • • 0x000 • • • 0xc0 0xb1 nxt • • • • • pkt • • • • • ld #addr • • • 0xf1 0xb2 ret • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 13 times 0xc0 call • • • • • pkt • • • • • 0x000 • • • 0xd0 0xc1 nxt • • • • • pkt • • • • • ld #addr • • • 0xf2 0xc2 ret • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG2 0xc3 rpt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG5 0x0 12 times 0xd0 call • • • • • pkt • • • • • 0x000 • • • 0xe0 0xd1 nxt • • • • • pkt • • • • • ld #addr • • • 0xf3 0xd2 ret • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG3 0x0 13 times 0xe0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf4 0xe1 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0xe2 nxt • • • • • pkt • • • • • 0x000 • • • BIOS_0_SCRATCH 0xe3 ret • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG4 0x0 12 times 0xf0 0x00000000 0xaaaaaaaa 0xf1 0x00000000 0xbbbbbbbb 0xf2 0x00000000 0xcccccccc 0xf3 0x00000000 0xdddddddd 0xf4 0x00000000 0xeeeeeeee 0x0 11 times PacketState After ExecutionHeader 0xc0031200 Data0 0xdeadbeef Data1 0xcafebeef Data2 0x1337beef Data3 0x1337fee7 NotesGUI_SCRATCH_REG0: 0x00000000 GUI_SCRATCH_REG1: 0x00000000 GUI_SCRATCH_REG2: 0xcccccccc GUI_SCRATCH_REG3: 0xdddddddd GUI_SCRATCH_REG4: 0xeeeeeeee GUI_SCRATCH_REG5: 0xdeadbeef BIOS_0_SCRATCH: 0xcafebeef BIOS_1_SCRATCH: 0x00000000 I suspected for a while that
reton an empty stack would return to the type-3 jump table. This no longer appears to be the case. There is an advance at0xe1, which means that we are making progress through the pktfifo when this call chain executes.If the whole chain ran more than once we would expect to see different values in REG5 and BIOS0. The test shows that REG5 gets the first data packet word, BIOS0 gets the second. If the
retstack underflow on0xc2dispatched to the jump table the entire chain will run again and we would see later packet words. I believe it would settle on REG5=0x1337beef and BIOS0=0x1337fee7. It does not.So on underflow it looks like execution stops, either wedging or waiting for the next packet.
-
- 0x0d jz
-
Jump to the instruction in
addrif the ALU register is zero.Evidence
-
seq-jz-jumps-on-alu-zero
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jz • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 13 times 0xb0 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 79 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0x00000000 GUI_SCRATCH_REG1: 0xdeadbeef -
seq-jz-does-not-jump-on-alu.h-positive
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jz • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 13 times 0xb0 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 63 times 0xf0 0x00000000 0x00010000 0x0 15 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000 -
seq-jz-does-not-jump-on-alu.h-negative
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jz • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 13 times 0xb0 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 63 times 0xf0 0x00000000 0xffff0000 0x0 15 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000 -
seq-jz-does-not-jump-on-alu.l-positive
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jz • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 13 times 0xb0 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 63 times 0xf0 0x00000000 0x00000001 0x0 15 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000 -
seq-jz-does-not-jump-on-alu.l-negative
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jz • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 13 times 0xb0 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 63 times 0xf0 0x00000000 0x0000ffff 0x0 15 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000
-
- 0x0e jz.l
-
Jump to the instruction in
addrif the low word of the ALU register is zero.Evidence
-
seq-jz.l-jumps-on-alu.l-zero
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jz.l • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 13 times 0xb0 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 63 times 0xf0 0x00000000 0xffff0000 0x0 15 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0x00000000 GUI_SCRATCH_REG1: 0xdeadbeef -
seq-jz.l-does-not-jump-on-alu.l-positive
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jz.l • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 13 times 0xb0 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 63 times 0xf0 0x00000000 0xffff0001 0x0 15 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000 -
seq-jz.l-does-not-jump-on-alu.l-negative
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 jz.l • • • • • pkt • • • • • 0x000 • • • 0xb0 0xa2 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 13 times 0xb0 rpt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 63 times 0xf0 0x00000000 0xffffffff 0x0 15 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000
-
- 0x0f–0x10 ?
b32 [32]
Unknown
cond [31]
Conditionally execute the current instruction based on the low bit of the idx register. If set execute, if unset skip the instruction. It’s currently unclear how the idx register works or if it exists at all. Confidence is high that this does control execution of the write (but not instruction seq). But… the rest is very fuzzy.
mcsel [30]
When enabled the addr field refers to a microcode instruction. This becomes the destination for write. Yes, the CP engine can modify it’s own microcode! The stock microcode contains a subroutine that does this.
Evidence
-
mcsel-write-alu-to-microcode
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • ld #addr • • • 0xf0 0xa1 nxt • • • • • alu • • • • • 0x000 • • • 0xf1 0xa2 nxt • • • • • alu • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 77 times 0xf0 0x00000000 0xaaaaaaaa 0x0 15 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xaaaaaaaa #241: 0x00000000 -
mcsel-write-pkt-to-microcode
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • 0x000 • • • 0xf1 0xa1 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0x0 94 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0x00000001 #241: 0x00000000
idxsel [29]
Select the idx register replacing the addr field for some operations. A good example of this is instruction 0, the Type-0 packet handler. The write flag combined with idxsel writes to the card register in the BASE_INDEX field of the current Type-0 packet header. This is often combined with b24 to walk a number of card registers.
Evidence
-
idxsel-writes-to-reg-in-idx
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0x0 95 times PacketState After ExecutionHeader 0x00000578 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xdeadbeef
b28 [28]
Unknown
src [27:26]
Values
- 0x00 pkt
-
Use the pkt register as a source.
- 0x01 alu
-
Use the full dword stored in the alu register as a source.
- 0x02 alu.h
-
Use the high word stored in the alu register as a source.
- 0x03 alu.l
-
Use the low word stored in the alu register as a source.
b25 [25]
Unknown
b24 [24]
In at least some cases this increments the value stored in the idx register for use in walking a number of card registers. This is usually used together with idxsel. A good example of this is instruction 0, the Type-0 packet handler.
Evidence
-
idxinc-post-increments-idx
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0xa1 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0xa2 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0xa3 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0xa4 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0x0 91 times PacketState After ExecutionHeader 0x00000578 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0xdeadbeef GUI_SCRATCH_REG1: 0x00000000 GUI_SCRATCH_REG2: 0x00000000 GUI_SCRATCH_REG3: 0xdeadbeef
b23 [23]
Unknown
b22 [22]
Seen used in conjunction with the cond bit. It in some way controls which bit is used to determine if a write happens. My initial thought was that it shifted the stored GUI_CONTROL 2D packet header stored in a flag register of some sort. But there’s also the possibility that it increments a counter that is then used to index into header bits.
Regardless, it is almost certainly used to iterate through the bits of a word and conditionally execute a write. (see dp_gui_2d, instruction 0xb8)
b21 [21]
While b24 is also set this will load the alu register contents into the idx register. When b24 is not set it so far appears to be a nop.
alu [20:15]
This appears to be an opcode for the ALU. The operations listed, for the most part, were discovered in a very quick sweep. Confidence is low unless otherwise stated. Many are likely missing/wrong.
Values
- 0x01 ?
- 0x02 sub.h
-
Subtract the high word of the alu register from the high word of the pkt register. Used by the paint packet handler (beginning at instruction
0x4d) to calculate the height of the blit. - 0x03 sub.l
-
Subtract the low word of the alu register from the low word of the pkt register. Used by the paint packet handler (beginning at instruction
0x4d) to calculate the width of the blit. - 0x04 neg.h
- 0x05 neg.l
- 0x07 ld #addr
- 0x08–0x0b ?
- 0x0c ld pkt
- 0x0d asr
- 0x0e shr11
-
Shift value in the ALU right by 11 bits. Used by the Type-1 packet handler (instruction
0xb4) to pull outREG_INDEX1andREG_INDEX2. - 0x0f ?
- 0x10 ld [pc+1]
-
Load the low dword of the next instruction into the ALU register.
- 0x11 mul3.h
- 0x12 mul3.l
- 0x13–0x14 ?
- 0x15 clr.l
- 0x16 clr.h
- 0x17 swp
- 0x18 ?
- 0x19 clr
- 0x1a lb
- 0x1b inc.l
- 0x1c inc.h
- 0x1e ?
- 0x1f add.h
- 0x20 add.l
- 0x21–0x22 ?
- 0x23 bswp.l
- 0x25 dec.l
- 0x26 neg.b
advance [14]
This is a control line for the pkt FIFO. The pkt FIFO head register latches the next word in the pkt, if available. If nothing is available the head register is untouched. This also controls dispatch in that the current pkt word count is decremented. If the word count for the packet has been exhausted then the header of the next packet is read and dispatched on. Which means this will cause the CP engine to either wait for the next packet or jump to the correct entrypoint for the next packet.
Evidence
-
advance-decrements-packet-word-count
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0xa1 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0xa2 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0xa3 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG2 0x0 92 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef NotesGUI_SCRATCH_REG0: 0x00000001 GUI_SCRATCH_REG1: 0x00000001 GUI_SCRATCH_REG2: 0x00000000 0xa2 advances the pktfifo bringing the word count for the current packet to 0. This causes a dispatch using the contents of the pktfifo head as the next packet header (0xdeadbeef). That dispatch lands on a zeroed type-3 handler. This means 0xa3 is never run and the engine essentially waits for a new packet.
-
advance-dispatches-on-stale-pktfifo-head
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xc0 0x0 1 times 0x02 jmp • • • • • pkt • • • • • 0x000 • • • 0xd0 0x0 189 times 0xc0 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0xc1 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 14 times 0xd0 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG2 0xd1 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG3 0x0 46 times PacketState After ExecutionHeader 0x00000001 Data0 0x40000000 NotesGUI_SCRATCH_REG0: 0x00000001 GUI_SCRATCH_REG1: 0x00000001 GUI_SCRATCH_REG2: 0x40000000 GUI_SCRATCH_REG3: 0x40000000 This one is a little bit involved and confused me for quite a while. What I think is happening here is the first packet word is dispatched on and execution begins at 0x0 (type-0). From there it jumps to 0xc0 and writes the pkt register to SCRATCH_REG0. The next instruction (0xc1) does the same to SCRATCH_REG1. The one difference is 0xc1 has the
advanceflag set.The
advanceflag does two things. First, it causes the pktfifo to read the next pkt word into the pktfifo head register. Second, it decrements the pkt word counter potentially causing a dispatch to fire.In this case there are no more packet words left to read into the pktfifo head register, so it remains 0x40000000. However, the packet count still decrements from 1 to 0 and a dispatch is fired. The dispatcher latches the contents of the pktfifo head into the pkt register, treating it as the next packet header.
The new packet header (0x40000000) is a type-1 packet and is dispatched to instruction 0x2. From there it’s pretty straightforward. Jump to 0xd0 and write the contents of the pkt register, the header, to SCRATCH_REG2 and SCRATCH_REG3.
Notice that the dispatcher must internally latch the pkt register to obtain the header word before jumping to an entrypoint. Nowhere in this do we ever use
latchpktto latch the value from the pktfifo header into thepktregister.For completeness, after 0xd1 we fall into a completely zeroed instruction (not shown). SEQ=0x0 or rpt. At that point the engine spins waiting for a new packet.
write [13]
Enable a write to the register address in the addr field. The destination can also be redirected via idxsel, and possibly others. The src seems to be selected by the src field.
latchpkt [12]
Read the current word at the head of the pktfifo. Store it in the pkt register.
Evidence
-
latchpkt-reads-current-fifo-head
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0xa1 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 94 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef GUI_SCRATCH_REG0: 0x00000001 GUI_SCRATCH_REG1: 0xdeadbeef -
latchpkt-loads-current-fifo-head-into-pkt
seq b32 cond mcsel idxsel b28 src b25 b24 b23 b22 b21 alu advance write latchpkt addr entry: 0x00 jmp • • • • • pkt • • • • • 0x000 • • • 0xa0 0x0 159 times 0xa0 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG0 0xa1 nxt • • • • • pkt • • • • • 0x000 • • • 0x000 0xa2 nxt • • • • • pkt • • • • • 0x000 • • • GUI_SCRATCH_REG1 0x0 93 times PacketState After ExecutionHeader 0x00000001 Data0 0xdeadbeef NotesGUI_SCRATCH_REG0: 0x00000001 GUI_SCRATCH_REG1: 0xdeadbeef latchpkt does not just place the pktfifo head onto the bus for this instruction. It also stores it in a register (
pkt). Subsequent writes use this register as a source, in this case writing it to scratch.
addr [11:0]
The addr field may hold an instruction address (0x00-0xff) or a card register address in words (SCRATCH_REG0 >> 2 = 0x578). This field is used by a number of chip functions. The sequencer (controlled by seq) can use it to set the program counter. The ALU can use it as an indirect reference to a full word stored in the microcode. write can use it as a destination card register.
Full Listing
| seq | b32 | cond | mcsel | idxsel | b28 | src | b25 | b24 | b23 | b22 | b21 | alu | advance | write | latchpkt | addr | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| type_0_pkt_entry: | |||||||||||||||||
| 0x00 | rpt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| type_0_one_reg_pkt_entry: | |||||||||||||||||
| 0x01 | rpt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| entry_type_1: | |||||||||||||||||
| 0x02 | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0xb4 |
| entry_type_3_gui_cntl_2d: | |||||||||||||||||
| 0x03 | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0xb8 |
| entry_type_3_jump_table: | |||||||||||||||||
| 0x04 | 0x00000000 0x6f5b4d4c | ||||||||||||||||
| 0x05 | 0x00000000 0x4c4c427f | ||||||||||||||||
| 0x06 | 0x00000000 0x5b568a92 | ||||||||||||||||
| 0x07 | 0x00000000 0x4ca09c6d | ||||||||||||||||
| 0x08 | 0x00000000 0xad4c4c4c | ||||||||||||||||
| 0x09 | 0x00000000 0x4ce1af3d | ||||||||||||||||
| 0x0a | 0x00000000 0xd8afafaf | ||||||||||||||||
| 0x0b | 0x00000000 0xd64c4cdc | ||||||||||||||||
| 0x0c | 0x00000000 0x4cd10d10 | ||||||||||||||||
| pkt_0x31: | |||||||||||||||||
| 0x0d | skp | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x1e | • | • | • | 0x000 |
| 0x0e | 0x00000000 0x362f242d | ||||||||||||||||
| 0x0f | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x12 |
| pkt_0x30: | |||||||||||||||||
| 0x10 | skp | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x1e | • | • | • | 0x000 |
| 0x11 | 0x00000000 0x362f282d | ||||||||||||||||
| 0x12 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe7 |
| 0x13 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | RB3D_DSTCACHE_CTLSTAT |
| 0x14 | skp | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x1e | • | • | • | MM_DATA |
| 0x15 | 0x00000000 0x333a3730 | ||||||||||||||||
| 0x16 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | IDCT_CONTROL |
| 0x17 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0x000 |
| 0x18 | jz | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x21 |
| 0x19 | seq_0x0f | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0x1a | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0x000 |
| 0x1b | jz | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x21 |
| 0x1c | seq_0x0f | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0x1d | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0x000 |
| 0x1e | jz | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x21 |
| 0x1f | seq_0x0f | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0x20 | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x17 |
| 0x21 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0x2b |
| 0x22 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | IDCT_RUNS |
| 0x23 | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x17 |
| 0x24 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | IDCT_RUNS |
| 0x25 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0x000 |
| 0x26 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | IDCT_LEVELS |
| 0x27 | ret | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | IDCT_LEVELS |
| 0x28 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | IDCT_RUNS |
| 0x29 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | IDCT_LEVELS |
| 0x2a | ret | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | IDCT_LEVELS |
| 0x2b | 0x00000000 0xffffffff | ||||||||||||||||
| 0x2c | 0x00000000 0x10000000 | ||||||||||||||||
| 0x2d | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0x2b |
| 0x2e | ret | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | IDCT_RUNS |
| 0x2f | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | MC_SRC2_CNTL |
| 0x30 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | MC_SRC1_CNTL |
| 0x31 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | MC_DST_CNTL |
| 0x32 | ret | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | MC_START_CNTL |
| 0x33 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0x2c |
| 0x34 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | MC_SRC1_CNTL |
| 0x35 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | MC_DST_CNTL |
| 0x36 | ret | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | MC_START_CNTL |
| 0x37 | call | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x2f |
| 0x38 | call | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x2f |
| 0x39 | ret | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0x3a | call | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x30 |
| 0x3b | call | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x30 |
| 0x3c | ret | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| load_microcode: | |||||||||||||||||
| 0x3d | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0x3e | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0x000 |
| 0x3f | nxt | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x13 | • | • | • | 0x000 |
| 0x40 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0x000 |
| 0x41 | jmp | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | 0x3e |
| polyline: | |||||||||||||||||
| 0x42 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe6 |
| 0x43 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DSTCACHE_CTLSTAT |
| 0x44 | skp | • | • | • | • | • | pkt | • | • | • | • | • | ld [pc+1] | • | • | • | 0x000 |
| 0x45 | 0x00000000 0x00000000 | ||||||||||||||||
| 0x46 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | BRUSH_Y_X |
| 0x47 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DST_LINE_START |
| 0x48 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | DST_LINE_END |
| 0x49 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DST_LINE_START |
| 0x4a | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | DST_LINE_END |
| 0x4b | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x49 |
| nop: | |||||||||||||||||
| 0x4c | rpt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| paint: | |||||||||||||||||
| 0x4d | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe6 |
| 0x4e | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DSTCACHE_CTLSTAT |
| 0x4f | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0x000 |
| 0x50 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DST_Y_X |
| 0x51 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | sub.l | • | • | • | 0x000 |
| 0x52 | jn.l | • | • | • | • | • | pkt | • | • | • | • | • | sub.h | • | • | • | 0x55 |
| 0x53 | jn.h | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x55 |
| 0x54 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DST_HEIGHT_WIDTH |
| 0x55 | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x4f |
| paint_multi: | |||||||||||||||||
| 0x56 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe6 |
| 0x57 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DSTCACHE_CTLSTAT |
| 0x58 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DST_X_Y |
| 0x59 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DST_WIDTH_HEIGHT |
| 0x5a | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x58 |
| bitblt: | |||||||||||||||||
| bitblt_multi: | |||||||||||||||||
| 0x5b | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe6 |
| 0x5c | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DSTCACHE_CTLSTAT |
| 0x5d | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | DP_CNTL_XDIR_YDIR_YMAJOR |
| 0x5e | nxt | • | • | • | • | • | alu | • | • | • | • | • | sub.l | • | • | • | 0xe4 |
| 0x5f | nxt | • | • | • | • | • | pkt | • | • | • | • | • | sub.h | • | • | • | 0x0e4 |
| 0x60 | call | • | • | • | • | • | alu | • | • | • | • | • | ld pkt | • | • | • | 0x66 |
| 0x61 | nxt | • | • | • | • | • | alu | • | • | • | • | • | alu_0x18 | • | • | • | DST_X_Y |
| 0x62 | call | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x66 |
| 0x63 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | SRC_X_Y |
| 0x64 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DST_WIDTH_HEIGHT |
| 0x65 | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x5d |
| 0x66 | seq_0x04 | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x069 |
| 0x67 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | add.l | • | • | • | 0x000 |
| 0x68 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | inc.l | • | • | • | 0x0ff |
| 0x69 | seq_0x04 | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x06c |
| 0x6a | nxt | • | • | • | • | • | pkt | • | • | • | • | • | add.h | • | • | • | 0x000 |
| 0x6b | nxt | • | • | • | • | • | pkt | • | • | • | • | • | inc.h | • | • | • | 0x0ff |
| 0x6c | ret | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| trans_bitblt: | |||||||||||||||||
| 0x6d | call | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x8f |
| 0x6e | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x5b |
| small_text: | |||||||||||||||||
| 0x6f | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe6 |
| 0x70 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DSTCACHE_CTLSTAT |
| 0x71 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DP_SRC_FRGD_CLR |
| 0x72 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0x000 |
| 0x73 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x01 | • | • | • | 0x000 |
| 0x74 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x08 | • | • | • | 0x000 |
| 0x75 | nxt | • | • | • | • | • | alu.l | • | • | • | • | • | 0x000 | • | • | • | DST_Y_X |
| 0x76 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x09 | • | • | • | 0x000 |
| 0x77 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x0a | • | • | • | 0x000 |
| 0x78 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x0f | • | • | • | HOST_DATA_LAST |
| 0x79 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0x7a | jcz.l | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x7e |
| 0x7b | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DST_HEIGHT_WIDTH_8 |
| 0x7c | seq_0x10 | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | HOST_DATA0 |
| 0x7d | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x73 |
| 0x7e | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x73 |
| hostdata_blt: | |||||||||||||||||
| 0x7f | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe6 |
| 0x80 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DSTCACHE_CTLSTAT |
| 0x81 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DP_SRC_FRGD_CLR |
| 0x82 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DP_SRC_BKGD_CLR |
| 0x83 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DST_Y_X |
| 0x84 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DST_HEIGHT_WIDTH |
| 0x85 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0x86 | jcz.l | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x83 |
| 0x87 | seq_0x10 | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | HOST_DATA0 |
| 0x88 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | HOST_DATA_LAST |
| 0x89 | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x83 |
| nextchar: | |||||||||||||||||
| 0x8a | nxt | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x14 | • | • | • | DST_Y_X |
| 0x8b | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe6 |
| 0x8c | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DSTCACHE_CTLSTAT |
| 0x8d | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DST_HEIGHT_WIDTH |
| 0x8e | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x86 |
| 0x8f | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | CLR_CMP_CNTL |
| 0x90 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | CLR_CMP_CLR_SRC |
| 0x91 | ret | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | CLR_CMP_CLR_DST |
| polyscanlines: | |||||||||||||||||
| 0x92 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe6 |
| 0x93 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DSTCACHE_CTLSTAT |
| 0x94 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0x95 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0x96 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DST_HEIGHT_Y |
| 0x97 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0x000 |
| 0x98 | jcz.l | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x95 |
| 0x99 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x0b | • | • | • | 0x000 |
| 0x9a | nxt | • | • | • | • | • | alu.l | • | • | • | • | • | 0x000 | • | • | • | DST_WIDTH_X |
| 0x9b | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x97 |
| ply_nextscan: | |||||||||||||||||
| 0x9c | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe6 |
| 0x9d | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DSTCACHE_CTLSTAT |
| 0x9e | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x96 |
| 0x9f | rpt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0xe5 |
| set_scissors: | |||||||||||||||||
| 0xa0 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe6 |
| 0xa1 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | DSTCACHE_CTLSTAT |
| 0xa2 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe5 |
| 0xa3 | jz.l | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0xa8 |
| 0xa4 | call | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0xaa |
| 0xa5 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | SC_TOP_LEFT |
| 0xa6 | call | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0xab |
| 0xa7 | rpt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | SC_BOTTOM_RIGHT |
| 0xa8 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SC_TOP_LEFT |
| 0xa9 | rpt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SC_BOTTOM_RIGHT |
| 0xaa | ret | • | • | • | • | • | pkt | • | • | • | • | • | mul3.l | • | • | • | 0x000 |
| 0xab | nxt | • | • | • | • | • | pkt | • | • | • | • | • | mul3.l | • | • | • | 0x000 |
| 0xac | ret | • | • | • | • | • | pkt | • | • | • | • | • | inc.l | • | • | • | CLOCK_CNTL_INDEX |
| 3d_rndr_gen_indx_prim: | |||||||||||||||||
| 0xad | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SE_VTX_AOD_ADDR0 |
| 0xae | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 3d_rndr_gen_prim: | |||||||||||||||||
| 3d_draw_vbuf: | |||||||||||||||||
| 3d_draw_immd: | |||||||||||||||||
| 3d_draw_indx: | |||||||||||||||||
| 0xaf | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe7 |
| 0xb0 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | RB3D_DSTCACHE_CTLSTAT |
| 0xb1 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SE_VTX_FMT |
| 0xb2 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SE_VF_CNTL |
| 0xb3 | rpt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SE_PORT_DATA0 |
| type_1_handler: | |||||||||||||||||
| 0xb4 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0xb5 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | shr11 | • | • | • | 0x000 |
| 0xb6 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0xb7 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| dp_gui_2d: | |||||||||||||||||
| 0xb8 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0x000 |
| 0xb9 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DP_GUI_MASTER_CNTL |
| 0xba | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SRC_PITCH_OFFSET |
| 0xbb | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | DST_PITCH_OFFSET |
| 0xbc | nxt | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x22 | • | • | • | 0x000 |
| 0xbd | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe5 |
| 0xbe | jz.l | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0xc6 |
| 0xbf | call | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0xab |
| 0xc0 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | SRC_SC_BOTTOM_RIGHT |
| 0xc1 | call | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0xaa |
| 0xc2 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | SC_TOP_LEFT |
| 0xc3 | call | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0xab |
| 0xc4 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | SC_BOTTOM_RIGHT |
| 0xc5 | jmp | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0xc9 |
| 0xc6 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SRC_SC_BOTTOM_RIGHT |
| 0xc7 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SC_TOP_LEFT |
| 0xc8 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SC_BOTTOM_RIGHT |
| 0xc9 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | alu_0x21 | • | • | • | 0x000 |
| 0xca | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0xcb | jcz.l | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0xcd |
| 0xcc | seq_0x10 | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0xcd | jn.h | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0xcf |
| 0xce | ret | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0xcf | ret | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | BRUSH_Y_X |
| 0xd0 | 0x00000000 0x00000000 | ||||||||||||||||
| pkt_0x32: | |||||||||||||||||
| 0xd1 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x75c |
| 0xd2 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0xd3 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld pkt | • | • | • | 0x000 |
| 0xd4 | seq_0x10 | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | 0x75d |
| 0xd5 | rpt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 3d_load_vbpntr: | |||||||||||||||||
| 0xd6 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SE_VTX_NUM_ARRAYS |
| 0xd7 | rpt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| pkt_0x2b: | |||||||||||||||||
| 0xd8 | 0x00000000 0x6464614d | ||||||||||||||||
| 0xd9 | 0x00000000 0x69687420 | ||||||||||||||||
| 0xda | 0x00000000 0x00000073 | ||||||||||||||||
| 0xdb | 0x00000000 0x00000000 | ||||||||||||||||
| load_palette: | |||||||||||||||||
| 0xdc | nxt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0xdd | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xd0 |
| 0xde | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | SRC_CLUT_ADDRESS |
| 0xdf | rpt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | SRC_CLUT_DATA |
| 0xe0 | 0x00000000 0x00000001 | ||||||||||||||||
| wait_for_idle: | |||||||||||||||||
| 0xe1 | nxt | • | • | • | • | • | pkt | • | • | • | • | • | ld #addr | • | • | • | 0xe0 |
| 0xe2 | nxt | • | • | • | • | • | alu | • | • | • | • | • | 0x000 | • | • | • | NQWAIT_UNTIL |
| 0xe3 | rpt | • | • | • | • | • | pkt | • | • | • | • | • | 0x000 | • | • | • | 0x000 |
| 0xe4 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xe5 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xe6 | 0x00000000 0x00000008 | ||||||||||||||||
| 0xe7 | 0x00000000 0x00000004 | ||||||||||||||||
| 0xe8 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xe9 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xea | 0x00000000 0x00000000 | ||||||||||||||||
| 0xeb | 0x00000000 0x00000000 | ||||||||||||||||
| 0xec | 0x00000000 0x00000000 | ||||||||||||||||
| 0xed | 0x00000000 0x00000000 | ||||||||||||||||
| 0xee | 0x00000000 0x00000000 | ||||||||||||||||
| 0xef | 0x00000000 0x00000000 | ||||||||||||||||
| 0xf0 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xf1 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xf2 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xf3 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xf4 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xf5 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xf6 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xf7 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xf8 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xf9 | 0x00000000 0x00000000 | ||||||||||||||||
| 0xfa | 0x00000000 0x00000000 | ||||||||||||||||
| 0xfb | 0x00000000 0x00000000 | ||||||||||||||||
| 0xfc | 0x00000000 0x00000000 | ||||||||||||||||
| 0xfd | 0x00000000 0x00000000 | ||||||||||||||||
| 0xfe | 0x00000000 0x00000000 | ||||||||||||||||
| 0xff | 0x00000000 0x00000000 | ||||||||||||||||