UNC miniMIPS Architecture Simulator V 1.1


 

1.0 UNC miniMIPS Processor Architecture

The UNC miniMIPS is a simple 32-bit processor with 32 registers, and a with main memory size of 2 gigabytes (231), or 536,870,912 (229) 32-bit words. It executes a subset of the MIPS R2000's instruction set. All native instructions occupy one 32-bit word in memory. Byte addresses of miniMIPs are in big-endian order.

The 32 registers are specified as $0-$31. Each register holds a 32-bit value, which can be interpreted a number, a character, or the address of some of a some variable or object in memory. Register, $0, is special. When used as a source operand, the contents of $0 are always 0, and all updates of $0, when used as a destination, are ignored.

Program execution begins at location 0x80000000 in kernel mode. However, the program must first be assembled (converted from its symbolic representation to a sequence of 32-bit words in memory) before it can be executed. If there are errors in the assembly process, a dialog box will pop up explaining the error.

2.0 Introduction to UNC miniMIPS Assembly Language

A typical line of assembly code specifies a single primitive operation, called an instruction, and its operands. The list of all UNC miniMIPs operations (its instruction set) is enumerated in section 3. In assembly language instructions are specified via short mneumonics of the operation specified (usually either abbreviations of acronymns). A list of comma-separated operands follows each instruction's mneumonic. The assembler uses this mneumonic and operand list to generate a binary encoding of the instruction, which is stored as a word in memory. Thus, an assembly language program is merely a way of generating a sequence of binary words, that the computer interprets as either (or both) program or data. To make this discussion concrete, consider the following example line of assembly code:

add $3,$4,$4 "add" is the instruction mneumonic
"$3,$4,$4" is a list of 3 operands

Generally, he first operand specifies the destination (output) of the operation, and subsequent operands specify source (input) operands. The instruction given tells the UNC miniMIPS to add the contents register 4 to itself and store the result in register 3.

Empty lines are ignored by the assmebler (they generate no output to memory), but they are often used to enhance readability. Any text following a "#" is considered a comment and the remainder of the line is ignored by the assembler. Comments are used to document the intent of the code beyond what is evident from the instruction specification alone.

Optionally, any line of assembly code can start with a label. A label is a sequence of characters followed by a colon (":"), which it is usually a meaningful name. A label provides a means for referencing the memory location that a particular instruction or variable is stored at. Instruction labels are often used to specify targets for branch instuctions. In the case of data, a label might represent a variable name. An example using label is shown below:

loop: addi $3,$3,-1 # loop is a label
bne $0,$3,loop # here the label is referenced

The UNC miniMIPS assembler also provides a small set of assembler directives, that are used like instructions. All assembler directives are prefixed with a "." (period) and they are generally used for allocating space for data and initializing variables. A complete list of assembler directives is given in section 4. Examples are given below.

Fib: .word 1,1,2,3,5,8,13,21 # first 8 Fibonacci numbers
masks: .word 0x000000ff,0x0000ff00,0x00ff0000,0xff000000 # byte masks
Name: .asciiz "Leonard" # 0-terminated string (8 bytes)
array: .space 20 # 20 uninitialized words

The UNC miniMIPS assembler also provides special support for simulation. Any line of assembly code beginning with an "*" (asterix) will act as a breakpoint causing the simulator to halt prior to the execution of the instruction following the mark, or after marked data is accessed via either a load or store instruction. One or more breakpoints can be set, and at least one is required to use the "Run" button.

3.0 UNC miniMIPS Instruction Set

Math Instructions

ADD: add registers
Syntax: add $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 0010 0000
Description:
Reg[d] ← Reg[s] + Reg[t]

Add the contents of registers Reg[s] and Reg[t], and place the result in Reg[d]. If the result overflows an exception is generated.

Example: add $6,$2,$0 # Encoded as: 0x00403020


ADDU: add registers without overflow
Syntax: addu $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 0010 0001
Description:
Reg[d] ← Reg[s] + Reg[t]

Add the contents of registers Reg[s] and Reg[t], and place the result in Reg[d]. Overflows are ignored.

Example: addu $3,$4,$4 # Encoded as: 0x00841821


ADDI: add immediate
Syntax: addi $t,$s,imm16
Encoding: 0010 00ss ssst tttt iiii iiii iiii iiii
Description:
Reg[t] ← Reg[s] + sign_extend(imm16)

