Reputation: 83
I am trying to translate from C this line of code of a nested array p=A[B[6]]
that I've found on the book I'm studying MIPS from.
Because I am pretty sure that the solution from the book is wrong or, at least, much more complicated than what it needs to be.
The base address of the array A[] is stored in the register $s1, the base address of B[] is stored in $s2 and the value of g is stored in $s0.
My translation of p=A[B[6]]
would be (please tell me if it is correct):
lw $t0, 24($s2) #load from memory B[6] in the register $t0
sll $t0, $t0, 2 #$t0=$t0*4
add $t0, $t0, $s1 #add to $t0 the address of A[B[6]]
lw $t0, 0($t0) #$t0=A[B[6]]
While instead the book (which is full of other errors) offers this solution:
addi $t0, $0, 6
sll sll $t0, $t0 2
add $t1, $s2, $t0
lw $t2, 0 ($t1)
sll $t2, $t2 2
add $t3, $s1, $t2
lw $s0, 0 ($t3)
Is my code correct or is the book right?
Upvotes: 1
Views: 426
Reputation: 365147
Both versions are logically correct; the only problem with the book version is that it's very inefficient.
It fails to optimize based on the fact that 6
is an assemble-time constant, so the 6*4
can be an immediate displacement in the lw
, instead of calculated at runtime in a register and added to the base separately.
lw
has room for 16 bits of immediate offset; it's silly not to take advantage and restrict yourself to only ever using 0
. It's an I-type instruction for a reason, dedicating lots of coding space to allowing a large offset.
Other than that your versions are equivalent. The book version calculates 6<<2
in a register and adds it to the base of B
($s2
). It gets the initial 6
into a register by adding to the zero-register.
Both yours and the book's use add
instead of addu
. Not sure why you want to trap on signed overflow, especially when doing address math. C compilers normally always use addu
. (Signed overflow is undefined behaviour in C, but compiler developers know that it's usually more useful / expected for it to silently wrap than to raise an exception.)
Upvotes: 1