MIPSym User's Guide




Using the MIPSym Simulator




Files

MIPSym is designed to open text files with a .asm or .s extension.

MIPSym can also open MIPSym-assembler generated object files with a .obj extension, using the 'File > Load .obj' command. This is a MIPSym-specific text file format, designed to be human-readable in a text editor; no hex editors required.

Please note that the 'Load .obj' command assumes that you have a .asm file with the same filename in the same directory; it will load this file in the code editor.

As soon as you begin making changes to a source file that you have saved, MIPSym begins making timed backup saves of your code. You can set the amount of time between automatic backups, in seconds, with 'Settings > Set Automatic Backup Interval'. By default, the interval is 5 minutes, but you can set it as low as 1 second. You can turn the feature off by setting it to 0 seconds. Auto-saves are typically saved as the original filename with a tilde and a unique number after it. These files are usually cleaned up when MIPSym exits normally.

MIPSym does not crash often, but if it does, it will make an attempt to open the last file it auto-saved the next time you run it.




Find and Replace

You can access Find and Replace feature with Ctrl-F. This feature is meant to work much the same as it does in other text editors.

Regular expression matching: MIPSym allows you to find and replace using Qt's regular expression engine, QRegExp. You can find documentation on QRegExp at doc.qt.io.

Regular expression capture groups: Regular expression engines allow you to reference capture groups in your replacement strings, often using $1, $2, $3 and so on. Using QRegExp's string replacement tools, you will need to use \1, \2, \3 and so on.

For example, if you had text that looked like this:

    Apples: add     $t0,$t1,$t2

... and you had a search string that looked like this:

    (\w+):\s+add\s+(\$\w+),(\$\w+),(\$\w+)

... and you had a replacement string that looked like this:

    # At label \1, we add \4 to \3 and store the result in \2.

... you could find that string, hit 'Replace', and end up with this string:

    # At label Apples, we add $t2 to $t1 and store the result in $t0.



Code editor shortcut keys

Menu tabs can be accessed through Alt. Each tab's corresponding key will be underlined on pressing Alt, at which point pressing its key will send you to the menu tab dropdown. Most of the shortcut keys you might need are written in the menus, right next to the actions they trigger. For instance, under the 'File' menu, the 'Save' action has the text Ctrl-S next to it, or -S on Mac.

There are a few keyboard shortcuts that are not on the menu; these are listed here:

Shortcut Keys Mac Equivalent Action
Ctrl-/ -/ Toggle-comment the line that the cursor is on.
If multiple lines are selected, every line selected will toggle-comment.
Tab Tab If any text is selected, the entire line (or block of lines) is indented with Tab characters.
Shift-Tab Shift-Tab If any text is selected, the entire line (or block of lines) is unindented.
Ctrl-MouseWheel+/- -MouseWheel+/- Increase/decrease the size of the text in the IDE or the console.



Panels

The main window of the MIPSym IDE is divided into four panels:

  • The Code Panel
  • The Register Panel
  • The Message Log Panel
  • The Memory Panel

By default, only the Code panel is visible when you start up MIPSym. You can change this behavior under 'Settings > On Startup Show'.

By default, the Message Log panel will show itself whenever it receives a new message. You can prevent this behavior with 'Settings > Auto Show Messages on Arrival'. The Message Log is used to provide feedback any time MIPSym has something useful to tell you, but doesn't want to use an obtrusive dialog box to do so. It is usually best to leave this setting turned on, unless you are really worried about screen space. If you turn it off, the Message Log will still record messages, and you can access them at any time.

The Register and Memory panels can be accessed at any time, either by using the 'View' menu, or by pulling on the vertical panel sliders at the right edge of the window. The panel sliders look like thick black lines, and your mouse cursor will change shape as you hover over them. If the Message Log is hidden, you can also access the Message Log using the horizontal panel slider at the bottom of the window.




Building Code

To build a program, click 'Run > Build F8'. The assembler should run on the code in the leftmost source tab, and the assembly results should show up in the Listing tab of the code panel.

Your copy of MIPSym may contain alternate assemblers in a directory marked asm; if you wish to use one of them instead of the default assembler, you can do so with 'Settings > Set Assembler Path'.

Every time the assembler runs, the Message Log will display a note that contains the path to the assembler used and the version number. If the assembler crashes, the Message Log will contain a note with the assembler's return value, and possibly an explanation of what happened. If you are able to get the assembler to crash, please alert the developers!




Running Code

You can step through your program one instruction at a time using the 'Run > Step F10' or 'Run > Step Over F11' commands. 'Run > Step Over F11' functions like 'Run > Step F10', except that subroutines called with jal and its variants will be executed at full speed.

You can run the program with 'Run > RunF9'; this will run your program until you hit a breakpoint, if any are set, or the program ends, or an exception occurs. This command will also save and build your program if you have unsaved changes. 'Run > Run Until Return Shift+F8' functions similarly to 'Run > RunF9', but will additionally pause execution after the current subroutine exits.

You can pause the program at any time with 'Run > Step F10'. This will be useful if your program uses spin locks or long/infinite loops; your PC will otherwise waste lots of CPU cycles and power to emulate these.

Clicking on a line number in the Listing file will send you to the corresponding line in your source code. You may find this useful if your program uses many macros, or includes other source files.

If you run a program, and it finishes, either via exception, syscall $exit, or by running off the end of the .code section, the simulator's PC and registers will all be in the same state so that you can examine them. If you want to re-run your program, use 'Run > Reset Shift-F8' first, otherwise your program may begin in the wrong state.




Breakpoints

To set breakpoints, go to the listing tab, highlight a memory address in a .code section, and click 'Breakpoint > Add Ctrl-B'. This will pause your program at that address the next time you run it.

You can also add and remove breakpoints without highlighting memory addresses; you will see a dialog box that allows you to set the addresses manually.

Be aware that breakpoints are cleared upon build or reset and will need to be set again.




Privacy

By default, MIPSym looks for updates at MIPSym.com every time it starts up. The Windows installation is capable of updating itself when MIPSym starts up, if you consent to the download (typically 11 MB). The Linux version should be capable of this soon as well.

However, the MIPSym team values your privacy and desire not to be tracked. You can turn off this feature in one of two ways:

  1. The 'Settings > Check for new version on launch' menu item. This item is checked by default, but you can un-check it the first time it runs, and MIPSym will stop contacting MIPSym.com in the future. This means that the first time MIPSym runs, it will contact MIPSym.com. If your preferences file is corrupted or deleted for some reason, it will also contact MIPSym.com until you uncheck this box.
  2. The -p or --private command line option. If you launch MIPSym from the command line, or use a shortcut, you can add this option to your launch command, and MIPSym will never access MIPSym.com for any reason.



Using the MIPSymCLI Simulator




Windows

After installation, there will be two shortcuts in your Start Menu, under a folder labelled MIPSym2. The MIPSym shortcut will run the GUI version of MIPSym; the MIPSymCLI shortcut will launch a Windows terminal with an environment set up to make it easier to run MIPSym from the command line.

This Windows terminal will start you out in your "home" directory. This is meant to encourage you not to try to modify files in the C:\Program Files (x86) directory. If you prefer to start in some other directory, please modify C:\Program Files (x86)\MIPSym2\MipsymCliEnv.bat accordingly.

If MIPSym is installed in the default location, there will be some example MIPS assembly files at C:\Program Files (x86)\MIPSym2\example_code. You may wish to copy these files to your home directory, using the xcopy command:

xcopy "C:\Program Files (x86)\MIPSym2\example_code" MIPS_workspace\

The xcopy command will copy the whole directory into your home directory, in a new directory called MIPS_workspace.

You can move into the MIPS_workspace directory with the cd command:

cd MIPS_workspace

Use the dir command to print a list of all the files in the current directory.

Assembling Programs

Within this terminal, you can assemble a MIPS program in the current directory called hello_world.asm by entering:

%ASM% hello_world.asm

If the assembler runs properly, it should produce an object file, in the same directory as the assembly file, with the .obj extension in place of the .asm extension.

You can check the assembler's return code with this command:

echo %errorlevel%

The assembler referenced by %ASM% returns 0 when assembly succeeded and 1 when assembly failed. Any other return code means the assembler crashed.

If you are able to get the assembler to crash, please alert the developers!

The assembler should have produced a few files when it assembled hello_world.asm:

  1. A log file, hello_world.log. This file stores some basic data about what assembler was used to assemble the program and what arguments were passed to the assembler. After you run the program in MIPSymCLI, some runtime statistics will be appended to this file.
  2. An object file, hello_world.obj. This file represents the machine code that corresponds to the program you assembled. It isn't an actual machine code binary; it is instead stored as ASCII text so that you can read it easily.
  3. A listing file, hello_world.lst. This file shows a direct mapping between the lines of assembly code in the hello_world.asm and the machine code written to hello_world.obj. It is meant to help you figure out what the assembler produced, and why.

You can print any of these files to the terminal, using the type command:

type hello_world.lst

If you prefer, you can also open the files in Notepad.exe:

notepad hello_world.lst

There are two assemblers available in C:\Program Files (x86)\MIPSym2\asm. One is available via the %ASM% environment variable; this is the recommended assembler.

You may decide that you prefer to use the older version of the assembler, C:\Program Files (x86)\MIPSym2\asm\assembler_builder.exe. If you want to use this one, please note that you will need to use the -W flag, and that every assembly source file must be preceded by a \, otherwise the assembler will crash. For example, if you want to assemble hello_world.asm in the working directory, you would need to use this command:

"C:\Program Files (x86)\MIPSym2\asm\assembler_builder.exe" -W .\hello_world.asm

Also, you should know that assembler_builder.exe produces a hello_world.sig file that contains no more than a few bytes. This file is used as a secondary form of communication with the GUI version of MIPSym, and it won't be very interesting to you. It is safe to delete this file. The newer assembler.exe produces .sig files as well, but the %ASM% variable includes a command line flag to suppress these files so that you will not see them.

Running Programs

Within this terminal, you can run a MIPS program in the current directory called hello_world.obj by typing:

MIPSymCLI hello_world.obj

A complete list of the command line flags that MIPSymCLI supports is available by typing:

MIPSymCLI -h

If you need to quit running a program, but you don't want exit the terminal, just press Ctrl-C to return to the command prompt.




Linux

The "MIPSym_x.xx.xxxx.tar.gz" archive includes the file "MIPSymCLI-x86_64.AppImage". This is an AppImage that you may relocate to any directory you wish. You will also find an assembler called "MIPSymAssembler" in the "asm" directory; please keep it in the same directory as "Mips1.adf". You may find it simplest to do something like this:

$ tar -xvzf MIPSym_x.xx.xxxx.tar.gz -C ~

This will extract the archive into your home directory, in a new directory called MIPSym_x.xx.xxxx.

If you expect to use MIPSymCLI for any length of time, you will probably want to add some aliases to your dotfiles to make MIPSymCLI easier to use. The developers recommend that you add these lines to your ~/.bashrc file (or ~/.zshrc, or ~/.config/fish file, depending on your preferred shell):

alias assembler='/home/$USER/MIPSym_x.xx.xxxx/asm/MIPSymAssembler -s'
alias MIPSymCLI='/home/$USER/MIPSym_x.xx.xxxx/MIPSymCLI-x86_64.AppImage'

The next time you open a terminal, you will be able to type assembler to run MIPSymAssembler with the -s flag, or MIPSymCLI to run the command-line version of MIPSym. For instance, if you had the file hello_world.asm in the working directory, you could run it like this:

$ assembler hello_world.asm && MIPSymCLI hello_world.obj

If there are any errors in hello_world.asm, assembler emits a nonzero return code that prevents MIPSymCLI from running.

To make this process automatic, you may wish to interact with MIPSymCLI using a file watcher like inotify-wait. This tool can be used to cause the assembler and MIPSymCLI emulator to run again any time you save changes to the hello_world.asm source.




Mac

The MIPSym.app file in your /Applications directory is actually a directory that includes many files, including an assembler and the MIPSymCLI application. You can access these programs from your terminal by adding the following lines to your ~/.bashrc file (or ~/.zshrc, or ~/.config/fish file, depending on your preferred shell):

alias assembler='/Applications/MIPSym.app/Contents/MacOS/asm/assembler -s'
alias MIPSymCLI='/Applications/MIPSym.app/Contents/MacOS/MIPSymCLI'

When you launch a new terminal session, you will be able to use the commands assembler and MIPSymCLI from any location, as long as MIPSym.app is in your /Applications directory. For instance, if you had the file hello_world.asm in the working directory, you could run it like this:

$ assembler hello_world.asm && MIPSymCLI hello_world.obj

If there are any errors in hello_world.asm, assembler emits a nonzero return code that prevents MIPSymCLI from running.




Debugging Programs in MIPSymCLI

You can put MIPSymCLI in interactive debug mode with this command:

MIPSymCLI -i hello_world.obj

In debug mode, you can type ? at any point to get a list of commands you can use, or x to exit the current mode.

When you enter debug mode, you will see a cryptic series of numbers and letters across the top of the screen. For example, you might see this:

Mem Addr  Contents Inst    Hex Args  Last Reg Diff
00400000  340a0021 ori   0a,00,0021  $ra = 004000f0 >>

The top line is meant to help you to understand the line below it. There are five columns of data here, followed by a >> symbol. The >> symbol is a prompt, meaning that MIPSymCLI expects you to type something.

The five columns of data are:

  1. The memory address that the Program Counter is currently pointed to. The .code section of MIPS programs usually begins at 0x400000, and that's where most MIPS programs start. If you wrote a MIPS program with a main label at some other location, and used the .globl main instruction to export that symbol, you would see some other memory address in this column. Note that all the numbers in this display are printed in hexadecimal; they are more compact and easier to read this way.
  2. The 32-bit integer stored at this memory address. Since we are in the .code section, this integer is most likely machine code for a MIPS instruction. The MIPSym simulator will interpret this number as if it were a MIPS instruction. Hopefully, the author of this program kept all the program's data in the .data section, and out of the .code section, so the MIPSym simulator doesn't try to interpret data as MIPS instructions!
  3. The assembly instruction that MIPSym will try to run when it sees the 32-bit integer at this address.
  4. The arguments to the MIPS instruction at this address, written in hexadecimal.
  5. The integer register that changed during the previous instruction. If no register has changed, this column will point to $ra by default. This column also shows you the value held in that register.

You can step through the program one instruction at a time by pressing the i or F10 key.

At any point, you can set or clear breakpoints, view the contents of the registers, or view and edit the contents of memory. Press ? to see a complete list of commands.

The Memory Viewer/Editor

From debug mode, you can enter the memory editor by pressing m. In this mode, the prompt turns into a >>> to denote that you are in the memory editor, and not in debug mode. From this point, you can press x to get back to debug mode.

In the memory editor, you can press d to display and edit memory. Once you have pressed d, you will see something like this:

0x10010000: 20202020 >

The first number is the hex address of the current location in memory, 0x10010000, which happens to be the beginning of the .data section. The second number is the value at that address: a series of 0x20's. In this program, the beginning of the data section is filled by a string of ASCII space characters. The last thing on this line is the data-entry prompt, a > symbol.

If you were to enter a 32-bit number here, the first four bytes at address 0x10010000 would be replaced by the number you entered.

If you were to press the up or down arrow keys, the memory address would increment/decrement by 4, and the value at the new address would be displayed in place of the previous value.

If you entered nothing at all, and just pressed the Enter key, the next memory address and memory value would appear on the next line. This is a good way to view a large block of memory at once: just press Enter over and over again, and the whole block will print out four bytes at a time.

