setting program counter on power8


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.

#include <stdio.h>
#include <stdint.h>

void* foo(){

void* addr = __builtin_return_address(0);

printf(“in foo addr: %p\n”, addr);

return addr;

int main(){

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” );

return 0;

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:
bcl 20,31,$+4

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.


Setting PC to an arbitrary value _is_ branching.

The $ in the "bcl 20,31,$+4" means "current program counter". Since bl and bcl use relative addressing, in inline assembly you could just write "bcl 20,31,4".

There are branch instructions that use absolute address as the immediate operand, but they don't cover the entire address space. If you want to be able to branch to anywhere, use the LR or CTR as the branch target.