Nolimips
Nolimips is a MIPS simulator designed to execute simple register based MIPS assembly code. It is a minimalist MIPS virtual machine that, in constrast to other simulators (SPIM), supports unlimited registers. The lack of a simulators featuring this behaviour prompted the development of Nolimips.
- Its features are:
sufficient support of MIPS instruction set
infinitely many registers
It was written by Benoît Perrot as an LRDE member, so that EPITA students could exercise their compiler projects after instruction selection but before register allocation. It is implemented in C++ and Python.
- Resources:
Required version is Nolimips 0.11
Feedback can be sent to LRDE’s Projects Address
Documentation:
Here is a brief summary of the documentation for Nolimips.
Table of Contents
Invoking Nolimips
- To invoke
nolimips
run: -h
--help
: Display a help message and exit successfully.-V
--version
: Display the version number and exit successfully.--usage
: Give a short usage message--tasks-selection
:Each task of NOLIMIPS (parsing, execution, etc.) comes with a set of prerequisites: for example the pretty printing of an input program implies the parsing of its source file. This option asks NOLIMIPS to display the tasks that must be run before to run the ones explicitly specified on command line.
--parse
: Parse a file.--trace-scan
: Trace the scanning.--trace-parse
: Trace the parse.-N
--nop-after-branch
:To avoid a bubble in their pipeline, MIPS processors execute the instruction immediately following a branch; this instruction is said to be in the delay slot (FIXME: see further). This option fills the delay slot of branch instructions with a NOP, disabling the delay slot, simplifying the task of assembly programmers how do not care about writing optimized code.
-u
--unlimited-regs
:During last stages of a compiler, the intermediate representation of a source file (which mainly consists in a generic, architecture independent assembly code) is progressively translated into an architecture dependent assembly code. Low level (but still intermediate) representations are designed to be as near as possible of target assembly code, but generaly consider an extended target machine with an unlimited amount of registers. This option gives NOLIMIPS the ability to handle an arbitrary number of registers, allowing compiler developpers to test their low level output before implementing register allocation. These new registers may be used as any other MIPS registers through the symbols
$x0
,$x1
, and so on. They have a general purpose and are not considered as caller save nor callee save registers.--prg-display
: Display the read program.--prg-solve
: Resolve jump offsets and check bounds of immediates.--callee-save=num
--caller-save=num
--argument-registers=num
: Respectively set the maximum number of callee-save, caller-save and argument registers to num, a positive number.--check-callee-save
: Warn if a callee save register is not preserved across a call.--profile
: Enable program profiling-l library
--system-library=library
:Specify the builtin system library to use. Accepted library values are ‘spim’ (selected by default and implementing SPIM’s behavior), ‘nolimips’ (NOLIMIPS’ own library), and ‘none’ (no builtin library).
-e
--execute
: Execute the program on virtual machine.-E
--trace-exec
: Trace the execution.-i
--shell
: Launch interactive shell.
Steps of Nolimips
- NOLIMIPS works in three steps:
it scans and parses the file (lexical and syntaxical analysis),
producing an abstract representation of a program; - it resolves the program, checking the existence of labels used and computing branch offsets (assembly); - it loads the resolved program in the virtual machine, search for an entry point labeled
main
and start execution (execution).
Nolimips Language
NOLIMIPS supports a minimal MIPS instruction set and unlimited registers.
- Basic main in Nolimips:
.data .text # Routine main main: # Your Code # Trigger exit syscall (mandatory to use nolimips) li $v0, 0x06 syscall ; exit
For more example of Mips program you can see tests in Nolimips.
The Nolimips supported instruction set
Here is a list of categories for which you would like a description of each instruction:
Arithmetic instructions
- ADD
Add
src1
andsrc2
and store the result indest
(32-bit integers). If an overflow occurs, then trap.add dest, src1, src2- ADDU
Add
src1
andsrc2
and store the result indest
(32-bit integers).addu dest, src1, src2- ADDI
Add a constant
imm
andsrc
and store the result indest
(32-bit integers). If overflow occurs, then trap.addi dest, src1, immediate- ADDIU
Add a constant
imm
andsrc
and store the result indest
(32-bit integer).addiu dest, src1, imm- SUB
Subtract
src2
fromsrc1
and store the result indest
(32-bit integers). If an overflow occurs (FIXME), then trap.sub dest, src1, src2- SUBU
Subtract
src2
fromsrc1
and store the result indest
(32-bit integers).subu dest, src1, src2- NEG
Negate (logical 2-complement)
src
and store the result indest
. If an overflow occurs (FIXME), then trap.neg dest, src- NEGU
Negate
src
(logical 2-complement) and store the result indest
.negu dest, src- ABS
Compute the absolute value of
src
(32-bit integer) and write it todest
.abs dest, src- MUL
Multiply two words
src1
andsrc2
and write the result todest
.mul dest, src1, src2- DIV
Divide
src1
bysrc2
(32-bit signed integers), write the quotient inLO
and the remainder inHI
(32-bit integer).div dest, src1, src2- DIVU
Divide
src1
bysrc2
(32-bit unsigned integers), write the quotient inLO
and the remainder inHI
(32-bit integer).divu dest, src1, src2- REM
Compute the remainder from dividing
src1
bysrc2
(32-bit signed integers) and write it todest
.rem dest, src1, src2- REMU
Compute the remainder from dividing
src1
bysrc2
(32-bit unsigned integers) and write it todest
.remu dest, src1, src2
Bitwise instructions
- SLL
Left-shift (logical) the word
src
by the fixed numberimm
of bits and store the result indest
.sll dest, src1, imm- SLLV
Left-shift (logical) the word
src1
by the variable numbersrc2
of bits and store the result indest
.sllv dest, src1, src2- SRA
Right-shift (arithmetic) the word
src
by the fixed numberimm
of bits and store the result indest
.sra dest, src1, imm- SRAV
Right-shift (arithmetic) the word
src1
by the variable numbersrc2
of bits and store the result indest
.srav dest, src1, src2- SRL
Right-shift (logical) the word
src1
by the fixed numberimm
of bits and store the result indest
.srl dest, src1, imm- SRLV
Right-shift (logical) the word
src1
by the variable numbersrc2
of bits and store the result indest
.srl dest, src1, src2- ROL
Left-rotate the word
src
by a number of bits (imm
orsrc2
) and store the result indest
.rol dest, src1, imm|src2- ROR
Right-rotate the word
src
by a number (imm
orsrc2
) of bits and store the result indest
.ror dest, src1, imm|src2- AND
Compute the bitwise logical AND between
src1
andsrc2
and store the result todest
.and dest, src1, src2- ANDI
Compute the bitwise logical AND between
src
and a constantimm
and store the result todest
.andi dest, src1, imm- OR
Compute the bitwise logical OR between
src1
andsrc2
and store the result todest
.or dest, src1, src2- ORI
Compute the bitwise logical OR between
src
and a constantimm
and store the result todest
.ori dest, src1, imm- XOR
Compute the bitwise logical XOR between
src1
andsrc2
and store the result todest
.xor dest, src1, src2- XORI
Compute the bitwise logical XOR between
src
and a constantimm
and store the result todest
.xori dest, src1, imm- NOR
Compute the bitwise logical NOR between
src1
andsrc2
and store the result todest
.nor dest, src1, src2- NOT
Negate (logical 1-complement)
src
and store the result indest
.not dest, src
Comparison instructions
- SEQ
Set
dest
to 1 ifsrc1
equalssrc2
, else clear it.seq dest, src1, src2- SNE
Set
dest
to 1 ifsrc1
does not equalsrc2
, else clear it.sne dest, src1, src2- SGE
Set
dest
to 1 ifsrc1
is greater or equal tosrc2
(signed comparison), else clear it.sge dest, src1, src2- SGEU
Set
dest
to 1 ifsrc1
is greater or equal tosrc2
(unsigned comparison), else clear it.sgeu dest, src1, src2- SGT
Set
dest
to 1 ifsrc1
is greater thansrc2
(signed comparison), else clear it.sgt dest, src1, src2- SGTU
Set
dest
to 1 ifsrc1
is greater thansrc2
(unsigned comparison), else clear it.sgtu dest, src1, src2- SLE
Set
dest
to 1 ifsrc1
is lower or equal tosrc2
(signed comparison), else clear it.sle dest, src1, src2- SLEU
Set
dest
to 1 ifsrc1
is lower or equal tosrc2
(unsigned comparison), else clear it.sleu dest, src1, src2- SLT
Set
dest
to 1 ifsrc1
is lower thansrc2
(signed comparison), else clear it.slt dest, src1, src2- SLTU
Set
dest
to 1 ifsrc1
is lower thansrc2
(unsigned comparison), else clear it.sltu dest, src1, src2- SLTI
Set
dest
to 1 ifsrc1
is lower than a constantimm
(signed comparison), else clear it.slti dest, src1, imm- SLTIU
Set
dest
to 1 ifsrc1
is lower than a constantimm
(unsigned comparison), else clear it.sltiu dest, src1, imm
Branch instructions
- BEQ
Branch to
label
ifsrc1
equalssrc2
.beq src1, src2, label- BEQZ
Branch to
label
if src equals zero.beqz src, label- BNE
Branch to
label
ifsrc1
does not equalsrc2
.bne src1, src2, label- BNEZ
Branch to
label
ifsrc
does not equal zero.bnez src, label- BGE
Branch to
label
ifsrc1
is greater or equal tosrc2
(signed comparison).bge src1, src2, label- BGEU
Branch to
label
ifsrc1
is greater or equal tosrc2
(unsigned comparison).bgeu src1, src2, label- BGEZ
Branch to
label
ifsrc
is greater or equal tozero
(signed comparison).bgez src, label- BGEZAL
Call
label
ifsrc
is greater or equal tozero
(signed comparison)bgezal src, label- BGT
Branch to
label
ifsrc1
is greater thansrc2
(signed comparison).bgt src1, src2, label- BGTU
Branch to
label
ifsrc1
is greater thansrc2
(unsigned comparison).bgtu src1, src2, label- BGTZ
Branch to
label
ifsrc
is greater thanzero
(signed comparison).bgtz src, label- BLE
Branch to
label
ifsrc1
is lower or equal tosrc2
(signed comparison).ble src1, src2, label- BLEU
Branch to
label
ifsrc1
is lower or equal tosrc2
(unsigned comparison).bleu src1, src2, label- BLEZ
Branch to
label
ifsrc
is lower or equal tozero
(signed comparison).blez src, label- BLT
Branch to
label
ifsrc1
is lower thansrc2
(signed comparison).blt src1, src2, label- BLTU
Branch to
label
ifsrc1
is lower thansrc2
(unsigned comparison).bltu src1, src2, label- BLTZ
Branch to
label
if src1 is lower thanzero
(signed comparison).bltz src, label- BLTZAL
Call
label
ifsrc1
is lower thanzero
(signed comparison).bltzal src, label- J
- Jump to
label
unconditionaly. j label- JAL
Call
label
unconditionaly.jal label- JR
Jump to address contained in
dest
unconditionaly.jr dest- JALR
Call address contained in
dest
unconditionaly.jalr dest
Load instructions
- LB
Load the 8-bit quantity at address (offset + base) into
dest
as a signed value.lb dest, address- LBU
Load the 8-bit quantity at address (offset + base) into
dest
as an unsigned value.lbu dest, address- LW
Load the 32-bit quantity at address (offset + base) into
dest
as a signed value.lw dest, address- LUI
- Move the constant
imm
into the upper half word ofdest
. lui dest, imm- LI
Move the constant
imm
intodest
.li dest, imm- LA
Move the computed address into
dest
.la dest, address
Store instructions
- SB
Store the low byte from
src
at address (offset + base).sb src, address- SW
Store the low word from
src
at address (offset + base).sw src, address
Movement instructions
- MOVE
Move the contents of
src
todest
.move dest, src- MFHI
Move the contents of
HI
todest
.mfhi dest- MFLO
Move the contents of
LO
todest
.mflo dest- MTHI
Move the contents of
dest
toHI
.mthi dest- MTLO
Move the contents of
dest
toLO
.mtlo dest- MFC0
Move the contents of control coprocessor
src
register to CPUdest
register.mfc0 dest, src- MTC0
Move the contents of CPU
src
register to control coprocessordest
register.mtc0 dest, src
Syscall instructions
- SYSCALL
- Raise a system call exception.
0x02
: read(fd:$a0
, buf:$a1
, count:$a2
):$v0
0x03
: write(fd:$a0
, buf:$a1
, count:$a2
):$v0
0x06
: exit(status:$a0
)
0x33
: malloc(size:$a0
)List of syscall for Nolimips
syscall ; syscall_name
Nop instructions
- NOP
To do nothing.
nop