Press x to leave data-entry mode and go back to the memory editor. Note that the prompt changes back to a >>>.

There are three things you can change in the memory editor:

  1. The current memory address (press a to modify). It could take a long time to press the arrow keys to reach the address you want to display or modify; this will get you there directly.
  2. Size mode (press s to modify). If you are modifying integers, you can choose between modifying 1 byte, 2 bytes, 4 bytes, or 8 bytes at a time.
  3. Entry mode (press e to modify). This allows you to change the way that data is displayed and entered in data-entry mode. You can use this to display blocks of memory as floating-point data, string data, integers, or as disassembled MIPS machine code.

You can press ? at any time in the memory editor to see what address, size mode, and entry mode are currently selected.




Differences between MIPSym's assembler and other MIPS assemblers (SPIM, GCC etc)




Local labels

MIPSym supports the use of "Local Labels." These were likely supported by the original MIPS assembler as seen in Appendix C page 9 of "MIPS RISC Architecture" (Kane and Heinrich, 1991) but are not supported by all assemblers.

Labels numbered 0 through 99 are reserved for use as local labels; these labels can be reused to eliminate the need for unique, descriptive labels in larger programs. Labels numbered 00 through 09 are used for assembler macros, and must be avoided outside of custom macro definitions.

When referring to local labels in expressions and instructions, the label number must be appended with a 'b' or 'f' to indicate whether it points backward or forward to the nearest instance of the label from the current line.

# Example of local labels in code:
    li      $t0,5
1:  addi    $t0,$t0,-1
    bgtz    $t0,1b          # backward label reference

# Example of local labels in an assembled macro:
    abs     $a0,$t1         # macro
    addu    $a0,$0,$t1
    bgez    $t1,09f         # forward label reference
    sub     $a0,$0,$t1
09:                         # end macro

# Example of 4x4 matrix multiplication, using 3 nested loops
MM: addi    $t0,$0,4
1:  addi    $t1,$0,4
2:  add     $t3,$0,$0       #sum=0
    addi    $t2,$0,4
3:  sll     $t5,$t0,4       #L[i][k]
    sll     $t6,$t2,2
    add     $t5,$t5,$t6
    add     $t5,$t5,$a1
    lw      $t9,($t5)
    sll     $t5,$t2,4       #R[k][j]
    sll     $t6,$t1,2
    add     $t5,$t5,$t6
    add     $t5,$t5,$a2
    lw      $t8,($t5)
    mul     $t7,$t8,$t9     # *
    add     $t3,$t3,$t7     #sum +=
    addi    $t2,$t2,-1
    bgtz    $t2,3b
    sll     $t5,$t0,4       #P[i][j]
    sll     $t6,$t1,2
    add     $t5,$t5,$t6
    add     $t5,$t5,$a0
    sw      $t3,($t5)       # = sum
    addi    $t1,$t1,-1
    bgtz    $t1,2b
    addi    $t0,$t0,-1
    bgtz    $t0,1b
    jr      $ra

It is good practice to keep labels in numerical order within functions. Local labels should not be referenced outside of the context they appear in.




Delay slot

The MIPS R2000 processor executes every instruction placed directly after a branch instruction before it executes the branch. This is called the delay slot. By default, the MIPSym simulator disables this behavior. The delay slot behavior may be restored by using the .delay assembler directive at the top of any program. Programs written for SPIM must be modified by adding this assembler directive before all other lines:

    .delay

The following blocks of code illustrate how the delay slot can alter the behavior of your programs.

# Default behavior: the '.delay' assembler directive is absent
    li      $a0,5           # put a 5 in $a0
    jal     some_function   # jump to some_function, with argument $a0 == 5
    addi    $a0,$a0,8       # when some_function returns, set $a0 = 5 + 8


# Delay slot mode: the '.delay' assembler directive appeared at the top of the program
    li      $a0,5           # put a 5 in $a0
    jal     some_function   # jump to some_function, with argument $a0 == 13
    addi    $a0,$a0,8       # delay slot: this instruction runs before some_function

Please do not attempt to use a macro in the delay slot: the first line of the macro will be executed before a branch, but subsequent instructions will not!




Fields

The MIPSym assembler reads each line of assembly code as a series of three fields, separated by whitespace:

  1. the label field
  2. the opcode/pseudo-op field
  3. the arguments field

This has two very important consequences that are common pain points for new users of MIPSym:

  1. Lines of code without a label must be indented

    # Valid code:
        add     $t0,$t0,$t0
    # Not valid:
    add     $t0,$t0,$t0
    
  2. Whitespace is not allowed between arguments or within mathematical expressions.

    # Not valid:
        add     $t0, $t0, $t0
    # Valid code:
        addi    $t0,$t0,1+2+3      # adds 6 to $t0
    # Valid, but not what you meant (Will throw a warning):
        addi    $t0,$t0,1 + 2 + 3  # adds 1 to $t0, not 6
    



Expressions

Mathematical expressions are evaluated from left to right, with no regard to operator precedence. Parentheses are not allowed.

# Valid code:
    addi  $t0,$0,1+2*3     # stores (1+2)*3, or 9, in $t0
# Not valid:
    addi  $t0,$0,1+(2*3)   # does not assemble

If you need an expression that would normally use parentheses, use aliasing for the nested expressions.

# Valid code:
i = 2*3
    addi $t0,$0,1+i        # evaluated as 1+(2*3)

Note that the MIPSym assembler evaluates each value in an expression as an integer, not as floating point data.

# Not valid code:
    addi  $t0,$0,3.9+3.9   # does not assemble



Aliasing and Constant Values

Like SPIM, you can use the assignment operator to assign a constant value to an identifier. This feature is meant to allow you to write readable code that isn't full of magic numbers. For example:

# Valid code:
num_days_in_year = 365
num_days_in_leap_year = num_days_in_year+1
    li    $t0,num_days_in_leap_year    # store 366 in register $t0

Don't forget to use whitespace before and after the = operator:

x=7     # fail; the `=` is interpreted as part of a label
x =7    # fail; the `=7` is interpreted as an undefined opcode
x= 7    # fail; the `x=` is interpreted as part of a label
x = 7   # OK: `7` is now assigned to `x`

This feature is often used with labels as well:

# Valid code:
my_string:  .asciiz   "I am the best programmer in my seat!"
end_my_string:

# assigns the length of the string, plus 1 for the null terminal
my_string_length = end_my_string-my_string

You may also assign registers to identifiers:

first_year_of_MIPS = 1986
year = $t0
    li    year,first_year_of_MIPS    # load 1986 into $t0

Assignment of a register to an identifier must be done before the identifier can be used as a register; otherwise, the assembler will treat it as an immediate.

The value attached to the identifier is assigned during assembly, and cannot be reassigned during runtime. However, it can be reassigned multiple times in the program source. The assembler will reference the most recent value assigned to the identifier.

The MIPSym assembler stores these values as integers. If you attempt to assign a floating point value to an identifier, it will fail.




Repeating Data

The MIPSym assembler provides a means of repeating sections of data, using the ':' operator.

Suppose you wanted to write a null-terminated string, consisting of 5 copies of the letter 'A'. You could (and probably should) use the .asciiz assembler directive, but let's see what happens when we use the .byte assembler directive.

five_As:    .byte   'A:5      # write 5 'A's
            .byte   0         # null-terminal

The result is a printable string that looks like: "AAAAA\0"

Please note that the MIPSym assembler will repeat all of the data on the line, not just the value that precedes the ':' operator. If you didn't know that, you might be tempted to tack the 0 onto the end of the first line, like this:

five_A0:    .byte   'A:5,0

This will not yield the same string; instead, it will result in 5 alternating A's and 0's, like this: "A\0A\0A\0A\0"




Character literals

The MIPSym assembler does not currently support Unicode. It interprets all ASCII characters as being on IBM code page 437. Some ASCII characters have been overwritten in favor of more useful or convenient characters: these are the hollow diamond and heart characters and the angle character, replacing the solid diamond and heart and Peseta characters respectively. The GUI will automatically convert between Unicode and ASCII on input/output, so characters can be copy/pasted from Unicode sources without causing issues. Not all control characters are supported in source code: 0x1a in particular will prevent your program from being read properly by the assembler. The use of ASCII over Unicode was done to make it easy for students to develop text-mode games, using the box-drawing characters in the range 0xb0 to 0xdf. All characters on this code page have a uniform width and height, which makes ASCII art simple to draw. This property is not true of some unicode characters, no matter what font you're using. Each character is exactly 8 bits, or 1 byte, which makes it easy to reason about the positioning of each character in a buffer, as opposed to the variable-length characters in utf-8.

You may represent character literals in code, preceded by a single quote:

    li      $a0,'A      # load 65, the ASCII value for 'A', in register $a0
    li      $a0,'\n     # load 10, the ASCII value for newline, in $a0
    li      $a0,'\'     # load 39, the value for single quote, in $a0
    li      $a0,'\\     # load 92, the value for backslash, in $a0

You may find it useful to run the program 'page2ASCII.asm', included in the 'examples' directory. This program prints every character that MIPSym is capable of printing, alongside the corresponding ASCII values.

The following escape codes are supported by the assembler:

Escape code ASCII value Name
\a 7 Bell
\b 8 Backspace
\t 9 Horizontal Tab
\n 10 Newline
\v 11 Vertical tab
\f 12 Form feed
\r 13 Carriage return
\xFF 255 Hex number: any number between 0 and 255
\255 255 Decimal number: any number between 0 and 255
\o377 255 Octal number: any number between 0 and 255
\B11111111 255 Binary number: any number between 0 and 255

If you need to print '⌂' in a string or character literal, you can use the escaped hex value:

    .data
    .ascii  "\x7F"
    .byte   '\x7F
    .code
    li      $a0,'\x7F

Please note that you cannot include raw control characters (ASCII values 7-14 and 26) in string literals or character literals. The assembler will convert these characters to blank space characters, aka ASCII 0x20. Indiscriminate use of these characters can have unpredictable effects, depending on which platform you are using. For example, on Windows, the character 0x1a, aka the 'substitute' character, causes a file IO error when a file is read in text mode. This is not a bug; it is a misuse of the text file format.

If you plan on using text editors other than MIPSym to edit assembly files, please only use characters within the range [32-126] inclusive. Most modern editors expect that text files are encoded in some form of Unicode, and characters outside this range will either cause IO errors or be interpreted as malformed UTF-8 text.

It is possible to use UTF-8 characters in MIPSym's CLI in ANSI Mode only. you are encouraged to use escape sequences to form UTF-8 characters. For example, to write the UTF-8 form of the character '⌂', you would need to write this sequence of bytes: 0xE2 0x8C 0x82 To write this as an ASCII string, you could use:

house:  .asciiz   "\xE2\x8C\x82"

or:

house:  .byte     '\xE2,'\x8C,'\x82,0

You can print this string as a UTF-8 character if you are using MIPSymCLI in ANSI Mode. To do this, pass the -a flag to MIPSymCLI at the command line:

$ MIPSymCLI -a your_utf8_program.obj



Keywords/Reserved Words

Unlike SPIM and GCC assembler, MIPSym does not consider assembler directives, opcodes, or registers to be reserved words. This means that you may use labels with the same names as opcodes and assembler directives. The assembler can decide whether an identifier should be interpreted as a label or an opcode/assembler directive based on which field it is in.

# Valid code (antipattern):

# define a label (addi), and store part of the address of that label in $t0
addi:   addi    $t0,$0,addi

# define a label (.data), and store the address of that label in $s0
.data:  li      $s0,.data

# define a label (.byte), and write 3 copies of the low 8 bits of that label
.byte:  .byte   .byte,.byte,.byte

WARNING: Do not write code like this without a very good reason for doing so! Redefining opcodes and assembler directives can be fun, but it makes your code very hard to read!

If you want to copy this code into MIPSym, make sure it isn't indented before you try to build it. Notice that the code highlighter can't figure out that addi, .data, and .byte are being used as labels and not opcodes or assembler directives. The highlighter is meant to run fast and to help make your code more readable, not to parse nonsense like this.




User-Defined Macros

The MIPSym assembler supports user-defined macros through the use of the .macro and .end_macro directives. The .macro directive accepts a macro name and a list of comma or parentheses-separated parameters, separated from the macro name by whitespace. Custom macro definitions may allow for up to three parameters. Macros should be defined before their first usage in the source file, or else the assembler will not recognize them.

# To define a macro:
    .macro    name  params
    # macro body
    .end_macro

# Example of a user-defined macro:
    .macro    swap  rs,rt      # swaps the contents of integer registers rs and rt
    mov       $at,rs
    mov       rs,rt
    mov       rt,$at
    .end_macro

The first character of each parameter in a macro must match the first character of the intended datatype of its argument. A list of datatypes supported by the MIPSym assembler can be found in Opcodes and Macros. Macros are limited to 100 lines maximum; an error will occur if they are any longer.

Users are free to use the assembler temporary register $at in their macros, as well as assembler-reserved local labels. However, it should be noted that in this case, embedding other macros within user-defined macros may lead to side effects. Users should read the assembler definition file in order to understand potential risks.




Include Directive

The MIPSym assembler supports a .include directive, which allows for multiple source files to be combined into one. This replaces the need for a linking loader or makefile. Namespaces are not supported, so care should be taken to ensure duplicate labels are not created across source files; it's recommended to use local labels generously. This also means that files which do not assemble independently due to missing labels can be assembled when these labels are provided by another source file.

Both relative and absolute file paths are supported, so include directives can be written as such:

# To include files in the same directory as the main source:
    .include  "source-one.asm"
    .include  "./source-two.asm"

# To include files which are in different directories:
    .include  "../filepath/source-one.asm"
    .include  "subdirectory/source-two.asm"
    .include  "C:/Users/Name/Asm-Files/source-three.asm"

The assembler searches for files at their location relative to the including source file, but the assembled .obj file will reference files relative to the main source. This allows users to move their source files, as long as included files are in the same relative locations as they were at assembly time.

It is best form to include a section directive at the beginning of any included file; otherwise the .include directive will assume the same section as the including file. For this reason, do not use section directives before .include; it will lead to either redundant or unreliable code. There is no need to put section directives at the end of included files either; the assembler will automatically return to the including file's section afterwards.




Syscalls, Register Names, Assembler Directives, and Macros

MIPSym aims to provide good compatibility with SPIM, but some differences exist. MIPSym adds several syscalls that do not exist in SPIM, a few nonstandard floating-point instructions, and many convenient macros that do not exist in SPIM or GCC. Specific differences are discussed in the appropriate section of the Quick Reference Guide.




Quick Reference Guide

This section presents a listing of all assembler directives, syscalls, registers, opcodes, and macros. Please note that all the information presented here is available within MIPSym's code editor, in the form of tooltips. Within the editor, just hover your mouse over a term that you are interested in, and the documentation for that term will pop up.




Assembler Directives

MIPSym handles a superset of the assembler directives that SPIM and the GCC assembler support. A full listing of these is provided here.

