Reputation: 1
I am currently learning MIPS and would like some clarification on store/load word.
is:
sw $t0, 4($s0)
the same as
addi $s0, $s0, 4 # offsets are in bytes/word 8*4*4
sw $t0, 0($s0)
Additionally, I understand the offsets are 16 bits signed immediates. However, what if it was greater like a 32 bits immediate?
example
sw $t0, x($s0) # x is a 32bits offset
Upvotes: 0
Views: 2176
Reputation: 365576
what if it was greater like a 32 bits immediate?
Then MIPS instruction words would have to be longer, like 48 bits, to still have room for opcodes and register numbers plus 32-bit immediates.
But I think you're asking what if you had a 32-bit offset that was too big to use as an immediate?
The obvious way would be to do all the address calculation yourself, materializing the 32-bit value into a temporary register with lui
/addiu
and then using addu
to calculate the final address in a register. (Because MIPS doesn't have a reg+reg addressing mode, only reg+imm16
). But then we wouldn't be taking advantage of the imm16 in the load at all.
We can do better by using the low part of the offset as the immediate in the load, only using 2 extra instructions instead of 3. Compilers know this trick so it's easy to show an example:
char foo(char *p) {
return p[0x123456];
}
compiles with MIPS gcc5.4 on the Godbolt compiler explorer to this asm:
# gcc5.4 -O3 -fno-delayed-branch
foo:
li $2,1179648 # 0x120000
addu $4,$4,$2
lb $2,13398($4) # 0x3456($4)
j $31
nop
$4
is $a0
, $2
is $v0
. So this is doing reg += %hi(0x123456)
with lui / addu, then using %lo(0x123456)
as an offset to that.
A similar trick should be possible if you used a static array and a register index, but that's not what GCC actually does. Probably because it doesn't know if the low 16 of the static address will have its high bit set or not, so sign-extension creates a possible off-by-one for the upper half of the address. Maybe there's no relocation type that will account for that and adjust the %hi()
part according to the high bit of the %lo()
part, making this optimization impossible :/
I used char
so C wouldn't scale my index: array index = byte offset because sizeof(char) = 1
. lb
is a sign-extending load into a word register because that's how MIPS's calling convention works for narrow args.
Upvotes: 0