Add a 16-bit sign-extended constant to the contents of Reg[s], and place the result in Reg[t]. If the result overflows an exception is generated.

Example: addi $6,$6,100 # Encoded as: 0x20c60064


ADDIU: add immediate without overflow
Syntax: addiu $t,$s,imm16
Encoding: 0010 01ss ssst tttt iiii iiii iiii iiii
Description:
Reg[t] ← Reg[s] + sign_extend(imm16)

Add a 16-bit sign-extended constant to the contents of Reg[s], and place the result in Reg[t]. Overflows are ignored.

Example: addiu $10,$9,-1 # Encoded as: 0x252affff


SUB: subtract registers
Syntax: sub $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 0010 0010
Description:
Reg[d] ← Reg[s] - Reg[t]

Subtract the contents of Reg[t] from Reg[s], and place the result in Reg[d]. If the result overflows an exception is generated.

Example:sub $16,$0,$12 # Encoded as: 0x00c8022


SUBU: subtract registers without overflow
Syntax: subu $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 0010 0011
Description:
Reg[d] ← Reg[s] - Reg[t]

Subtract the contents of Reg[t] from Reg[s], and place the result in Reg[d]. Overflows are ignored.

Example:subu $26,$24,$25 # Encoded as: 0x0319d023


MUL: multiply registers
Syntax: mul $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 001 1000
Description:
Reg[d] ← Reg[s] * Reg[t]

Multiply the contents of Reg[s] and Regts], and place the lower 32-bits of the product in Reg[d]. Overflows are ignored.

Example:mul $16,$2,$12 # Encoded as: 0x004c8018


DIV: divide registers
Syntax: div $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 001 1010
Description:
Reg[d] ← Reg[s] / Reg[t]

Divide the contents of Reg[s] by Reg[t], and place the quotient in Reg[d]. An overflow exception is generated and the destination is unchanged if the divisor is 0.

Example:div $12,$16,$2 # Encoded as: 0x0202601a


SLT: set if less than
Syntax: slt $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 0010 1010
Description:
Reg[d] ← 1 if (Reg[s] < Reg[t]); 0 otherwise

Set Reg[d] to '1' if the contents of Reg[s] is less than the contents of Reg[t].

Example:slt $17,$18,$19 # Encoded as: 0x0253882a


SLTU: set if less than unsigned
Syntax: sltu $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 0010 1011
Description:
Reg[d] ← 1 if (Reg[s] < Reg[t]); 0 otherwise

Set Reg[d] to '1' if the contents of Reg[s] is less than the contents of Reg[t]. Both operands (Reg[s] and Reg[t]) are compared as unsigned integers.

Example:sltu $20,$21,$22 # Encoded as: 0x02b6a02b


SLTI: set if less than immediate
Syntax: slti $t,$s,imm16
Encoding: 0010 10ss ssst tttt iiii iiii iiii iiii
Description:
Reg[t] ← 1 if (Reg[s] < sign_extend(imm16)); 0 otherwise

Set Reg[d] to '1' if the contents of Reg[s] is less than the supplied sign extended immediate value.

Example:slti $6,$2,10 # Encoded as: 0x2846000a


SLTIU: set if less than immediate unsigned
Syntax: sltiu $t,$s,imm16
Encoding: 0010 11ss ssst tttt iiii iiii iiii iiii
Description:
Reg[t] ← 1 if (Reg[s] < sign_extend(imm16)); 0 otherwise

Set Reg[d] to '1' if the contents of Reg[s] is less than the supplied sign-extended immediate value. Both arguments are treated as unsigned integers (despite the sign extension... go figure?).

Example:sltiu $2,$6,0xffff # Encoded as: 0x252affff


Logic Instructions

AND: bitwise and registers
Syntax: and $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 0010 0100
Description:
Reg[d] ← Reg[s] & Reg[t]

Performs a "bitwise" anding of the contents of registers Reg[s] and Reg[t] and places the result in Reg[d].

Example: and $6,$2,$3 # Encoded as: 0x00433024


ANDI: bitwise and with immediate
Syntax: andi $t,$s,imm16
Encoding: 0011 00ss ssst tttt iiii iiii iiii iiii
Description:
Reg[t] ← Reg[s] & zero_extend(imm16)

