Chapter 8: Writing Full Values to Registers
This chapter will teach you how to write in any value (32-bits limited ofc) to a GPR. Knowing this will help you get around invalid Immediate Value ranges as that can be a nuisance sometimes.
Load Immediate Shifted
You will notice that unlike the li instruction, the lis instruction uses the UIMM range for Immediate Values. Thus any value from 0x0000 thru 0xFFFF will work. This allows you to write in any value to the upper 16 bits of any GPR.
The lis instruction will write the value of 0xUIMM0000 to rD, where UIMM is the Immediate Value used. Confused? Let's go over an example...
Example:
lis r10, 0x8034
Here's a picture of right before the instruction gets executed. r10 is outlined in magenta. The lis instruction is outlined in green.
NOTE: GDB prefers to show some 16-bit Immediate Values in Signed/Unsigned Decimal Form. Hence why 0x8034 is -32716 and 0xF5CC is 62924.
Now here's a picture of once the instruction has executed. r10 outlined in magenta.
We can see that r10 is now 0x80340000. So we've covered how to write the upper 16 bits of a GPR, now how do we write the lower 16 bits, and also make sure our upper 16 bits don't get destroyed?
Or Immediate
ori rD, rA, UIMM
The ori instruction won't make sense to you if I explain it literally since you haven't learned about logical operations yet. That will be Covered in Chapter 14. What you do need to know is that you can write any 32-bit value using this template....
YYYYZZZZ = 32-bit Value
rX = GPR
lis rX, 0xYYYY
ori rX, rX, 0xZZZZ
Let's continue on from our earlier example. We have r10 with the current value of 0x80340000. We want the value to be 0x8034F5CC. We can accomplish that with the following ori instruction.
ori r10, r10, 0xF5CC
We saw earlier that this exact instruction was present after the lis instruction in the above pics. Let's execute the ori instruction to see what happens...
We see the result in r10 is 0x8034F5CC. To recap, the following two instructions were used to write 0x8034F5CC to r10...
lis r10, 0x8034 #Write upper 16 bits ori r10, r10, 0xF5CC #Write lower 16 bits
Hey Vega, what about using the addi instruction instead?
The addi instruction won't work for every 32-bit value. This is because the addi instruction uses SIMM instead of UIMM. For example, look at the following code below...
lis r10, 0x8034 addi r10, r10, 0xF5CC
The code contains an invalid addi instruction. However, can we use a simple Assembler trick to make addi work universally...
.set value, 0x8034F5CC lis r10, value@ha addi r10, r10, value@l
The above uses what is called Assembler Directives. You will learn about Assembler Directives in Chapter 18. Until then, stick with using lis+ori. It's easier to visually understand, and it requires zero assembler directives.