Overview

Although there are several MIPS simulators/emulators, we will use SPIM in this course. SPIM is a simple MIPS simulator/emulator. It reads MIPS assembly language programs, then assembles and executes them.

Here are some useful resources about MIPS and SPIM:

LC-3 is optional, here are some useful resources if you want to learn more abouyt LC-3 programming (including manuals and simulators/emulators):

Here are some useful notes regarding computer architecture:

Text Editors for MIPS Assembly

Visual Studio Code

In Visual Studio Code, open the quick-open (Ctrl+P) and type ext install kdarkhan.mips. Like Atom’s and Sublime Text’s support, this is based on the TextMate syntax bundle.

Sublime Text

In PackageControl, install “MIPS Syntax”, which corresponds to github:contradictioned/mips-syntax. Like Atom’s and VSCode’s support, this is based on the TextMate syntax bundle.

Atom

Install atom:language-mips, by going to Edit ▷ Preferences ▷ Install, and searching for the package. Like Sublime Text’s and VSCode’s support, this is based on the TextMate syntax bundle.

Vim

A few good options exist for Vim syntax files. We suggest github:harenome/vim-mipssyntax. Add the mips.vim language file from that repository to your ~/.vim/syntax, or if you use Pathogen, add the repository to your set of bundles.

Emacs

GNU Emacs’ asm-mode works great for writing assembly. It will automatically ensure your operands, comments, and labels are correctly aligned — but beware, it assumes that ;, //, or /**/ indicate comments, which is not the case for SPIM.

On some machines, files with a .s extension are assumed to be for a statistics language in the S family (e.g., R), and will start in ESS mode. You’ll need to explicitly flip into asm-mode, by running M-x asm-mode, or change your auto-mode-alist.

SPIM Installation

There are three ways to execute MIPS code with SPIM:

  • spim command line tool
    • load programs using -file option
    • interact using stdin/stdout via login terminal
  • qtspim GUI environment
    • load programs via a load button
    • interact via a pop-up stdin/stdout terminal
  • xspim GUI environment
    • I do not recommend using this version
    • requires X-windows server

On MacOS you can install spim using homebrew:

$ brew install spim

If you want to set up qtspim on your own computer, download it from spimsimulator.sourceforge.net, or from one of these links:

For Windows, run the .MSI installer bundle, which will set up QtSPIM for you.

For macOS, run the .PKG installer bundle, which will set up QtSPIM for you.

For 64-bit Debian Linux, including Ubuntu and Mint, install the .deb file, which will set up QtSPIM for you.

Building your own SPIM

On other platforms, you may need to compile from source.

We suggest the patched version of SPIM, linked above. You’ll need CMake, a C/C++ compiler, flex, and bison; if you want QtSPIM, you’ll need Qt development files installed. These should be available from your package manager.

$ apt install cmake gcc flex bison lib{xt6,xaw7}-dev qtbase5-dev

Extract the tarball

$ tar -xzf spim-simulator-spim-pkg.tar.gz
$ cd spim-simulator-spim-pkg

And run CMake to configure, build, and install SPIM. You should probably set the value of CMAKE_INSTALL_PREFIX to your home directory, which we do here; by default, it will install into /usr/local, so the installation may need administrative permissions.

$ cmake -S . -B obj -D CMAKE\_INSTALL\_PREFIX=$HOME
$ cmake --build obj
$ cmake --build obj -t install
[... some output, ending in ...]
-- Install configuration: ""
-- Installing: $HOME/share/spim/exceptions.s
-- Installing: $HOME/share/spim/helloworld.s
-- Installing: $HOME/bin/spim
-- Installing: $HOME/bin/xspim                  [if X11 was found\]
-- Installing: $HOME/bin/qtspim                 [if Qt was found\]

If all went well, you should now be able to run the spim or qtspim commands.

If you have questions, please ask on the course forum, and we’ll try and help you out.

Running MIPS programs on SPIM