Pseudo Name Arguments Comment
.align n Increment the location counter to make the n low order bits of the counter 0.
If n is zero, turns off auto alignment.
.ascii string delimited by double quotes Writes a string without marking an endpoint
.asciiz string delimited by double quotes Writes a null-terminated string
.byte comma-separated ints or expressions Writes data in 8-bit chunks
.code optional address Enters the section of the program that contains code.
Alias for '.text'
.data optional address Enters the section of the program that contains data
.delay no args Turns on branch-delay mode: the simulator will execute the first instruction following a branch instruction before taking the branch.
The assembler will use special versions of macros containing branches.
Should be the first line of a program.
.double comma-separated doubles Writes 64-bit floating point datapoints
.dword comma-separated ints Writes data in 64-bit chunks # Numbers only
.end_macro no args Ends a macro defined using .macro
.endr no args Not implemented!
Ends the repeated section begun by .repeat.
.extern name of variable, size of variable Defines a global symbol offset from the $gp, whose size is n bytes.
.external name of variable Declares that a symbol is externally visible so it can be referenced by other files via $gp
.float comma-separated floats Writes 32-bit floating point datapoints
.global name of variable, size of variable Defines a global symbol whose size is n bytes.
.globl name of variable Declares that a symbol is externally visible so it can be referenced by other files via $gp
.half comma-separated ints Writes data in 16-bit chunks
.include filepath delimited by double quotes Includes a source file
.kcode optional address Enters the section of the program that contains kernel code
.kdata optional address Enters the section of the program that contains data, accessible by the kernel
.ktext optional address Enters the section of the program that contains kernel code
.macro name of macro, comma-separated parameters Defines a custom macro.
Parameters must begin with the character corresponding to their type (see Help > MIPSym Help > Documentation).
End with .end_macro
.repeat number of repetitions Not implemented!
Repeats all instructions or data between the .repeat and .endr directives.
.sdata optional address Enters the small data section;
accessible via $gp using 16-bit addressing
.space number of bytes Adds n bytes of empty space
.struct optional argument: defines inheritance from another struct Defines a data structure type as the label.
The value of the label is the length of the structure in bytes.
Subsequent items are included in the structure until the next segment directive or another struct.
.text optional address Enters the section of the program that contains code.
.word comma-separated ints Writes data in 32-bit chunks



Syscalls

Like SPIM, MIPSym employs syscalls to handle operations that would otherwise be very tedious to write. MIPSym provides compatibility with all of SPIM's syscalls and allows you to call them the same way. MIPSym also provides its own syntax for syscalls, which is smaller, more concise and readable.

# Valid code (SPIM syntax, deprecated in MIPSym):
    li      $v0,5     # 5 denotes the read_int syscall
    syscall           # runs the syscall in $v0
# Valid code (MIPSym syntax):
    syscall $read_int # runs the read_int syscall directly

MIPSym supports all of the syscalls that SPIM supports. A full listing of these syscalls is provided here.



SPIM-Compatible Syscalls

Syscall Name Arguments Comment
$close $a0 holds file handle Closes file
$exit no args ends program
$exit2 $a0 holds return value ends program, returning the value in $a0
$malloc $a0 holds number of bytes requested. Returns address in $v0
$open $a0 holds address of filename,
$a1 holds flags,
$a2 holds mode.
Returns file handle in $v0
$print_char $a0 holds char to print prints char in $a0
$print_double $a0 holds double to print prints double in $f12
$print_float $a0 holds float to print prints float in $f12
$print_int $a0 holds int to print prints integer in $a0
$print_string $a0 holds string to print prints string in memory at $a0
$read $a0 holds file handle,
$a1 holds buffer address,
$a2 holds buffer length.
Returns number of bytes read in $v0
$read_char no args returns char from console input in $v0
$read_double no args returns double from console input in $f0
$read_float no args returns float from console input in $f0
$read_int no args returns integer from console input in $v0
$read_string $a0 holds address of buffer in memory,
$a1 holds buffer length.
Returns string length in $v0
$write $a0 holds file handle,
$a1 holds buffer address,
$a2 holds buffer length.
Returns number of bytes written in $v0


MIPSym-Specific Syscalls

Syscall Name Arguments Comment
$IO_read $a0 holds address,
$a1 holds number of bytes {1,2,4}.
Returns data in $v0
$IO_write $a0 holds address,
$a1 holds number of bytes {1,2,4},
$a2 holds data to write
writes data to hardware
$callback $a0 holds address of interrupt callback routine,
$a1 holds interrupt number [2-7]
assigns callback function
$close_cons $a0 holds id of console to close Unimplemented
$date_time no args Returns local datetime, spanned across $v0-$v1.
Bits from high($v1) to low($v0): 23 bits=year, 4=month, 5=day, 5=hour, 6=min, 6=sec, 10=mil, 5=local timezone offset from UTC
$flush_print no args transfers the screen buffer to console, avoiding flicker.
$free $a0 holds address of buffer to free Frees memory at address
$open_cons $a0 is console height,
$a1 is console width
Unimplemented
$position $a0 holds file handle,
$a1 holds number of bytes from $a2,
$a2 = start / current / end of file: 0/1/2
Returns absolute position in $v0
$random no args Copies the RANDOM register to $v0.
RANDOM counts down with each instruction run since the program began.
Commonly used to seed an RNG algorithm after waiting for user input.
$select_cons $a0 holds id of console to select Unimplemented
$spool_print no args holds outputs to screen buffer until $flush_print
$string2double $a0 holds address of input string Returns double in $f0 converted from string in memory at $a0
$utc_date_time no args Returns datetime in Universal Coordinated Time, spanned across $v0-$v1.
Bits from high($v1) to low($v0): 23 bits=year, 4=month, 5=day, 5=hour, 6=min, 6=sec, 10=mil, 5=local timezone offset from UTC
$utc_millis no args Returns the number of milliseconds since the Unix Epoch, in Universal Coordinated Time, spanned across $v0-$v1
$xy $a0 holds cursor column [0-79],
$a1 holds cursor row [0-24].
Positions Cursor on the console.
Returns character at ($a0,$a1) in $v0.



Register Names

The GCC assembler refers to registers only by their numeric values, $0-$31. By default MIPSym does not allow the use of $0-$31 as register names, unless you define the symbols $0-$31 in your own code (see aliasing) or add them to MIPSym/asm/mips1.adf. For example, in your own code you could type the following (unindented):

$31 = $ra

MIPSym uses the register names enumerated below. SPIM allows the use of either type of register name. Code written for SPIM or GCC must be adjusted accordingly before the MIPSym assembler will be able to assemble it.


Integer Registers

GCC name MIPSym name Purpose
$0 $zero $0 Always 0
$1 $at Assembler Temporary
$2-$3 $v0-$v1 Function return values/ syscall choice
$4-$7 $a0-$a3 Function arguments
$8-$15 $t0-$t7 Temporary storage, not saved
$16-$23 $s0-$s7 Saved storage, not overwritten
$24-$25 $t8-$t9 Temporary storage, not saved
$26-$27 $k0-$k1 For kernel use only
$28 $gp Global pointer
$29 $sp Stack pointer
$30 $fp Frame pointer
$31 $ra Return address


Floating Point Registers

GCC name MIPSym name Purpose
$0-$31 $f0-$f31 Floating point registers in coprocessor 1


Coprocessor 0 Control Registers

GCC Name MIPSym Name Register Type
$0 $INDEX Coprocessor 0 Control Register
$1 $RANDOM Coprocessor 0 Control Register
$10 $ENTRY_HI Coprocessor 0 Control Register
$11 $COMPARE Coprocessor 0 Control Register
$12 $STATUS Coprocessor 0 Control Register
$13 $CAUSE Coprocessor 0 Control Register
$14 $EPC Coprocessor 0 Control Register
$15 $PRID Coprocessor 0 Control Register
$16 $CONFIG Coprocessor 0 Control Register
$17 $LLADDR Coprocessor 0 Control Register
$18 $WATCH_LO Coprocessor 0 Control Register
$19 $WATCH_HI Coprocessor 0 Control Register
$2 $ENTRY_LO Coprocessor 0 Control Register
$26 $ECC Coprocessor 0 Control Register
$27 $CACHE_ERR Coprocessor 0 Control Register
$28 $TAG_LO Coprocessor 0 Control Register
$29 $TAG_HI Coprocessor 0 Control Register
$3 $ENTRY_LO1 Coprocessor 0 Control Register
$30 $ERROR_EPC Coprocessor 0 Control Register
$4 $CONTEXT Coprocessor 0 Control Register
$5 $PAGEMASK Coprocessor 0 Control Register
$6 $WIRED Coprocessor 0 Control Register
$7 $ERROR Coprocessor 0 Control Register
$8 $BAD_V_ADDR Coprocessor 0 Control Register
$9 $COUNT Coprocessor 0 Control Register


Coprocessor 1 Control Registers

GCC Name MIPSym Name Register Type
$0 $FCR0 Coprocessor 1 Control Register
$31 $FCR31 Coprocessor 1 Control Register



Opcodes and Macros




How to read these tables

These tables present each opcode or macro in the R2000 instruction set, along with its required arguments, and in most cases a brief comment to describe what the instruction does.

In general, the destination argument comes first in an argument list, and the source operand(s) come afterwards. However, five of instructions have this order backwards: mtc0, sb, sh, sw, swl, and swr. These instructions have comments marked in bold to warn you of this.

There are several kinds of arguments:

  • Imm: This stands for 'immediate value'. This can be any signed or unsigned, 32-bit constant integer value. It can be a number, an alias, or a mathematical expression. Note that whether or not Imm is treated as signed or unsigned will depend on the operation being performed.
  • imm: This stands for 'immediate value'. This is similar to 'Imm', but only occupies 16 bits.
  • uimm: This stands for 'unsigned immediate value'. This is similar to 'Uimm', but only occupies 16 bits.
  • label: This is exactly the same as a 32-bit 'immediate value'. The assembler sees both as integers, and it doesn't care whether it's really a label, or just some number you made up. The distinction is meant to show you how the instructions are meant to be used, and to help other programmers to understand your code.
  • sn: This stands for 'shift number'. It can hold any unsigned 5-bit constant integer value.
  • oimm: This stands for 'offset immediate'. It is exactly the same as a 16-bit 'imm' value.
  • rd/rs/rt: These symbols denote integer registers. Usually, the 'd' stands for 'destination' and the 's' stands for 'source.' In the majority of the instructions (r-form instructions), the 't' stands for 'second source' (t comes right after s in the alphabet). Most of the remaining instructions (i-form instructions) use 'rt' as the destination register instead, and rd is unused.
  • fd/fs/ft: These symbols denote single floating point registers ($f0-31). The same general rule for d, s, and t that applies to the integer registers also applies here.
  • dd/ds/dt: These symbols denote double floating point registers: floating point registers with even numbers ($f0-30). The R2000 has 32-bit floating point registers, so a single 64-bit value needs to be spanned across two 32-bit registers. For example:

    # Add the value in $f2-$f3 to the value in $f4-$f5, and store it in $f0-$f1
        add.d   $f0,$f2,$f4
    # Attempt addition with odd registers: this is undefined behavior, and will not assemble!
        add.d   $f6,$f8,$f9
    
  • Cd/Cs/Ct: These symbols denote registers in Coprocessor 0, the System Control Processor.

  • Fd/Fs/Ft: These symbols denote control word registers in Coprocessor 1 ($FCR0 & $FCR31).

The assembler performs type checking for data types; attempting to pass incompatibly signed or over/underflowed values to immediate fields will only generate a warning message, but incorrect use of registers will produce an error. Expressions are treated as being the type of the first operand. The assembler does not currently support under/overflow checking for expressions or 32-bit immediates, however, so caution is advised.

Comments field: The comment field usually includes some pseudocode to describe what the instruction does. This pseudocode includes some abbreviations that may not be clear at first:

  • RF[Rs]: The 'RF' stands for 'Register File', and the Rs denotes the source register. This notation makes more sense if you think of all 32 integer registers as an array of integers. If the source register is $t0 ($t0 is the 8th register), then Rf[Rs] evaluates to the value in register $t0.
  • FpRf[fs]: The 'FpRf' stands for 'Floating Point Register File,' and the 'fs' denotes the source register.
  • un(): This stands for the 'unordered' function. In this context, it means 'check to see if this value is NaN.' See Wikipedia NaN

Memory offsets: Several instructions have the last argument in parentheses. For example, the instruction 'lb' takes the arguments 'rt,oimm(rs)'. The comment includes the pseudocode 'RF[Rt] = Mem[RF[Rs] + Offset]'. 'Mem' stands for MIPSym's simulated memory. It is expected that Rs is an integer register that holds a pointer to a particular location in memory. 'Offset' is the 'oimm' in the second argument: here, it is used as an offset from the pointer in Rs. So, the 'lb' instruction finds the memory that Rs points to, looks 'oimm' bytes away from that address, and copies the byte at that location into Rt.

Note that any instruction that takes the arguments 'rt,oimm(rs)' will also take the arguments 'rt,(rs)'. The assembler will interpret the offset as 0 in this case.




Integer Instruction Set

Most of these instructions are standard on the R2000/R3000. A few of these are from later processors; these are marked as 'Unimplemented.'

