You're attempting to load a half word (lhu
) that is declared as a .byte
. That is a size mismatch, which goes to the error you're getting.
But the processor doesn't care about the size mismatch, but rather the alignment. So, if you want to load a half word (two bytes) they must start on an even byte boundary, which isn't the case for your data set up.
lhu $t0, b1
will work, as will lhu $t0,b3
, and lhu $t0,w1
as well because these data are at even addresses. However, b2
and b4
are at odd addresses.
A C compiler would not let you perform the size mismatched loads in the first place, without some serious casting, which would get you back to these unaligned errors on MIPS. Further, an x86 processor would allow the misaligned access, though in some cases those would be slower than the aligned equivalents.
Because misaligned accesses require more hardware and also that compilers can generally avoid these problems using their type systems to prevent them, some designs choose to forgo the extra hardware and MIPS is one of them.
You can also alter the alignment by inserting padding — one extra byte inserted between b1
& b2
would change b2
's alignment allowing to load b2
and b3
using lhu
. Because w1
is declare as a .word
the assembler knows it needs to be word aligned, so inserting that one byte between b1
& b3
will cause w1
to require 3 bytes of additional alignment padding (which the assembler will provide due to the .word
data declaration being used).
When you use this kind of size mismatch, there will also be the issue of endianness. The MIPS simulators will use the same endianness as the underlying processor so you'll generally see little endian behavior when loading 2 bytes. If you declare two .bytes
instead of using one .half
you will have to pick a byte order.