On inline assembly, I spent some time trying to clobber float registers on inline assembly.
I was trying to clobber a float register, and I was getting:
unknown register name ‘f10’ in ‘asm’
After some debugging I found that the float registers should be clobbered as fr, so, here is an example where we are using and clobbering Counter Register, Conditional register, VSX and FP registers.
asm ( // prepare to merge low and high "mtvsrd 33, %[high_vs0] ;" "mtvsrd 34, %[low_vs0] ;" /* * ADJUST vs0 EXPECTED VALUE AFTER AN HTM FAILURE */ // vs0 = 0x5555555555555555555FFFFFFFFFFFFFFFF "xxmrghd 0, 33, 34 ;" /* * ADJUST vs32 EXPECTED VALUE AFTER AN HTM FAILURE */ // vs32 = 0x5555555555555555555FFFFFFFFFFFFFFFF "xxmrghd 32, 33, 34 ;" /* * Wait an amount of context switches so load_fp and load_vec * overflow and MSR.FP, MSR.VEC, and MSR.VSX become zero (off). */ "mtctr %[counter];" "1: bdnz 1b ;" /*Decrement CTR branch if CTR non zero */ /* * Do or don't touch FP prior to the test. * set MSR.FP = 1 before provoking a unavailable in TM * exception */ "cmpldi %[test_fp],0;" "beq no_fp ;" "fadd 10,10,10 ;" "no_fp: ;" /* * Do or don't touch VEC prior to the test * set MSR.VEC = 1 before provoking a unavailable in TM * exception */ "cmpldi %[test_vec],0;" "beq no_vec ;" "vaddcuw 10, 10, 10 ;" "no_vec: ;" /* * Perhaps it would be a better idea to do the * compares outside transactional context and simply * duplicate code */ "tbegin. ;" "beq trans_fail;" /* Do we do FP unavailable? */ "cmpldi %[exception],%[ex_fp];" "bne 1f ;" "fadd 10,10,10 ;" "b done ;" /* Do we do VEC unavailable? */ "1: cmpldi %[exception],%[ex_vec];" "bne 2f ;" "vaddcuw 10,10,10 ;" "b done ;" /* * Not FP or VEC, therefore VSX. Ensure this * instruction always generates a VSX Unavailiable. * ISA 3.0 is tricky here. * (xxmrghd will on 2.07 and 3.0) */ "2: xxmrghd 10,10,10;" "done: tend. ;" "trans_fail: ;" /* Give values back to C */ "mfvsrd %[high_vs0],0 ;" "xxsldwi 3,0,0,2 ;" "mfvsrd %[low_vs0],3 ;" "mfvsrd %[high_vs32],32 ;" "xxsldwi 3,32,32,2 ;" "mfvsrd %[low_vs32],3 ;" /* Give CR back to C so that it can check what happend */ "mfcr %[counter];" : [high_vs0] "+r" (high_vs0), [low_vs0] "+r" (low_vs0), [high_vs32] "=r" (high_vs32), [low_vs32] "=r" (low_vs32), [counter] "+r" (counter) : [test_fp] "r" (flags.test_fp), [test_vec]"r" (flags.test_vec), [exception]"r" (flags.exception), [ex_fp] "i" (FP_UNA_EXCEPTION), [ex_vec] "i" (VEC_UNA_EXCEPTION), [ex_vsx] "i" (VSX_UNA_EXCEPTION) /* * It is a mystery to me as to why "f10" doesn't work * in the clobbers */ : "cr0", "ctr", "v10", "vs0", "vs10", "vs3", "vs32", "vs33", "vs34", "fr10"