views:

28

answers:

2

Hi,

I'm writing an assembly macro to a C-program, and being quite new with this I have gotten stuck on something. I'm trying to write a macro for moving data from a general purpose register to a special purpose register.

My problem is that the syntax I've found to move data from a GPR to an SPR takes a constant SPR value, while I want to use a variable one stored in another register.

# SPR is constant, rA is the value to be written
mtspr SPR, rA

I'm after something that looks like this:

# rA contains the number of the SPR, and rB the value to be moved.
AWESOMEmtspr rA, rB

Is there a reason there is no such macro available, and how would I make it myself?

Many thanks in advance.

---- Edit: ---- As it looks now I have a giant switch case in my C-code that jumps to the correct mtspr-section. I have twenty-some sections for reading and writing specifit SPR:s that each look exactly the same, but differ by a constant value.

A: 

This seems like a bizarre thing to do, but if you're convinced you need to do this for some reason then you'll need to implement a jump table or sequence of conditionals whereby you test rA and jump to the appropriate hard-coded mtspr instruction. You'll need to think about how you handle invalid SPR numbers too.

Paul R
Currently I do exactly that. I have a huge switch-case based in an enum in my C-code that jumps to the correct instructions. As it looks now I have a ton of mtspr-instructions that only differ by constants. I would be a much happier programmer if I could get rid of all that code.
Nubsis
+1  A: 

The reason you can't do it is that the instruction architecture doesn't accept register-indirect as an addressing mode for the register parameter. Honestly, I've never seen a machine architecture that does, as the number of registers is usually fairly small, so the register is encoded as part of the instruction itself. If you really don't like the solution you've got, you can try to synthesize the instruction yourself (take the base opcode, see where the register specifier goes and OR in the appropriate value), then execute it. Depending on your OS and compiler, this may not be possible (self-modifying code is often taboo).

Does it make the code cleaner if you write the jump table in assembly? Maybe pass in the SPR specifier (assuming it's a zero-based integer, or can be coerced into one), shift it left to get the offset into the jump table, then jump into the table, which would be a sequence of

MTPSR PSRx, val
RET
MTPSR PSRx+1, val
RET

I don't know what counts as "cleaner" to you, just thought I'd throw that out. Note that you might have to pad with NOPs to get everything aligned, I don't have a PowerPC manual so I have no idea what the instruction sizes or alignment requirements are.

TMN
I suppose there will have to be code you are not fully comfortable with. I would like to keep as much code as possible in C, but I suppose I will settle with what I have. Thanks anyway.
Nubsis