MIPS Instruction - muneeb-mbytes/computerArchitectureCourse GitHub Wiki

MIPS Instruction Formats

  • All MIPS instructions are encoded in binary.

  • They are 32 bits long.

    Example:

        001000  10011010100000000000000100
        -6bit-  -----------26bit----------
  • All instructions have an operation code (or opcode) that specifies the operation (first 6 bits).
  • There are three instruction categories:
    1. I-format
    2. J-format
    3. R-format

MIPS Register Set

MIPS register set consists of 32 general-purpose registers, denoted as $0 through $31, where each register is 32 bits in size. These registers are fundamental to the processor's operation as they provide temporary storage for data during program execution. The register set includes special-purpose registers like the Program Counter (PC), Memory Address Register (MAR), and various others that play distinct roles in managing the flow of instructions and data within the CPU. MIPS registers are utilized for a variety of purposes, including storing variables, holding intermediate results of calculations, and facilitating communication between different parts of a program. The efficient use of registers contributes to the speed and performance of the MIPS architecture, allowing for streamlined execution of instructions in diverse computing applications.

Why register set is used?

The MIPS register set is used for several critical purposes in computer architecture and assembly language programming:

  • Data Storage and Manipulation: Registers provide high-speed storage within the CPU, allowing for rapid access to data during program execution. These registers serve as temporary storage for variables, intermediate results, and other data used in calculations and operations.

  • Efficient Data Access: Accessing data from registers is much faster than fetching it from the system's main memory. By utilizing registers, the MIPS architecture enhances the efficiency of data operations, contributing to faster execution of instructions.

  • Communication between CPU and Memory: Registers facilitate communication between the CPU and memory by temporarily holding data that needs to be fetched from or written to memory. This reduces the need for frequent and time-consuming access to slower memory locations.

  • Processor Control and Status: Special-purpose registers, such as the Program Counter (PC), are crucial for managing the flow of instructions within the CPU. The PC keeps track of the address of the next instruction to be fetched, enabling the sequential execution of program instructions.

  • Optimization for Compilation: MIPS registers are designed to facilitate automatic generation of machine code by compilers. Compilers can efficiently use registers to store intermediate values and optimize code for better performance.

  • Pipeline Processing: MIPS architecture employs pipeline processing, breaking down instruction execution into stages. Registers are crucial for managing the flow of data between these stages, enabling the simultaneous processing of multiple instructions.

Symbolic Name Number Usage
zero 0 Constant 0
at 1 Reserved for the assembler
v0 - v1 2 - 3 Result Registers
a0 - a3 4 - 7 Argument Registers 1 · · · 4
t0 - t9 8 - 15, 24 - 25 Temporary Registers 0 · · · 9
s0 - s7 16 - 23 Saved Registers 0 · · · 7
k0 - k1 26 - 27 Kernel Registers 0 · · · 1
gp 28 Global Data Pointer.
sp 29 Stack Pointer
fp 30 Frame Pointer
ra 31 Return Address
  • Zero Register ($0): Zero register always contains the value 0. It is used for operations that should yield a constant 0 result. Assigning a value to $0 has no effect.

  • Assembler Temporary Register ($1 - at): Reserved for the assembler. It is typically used as a temporary register during the assembly process and does not have a specific purpose during program execution.

  • Result Registers ($2 - $3 - v0, v1): These registers are used to store the results of function calls. Functions return values in v0, and v1 is sometimes used for larger return values.

  • Argument Registers ($4 - $7 - a0, a1, a2, a3): it is used to pass arguments to functions. The calling function places values in these registers, and the called function can access them as parameters.

  • Temporary Registers ($8 - $15, $24 - $25 - t0 to t9): These registers are temporary and can be freely used by a function. They are not preserved across function calls.

  • Saved Registers ($16 - $23 - s0 to s7): Must be saved and restored by functions if they use them. They retain their values across function calls.

  • Kernel Registers ($26 - $27 - k0, k1): Reserved for use by the operating system kernel. Typically used for exception handling.

  • Global Data Pointer ($28 - gp): Points to the global data area. It is commonly used to access global variables.

  • Stack Pointer ($29 - sp): Points to the top of the stack. It is crucial for managing the function call stack and local variables.

  • Frame Pointer ($30 - fp): it is often used as a reference point within the stack frame. It assists in accessing local variables and parameters.

  • Return Address ($31 - ra): Stores the return address of a function. It is used by the jal (jump and link) instruction to store the address to return to after a function call.

