sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 1 | #include <stdio.h> |
sewardj | d50650d | 2011-04-13 14:57:44 +0000 | [diff] [blame] | 2 | #include "opcodes.h" |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 3 | |
sewardj | 8ef7224 | 2011-03-24 08:58:42 +0000 | [diff] [blame] | 4 | /* The FLOGR insn reads from register R2 and writes to register R1 and |
| 5 | R1 + 1. So we need to distinguish three cases: |
| 6 | |
| 7 | (1) All three registers R1, R1 + 1, and R2 are distinct |
| 8 | (2) R2 == R1 |
| 9 | (3) R2 == R1 + 1 |
| 10 | |
| 11 | These are tested by flogr1, flogr2, and flogr3, respectively. */ |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 12 | |
| 13 | /* Call FLOGR on INPUT. The results are returned through the parms. */ |
sewardj | 8ef7224 | 2011-03-24 08:58:42 +0000 | [diff] [blame] | 14 | |
| 15 | /* R2 != R1 && R2 != R1 + 1 */ |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 16 | void |
sewardj | 8ef7224 | 2011-03-24 08:58:42 +0000 | [diff] [blame] | 17 | flogr1(unsigned long input, unsigned long *bitpos, unsigned long *modval, |
| 18 | unsigned int *cc) |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 19 | { |
| 20 | unsigned int psw; |
| 21 | register unsigned long value asm("4") = input; |
| 22 | |
sewardj | d50650d | 2011-04-13 14:57:44 +0000 | [diff] [blame] | 23 | asm volatile ( FLOGR(2,4) |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 24 | "ipm %[psw]\n\t" |
| 25 | "stg 2, %[bitpos]\n\t" |
| 26 | "stg 3, %[modval]\n\t" |
| 27 | : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval), |
| 28 | [psw]"=d"(psw) |
| 29 | : [val] "d"(value) |
| 30 | : "2", "3", "cc"); |
| 31 | |
| 32 | *cc = psw >> 28; |
| 33 | #if 0 |
| 34 | printf("value = %lx, bitpos = %lu, modval = %lx, cc = %d\n", |
| 35 | value, *bitpos, *modval, *cc); |
| 36 | #endif |
| 37 | } |
| 38 | |
sewardj | 8ef7224 | 2011-03-24 08:58:42 +0000 | [diff] [blame] | 39 | /* R2 == R1 */ |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 40 | void |
sewardj | 8ef7224 | 2011-03-24 08:58:42 +0000 | [diff] [blame] | 41 | flogr2(unsigned long input, unsigned long *bitpos, unsigned long *modval, |
| 42 | unsigned int *cc) |
| 43 | { |
| 44 | unsigned int psw; |
| 45 | register unsigned long value asm("2") = input; |
| 46 | |
sewardj | d50650d | 2011-04-13 14:57:44 +0000 | [diff] [blame] | 47 | asm volatile ( FLOGR(2,2) |
sewardj | 8ef7224 | 2011-03-24 08:58:42 +0000 | [diff] [blame] | 48 | "ipm %[psw]\n\t" |
| 49 | "stg 2, %[bitpos]\n\t" |
| 50 | "stg 3, %[modval]\n\t" |
| 51 | : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval), |
| 52 | [psw]"=d"(psw), [val] "+d"(value) |
| 53 | : |
| 54 | : "3", "cc"); |
| 55 | |
| 56 | *cc = psw >> 28; |
| 57 | #if 0 |
| 58 | printf("value = %lx, bitpos = %lu, modval = %lx, cc = %d\n", |
| 59 | value, *bitpos, *modval, *cc); |
| 60 | #endif |
| 61 | } |
| 62 | |
| 63 | /* R2 == R1 + 1 */ |
| 64 | void |
| 65 | flogr3(unsigned long input, unsigned long *bitpos, unsigned long *modval, |
| 66 | unsigned int *cc) |
| 67 | { |
| 68 | unsigned int psw; |
| 69 | register unsigned long value asm("3") = input; |
| 70 | |
sewardj | d50650d | 2011-04-13 14:57:44 +0000 | [diff] [blame] | 71 | asm volatile ( FLOGR(2,3) |
sewardj | 8ef7224 | 2011-03-24 08:58:42 +0000 | [diff] [blame] | 72 | "ipm %[psw]\n\t" |
| 73 | "stg 2, %[bitpos]\n\t" |
| 74 | "stg 3, %[modval]\n\t" |
| 75 | : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval), |
| 76 | [psw]"=d"(psw), [val] "+d"(value) |
| 77 | : |
| 78 | : "2", "cc"); |
| 79 | |
| 80 | *cc = psw >> 28; |
| 81 | #if 0 |
| 82 | printf("value = %lx, bitpos = %lu, modval = %lx, cc = %d\n", |
| 83 | value, *bitpos, *modval, *cc); |
| 84 | #endif |
| 85 | } |
| 86 | |
| 87 | void |
| 88 | runtest(void (*func)(unsigned long, unsigned long *, unsigned long *, |
| 89 | unsigned int *)) |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 90 | { |
| 91 | unsigned long bitpos, modval, value; |
| 92 | unsigned int cc; |
| 93 | int i; |
| 94 | |
| 95 | /* Value 0 is special */ |
| 96 | value = 0; |
sewardj | 8ef7224 | 2011-03-24 08:58:42 +0000 | [diff] [blame] | 97 | func(value, &bitpos, &modval, &cc); |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 98 | if (modval != 0) fprintf(stderr, "modval is wrong for %lx\n", value); |
| 99 | if (bitpos != 64) fprintf(stderr, "bitpos is wrong for %lx\n", value); |
| 100 | if (cc != 0) fprintf(stderr, "cc is wrong for %lx\n", value); |
| 101 | |
| 102 | /* Test with exactly 1 bit set */ |
| 103 | for (i = 0; i < 64; ++i) { |
| 104 | value = 1ull << i; |
sewardj | 8ef7224 | 2011-03-24 08:58:42 +0000 | [diff] [blame] | 105 | func(value, &bitpos, &modval, &cc); |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 106 | if (modval != 0) fprintf(stderr, "modval is wrong for %lx\n", value); |
| 107 | if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value); |
| 108 | if (cc != 2) fprintf(stderr, "cc is wrong for %lx\n", value); |
| 109 | } |
| 110 | |
| 111 | /* Test with all bits 1 right from first 1 bit */ |
| 112 | for (i = 1; i < 64; ++i) { |
| 113 | value = 1ull << i; |
| 114 | value = value | (value - 1); |
sewardj | 8ef7224 | 2011-03-24 08:58:42 +0000 | [diff] [blame] | 115 | func(value, &bitpos, &modval, &cc); |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 116 | if (modval != (value >> 1)) fprintf(stderr, "modval is wrong for %lx\n", value); |
| 117 | if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value); |
| 118 | if (cc != 2) fprintf(stderr, "cc is wrong for %lx\n", value); |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | |
| 123 | int main() |
| 124 | { |
sewardj | 8ef7224 | 2011-03-24 08:58:42 +0000 | [diff] [blame] | 125 | runtest(flogr1); |
| 126 | runtest(flogr2); |
| 127 | runtest(flogr3); |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 128 | |
| 129 | return 0; |
| 130 | } |