Arithmetic Overflow in mips - mips

I am just started learning exception handler of MIPS instruction.
I need to make my program to have Arithmetic overflow exception so that i can test my exception handler.
I have two array A and B. Array A has hex number and Array B has integers.
How to make overflow by adding hex number and integer ?
The addition of which hex number and integer can cause overflow?

According to the MIPS instruction reference, the only addition operations which can produce overflow exceptions are the signed addition instructions:
ADD
ADDI
MIPS integers are 32-bit, and since you'll be using signed integers, the maximum value is 231-1 (aka 2147483647 or hex 7FFFFFFF). Thus any addition which results in a number larger than this should throw an exception, e.g if you try to add 1 to 2147483647:
# Load 2147483647 into $s1
LUI $s0, 32767
ORI $s1, $s0, 65535
# Add 1 to $s1 and store in $s2. This should produce an overflow exception
ADDI $s2, $s1, 1

Related

How to translate MIPS into C and how to reduce MIPS instructions?

Supposing that f, g, h, i are stored in $s0~$s4 respectively and the base addresses of arrays A and B are in $S6 and $S7.
sll $t0, $s0, 2
add $t0, $s6, $t0
sll $tl, $sl, 2
add $tl, $s7, $tl
lw $s0, 0($t0)
addi $t2 , $t0, 4
lw $t0, 0($t2)
add $t0, $t0, $s0
SW $t0, 0($tl)
I'm not familiar with MIPS so I Wonder how to translate MIPS into C and how to minimize these MIPS instructions?
how to translate MIPS into C
You recognize the patterns, here for array indexing / array element access.
On a byte addressable machine (all modern hardware), a 4-byte integer occupies 4 bytes in memory, and each of those bytes has a unique memory address.  Because of the way the hardware works, we only use one of those 4 addresses to refer to the whole 4-byte integer, namely we use the lowest address among the 4.  The hardware can load a 4-byte integer from memory given that one address (the lowest).
Since each 4-byte integer in memory occupies 4 addresses, in an array of 4-byte integers, the memory address of the first element and the memory address of the second element are 4 addresses apart even though are sequential index positions (i.e. they are only 1 index position apart).
The formula for indexing a 4-byte integer array, then is to convert the index into a byte offset, then add the byte offset to the base address of the array.  The first part of that: converting an index to a byte offset, is sometimes referred to as "scaling".  Scaling is conceptually done by multiplication, so in A[i], i needs to be scaled by the size of the array elements of A.  If 4-byte integers that means scaling (multiplying) the index by 4.  A quick way of doing that is shifting by 2 bit positions, which has the same effect as multiplying by 4.
The C language automatically scales when doing array references, whereas assembly language requires explicit scaling.  C can do this because it knows the type of the array, whereas assembly language does not.
In C we can do expressions like A[i].  The C language allows us to break that down somewhat into *(A+i), which separates the pointer arithmetic addition A+i from the dereferencing of that sum, dereferencing with the unary indirection operator, *.  As previously mentioned, C automatically scales, so A+i becomes the equivalent of A+i*4, in which we can substitute shifting for multiplication: A+(i<<2).
Next, we need to know if the dereference is for read or for write.  When A[i] is accessed for its value, we will see it on what we call the "right hand side" of an assignment operator, as in ... = A[i].  When A[i] is access to update/store a value, we will see it on what we call the left hand side of an assignment operator, as in A[i] = ....
So, the sequence for doing A[i] for read (right hand side) in C is the following in assembly:
sll $temp1, $i, 2
addu $temp2, $A, $temp1
lw $temp3, 0($temp1)
Where $tempN is some register (usually a designated temporary) chosen to hold an intermediate value.  Since multiple instructions are needed to accomplish anything, sequences of instructions are interconnected with registers that hold the intermediate states.  And also, in assembly we name registers, not variables, so in my above $i and $A should be a registers names representing those variables rather than variable names directly used.
The pattern for write/store array access is similar but ends with a sw instruction instead, to store some value into memory at the index position.
These instruction sequence are interconnected by the use of these registers, and the sequences can be interrupted or interspersed with other instructions — what we have to follow then is the above pattern by paying attention to to the register usages that interconnect them rather than the specific sequences.
In your sample code:
sll $t0, $s0, 2 # sourcing an index in $s0, scaling it into temp $t0
add $t0, $s6, $t0 # adding a base array in $s6, putting back into $t0
sll $tl, $sl, 2
add $tl, $s7, $tl
lw $s0, 0($t0) # accessing the value of $s6[$s0*4], aka A[f]
addi $t2 , $t0, 4
lw $t0, 0($t2)
add $t0, $t0, $s0
SW $t0, 0($tl)
We can see the pattern for a read access to an index in $s0, and an array in $s6, these, we are told, map to f and A, so those three instructions comprise A[f] to read a value from A at index f.
The rest are done similarly.  Your job is to use this knowledge to find the other array indexing patterns in the above sequence.  Find out how the results of the array indexing operations are used and you'll have the complete C code.
NOTE that the sample you've been given incorrectly uses add and addi when pointer arithmetic should use addu and addiu — we don't want signed integer overflow checking on pointer arithmetic, as pointers are unsigned.
One of the add instructions is not for pointer arithmetic, but should probably still have used addu if this is intended to be replicated in C, because the C language does not have a built in operator to trap on overflow.

