Using SPIM with Modern Compiler Implementation

SPIM is a simulator for the MIPS instruction set. MIPS is a simple, clean, and efficient RISC computer architecture; Silicon Graphics workstations and Nintendo 64 use MIPS processors.

Why use SPIM?

A valuable part of the learning experience for students of compiler design is the implementation of a real compiler and code generator. I recommend that students build a code generator for a RISC architecture (such as MIPS, Sparc, PowerPC, or Alpha) because

But many people do not have access to a RISC-based workstation. The SPIM simulator allows MIPS assembly-language to be assembled and run on a Pentium PC running Microsoft Windows (or on a Unix workstation of almost any type).

But on the other hand...

There is a great satisfaction to be had in writing a compiler that generates real native code that runs on the bare machine. If you have a Pentium and you want this satisfaction, Section 9.2 of Modern Compiler Implementation shows how to handle Complex Instruction Set Computers (CISC).

Where is SPIM?

SPIM is available from the University of Wisconsin; it can be freely used and distributed for non-commercial purposes.

The documentation for SPIM also includes a detailed summary of the MIPS instruction set and assembly language.

How can I use SPIM in my Tiger compiler?

I have found that MIPS assembly language generated by my Tiger compiler runs under SPIM with very few modifications.

  1. A normal Tiger compiler takes a file myprog.tig and produces a file myprog.s, which is then assembled and linked with a runtime.o object file derived from a runtime.c.

    SPIM has no link-loader, and its system calls are incompatible with those assumed by runtime.c. A new version of the runtime is necessary: the file runtime.s. Warning: This file is not fully tested! Only main, initArray, and print are tested.

    Instead of link-loading, it is necessary to concatenate the Tiger-compiler output file myprog.s with runtime.s (either one can go first) and load the combined file into the SPIM simulator.

  2. Unlike a real MIPS assembler, SPIM has no support for string literals in the text segment, so it is necessary to use a .data directive before emitting string literals, and a .text directive afterwards.
  3. In procedure-entry prologues, my Tiger compiler for MIPS generated the lines
    L12_framesize=60
    addiu $sp,$sp,-L12_framesize
    
    and then within the function L12 it generates offsets such as
    sw $25,-24+L12_framesize($sp)
    
    The SPIM assembler seems unable to handle negated labels in expressions, so I had to modify the prologue to read as,
    L12_framesize=60
    addiu $sp,$sp,-60
    
    However, the offset expressions such as -24+L12_framesize($sp) work just fine.
  4. The not function in runtime.s has been renamed to _not because opcode-names in SPIM are not legal labels.
Miraculously, no other changes were necessary to my Tiger compiler to make the output runnable under PC-SPIM.

Andrew Appel