So the material on addressing modes may be length and scattered
You will have to scavenge the material on addressing modes by skimming verious parts of the book/manual...
I have done this for the SPARC....
The programmer must write a "small program" (several instructions) to get variables from memory.
In fact, you can say that the programming is "implementing" the address modes with simple instructions - this is called "micro programming".
By "clear cut", I mean, in M68000, you can see exactly what addressing mode is used by looking at one single instruction.
In SPARC, you may need multiple instructions to obtain the operand... which can be quite confusing...
Syntax: add %r1, %r2, %r3
add %r1, constant, %r3 (-212 <= constant <= 212-1)
Effect: r3 = r1 + r2
r3 = r1 + constant
Examples:
Instruction Effect
=========== ==============
add %i0, %i2, %i3 Reg. i3 = Reg. i1 + Reg. i2
add %i0, %g0, %i2 Reg. i2 = Reg. i1
(because Reg. g0 = 0 !)
add %i0, 0, %i2 Reg. i2 = Reg. i1
add %g0, %g0, %i2 Reg. i2 = 0
add %g0, 1, %i2 Reg. i2 = 1
Usage of the "add" operation:
Syntax: sethi constant, %r
Effect: r = constant * 210
Examples:
sethi 0, %i0
+----------+----------+----------+----------+
i0 = | 00000000 | 00000000 | 00000000 | 00000000 |
+----------+----------+----------+----------+
sethi 1, %i0
+----------+----------+----------+----------+
i0 = | 00000000 | 00000000 | 00000100 | 00000000 |
+----------+----------+----------+----------+
sethi 2, %i0
+----------+----------+----------+----------+
i0 = | 00000000 | 00000000 | 00001000 | 00000000 |
+----------+----------+----------+----------+
The "sethi" instruction is used to move the "high" portion of a large constant (such as a memory address) into a register.
The "sethi" instruction is typically followed by a second instruction that completes the lower portion of the constant.
Any (large) constant can be split into 2 half and put back together as follows:
(1) Let large constant be C
(2) Find highPortion = C / 1024 (quotient)
(3) Find lowPortion = C % 1024 (remainder)
(4) Then:
C = highPortion*1024 + lowPortion
For example:
C = 987654
C / 1024 = (quotient) = 964
C % 1024 = (remainder) = 518
Then: 964 * 1024 + 518 = 987654
Example:
Move 100000 into register i0:
(1) Find highPortion = 100000 / 1024 = 97
(2) Find lowPortion = 100000 % 1024 = 672
We can move 100000 into register i0 in 2 steps:
sethi 97, %i0 // Put in the high portion
add %i0, 672, %i0 // Add in the low portion
Making SPARC do the calculations of (/ 1024) and (% 1024)
The SPARC assembler has a "built-in" calculator that can
compute the division and remainder by 1024.
%hi(Value) == Value / 1024
%lo(Value) == Value % 1024
Therefore, we can move 100000 into register i0 using:
sethi %hi(100000), %i0 // Put in the high portion
add %i0, %lo(100000), %i0 // Add in the low portion
Example: move an address into a register
Labels are nothing more than a symbolic name for a number, they are in fact numbers.... huge numbers (32 bits). Hence, we can use the same old technique (of splitting big numbers up) to move (copy) addresses into a register: Let X be a label, like: X: .... We can move the address of X into a register by: sethi %hi(X), %i0 // Put in the high portion add %i0, %lo(X), %i0 // Add in the low PORTion
Syntax:
ld [%r1 + %r2], %r3
ld [%r1 + constant], %r3 (-212 <= constant <= 212-1)
Effect:
"ld [%r1 + %r2], %r3" loads the word (a word is
32 bits in SPARC) from the memory address that
is equal to the sum of the values in register r1
and r2, into the register r3
So, if r1 = 1000 and r2 = 16, then the word (32 bits)
at memory address 1016 is moved into register r3
"ld [%r1 + constant], %r3" loads the word
from the memory address that is equal to
the sum of the values in register r1 and
the constant, into register r3
The main usage of "ld" is to follow "sethi" to move data from
a memory location into a register.
Because a memory address is 32 bits, SPARC cannot specify the address
with 1 instruction and need to break the load instruction into 2 instructions.
Examples: move the value in the integer variable X into register i0
sethi %hi(X), %l0 // Puts high part of addr X // in local reg l0 add %l0, %lo(X), %l0 // Add in the low part of addr X // Now local reg l0 = address value of X ld [%l0 + 0], %i0 // Move the integer value from memory // at the addr given by l0 + 0 (= addr X) // into reg i0We can do better: again, move the value in the integer variable X into register i0
sethi %hi(X), %l0 // Puts high part of addr X // in local reg l0 ld [%l0 + %lo(X)], %i0 // Move the integer value // from memory at the addr // given by l0 + %lo(X) // into reg i0 // ... Since l0 = %hi(X), we have // that l0 + %lo(X) = addr X !!!
Syntax:
st %r3, [%r1 + %r2]
ld %r3, [%r1 + constant] (-212 <= constant <= 212-1)
Effect:
"st %r3, [%r1 + %r2]" stores (copies) the word
(a word is 32 bits in SPARC) from register r3 to
the memory location with the address that is equal
to the sum of the values in register r1 and r2
So, if r1 = 1000 and r2 = 16, then the word (32 bits)
from r3 is copied to memory location starting at 1016
"st %r3, [%r1 + constant]" stores the word
from register r3 into the memory location with
the address that is equal to the sum of the values
in register r1 and the constant
The main usage of "st" is to follow "sethi" to move data from
a register to memory.
Because a memory address is 32 bits, SPARC cannot specify the address
with 1 instruction and need to break the store instruction
into 2 instructions.
Examples: move the value in register i0 to the integer variable X
sethi %hi(X), %l0 // Puts high part of addr X // in local reg l0 add %l0, %lo(X), %l0 // Add in the low part of addr X // Now local reg l0 = address value of X st %i0, [%l0 + 0] // Move the 32 bit value from reg i0 to // memory at the addr given by l0 + 0 // (= addr X)We can do better: again, move the value in the integer variable X into register i0
sethi %hi(X), %l0 // Puts high part of addr X // in local reg l0 st %i0, [%l0 + %lo(X)] // Move the integer value // from rge i0 to memory starting // at the addr given by l0 + %lo(X) // ... Since l0 = %hi(X), we have // that l0 + %lo(X) = addr X !!!