User:Athena/MIPS
This is a sub-page of User:Athena.
This page contains notes about the MIPS CPU on the N64, PS1, PS2 and PSP. You may edit this!
...But does it make sense? The translations on this page need to be proofread. If you are fluent enough in this language, please make any corrections necessary! |
This article is a work in progress. ...Well, all the articles here are, in a way. But this one moreso, and the article may contain incomplete information and editor's notes. |
Contents
Emulator
Registers
Number | Name | Notes |
---|---|---|
0 | zero | Always 0 |
1 | at | Temporary (used by the assembler.) |
2, 3 | v0, v1 | Return value |
4, 5, 6, 7 | a0, a1, a2, a3 | Function arguments |
8, 9, 10, 11, 12, 13, 14, 15, 24, 25 | t0, t1, t2, t3, t4, t5, t6, t7, t8, t9 | Temporary. These can destroy on exit function. |
16, 17, 18, 19, 20, 21, 22, 23 | s0, s1, s2, s3, s4, s5, s6, s7 | These doesn't destroy on exit function. |
26, 27 | k0, k1 | (Used by the OS. These are not often seen in PlayStation "game" programs.) |
28 | gp | Global pointer (Used for access to .bss or .data) |
29 | sp | Stack pointer |
30 | fp | Frame pointer |
31 | ra | Return address |
Instructions
MIPS Instruction Reference jawp:MIPSアーキテクチャ enwp:MIPS architecture MIPS IV Instruction Set
Jump Instructions
Jump ranges.
beq / bne
Uses for relative jump on inside of function. for relocatable function.
Jump range:
PC = PC + 4 + ( 4 * t ); // t = -32768~32767;
j / jal
Uses for (limited) absolute jump.
Jump range:
PC = ( PC & 0xFC000000 ) | ( t * 4 ); // t = 0~67108863(0x3FFFFFF);
jr / jalr
Uses for absolute jump.
Jump range:
PC = register;
Pseudo Instructions
These instructions appear in disassembled code. However, sometimes the emulator's change feature doesn't know these instructions.
move
This instruction is as follows 4 patterns:
; result "v0 <- v1" ; syntax "move v0,v1" addiu v0,v1,$0 addu v0,v1,zero ori v0,v1,$0 or v0,v1,zero ; later MIPS IV movz v0,v1,zero
dmove
This is the 64-bit version of move.
; result "v0 <- v1" ; syntax "dmove v0,v1" daddiu v0,v1,$0 daddu v0,v1,zero
li, la
- li is load immediate.
- la is load address.
; result "v0 <- $10FF ; syntax "li v0, $10FF" addiu v0, zero, $10FF ; result "v0 <- $80012345" ; syntax "li v0,$80012345" lui v0,$8001 addiu v0,v0,$2345 lui v0,$8001 ori v0,v0,$2345
li.s
- li.s is load single.
This instruction follows 2 patterns, depending on if the lower half of the float is needed.
; result "f0 <- 180.0f" ; syntax "li.s f0,180.0f" lui v0,$0x4334 mtc1 v0,f0 ; result "f0 <- Math.PI" ; syntax "li.s f0,3.1415926f" lui v0,$0x4049 ori v0,$0x0FDB mtc1 v0,f0
Single float 180.0f is 00 00 34 43 in hexadecimal (little endian).
li.d
- li.d is load double.
Note:
While the PS2 doesn't have any native support for double-precision floating point calculations, the PS2 can still utilize doubles in some limited fashion. Therefore, it is worthwhile noting how a double may be loaded into a register.
; result "v0 <- 1.0d" ; syntax "li.d v0, 1.0d" lui v0, $0x3FF0 dsll32 v0, v0, 32 ; may appear as "dsll32 v0, 32" depending on disassembler ; v0 = "0x3FF0000000000000" or 1.0d ; result "v0 <- nexttoward(1.0d, 0.0d)" ; syntax "li.d <- ~0.9999999999999d" lui v0, $0x3FEF ori v0, $0xFFFF dsll32 v0, v0, 32 ; may appear as "dsll32 v0, 32" depending on disassembler lui v0, $0xFFFF ori v0, $0xFFFF ; v0 = "0x3FEFFFFFFFFFFFFF" or ~0.9999999999999d
b
This instruction is as follows:
; syntax "b [address]" beq zero,zero,[address]
bgt / blt / bge / ble
This instruction is as follows:
; syntax "b** v0,v1,[address]" ; Greater Than v0>v1 slt at,v1,v0 bne at,zero,[address] ; Less Than v0<v1 slt at,v0,v1 bne at,zero,[address] ; Greater Equal v0>=v1 slt at,v0,v1 beq at,zero,[address] ; Less Equal v0<=v1 slt at,v1,v0 beq at,zero,[address]
subi
This instruction is as follows 2 patterns:
; syntax "subi v0,v0,$1234" addi v0,v0,-$1234 addi v0,v0,$EDCC
subiu
This instruction is as follows 2 patterns:
; syntax "subiu v0,v0,$1234" addiu v0,v0,-$1234 addiu v0,v0,$EDCC
nop
This instruction code is 0x00000000. It is helpful when you paint the nop on code.
sll zero,zero,$0 ; This code is 0x00000000
Common Patterns
These are often seen in PS1, PS2, PSP and N64 games.
(begin the function)
PSX: Notes:
- The stack is aligned to 0x08 when a function is called, therefore the amount of space allocated for the stack will be a multiple of 0x08. however, PS1 system calls aligned to 0x10.
addiu sp,sp,$xxxx ; alloc stack frame sw ra,$xxxx(sp) ; store return address sw s0,$xxxx(sp) ; when using saved registers (s0-s7, fp) in function ...
PS2:
Notes:
- The stack is aligned to 0x10 when a function is called, therefore the amount of space allocated for the stack will be a multiple of 0x10.
addiu sp,sp,$xxxx ; alloc stack frame sd ra,$xxxx(sp) ; store return address sq s0,$xxxx(sp) ; when using saved GPR (s0-s7, fp) in function swc1 f20, $xxxx(sp) ; when using saved FPU registers (f20-f27) in function ...
return
PS1: lw ra,$xxxx(sp) ; load return address lw s0,$xxxx(sp) ; when using saved GPR (s0-s7, fp) in function ... jr ra ; return! addiu sp,sp,$xxxx ; free stack frame (delay slot)
PS2:
ld ra,$xxxx(sp) ; load return address lq s0,$xxxx(sp) ; when using saved GPR (s0-s7, fp) in function lwc1 f20, $xxxx(sp) ; when using saved FPU registers (f20-f27) in function ... jr ra ; return! addiu sp,sp,$xxxx ; free stack frame (delay slot)
switch~case
It is almost as follows:
; switch( v1 ) { } ; check out of range sltiu v0,v1,$5 beq v0,zero,end_of_switch nop ; delay slot ; get the target case address sll v0,v1,2 li at,[address_table] addu at,at,v0 lw v0,$0(at) ; jump! jr v0 nop end_of_switch:
or like this:
; switch( v0 ) addiu v1,zero,$0 beq v0,v1,CASE_0 nop addiu v0,zero,$1 beq v0,v1,CASE_1 nop addiu v0,zero,$2 beq v0,v1,CASE_2 nop beq zero,zero,DEFAULT CASE_0: ; case 0: CASE_1: ; case 1: ; break; beq zero,zero,end_of_switch nop CASE_2: ; case 2: DEFAULT: ; default: end_of_switch:
(call function pointer)
lw v0,$xxxx(at) ; load from table or structure or something. jalr v0 ; call! nop ; delay slot
Calling Conventions
PS1
Integer arguments are passed in registers a0, a1, a2, a3, with additional arguments being stored at the bottom of the stack frame. For example, a 8-argument function might accept its parameters as such, f(a0, a1, a2, a3, $0(sp), $4(sp), $8(sp), $10(sp)). The amount of space each argument has on the stack depends on the size of the argument. In this example, each argument is a 32-bit value.
Integral values are returned in v0.
PS2
Integer arguments are passed in registers a0, a1, a2, a3, t0, t1, t2, t3, with additional arguments being stored at the bottom of the stack frame. For example, a 12-argument function might accept its parameters as such, f(a0, a1, a2, a3, t0, t1, t2, t3, 0(sp), 8(sp), 0x10(sp), 0x18(sp)). The amount of space each argument has on the stack depends on the size of the argument. In this example, each argument is a 64-bit value.
Floats are passed in registers f12-f19, with additional arguments being stored on the stack. For example, a 12-argument function might accept its parameters as such, f(f12, f13, f14, f15, f16, f17, f18, f19, 0(sp), 4(sp), 8(sp), 0xC(sp)).
Integral values are returned in GPR v0, while floating point values are returned in FPU register f0.
Machines Dependency
PS1
break Instruction
nearly to entry point.
; entry point ; .... ; initialize code ... ; .... jal $xxxxxxxx ; jump to startup routine. after that jump to main( ). or simply jump to main( ) nop break (00001)
System Call
PS1 system call code like this:
; t1 <- function type number ; arguments to a0,a1,a2,a3 (sp+0x10) (sp+0x20) (sp+0x30) (sp+0x40)... addiu k0,zero,$00A0 ; call address addiu t1,zero,$0000 ; function type number jalr k0 ; fire! nop ; delay slot ; shorter j $800000A0 ; fire! addiu t1,zero,$0000 ; function type number (delay slot)
Call Address | Function Type Number | Function | Description |
---|---|---|---|
0x00A0 | 0x0000 | FileDiscriptor open( char* name, int mode ) | |
0x00A0 | 0x0001 | int seek( FileDiscriptor descriptor, size_t offset, int mode ) | |
0x00A0 | 0x0002 | int read( FileDiscriptor descriptor, char* buffer, size_t bytes ) | |
0x00A0 | 0x0003 | int write( FileDiscriptor descriptor, char* buffer, size_t bytes ) | |
0x00A0 | 0x0004 | void close( FileDiscriptor descriptor ) | |
0x00A0 | 0x000B | double atof( char* s ) | |
0x00A0 | 0x000D | unsigned long strtol( char* s, char** ptr, int base ) | |
0x00A0 | 0x000E | int abs( int val ) | |
0x00A0 | 0x0010 | int atoi( char* s ) | |
0x00A0 | 0x0013 | int setjmp( jmp_buf *ctx ) |
Blackmagic |
0x00A0 | 0x0014 | int longjmp( jmp_buf *ctx, int value ) |
Blackmagic |
0x00A0 | 0x0015 | char* strcat( char* dest, char* src ) | |
0x00A0 | 0x0016 | char* strncat( char* dest, char* src, size_t n ) | |
0x00A0 | 0x0017 | int strcmp( char* dest, char* src ) | |
0x00A0 | 0x0018 | int strncmp( char* dest, char* src, size_t n ) | |
0x00A0 | 0x0019 | char* strcpy( char* dest, char* src ) | |
0x00A0 | 0x001A | char* strncpy( char* dest, char* src, size_t n ) | |
0x00A0 | 0x001B | size_t strlen( char* s ) | |
0x00A0 | 0x001C | char* index( char* s, int c ) | |
0x00A0 | 0x001D | char* rindex( char* s, int c ) | |
0x00A0 | 0x001E | char* strchr( char* s, int c ) | |
0x00A0 | 0x001F | char* strrchr( char* s, int c ) | |
0x00A0 | 0x0020 | char* strpbrk( char* dest, char* src ) | |
0x00A0 | 0x0021 | size_t strspn( char* s1, char* s2 ) | |
0x00A0 | 0x0022 | size_t strcspn( char* s1, char* s2 ) | |
0x00A0 | 0x0023 | char* strtok( char* s1, char* s2 ) | |
0x00A0 | 0x0024 | char* strstr( char* s1, char* s2 ) | |
0x00A0 | 0x0025 | int toupper( int c ) | |
0x00A0 | 0x0026 | int tolower( int c ) | |
0x00A0 | 0x0027 | void bcopy( void* src, void* dest, size_t n ) | |
0x00A0 | 0x0028 | void bzero( void* s, size_t n ) | |
0x00A0 | 0x0029 | int bcmp( void* s1, void* s2, size_t n ) | |
0x00A0 | 0x002A | void* memcpy( void* dest, void* src, size_t n ) | |
0x00A0 | 0x002B | void* memset( void* dest, int c, size_t n ) | |
0x00A0 | 0x002C | void* memmove( void* dest, void* src, size_t n ) | |
0x00A0 | 0x002D | int memcmp( void* dest, void* src, size_t n ) | |
0x00A0 | 0x002E | void* memchr( void* s, int c, size_t n ) | |
0x00A0 | 0x002F | int rand( ) | |
0x00A0 | 0x0030 | void srand( unsigned s ) | |
0x00A0 | 0x0031 | void qsort( void* base, size_t num, size_t size, int (*compare)( void*, void* ) ) | |
0x00A0 | 0x0032 | double strtod( char* s, char** endptr ) | |
0x00A0 | 0x0033 | void* malloc( size_t size ) |
need call InitHeap before call this. |
0x00A0 | 0x0034 | void free( void* s ) | |
0x00A0 | 0x0035 | void lsearch( void* key, void* base, size_t* nmemb, size_t size, int (*compare)( void*, void* ) ) | |
0x00A0 | 0x0036 | void bsearch( void* key, void* base, size_t* nmemb, size_t size, int (*compare)( void*, void* ) ) | |
0x00A0 | 0x0037 | void* calloc( size_t size, size_t n ) | |
0x00A0 | 0x0038 | void* realloc( void* s, size_t n ) | |
0x00A0 | 0x0039 | int InitHeap( void* head, size_t size ) | |
0x00A0 | 0x003C | int putchar( int c ) |
Output to TTY console |
0x00A0 | 0x003E | int puts( char* s ) |
Output to TTY console |
0x00A0 | 0x003F | int printf( char* format, ... ) |
Output to TTY console |
0x00A0 | 0x0041 | int LoadTest( char* s, struct PSEXE *header ) |
Load PS-EXE file header. |
0x00A0 | 0x0042 | int Load( char* s, struct PSEXE *header ) |
Load PS-EXE file. |
0x00A0 | 0x0043 | int Exec( struct PSEXE *header, int arc, char* argv[] ) |
Execute loaded PS-EXE. |
0x00A0 | 0x0042 | int LoadExec( char* s, int argc, char* argv[] ) |
Load PS-EXE file. |
0x00B0 | 0x0012 | int InitPAD( char* pad1, size_t len1, char* pad2, size_t len2 ) | |
0x00B0 | 0x0013 | int StartPAD( ) | |
0x00B0 | 0x0014 | int StopPAD( ) | |
0x00B0 | 0x0016 | unsigned int PAD_dr( ) | |
0x00B0 | 0x0040 | int chdir( char* s ) | |
0x00B0 | 0x0041 | int format( char* s ) |
Format memory card |
0x00B0 | 0x0044 | int rename( char* old, char* new ) | |
0x00B0 | 0x0045 | int delete( char* s ) | |
0x00B0 | 0x0051 | void* Krom2RawAdd( int c ) |
Calculate Kanji ROM address by shift-jis code. |
GPU Packet Command
- Vertex: 16 bit
- UV: 8 bit
Format | Draw |
---|---|
20 B G R ; Command and Color Y0 Y0 X0 X0 ; Vertex #0 Y1 Y1 X1 X1 ; Vertex #1 Y2 Y2 X2 X2 ; Vertex #2 |
Single Color Triangle |
24 B G R ; Command and Color Y0 Y0 X0 X0 ; Vertex #0 CLUT V0 U0 ; CLUT-ID and UV #0 Y1 Y1 X1 X1 ; Vertex #1 tpage V1 U1 ; Texture page and UV #1 Y2 Y2 X2 X2 ; Vertex #2 00 00 V2 U2 ; UV #2 |
Texture Triangle |
28 B G R ; Command and Color Y0 Y0 X0 X0 ; Vertex #0 Y1 Y1 X1 X1 ; Vertex #1 Y2 Y2 X2 X2 ; Vertex #2 Y3 Y3 X3 X3 ; Vertex #3 |
Single Color Quadrilateral |
2C B G R ; Command and Color Y0 Y0 X0 X0 ; Vertex #0 CLUT V0 U0 ; CLUT-ID and UV #0 Y1 Y1 X1 X1 ; Vertex #1 tpage V1 U1 ; Texture page and UV #1 Y2 Y2 X2 X2 ; Vertex #2 00 00 V2 U2 ; UV #2 Y3 Y3 X3 X3 ; Vertex #3 00 00 V3 U3 ; UV #3 |
Texture Quadrilateral |
30 B0 G0 R0 ; Command and Color #0 Y0 Y0 X0 X0 ; Vertex #0 00 B1 G1 R1 ; Color #1 Y1 Y1 X1 X1 ; Vertex #1 00 B2 G2 R2 ; Color #2 Y2 Y2 X2 X2 ; Vertex #2 |
Gradation Triangle |
34 B0 G0 R0 ; Command and Color #0 Y0 Y0 X0 X0 ; Vertex #0 CLUT V0 U0 ; CLUT-ID and UV #0 00 B1 G1 R1 ; Color #1 Y1 Y1 X1 X1 ; Vertex #1 tpage V1 U1 ; Texture page and UV #1 00 B2 G2 R2 ; Color #2 Y2 Y2 X2 X2 ; Vertex #2 00 00 V2 U2 ; UV #2 |
Gradation Texture Triangle |
38 B0 G0 R0 ; Command and Color #0 Y0 Y0 X0 X0 ; Vertex #0 00 B1 G1 R1 ; Color #1 Y1 Y1 X1 X1 ; Vertex #1 00 B2 G2 R2 ; Color #2 Y2 Y2 X2 X2 ; Vertex #2 00 B3 G3 R3 ; Color #3 Y3 Y3 X3 X3 ; Vertex #3 |
Gradation Quadrilateral |
3C B0 G0 R0 ; Command and Color #0 Y0 Y0 X0 X0 ; Vertex #0 CLUT V0 U0 ; CLUT-ID and UV #0 00 B1 G1 R1 ; Color #1 Y1 Y1 X1 X1 ; Vertex #1 tpage V1 U1 ; Texture page and UV #1 00 B2 G2 R2 ; Color #2 Y2 Y2 X2 X2 ; Vertex #2 00 00 V2 U2 ; UV #2 00 B3 G3 R3 ; Color #3 Y3 Y3 X3 X3 ; Vertex #3 00 00 V3 U3 ; UV #3 |
Gradation Texture Quadrilateral |
40 B G R ; Command and Color Y0 Y0 X0 X0 ; Vertex #0 Y1 Y1 X1 X1 ; Vertex #1 |
Line |
48 B G R ; Command and Color Yn Yn Xn Xn ; Vertex #n ... 55 55 55 55 ; Terminate |
Poly Line |
50 B0 G0 R0 ; Command and Color #0 Y0 Y0 X0 X0 ; Vertex #0 00 B1 G1 R1 ; Color #1 Y1 Y1 X1 X1 ; Vertex #1 |
Gradation Line |
58 B0 G0 R0 ; Command and Color #0 Y0 Y0 X0 X0 ; Vertex #0 00 Bn Gn Rn ; Color #n Yn Yn Xn Xn ; Vertex #n ... 55 55 55 55 ; Terminate |
Gradation Poly Line |
60 B G R ; Command and Color Y Y X X ; Upper left coordinate H H W W ; Height and Width |
Rectangle |
64 B G R ; Command and Color Y Y X X ; Upper left coordinate CLUT V U ; CLUT-ID and UV H H W W ; Height and Width |
Sprite |
68 B G R ; Command and Color Y Y X X ; Coordinate |
Dot |
70 B G R ; Command and Color Y Y X X ; Coordinate |
8x8 Rectangle |
74 B G R ; Command and Color Y Y X X ; Coordinate CLUT V U ; CLUT-ID and UV |
8x8 Sprite |
78 B G R ; Command and Color Y Y X X ; Coordinate |
16x16 Rectangle |
7C B G R ; Command and Color Y Y X X ; Coordinate CLUT V U ; CLUT-ID and UV |
16x16 Sprite |
To do: Other Commands |
PSP
Some machine code are different in PSP MIPS. ex: jump, jump address.