Opcode Name Arguments Comment Form
add rd,rs,rt Add
RF[Rd] = RF[Rs] + RF[Rt]
r
add rt,rs,imm Add
alias for addi rt,rs,imm
RF[Rt] = RF[Rs] + Imm
i
addi rt,rs,imm Add Immediate
RF[Rt] = RF[Rs] + Imm
i
addiu rt,rs,imm Add Immediate Unsigned
RF[Rt] = RF[Rs] + Imm
i
addu rd,rs,rt Add Unsigned
RF[Rd] = RF[Rs] + RF[Rt]
r
addu rt,rs,imm Add Unsigned
alias for addiu rt,rs,imm
RF[Rt] = RF[Rs] + imm
i
and rd,rs,rt Bitwise And
RF[Rd] = RF[Rs] & RF[Rt]
r
andi rt,rs,uimm Bitwise And Immediate
RF[Rt] = RF[Rs] & Imm
i
b label Branch
alias for bgez $0,label
PC = label
i
bc0f label Branch Coprocessor0 True
This is a do nothing. It used to test a pin on the part.
i
bc0t label Branch Coprocessor0 False
This is a do nothing. It used to test a pin on the part.
i
beq rs,rt,label Branch Equal
If (RF[Rs] == RF[Rt] )then PC = PC + Imm<< 2
i
beqz rs,label Branch Equal to Zero
alias for beq rs,$0,label
If (RF[Rs] == 0) then PC = PC + Imm<< 2
i
bgez rs,label Branch Greater than or Equal to Zero
If (RF[Rs] >= RF[0]) then PC = PC + Imm<< 2
i
bgezal rs,label Branch Greater than or Equal to Zero And Link
If ( RF[Rs] >= RF[0] ) then {RF[$ra] = PC; PC = PC + Imm<< 2 }
i
bgtz rs,label Branch Greater Than Zero
If (RF[Rs] > RF[0] ) then PC = PC + Imm<< 2
i
blez rs,label Branch Less than or Equal to Zero
If (RF[Rs] <= RF[0]) then PC = PC + Imm<< 2
i
bltz rs,label Branch Less Than Zero
If RF[Rs] < RF[0] then PC = PC + Imm<< 2
i
bltzal rs,label Branch Less Than Zero And Link
If ( RF[Rs] < RF[0] ) then {RF[$ra] = PC; PC = PC + Imm<< 2 }
i
bne rs,rt,label Branch Not Equal
If RF[Rs] != RF[Rt] then PC = PC + Imm<< 2
i
bnez rs,label Branch Not Equal to Zero
alias for bne rs,$0,label
If RF[Rs] != 0 then PC = PC + Imm<< 2
i
break Bcode pause execution b
break Icode pause execution b
break pause execution
alias for break 0
b
div rs,rt Divide (signed)
Low = Quotient ( RF[Rs] / RF[Rt] );
High = Remainder ( RF[Rs] / RF[Rt] )
r
divu rs,rt Divide Unsigned
Low = Quotient ( RF[Rs] / RF[Rt] );
High = Remainder ( RF[Rs] / RF[Rt] )
r
j label Jump
PC = PC(31:28) | Imm<< 2
j
jal label Jump And Link
RF[$ra] = PC;
PC = PC(31:28) | Imm<< 2
j
jalr rd,rs Jump And Link Register
RF[Rd] = PC;
PC = RF[Rs]
r
jalr rs Jump And Link Register
alias for jalr $ra,rs
$ra = PC;
PC = RF[Rs]
r
jr rs Jump Register
PC = RF[Rs]
r
lb rt,oimm(rs) Load Byte
RF[Rt] = Mem[RF[Rs] + Offset]
i
lbu rt,oimm(rs) Load Byte Unsigned
RF[Rt] = Mem[RF[Rs] + Offset]
i
lh rt,oimm(rs) Load Half
RF[Rt] = Mem[RF[Rs] + Offset]
i
lhu rt,oimm(rs) Load Half Unsigned
RF[Rt] = Mem[RF[Rs] + Offset]
i
ll rt,oimm(rs) Load Linked
Unimplemented
i
lui rt,uimm Load Upper Immediate
RF[Rt] = Imm<<16
i
lw rt,oimm(rs) Load Word
RF[Rt] = Mem[RF[Rs] + Offset]
i
lwl rt,oimm(rs) Load Word Left
RF[Rt] = Mem[RF[Rs] + Offset]
i
lwr rt,oimm(rs) Load Word Right
RF[Rt] = Mem[RF[Rs] + Offset]
i
mfc0 rt,Cd Move From Coprocessor0:
Rf[rt] = CP0Rf[cd]
r
mfhi rd Move From Hi
RF[Rd] = HIGH
r
mflo rd Move From Low
RF[Rd] = LOW
r
mov rd,rs Move
alias for addu rd,rs,$0
RF[Rd] = RF[Rs]
r
move rd,rs Move
alias for addu rd,rs,$0
RF[Rd] = RF[Rs]
r
mtc0 rt,Cd Move To Coprocessor0:
CP0Rf[cd] = Rf[rt]
Backwards Arguments!
r
mthi rs Move To Hi
HIGH = RF[Rs]
r
mtlo rs Move To Low
LOW = RF[Rs]
r
mult rs,rt Multiply (signed)
High |Low = RF[Rs] * RF[Rt]
r
multu rs,rt Multiply Unsigned
High |Low = RF[Rs] * RF[Rt]
r
neg rd,rt Negate
alias for sub rd,$0,rt
RF[Rd] = -RF[Rt]
r
negu rd,rt Negate
alias for subu rd,$0,rt
RF[Rd] = -RF[Rt]
r
nop no operation
alias for sll $0,$0,0
r
nor rd,rs,rt Bitwise Nor
RF[Rd] = !(RF[Rs] | RF[Rt])
r
not rd,rs Boolean Not
alias for nor rd,rs,$0
RF[Rd] = !(RF[Rs] | 0)
r
or rd,rs,rt Bitwise Or
RF[Rd] = RF[Rs] | RF[Rt]
r
ori rt,rs,uimm Bitwise Or Immediate
RF[Rt] = RF[Rs] | Imm
i
rfe Restore From Exception
restores the status register to its value before the last exception occurred.
r
sb rt,oimm(rs) Store Byte:
Mem[RF[Rs] + Offset] = RF[Rt]
Backwards Arguments!
i
sgt rd,rt,rs Set Greater Than
alias for slt rd,rs,rt
if (RF[Rt] > RF[Rs] ) then RF[Rd] =1 else RF[Rd] = 0
r
sgtu rd,rt,rs Set Greater Than Unsigned
alias for sltu rd,rs,rt
if (RF[Rt] > RF[Rs] ) then RF[Rd] =1 else RF[Rd] = 0
r
sh rt,oimm(rs) Store Half:
Mem[RF[Rs] + Offset] = RF[Rt]
Backwards Arguments!
i
sll rd,rt,sn Shift Left Logical (immediate)
RF[Rd] = RF[Rt] << n
r
sll rd,rt,rs Shift Left Logical
alias for sllv rd,rt,rs
RF[Rd] = RF[Rt] << RF[Rs] amount
r
sllv rd,rt,rs Shift Left Logical Variable
RF[Rd] = RF[Rt] << RF[Rs] amount
r
slt rd,rs,rt Set Less Than
if (RF[Rs] < RF[Rt] ) then RF[Rd] =1 else RF[Rd] = 0
r
slti rt,rs,imm Set Less Than Immediate
if (RF[Rs] < Imm) then RF[Rt] = 1 else RF[Rt] = 0
i
sltiu rt,rs,imm Set Less Than Immediate Unsigned
if (RF[Rs] < Imm) then RF[Rt] = 1 else RF[Rt] = 0
i
sltu rd,rs,rt Set Less Than Unsigned
if (RF[Rs] < RF[Rt] ) then RF[Rd] =1 else RF[Rd] = 0
r
sra rd,rt,sn Shift Right Arithmetic (immediate)
RF[Rd] = RF[Rt] >> n (sign-extend)
r
sra rd,rt,rs Shift Right Arithmetic
alias for srav rd,rt,rs
RF[Rd] = RF[Rt] >> RF[Rs] amount (sign-extend)
r
srav rd,rt,rs Shift Right Arithmetic Variable
RF[Rd] = RF[Rt] >> RF[Rs] amount (sign-extend)
r
srl rd,rt,sn Shift Right Logical
RF[Rd] = RF[Rt] >> n (no sign extension)
r
srl rd,rt,rs Shift Right Logical
alias for srlv rd,rt,rs
RF[Rd] = RF[Rt] >> RF[Rs] amount (no sign extension)
r
srlv rd,rt,rs Shift Right Logical Variable
RF[Rd] = RF[Rt] >> RF[Rs] amount (no sign extension)
r
sub rd,rs,rt Subtract
RF[Rd] = RF[Rs] - RF[Rt]
r
subu rd,rs,rt Subtract Unsigned
RF[Rd] = RF[Rs] - RF[Rt]
r
sw rt,oimm(rs) Store Word:
Mem[RF[Rs] + Offset] = RF[Rt]
Backwards Arguments!
i
swl rt,oimm(rs) Store Word Left (1-4 bytes, depending on offset):
Mem[RF[Rs] + Offset] = RF[Rt]
Backwards Arguments!
i
swr rt,oimm(rs) Store Word Right (1-4 bytes, depending on offset):
Mem[RF[Rs] + Offset] = RF[Rt]
Backwards Arguments!
i
syscall call syscall in $v0 b
syscall Scode call syscall in argument b
syscall Icode call syscall in argument b
tlbp Probe TLB For Matching Entry
Unimplemented
r
tlbr Read Indexed TLB Entry
Unimplemented
r
tlbwi Write Indexed TLB Entry
Unimplemented
r
tlbwr Write Random TLB Entry
Unimplemented
r
xor rd,rs,rt Bitwise Xor
RF[Rd] = RF[Rs] ^ RF[Rt]
r
xori rt,rs,uimm Bitwise Xor Immediate
RF[Rt] = RF[Rs] ^ Imm
i



Floating-Point Instruction Set

Most of these instructions are standard on the R2000/R3000. A few of these are from later processors; these are marked as 'Unimplemented.'

Opcode Name Arguments Comment Form
abs.d dd,ds Absolute value double:
FpRf[dd] = |FpRf[ds]|
r
abs.s fd,fs Absolute value single:
FpRf[fd] = |FpRf[fs]|
r
add.d dd,ds,dt Add double:
FpRf[dd] = FpRf[ds] + FpRf[dt]
r
add.s fd,fs,ft Add single:
FpRf[fd] = FpRf[fs] + FpRf[ft]
r
bc1f label branch if status flag is false i
bc1t label branch if status flag is true i
c.eq.d ds,dt Compare Equal Doubles:
ControlRf[31].condition_bit = FpRf[dt] == FpRf[ds] && !(un(FpRf[dt]) || un(FpRf[ds]))
r
c.eq.s fs,ft Compare Equal Singles:
ControlRf[31].condition_bit = FpRf[ft] == FpRf[fs] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.f.d ds,dt Compare False:
ControlRf[31].condition_bit = 0
r
c.f.s fs,ft Compare False:
ControlRf[31].condition_bit = 0
r
c.le.d ds,dt Compare Less Than or Equal:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] <= FpRf[dt] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.le.s fs,ft Compare Less Than or Equal:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] <= FpRf[ft] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.lt.d ds,dt Compare Less Than:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] < FpRf[dt] && !(un(FpRf[dt]) || un(FpRf[ds]))
r
c.lt.s fs,ft Compare Less Than:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] < FpRf[ft] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.nge.d ds,dt Compare Not Greater or Equal, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] < FpRf[dt] || (un(FpRf[ds]) || un(FpRf[dt]))
r
c.nge.s fs,ft Compare Not Greater or Equal, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] < FpRf[ft] || (un(FpRf[fs]) || un(FpRf[ft]))
r
c.ngl.d ds,dt Compare Not Greater or Less Than, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] == FpRf[dt] || (un(FpRf[ds]) || un(FpRf[dt]))
r
c.ngl.s fs,ft Compare Not Greater or Less Than, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] == FpRf[ft] || (un(FpRf[fs]) || un(FpRf[ft]))
r
c.ngle.d ds,dt Compare Not Greater, Less, or Equal (only true if unordered):
exception if unordered;
ControlRf[31].condition_bit = (un(FpRf[dt]) || un(FpRf[ds]))
r
c.ngle.s fs,ft Compare Not Greater, Less, or Equal (only true if unordered):
exception if unordered;
ControlRf[31].condition_bit = (un(FpRf[ft]) || un(FpRf[fs]))
r
c.ngt.d ds,dt Compare Not Greater Than, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] <= FpRf[dt] || (un(FpRf[fs]) || un(FpRf[ft]))
r
c.ngt.s fs,ft Compare Not Greater Than, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] <= FpRf[ft] || (un(FpRf[fs]) || un(FpRf[ft]))
r
c.ole.d ds,dt Compare Ordered Less Than Or Equal:
ControlRf[31].condition_bit = FpRf[ds] <= FpRf[dt] && !(un(FpRf[dt]) || un(FpRf[ds]))
r
c.ole.s fs,ft Compare Ordered Less Than Or Equal:
ControlRf[31].condition_bit = FpRf[fs] <= FpRf[ft] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.olt.d ds,dt Compare Ordered Less Than:
ControlRf[31].condition_bit = FpRf[ds] < FpRf[dt] && !(un(FpRf[dt]) || un(FpRf[ds]))
r
c.olt.s fs,ft Compare Ordered Less Than:
ControlRf[31].condition_bit = FpRf[fs] < FpRf[ft] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.seq.d ds,dt Compare Signaling Equal:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] == FpRf[dt] && !(un(FpRf[dt]) || un(FpRf[ds]))
r
c.seq.s fs,ft Compare Signaling Equal:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] == FpRf[ft] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.sf.d ds,dt Compare Signaling False:
exception if unordered;
ControlRf[31].condition_bit = 0
r
c.sf.s fs,ft Compare Signaling False:
exception if unordered;
ControlRf[31].condition_bit = 0
r
c.ueq.d ds,dt Compare Unordered/Equal Doubles:
ControlRf[31].condition_bit = (FpRf[dt] == FpRf[ds]) || (un(FpRf[dt]) || un(FpRf[ds]))
r
c.ueq.s fs,ft Compare Unordered/Equal Singles:
ControlRf[31].condition_bit = (FpRf[ft] == FpRf[fs]) || (un(FpRf[ft]) || un(FpRf[fs]))
r
c.ule.d ds,dt Compare Unordered Less Than Or Equal:
ControlRf[31].condition_bit = FpRf[ds] <= FpRf[dt] || (un(FpRf[dt]) || un(FpRf[ds]))
r
c.ule.s fs,ft Compare Unordered Less Than Or Equal:
ControlRf[31].condition_bit = FpRf[fs] <= FpRf[ft] || (un(FpRf[ft]) || un(FpRf[fs]))
r
c.ult.d ds,dt Compare Unordered Less Than:
ControlRf[31].condition_bit = FpRf[ds] < FpRf[dt] || (un(FpRf[dt]) || un(FpRf[ds]))
r
c.ult.s fs,ft Compare Unordered Less Than:
ControlRf[31].condition_bit = FpRf[fs] < FpRf[ft] || (un(FpRf[ft]) || un(FpRf[fs]))
r
c.un.d ds,dt Compare Unordered Doubles:
ControlRf[31].condition_bit = un(FpRf[dt]) || un(FpRf[ds])
r
c.un.s fs,ft Compare Unordered Singles:
ControlRf[31].condition_bit = un(FpRf[ft]) || un(FpRf[fs])
r
cfc1 rt,Fs move control word from cop1:
Rf[rt] = ControlRf[Cs]
r
ctc1 rt,Fs move control word to cop1:
ControlRf[Cs] = Rf[rt]
Backwards Arguments!
r
cvt.d.s dd,fs Convert single to double:
FpRf[dd] = (double) FpRf[fs]
r
cvt.d.w dd,fs Convert integer to double:
FpRf[dd] = (double) FpRf[fs]
r
cvt.s.d fd,ds Convert double to single:
FpRf[fd] = (float) FpRf[ds]
r
cvt.s.w fd,fs Convert integer to single:
FpRf[fd] = (float) FpRf[fs]
r
cvt.w.d fd,ds Convert double to integer:
FpRf[fd] = (int) FpRf[ds]
r
cvt.w.s fd,fs Convert single to integer:
FpRf[fd] = (int) FpRf[fs]
r
div.d dd,ds,dt Divide double:
FpRf[dd] = FpRf[ds] / FpRf[dt]
r
div.s fd,fs,ft Divide single:
FpRf[fd] = FpRf[fs] / FpRf[ft]
r
l.s ft,oimm(rs) load word to cop1:
FpRf[ft] = Mem[Rf[rs] + Offset]
i
lwc1 ft,oimm(rs) load word to cop1:
FpRf[ft] = Mem[Rf[rs] + Offset]
i
lwc2 rt,oimm(rs) load word to cop2:
Unimplemented
i
lwc3 rt,oimm(rs) load word to cop3:
Unimplemented
i
mfc1 rt,fs move from cop1:
Rf[rt] = FpRf[fs]
r
mov.d dd,ds Copy double value:
FpRf[dd] = FpRf[ds]
r
mov.s fd,fs Copy single value:
FpRf[fd] = FpRf[fs]
r
mtc1 rt,fs move to cop1:
FpRf[fs] = Rf[rt]
Backwards Arguments!
r
mul.d dd,ds,dt Multiply double:
FpRf[dd] = FpRf[ds] * FpRf[dt]
r
mul.s fd,fs,ft Multiply single:
FpRf[fd] = FpRf[fs] * FpRf[ft]
r
neg.d dd,ds Negate double value:
FpRf[dd] = -FpRf[ds]
r
neg.s fd,fs Negate single value:
FpRf[fd] = -FpRf[fs]
r
s.s ft,oimm(rs) store word from cop1:
Mem[Rf[rs] + Offset] = FpRf[ft]
Backwards Arguments!
i
sc rt,oimm(rs) Unimplemented i
sub.d dd,ds,dt Subtract double:
FpRf[dd] = FpRf[ds] - FpRf[dt]
r
sub.s fd,fs,ft Subtract single:
FpRf[fd] = FpRf[fs] - FpRf[ft]
r
swc1 ft,oimm(rs) store word from cop1:
Mem[Rf[rs] + Offset] = FpRf[ft]
Backwards Arguments!
i
swc2 rt,oimm(rs) store word from cop2:
Mem[Rf[rs] + Offset] = Unimplemented
i
swc3 rt,oimm(rs) store word from cop3:
Mem[Rf[rs] + Offset] = Unimplemented
i



