If you find any bugs or create any DAT files, please let me know: Sean Riddlemipsdasm.c (12/26/00)
MIPS processors are RISC- reduced instruction set CPUs. There aren't many opcodes, but lots of registers. The registers are named, but ReplayTV doesn't always use them in a standard manner. $zero always returns a 0 on reads, and writes don't do anything. $ra contains the return address to jump to after a subroutine call. $sp is the stack pointer. Most other registers are general purpose, but $a0 and $a1 are used a lot for function parameters. All registers are 32 bits in length, and the CPU requires 32-bit alignment (although there are some load and store byte commands that can access non-aligned data).
If you're used to disassembling CISC machine code, there are some interesting differences. Instruction pipelining causes delayed branches and loads. The CPU is already processing the next operand before it decides whether or not to branch. So when you look at machine code, the instruction that you see immediately following a branch was really executed before the branch.
Delayed loads mean that the results of the load are not available in the next opcode. This results in a lot of no-operation (NOOP) instructions being inserted. Both of these are confusing, but much easier to handle when disassembling code than when writing it!
JAL jumps to a subroutine, storing the return address in $ra. BEQ $zero,$zero is a branch always. Actually, a BEQ comparing any register to itself will always branch, but I've only noticed $zero used in this way.
JR $ra is a return from subroutine. mipsdasm automatically inserts a blank line after both of these instructions to help break up the code into logical chunks.
It's a good idea to go through and locate all the text in the file first, and put those addresses into the DAT file so mipsdasm doesn't try to disassemble them. Then look for obvious data chunks and put them into the DAT file. Then search the mipsdasm output file for ??? which indicated an unknown opcode. This is probably also data or text.
PTV.BIN is the main program on the ReplayTV unit, so I started disassembling it first. The file has a 512-byte header that contains the header size as well as the binary file load address and length. PTV.BIN loads at $9C000000, so you'll see a lot of pointers in the code that start with 9C. Here are the top 20 subroutines that are called (I've figured some of them out):
name/address count ----------------------------------------- print_string_a0 1566 process_str_ptr_a1 796 save_t6_s0-s2 612 restore_t6_s0-s2 610 strcmp_a0_a1 595 save_t6_s0-s3 499 restore_t6_s0-s3 497 save_t6_s0-s7_fp 447 restore_t6_s0-s7_fp 443 strlen_a0 402 9C158834 397 9C0B0F74 372 save_t6_s0-s4 364 restore_t6_s0-s4 363 9C10DF3C 343 9C0B9B9C 311 9C0B97F8 289 9C154CA0 283 9C08FAD4 262 9C14B1E0 261
SPIM- the MIPS emulator
MIPS instruction reference
notes on implementing MIPS on an FPGA
PSX hacking- it also uses a MIPS processor