I’ve been working on powerpc and I’m having some trouble since there’s no PC register. What I would like to do is to be able to set PC to an arbitrary address that I want. I know that the only way to do this is to branch.
I’ve written the following code to be able to jump to the beginning of foo. I need to be able to use both immediate values and a register for introducing the address. I compiled on power8 with
clang -O3 power_pc_write.c -o power_pc_write
The code is working.
void* addr = __builtin_return_address(0);
printf(“in foo addr: %p\n”, addr);
void* addr = foo();
void* foo_addr = foo;
printf(“foo addr: %p\n”, foo_addr);
// This is for setting PC_IMM
asm volatile(“bl %0” : : “i” (foo) );
asm volatile(“bcl 20,31,%0” : : “i” (foo) );
// This is for setting PC_REG
asm volatile(“mflr 4; mtlr %0 ; bclrl 20,31” : : “r” (foo_addr): “r4” );
My concerns are as follows:
I’m not sure if there’s a specific way of setting PC to an arbitrary address other than branching. Am I doing this the right way?
I realized that bl instruction jumps to foo+8. But bcl does not. I couldn’t figure out why.
The ISA specification says that for gettin the the next instruction we can use this:
So I tried bcl first. But this is a conditional branch instruction. It’s not really clear to me why I need to use a conditional branch here.
Also I assumed that $ give me some sort of address. But I wasn’t able to use “$” in another way. Could you provide me hints on this?
I appreciate if you can help me clear these in my mind.
P.S. I’m using llvm 3.7. The ISA specification I’m currently workign with is PowerISA Version 3.0 B.