Floating-Point Math Opcodes, MIPSym-Specific

These are nonstandard opcodes for various mathematic functions. They are not native to the R2000/R3000, but they may be useful for your programs. Some of these opcodes are standard in later versions of MIPS.

Opcode Name Arguments Comment Form
acos.d dd,ds arc cosine double:
FpRf[dd] = acos(FpRf[ds])
r
acos.s fd,fs arc cosine single:
FpRf[fd] = acos(FpRf[fs])
r
acosh.d dd,ds arc hyperbolic cosine double:
FpRf[dd] = acosh(FpRf[ds])
r
acosh.s fd,fs arc hyperbolic cosine single:
FpRf[fd] = acosh(FpRf[fs])
r
asin.d dd,ds arc sine double:
FpRf[dd] = asin(FpRf[ds])
r
asin.s fd,fs arc sine single:
FpRf[fd] = asin(FpRf[fs])
r
asinh.d dd,ds arc hyperbolic sine double:
FpRf[dd] = asinh(FpRf[ds])
r
asinh.s fd,fs arc hyperbolic sine single:
FpRf[fd] = asinh(FpRf[fs])
r
atan.d dd,ds arc tangent double:
FpRf[dd] = atan(FpRf[ds])
r
atan.s fd,fs arc tangent single:
FpRf[fd] = atan(FpRf[fs])
r
atan2.d dd,ds,dt arc tangent of y,x double:
FpRf[dd] = atan2(FpRf[ds],FpRf[dt])
r
atan2.s fd,fs,ft arc tangent of y,x single:
FpRf[fd] = atan2(FpRf[fs],FpRf[ft])
r
atanh.d dd,ds arc hyperbolic tangent double:
FpRf[dd] = atanh(FpRf[ds])
r
atanh.s fd,fs arc hyperbolic tangent single:
FpRf[fd] = atanh(FpRf[fs])
r
ceil.d dd,ds ceiling double and convert to integer:
FpRf[dd] = (int) ceil(FpRf[ds])
r
ceil.s fd,fs ceiling single and convert to integer:
FpRf[fd] = (int) ceil(FpRf[fs])
r
ceil.w.d dd,ds ceiling double:
FpRf[dd] = ceil(FpRf[ds])
r
ceil.w.s fd,fs ceiling single:
FpRf[fd] = ceil(FpRf[fs])
r
cos.d dd,ds cosine double:
FpRf[dd] = cos(FpRf[ds])
r
cos.s fd,fs cosine single:
FpRf[fd] = cos(FpRf[fs])
r
cosh.d dd,ds hyperbolic cosine double:
FpRf[dd] = cosh(FpRf[ds])
r
cosh.s fd,fs hyperbolic cosine single:
FpRf[fd] = cosh(FpRf[fs])
r
exp.d dd,ds e to the x power double:
FpRf[dd] = exp(FpRf[ds])
r
exp.s fd,fs e to the x power single:
FpRf[fd] = exp(FpRf[fs])
r
floor.d dd,ds floor double and convert to integer:
FpRf[dd] = (int) floor(FpRf[ds])
r
floor.s fd,fs floor single and convert to integer:
FpRf[fd] = (int) floor(FpRf[fs])
r
floor.w.d dd,ds floor double:
FpRf[dd] = floor(FpRf[ds])
r
floor.w.s fd,fs floor single:
FpRf[fd] = floor(FpRf[fs])
r
ln.d dd,ds natural log double:
FpRf[dd] = ln(FpRf[ds])
r
ln.s fd,fs natural log single:
FpRf[fd] = ln(FpRf[fs])
r
round.d dd,ds round double and convert to integer:
FpRf[dd] = (int) round(FpRf[ds])
r
round.s fd,fs round single and convert to integer:
FpRf[fd] = (int) round(FpRf[fs])
r
round.w.d dd,ds round double:
FpRf[dd] = round(FpRf[ds])
r
round.w.s fd,fs round single:
FpRf[fd] = round(FpRf[fs])
r
sin.d dd,ds sine double:
FpRf[dd] = sin(FpRf[ds])
r
sin.s fd,fs sine single:
FpRf[fd] = sin(FpRf[fs])
r
sinh.d dd,ds hyperbolic sine double:
FpRf[dd] = sinh(FpRf[ds])
r
sinh.s fd,fs hyperbolic sine single:
FpRf[fd] = sinh(FpRf[fs])
r
sqrt.d dd,ds square root double:
FpRf[dd] = sqrt(FpRf[ds])
r
sqrt.s fd,fs square root single:
FpRf[fd] = sqrt(FpRf[fs])
r
tan.d dd,ds tangent double:
FpRf[dd] = tan(FpRf[ds])
r
tan.s fd,fs tangent single:
FpRf[fd] = tan(FpRf[fs])
r
tanh.d dd,ds hyperbolic tangent double:
FpRf[dd] = tanh(FpRf[ds])
r
tanh.s fd,fs hyperbolic tangent single:
FpRf[fd] = tanh(FpRf[fs])
r
trunc.d dd,ds truncate double and convert to integer:
FpRf[dd] = (int) trunc(FpRf[ds])
r
trunc.s fd,fs truncate single and convert to integer:
FpRf[fd] = (int) trunc(FpRf[fs])
r
trunc.w.d dd,ds truncate double:
FpRf[dd] = trunc(FpRf[ds])
r
trunc.w.s fd,fs truncate single:
FpRf[fd] = trunc(FpRf[fs])
r



Macros

In addition to the original instructions implemented in the R2000, MIPSym also supports the use of several macros to make the process of writing assembly code easier.

Unlike SPIM, macros can be defined in program code using the .macro and .end_macro assembler directives. Predefined macros are defined in the file MIPSym/asm/Mips1.adf.

Macro Name Arguments Comment
abs rd,rs Absolute Value
Rf[rd] = abs(Rf[rs])
Note that if Rf[rs] == 0x80000000, an arithmetic overflow will occur, because 'positive 0x80000000' cannot be represented as a 32-bit signed integer.
Use `absu` to prevent this.

Delay Slot OffDelay Slot On
  addu  rd,$0,rs
  bgez  rs,09f
  sub   rd,$0,rs
09:
  bgez  rs,09f
  addu  rd,$0,rs
  sub   rd,$0,rs
09:
absu rd,rs Absolute Value Unsigned
Rf[rd] = abs(Rf[rs])
Stores an unsigned 32-bit integer in Rf[rd].
Note that this can store 'positive 0x80000000' in Rf[rd], which is negative when interpreted as a signed integer.
Use `abs` to prevent this.

Delay Slot OffDelay Slot On
  addu  rd,$0,rs
  bgez  rs,09f
  subu  rd,$0,rs
09:
  bgez  rs,09f
  addu  rd,$0,rs
  subu  rd,$0,rs
09:
addi rt,imm Add immediate:
Rf[rt] = Rf[rt] + imm

  addi  rt,rt,imm
addiu rt,imm Add immediate unsigned:
Rf[rt] = Rf[rt] + imm

  addiu rt,rt,imm
andi rt,imm And immediate:
Rf[rt] = Rf[rt] & imm

  andi  rt,rt,imm
beq rs,Imm,label Branch equal to
If (RF[Rs] == Imm) then branch to Label

  li    $at,Imm
  beq   rs,$at,label
bge rs,rt,label Branch greater than or equal to
If (RF[Rs] >= Rf[Rt]) then branch to Label

  slt   $at,rs,rt
  beq   $at,$0,label
bge rs,Imm,label Branch greater than or equal to
If (RF[Rs] >= Imm) then branch to Label

  li    $at,Imm
  slt   $at,rs,$at
  beq   $at,$0,label
bgeu rs,rt,label Branch greater than or equal to (Unsigned)
If (RF[Rs] >= Rf[Rt]) then branch to Label

  sltu  $at,rs,rt
  beq   $at,$0,label
bgeu rs,Uimm,label Branch greater than or equal to (Unsigned)
If (RF[Rs] >= Imm) then branch to Label

  li    $at,Uimm
  sltu  $at,rs,$at
  beq   $at,$0,label
bgt rs,rt,label Branch greater than
If (RF[Rs] > Rf[Rt]) then branch to Label

  slt   $at,rt,rs
  bne   $at,$0,label
bgt rs,Imm,label Branch greater than
If (RF[Rs] > Imm) then branch to Label

  li    $at,Imm
  slt   $at,$at,rs
  bne   $at,$0,label
bgtu rs,rt,label Branch greater than (Unsigned)
If (RF[Rs] > Rf[Rt]) then branch to Label

  sltu  $at,rt,rs
  bne   $at,$0,label
bgtu rs,Uimm,label Branch greater than (Unsigned)
If (RF[Rs] > Imm) then branch to Label

  li    $at,Uimm
  sltu  $at,$at,rs
  bne   $at,$0,label
ble rs,rt,label Branch less than or equal to
If (RF[Rs] <= Rf[Rt]) then branch to Label

  slt   $at,rt,rs
  beq   $at,$0,label
ble rs,Imm,label Branch less than or equal to
If (RF[Rs] <= Imm) then branch to Label

  li    $at,Imm
  slt   $at,$at,rs
  beq   $at,$0,label
bleu rs,rt,label Branch less than or equal to (Unsigned)
If (RF[Rs] <= Rf[Rt]) then branch to Label

  sltu  $at,rt,rs
  beq   $at,$0,label
bleu rs,Uimm,label Branch less than or equal to (Unsigned)
If (RF[Rs] <= Imm) then branch to Label

  li    $at,Uimm
  sltu  $at,$at,rs
  beq   $at,$0,label
blt rs,rt,label Branch less than
If (RF[Rs] < Rf[Rt]) then branch to Label

  slt   $at,rs,rt
  bne   $at,$0,label
blt rs,Imm,label Branch less than
If (RF[Rs] < Imm) then branch to Label

  li    $at,Imm
  slt   $at,rs,$at
  bne   $at,$0,label
bltu rs,rt,label Branch less than (Unsigned)
If (RF[Rs] < Rf[Rt]) then branch to Label

  sltu  $at,rs,rt
  bne   $at,$0,label
bltu rs,Uimm,label Branch less than (Unsigned)
If (RF[Rs] < Imm) then branch to Label

  li    $at,Uimm
  sltu  $at,rs,$at
  bne   $at,$0,label
bne rs,Imm,label Branch not equal
If (RF[Rs] != Imm) then branch to Label

  li    $at,Imm
  bne   rs,$at,label
div rd,rs,rt Divide:
Rf[rd] = Rf[rs]/Rf[rt]
(break on divide by zero)

Delay Slot OffDelay Slot On
  bne   rt,$0,08f
  break
08:
  div   rs,rt
  mflo  rd
  bne   rt,$0,08f
  nop
  break
08:
  div   rs,rt
  mflo  rd
div rd,rs,Imm Divide:
Rf[rd] = Rf[rs]/Imm

  li    $at,Imm
  div   rs,$at
  mflo  rd
div rd,Imm Divide:
Rf[rd] = Rf[rd]/Imm

  li    $at,Imm
  div   rd,$at
  mflo  rd
divnz rd,rs,rt Divide:
Rf[rd] = Rf[rs]/Rf[rt]

  div   rs,rt
  mflo  rd
divu rd,rs,rt Divide unsigned:
Rf[rd] = Rf[rs] / Rf[rt]
(break on divide by zero)

Delay Slot OffDelay Slot On
  bne   rt,$0,08f
  break
08:
  divu  rs,rt
  mflo  rd
  bne   rt,$0,08f
  nop
  break
08:
  divu  rs,rt
  mflo  rd
divu rd,rs,Uimm Divide unsigned:
Rf[rd] = Rf[rs] / Imm

  li    $at,Uimm
  divu  rs,$at
  mflo  rd
divu rd,Uimm Divide unsigned:
Rf[rd] = Rf[rd] / Imm

  li    $at,Uimm
  divu  rd,$at
  mflo  rd
l.d dd,laddress Load double:
FpRf[dd] = laddress

  lui   $at,laddress&0x8000<<1+laddress>>16
  lwc1  dd,laddress&0xFFFF($at)
  lwc1  dd+1,laddress&0xFFFF+4($at)
l.d dd,imm(rs) Load double:
FpRf[dd] = Mem[RF[Rs] + Offset]

  lwc1  dd,imm(rs)
  lwc1  dd+1,imm+4(rs)
l.s fd,laddress Load single:
FpRf[fd] = laddress

  lui   $at,laddress&0x8000<<1+laddress>>16
  lwc1  fd,laddress&0xFFFF($at)
la rd,laddress Load Address into Rf[rd]

  lui   rd,laddress>>16
  ori   rd,rd,laddress&0xffff
lb rd,laddress Load byte (low 8 bits):
Rf[rd] = Mem[laddress]

  lui   $at,laddress&0x8000<<1+laddress>>16
  lb    rd,laddress&0xFFFF($at)
lbu rd,laddress Load byte unsigned (low 8 bits):
Rf[rd] = Mem[laddress]

  lui   $at,laddress&0x8000<<1+laddress>>16
  lbu   rd,laddress&0xFFFF($at)
lh rd,laddress Load half (low 16 bits):
Rf[rd] = Mem[laddress]

  lui   $at,laddress&0x8000<<1+laddress>>16
  lh    rd,laddress&0xFFFF($at)
lhu rd,laddress Load half unsigned (low 16 bits):
Rf[rd] = Mem[laddress]

  lui   $at,laddress&0x8000<<1+laddress>>16
  lhu   rd,laddress&0xFFFF($at)
li rd,imm Load Immediate into Rf[rd] variable size, no forward reference.
This macro is used when the high 16 bits of imm are zero.

ori   rd,$0,imm
li rd,imm Load Immediate into Rf[rd] variable size, no forward reference.
This macro is used when the low 16 bits of imm are zero.

