3
votes

Feeling a little silly here, trying to work out what this line is doing:

addiu   sp,sp,-24

I understand that it is setting the stack pointer, my confusion is the addiu part. It's adding the UNSIGNED -24 to the stack pointer, and storing it back in the stack pointer.

Does sp take the value of the 16 bit -24(FFE8) (the "immediate" value of the addiu operation is 16 bits wide) or does it extend the sign to the full 32 bits?

Also, is sp=0 prior to this instruction? It is the first instruction in a trivial piece of c code.

I'm implementing a MIPS core as a personal project, and this has me a little stumped.

2

2 Answers

2
votes

The addiu instruction includes a 16-bit immediate operand. When the ALU executes the instruction, the immediate operand is sign-extended to 32 bits. If two's complement overflow occurs during the addition, it is ignored.

addiu   d,s,const        # $d <—— s + const. 
                         # Const is 16-bit two's comp. sign-extended to 32 bits
                         # when the addition is done. No overflow trap.
1
votes

Arithmetic Instructions

MIPS supports the four basic arithmetic operations: addition, subtraction, multiplication, and division.

Addition Instructions: The basic addition instruction

 add Rdest,Rsrc1,Rsrc2

adds contents of Rsrc1 and Rsrc2 and stores the result in Rdest. The numbers are treated as signed integers. In case of an overflow, an overflow exception is generated. addu can be used if no overflow exception is needed.

The second operand can be specified as an immediate 16-bit number. The format is:

 addi Rdest,Rsrc1,imm

The 16-bit value is sign-extended to 32 bits and added to the contents of Rsrc1. As in the add instruction, an overflow exception is generated. As in add, we can use addiu if an overflow exception is not needed.

Stack Implementation

The MIPS does not explicitly support stack operations. In contrast, it provides instructions such as push and pop to facilitate stack operations. In addition, there is a special stack pointer register sp that keeps the top-of-stack information. In the MIPS, a register plays the role of the stack pointer. We have to manipulate this register to implement the stack.

For example, the stack grows downward (i.e., as we push items onto the stack, the address de- creases). Thus, when reserving space on the stack for pushing values, we have to decrease the sp value. Thus, the relative value of the stack pointer at the beginning of execution could be taken as zero.

For example, to push registers a0 and ra, we have to reserve eight bytes of stack space and use sw to push the values as shown below:

sub $sp,$sp,8 # reserve 8 bytes of stack
sw $a0,0($sp) # save registers
sw $ra,4($sp)

This sequence is typically used at the beginning of a procedure to save registers. To restore these registers before returning from the procedure, we can use the following sequence:

lw $a0,0($sp) # restore the two registers
lw $ra,4($sp)
addu $sp,$sp,8 # clear 8 bytes of stack

So, the answer to your first question:

The 16-bit value is sign-extended to 32 bits and added to the contents of Rsrc1.

and to your second question:

Thus, the relative value of the stack pointer at the beginning of execution could be taken as zero.