MIPS overflow logic - overflow

Good evening. I am trying to figure out how to determine if an integer qualifies 16 bit integer in MIPS.
I understand that 2^15-1 =32767 or 2^(16-1)-1=32767 and that we want 16 bit values for binary number. Anyway, I am trying to determine if an integer passes the test. I wrote this:
addi $s3, $zero, 32767
bgt $t2, $s3, else #branch to else if t2>s3
move $v0, $t2 #if no overflow; place t2 in v0
addi $v1, $zero, 0 #if no overflow; place zero in v1
else:
addi $v0, $zero, 0 #if overflow; place 0 in v0
addi $v1, $zero, -1 #if overflow; place -1 in v1
Anyway, There's a problem with my logic when I try and evaluate negative numbers. I have assignment due tomorrow. I am learning MIPS programming. I am not a programming snob so any helpful advice is appreciate. Thank you for your time.

This is too late for you assignment1.
It's a bit unclear whenever you want to test a) if a number N encoded as a 32-bit two's complement number can be also encoded as a 16-bit two's complement number or if you want to test b) if a 32-bit number can be encoded as a 16-bit number.
In the case of b) you just need to test if any bit higher than the 16th is set:
#Assume $t0 is the number to test
lui $t1, 0xffff #$t1 = 0xffff0000
and $t1, $t1, $t0 #$t1 is zero if all higher bits of $t0 are zero
beq $t1, $0 fits16bits #Jump to label if fits
#Here the number doesn't fit 16 bits
For the case a) the key is to understand that just like the number 0x00f1 and the number 0x0000000f1 are the same, the leading zeros are not significant, the number 0xffff and the number 0xffffffff are the same number in two's complement (the number -1).
To extend a 16-bit two's complement number to 32-bit we need to perform a sign extension, i.e. replicate the most significant bit (the sign bit) of the original number in the upper 16 bits.
So 0x7fff becomes 0x00007fff, 0xc000 becomes 0xffffc0000.
A simple way to test that all the upper 17 bits are equal is to shift them right arithmetically so that if they actually are equal we end up with 0x00000000 or 0xffffffff.
sra $t1, $t0, 15 #Shift right 16 bits duplicanting the MSb
beqz $t1, $0, fits16bits #Jump to label if fits (All zero)
addiu $t1, 1 #Add 1
beqz $t1, $0, fits16bits #Jump to label if fits (Before +1 was all ones)
#Here the numbers doesn't fit
1 Maybe it's better this way.

Related

For loop counter in MIPS

so I'm currently trying to go through a for loop in MIPS and trying to multiply with it. I did the same thing with addition and it worked. Below, $t0 is the lower integer the user has entered, $t6 is the upper integer + 1, and $t4 is the register that stores the result. Here it is:
beq $t0, $t6, resultFunction
add $t4, $t4, $t0
addi $t0, $t0, 1
j addForLoop
What this does is store the lowest integer value a user has entered and then increments it to an upper integer value they have entered + 1 so that it increments correctly. It then adds appropriately and then increments the counter by 1, repeating if they are not the same. When the values are the same, it exits out of the loop. For example, if the values are 2 and 4, the answer would be 2 + 3 = 5, then 5 + 4 = 9. The loop would output with the answer 9 as it should. I tried to do this same thing but multiplying instead, and this is where my problem is. When trying to replace add with mul (like this),:
beq $t0, $t6, resultFunction
mul $t4, $t4, $t0
addi $t0, $t0, 1
j multForLoop
it is not working correctly and I'm getting 0 as the output instead. If the two integers are 2 and 4 again, it should output 24 (2 * 3 = 6, 6 * 4 = 24). I'm not quite sure why this isn't working and any help would be appreciated.
You haven't shown us all your code, but presumably $t4 is 0 when the loop starts, and anything multiplied by 0 equals 0.
Set $t4 to 1 before the loop.

How to count the number of cycles in code by hand?