lui   rd,imm
li rd,imm Load Immediate into Rf[rd] variable size, no forward reference.
This macro is used when the high 17 bits of imm are 1 (it's a small negative number).

addi   rd,$0,imm
li rd,imm Load Immediate into Rf[rd] variable size, no forward reference.
This macro is used when none of the three other forms can be used.

lui   rd,imm
ori   rd,$0,imm
lw rd,laddress Load word (full 32 bits):
Rf[rd] = Mem[laddress]

  lui   $at,laddress&0x8000<<1+laddress>>16
  lw    rd,laddress&0xFFFF($at)
mul rd,rs,rt Multiply:
Rf[rd] = Rf[rs] * Rf[rt]

  mult  rs,rt
  mflo  rd
mul rd,rs,Imm Multiply:
Rf[rd] = Rf[rs]*Imm

  li    $at,Imm
  mult  rs,$at
  mflo  rd
mul rd,Imm Multiply:
Rf[rd] = Rf[rd]*Imm

  li    $at,Imm
  mult  rd,$at
  mflo  rd
mulo rd,rs,rt Multiply, break on overflow

Delay Slot OffDelay Slot On
  mult  rs,rt
  mfhi  $at
  mflo  rd
  sra   rd,rd,31
  beq   $at,rd,08f
  break
08:
  mflo  rd
  mult  rs,rt
  mfhi  $at
  mflo  rd
  sra   rd,rd,31
  beq   $at,rd,08f
  mflo  rd
  break
08:
mulou rd,rs,rt Multiply unsigned, break on overflow

Delay Slot OffDelay Slot On
  multu rs,rt
  mfhi  $at
  beq   $at,$0,08f
  break
08:
  mflo  rd
  multu rs,rt
  mfhi  $at
  beq   $at,$0,08f
  mflo  rd
  break
08:
mulu rd,rs,rt Multiply unsigned:
Rf[rd] = Rf[rs] * Rf[rt]

  multu rs,rt
  mflo  rd
mulu rd,rs,Uimm Multiply unsigned:
Rf[rd] = Rf[rs] * Imm

  li    $at,Uimm
  multu rs,$at
  mflo  rd
mulu rd,Uimm Multiply unsigned:
Rf[rd] = Rf[rd] * Imm

  li    $at,Uimm
  multu rd,$at
  mflo  rd
ori rt,imm Or immediate:
Rf[rt] = Rf[rt] | imm

  ori   rt,rt,imm
rem rd,rs,rt Remainder:
Rf[rd] = Rf[rs] % Rf[rt]

Delay Slot OffDelay Slot On
  bne   rt,$0,08f
  break
08:
  div   rs,rt
  mfhi  rd
  bne   rt,$0,08f
  nop
  break
08:
  div   rs,rt
  mfhi  rd
rem rd,rs,Imm Remainder:
Rf[rd] = Rf[rs] % Imm

  li    $at,Imm
  div   rs,$at
  mfhi  rd
rem rd,Imm Remainder:
Rf[rd] = Rf[rd] % Imm

  li    $at,Imm
  div   rd,$at
  mfhi  rd
remu rd,rs,rt Remainder unsigned:
Rf[rd] = Rf[rs] % Rf[rt]

Delay Slot OffDelay Slot On
  bne   rt,$0,08f
  break
08:
  divu  rs,rt
  mfhi  rd
  bne   rt,$0,08f
  nop
  break
08:
  divu  rs,rt
  mfhi  rd
remu rd,rs,Uimm Remainder unsigned:
Rf[rd] = Rf[rs] % Imm

  li    $at,Uimm
  divu  rs,$at
  mfhi  rd
remu rd,Uimm Remainder unsigned:
Rf[rd] = Rf[rd] % Imm

  li    $at,Uimm
  divu  rd,$at
  mfhi  rd
rol rd,rt,rs Rotate left

  subu  $at,$0,rs
  srlv  $at,rt,$at
  sllv  rd,rt,rs
  or    rd,rd,$at
rol rd,rt,sn Rotate left

  srl   $at,rt,-sn
  sll   rd,rt,sn
  or    rd,rd,$at
ror rd,rt,rs Rotate right

  subu  $at,$0,rs
  sllv  $at,rt,$at
  srlv  rd,rt,rs
  or    rd,rd,$at
ror rd,rt,sn Rotate right

  sll   $at,rt,-sn
  srl   rd,rt,sn
  or    rd,rd,$at
s.d dd,laddress Store double:
Mem[laddress] = FpRf[dd]
Backwards Arguments!

  lui   $at,laddress&0x8000<<1+laddress>>16
  swc1  dd,laddress&0xFFFF($at)
  swc1  dd+1,laddress&0xFFFF+4($at)
s.d dd,oimm(rs) Store double:
Mem[RF[Rs] + Offset] = FpRf[dd]
Backwards Arguments!

  swc1  dd,oimm(rs)
  swc1  dd+1,oimm+4(rs)
s.s fd,laddress Store single:
Mem[laddress] = FpRf[fd]
Backwards Arguments!

  lui   $at,laddress&0x8000<<1+laddress>>16
  swc1  fd,laddress&0xFFFF($at)
sb rd,laddress Store byte (low 8 bits):
Mem[laddress] = Rf[rd]
Backwards Arguments!

  lui   $at,laddress&0x8000<<1+laddress>>16
  sb    rd,laddress&0xFFFF($at)
seq rd,rs,rt Set if equal:
Rf[rd] = Rf[rs] == Rf[rt]

  subu  $at,rs,rt
  sltiu rd,$at,1
sge rd,rs,rt Set greater than:
Rf[rd] = Rf[rs] > Rf[rt]

  slt   rd,rs,rt
  slti  rd,rd,1
sgeu rd,rs,rt Set greater than unsigned:
Rf[rd] = Rf[rs] > Rf[rt]

  sltu  rd,rs,rt
  slti  rd,rd,1
sh rd,laddress Store half (low 16 bits):
Mem[laddress] = Rf[rd]
Backwards Arguments!

  lui   $at,laddress&0x8000<<1+laddress>>16
  sh    rd,laddress&0xFFFF($at)
sle rd,rs,rt Set less than or equal:
Rf[rd] = Rf[rs] <= Rf[rt]

  slt   rd,rt,rs
  slti  rd,rd,1
sleu rd,rs,rt Set less than or equal unsigned:
Rf[rd] = Rf[rs] <= Rf[rt]

  sltu  rd,rt,rs
  slti  rd,rd,1
sne rd,rs,rt Set if not equal:
Rf[rd] = Rf[rs] != Rf[rt]

  subu  $at,rs,rt
  sltu  rd,$0,$at
sub rt,rs,imm Subtract:
Rf[rt] = Rf[rs] - imm

  addi  rt,rs,-imm
sub rt,imm Subtract:
Rf[rt] = Rf[rt] - imm

  addi  rt,rt,-imm
subu rt,imm Subtract unsigned:
Rf[rt] = Rf[rt] - imm

  addiu rt,rt,-imm
subu rt,rs,imm Subtract unsigned:
Rf[rt] = Rf[rs] - imm

  addiu rt,rs,-imm
sw rd,laddress Store word (full 32 bits):
Mem[laddress] = Rf[rd]
Backwards Arguments!

  lui   $at,laddress&0x8000<<1+laddress>>16
  sw    rd,laddress&0xFFFF($at)
ulh rt,oimm(rs)

  lb    rt,oimm+1(rs)
  lbu   $at,oimm(rs)
  sll   rt,rt,8
  or    rt,rt,$at
ulhu rt,oimm(rs)

  lbu   rt,oimm+1(rs)
  lbu   $at,oimm(rs)
  sll   rt,rt,8
  or    rt,rt,$at
ulw rt,oimm(rs)

  lwl   rt,oimm+3(rs)
  lwr   rt,oimm(rs)
ush rt,oimm(rs)

  sb    rt,oimm(rs)
  srl   $at,rt,8
  sb    $at,oimm+1(rs)
usw rt,oimm(rs)

  swl   rt,oimm+3(rs)
  swr   rt,oimm(rs)
xori rt,imm Xor immediate:
Rf[rt] = Rf[rt] ^ imm

  xori  rt,rt,imm



Full Listing of All Opcodes and Macros

For your convenience, all of the opcodes and macros are repeated here, alphabetized. Many of the opcodes have overloaded macro definitions, which will be invoked based on the arguments you provide. This view is intended to help you to see what those overloads are.

Opcode/Macro Name Arguments Comment Form
abs rd,rs Absolute Value
Rf[rd] = abs(Rf[rs])
Note that if Rf[rs] == 0x80000000, an arithmetic overflow will occur, because 'positive 0x80000000' cannot be represented as a 32-bit signed integer.
Use `absu` to prevent this.

Delay Slot OffDelay Slot On
  addu  rd,$0,rs
  bgez  rs,09f
  sub   rd,$0,rs
09:
  bgez  rs,09f
  addu  rd,$0,rs
  sub   rd,$0,rs
09:
abs.d dd,ds Absolute value double:
FpRf[dd] = |FpRf[ds]|
r
abs.s fd,fs Absolute value single:
FpRf[fd] = |FpRf[fs]|
r
absu rd,rs Absolute Value Unsigned
Rf[rd] = abs(Rf[rs])
Stores an unsigned 32-bit integer in Rf[rd].
Note that this can store 'positive 0x80000000' in Rf[rd], which is negative when interpreted as a signed integer.
Use `abs` to prevent this.

Delay Slot OffDelay Slot On
  addu  rd,$0,rs
  bgez  rs,09f
  subu  rd,$0,rs
09:
  bgez  rs,09f
  addu  rd,$0,rs
  subu  rd,$0,rs
09:
acos.d dd,ds arc cosine double:
FpRf[dd] = acos(FpRf[ds])
r
acos.s fd,fs arc cosine single:
FpRf[fd] = acos(FpRf[fs])
r
acosh.d dd,ds arc hyperbolic cosine double:
FpRf[dd] = acosh(FpRf[ds])
r
acosh.s fd,fs arc hyperbolic cosine single:
FpRf[fd] = acosh(FpRf[fs])
r
add rd,rs,rt Add
RF[Rd] = RF[Rs] + RF[Rt]
r
add rt,rs,imm Add
alias for addi rt,rs,imm
RF[Rt] = RF[Rs] + Imm
i
add.d dd,ds,dt Add double:
FpRf[dd] = FpRf[ds] + FpRf[dt]
r
add.s fd,fs,ft Add single:
FpRf[fd] = FpRf[fs] + FpRf[ft]
r
addi rt,rs,imm Add Immediate
RF[Rt] = RF[Rs] + Imm
i
addi rt,imm Add immediate:
Rf[rt] = Rf[rt] + imm

  addi  rt,rt,imm
addiu rt,rs,imm Add Immediate Unsigned
RF[Rt] = RF[Rs] + Imm
i
addiu rt,imm Add immediate unsigned:
Rf[rt] = Rf[rt] + imm

  addiu rt,rt,imm
addu rd,rs,rt Add Unsigned
RF[Rd] = RF[Rs] + RF[Rt]
r
addu rt,rs,imm Add Unsigned
alias for addiu rt,rs,imm
RF[Rt] = RF[Rs] + imm
i
and rd,rs,rt Bitwise And
RF[Rd] = RF[Rs] & RF[Rt]
r
andi rt,rs,uimm Bitwise And Immediate
RF[Rt] = RF[Rs] & Imm
i
andi rt,imm And immediate:
Rf[rt] = Rf[rt] & imm

  andi  rt,rt,imm
asin.d dd,ds arc sine double:
FpRf[dd] = asin(FpRf[ds])
r
asin.s fd,fs arc sine single:
FpRf[fd] = asin(FpRf[fs])
r
asinh.d dd,ds arc hyperbolic sine double:
FpRf[dd] = asinh(FpRf[ds])
r
asinh.s fd,fs arc hyperbolic sine single:
FpRf[fd] = asinh(FpRf[fs])
r
atan.d dd,ds arc tangent double:
FpRf[dd] = atan(FpRf[ds])
r
atan.s fd,fs arc tangent single:
FpRf[fd] = atan(FpRf[fs])
r
atan2.d dd,ds,dt arc tangent of y,x double:
FpRf[dd] = atan2(FpRf[ds],FpRf[dt])
r
atan2.s fd,fs,ft arc tangent of y,x single:
FpRf[fd] = atan2(FpRf[fs],FpRf[ft])
r
atanh.d dd,ds arc hyperbolic tangent double:
FpRf[dd] = atanh(FpRf[ds])
r
atanh.s fd,fs arc hyperbolic tangent single:
FpRf[fd] = atanh(FpRf[fs])
r
b label Branch
alias for bgez $0,label
PC = label
i
bc0f label Branch Coprocessor0 True
This is a do nothing. It used to test a pin on the part.
i
bc0t label Branch Coprocessor0 False
This is a do nothing. It used to test a pin on the part.
i
bc1f label branch if status flag is false i
bc1t label branch if status flag is true i
beq rs,rt,label Branch Equal
If (RF[Rs] == RF[Rt] )then PC = PC + Imm<< 2
i
beq rs,Imm,label Branch equal to
If (RF[Rs] == Imm) then branch to Label

  li    $at,Imm
  beq   rs,$at,label
beqz rs,label Branch Equal to Zero
alias for beq rs,$0,label
If (RF[Rs] == 0) then PC = PC + Imm<< 2
i
bge rs,rt,label Branch greater than or equal to
If (RF[Rs] >= Rf[Rt]) then branch to Label

  slt   $at,rs,rt
  beq   $at,$0,label
bge rs,Imm,label Branch greater than or equal to
If (RF[Rs] >= Imm) then branch to Label

  li    $at,Imm
  slt   $at,rs,$at
  beq   $at,$0,label
bgeu rs,rt,label Branch greater than or equal to (Unsigned)
If (RF[Rs] >= Rf[Rt]) then branch to Label

  sltu  $at,rs,rt
  beq   $at,$0,label
bgeu rs,Uimm,label Branch greater than or equal to (Unsigned)
If (RF[Rs] >= Imm) then branch to Label

  li    $at,Uimm
  sltu  $at,rs,$at
  beq   $at,$0,label
bgez rs,label Branch Greater than or Equal to Zero
If (RF[Rs] >= RF[0]) then PC = PC + Imm<< 2
i
bgezal rs,label Branch Greater than or Equal to Zero And Link
If ( RF[Rs] >= RF[0] ) then {RF[$ra] = PC; PC = PC + Imm<< 2 }
i
bgt rs,rt,label Branch greater than
If (RF[Rs] > Rf[Rt]) then branch to Label

  slt   $at,rt,rs
  bne   $at,$0,label
bgt rs,Imm,label Branch greater than
If (RF[Rs] > Imm) then branch to Label

  li    $at,Imm
  slt   $at,$at,rs
  bne   $at,$0,label
bgtu rs,rt,label Branch greater than (Unsigned)
If (RF[Rs] > Rf[Rt]) then branch to Label

  sltu  $at,rt,rs
  bne   $at,$0,label
bgtu rs,Uimm,label Branch greater than (Unsigned)
If (RF[Rs] > Imm) then branch to Label

  li    $at,Uimm
  sltu  $at,$at,rs
  bne   $at,$0,label
bgtz rs,label Branch Greater Than Zero
If (RF[Rs] > RF[0] ) then PC = PC + Imm<< 2
i
ble rs,rt,label Branch less than or equal to
If (RF[Rs] <= Rf[Rt]) then branch to Label

  slt   $at,rt,rs
  beq   $at,$0,label
ble rs,Imm,label Branch less than or equal to
If (RF[Rs] <= Imm) then branch to Label

  li    $at,Imm
  slt   $at,$at,rs
  beq   $at,$0,label
bleu rs,rt,label Branch less than or equal to (Unsigned)
If (RF[Rs] <= Rf[Rt]) then branch to Label

  sltu  $at,rt,rs
  beq   $at,$0,label
bleu rs,Uimm,label Branch less than or equal to (Unsigned)
If (RF[Rs] <= Imm) then branch to Label

  li    $at,Uimm
  sltu  $at,$at,rs
  beq   $at,$0,label
blez rs,label Branch Less than or Equal to Zero
If (RF[Rs] <= RF[0]) then PC = PC + Imm<< 2
i
blt rs,rt,label Branch less than
If (RF[Rs] < Rf[Rt]) then branch to Label

  slt   $at,rs,rt
  bne   $at,$0,label
blt rs,Imm,label Branch less than
If (RF[Rs] < Imm) then branch to Label

  li    $at,Imm
  slt   $at,rs,$at
  bne   $at,$0,label
bltu rs,rt,label Branch less than (Unsigned)
If (RF[Rs] < Rf[Rt]) then branch to Label

  sltu  $at,rs,rt
  bne   $at,$0,label
bltu rs,Uimm,label Branch less than (Unsigned)
If (RF[Rs] < Imm) then branch to Label

  li    $at,Uimm
  sltu  $at,rs,$at
  bne   $at,$0,label
bltz rs,label Branch Less Than Zero
If RF[Rs] < RF[0] then PC = PC + Imm<< 2
i
bltzal rs,label Branch Less Than Zero And Link
If ( RF[Rs] < RF[0] ) then {RF[$ra] = PC; PC = PC + Imm<< 2 }
i
bne rs,rt,label Branch Not Equal
If RF[Rs] != RF[Rt] then PC = PC + Imm<< 2
i
bne rs,Imm,label Branch not equal
If (RF[Rs] != Imm) then branch to Label

  li    $at,Imm
  bne   rs,$at,label
bnez rs,label Branch Not Equal to Zero
alias for bne rs,$0,label
If RF[Rs] != 0 then PC = PC + Imm<< 2
i
break Bcode pause execution b
break Icode pause execution b
break pause execution
alias for break 0
b
c.eq.d ds,dt Compare Equal Doubles:
ControlRf[31].condition_bit = FpRf[dt] == FpRf[ds] && !(un(FpRf[dt]) || un(FpRf[ds]))
r
c.eq.s fs,ft Compare Equal Singles:
ControlRf[31].condition_bit = FpRf[ft] == FpRf[fs] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.f.d ds,dt Compare False:
ControlRf[31].condition_bit = 0
r
c.f.s fs,ft Compare False:
ControlRf[31].condition_bit = 0
r
c.le.d ds,dt Compare Less Than or Equal:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] <= FpRf[dt] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.le.s fs,ft Compare Less Than or Equal:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] <= FpRf[ft] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.lt.d ds,dt Compare Less Than:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] < FpRf[dt] && !(un(FpRf[dt]) || un(FpRf[ds]))
r
c.lt.s fs,ft Compare Less Than:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] < FpRf[ft] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.nge.d ds,dt Compare Not Greater or Equal, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] < FpRf[dt] || (un(FpRf[ds]) || un(FpRf[dt]))
r
c.nge.s fs,ft Compare Not Greater or Equal, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] < FpRf[ft] || (un(FpRf[fs]) || un(FpRf[ft]))
r
c.ngl.d ds,dt Compare Not Greater or Less Than, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] == FpRf[dt] || (un(FpRf[ds]) || un(FpRf[dt]))
r
c.ngl.s fs,ft Compare Not Greater or Less Than, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] == FpRf[ft] || (un(FpRf[fs]) || un(FpRf[ft]))
r
c.ngle.d ds,dt Compare Not Greater, Less, or Equal (only true if unordered):
exception if unordered;
ControlRf[31].condition_bit = (un(FpRf[dt]) || un(FpRf[ds]))
r
c.ngle.s fs,ft Compare Not Greater, Less, or Equal (only true if unordered):
exception if unordered;
ControlRf[31].condition_bit = (un(FpRf[ft]) || un(FpRf[fs]))
r
c.ngt.d ds,dt Compare Not Greater Than, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] <= FpRf[dt] || (un(FpRf[fs]) || un(FpRf[ft]))
r
c.ngt.s fs,ft Compare Not Greater Than, or unordered:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] <= FpRf[ft] || (un(FpRf[fs]) || un(FpRf[ft]))
r
c.ole.d ds,dt Compare Ordered Less Than Or Equal:
ControlRf[31].condition_bit = FpRf[ds] <= FpRf[dt] && !(un(FpRf[dt]) || un(FpRf[ds]))
r
c.ole.s fs,ft Compare Ordered Less Than Or Equal:
ControlRf[31].condition_bit = FpRf[fs] <= FpRf[ft] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.olt.d ds,dt Compare Ordered Less Than:
ControlRf[31].condition_bit = FpRf[ds] < FpRf[dt] && !(un(FpRf[dt]) || un(FpRf[ds]))
r
c.olt.s fs,ft Compare Ordered Less Than:
ControlRf[31].condition_bit = FpRf[fs] < FpRf[ft] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.seq.d ds,dt Compare Signaling Equal:
exception if unordered;
ControlRf[31].condition_bit = FpRf[ds] == FpRf[dt] && !(un(FpRf[dt]) || un(FpRf[ds]))
r
c.seq.s fs,ft Compare Signaling Equal:
exception if unordered;
ControlRf[31].condition_bit = FpRf[fs] == FpRf[ft] && !(un(FpRf[ft]) || un(FpRf[fs]))
r
c.sf.d ds,dt Compare Signaling False:
exception if unordered;
ControlRf[31].condition_bit = 0
r
c.sf.s fs,ft Compare Signaling False:
exception if unordered;
ControlRf[31].condition_bit = 0
r
c.ueq.d ds,dt Compare Unordered/Equal Doubles:
ControlRf[31].condition_bit = (FpRf[dt] == FpRf[ds]) || (un(FpRf[dt]) || un(FpRf[ds]))
r
c.ueq.s fs,ft Compare Unordered/Equal Singles:
ControlRf[31].condition_bit = (FpRf[ft] == FpRf[fs]) || (un(FpRf[ft]) || un(FpRf[fs]))
r
c.ule.d ds,dt Compare Unordered Less Than Or Equal:
ControlRf[31].condition_bit = FpRf[ds] <= FpRf[dt] || (un(FpRf[dt]) || un(FpRf[ds]))
r
c.ule.s fs,ft Compare Unordered Less Than Or Equal:
ControlRf[31].condition_bit = FpRf[fs] <= FpRf[ft] || (un(FpRf[ft]) || un(FpRf[fs]))
r
c.ult.d ds,dt Compare Unordered Less Than:
ControlRf[31].condition_bit = FpRf[ds] < FpRf[dt] || (un(FpRf[dt]) || un(FpRf[ds]))
r
c.ult.s fs,ft Compare Unordered Less Than:
ControlRf[31].condition_bit = FpRf[fs] < FpRf[ft] || (un(FpRf[ft]) || un(FpRf[fs]))
r
c.un.d ds,dt Compare Unordered Doubles:
ControlRf[31].condition_bit = un(FpRf[dt]) || un(FpRf[ds])
r
c.un.s fs,ft Compare Unordered Singles:
ControlRf[31].condition_bit = un(FpRf[ft]) || un(FpRf[fs])
r
ceil.d dd,ds ceiling double and convert to integer:
FpRf[dd] = (int) ceil(FpRf[ds])
r
ceil.s fd,fs ceiling single and convert to integer:
FpRf[fd] = (int) ceil(FpRf[fs])
r
ceil.w.d dd,ds ceiling double:
FpRf[dd] = ceil(FpRf[ds])
r
ceil.w.s fd,fs ceiling single:
FpRf[fd] = ceil(FpRf[fs])
r
cfc1 rt,Fs move control word from cop1:
Rf[rt] = ControlRf[Cs]
r
cos.d dd,ds cosine double:
FpRf[dd] = cos(FpRf[ds])
r
cos.s fd,fs cosine single:
FpRf[fd] = cos(FpRf[fs])
r
cosh.d dd,ds hyperbolic cosine double:
FpRf[dd] = cosh(FpRf[ds])
r
cosh.s fd,fs hyperbolic cosine single:
FpRf[fd] = cosh(FpRf[fs])
r
ctc1 rt,Fs move control word to cop1:
ControlRf[Cs] = Rf[rt]
Backwards Arguments!
r
cvt.d.s dd,fs Convert single to double:
FpRf[dd] = (double) FpRf[fs]
r
cvt.d.w dd,fs Convert integer to double:
FpRf[dd] = (double) FpRf[fs]
r
cvt.s.d fd,ds Convert double to single:
FpRf[fd] = (float) FpRf[ds]
r
cvt.s.w fd,fs Convert integer to single:
FpRf[fd] = (float) FpRf[fs]
r
cvt.w.d fd,ds Convert double to integer:
FpRf[fd] = (int) FpRf[ds]
r
cvt.w.s fd,fs Convert single to integer:
FpRf[fd] = (int) FpRf[fs]
r
div rs,rt Divide (signed)
Low = Quotient ( RF[Rs] / RF[Rt] );
High = Remainder ( RF[Rs] / RF[Rt] )
r
div rd,rs,rt Divide:
Rf[rd] = Rf[rs]/Rf[rt]
(break on divide by zero)

