How is the correct address calculated for accessing data in the MIPS data memory? Considering that the dynamic data segment starts at 0x10010000
and goes up to 0x7FFFFFFC
, when using the instruction sw $t0, 20($0)
, converting the decimal offset 20 to hexadecimal we would have 0x14, so the offset calculation would be done by 0x14 + read($0) = 0x14 + 0 = 0x14
.
This resulting value should be added to the starting address of the dynamic data segment (0x14 + 0x10010000
), to result in the address of the exact byte to be read.
My question is: How is this calculation done? Is it a calculation that is done directly by the operating system or is there a full-adder internal to the data memory that does this addition (SEE IMAGE BELOW). Or neither?
Consider the multi-cycle implementation of MIPS
For loads & stores, the addition of immediate to base register is accomplished via the main ALU using addition during the EX stage.
In any MIPS that I've seen, there is no adder in the (data) memory block.
This resulting value should be added to the starting address of the dynamic data segment (0x14 + 0x10010000), to result in the address of the exact byte to be read.
This would have to be done by the program's machine code, which that snippet (sw $t0, 20($0)
) does not have.
It could be accomplished via sw $t0, 20($gp)
instead, if $gp
were to hold the value 0x10010000
, which is a fairly normal configuration initialized for MIPS programs.
If there were an adder in the memory block, it would shift all memory accesses. So, in the case you're showing it would have to suppress the addition for instruction accesses. Such an addition would also prevent accesses to low memory, which may or may not be desirable, depending on what's stored there. Accesses to high memory would also be altered, such as might be used to access device memory (e.g. above 0x80000000). So, this would either require changes to the executable program's machine code to accommodate, or a very selective addition in the memory block — such as only add to data accesses (not code/instruction accesses), and then only if the value is in a certain range — fairly complicated.
Especially considering the expected way to do this with regular MIPS is to simply use the $gp
register as the base register (holding 0x10010000), allowing program the control to specify and perform that addition when it wants it.
Let's also note that the memory block is already sufficiently slow, so that performing an extra addition therein would slow it down further. This is one reason why regular MIPS preforms addition for loads & stores using the main ALU, and why the EX stage and MEM stage are separate (albeit in pipelined implementation, though a multicycle processor would likely have separate cycles for ALU vs. memory operations as well).