Performs a "bitwise" anding of the contents of Reg[s] with the given zero-extended 16-bit constant and places the result in Reg[t].

Example: andi $6,$2,255 # Encoded as: 0x304600ff


OR: bitwise or registers
Syntax: or $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 0010 0101
Description:
Reg[d] ← Reg[s] | Reg[t]

Performs a "bitwise" oring of the contents of Reg[s] with Reg[t], and place the result in Reg[d].

Example:or $4,$4,$5 # Encoded as: 0x00852025


ORI: bitwise or with immediate
Syntax: ori $t,$s,imm16
Encoding: 0011 01ss ssst tttt iiii iiii iiii iiii
Description:
Reg[t] ← Reg[s] | imm16

Performs a "bitwise" oring of the contents of Reg[s] with the given zero-extended 16-bit constant and place the result in Reg[t].

Example:ori $12,$1,0xabcd # Encoded as: 0x342cabcd


XOR: bitwise exclusive or registers
Syntax: xor $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 0010 0110
Description:
Reg[d] ← Reg[s] ^ Reg[t]

Perform a "bitwise" exclusive-or of the contents of Reg[s] with Reg[t]), and place the result in Reg[d].

Example:xor $6,$9,$1 # Encoded as: 0x012113026


XORI: bitwise exclusive-or with immediate
Syntax: xori $t,$s,imm16
Encoding: 0011 10ss ssst tttt iiii iiii iiii iiii
Description:
Reg[t] ← Reg[s] ^ imm16

Performs a "bitwise" exclusive-oring of the contents of Reg[s] with the zero-extended 16-bit constant and places the result in Reg[t].

Example:xori $6,$2,0xffff # Encoded as: 0x3846ffff


NOR: bitwise nor registers
Syntax: nor $d,$s,$t
Encoding: 0000 00ss ssst tttt dddd d000 0010 0111
Description:
Reg[d] ← ~(Reg[s] | Reg[t])

Perform a "bitwise" nor of the contents of Reg[s] with Reg[t]), and place the result in Reg[d]. This instruction is commonly to complement the contents of a register by setting the other operand to $0.

Example:nor $1,$1,$0 # Encoded as: 0x00200827


Shift Instructions

LUI: load upper immediate while filling lower bits with zeros
Syntax: lui $t,imm16
Encoding: 0011 1100 000t tttt iiii iiii iiii iiii
Description:
Reg[t] ← imm16 << 16

Load Reg[t] with the given 16-bit constant shifted left by 16 bits. Vacated bits are filled with 0's. This instruction is frequently followed by an ori $t,$0,imm16 to initialize a register with a 32-bit constant. If a label is specified the upper 16 bits of the associated address are used as the constant.

Example: lui $1,0xaaaa # Encoded as: 0x3c01aaaa


SLL: shift left logical by filling lower bits with zeros
Syntax: sll $d,$t,imm5
Encoding: 0000 0000 000t tttt dddd diii ii00 0000
Description:
Reg[d] ← Reg[t] << imm5

Shift the contents of Reg[t] left the number of positions specified by the given unsigned constant (0-31) and place the result in Reg[d]. Vacated bits are filled with 0's. This instruction is frequently used to multiply by powers of 2. It also serves as the default NOP (No OPeration) instruction, which is equivalent to sll $0,$0,$0 and is encoded as 0x00000000.

Example: sll $6,$2,2 # Encoded as: 0x00023080


SLLV: shift left logical variable; zero-fill lower bits
Syntax: sllv $d,$t,$s
Encoding: 0000 00ss ssst tttt dddd d000 0000 0100
Description:
Reg[d] ← Reg[t] << Reg[s]

Shift the contents of Reg[t] left the number of positions specified by the specified by lower 5-bits of Reg[s] and place the result in Reg[d]. Vacated bits are filled with 0's. This instruction is frequently used to multiply by powers of 2.

Example:sllv $6,$2,$2 # Encoded as: 0x00423004


SRL: shift right logical filling upper bits with zeros
Syntax: srl $d,$t,imm5
Encoding: 0000 0000 000t tttt dddd diii ii00 0010
Description:
Reg[d] ← Reg[t] >>> imm4

Shift the contents of Reg[t] right the number of positions specified by the given unsigned constant (0-31). Vacated register bits are filled with 0's. This instruction can be used to perform unsigned integer divides by a power of 2.