Delay Slot OffDelay Slot On
  bne   rt,$0,08f
  break
08:
  div   rs,rt
  mflo  rd
  bne   rt,$0,08f
  nop
  break
08:
  div   rs,rt
  mflo  rd
div rd,rs,Imm Divide:
Rf[rd] = Rf[rs]/Imm

  li    $at,Imm
  div   rs,$at
  mflo  rd
div rd,Imm Divide:
Rf[rd] = Rf[rd]/Imm

  li    $at,Imm
  div   rd,$at
  mflo  rd
div.d dd,ds,dt Divide double:
FpRf[dd] = FpRf[ds] / FpRf[dt]
r
div.s fd,fs,ft Divide single:
FpRf[fd] = FpRf[fs] / FpRf[ft]
r
divnz rd,rs,rt Divide:
Rf[rd] = Rf[rs]/Rf[rt]

  div   rs,rt
  mflo  rd
divu rs,rt Divide Unsigned
Low = Quotient ( RF[Rs] / RF[Rt] );
High = Remainder ( RF[Rs] / RF[Rt] )
r
divu rd,rs,rt Divide unsigned:
Rf[rd] = Rf[rs] / Rf[rt]
(break on divide by zero)

Delay Slot OffDelay Slot On
  bne   rt,$0,08f
  break
08:
  divu  rs,rt
  mflo  rd
  bne   rt,$0,08f
  nop
  break
08:
  divu  rs,rt
  mflo  rd
divu rd,rs,Uimm Divide unsigned:
Rf[rd] = Rf[rs] / Imm

  li    $at,Uimm
  divu  rs,$at
  mflo  rd
divu rd,Uimm Divide unsigned:
Rf[rd] = Rf[rd] / Imm

  li    $at,Uimm
  divu  rd,$at
  mflo  rd
exp.d dd,ds e to the x power double:
FpRf[dd] = exp(FpRf[ds])
r
exp.s fd,fs e to the x power single:
FpRf[fd] = exp(FpRf[fs])
r
floor.d dd,ds floor double and convert to integer:
FpRf[dd] = (int) floor(FpRf[ds])
r
floor.s fd,fs floor single and convert to integer:
FpRf[fd] = (int) floor(FpRf[fs])
r
floor.w.d dd,ds floor double:
FpRf[dd] = floor(FpRf[ds])
r
floor.w.s fd,fs floor single:
FpRf[fd] = floor(FpRf[fs])
r
j label Jump
PC = PC(31:28) | Imm<< 2
j
jal label Jump And Link
RF[$ra] = PC;
PC = PC(31:28) | Imm<< 2
j
jalr rd,rs Jump And Link Register
RF[Rd] = PC;
PC = RF[Rs]
r
jalr rs Jump And Link Register
alias for jalr $ra,rs
$ra = PC;
PC = RF[Rs]
r
jr rs Jump Register
PC = RF[Rs]
r
l.d dd,laddress Load double:
FpRf[dd] = laddress

  lui   $at,laddress&0x8000<<1+laddress>>16
  lwc1  dd,laddress&0xFFFF($at)
  lwc1  dd+1,laddress&0xFFFF+4($at)
l.d dd,imm(rs) Load double:
FpRf[dd] = Mem[RF[Rs] + Offset]

  lwc1  dd,imm(rs)
  lwc1  dd+1,imm+4(rs)
l.s ft,oimm(rs) load word to cop1:
FpRf[ft] = Mem[Rf[rs] + Offset]
i
l.s fd,laddress Load single:
FpRf[fd] = laddress

  lui   $at,laddress&0x8000<<1+laddress>>16
  lwc1  fd,laddress&0xFFFF($at)
la rd,laddress Load Address into Rf[rd]

  lui   rd,laddress>>16
  ori   rd,rd,laddress&0xffff
lb rt,oimm(rs) Load Byte
RF[Rt] = Mem[RF[Rs] + Offset]
i
lb rd,laddress Load byte (low 8 bits):
Rf[rd] = Mem[laddress]

  lui   $at,laddress&0x8000<<1+laddress>>16
  lb    rd,laddress&0xFFFF($at)
lbu rt,oimm(rs) Load Byte Unsigned
RF[Rt] = Mem[RF[Rs] + Offset]
i
lbu rd,laddress Load byte unsigned (low 8 bits):
Rf[rd] = Mem[laddress]

  lui   $at,laddress&0x8000<<1+laddress>>16
  lbu   rd,laddress&0xFFFF($at)
lh rt,oimm(rs) Load Half
RF[Rt] = Mem[RF[Rs] + Offset]
i
lh rd,laddress Load half (low 16 bits):
Rf[rd] = Mem[laddress]

  lui   $at,laddress&0x8000<<1+laddress>>16
  lh    rd,laddress&0xFFFF($at)
lhu rt,oimm(rs) Load Half Unsigned
RF[Rt] = Mem[RF[Rs] + Offset]
i
lhu rd,laddress Load half unsigned (low 16 bits):
Rf[rd] = Mem[laddress]

  lui   $at,laddress&0x8000<<1+laddress>>16
  lhu   rd,laddress&0xFFFF($at)
li rd,imm Load Immediate into Rf[rd] variable size, no forward reference.
This macro is used when the high 16 bits of imm are zero.

ori   rd,$0,imm
li rd,imm Load Immediate into Rf[rd] variable size, no forward reference.
This macro is used when the low 16 bits of imm are zero.

