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
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 Source Code Panel
- The Register Panel
- The Message Log Panel
- The Memory Panel
By default, only the Source 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, and the assembly results should show up in the Listing tab of the source 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. Considerable effort has been put into fuzz-testing assembler version 3.1; the developers believe that it is very unlikely that this assembler will crash. If the assembler does crash, 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 assembler version 3.1 to crash, please alert the developers!
Running Code
You can step through your program one instruction at a time using the 'Run > Step F10' command.
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.
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 battery to emulate these.
You will not be able to run your program if you did not define a .text
or .code
section, or did not specify a global main:
label, even if it assembled correctly.
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, hit 'Run > Reset Shift-F8' first, otherwise your program may begin in the wrong state.
Breakpoints
To set breakpoints, go to the listing section, highlight a memory address in the .code
/.text
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.
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:
- 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.
- 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.
Considerable effort has been put into fuzz-testing the assembler at %ASM%
; the developers believe that it is very unlikely that this assembler will crash. If you are able to get this assembler (version 3.1, not 3.0) to crash, please alert the developers!
The assembler should have produced a few files when it assembled hello_world.asm
:
- 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. - 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. - A listing file,
hello_world.lst
. This file shows a direct mapping between the lines of assembly code in thehello_world.asm
and the machine code written tohello_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:
- The memory address that the Program Counter is currently pointed to. The
.text
section of MIPS programs usually begins at 0x400000, and that's where most MIPS programs start. If you wrote a MIPS program with amain
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. - The 32-bit integer stored at this memory address. Since we are in the
.text
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.text
section, so the MIPSym simulator doesn't try to interpret data as MIPS instructions! - The assembly instruction that MIPSym will try to run when it sees the 32-bit integer at this address.
- The arguments to the MIPS instruction at this address, written in hexadecimal.
- 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:
- 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.
- 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.
- 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)
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
pseudocode at the top of any program. Programs written for SPIM must be modified by adding this pseudocode 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' pseudocode 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' pseudocode 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:
- the label field
- the opcode/pseudo-op field
- the arguments field
This has two very important consequences that are common pain points for new users of MIPSym:
Lines of code without a label must be indented
# Valid code: add $t0,$t0,$t0 # Not valid: add $t0,$t0,$t0
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: 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
Note that the MIPSym assembler evaluates each value in an expression as an integer, not as floating point data.
# Valid code:
addi $t0,$0,3.9+3.9 # stores 3+3, or 6, in $t0
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 identifiers to registers, as long as your identifier begins with a '$':
first_year_of_MIPS = 1986
$year = $t0
li $year,first_year_of_MIPS # load 1986 into $t0
The value attached to the identifier is assigned during assembly, and cannot be reassigned during runtime.
The MIPSym assembler stores these values as integers. If you attempt to assign a floating point value to an identifier, the value will be truncated.
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
pseudocode, but let's see what happens when we use the .byte
pseudocode.
five_As: .byte 65: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 65: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
MIPSym does not currently support unicode. It interprets all ASCII characters as being on IBM code page 437. This 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 bytes, 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
.text
li $a0,'\x7F
Please note that you cannot include raw control characters (ASCII values 0-31 and 127) 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.
If you absolutely must use UTF-8 text in your programs, 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 pseudocodes, opcodes, or registers to be reserved words. This means that you may use labels with the same names as opcodes and pseudocodes. The assembler can decide whether an identifier should be interpreted as a label or an opcode/pseudocode 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 pseudocodes 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 pseudocodes. The highlighter is meant to run fast and to help make your code more readable, not to parse nonsense like this.
Syscalls, Register Names, Pseudocodes, 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 pseudocodes (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.
Pseudocodes (aka assembler directives)
MIPSym handles a subset of the pseudocodes 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 |
.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 |
.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 |
.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. The optional 'symbol' argument defines inheritance from 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 more concise and readable.
# Valid code (SPIM syntax):
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 = 31
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 constant integer value. It can be a number, an alias, or a mathematical expression.
- label: This is exactly the same as an '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.
- 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 misaligned registers: this is undefined behavior! add.d $f6,$f8,$f9
cd/cs/ct: These symbols denote registers in Coprocessor 0, the System Control Processor.
- Cd/Cs/Ct: These symbols denote control word registers in Coprocessor 1 ($FCR0 & $FCR31).
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,imm(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 'imm' 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 'imm' bytes away from that address, and copies the byte at that location into Rt.
Note that any instruction that takes the arguments 'rt,imm(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,imm | 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 | icode | pause execution | b |
break | rcode | 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,imm(rs) | Load Byte RF[Rt] = Mem[RF[Rs] + Offset] | i |
lbu | rt,imm(rs) | Load Byte Unsigned RF[Rt] = Mem[RF[Rs] + Offset] | i |
lh | rt,imm(rs) | Load Half RF[Rt] = Mem[RF[Rs] + Offset] | i |
lhu | rt,imm(rs) | Load Half Unsigned RF[Rt] = Mem[RF[Rs] + Offset] | i |
ll | rt,imm(rs) | Load Linked Unimplemented | i |
lui | rt,imm | Load Upper Immediate RF[Rt] = Imm<<16 | i |
lw | rt,imm(rs) | Load Word RF[Rt] = Mem[RF[Rs] + Offset] | i |
lwl | rt,imm(rs) | Load Word Left RF[Rt] = Mem[RF[Rs] + Offset] | i |
lwr | rt,imm(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,imm | 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,imm(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,imm(rs) | Store Half: Mem[RF[Rs] + Offset] = RF[Rt] Backwards Arguments! | i |
sll | rd,rt,n | 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,n | 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,n | 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,imm(rs) | Store Word: Mem[RF[Rs] + Offset] = RF[Rt] Backwards Arguments! | i |
swl | rt,imm(rs) | Store Word Left (1-4 bytes, depending on offset): Mem[RF[Rs] + Offset] = RF[Rt] Backwards Arguments! | i |
swr | rt,imm(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 | rcode | call syscall in register | 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,imm | 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,Cs | move control word from cop1: Rf[rt] = ControlRf[Cs] | r |
ctc1 | rt,Cs | move control word to cop1: ControlRf[Cs] = Rf[rt] | 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,imm(rs) | load word to cop1: FpRf[ft] = Mem[Rf[rs] + Offset] | i |
lwc1 | ft,imm(rs) | load word to cop1: FpRf[ft] = Mem[Rf[rs] + Offset] | i |
lwc2 | rt,imm(rs) | load word to cop2: Unimplemented | i |
lwc3 | rt,imm(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] | 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,imm(rs) | store word from cop1: Mem[Rf[rs] + Offset] = FpRf[ft] | i |
sc | rt,imm(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,imm(rs) | store word from cop1: Mem[Rf[rs] + Offset] = FpRf[ft] | i |
swc2 | rt,imm(rs) | store word from cop2: Mem[Rf[rs] + Offset] = Unimplemented | i |
swc3 | rt,imm(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: FpRf[dd] = ceil(FpRf[ds]) | r |
ceil.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: FpRf[dd] = floor(FpRf[ds]) | r |
floor.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: FpRf[dd] = round(FpRf[ds]) | r |
round.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: FpRf[dd] = trunc(FpRf[ds]) | r |
trunc.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 cannot be defined in program code. Supported 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.
| ||||
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.
| ||||
addi | rt,imm | Add immediate: Rf[rt] = Rf[rt] + imm
| ||||
addiu | rt,imm | Add immediate unsigned: Rf[rt] = Rf[rt] + imm
| ||||
andi | rt,imm | And immediate: Rf[rt] = Rf[rt] & imm
| ||||
beq | rs,imm,label | Branch equal to If (RF[Rs] == Imm) then branch to Label
| ||||
bge | rs,rt,label | Branch greater than or equal to If (RF[Rs] >= Rf[Rt]) then branch to Label
| ||||
bge | rs,imm,label | Branch greater than or equal to If (RF[Rs] >= Imm) then branch to Label
| ||||
bgeu | rs,rt,label | Branch greater than or equal to (Unsigned) If (RF[Rs] >= Rf[Rt]) then branch to Label
| ||||
bgeu | rs,imm,label | Branch greater than or equal to (Unsigned) If (RF[Rs] >= Imm) then branch to Label
| ||||
bgt | rs,rt,label | Branch greater than If (RF[Rs] > Rf[Rt]) then branch to Label
| ||||
bgt | rs,imm,label | Branch greater than If (RF[Rs] > Imm) then branch to Label
| ||||
bgtu | rs,rt,label | Branch greater than (Unsigned) If (RF[Rs] > Rf[Rt]) then branch to Label
| ||||
bgtu | rs,imm,label | Branch greater than (Unsigned) If (RF[Rs] > Imm) then branch to Label
| ||||
ble | rs,rt,label | Branch less than or equal to If (RF[Rs] <= Rf[Rt]) then branch to Label
| ||||
ble | rs,imm,label | Branch less than or equal to If (RF[Rs] <= Imm) then branch to Label
| ||||
bleu | rs,rt,label | Branch less than or equal to (Unsigned) If (RF[Rs] <= Rf[Rt]) then branch to Label
| ||||
bleu | rs,imm,label | Branch less than or equal to (Unsigned) If (RF[Rs] <= Imm) then branch to Label
| ||||
blt | rs,rt,label | Branch less than If (RF[Rs] < Rf[Rt]) then branch to Label
| ||||
blt | rs,imm,label | Branch less than If (RF[Rs] < Imm) then branch to Label
| ||||
bltu | rs,rt,label | Branch less than (Unsigned) If (RF[Rs] < Rf[Rt]) then branch to Label
| ||||
bltu | rs,imm,label | Branch less than (Unsigned) If (RF[Rs] < Imm) then branch to Label
| ||||
bne | rs,imm,label | Branch not equal If (RF[Rs] != Imm) then branch to Label
| ||||
div | rd,rs,rt | Divide: Rf[rd] = Rf[rs]/Rf[rt] (break on divide by zero)
| ||||
div | rd,rs,n | Divide: Rf[rd] = Rf[rs]/n
| ||||
div | rd,n | Divide: Rf[rd] = Rf[rd]/n
| ||||
divu | rd,rs,rt | Divide unsigned: Rf[rd] = Rf[rs] / Rf[rt] (break on divide by zero)
| ||||
divu | rd,rs,n | Divide unsigned: Rf[rd] = Rf[rs] / n
| ||||
divu | rd,n | Divide unsigned: Rf[rd] = Rf[rd] / n
| ||||
l.d | dd,laddress | Load double: FpRf[dd] = laddress
| ||||
l.d | dd,imm(rs) | Load double: FpRf[dd] = Mem[RF[Rs] + Offset]
| ||||
l.s | fd,laddress | Load single: FpRf[fd] = laddress
| ||||
la | rd,laddress | Load Address into Rf[rd]
| ||||
lb | rd,laddress | Load byte (low 8 bits): Rf[rd] = Mem[laddress]
| ||||
lbu | rd,laddress | Load byte unsigned (low 8 bits): Rf[rd] = Mem[laddress]
| ||||
lh | rd,laddress | Load half (low 16 bits): Rf[rd] = Mem[laddress]
| ||||
lhu | rd,laddress | Load half unsigned (low 16 bits): Rf[rd] = Mem[laddress]
| ||||
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 empty.
| ||||
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 empty.
| ||||
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).
| ||||
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.
| ||||
lw | rd,laddress | Load word (full 32 bits): Rf[rd] = Mem[laddress]
| ||||
mul | rd,rs,rt | Multiply: Rf[rd] = Rf[rs] * Rf[rt]
| ||||
mul | rd,rs,n | Multiply: Rf[rd] = Rf[rs]*n
| ||||
mul | rd,n | Multiply: Rf[rd] = Rf[rd]*n
| ||||
mulo | rd,rs,rt | Multiply, break on overflow
| ||||
mulou | rd,rs,rt | Multiply unsigned, break on overflow
| ||||
mulu | rd,rs,rt | Multiply unsigned: Rf[rd] = Rf[rs] * Rf[rt]
| ||||
mulu | rd,rs,n | Multiply unsigned: Rf[rd] = Rf[rs] * n
| ||||
mulu | rd,n | Multiply unsigned: Rf[rd] = Rf[rd] * n
| ||||
ori | rt,imm | Or immediate: Rf[rt] = Rf[rt] | imm
| ||||
rem | rd,rs,rt | Remainder: Rf[rd] = Rf[rs] % Rf[rt]
| ||||
rem | rd,rs,n | Remainder: Rf[rd] = Rf[rs] % n
| ||||
rem | rd,n | Remainder: Rf[rd] = Rf[rd] % n
| ||||
remu | rd,rs,rt | Remainder unsigned: Rf[rd] = Rf[rs] % Rf[rt]
| ||||
remu | rd,rs,n | Remainder unsigned: Rf[rd] = Rf[rs] % n
| ||||
remu | rd,n | Remainder unsigned: Rf[rd] = Rf[rd] % n
| ||||
rol | rd,rt,rs | Rotate left
| ||||
rol | rd,rt,n | Rotate left
| ||||
ror | rd,rt,rs | Rotate right
| ||||
ror | rd,rt,n | Rotate right
| ||||
s.d | dd,laddress | Store double: Mem[laddress] = FpRf[dd]
| ||||
s.d | dd,imm(rs) | Store double: Mem[RF[Rs] + Offset] = FpRf[dd]
| ||||
s.s | fd,laddress | Store single: Mem[laddress] = FpRf[fd]
| ||||
sb | rd,laddress | Store byte (low 8 bits): Mem[laddress] = Rf[rd]
| ||||
seq | rd,rs,rt | Set if equal: Rf[rd] = Rf[rs] == Rf[rt]
| ||||
sge | rd,rs,rt | Set greater than: Rf[rd] = Rf[rs] > Rf[rt]
| ||||
sgeu | rd,rs,rt | Set greater than unsigned: Rf[rd] = Rf[rs] > Rf[rt]
| ||||
sh | rd,laddress | Store half (low 16 bits): Mem[laddress] = Rf[rd]
| ||||
sle | rd,rs,rt | Set less than or equal: Rf[rd] = Rf[rs] <= Rf[rt]
| ||||
sleu | rd,rs,rt | Set less than or equal unsigned: Rf[rd] = Rf[rs] <= Rf[rt]
| ||||
sne | rd,rs,rt | Set if not equal: Rf[rd] = Rf[rs] != Rf[rt]
| ||||
sub | rt,rs,imm | Subtract: Rf[rt] = Rf[rs] - imm
| ||||
sub | rt,imm | Subtract: Rf[rt] = Rf[rt] - imm
| ||||
subu | rt,imm | Subtract unsigned: Rf[rt] = Rf[rt] - imm
| ||||
subu | rt,rs,imm | Subtract unsigned: Rf[rt] = Rf[rs] - imm
| ||||
sw | rd,laddress | Store word (full 32 bits): Mem[laddress] = Rf[rd]
| ||||
ulh | rt,imm(rs) |
| ||||
ulhu | rt,imm(rs) |
| ||||
ulw | rt,imm(rs) |
| ||||
ush | rt,imm(rs) |
| ||||
usw | rt,imm(rs) |
| ||||
xori | rt,imm | Xor immediate: Rf[rt] = Rf[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.
| |||||
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.
| |||||
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
| |||||
addiu | rt,rs,imm | Add Immediate Unsigned RF[Rt] = RF[Rs] + Imm | i | ||||
addiu | rt,imm | Add immediate unsigned: Rf[rt] = Rf[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,imm | Bitwise And Immediate RF[Rt] = RF[Rs] & Imm | i | ||||
andi | rt,imm | And immediate: Rf[rt] = Rf[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
| |||||
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
| |||||
bge | rs,imm,label | Branch greater than or equal to If (RF[Rs] >= Imm) then branch to Label
| |||||
bgeu | rs,rt,label | Branch greater than or equal to (Unsigned) If (RF[Rs] >= Rf[Rt]) then branch to Label
| |||||
bgeu | rs,imm,label | Branch greater than or equal to (Unsigned) If (RF[Rs] >= Imm) then branch to 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
| |||||
bgt | rs,imm,label | Branch greater than If (RF[Rs] > Imm) then branch to Label
| |||||
bgtu | rs,rt,label | Branch greater than (Unsigned) If (RF[Rs] > Rf[Rt]) then branch to Label
| |||||
bgtu | rs,imm,label | Branch greater than (Unsigned) If (RF[Rs] > Imm) then branch to 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
| |||||
ble | rs,imm,label | Branch less than or equal to If (RF[Rs] <= Imm) then branch to Label
| |||||
bleu | rs,rt,label | Branch less than or equal to (Unsigned) If (RF[Rs] <= Rf[Rt]) then branch to Label
| |||||
bleu | rs,imm,label | Branch less than or equal to (Unsigned) If (RF[Rs] <= Imm) then branch to 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
| |||||
blt | rs,imm,label | Branch less than If (RF[Rs] < Imm) then branch to Label
| |||||
bltu | rs,rt,label | Branch less than (Unsigned) If (RF[Rs] < Rf[Rt]) then branch to Label
| |||||
bltu | rs,imm,label | Branch less than (Unsigned) If (RF[Rs] < Imm) then branch to 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
| |||||
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 | icode | pause execution | b | ||||
break | rcode | 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: FpRf[dd] = ceil(FpRf[ds]) | r | ||||
ceil.s | fd,fs | ceiling single: FpRf[fd] = ceil(FpRf[fs]) | r | ||||
cfc1 | rt,Cs | 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,Cs | move control word to cop1: ControlRf[Cs] = Rf[rt] | 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)
| |||||
div | rd,rs,n | Divide: Rf[rd] = Rf[rs]/n
| |||||
div | rd,n | Divide: Rf[rd] = Rf[rd]/n
| |||||
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 | ||||
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)
| |||||
divu | rd,rs,n | Divide unsigned: Rf[rd] = Rf[rs] / n
| |||||
divu | rd,n | Divide unsigned: Rf[rd] = Rf[rd] / n
| |||||
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: FpRf[dd] = floor(FpRf[ds]) | r | ||||
floor.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
| |||||
l.d | dd,imm(rs) | Load double: FpRf[dd] = Mem[RF[Rs] + Offset]
| |||||
l.s | ft,imm(rs) | load word to cop1: FpRf[ft] = Mem[Rf[rs] + Offset] | i | ||||
l.s | fd,laddress | Load single: FpRf[fd] = laddress
| |||||
la | rd,laddress | Load Address into Rf[rd]
| |||||
lb | rt,imm(rs) | Load Byte RF[Rt] = Mem[RF[Rs] + Offset] | i | ||||
lb | rd,laddress | Load byte (low 8 bits): Rf[rd] = Mem[laddress]
| |||||
lbu | rt,imm(rs) | Load Byte Unsigned RF[Rt] = Mem[RF[Rs] + Offset] | i | ||||
lbu | rd,laddress | Load byte unsigned (low 8 bits): Rf[rd] = Mem[laddress]
| |||||
lh | rt,imm(rs) | Load Half RF[Rt] = Mem[RF[Rs] + Offset] | i | ||||
lh | rd,laddress | Load half (low 16 bits): Rf[rd] = Mem[laddress]
| |||||
lhu | rt,imm(rs) | Load Half Unsigned RF[Rt] = Mem[RF[Rs] + Offset] | i | ||||
lhu | rd,laddress | Load half unsigned (low 16 bits): Rf[rd] = Mem[laddress]
| |||||
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 empty.
| |||||
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 empty.
| |||||
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).
| |||||
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.
| |||||
ll | rt,imm(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,imm | Load Upper Immediate RF[Rt] = Imm<<16 | i | ||||
lw | rt,imm(rs) | Load Word RF[Rt] = Mem[RF[Rs] + Offset] | i | ||||
lw | rd,laddress | Load word (full 32 bits): Rf[rd] = Mem[laddress]
| |||||
lwc1 | ft,imm(rs) | load word to cop1: FpRf[ft] = Mem[Rf[rs] + Offset] | i | ||||
lwc2 | rt,imm(rs) | load word to cop2: Unimplemented | i | ||||
lwc3 | rt,imm(rs) | load word to cop3: Unimplemented | i | ||||
lwl | rt,imm(rs) | Load Word Left RF[Rt] = Mem[RF[Rs] + Offset] | i | ||||
lwr | rt,imm(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] | 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]
| |||||
mul | rd,rs,n | Multiply: Rf[rd] = Rf[rs]*n
| |||||
mul | rd,n | Multiply: Rf[rd] = Rf[rd]*n
| |||||
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
| |||||
mulou | rd,rs,rt | Multiply unsigned, break on overflow
| |||||
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]
| |||||
mulu | rd,rs,n | Multiply unsigned: Rf[rd] = Rf[rs] * n
| |||||
mulu | rd,n | Multiply unsigned: Rf[rd] = Rf[rd] * n
| |||||
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,imm | Bitwise Or Immediate RF[Rt] = RF[Rs] | Imm | i | ||||
ori | rt,imm | Or immediate: Rf[rt] = Rf[rt] | imm
| |||||
rem | rd,rs,rt | Remainder: Rf[rd] = Rf[rs] % Rf[rt]
| |||||
rem | rd,rs,n | Remainder: Rf[rd] = Rf[rs] % n
| |||||
rem | rd,n | Remainder: Rf[rd] = Rf[rd] % n
| |||||
remu | rd,rs,rt | Remainder unsigned: Rf[rd] = Rf[rs] % Rf[rt]
| |||||
remu | rd,rs,n | Remainder unsigned: Rf[rd] = Rf[rs] % n
| |||||
remu | rd,n | Remainder unsigned: Rf[rd] = Rf[rd] % n
| |||||
rfe | Restore From Exception restores the status register to its value before the last exception occurred. | r | |||||
rol | rd,rt,rs | Rotate left
| |||||
rol | rd,rt,n | Rotate left
| |||||
ror | rd,rt,rs | Rotate right
| |||||
ror | rd,rt,n | Rotate right
| |||||
round.d | dd,ds | round double: FpRf[dd] = round(FpRf[ds]) | r | ||||
round.s | fd,fs | round single: FpRf[fd] = round(FpRf[fs]) | r | ||||
s.d | dd,laddress | Store double: Mem[laddress] = FpRf[dd]
| |||||
s.d | dd,imm(rs) | Store double: Mem[RF[Rs] + Offset] = FpRf[dd]
| |||||
s.s | ft,imm(rs) | store word from cop1: Mem[Rf[rs] + Offset] = FpRf[ft] | i | ||||
s.s | fd,laddress | Store single: Mem[laddress] = FpRf[fd]
| |||||
sb | rt,imm(rs) | Store Byte: Mem[RF[Rs] + Offset] = RF[Rt] Backwards Arguments! | i | ||||
sb | rd,laddress | Store byte (low 8 bits): Mem[laddress] = Rf[rd]
| |||||
sc | rt,imm(rs) | Unimplemented | i | ||||
seq | rd,rs,rt | Set if equal: Rf[rd] = Rf[rs] == Rf[rt]
| |||||
sge | rd,rs,rt | Set greater than: Rf[rd] = Rf[rs] > Rf[rt]
| |||||
sgeu | rd,rs,rt | Set greater than unsigned: Rf[rd] = Rf[rs] > Rf[rt]
| |||||
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,imm(rs) | Store Half: Mem[RF[Rs] + Offset] = RF[Rt] Backwards Arguments! | i | ||||
sh | rd,laddress | Store half (low 16 bits): Mem[laddress] = Rf[rd]
| |||||
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]
| |||||
sleu | rd,rs,rt | Set less than or equal unsigned: Rf[rd] = Rf[rs] <= Rf[rt]
| |||||
sll | rd,rt,n | 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]
| |||||
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,n | 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,n | 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
| |||||
sub | rt,imm | Subtract: Rf[rt] = Rf[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
| |||||
subu | rt,rs,imm | Subtract unsigned: Rf[rt] = Rf[rs] - imm
| |||||
sw | rt,imm(rs) | Store Word: Mem[RF[Rs] + Offset] = RF[Rt] Backwards Arguments! | i | ||||
sw | rd,laddress | Store word (full 32 bits): Mem[laddress] = Rf[rd]
| |||||
swc1 | ft,imm(rs) | store word from cop1: Mem[Rf[rs] + Offset] = FpRf[ft] | i | ||||
swc2 | rt,imm(rs) | store word from cop2: Mem[Rf[rs] + Offset] = Unimplemented | i | ||||
swc3 | rt,imm(rs) | store word from cop3: Mem[Rf[rs] + Offset] = Unimplemented | i | ||||
swl | rt,imm(rs) | Store Word Left (1-4 bytes, depending on offset): Mem[RF[Rs] + Offset] = RF[Rt] Backwards Arguments! | i | ||||
swr | rt,imm(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 | rcode | call syscall in register | 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: FpRf[dd] = trunc(FpRf[ds]) | r | ||||
trunc.s | fd,fs | truncate single: FpRf[fd] = trunc(FpRf[fs]) | r | ||||
ulh | rt,imm(rs) |
| |||||
ulhu | rt,imm(rs) |
| |||||
ulw | rt,imm(rs) |
| |||||
ush | rt,imm(rs) |
| |||||
usw | rt,imm(rs) |
| |||||
xor | rd,rs,rt | Bitwise Xor RF[Rd] = RF[Rs] ^ RF[Rt] | r | ||||
xori | rt,rs,imm | Bitwise Xor Immediate RF[Rt] = RF[Rs] ^ Imm | i | ||||
xori | rt,imm | Xor immediate: Rf[rt] = Rf[rt] ^ imm
|