====== MIPS R4300i CPU ======
The main processor used by the Nintendo 64.
  * R43XX User manual: https://hack64.net/docs/VR43XX.pdf
  * R4300i Product info: http://datasheets.chipdb.org/MIPS/R4300i_datasheet.pdf
Information on this page that is specifically related to the Nintendo 64 is highlighted in green.
...
...
...
===== Commands =====
^ Command                       ^ Definition                                                    ^ Pseudo code                        ^
| AND         rd, rs, rt        | And                                                           | %%rd = rs & rt                  %% |
| ANDI        rt, rs, immediate | And Immediate                                                 | %%rt = rs & immediate           %% |
| OR          rd, rs, rt        | Or                                                            | %%rd = rs | rt                  %% |
| ORI         rt, rs, immediate | Or Immediate                                                  | %%rt = rs | immediate           %% |
| XOR         rd, rs, rt        | Exclusive Or                                                  | %%rd = rs ^ rt                  %% |
| XORI        rt, rs, immediate | Exclusive Or Immediate                                        | %%rd = rs ^ immediate           %% |
| NOR         rd, rs, rt        | Nor                                                           | %%rd = ~(rs | rt)               %% |
| SLT         rd, rs, rt        | Set On Less Than                                              | %%rd = (rs < rt) ? 1 : 0        %% |
| SLTU        rd, rs, rt        | Set On Less Than Unsigned                                     | %%rd = (rs < rt) ? 1 : 0        %% |
| SLTI        rt, rs, immediate | Set On Less Than Immediate                                    | %%rt = (rs < immediate) ? 1 : 0 %% |
| SLTIU       rt, rs, immediate | Set On Less Than Immediate Unsigned                           | %%rt = (rs < immediate) ? 1 : 0 %% |
| ADD         rd, rs, rt        | Add                                                           | %%rd = rs + rt                  %% |
| ADDU        rd, rs, rt        | Add Unsigned                                                  | %%rd = rs + rt                  %% |
| ADDI        rt, rs, immediate(("immediate": 16-bit signed immediate value)) | Add Immediate   | %%rd = rs + immediate           %% |
| ADDIU       rt, rs, immediate | Add Immediate Unsigned                                        | %%rd = rs + immediate           %% |
| SUB         rd, rs, rt        | Subtract                                                      | %%rd = rs - rt                  %% |
| SUBU        rd, rs, rt        | Subtract Unsigned                                             | %%rd = rs - rt                  %% |
| MULT        rs, rt            | Multiply                                                      | %%lo = rs * rt                  %% |
| MULTU       rs, rt            | Multiply Unsigned                                             | %%lo = rs * rt                  %% |
| DIV         rs, rt            | Divide                                                        | %%lo = rs / rt; hi = rs % rt    %% |
| DIVU        rs, rt            | Divide Unsigned                                               | %%lo = rs / rt; hi = rs % rt    %% |
| SLL         rd, rt, sa(("sa": 5-bit immediate shift amount))| Shift Left Logical              | %%rd = rt << sa                 %% |
| SLLV        rd, rt, rs        | Shift Left Logical Variable                                   | %%rd = rt << rs                 %% |
| SRA         rd, rt, sa        | Shift Right Arithmetic                                        | %%rd = (int32)rt >> sa          %% |
| SRAV        rd, rt, rs        | Shift Right Arithmetic Variable                               | %%rd = (int32)rt >> rs          %% |
| SRL         rd, rt, sa        | Shift Right Logical                                           | %%rd = (uint32)rt >> sa         %% |
| SRLV        rd, rt, rs        | Shift Right Logical Variable                                  | %%rd = (uint32)rt >> rs         %% |
| DADD        rd, rs, rt        | Doubleword Add                                                | %%rd = rs + rt                  %% |
| DADDU       rd, rs, rt        | Doubleword Add Unsigned                                       | %%rd = rs + rt                  %% |
| DADDI       rt, rs, immediate | Doubleword Add Immediate                                      | %%rd = rs + immediate           %% |
| DADDIU      rt, rs, immediate | Doubleword Add Immediate Unsigned                             | %%rd = rs + immediate           %% |
| DSUB        rd, rs, rt        | Doubleword Subtract                                           | %%rd = rs - rt                  %% |
| DSUBU       rd, rs, rt        | Doubleword Subtract Unsigned                                  | %%rd = rs - rt                  %% |
| DMULT       rs, rt            | Doubleword Multiply                                           | %%lo = rs * rt                  %% |
| DMULTU      rs, rt            | Doubleword Multiply Unsigned                                  | %%lo = rs * rt                  %% |
| DDIV        rs, rt            | Doubleword Divide                                             | %%lo = rs / rt; hi = rs % rt    %% |
| DDIVU       rs, rt            | Doubleword Divide Unsigned                                    | %%lo = rs / rt; hi = rs % rt    %% |
| DSLL        rd, rt, sa        | Doubleword Shift Left Logical                                 | %%rd = rt << sa                 %% |
| DSLL32      rd, rt, sa        | Doubleword Shift Left Logical + 32                            | %%rd = rt << (sa + 32)          %% |
| DSLLV       rd, rt, rs        | Doubleword Shift Left Logical Variable                        | %%rd = rt << rs                 %% |
| DSRA        rd, rt, sa        | Doubleword Shift Right Arithmetic                             | %%rd = (int64)rt >> sa          %% |
| DSRA32      rd, rt, sa        | Doubleword Shift Right Arithmetic + 32                        | %%rd = (int64)rt >> (sa + 32)   %% |
| DSRAV       rd, rt, rs        | Doubleword Shift Right Arithmetic Variable                    | %%rd = (int64)rt >> rs          %% |
| DSRL        rd, rt, sa        | Doubleword Shift Right Logical                                | %%rd = (uint64)rt >> sa         %% |
| DSRL32      rd, rt, sa        | Doubleword Shift Right Logical + 32                           | %%rd = (uint64)rd >> (sa + 32)  %% |
| DSRLV       rd, rt, rs        | Doubleword Shift Right Logical Variable                       | %%rd = (uint64)rd >> rs         %% |
| MFHI        rd                | Move From HI                                                  | %%rd = hi                       %% |
| MFLO        rd                | Move From LO                                                  | %%rd = lo                       %% |
| MTHI        rs                | Move To HI                                                    | %%hi = rs                       %% |
| MTLO        rs                | Move To LO                                                    | %%lo = rs                       %% |
| LUI         rt, immediate     | Load Upper Immediate                                          | %%rt = immediate << 16          %% |
| LB          rt, offset(rs)    | Load Byte                                                     | %%rt = *(int8*)(rs + offset)  %% |
| LBU         rt, offset(rs)    | Load Byte Unsigned                                            | %%rt = *(uint8*)(rs + offset) %% |
| LH          rt, offset(rs)    | Load Halfword                                                 | %%rt = *(int16*)(rs + offset) %% |
| LHU         rt, offset(rs)    | Load Halfword Unsigned                                        | %%rt = *(uint16*)(rs + offset)%% |
| LW          rt, offset(rs)    | Load Word                                                     | %%rt = *(int32*)(rs + offset) %% |
| LWU         rt, offset(rs)    | Load Word Unsigned                                            | %%rt = *(uint32*)(rs + offset)%% |
| LWC1        ft, offset(rs)    | Load Word To FPU(("FPU": Floating-point unit, another name for Coprocessor 1)) | %%ft = *(float*)(rs + offset) %% |
| LWL         rt, offset(rs)    | Load Word Left                                                | %%                              %% |
| LWR         rt, offset(rs)    | Load Word Right                                               | %%                              %% |
| LD          rt, offset(rs)    | Load Doubleword                                               | %%rt = *(uint64*)(rs + offset)%% |
| LDC1        ft, offset(rs)    | Load Doubleword To FPU                                        | %%ft = *(double*)(rs + offset)%% |
| LDL         rt, offset(rs)    | Load Doubleword Left                                          | %%                              %% |
| LDR         rt, offset(rs)    | Load Doubleword Right                                         | %%                              %% |
| LL          rt, offset(rs)    | Load Linked                                                   | %%                              %% |
| LLD         rt, offset(rs)    | Load Linked Doubleword                                        | %%                              %% |
| SB          rt, offset(rs)    | Store Byte                                                    | %%*(int8*)(rs + offset) = rt  %% |
| SH          rt, offset(rs)    | Store Halfword                                                | %%*(int16*)(rs + offset) = rt %% |
| SW          rt, offset(rs)    | Store Word                                                    | %%*(int32*)(rs + offset) = rt %% |
| SWC1        ft, offset(rs)    | Store Word From FPU                                           | %%*(float*)(rs + offset) = ft %% |
| SWL         rt, offset(rs)    | Store Word Left                                               | %%                              %% |
| SWR         rt, offset(rs)    | Store Word Right                                              | %%                              %% |
| SD          rt, offset(rs)    | Store Doubleword                                              | %%*(int64*)(rs + offset) = rt %% |
| SDC1        ft, offset(rs)    | Store Doubleword From FPU                                     | %%*(double*)(rs + offset) = rt %% |
| SDL         rt, offset(rs)    | Store Doubleword Left                                         | %%                              %% |
| SDR         rt, offset(rs)    | Store Doubleword Right                                        | %%                              %% |
| SC          rt, offset(rs)    | Store Conditional                                             | %%                              %% |
| SCD         rt, offset(rs)    | Store Conditional Doubleword                                  | %%                              %% |
| J           target            | Jump                                                          | %% PC = target                  %% |
| JR          rs                | Jump Register                                                 | %% PC = rs                      %% |
| JAL         target            | Jump And Link                                                 | %% RA = PC + 8; PC = target     %% |
| JALR        rs                | Jump And Link Register                                        | %% rd = PC + 8; PC = rs         %% |
| JALR        rd, rs            | Jump And Link Register                                        | %% rd = PC + 8; PC = rs         %% |
| BEQ         rs, rt, target    | Branch On Equal                                               | %% if(rs == rt) PC = target     %% |
| BEQL        rs, rt, target    | Branch On Equal Likely                                        | %% if(rs == rt) PC = target     %% |
| BNE         rs, rt, target    | Branch On Not Equal                                           | %% if(rs != rt) PC = target     %% |
| BNEL        rs, rt, target    | Branch On Not Equal Likely                                    | %% if(rs != rt) PC = target     %% |
| BGTZ        rs, target        | Branch On Greater Than Zero                                   | %% if(rs > 0) PC = target       %% |
| BGTZL       rs, target        | Branch On Greater Than Zero Likely                            | %% if(rs > 0) PC = target       %% |
| BLEZ        rs, target        | Branch On Less Than Or Equal To Zero                          | %% if(rs <= 0) PC = target      %% |
| BLEZL       rs, target        | Branch On Less Than Or Equal To Zero Likely                   | %% if(rs <= 0) PC = target      %% |
| BGEZ        rs, target        | Branch On Greater Than Or Equal To Zero                       | %% if(rs >= 0) PC = target      %% |
| BGEZL       rs, target        | Branch On Greater Than Or Equal To Zero\\ Likely              | %% if(rs >= 0) PC = target       %% |
| BGEZAL      rs, target        | Branch On Greater Than Or Equal To Zero\\ And Link            | if(rs %%>=%% 0) {\\ RA = PC + 8; PC = target\\ } |
| BGEZALL     rs, target        | Branch On Greater Than Or Equal To Zero\\ And Link Likely     | if(rs %%>=%% 0) {\\ RA = PC + 8; PC = target\\ } |
| BLTZ        rs, target        | Branch On Less Than Zero                                      | %% if(rs < 0) PC = target       %% |
| BLTZL       rs, target        | Branch On Less Than Zero Likely                               | %% if(rs < 0) PC = target       %% |
| BLTZAL      rs, target        | Branch On Less Than Zero And Link                             | if(rs < 0) {\\ RA = PC + 8; PC = target\\ } |
| BLTZALL     rs, target        | Branch On Less Than Zero And Link Likely                      | if(rs < 0) {\\ RA = PC + 8; PC = target\\ } |
| MFC1        rt, fs            | Move Word From FPU                                            | %% rt = fs %% |
| DMFC1       rt, fs            | Doubleword Move From FPU                                      | %%  rt = fs  %% |
| MTC1        rt, fs            | Move To FPU                                                   | %% fs = rt %% |
| DMTC1       rt, fs            | Doubleword Move To FPU                                        | %% fs = rt %% |
| CFC1        rt, fcr           | Move Control Word From FPU                                    | %% rt = fcr %% |
| CTC1        rt, fcr           | Move Control Word To FPU                                      | %% rt = fcr %% |
| MOV.S     fd, fs              | FPU Move Float                                                | %% fd = fs                %% |
| ABS.S     fd, fs              | FPU Absolute Value Float                                      | %% fd = abs(fs)           %% |
| NEG.S     fd, fs              | FPU Negate Float                                              | %% fd = -fs               %% |
| SQRT.S    fd, fs              | FPU Square Root Float                                         | %% fd = sqrt(fs)          %% |
| ADD.S     fd, fs, ft          | FPU Add Floats                                                | %% fd = fs + ft           %% |
| SUB.S     fd, fs, ft          | FPU Subtract Floats                                           | %% fd = fs - ft           %% |
| MUL.S     fd, fs, ft          | FPU Multiply Floats                                           | %% fd = fs * ft           %% |
| DIV.S     fd, fs, ft          | FPU Divide Floats                                             | %% fd = fs / ft           %% |
| MOV.D     fd, fs              | FPU Move Double                                               | %% fd = fs                %% |
| ABS.D     fd, fs              | FPU Absolute Value Double                                     | %% fd = abs(fs)           %% |
| NEG.D     fd, fs              | FPU Negate Double                                             | %% fd = -fs               %% |
| SQRT.D    fd, fs              | FPU Square Root Double                                        | %% fd = sqrt(fs)          %% |
| ADD.D     fd, fs, ft          | FPU Add Doubles                                               | %% fd = fs + ft           %% |
| SUB.D     fd, fs, ft          | FPU Subtract Doubles                                          | %% fd = fs - ft           %% |
| MUL.D     fd, fs, ft          | FPU Multiply Doubles                                          | %% fd = fs * ft           %% |
| DIV.D     fd, fs, ft          | FPU Divide Doubles                                            | %% fd = fs / ft           %% |
| FLOOR.L.S   fd, fs            | FPU Floor Float To Fixed-point Long                           | %%  fd = (int64)floor(fs) %% |
| FLOOR.W.S   fd, fs            | FPU Floor Float To Fixed-point Word                           | %%  fd = (int32)floor(fs) %% |
| ROUND.L.S   fd, fs            | FPU Round Float To Fixed-point Long                           | %%  fd = (int64)round(fs) %% |
| ROUND.W.S   fd, fs            | FPU Round Float To Fixed-point Word                           | %%  fd = (int32)round(fs) %% |
| TRUNC.L.S   fd, fs            | FPU Truncate Float To Fixed-point Long                        | %%  fd = (int64)trunc(fs) %% |
| TRUNC.W.S   fd, fs            | FPU Truncate Float To Fixed-point Word                        | %%  fd = (int32)trunc(fs) %% |
| CEIL.L.S    fd, fs            | FPU Ceiling Float To Fixed-point Long                         | %%  fd = (int64)ceil(fs)  %% |
| CEIL.W.S    fd, fs            | FPU Ceiling Float To Fixed-point Word                         | %%  fd = (int32)ceil(fs)  %% |
| FLOOR.L.D   fd, fs            | FPU Floor Double To Fixed-point Long                          | %%  fd = (int64)floor(fs) %% |
| FLOOR.W.D   fd, fs            | FPU Floor Double To Fixed-point Word                          | %%  fd = (int32)floor(fs) %% |
| ROUND.L.D   fd, fs            | FPU Round Double To Fixed-point Long                          | %%  fd = (int64)round(fs) %% |
| ROUND.W.D   fd, fs            | FPU Round Double To Fixed-point Word                          | %%  fd = (int32)round(fs) %% |
| TRUNC.L.D   fd, fs            | FPU Truncate Double To Fixed-point Long                       | %%  fd = (int64)trunc(fs) %% |
| TRUNC.W.D   fd, fs            | FPU Truncate Double To Fixed-point Word                       | %%  fd = (int32)trunc(fs) %% |
| CEIL.L.D    fd, fs            | FPU Ceiling Double To Fixed-point Long                        | %%  fd = (int64)ceil(fs)  %% |
| CEIL.W.D    fd, fs            | FPU Ceiling Double To Fixed-point Word                        | %%  fd = (int32)ceil(fs)  %% |
| CVT.D.S   fd, fs              | FPU Convert Float To Double                                   | %% fd = (double)fs        %% |
| CVT.W.S   fd, fs              | FPU Convert Float To Fixed-point Word                         | %% fd = (int32)fs         %% |
| CVT.L.S   fd, fs              | FPU Convert Float To Fixed-Point Long                         | %% fd = (int64)fs         %% |
| CVT.S.D   fd, fs              | FPU Convert Double To Float                                   | %% fd = (float)fs         %% |
| CVT.W.D   fd, fs              | FPU Convert Double To Fixed-point Word                        | %% fd = (int32)fs         %% |
| CVT.L.D   fd, fs              | FPU Convert Double To Fixed-Point Long                        | %% fd = (int64)fs         %% |
| CVT.S.W   fd, fs              | FPU Convert Fixed-Point Word To Float                         | %% fd = (float)fs         %% |
| CVT.S.L   fd, fs              | FPU Convert Fixed-Point Long To Float                         | %% fd = (float)fs         %% |
| CVT.D.W   fd, fs              | FPU Convert Fixed-Point Word To Double                        | %% fd = (double)fs        %% |
| CVT.D.L   fd, fs              | FPU Convert Fixed-Point Long To Double                        | %% fd = (double)fs        %% |
| C.EQ.S    fs, ft              | FPU Compare Equal Float                                       | %% FCR31.C = (fs == ft)   %% |
| C.LT.S    fs, ft              | FPU Compare Less Than Float                                   | %% FCR31.C = (fs < ft)    %% |
| C.LE.S    fs, ft              | FPU Compare Less Than or Equal Float                          | %% FCR31.C = (fs <= ft)   %% |
| C.EQ.D    fs, ft              | FPU Compare Equal Double                                      | %% FCR31.C = (fs == ft)   %% |
| C.LT.D    fs, ft              | FPU Compare Less Than Double                                  | %% FCR31.C = (fs < ft)    %% |
| C.LE.D    fs, ft              | FPU Compare Less Than or Equal Double                         | %% FCR31.C = (fs <= ft)   %% |
| C.F.S     fs, ft              | FPU Compare False Float                                       | %% FCR31.C = FALSE                                     %% |
| C.UN.S    fs, ft              | FPU Compare Unordered Float                                   | %% FCR31.C = (isNaN(fs) || isNaN(ft))                  %% |
| C.UEQ.S   fs, ft              | FPU Compare Unordered or Equal Float                          | %% FCR31.C = (isNaN(fs) || isNaN(ft) || (fs == ft))    %% |
| C.OLT.S   fs, ft              | FPU Compare Ordered Less Than Float                           | %% FCR31.C = (!isNaN(fs) && !isNaN(ft) && (fs < ft))   %% |
| C.ULT.S   fs, ft              | FPU Compare Unordered or Less Than Float                      | %% FCR31.C = (isNaN(fs) || isNaN(ft) || (fs < ft))     %% |
| C.OLE.S   fs, ft              | FPU Compare Ordered Less Than\\ Or Equal Float                | %% FCR31.C = (!isNaN(fs) && !isNaN(ft) && (fs <= ft))  %% |
| C.ULE.S   fs, ft              | FPU Compare Unordered or Less Than\\ or Equal Float           | %% FCR31.C = (isNaN(fs) || isNaN(ft) || (fs <= ft))    %% |
| C.SF.S    fs, ft              | FPU Compare Signaling False Float                             | %% FCR31.C = FALSE                                     %% |
| C.NGLE.S  fs, ft              | FPU Compare Not Greater\\ Or Less Than or Equal Float         | %% FCR31.C = (isNaN(fs) || isNaN(ft))                  %% |
| C.SEQ.S   fs, ft              | FPU Compare Signaling Equal Float                             | %% FCR31.C = (fs == ft)                                %% |
| C.NGL.S   fs, ft              | FPU Compare Not Greater Or Less Than Float                    | %% FCR31.C = !((fs > ft) || (fs < ft))                 %% |
| C.NGE.S   fs, ft              | FPU Compare Not Greater Than or Equal Float                   | %% FCR31.C = !(fs >= ft)                               %% |
| C.NGT.S   fs, ft              | FPU Compare Not Greater Than Float                            | %% FCR31.C = !(fs > ft)                                %% |
| C.F.D     fs, ft              | FPU Compare False Double                                      | %% FCR31.C = FALSE                                     %% |
| C.UN.D    fs, ft              | FPU Compare Unordered Double                                  | %% FCR31.C = (isNaN(fs) || isNaN(ft))                  %% |
| C.UEQ.D   fs, ft              | FPU Compare Unordered or Equal Double                         | %% FCR31.C = (isNaN(fs) || isNaN(ft) || (fs == ft))    %% |
| C.OLT.D   fs, ft              | FPU Compare Ordered Less Than Double                          | %% FCR31.C = (!isNaN(fs) && !isNaN(ft) && (fs < ft))   %% |
| C.ULT.D   fs, ft              | FPU Compare Unordered or Less Than Double                     | %% FCR31.C = (isNaN(fs) || isNaN(ft) || (fs < ft))     %% |
| C.OLE.D   fs, ft              | FPU Compare Ordered Less Than Or Equal Double                 | %% FCR31.C = (!isNaN(fs) && !isNaN(ft) && (fs <= ft))  %% |
| C.ULE.D   fs, ft              | FPU Compare Unordered\\ or Less Than or Equal Double          | %% FCR31.C = (isNaN(fs) || isNaN(ft) || (fs <= ft))    %% |
| C.SF.D    fs, ft              | FPU Compare Signaling False Double                            | %% FCR31.C = FALSE                                     %% |
| C.NGLE.D  fs, ft              | FPU Compare Not Greater\\ Or Less Than or Equal Double        | %% FCR31.C = (isNaN(fs) || isNaN(ft))                  %% |
| C.SEQ.D   fs, ft              | FPU Compare Signaling Equal Double                            | %% FCR31.C = (fs == ft)                                %% |
| C.NGL.D   fs, ft              | FPU Compare Not Greater Or Less Than Double                   | %% FCR31.C = !((fs > ft) || (fs < ft))                 %% |
| C.NGE.D   fs, ft              | FPU Compare Not Greater Than or Equal Double                  | %% FCR31.C = !(fs >= ft)                               %% |
| C.NGT.D   fs, ft              | FPU Compare Not Greater Than Double                           | %% FCR31.C = !(fs > ft)                                %% |
| BC1F        offset            | Branch On FPU False                                           | %% if(FCR31.C == 0) PC = offset %% |
| BC1FL       offset            | Branch On FPU False Likely                                    | %% if(FCR31.C == 0) PC = offset %% |
| BC1T        offset            | Branch On FPU True                                            | %% if(FCR31.C == 1) PC = offset %% |
| BC1TL       offset            | Branch On FPU True Likely                                     | %% if(FCR31.C == 1) PC = offset %% |
| MFC0        rt, rd            | Move From Coprocessor 0                                       | %% rt = rd                      %% |
| MTC0        rt, rd            | Move To Coprocessor 0                                         | %% rd = rt                      %% |
| CACHE       op, offset(base)  | Cache Operation                                               | %%                              %% |
| TEQ         rs, rt            | Trap If Equal                                                 | if(rs == rt) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| TEQI        rs, immediate     | Trap If Equal Immediate                                       | if(rs == immediate) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| TGE         rs, rt            | Trap If Greater Than Or Equal                                 | if(rs >= rt) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| TGEI        rs, immediate     | Trap If Greater Than Or Equal Immedate                        | if(rs >= immediate) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| TGEIU       rs, immediate     | Trap If Greater Than Or Equal Immediate Unsigned              | if(rs >= immediate) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| TGEU        rs, rt            | Trap If Greater Than Or Equal Unsigned                        | if(rs >= rt) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| TLT         rs, rt            | Trap If Less Than                                             | if(rs < rt) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| TLTI        rs, immediate     | Trap If Less Than Immediate                                   | if(rs < immediate) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| TLTIU       rs, immediate     | Trap If Less Than Immediate Unsigned                          | if(rs < immediate) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| TLTU        rs, rt            | Trap If Less Than Unsigned                                    | if(rs < rt) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| TNE         rs, rt            | Trap If Not Equal                                             | if(rs != rt) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| TNEI        rs, immediate     | Trap If Not Equal Immediate                                   | if(rs != immediate) {\\ COP0_CAUSE %%|=%% (13 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180\\ } |
| SYNC                          | Synchronize                                                   | (No operation on R4300)            |
| SYSCALL                       | System Call                                                   | COP0_CAUSE %%|=%% (8 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180 |
| BREAK                         | Breakpoint                                                    | COP0_CAUSE %%|=%% (9 %%<<%% 2);\\ COP0_EPC = PC;\\ PC = exc_vector_base + 0x180 |
| ERET                          | Return From Exception                                         | PC = COP0_EPC (or COP0_ERROREPC)\\ LLBit = 0 |
| TLBP                          | Probe TLB For Matching Entry                                  | %%                              %% |
| TLBR                          | Read Indexed TLB Entry                                        | %%                              %% |
| TLBWI                         | Write Indexed TLB Entry                                       | %%                              %% |
| TLBWR                         | Write Random TLB Entry                                        | %%                              %% |
----
===== General Purpose Registers =====
^ Number ^ Name ^ Preserved ^ Purpose ^
| 0	    | R0       | n/a | Hardwired zero               |
| 1	    | AT       | no	 | Assembler temporary value    |
| 2:3	| V0:V1    | no	 | Subroutine return value      |
| 4:7	| A0:A3    | no	 | Subroutine arguments         |
| 8:15	| T0:T7    | no	 | Temporary values             |
| 16:23	| S0:S7    | yes | Saved values                 |
| 24:25	| T8:T9    | no	 | Temporary values             |
| 26:27	| K0:K1    | n/a | Reserved by the kernel       |
| 28	| GP	   | yes | Global pointer               |
| 29	| SP	   | yes | Stack pointer                |
| 30	| S8 or FP | yes | Saved value or frame pointer |
| 31	| RA	   | yes | Return address               |
  * Excluding R0 and RA, the register purposes noted above are conventional; they are not enforced by the processor.
  * By convention if a subroutine uses a "preserved" register, the subroutine must restore that register to its original value before returning.
----
===== Floating-point Registers (COP1) =====
^ Number ^ Name    ^ Preserved ^ Purpose                 ^
| 0:2    | F0:F2   | no        | Subroutine return value |
| 4:10   | F4:F10  | no        | Temporary values        |
| 12:14  | F12:F14 | no        | Subroutine arguments    |
| 16:18  | F16:F18 | no        | Temporary values        |
| 20:30  | F20:F30 | yes       | Saved values            |
  * When the [[r4300#COP0 Status Register]]'s FR bit is 0, only even numbered registers should be used.
  * All register purposes noted above are conventional; they are not enforced by the processor.
  * By convention if a subroutine uses a “preserved” register, the subroutine must restore that register to its original value before returning.
----
===== Floating-point FCR31 (Control/Status) Register (COP1) =====
|     25|24|23|   18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 0|
|0000000| .| .|00000| .| .| .| .| .| .| .| .| .| .| .| .| .| .| .| .|..|
|-------|FS|C |-----|CE|CV|CZ|CO|CU|CI|EV|EZ|EO|EU|EI|FV|FZ|FO|FU|FI|RM|
|   7   |1 |1 |  5  | 1| 1| 1| 1| 1| 1| 1| 1| 1| 1| 1| 1| 1| 1| 1| 1|2 |
^ Field ^ Description ^
| FS    | Enables flashing of denormalized numbers \\ (See [[https://hack64.net/docs/VR43XX.pdf#page=213|Page 213 of the manual]]) |
| C     | Compare bit (1: TRUE, 0: FALSE)\\ Result of the last compare (C.COND.FMT) operation |
| CE    | Cause  bit: Unimplemented operation |
| CV    | Cause bit: Invalid operation |
| CZ    | Cause bit: Division by Zero |
| CO    | Cause bit: Overflow |
| CU    | Cause bit: Underflow |
| CI    | Cause bit: Inexact operation |
| EV    | Enable bit: Invalid operation |
| EZ    | Enable bit: Division by Zero |
| EO    | Enable bit: Overflow |
| EU    | Enable bit: Underflow |
| EI    | Enable bit: Inexact operation |
| FV    | Flag bit: Invalid operation |
| FZ    | Flag bit: Division by Zero |
| FO    | Flag bit: Overflow |
| FU    | Flag bit: Underflow |
| FI    | Flag bit: Inexact operation |
| RM    | [[r4300#Rounding Mode]] |
  * Cause bits indicate the last exception - more than one may be set at a time.
  * Enable bits mask exceptions when set to 0.
  * Like the Cause bits, the Flag bits indicate the last exceptions, however they can only be cleared by writing a new value to FCR31 using the CTC1 instruction.
   
==== Rounding modes ====
^ Value ^ Mnemonic ^ Description ^
|   0   |    RN    | Round to nearest representable value |
|   1   |    RZ    | Round towards zero |
|   2   |    RP    | Round towards positive infinity |
|   3   |    RM    | Round towards negative infinity |
----
===== COP0 Status Register =====
| 31| 30| 29| 28|27|26|25| 24|23| 22|21|20|19|18|17|16|       8| 7| 6| 5|  4|  2|  1| 0|
|  .|  .|  .|  .| .| .| .|  .| 0|  .| .| .| .| .| 0| 1|........| .| .| .| ..|  .|  .| .|
|CU3|CU2|CU1|CU0|RP|FR|RE|ITS| -|BEV|TS|SR| -|CH|CE|DE|   IM   |KX|SX|UX|KSU|ERL|EXL|IE|
| 1 | 1 | 1 | 1 |1 |1 |1 |1  | 1|1  |1 |1 | 1|1 |1 |1 |   8    |1 |1 |1 |2  |1  |1  |1 |
^Field ^Description^
|CU3   |(Reserved)|
|CU2   |(Reserved)|
|CU1   |Coprocessor 1 (FPU) Usability (1: Usable, 0: Unusable)|
|CU0   |Coprocessor 0 Usability (1: Usable, 0: Unusable)\\ COP0 is always usable while in kernel mode, regardless of setting|
|RP    |Reduce Power (0: Normal, 1: Low Power Mode)\\ Clock frequency is reduced to one-quarter speed when enabled|
|FR    |Additional floating point registers (0: 16 registers, 1: 32 registers)|
|RE    |Reverse Endian in User mode (0: Disabled, 1: Reversed)|
|ITS   |Enable instruction trace support (0: False, 1: True)|
|BEV   |Bootstrap exception vector (0: Normal, 1: Bootstrap)\\ Controls [[r4300#Exception Vector locations]] |
|TS    |TLB shutdown has occurred (0: False, 1: True)\\ On R4300i, the TLB does not shutdown and the processor will continue execution, but the TS bit is still set.|
|SR    |Soft reset or NMI has occurred (0: False, 1: True)|
|CH    |CP0 Condition bit (0: False, 1: True)|
|CE    |(Unused on R4300i)|
|DE    |(Unused on R4300i)|
|IM    |Interrupt Mask (0: Disabled, 1: Enabled)|
|KX    |Enable 64-bit addressing in Kernel mode (0: Disabled, 1: Enabled)|
|SX    |Enable 64-bit addressing and operations in Supervisor mode (0: Disabled, 1: Enabled)|
|UX    |Enable 64-bit addressing and operations in User mode (0: Disabled, 1: Enabled)|
|KSU   |Mode (10: User, 01: Supervisor, 00: Kernel)|
|ERL   |Error level (0: Normal, 1: Error)|
|EXL   |Exception level (0: Normal, 1: Exception)|
|%%IE%% |Global interrupt enable (0: Disabled, 1: Enabled)|
==== Exception Vector Locations ====
^Exception   ^Base (BEV=0) ^Base (BEV=1)  ^Offset^
|Reset & NMI |n/a          |0xBFC000000   |0x000 |
|TLB Miss    |0x80000000   |0xBFC000200   |0x000 |
|XTLB Miss   |0x80000000   |0xBFC000200   |0x080 |
|Other       |0x80000000   |0xBFC000200   |0x180 |
----
===== COP0 Cause Register =====
|31|30|28|          16|       8|7|    2| 0|
| .| 0|..|............|........|0|.....|00|
|BD| -|CE|------------|   IP   |-| EXC |--|
|1 |1 |2 |     12     |   8    |1|  5  |2 |
^Field ^Description^
|BD    |Branch delay (1: Last exception occurred in delay slot, 0: Normal)|
|CE    |Coprocessor number for coprocessor unusable exception|
|IP    |[[r4300#Interrupts|Interrupt]] pending (1: Interrupt, 0: No Interrupt)\\ IP7   Timer interrupt\\ IP6:2 External normal interrupts\\ IP1:0 Software interrupt|
|EXC   |Exception code|
==== Exception Codes ====
^Code  ^Mnemonic ^Description^Generated...^
|0     |Int      |[[r4300#Interrupts|Interrupt]]|- When one of the eight interrupt conditions are asserted|
|1     |Mod      |TLB Modification exception|- When the TLB entry that matches the the virtual address referenced by the store instruction is marked as read-only (the D bit = 0)|
|2     |TLBL     |TLB Invalid exception (load or instruction fetch)|- When an attempt is made to read from an mapped area in a TLB segment that is marked invalid|
|3     |TLBS     |TLB Invalid exception (store)|- When an attempt is made to write to a mapped area in a TLB segment that is marked invalid|
|2     |TLBL     |TLB Miss exception (load or instruction fetch)|- When an attempt is made to read from an unmapped area in a TLB segment (Uses special TLB miss exception vector)|
|3     |TLBS     |TLB Miss exception (store)|- When an attempt is made to write to an unmapped area in a TLB segment (Uses special TLB miss exception vector)|
|4     |AdEL     |Address Error exception (load or instruction fetch)|- When an attempt is made to read from an address whose boundary alignment is incompatible with the instruction\\ - When an attempt is made to read from an address that is not accessible in the current operating mode|
|5     |AdES     |Address Error exception (store)|- When an attempt is made to write to an address whose boundary alignment is incompatible with the opcode\\ - When an attempt is made to write to an address that is not accessible in the current operating mode|
|6     |IBE      |Bus Error exception (instruction fetch)||
|7     |DBE      |Bus Error exception (data reference: load or store)||
|8     |Sys      |Syscall exception|- When a SYSCALL instruction is executed|
|9     |Bp       |Breakpoint exception|- When a BREAK instruction is executed|
|10    |RI       |Reserved instruction exception|- When an attempt is made to execute a reserved/nonexistant command|
|11    |CpU      |Coprocessor unusable exception|- When an attempt is made to use a coprocessor instruction and the corresponding coprocessor is marked unusable (Status CU bit = 0)\\ - When an attempt is made to use a COP0 instruction while operating in user or supervisor mode|
|12    |Ov       |Arithmetic overflow exception|- When an ADD, ADDI, SUB, DADD, DADDI or DSUB instruction results in a 2's complement overflow|
|13    |Tr       |Trap exception|- When a trap instruction results in a TRUE condition|
|14    |-        |(Reserved)||
|15    |FPE      |Floating-point exception|(Generated by the floating-point coprocessor (COP1); contents of the Floating-Point Control/Status register (FCSR31) indicate the cause of the exception)|
|16:22 |-        |(Reserved)||
|23    |WATCH    |Watch exception|- When a load/store instruction references the address specified in the WatchLo/WatchHi registers|
|24:31 |-        |(Reserved)||
==== Interrupts ====
^Cause bit^Source         ^
|IP0      |Set by software|
|IP1      |Set by software|
|IP2      |Int0 pin (N64: RCP)|
|IP3      |Int1 pin (N64: Cartridge)|
|IP4      |Int2 pin (N64: Pre-NMI (Reset button))|
|IP5      |Int3 pin (N64: RDB Read)|
|IP6      |Int4 pin (N64: RDB Write)|
|IP7      |Timer interrupt|
  * Software interrupts (IP1:IP0) are generated when software manually sets the Cause register's IP1 or IP0 bit to 1 using an MTC0 instruction.
  * The Timer interrupt (IP7) is generated when the Count and Compare registers are equal. 
  * Interrupts may be masked by setting the respective IM bits of the Status register to 0.
On the Nintendo 64, IP2 represents an RCP (Reality Coprocessor) interrupt. When an RCP interrupt occurs, a flag representing the specific RCP interface may be read from MI_INTR_REG (0x04300008).
^Bit^Name^Description^
|0x01|MI_INTR_SP|Signal Processor - Task Done/Task Yield|
|0x02|MI_INTR_SI|Serial Interface - Controller input available|
|0x04|MI_INTR_AI|Audio Interface - Audio buffer swap|
|0x08|MI_INTR_VI|Video Interface - Vertical retrace|
|0x10|MI_INTR_PI|Peripheral Interface - ROM to RAM DMA done|
|0x20|MI_INTR_DP|Display Processor - RDP processing done (gDPFullSync)|
RCP-specific interrupts may be enabled or disabled by writing one or more of the following values to MI_INTR_MASK_REG (0x0430000C).
^Bit^Name^Description^
|0x0001|MI_INTR_MASK_CLR_SP|Disable SP interrupts|
|0x0002|MI_INTR_MASK_SET_SP|Enable SP interrupts|
|0x0004|MI_INTR_MASK_CLR_SI|Disable SI interrupts|
|0x0008|MI_INTR_MASK_SET_SI|Enable SI interrupts|
|0x0010|MI_INTR_MASK_CLR_AI|Disable AI interrupts|
|0x0020|MI_INTR_MASK_SET_AI|Enable AI interrupts|
|0x0040|MI_INTR_MASK_CLR_VI|Disable VI interrupts|
|0x0080|MI_INTR_MASK_SET_VI|Enable VI interrupts|
|0x0100|MI_INTR_MASK_CLR_PI|Disable PI interrupts|
|0x0200|MI_INTR_MASK_SET_PI|Enable PI interrupts|
|0x0400|MI_INTR_MASK_CLR_DP|Disable DP interrupts|
|0x0800|MI_INTR_MASK_SET_DP|Enable DP interrupts|
----
===== Memory Segments (32-bit) =====
^ Virtual address range       ^ Segment ^ Description ^
| 00000000:7FFFFFFF | useg  | TLB mapped to physical memory\\ Accessible in all operating modes^
| 80000000:9FFFFFFF | kseg0 | Cached, translated to physical address by subtracting 80000000\\ Accessible in kernel mode^
| A0000000:BFFFFFFF | kseg1 | Uncached, translated to physical address by subtracting A0000000\\ Accessible in kernel mode^
| C0000000:DFFFFFFF | sseg  | TLB mapped to physical memory\\ Accessible in kernel and supervisor mode^
| E0000000:FFFFFFFF | kseg3 | TLB mapped to physical memory\\ Accessible in kernel mode^
Note: Commercial Nintendo 64 games operate in kernel mode at all times.
===== References =====
  * http://hack64.net/docs/VR43XX.pdf
  * http://datasheets.chipdb.org/MIPS/R4300i_datasheet.pdf
  * https://level42.ca/projects/ultra64/Documentation/man/pro-man/pro07/index7.7.html
  * https://level42.ca/projects/ultra64/Documentation/man/pro-man/pro07/index7.8.html
  * https://level42.ca/projects/ultra64/Documentation/man/n64man/u64/u64.html
  * https://level42.ca/projects/ultra64/Documentation/man/header/rcp.htm
  * https://github.com/n64dev/cen64/blob/72c778c3bfb25262498af6a21e8dec828a28be19/vr4300/interface.h#L16
  * http://ti.ira.uka.de/TI-2/Mips/Befehlssatz.pdf