Why MIPS has 32 registers?

So first of all, the instruction length in MIPS is 32 bits. (64-bit version is also there). In many MIPS instructions, you have to supply three registers, say two sources and one destination.

For example: r4=r2+r4

The MIPS architecture allows 5 bits to specify each of the registers, so 32 is the maximum value possible (2^5=32), so there is no point in giving more registers that you can't access. If 32 registers require 5 bits means it takes 15 bits of the 32-bit MIPS instruction (if there are 3 registers). If MIPS allows to choose 6 bit for a register, then we can use up to 64 different registers. But to represent those extra bits we need some space which will result in reducing the space for other constants or opcodes in instruction.

Another reason is the access time. The larger you make a memory the slower it is to access data from it.

Why MIPS instructions are 32-bit wide?

The 32-bit width of each register in MIPS serves several purposes:

1. Speed of operation:

The desire for speed is a significant factor in the choice of 32 registers, as smaller registers were faster and easier to access at the time when MIPS was developed

2. Instruction Length:

The 32-bit register size aligns with the MIPS instruction length. MIPS instructions are typically 32 bits wide, and the architecture allows 5 bits to specify each register. Therefore, 32 is the maximum number that can be represented with five bits, limiting the number of registers that can be accessed in a single instruction

3. Efficient Data Access:

The 32-bit register size allows for efficient and fast access to registers, contributing to the overall performance and efficiency of the processor

4. Compatibility and Design Simplicity:

The 32-bit register size has remained a consistent feature across different versions of the MIPS architecture, contributing to compatibility and design simplicity

In summary, the 32-bit width of each register in MIPS is a result of historical considerations, alignment with instruction length, and the need for efficient data access and design simplicity.

1. I-format

  • I-format (Immediate-format) instructions in MIPS architecture are primarily designed for operations that involve immediate values (constants) and memory access with offsets.
  • It has 2 registers and a constant value immediately present in the instruction.

Structure of I-Format Instructions:

new1

The I-format instructions in MIPS consist of the following components:

  1. Opcode (Operation Code): Specifies the operation to be performed.

  2. Source Register (rs): Indicates the source register for the operation.

  3. Destination Register (rt): Specifies the destination register for storing results.

  4. Immediate Value (16 bits):

  • Represents the immediate value or constant used in the operation.

  • In MIPS assembly language, the immediate value in an I-format instruction is a 16-bit signed value, which means it can represent integers in the range from -32768 to 32767.

  • This is because one bit is used for the sign, leaving 15 bits for the actual value.

Advantages :

  • Memory Access: Specifically for accessing memory by using immediate values as offsets to load or store data.
  • Simpler Arithmetic with Constants: Convenient for simpler arithmetic operations that include constants along with register values.

Examples :

1. adding the contents of register with constant value and put it in the temporary register

addi $t2, $s3, 4

i format

2. loading the contents of the data from memory to temporary register

lw $t0, 4($s2)

load1 (1)

axi loadNEW

3. storing the data from temporary register to a memory

sw $t0, 4($s1)

store1 (1)

axistore

refer this link for load and store operations happening in axi protocol : https://github.com/muneeb-mbytes/computerArchitectureCourse/wiki/AXI-interface-between-register-files-and-memory

