How to bind a register variable with a given general purpose register?

Hi everyone,

There are 16 GPRs in my RISC, but in fact GPR13 is read-only and connected to output of an A/D converter.
It would be very convenient if i could bind a register variable with GPR13.

Because i am a newbie i don’t know how my llvm backend can support that.

I plan to implement it as below.

A. first declare a global variable in c-code
int ADC asm(“GPR13”);
B. If backend finds a variable is loaded from “GPR13” use GPR13 instead.
C. backend can’t allocate GPR13 to other variable

Is it a foolish method? Is there a better one? Please give me some guidance

Thanks

hi zhu,

i think you should map the peripheral registers to data memory space instead of register file, then mark that memory address as "volatile".
like said the adc register was mapped to address 0xc0000, and then the corresponding c source will goes like this:
//define the register
#define ADCREG (*((volatile unsigned int *)0xc0000))
//read the register
a = ADCREG

--ether

hi zhu,

i am not sure if your c frontend support "int ADC asm("GPR13");"
i think you could:

1. add a attribute "GPR13"(or a more meaningful name like "adcreg") and
the corresponding handler, so you code "int ADC asm("GPR13");" became
"int ADC __attribute__((GPR13));"
2. add a intrinsic functions like "llvm.zhu.readadcreg()".
3. map any read to the variable marked with __attribute__((GPR13)) to
llvm.zhu.readadcreg() instead of "load" instruction
4. assign gpr13 to a special register class like "gpr13class" instead of
gprclass, so gpr13 will not be allocated as other gpr.
5. lower instrinisic functions "llvm.zhu.readadcreg()" to register node
"gpr13" in your backend.

regards

--ether

Hello

Is it a foolish method? Is there a better one? Please give me some guidance

Inline assembler is your friend. Also, do not forget to mark this
register as unallocable, so codegen won't use / clobber it.

or you can just add a built-in function in c frontend "readadcreg()" and
emit it as llvm.zhu.readadcreg(), so you can just call the built-in
function to get the adc register value.

If your end goal is to allow programs to use the output of the A/D
converter, my recommendation would be to create a platform-specific
intrinsic function that returns the output of the A/D converter, and
have your back-end refuse to allocate GPR13 as a register. The
intrinsic function would of course simply cough up the value of GPR13,
which would then be available for use in the program.