These steps show how to run a MIPS program on SPIM. After completing these steps look at the Basic Skills section to learn techniques useful for debugging.

  • Load a MIPS assembler file (e.g., hello.s) into your editor. The MIPS instructions should be highlighted appropriately if you have setup the syntax highlighters appropriately.
  • Start the simulator either with qtspim (graphical interface tool) or spim (command line tool). You should be able to see the register values, the program in binary and assembler forms, the data area, and messages.
  • Check the bottommost pane for error messages. It may be necessary to make other panes smaller to see the bottommost pane. If there are any errors fix them, exit the simulator and restart!
  • Run the program by clicking the run button. If the program generates output a window entitled SPIM Console should pop up. If you don’t see it try moving the simulator window. Use the arrow keys to scroll within the SPIM Console window.
  • If you’re satisfied with the output then you’re done, otherwise edit the MIPS program and try again. See the Basic Skills section for some debugging techniques.

Basic Debugging Skills

Students should have the following basic debugging skills before attempting a homework assignment.

  • Single-Step Execution: Do this by clicking step in the main SPIM window then clicking stepin the small dialog that pops up. Each press of step will advance execution by one instruction, this can be seen by the movement of highlighting in the Text Segments pane.

  • Determine Register and Memory Values: The main SPIM window shows register values. Memory values are shown in the Data Segments pane. To find the address of the data you are interested find a la pseudo-instruction that loads the address of that data.
  • Set a Breakpoint: Single-stepping is a pain if you need to execute hundreds of instructions before execution reaches the instruction you’re interested in. If this applies to you, find the address of the instruction by scrolling the Text Segments pane until your instruction is visible; the address is the first hexadecimal number. Then select breakpoints and enter the address.
  • Find Documentation: Many errors are due to the incorrect usage of an instruction. Looking up an instruction should be quick and easy, so set a bookmark on your favorite browser or otherwise provide one-click access to the instruction documentation

Common SPIM Problems

The following problems are frequently encountered when using SPIM.

  • Syntax and Other Assembly Errors When you start SPIM look for errors on the bottommost pane.
  • Program Does not Seem to Run In the run or step dialog the staring address should be about 0x00400000. If the starting address is zero then SPIM could not find the main: symbol that should appear before the routine that is to run first. Make sure there are no errors that are confusing SPIM before it reaches main:.
  • Stack Overflow Error Most likely due to an infinite recursion error. A recursive procedure needs to test some kind of no-more-recursion condition before making a recursive call. If this condition is always false then recursion will be infinite and stack space will be exhausted.
  • Address Errors A zero or other invalid address is often due to common programming errors, such as never setting a register to an address in the first place. A misaligned address occurs when a lw or sw instruction is executed with an address that’s not a multiple of 4, or for lh, etc., a multiple of 2.

Common MIPS Errors

The following are common errors in MIPS programs.

  • Unintended Instruction in Delay Slot
#
# Example Error:
#
    addi $a0, $a0, 4
    j SOMEWHERE

    # Okay, here I do something else.
ELSEWHERE:
   add $a0, $t0, $s1

#
# Code with Error Fixed:
#
    addi $a0, $a0, 4
    j SOMEWHERE
    nop              # Or any other instruction relevant to your program

    # Okay, here I do something else.
ELSEWHERE:
   add $a0, $t0, $s1

In the first code fragment above the add \$a0, \$t0, \$s1 is executed even though the jump is taken.

  • Wrong Data Type Size
#
# Example Error
#
  lw $t0, 0($a0)
  addi $a0, $a0, 1
  lw $t1, 0($a0)

# Correct Code
  lw $t0, 0($a0)
  addi $a0, $a0, 4
  lw $t1, 0($a0)
  • Program Does Not Work Properly, For Some Reason To debug a program find the point at which it stops doing what was intended. To do this you need to know what the program should be doing, so review the algorithm and work out a bit by hand. You should also be able to single step, set SPIM breakpoints, and examine register and memory values. Simple errors can be caught by reviewing the code, but in more complex programs there is no substitute for watching what happens when it runs.