We are learning pipeline processing and I have an exercise, where I have to count the number of cycles a MIPS code runs for - by hand. We have the following code in C and MIPS:
0. for (i=0; i<10; i++)
1. som = som + a[i];
0. add $t0, $zero , $zero
1. L:
2 sll $t1 , $t2, 2
3 add $t1 , $a0 , $t1
4 lw $t1, 0($t1)
5 add $v0, $v0, $t1
6 slti $t2, $t0, 9
7 addi $t0, $t0, 1
8 bne $t2, $zero, L
9 nop
The code inside the loop has 7 instructions and it is executed 10 times, therefore we get 70 cycles. Then we have a stall cycles in line 5 because of the load use hazard on $t1. Again the code runs 10 times, thus an additional 10 cycles. In total we now have 80 cycles. Because of the bne, we have 9 flushes (not 10 because after 9 we don't come back down). Therefore, now we have 89 cycles. We then have 1 cycle for the one NOP and 1 cycle for the initialisation of the variable i. This gives us a total of 91 cycles. In the MIPS reference sheet, it says to always add 4, because of the first line of code, thus bringing our total to 95 cycles.
Assuming I'm right, which I should be, is there a faster way to count the number of cycles in any MIPS code? I could use the equation CPI = # of cycles / clock rate but assuming we're not given that information and only have the given code, is there a way? I found that if you use the following equation, you get the right answer for the given code.
# of cycles = 4 + # of instructions x (# of pipeline levels - 1) + # of NOPs
However, I'm not sure if this works in general or I got lucky with my specific example. BTW - # refers to the number of.

Mips assembly language loop through array and isolates bits of interest

I need to loop through this array of bytes
testCases: .byte 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47
Im assuming I would do something like this, but not sure
ori $a1, $0, 0x0 # Initialize index with 0
LOOP:
lw $t1, testCases($a1)
...
...
addi $a1, $a1, 1 # Increment index by 1
j LOOP
and isolate the b6,b2,b1,b0 bits using a bitmask. I'm very new to mips and would appreciate any help. Thank you.
No, lw stands for load word. A word is 4 bytes. If you want to load a single byte you should use lb (if you want sign-extension) or lbu (if you want zero-extension).

How to improve cache performance on this MIPS code

Using a simulator called MARS 4.5 I am trying to improve the cache performance of this code. This is a sub section of an assembly program that computes prime numbers using the Sieve of Eratosthenes algorithm.
For some reason the sw (store word) has a cache hit rate of 25% where the rest of the program is averaging at about 50% in it's current state. I've tried rearranging some things but I can't figure out what is causing this bottleneck. What needs to be done in order to improve this cache hit rate?
inner: add $t2, $s2, 0 # save the bottom of stack address to $t2
mul $t3, $t1, 4 # calculate the number of bytes to jump over
sub $t2, $t2, $t3 # subtract them from bottom of stack address
add $t2, $t2, 8 # add 2 words - we started counting at 2!
sw $s0, ($t2) # store 1's -> it's not a prime number!
add $t1, $t1, $t0 # do this for every multiple of $t0
bgt $t1, $t9, outer # every multiple done? go back to outer loop
j inner # some multiples left? go back to inner loop
I was able to fix this issue by modifying the program to store bytes instead of words. This increased the number of storage blocks in the cache and thus increased the hit rate.
inner: add $t2, $s2, 0 # save the bottom of stack address to $t2
addi $t3, $t1, 1 # add one byte
sub $t2, $t2, $t3 # subtract them from bottom of stack address
add $t2, $t2, 2 # add 2 bytes - we started counting at 2!
sb $s0, ($t2) # store 1's -> it's not a prime number!
add $t1, $t1, $t0 # do this for every multiple of $t0
bgt $t1, $t9, outer # every multiple done? go back to outer loop
j inner # some multiples left? go back to inner loop

Using a random number generator in MIPS?

So I was reading a few threads on this site and I found one on how to make one..
But I can't really find a link that explains more about how to code it..
My textbook for the course didn't provide any information about RNG at all so no help there.
The code was
li $a1, 4
li $v0, 42
add $a0, $a0, 1
is this correct for asking for a range between 1-3?
I tried outputting what random number it was but it gave me the same number constantly.
#sw $a0, 0($s0)
li $a1, 4
li $v0, 42
add $a0, $a0, 1
#syscall
li $v0, 4
la $a0, Checking
syscall
li $v0, 1
move $t0, $a0
syscall
I saw the sw $a0, 0($s0) but I'm not sure what that does -- is it needed to output? (I took it out because after I pushed a key to go to the RNG, it said the program crashed)
I keep getting the output of 268501267 which I'm not sure what that means
edit: now it started giving me 268500992 all the time
Can anyone help explain this a little more in depth?
Logically speaking -- I understand the where the 42 comes from and why I need to add +1 (This is so I won't get the value of 0)
From there, I have no clue on why the code won't output a number in the range I gave.
As stated by MARS documentation (in the GUI Help > Syscalls):
random int 41 $a0 = i.d. of pseudorandom number generator (any int).
$a0 contains the next pseudorandom, uniformly distributed int value
from this random number generator's sequence
So
li $v0, 41 ; Service 41, random int
li $a0, 0 ; Select random generator 0
syscall ; Generate random int (returns in $a0)
li $v0, 1 ; Service 1, print int
syscall ; Print previously generated random int
Works fine for me, every time a different number is printed.
You don't need to initialize or seed a random stream before using it, you can just use stream 0.

Resources