MIPS recursive function flow

I am new to MIPS and I have a given MIPS recursive code which I have to apply it to a specific number (ex. number 3)
Bellow is the given MIPS code and I am supposed to write if I were to pass ex. number 3 in the function what would be the changes in the registries and cache for the recursion for said number 3?
I have tried to do it step by step on a piece of paper but got nowhere.
fact:
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $a0, 0($sp)
slti $t0,$a0,1
beq $t0,$zero,L1
addi $v0,$zero,1
addi $sp,$sp,8
jr $ra
Ll:addi $a0,$a0,-1
jal fact
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
mul $v0,$a0,$v0
jr $ra
Always test your code with the smallest possible input first.  If you try with 0, and single step some 8 instructions worth, you can observe that your code doesn't return to its caller with the proper stack pointer value — an important part of functions is to preserve the registers that must be preserved for the caller, and that includes the stack pointer.  Usually, the way to restore the stack pointer is to deallocate any allocated space, and as long as this is balanced, the preservation rule for $sp is honored.
As a result of an improper stack pointer, the caller is messed up.  Where this bites you, then is when the caller tries to return to its caller.  Likely this is not a problem for main b/c on MARS, for example, we usually exit main via the exit syscall.  However, if you do fact(2), you'll see that the first return it executes works ok, but after that the caller (fact itself, recursive caller) doesn't work — it is unable to return to its caller, because it cannot properly restore its previously preserved $ra, because the stack pointer has been unbalanced by the terminal case.
We need to balance prologue with epilogue: not just statically but dynamically.
Your code is allocating stack space in all cases, though in the terminal case, your code is omitting the deallocation of the stack, so it becomes unbalanced.
Either add stack adjustment (deallocation) to the terminal case, or, test for the terminal case before even allocating stack space (so you don't have to either allocate or deallocate in that terminal case).

MIPS multu overflow

As part of a hex to decimal program I'm writing in MIPS using QT spim I load the value of 16^7 (268435456) into a generic register. I then multiply this number by 1-15 depending on the character, add the result to a running total, and divide 16^7 by 16.
However, I encounter what I assume to be overflow issues when multiplying 268435456. For instance, the code
li $t0, 10
li $t1, 268435456
multu $t0, $t1
mflo $t2
li $v0, 10
syscall
Which is intended to multiply 268435456 by 10 and store the result in $t2 stores -1610612736 instead of 2684354560. Any ideas on how to fix this code to store the correct value?
multu is the unsigned version of mult, which means that it is not going to generate an overflow because the result is taken as an unsigned number. When you show the value through a syscall it is taken as a signed number, so the signed value is shown (which in this case is negative).
You didn't give much info regarding what you are trying to achieve, but if you mean to perform a signed multiplication (meaning you want to keep the sign of the result) and store the result in a 32 bit register then you are going to run into limitations. If this is the case you will need to check whether the operation is possible within these bounds before printing the results, meaning you have to check whether the overflow happened:
li $t0, 10
li $t1, 268435456
multu $t0, $t1
mflo $t2
li $t3, 31
srl $t0, $t0, $t3
srl $t1, $t1, $t3
srl $t2, $t2, $t3
xor $t0, $t0, $t1
xor $t0, $t0, $t2
bgtz $t0, noOperationRoutine
li $v0, 10
syscall
noOperationRoutine:
....
The above solution performs a check on the leftmost bit (obtained by shifting right by 31 bits), which is indicative of the sign (1 for negative and 0 for positive). If one and only one of the operands is negative, then the result should be negative. If both are negative or positive, then the result should be positive. I think you can see how the two xors perform this check.
If you want to work with results that are bigger than the maximum size of a signed number then you have to keep in mind that mult stores the low part of the result in LO and the high part in HI. At this point you are going to deal with 64 bits numbers, which occupy two words/registers each.

How does 'alignment of memory operands' help MIPS to be pipelined?

How does 'alignment of memory operands' help MIPS to be pipelined?
The book says:
Fourth, as discussed in Chapter 2, operands must be aligned in memory. Hence,
we need not worry about a single data transfer instruction requiring two data
memory accesses; the requested data can be transferred between processor and
memory in a single pipeline stage.
I think I understand that one data transfer instruction does not require two or more data memory aaccesses.
However, I am not sure what does it have to do with the alignment of memory operands.
Thanks, in advance!
The lw instruction requires that the memory address be word aligned.
Therefore, to access an unaligned word, one would need to access the two word boundaries that the required word intersects and mask out the necessary bytes.
For example, suppose you desire to load a word stored at address 0x2. 0x2 is not word aligned, so you would need to load the half word stored at 0x2 and the half-word stored at 0x4.
To do so, one might write:
lh $t0 2($zero)
lh $t1 4($zero)
sll $t1 $t1 16
or $t2 $t0 $t1
This only gets more complicated if you want to load for example a word stored at address 0x3:
# load first byte
lb $t0 3($zero)
# load second word, mask out first 3 bytes
lw $t1 4($zero)
lui $t2 0x0000FFFF
ori $t2 $t2 0xFFFFFFFF
or $t1 $t1 $t2
# combine
sll $t1 $t1 8
or $t2 $t0 $t1
So, it can be seen that the requirement for word alignment doesn't help MIPS to be pipelined, but rather that access to unaligned words requires excess memory accesses — this is a limitation of the ISA.

Finding offset from a code snippet

I am a bit stuck up with the following question,
Consider the following MIPS code and answer the questions that follow.
addi $t1, $s0, 400
loop: lw $s1, 0($s0)
add $s2, $s2, $s1
lw $s1, 4($s0)
add $s2, $s2, $s1
addi $s0, $s0, 8
bne $t1, $s0, loop
What value is the label loop translated to in the conditional branch
instruction?
Now I know the mathematical formula for Branch Target Address. But here as memory addressing is not done so I found out the offset by counting the lines between the target address and PC. This gives the answer to be 7 (word offset). Am I right with this approach?
A quick experiment with MARS simulator http://courses.missouristate.edu/KenVollmar/MARS/download.htm gave me the answer-6, -5 for number of lines difference and another -1 because PC is increased by 1 after the instruction.
AFAIK, I'm afraid not.
As MIPS instruction reference says:
An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
is added to the address of the instruction following the branch (not
the branch itself), in the branch delay slot, to form a PC-relative
effective target address.
So as I understand, the distance from the branch instruction to the loop label is negative (because the label is before the branch, thus the address is lower). The distance is calculated in number of words (hence the 2 bits left shift). As all MIPS instructions are 4 bytes, this would be 6 instructions before, hence -6 is the value that should appear in the branch instruction offset (lower half-word). In binary: 1111 1111 1111 1010 (two's complement). In hexadecimal: FFFA.
Checked with simulator and seems that my reasoning is correct since the instruction is coded as 0x1530FFFA.