Example:srl $1,$1,8 # Encoded as: 0x00010a02


SRLV: shift right logical variable; zero-fill upper bits
Syntax: srlv $d,$t,$s
Encoding: 0000 00ss ssst tttt dddd d000 0000 0110
Description:
Reg[d] ← Reg[t] >>> Reg[s]

Shift the contents of Reg[t] right the number of positions specified by the lower 5-bits of Reg[s] and place the result in Reg[d]. Vacated bits are filled with 0's. This instruction is frequently used to divide unsigned integers by powers of 2.

Example:srlv $6,$8,$24 # Encoded as: 0x01183006


SRA: shift right arithmetic filling upper-bits with the sign
Syntax: sra $d,$t,imm5
Encoding: 0000 0000 000t tttt dddd diii ii00 0011
Description:
Reg[d] ← Reg[t] >> imm5

Shift the contents of Reg[t] right the number of positions specified by the given unsigned constant (0-31). Vacated register bits are filled with copies of the sign bit. An alternate intepretation of is:

Reg[d] ← Reg[t] / 2imm5

Where the contents of Reg[t] are treated as a signed integer.

Example:sra $1,$1,31 # Encoded as: 0x00010fc3


SRAV: shift right variable filling upper-bits with the sign
Syntax: srav $d,$t,$s
Encoding: 0000 00ss ssst tttt dddd d000 0000 0111
Description:
Reg[d] ← Reg[t] >> Reg[s]

Shift the contents of Reg[t] right the number of positions specified by the lower 5-bits of Reg[s]. The vacated register bits are filled with copies of the sign bit.

Example:srav $1,$1,$2 # Encoded as: 0x00220807


Memory Access Instructions

SW: store word
Syntax: sw $t,imm16($s)
sw $t,imm16      # implicit $s = $0
sw $t,($s)       # implicit $imm16 = 0
Encoding: 1010 11ss ssst tttt iiii iiii iiii iiii
Description:
Memory[Reg[s]+sign_extended(imm16)] ← Reg[t]

Save the contents of Reg[d] into the memory address given by the contents of Reg[s] plus a sign-extended 16-bit constant. If the computed memory address is not word aligned an exception is generated.

Example:sw $1,-4($29) # Encoded as: 0xafa1fffc


LW: load word
Syntax: lw $t,imm16($s)
lw $t,imm16      # implicit $s = $0
lw $t,($s)       # implicit $imm16 = 0
Encoding: 1000 11ss ssst tttt iiii iiii iiii iiii
Description:
Reg[t] ← Memory[Reg[s]+sign_extended(imm16)]

Load Reg[d] with the contents of memory at the address given by the contents of Reg[s] plus a sign-extended 16-bit constant. If the computed memory address is not word aligned an exception is generated.

Example:lw $1,8($29) # Encoded as: 0x8fa10008


Branch and Jump Instructions

BEQ: branch if equal
Syntax: beq $s,$t,imm16
Encoding: 0001 00ss ssst tttt iiii iiii iiii iiii
Description:
if (Reg[s] == Reg[t]) {
    PC ← PC + 4*sign_extended(imm16)
}

If the contents of Reg[s] equals the contents of Reg[t] branch to the instruction given by the specified constant, which is usually specified by a label.

Example:halt: beq $0,$0,halt # Encoded as: 0x1000ffff


BNE: branch if not equal
Syntax: bne $s,$t,imm16
Encoding: 0001 01ss ssst tttt iiii iiii iiii iiii
Description:
if (Reg[s] ≠ Reg[t]) {
    PC ← PC + 4*sign_extended(imm16)
}

If the contents of Reg[s] does not equal the contents of Reg[t] branch to the instruction given by the specified constant, which is usually specified by a label.

Example:bne $1,$0,skip # Encoded as: 0x14200000
  skip:


JR: jump register
Syntax: jr $s
Encoding: 0000 00ss sss0 0000 0000 0000 0000 1000
Description:
PC ← Reg[s]

Jump to the instruction given by the contents of Reg[s].

Example:jr $31 # Encoded as: 0x03e00008


JALR: jump and link register
Syntax: jalr $s,$d
jalr $s      # implicit $d = $31
Encoding: 0000 00ss sss0 0000 dddd d000 0000 1001
Description:
Reg[d] ← PC + 4
PC ← Reg[s]

