Flag abuse and ""extended"" flag register set
moony
Posts: 27
in Propeller 2
As it turns out, it's possible to implement every necessary operation to pretend the GPR are just additional flag registers. This enables some neat tricks with conditionals/etc. I figured this out while working on the LLVM backend, and used it to tell LLVM a bit of a white lie, so it thinks the P2 has a nice 514 flag registers, not two. Should net some better codegen around flag handling (especially boolean logic) if I do this right. (The generated code for the P2's regfile is also an additional 5000 lines longer. Tablegen description remains under 100 lines.)
' XOR flag, flag modc 0b0110 ' C = C ^ Z modz 0b0110 ' Z = C ^ Z ' XOR flag, reg[0] testb reg, #0 xorc ' C = C ^ reg[0] testb reg, #0 xorz ' Z = Z ^ reg[0] ' XOR reg[0], flag ' The first and only non-trivial one. I thought it wouldn't work at first. ' Thanks to Wuerful_21 for telling me about this; I didn't think to abuse predicates! if_c xor reg, #1 ' reg[0] = reg[0] ^ C if_z xor reg, #1 ' reg[0] = reg[0] ^ Z ' XOR reg[0], reg[0] ' I couldn't think of a 1 instr solution to this, nor a 'don't clobber other regs' solution. ' In the LLVM backend, I simply opt to clobber the whole register to do it in 1 instr. xor reg, reg ' NOT flag modc 0b1010 ' C = !C modz 0b1010 ' Z = !Z ' NOT reg[0] xor reg, #1 ' Doing the above for all other bitwise ops is left as an exercise for the reader. (It's pretty easy)
Comments
My favourite abuse is RET WCZ in leaf routines. Then I can use the flags in higher level loops without needing to explicitly preserve them.
I wonder if a set of pseudo-instructions could be nice for this. The LLVM backend I'm writing does exactly that, providing the following pseudo-instrs: