If you appreciate the work done within the wiki, please consider supporting The Cutting Room Floor on Patreon. Thanks for all your support!

User:Athena/MIPS

From The Cutting Room Floor
Jump to navigation Jump to search

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!

Cacti may speak Japanese, but do they speak it well?
...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 cactus is UNDER CONSTRUCTION
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.

Emulator

online MIPS 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
Hmmm...
To do:
Other Commands

PSP

Some machine code are different in PSP MIPS. ex: jump, jump address.