I am new to RISC-V programming and assembly programming in general.
I want to move a 32 bit word from an address in memory, say 0x04000000
, to another address say 0x00000190
.
Do I have to load the data to a GPR first (using lw
?), then store to the new address (e.g. sw
?)? Or is there a more direct way?
Is there anything wrong with these instructions:
lw x8, 0(x67108864)
sw x8, 192(x0)
thanks
CodePudding user response:
You won't be able to encode that load instruction on RISC V, as it only allows for 12-bits of immediate/offset, and, it must follow the regular base displacement form usually written as disp(reg)
. Some assemblers will accept immediates of that size by expanding that line into multiple machine code instructions.
There are two additional instructions that can help form larger immediates:
LUI
— Load Upper Immediate provides for 20 bits of immediate that when combined in sequence with an I-Type instruction (which offer 12 bits of immediate) allows for a 32-bit immediate in 2 instructions.AUIPC
— Add upper immediate to the PC also provides for 20 bits of immediate and adds the immediate to the PC to form PC-relative addressing capability.
Additionally we can use shifts and other instructions as well.
Even if that load were encodable, the x
is a typo, since you want x4000000, aka 67,108,86410 (not x67108864).
That store instruction will encode is ok.
CodePudding user response:
I have had/issues with the volatile pointer thing, but it works here. You can have the tools show you how to do it...sometimes...
#define ONE (*((volatile unsigned int *)0x04000000))
#define TWO (*((volatile unsigned int *)0x00000100))
void fun ( void )
{
TWO=ONE;
}
which, for me, gives
00000000 <fun>:
0: 040007b7 lui x15,0x4000
4: 439c lw x15,0(x15)
6: 10f02023 sw x15,256(x0) # 100 <fun 0x100>
a: 8082 ret
you can often just use the li pseudo instruction and the assembler will pick the right combination of lui, addi, for you.