2. J-format

  • The J format is often used for jump or branch instructions, which involve changing the program counter to jump to a different instruction.
  • since the addressess are large in J format it has the most space for an immediate value compared to other formats. i.e 26 bits are allocated for immediate value, which is got by discarding the higher-order 4 bits and lower-order 2 bits(which will always be 00 since addresses are multiples of 4)of the 32bit address value.

J instructions have the following machine-code format: opcode (address)

opcode:The 6 bit opcode corresponding to the particular jump command. address:A 26-bit shortened address of the destination.

Example: jump to target address 1000

     J 1000

j format

In order to represent the given address in j format, following steps are required:

1. Represent the given address in hex format (8 bits in hex).

2. Drop the first hex digit.

3. Convert it into binary.

4. Drop the last 2 binary digits.

(or convert it into binary drop the first 4 bits and last 2 bits).

In this example we have the address as 1000. 1000 in hex is 0000_03E8. Drop 0 from msb then it becomes 00003E8 After converting it to binary we get 0000_0000_0000_0000_0011_1110_1000 Dropping the last 2 bits => 00000000000000000011111010 = 250 in decimal (26 bits)

Another method is simply dividing the given address by 4 since the address should be divisible by 4. Therefore 1000/4=250.

To form the full 32-bit jump target:

  • append the end with two 0 bits which will result in 28-bit address (As the instructions are 32 bits, alignment is useful and allows the omitting of the last two 0's.).
  • add the first four bits of the PC in the beginning.

Therefore the target address is PC(4 bits of MSB) + 26 bits + 00(two zeros at end).

image

So including 26 bits and the two 0's we will have a 28-bits of data which will result in a 2^28 i.e., 268435456 bytes or 256MB range for jump instruction.

image

3. R-format

  • R-format instructions in MIPS are used when all the data values used by the instruction are located in registers. They are identified by an opcode of 0, and are differentiated by their function values.

  • 3 register operands are used

    • 2 source registers rs1, rs2
    • 1 destination register rd
  • The format for R-type instructions is: OP, rd, rs, rt, shamt, funct

    • Opcode: A 6 bit operation code that is always zero
    • Funct: A 6 bit function code that identifies the specific R-format instruction
    • Shamt: A 5 bit shift amount
    • Rd: A 5 bit register destination
    • Rt: A 5 bit 2nd register operand
    • Rs: A 5 bit 1st register operand

Example

  1. add $s0, $s1, $s2 (registers 16, 17, 18)

rformat (1)

Representation in 3 different level

Untitled Diagram drawio

Mips Instruction Set

1.Arithmetic Instructions

Instruction Example Meaning Explanation
add add $1, $2, $3 $1 = $2 + $3 Addition of values in registers $2 and $3
subtract sub $1, $2, $3 $1 = $2 - $3 Subtraction of value in register $3 from $2
add immediate addi $1, $2, 100 $1 = $2 + 100 Addition of immediate value 100 to register $2
add unsigned addu $1, $2, $3 $1 = $2 + $3 Addition of values in registers $2 and $3
subtract unsigned subu $1, $2, $3 $1 = $2 - $3 Subtraction of values in registers $2 and $3
Multiply mult $2, $3 $hi, $lo = $2 * $3 (result in $hi, $lo) Multiplies the values in registers $2 and $3 and stores the result in special registers $hi and $lo. The high-order bits go to $hi and the low-order bits to $lo
Divide div $2, $3 $hi, $lo = $2 / $3 (result in $hi, $lo) Division of value in $2 by $3, quotient in $lo, remainder in $hi

In MIPS assembly language, there is a multiplication instruction for signed integers, mult, and for unsigned integers multu. Since multiplication takes two 32 bit numbers and returns a 64 bit number, special treatment must be given to the result. The 64 bit product is located in a “product” register. You access the contents of this register using two separate instructions.

mult $s0, $s1 # Multiply the numbers stored in these registers.
# This yields a 64 bit number, which is stored in two
# 32 bits parts: "hi" and "lo"
mfhi $t0 # loads the upper 32 bits from the product register
mflo $t1 # loads the lower 32 bits from the product register

2.Logical Instructions

Instruction Example Meaning Explanation
and and $1, $2, $3 $1 = $2 & $3 Bitwise AND of values in registers $2 and $3, result is stored in register $1
or or $1, $2, $3 $1 = $2 | $3 Bitwise OR of values in registers $2 and $3, result is stored in register $1
and immediate andi $1, $2, 100 $1 = $2 & 100 Bitwise AND of value in register $2 and immediate value 100
shift left logical sll $1, $2, 10 $1 = $2 << 10 Logical left shift of the bits in register $2 by 10 positions
shift right logical srl $1, $2, 10 $1 = $2 >> 10 Logical right shift of the bits in register $2 by 10 positions

3.Data Transfer

Instruction Example Meaning Explanation
load word (lw) lw $1, 100($2) $1 = Memory[$2 + 100] Loads a 32-bit word from memory at the address $2 + 100 into register $1
store word (sw) sw $1, 100($2) Memory[$2 + 100] = $1 Stores the value in register $1 into memory at the address $2 + 100
load upper immediate (lui) lui $1, 4097 $1={immediate value,16'b0} 4097 = 0x1001 (hexa value) --->lui $t0, 4097 is the load upper immediate instruction. The immediate value(4097) is shifted left 16 bits and stored in the $1 register. The lower 16 bits are zeroes hence it will be [0x10010000]
load address (la) la $1, label $1 = Address of label Loads the address of the specified label into register $1
load immediate (li) li $1, 100 $1 = 100 Loads the immediate value (100) into register $1
move (move) move $1, $2 $1 = $2 Moves the value from register $2 into register $1

4. Conditional Branch

Instruction Example Meaning Explanation
branch on equal beq $1,$2,100 if($1==$2) go to PC+4+100 Test if registers are equal
branch on not equal bne $1,$2,100 if($1!=$2) go to PC+4+100 Test if registers are not equal
branch on greater than bgt $1,$2,100 if($1>$2) go to PC+4+100 Test if $1 registrer is greater than $2 register
branch on greater than or equal bge $1,$2,100 if($1>=$2) go to PC+4+100 Test if $1 register is greater or equal to $2 register
branch on less than blt $1,$2,100 if($1<$2) go to PC+4+100 Test if $1 is less than $2 register
branch on less than or equal ble $1,$2,100 if($1<=$2) go to PC+4+100 Test if $1 is less than or equal to $2 register

Conditional branch instructions uses I-format. In general the branch instructions are given as:

Opcode, $rs, $rt, immediate value

Untitled Diagram-Page-3 drawio

The immediate value (which is 100 in above example) is allocated with sign extended 16 bits.

5.Comparision

Instruction Example Meaning Explanation
set on less than slt $1,$2,$3 if($2<$3)$1=1; else $1=0 Test if $2 less than $3. If true, set $1 to 1. Otherwise, set $1 to 0
set on less than immediate slti $1,$2,100 if($2<100)$1=1; else $1=0 Test if $2 less than 100. If true, set $1 to 1. Otherwise, set $1 to 0

6.Unconditional jump

Instruction Example Meaning Explanation
jump j 1000 go to address 1000 jumps to the specified target address without any condition
jump register jr $1 go to address stored in $1 jump to the address of the specified register
jump and link jal 1000 $ra=PC+4; go to address 1000 jump to the specified address and return address is stored in $ra register

7.System call

  • In computer architecture, a system call is a request to the operating system's kernel to perform a specific task or operation on behalf of a user program or application.

  • A system call is a mechanism that allows user-level processes to request services from the operating system.

why system calls?

  • CPUs can perform basic operations like arithmetic and memory access, but for tasks such as printing or reading from a keyboard, additional software like libraries and the operating system is needed.
  • CPUs provide a mechanism for interacting with the operating system through system calls. On the MIPS architecture, the syscall instruction is used to initiate these calls

image

Syscall Number Arguments Result
print_int 1 $a0 = integer Value is printed
print_float 2 $f12 = float Float value is printed
print_double 3 $f12 = double Double value is printed
print_string 4 $a0 = string String is printed
read_int 5 - Integer read is returned in $v0
read_float 6 - Float read is returned in $f0
read_double 7 - Double read is returned in $f0
read_string 8 $a0 = buffer, $a1 = len String read is stored in the buffer
sbrk 9 $a0 = amount The sbrk service returns the address to a block of memory containing n additional bytes. This would be used for dynamic memory allocation.
exit 10 - Exits the program

MIPS Code to print an integer , string and to exit the program

.data
str: .asciiz "Hello, MIPS Assembly!"  # Example string

.text
main:
    li $v0, 1       # $system call code for print_int
    li $a0, 5       # $integer to print
    syscall         # print it

    li $v0, 4       # $system call code for print_str
    la $a0, str     # Load the address of the string
    syscall         # print it

    li $v0, 10      # $system call code for exit
    syscall         # exit program 

console output

pseudo instructions

Pseudo instructions also known as pseudo-ops or assembler directives, are not actual machine instructions but rather instructions used by the assembler or compiler to generate machine code. These instructions are specific to the assembly language or compiler being used and do not have a direct equivalent in the machine's instruction set.

Here are some common pseudo instructions in MIPS along with examples:

  1. li (Load Immediate): Assigns an immediate value to a register

    li $t0, 42 # $t0 = 42

  2. la (Load Address): Loads the address of a label or variable into a register.

    la $a0, array # $a0 = address of 'array'

  3. move: Copies the value from one register to another.

    move $t1, $t0 # $t1 = $t0

Translating Pseudo instructions to actual Instruction

Pseudoinstruction Translation mipscode
move $dest, $src add $dest, $src, $zero or addu $dest, $src, $zero
li $dest, imm ori $dest, $zero, imm
la $t0, my_label lui $t0, %hi(my_label) ori $t0, $t0, %lo(my_label)
muli $dest, $src, imm li $at, imm mul $dest, $src, $at
blt $to, $t1, label slt $t2, $t0, $t1 bne $t2, $zero, label(less_than)
bgt $to, $t1, label slt $t2, $t0, $t1 bne $t2, $zero, label(greater_than)
ble $to, $t1, label slt $t2, $t0, $t1 bne $t2, $zero, label(less_than_equal)
bge $to, $t1, label slt $t2, $t0, $t1 bne $t2, $zero, label(greater_than_equal)

The ori(or immediate) instructions used to load immediate values into registers. However, it's more conventional and readable to use the li instruction for this purpose.

Multiplication in mips

In MIPS assembly, mul is the instruction used to perform multiplication. It's important to understand that MIPS registers are 32 bits wide, which means they can hold values up to 2^32 - 1. When you multiply two 32-bit values together, the result can potentially be up to 64 bits wide.

the mul instruction is a real instruction, not a pseudo instruction. It is a hardware-supported instruction provided by the MIPS architecture.

1. mul (Multiply):

  • Purpose: Multiplies two 32-bit numbers.
  • Result: Produces a 64-bit result.
  • Registers: Does not modify hi or lo registers.
  • Use Case: When you only need the lower 32 bits of the result.
  • Example: mul $v0, $a0, $a1

This multiplies the values in registers $a0 and $a1, storing the result in $v0.

2. mult (Multiply with Overflow Check):

  • Purpose: Used for signed integer multiplication.

  • Result: Also produces a 64-bit result.

  • Registers: Modifies both hi and lo registers.

  • Use Case: When you need greater accuracy and want to check for overflow.

  • Example:

      mult $s0, $s1
    
      mflo $t0
    

Here, mult multiplies the values in registers $s0 and $s1, and mflo retrieves the lower 32 bits of the result from the lo register.