Back in the beginning, we did a register scan and noticed two sets of registers that, by default, have values strangely similiar to the NOP encodings for the 4 execution units:
00f448: df000000 ffffffff 00000000 * 00f44c: 4f000000 ffffffff 00000000 * 00f450: bf000000 ffffffff 00000000 * 00f454: ef000000 ffffffff 00000000 *
00f510: df000000 df000000 df000000 00f514: 4f000000 4f000000 4f000000 00f518: bf000000 bf000000 bf000000 00f51c: ef000000 ef000000 ef000000
f448+ are writable, though only from MMIO side. f510 are read-only, but back in episode 3 we've seen them read out as the most recently executed instruction of the corresponding type. This strongly suggests that they represent the current state of branch unit -> execution unit opcode path.
The f448+ ones are more interesting. Being writable strongly suggests that we can use them to manually launch an instruction, without going through the trouble of setting up and executing a microcode piece. Let's try setting $r0 to 0xdead. Since f44c appears to hold the scalar path NOP, we'll try poking the opcode to that one:
$ nvapoke f44c 6500dead $ nvapeek f448 10 0000f448: df000000 6500dead bf000000 ef000000 $ nvapeek f780 0000f780: 6df5e6ef
Nope, but there may be a trigger register in the f400+ range that launches the instruction. Let's see.
$ nvascan f400 200 [...] $ nvapeek f780 0000f780: 0000dead $ nvapeek f448 10 0000f448: df000000 4f000000 bf000000 ef000000
Yeah. That did it. And the opcode registers got reset to NOPs again, how convenient. After a bit of binary searching to narrow it down, we deduce that register f458 has to be written with a value that has bit 0 set to 1 to trigger the launch and clear to NOP.
So we can now launch instructions without bothering with the upload stuff. That'll be quite useful for REing the vector/scalar and maybe address instructions.
Elapsed time: 30m.Share on Twitter Share on Facebook