lui   rd,imm
li rd,imm Load Immediate into Rf[rd] variable size, no forward reference.
This macro is used when the high 17 bits of imm are 1 (it's a small negative number).

addi   rd,$0,imm
li rd,imm Load Immediate into Rf[rd] variable size, no forward reference.
This macro is used when none of the three other forms can be used.

lui   rd,imm
ori   rd,$0,imm
ll rt,oimm(rs) Load Linked
Unimplemented
i
ln.d dd,ds natural log double:
FpRf[dd] = ln(FpRf[ds])
r
ln.s fd,fs natural log single:
FpRf[fd] = ln(FpRf[fs])
r
lui rt,uimm Load Upper Immediate
RF[Rt] = Imm<<16
i
lw rt,oimm(rs) Load Word
RF[Rt] = Mem[RF[Rs] + Offset]
i
lw rd,laddress Load word (full 32 bits):
Rf[rd] = Mem[laddress]

  lui   $at,laddress&0x8000<<1+laddress>>16
  lw    rd,laddress&0xFFFF($at)
lwc1 ft,oimm(rs) load word to cop1:
FpRf[ft] = Mem[Rf[rs] + Offset]
i
lwc2 rt,oimm(rs) load word to cop2:
Unimplemented
i
lwc3 rt,oimm(rs) load word to cop3:
Unimplemented
i
lwl rt,oimm(rs) Load Word Left
RF[Rt] = Mem[RF[Rs] + Offset]
i
lwr rt,oimm(rs) Load Word Right
RF[Rt] = Mem[RF[Rs] + Offset]
i
mfc0 rt,Cd Move From Coprocessor0:
Rf[rt] = CP0Rf[cd]
r
mfc1 rt,fs move from cop1:
Rf[rt] = FpRf[fs]
r
mfhi rd Move From Hi
RF[Rd] = HIGH
r
mflo rd Move From Low
RF[Rd] = LOW
r
mov rd,rs Move
alias for addu rd,rs,$0
RF[Rd] = RF[Rs]
r
mov.d dd,ds Copy double value:
FpRf[dd] = FpRf[ds]
r
mov.s fd,fs Copy single value:
FpRf[fd] = FpRf[fs]
r
move rd,rs Move
alias for addu rd,rs,$0
RF[Rd] = RF[Rs]
r
mtc0 rt,Cd Move To Coprocessor0:
CP0Rf[cd] = Rf[rt]
Backwards Arguments!
r
mtc1 rt,fs move to cop1:
FpRf[fs] = Rf[rt]
Backwards Arguments!
r
mthi rs Move To Hi
HIGH = RF[Rs]
r
mtlo rs Move To Low
LOW = RF[Rs]
r
mul rd,rs,rt Multiply:
Rf[rd] = Rf[rs] * Rf[rt]

  mult  rs,rt
  mflo  rd
mul rd,rs,Imm Multiply:
Rf[rd] = Rf[rs]*Imm

  li    $at,Imm
  mult  rs,$at
  mflo  rd
mul rd,Imm Multiply:
Rf[rd] = Rf[rd]*Imm

  li    $at,Imm
  mult  rd,$at
  mflo  rd
mul.d dd,ds,dt Multiply double:
FpRf[dd] = FpRf[ds] * FpRf[dt]
r
mul.s fd,fs,ft Multiply single:
FpRf[fd] = FpRf[fs] * FpRf[ft]
r
mulo rd,rs,rt Multiply, break on overflow

Delay Slot OffDelay Slot On
  mult  rs,rt
  mfhi  $at
  mflo  rd
  sra   rd,rd,31
  beq   $at,rd,08f
  break
08:
  mflo  rd
  mult  rs,rt
  mfhi  $at
  mflo  rd
  sra   rd,rd,31
  beq   $at,rd,08f
  mflo  rd
  break
08:
mulou rd,rs,rt Multiply unsigned, break on overflow

Delay Slot OffDelay Slot On
  multu rs,rt
  mfhi  $at
  beq   $at,$0,08f
  break
08:
  mflo  rd
  multu rs,rt
  mfhi  $at
  beq   $at,$0,08f
  mflo  rd
  break
08:
mult rs,rt Multiply (signed)
High |Low = RF[Rs] * RF[Rt]
r
multu rs,rt Multiply Unsigned
High |Low = RF[Rs] * RF[Rt]
r
mulu rd,rs,rt Multiply unsigned:
Rf[rd] = Rf[rs] * Rf[rt]

  multu rs,rt
  mflo  rd
mulu rd,rs,Uimm Multiply unsigned:
Rf[rd] = Rf[rs] * Imm

  li    $at,Uimm
  multu rs,$at
  mflo  rd
mulu rd,Uimm Multiply unsigned:
Rf[rd] = Rf[rd] * Imm

  li    $at,Uimm
  multu rd,$at
  mflo  rd
neg rd,rt Negate
alias for sub rd,$0,rt
RF[Rd] = -RF[Rt]
r
neg.d dd,ds Negate double value:
FpRf[dd] = -FpRf[ds]
r
neg.s fd,fs Negate single value:
FpRf[fd] = -FpRf[fs]
r
negu rd,rt Negate
alias for subu rd,$0,rt
RF[Rd] = -RF[Rt]
r
nop no operation
alias for sll $0,$0,0
r
nor rd,rs,rt Bitwise Nor
RF[Rd] = !(RF[Rs] | RF[Rt])
r
not rd,rs Boolean Not
alias for nor rd,rs,$0
RF[Rd] = !(RF[Rs] | 0)
r
or rd,rs,rt Bitwise Or
RF[Rd] = RF[Rs] | RF[Rt]
r
ori rt,rs,uimm Bitwise Or Immediate
RF[Rt] = RF[Rs] | Imm
i
ori rt,imm Or immediate:
Rf[rt] = Rf[rt] | imm

  ori   rt,rt,imm
rem rd,rs,rt Remainder:
Rf[rd] = Rf[rs] % Rf[rt]

Delay Slot OffDelay Slot On
  bne   rt,$0,08f
  break
08:
  div   rs,rt
  mfhi  rd
  bne   rt,$0,08f
  nop
  break
08:
  div   rs,rt
  mfhi  rd
rem rd,rs,Imm Remainder:
Rf[rd] = Rf[rs] % Imm

  li    $at,Imm
  div   rs,$at
  mfhi  rd
rem rd,Imm Remainder:
Rf[rd] = Rf[rd] % Imm

  li    $at,Imm
  div   rd,$at
  mfhi  rd
remu rd,rs,rt Remainder unsigned:
Rf[rd] = Rf[rs] % Rf[rt]

Delay Slot OffDelay Slot On
  bne   rt,$0,08f
  break
08:
  divu  rs,rt
  mfhi  rd
  bne   rt,$0,08f
  nop
  break
08:
  divu  rs,rt
  mfhi  rd
remu rd,rs,Uimm Remainder unsigned:
Rf[rd] = Rf[rs] % Imm

  li    $at,Uimm
  divu  rs,$at
  mfhi  rd
remu rd,Uimm Remainder unsigned:
Rf[rd] = Rf[rd] % Imm

  li    $at,Uimm
  divu  rd,$at
  mfhi  rd
rfe Restore From Exception
restores the status register to its value before the last exception occurred.
r
rol rd,rt,rs Rotate left

  subu  $at,$0,rs
  srlv  $at,rt,$at
  sllv  rd,rt,rs
  or    rd,rd,$at
rol rd,rt,sn Rotate left

  srl   $at,rt,-sn
  sll   rd,rt,sn
  or    rd,rd,$at
ror rd,rt,rs Rotate right

  subu  $at,$0,rs
  sllv  $at,rt,$at
  srlv  rd,rt,rs
  or    rd,rd,$at
ror rd,rt,sn Rotate right

  sll   $at,rt,-sn
  srl   rd,rt,sn
  or    rd,rd,$at
round.d dd,ds round double and convert to integer:
FpRf[dd] = (int) round(FpRf[ds])
r
round.s fd,fs round single and convert to integer:
FpRf[fd] = (int) round(FpRf[fs])
r
round.w.d dd,ds round double:
FpRf[dd] = round(FpRf[ds])
r
round.w.s fd,fs round single:
FpRf[fd] = round(FpRf[fs])
r
s.d dd,laddress Store double:
Mem[laddress] = FpRf[dd]
Backwards Arguments!

  lui   $at,laddress&0x8000<<1+laddress>>16
  swc1  dd,laddress&0xFFFF($at)
  swc1  dd+1,laddress&0xFFFF+4($at)
s.d dd,oimm(rs) Store double:
Mem[RF[Rs] + Offset] = FpRf[dd]
Backwards Arguments!

  swc1  dd,oimm(rs)
  swc1  dd+1,oimm+4(rs)
s.s ft,oimm(rs) store word from cop1:
Mem[Rf[rs] + Offset] = FpRf[ft]
Backwards Arguments!
i
s.s fd,laddress Store single:
Mem[laddress] = FpRf[fd]
Backwards Arguments!

  lui   $at,laddress&0x8000<<1+laddress>>16
  swc1  fd,laddress&0xFFFF($at)
sb rt,oimm(rs) Store Byte:
Mem[RF[Rs] + Offset] = RF[Rt]
Backwards Arguments!
i
sb rd,laddress Store byte (low 8 bits):
Mem[laddress] = Rf[rd]
Backwards Arguments!

  lui   $at,laddress&0x8000<<1+laddress>>16
  sb    rd,laddress&0xFFFF($at)
sc rt,oimm(rs) Unimplemented i
seq rd,rs,rt Set if equal:
Rf[rd] = Rf[rs] == Rf[rt]

  subu  $at,rs,rt
  sltiu rd,$at,1
sge rd,rs,rt Set greater than:
Rf[rd] = Rf[rs] > Rf[rt]

  slt   rd,rs,rt
  slti  rd,rd,1
sgeu rd,rs,rt Set greater than unsigned:
Rf[rd] = Rf[rs] > Rf[rt]

  sltu  rd,rs,rt
  slti  rd,rd,1
sgt rd,rt,rs Set Greater Than
alias for slt rd,rs,rt
if (RF[Rt] > RF[Rs] ) then RF[Rd] =1 else RF[Rd] = 0
r
sgtu rd,rt,rs Set Greater Than Unsigned
alias for sltu rd,rs,rt
if (RF[Rt] > RF[Rs] ) then RF[Rd] =1 else RF[Rd] = 0
r
sh rt,oimm(rs) Store Half:
Mem[RF[Rs] + Offset] = RF[Rt]
Backwards Arguments!
i
sh rd,laddress Store half (low 16 bits):
Mem[laddress] = Rf[rd]
Backwards Arguments!

  lui   $at,laddress&0x8000<<1+laddress>>16
  sh    rd,laddress&0xFFFF($at)
sin.d dd,ds sine double:
FpRf[dd] = sin(FpRf[ds])
r
sin.s fd,fs sine single:
FpRf[fd] = sin(FpRf[fs])
r
sinh.d dd,ds hyperbolic sine double:
FpRf[dd] = sinh(FpRf[ds])
r
sinh.s fd,fs hyperbolic sine single:
FpRf[fd] = sinh(FpRf[fs])
r
sle rd,rs,rt Set less than or equal:
Rf[rd] = Rf[rs] <= Rf[rt]

  slt   rd,rt,rs
  slti  rd,rd,1
sleu rd,rs,rt Set less than or equal unsigned:
Rf[rd] = Rf[rs] <= Rf[rt]

  sltu  rd,rt,rs
  slti  rd,rd,1
sll rd,rt,sn Shift Left Logical (immediate)
RF[Rd] = RF[Rt] << n
r
sll rd,rt,rs Shift Left Logical
alias for sllv rd,rt,rs
RF[Rd] = RF[Rt] << RF[Rs] amount
r
sllv rd,rt,rs Shift Left Logical Variable
RF[Rd] = RF[Rt] << RF[Rs] amount
r
slt rd,rs,rt Set Less Than
if (RF[Rs] < RF[Rt] ) then RF[Rd] =1 else RF[Rd] = 0
r
slti rt,rs,imm Set Less Than Immediate
if (RF[Rs] < Imm) then RF[Rt] = 1 else RF[Rt] = 0
i
sltiu rt,rs,imm Set Less Than Immediate Unsigned
if (RF[Rs] < Imm) then RF[Rt] = 1 else RF[Rt] = 0
i
sltu rd,rs,rt Set Less Than Unsigned
if (RF[Rs] < RF[Rt] ) then RF[Rd] =1 else RF[Rd] = 0
r
sne rd,rs,rt Set if not equal:
Rf[rd] = Rf[rs] != Rf[rt]

  subu  $at,rs,rt
  sltu  rd,$0,$at
sqrt.d dd,ds square root double:
FpRf[dd] = sqrt(FpRf[ds])
r
sqrt.s fd,fs square root single:
FpRf[fd] = sqrt(FpRf[fs])
r
sra rd,rt,sn Shift Right Arithmetic (immediate)
RF[Rd] = RF[Rt] >> n (sign-extend)
r
sra rd,rt,rs Shift Right Arithmetic
alias for srav rd,rt,rs
RF[Rd] = RF[Rt] >> RF[Rs] amount (sign-extend)
r
srav rd,rt,rs Shift Right Arithmetic Variable
RF[Rd] = RF[Rt] >> RF[Rs] amount (sign-extend)
r
srl rd,rt,sn Shift Right Logical
RF[Rd] = RF[Rt] >> n (no sign extension)
r
srl rd,rt,rs Shift Right Logical
alias for srlv rd,rt,rs
RF[Rd] = RF[Rt] >> RF[Rs] amount (no sign extension)
r
srlv rd,rt,rs Shift Right Logical Variable
RF[Rd] = RF[Rt] >> RF[Rs] amount (no sign extension)
r
sub rd,rs,rt Subtract
RF[Rd] = RF[Rs] - RF[Rt]
r
sub rt,rs,imm Subtract:
Rf[rt] = Rf[rs] - imm

  addi  rt,rs,-imm
sub rt,imm Subtract:
Rf[rt] = Rf[rt] - imm

  addi  rt,rt,-imm
sub.d dd,ds,dt Subtract double:
FpRf[dd] = FpRf[ds] - FpRf[dt]
r
sub.s fd,fs,ft Subtract single:
FpRf[fd] = FpRf[fs] - FpRf[ft]
r
subu rd,rs,rt Subtract Unsigned
RF[Rd] = RF[Rs] - RF[Rt]
r
subu rt,imm Subtract unsigned:
Rf[rt] = Rf[rt] - imm

  addiu rt,rt,-imm
subu rt,rs,imm Subtract unsigned:
Rf[rt] = Rf[rs] - imm

  addiu rt,rs,-imm
sw rt,oimm(rs) Store Word:
Mem[RF[Rs] + Offset] = RF[Rt]
Backwards Arguments!
i
sw rd,laddress Store word (full 32 bits):
Mem[laddress] = Rf[rd]
Backwards Arguments!

  lui   $at,laddress&0x8000<<1+laddress>>16
  sw    rd,laddress&0xFFFF($at)
swc1 ft,oimm(rs) store word from cop1:
Mem[Rf[rs] + Offset] = FpRf[ft]
Backwards Arguments!
i
swc2 rt,oimm(rs) store word from cop2:
Mem[Rf[rs] + Offset] = Unimplemented
i
swc3 rt,oimm(rs) store word from cop3:
Mem[Rf[rs] + Offset] = Unimplemented
i
swl rt,oimm(rs) Store Word Left (1-4 bytes, depending on offset):
Mem[RF[Rs] + Offset] = RF[Rt]
Backwards Arguments!
i
swr rt,oimm(rs) Store Word Right (1-4 bytes, depending on offset):
Mem[RF[Rs] + Offset] = RF[Rt]
Backwards Arguments!
i
syscall call syscall in $v0 b
syscall Scode call syscall in argument b
syscall Icode call syscall in argument b
tan.d dd,ds tangent double:
FpRf[dd] = tan(FpRf[ds])
r
tan.s fd,fs tangent single:
FpRf[fd] = tan(FpRf[fs])
r
tanh.d dd,ds hyperbolic tangent double:
FpRf[dd] = tanh(FpRf[ds])
r
tanh.s fd,fs hyperbolic tangent single:
FpRf[fd] = tanh(FpRf[fs])
r
tlbp Probe TLB For Matching Entry
Unimplemented
r
tlbr Read Indexed TLB Entry
Unimplemented
r
tlbwi Write Indexed TLB Entry
Unimplemented
r
tlbwr Write Random TLB Entry
Unimplemented
r
trunc.d dd,ds truncate double and convert to integer:
FpRf[dd] = (int) trunc(FpRf[ds])
r
trunc.s fd,fs truncate single and convert to integer:
FpRf[fd] = (int) trunc(FpRf[fs])
r
trunc.w.d dd,ds truncate double:
FpRf[dd] = trunc(FpRf[ds])
r
trunc.w.s fd,fs truncate single:
FpRf[fd] = trunc(FpRf[fs])
r
ulh rt,oimm(rs)

  lb    rt,oimm+1(rs)
  lbu   $at,oimm(rs)
  sll   rt,rt,8
  or    rt,rt,$at
ulhu rt,oimm(rs)

  lbu   rt,oimm+1(rs)
  lbu   $at,oimm(rs)
  sll   rt,rt,8
  or    rt,rt,$at
ulw rt,oimm(rs)

  lwl   rt,oimm+3(rs)
  lwr   rt,oimm(rs)
ush rt,oimm(rs)

  sb    rt,oimm(rs)
  srl   $at,rt,8
  sb    $at,oimm+1(rs)
usw rt,oimm(rs)

  swl   rt,oimm+3(rs)
  swr   rt,oimm(rs)
xor rd,rs,rt Bitwise Xor
RF[Rd] = RF[Rs] ^ RF[Rt]
r
xori rt,rs,uimm Bitwise Xor Immediate
RF[Rt] = RF[Rs] ^ Imm
i
xori rt,imm Xor immediate:
Rf[rt] = Rf[rt] ^ imm

  xori  rt,rt,imm