| #include <stdio.h> |
| #include "opcodes.h" |
| |
| /* The FLOGR insn reads from register R2 and writes to register R1 and |
| R1 + 1. So we need to distinguish three cases: |
| |
| (1) All three registers R1, R1 + 1, and R2 are distinct |
| (2) R2 == R1 |
| (3) R2 == R1 + 1 |
| |
| These are tested by flogr1, flogr2, and flogr3, respectively. */ |
| |
| /* Call FLOGR on INPUT. The results are returned through the parms. */ |
| |
| /* R2 != R1 && R2 != R1 + 1 */ |
| void |
| flogr1(unsigned long input, unsigned long *bitpos, unsigned long *modval, |
| unsigned int *cc) |
| { |
| unsigned int psw; |
| register unsigned long value asm("4") = input; |
| |
| asm volatile ( FLOGR(2,4) |
| "ipm %[psw]\n\t" |
| "stg 2, %[bitpos]\n\t" |
| "stg 3, %[modval]\n\t" |
| : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval), |
| [psw]"=d"(psw) |
| : [val] "d"(value) |
| : "2", "3", "cc"); |
| |
| *cc = psw >> 28; |
| #if 0 |
| printf("value = %lx, bitpos = %lu, modval = %lx, cc = %d\n", |
| value, *bitpos, *modval, *cc); |
| #endif |
| } |
| |
| /* R2 == R1 */ |
| void |
| flogr2(unsigned long input, unsigned long *bitpos, unsigned long *modval, |
| unsigned int *cc) |
| { |
| unsigned int psw; |
| register unsigned long value asm("2") = input; |
| |
| asm volatile ( FLOGR(2,2) |
| "ipm %[psw]\n\t" |
| "stg 2, %[bitpos]\n\t" |
| "stg 3, %[modval]\n\t" |
| : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval), |
| [psw]"=d"(psw), [val] "+d"(value) |
| : |
| : "3", "cc"); |
| |
| *cc = psw >> 28; |
| #if 0 |
| printf("value = %lx, bitpos = %lu, modval = %lx, cc = %d\n", |
| value, *bitpos, *modval, *cc); |
| #endif |
| } |
| |
| /* R2 == R1 + 1 */ |
| void |
| flogr3(unsigned long input, unsigned long *bitpos, unsigned long *modval, |
| unsigned int *cc) |
| { |
| unsigned int psw; |
| register unsigned long value asm("3") = input; |
| |
| asm volatile ( FLOGR(2,3) |
| "ipm %[psw]\n\t" |
| "stg 2, %[bitpos]\n\t" |
| "stg 3, %[modval]\n\t" |
| : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval), |
| [psw]"=d"(psw), [val] "+d"(value) |
| : |
| : "2", "cc"); |
| |
| *cc = psw >> 28; |
| #if 0 |
| printf("value = %lx, bitpos = %lu, modval = %lx, cc = %d\n", |
| value, *bitpos, *modval, *cc); |
| #endif |
| } |
| |
| void |
| runtest(void (*func)(unsigned long, unsigned long *, unsigned long *, |
| unsigned int *)) |
| { |
| unsigned long bitpos, modval, value; |
| unsigned int cc; |
| int i; |
| |
| /* Value 0 is special */ |
| value = 0; |
| func(value, &bitpos, &modval, &cc); |
| if (modval != 0) fprintf(stderr, "modval is wrong for %lx\n", value); |
| if (bitpos != 64) fprintf(stderr, "bitpos is wrong for %lx\n", value); |
| if (cc != 0) fprintf(stderr, "cc is wrong for %lx\n", value); |
| |
| /* Test with exactly 1 bit set */ |
| for (i = 0; i < 64; ++i) { |
| value = 1ull << i; |
| func(value, &bitpos, &modval, &cc); |
| if (modval != 0) fprintf(stderr, "modval is wrong for %lx\n", value); |
| if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value); |
| if (cc != 2) fprintf(stderr, "cc is wrong for %lx\n", value); |
| } |
| |
| /* Test with all bits 1 right from first 1 bit */ |
| for (i = 1; i < 64; ++i) { |
| value = 1ull << i; |
| value = value | (value - 1); |
| func(value, &bitpos, &modval, &cc); |
| if (modval != (value >> 1)) fprintf(stderr, "modval is wrong for %lx\n", value); |
| if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value); |
| if (cc != 2) fprintf(stderr, "cc is wrong for %lx\n", value); |
| } |
| } |
| |
| |
| int main() |
| { |
| runtest(flogr1); |
| runtest(flogr2); |
| runtest(flogr3); |
| |
| return 0; |
| } |