Jump to the instruction given by the contents of Reg[s], and save the location of the next instruction in Reg[s].

Example:jalr $1,$31 # Encoded as: 0x0020F809


J: jump
Syntax: j imm26
Encoding: 0000 10ii iiii iiii iiii iiii iiii iiii
Description:
PC ← (PC & 0xf0000000) | (4*imm26)

Jump to the instruction given by 4 times the immediate 26-bit constant, which is usually references a label.

Example:j 0x00400000 # Encoded as: 0x08100000


JAL: jump and link
Syntax: jal imm26
Encoding: 0000 11ii iiii iiii iiii iiii iiii iiii
Description:
Reg[31] ← PC + 4
PC ← (PC & 0xf0000000) | (4*imm26)

Jump to the instruction given by 4 times the immediate 26-bit constant, which is usually references a label, and save the location of the next instruction in Reg[31].

Example:jal main # Encoded as: 0x0c100000


4.0 Pseudoinstructions

NEG: negate register
Syntax: neg $d,$s
Encoding: pseudoinstruction
Description:
Reg[d] ← -Reg[s]

Negates the contents of register Reg[s] and places the result in Reg[d]. Generates an overflow if the sign of the result is the same as the original contents of the source register.

Example: neg $6,$2


NEGU: negate register and ingore overflows.
Syntax: negu $d,$s
Encoding: pseudoinstruction
Description:
Reg[d] ← -Reg[s]

Negates the contents of register Reg[s] and places the result in Reg[d]. Overflows are ignored.

Example: negu $6,$2


NOT: bitwise complement
Syntax: not $d,$s
Encoding: pseudoinstruction
Description:
Reg[d] ← ~Reg[s]

Performs a "bitwise" complement of the contents of Reg[s] and places the result in Reg[d]. Each '0' is replaced by a '1', and each '1' with a '0';

Example:not $4,$4


MOVE: copy a register's contents of
Syntax: move $d,$s
Encoding: pseudoinstruction
Description:
Reg[d] ← Reg[s]

Copies the contents of Reg[s] to Reg[d].

Example:move $1,$4


LA: load address
Syntax: la $d,imm16($s)
la $d,imm16      # implicit $s = $0
la $d,($s)       # implicit $imm16 = 0
Encoding: pseudoinstruction
Description:
Reg[d] ← Reg[s]+sign_extended(imm16)

Load Reg[d] with the address given by the adding the contents of Reg[s] to a sign-extended 16-bit constant. Using $1 as an operand may give unexpected results.

Example:la $1,8($29)


SGT: set if greater than
Syntax: sgt $d,$s,$t
Encoding: pseudoinstruction
Description:
Reg[d] ← 1 if (Reg[s] > Reg[t]); 0 otherwise

Set Reg[d] to '1' if the contents of Reg[s] is greater than the contents of Reg[t].

Example:sgt $17,$18,$19


B: unconditional branch
Syntax: b imm16
Encoding: pseudoinstruction
Description:
PC ← PC + 4*sign_extended(imm16)

Branch to the instruction given by the specified constant, which is usually specified by a label.

Example:halt: b halt


5.0 Assembler Directives

.WORD: Specify initialized data
Syntax: .word value1, value2, ..., valuen
Description:
Successive words in memory are initialized with constant values from the list. Constants can be decimal numbers, octal numbers prefixed with '0', hexadecimal numbers prefixed with '0x', or labels, which specify an address.

Example: .word 10,010,0x10 # Encoded as: 0x0000000a, 0x00000008, 0x00000010


.SPACE: Specify a block of uninitialized space
Syntax: .space value1,value2, ..., valuen
Description:
Blocks of sizes specified in the list of constant values are reserved. Constants can be decimal numbers, octal numbers prefixed with '0', hexadecimal numbers prefixed with '0x', or an address label.

Example: .space 50 # reserves 50 uninitialized words


.ASCIIZ: Initialize memory with strings
Syntax: .asciiz "string1","string2", ..., "stringn"
Description:
Fills successive memory locations with characters from the given list of quoted strings, each string is termnated with one or more "0"s. The address of the first letter of each string is word aligned.

Example: .asciiz "Tarheels" # Encoded as: 0x54617268, 0x65656C73, 0x00000000
 

Back to course web page


© 2012, 2013, 2015 Leonard McMillan