1b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#include <stdio.h>
2d50650d6cb0e3577ba28b470a4e5f5df8368afaasewardj#include "opcodes.h"
3b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
48ef7224ba09b9320f1417cabbd56109e0408351esewardj/* The FLOGR insn reads from register R2 and writes to register R1 and
58ef7224ba09b9320f1417cabbd56109e0408351esewardj   R1 + 1. So we need to distinguish three cases:
68ef7224ba09b9320f1417cabbd56109e0408351esewardj
78ef7224ba09b9320f1417cabbd56109e0408351esewardj   (1) All three registers R1, R1 + 1, and R2 are distinct
88ef7224ba09b9320f1417cabbd56109e0408351esewardj   (2) R2 == R1
98ef7224ba09b9320f1417cabbd56109e0408351esewardj   (3) R2 == R1 + 1
108ef7224ba09b9320f1417cabbd56109e0408351esewardj
118ef7224ba09b9320f1417cabbd56109e0408351esewardj   These are tested by flogr1, flogr2, and flogr3, respectively. */
12b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
13b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj/* Call FLOGR on INPUT. The results are returned through the parms. */
148ef7224ba09b9320f1417cabbd56109e0408351esewardj
158ef7224ba09b9320f1417cabbd56109e0408351esewardj/* R2 != R1 && R2 != R1 + 1 */
16b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardjvoid
178ef7224ba09b9320f1417cabbd56109e0408351esewardjflogr1(unsigned long input, unsigned long *bitpos, unsigned long *modval,
188ef7224ba09b9320f1417cabbd56109e0408351esewardj       unsigned int *cc)
19b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj{
20b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   unsigned int psw;
21b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   register unsigned long value asm("4") = input;
22b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
23d50650d6cb0e3577ba28b470a4e5f5df8368afaasewardj   asm volatile ( FLOGR(2,4)
24b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj                  "ipm   %[psw]\n\t"
25b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj                  "stg   2, %[bitpos]\n\t"
26b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj                  "stg   3, %[modval]\n\t"
27b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj                  : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval),
28465adfd4c7776a768a7919e6119d0c144ae1aaeeflorian                    [psw]"=&d"(psw)
29b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj                  : [val] "d"(value)
30b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj                  : "2", "3", "cc");
31b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
32b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   *cc = psw >> 28;
33b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#if 0
34b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   printf("value = %lx,  bitpos = %lu,  modval = %lx,  cc = %d\n",
35b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj          value, *bitpos, *modval, *cc);
36b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#endif
37b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj}
38b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
398ef7224ba09b9320f1417cabbd56109e0408351esewardj/* R2 == R1 */
408ef7224ba09b9320f1417cabbd56109e0408351esewardjvoid
418ef7224ba09b9320f1417cabbd56109e0408351esewardjflogr2(unsigned long input, unsigned long *bitpos, unsigned long *modval,
428ef7224ba09b9320f1417cabbd56109e0408351esewardj       unsigned int *cc)
438ef7224ba09b9320f1417cabbd56109e0408351esewardj{
448ef7224ba09b9320f1417cabbd56109e0408351esewardj   unsigned int psw;
458ef7224ba09b9320f1417cabbd56109e0408351esewardj   register unsigned long value asm("2") = input;
468ef7224ba09b9320f1417cabbd56109e0408351esewardj
47d50650d6cb0e3577ba28b470a4e5f5df8368afaasewardj   asm volatile ( FLOGR(2,2)
488ef7224ba09b9320f1417cabbd56109e0408351esewardj                  "ipm   %[psw]\n\t"
498ef7224ba09b9320f1417cabbd56109e0408351esewardj                  "stg   2, %[bitpos]\n\t"
508ef7224ba09b9320f1417cabbd56109e0408351esewardj                  "stg   3, %[modval]\n\t"
518ef7224ba09b9320f1417cabbd56109e0408351esewardj                  : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval),
52465adfd4c7776a768a7919e6119d0c144ae1aaeeflorian                    [psw]"=&d"(psw), [val] "+d"(value)
538ef7224ba09b9320f1417cabbd56109e0408351esewardj                  :
548ef7224ba09b9320f1417cabbd56109e0408351esewardj                  : "3", "cc");
558ef7224ba09b9320f1417cabbd56109e0408351esewardj
568ef7224ba09b9320f1417cabbd56109e0408351esewardj   *cc = psw >> 28;
578ef7224ba09b9320f1417cabbd56109e0408351esewardj#if 0
588ef7224ba09b9320f1417cabbd56109e0408351esewardj   printf("value = %lx,  bitpos = %lu,  modval = %lx,  cc = %d\n",
598ef7224ba09b9320f1417cabbd56109e0408351esewardj          value, *bitpos, *modval, *cc);
608ef7224ba09b9320f1417cabbd56109e0408351esewardj#endif
618ef7224ba09b9320f1417cabbd56109e0408351esewardj}
628ef7224ba09b9320f1417cabbd56109e0408351esewardj
638ef7224ba09b9320f1417cabbd56109e0408351esewardj/* R2 == R1 + 1 */
648ef7224ba09b9320f1417cabbd56109e0408351esewardjvoid
658ef7224ba09b9320f1417cabbd56109e0408351esewardjflogr3(unsigned long input, unsigned long *bitpos, unsigned long *modval,
668ef7224ba09b9320f1417cabbd56109e0408351esewardj       unsigned int *cc)
678ef7224ba09b9320f1417cabbd56109e0408351esewardj{
688ef7224ba09b9320f1417cabbd56109e0408351esewardj   unsigned int psw;
698ef7224ba09b9320f1417cabbd56109e0408351esewardj   register unsigned long value asm("3") = input;
708ef7224ba09b9320f1417cabbd56109e0408351esewardj
71d50650d6cb0e3577ba28b470a4e5f5df8368afaasewardj   asm volatile ( FLOGR(2,3)
728ef7224ba09b9320f1417cabbd56109e0408351esewardj                  "ipm   %[psw]\n\t"
738ef7224ba09b9320f1417cabbd56109e0408351esewardj                  "stg   2, %[bitpos]\n\t"
748ef7224ba09b9320f1417cabbd56109e0408351esewardj                  "stg   3, %[modval]\n\t"
758ef7224ba09b9320f1417cabbd56109e0408351esewardj                  : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval),
76465adfd4c7776a768a7919e6119d0c144ae1aaeeflorian                    [psw]"=&d"(psw), [val] "+d"(value)
778ef7224ba09b9320f1417cabbd56109e0408351esewardj                  :
788ef7224ba09b9320f1417cabbd56109e0408351esewardj                  : "2", "cc");
798ef7224ba09b9320f1417cabbd56109e0408351esewardj
808ef7224ba09b9320f1417cabbd56109e0408351esewardj   *cc = psw >> 28;
818ef7224ba09b9320f1417cabbd56109e0408351esewardj#if 0
828ef7224ba09b9320f1417cabbd56109e0408351esewardj   printf("value = %lx,  bitpos = %lu,  modval = %lx,  cc = %d\n",
838ef7224ba09b9320f1417cabbd56109e0408351esewardj          value, *bitpos, *modval, *cc);
848ef7224ba09b9320f1417cabbd56109e0408351esewardj#endif
858ef7224ba09b9320f1417cabbd56109e0408351esewardj}
868ef7224ba09b9320f1417cabbd56109e0408351esewardj
87b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardjvoid
888ef7224ba09b9320f1417cabbd56109e0408351esewardjruntest(void (*func)(unsigned long, unsigned long *, unsigned long *,
898ef7224ba09b9320f1417cabbd56109e0408351esewardj                     unsigned int *))
90b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj{
91b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   unsigned long bitpos, modval, value;
92b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   unsigned int cc;
93b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   int i;
94b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
95b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   /* Value 0 is special */
96b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   value = 0;
978ef7224ba09b9320f1417cabbd56109e0408351esewardj   func(value, &bitpos, &modval, &cc);
98b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   if (modval != 0)  fprintf(stderr, "modval is wrong for %lx\n", value);
99b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   if (bitpos != 64) fprintf(stderr, "bitpos is wrong for %lx\n", value);
100b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   if (cc != 0)      fprintf(stderr, "cc is wrong for %lx\n", value);
101b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
102b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   /* Test with exactly 1 bit set */
103b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   for (i = 0; i < 64; ++i) {
104b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     value = 1ull << i;
1058ef7224ba09b9320f1417cabbd56109e0408351esewardj     func(value, &bitpos, &modval, &cc);
106b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     if (modval != 0) fprintf(stderr, "modval is wrong for %lx\n", value);
107b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value);
108b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     if (cc != 2)          fprintf(stderr, "cc is wrong for %lx\n", value);
109b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   }
110b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
111b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   /* Test with all bits 1 right from first 1 bit */
112b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   for (i = 1; i < 64; ++i) {
113b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     value = 1ull << i;
114b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     value = value | (value - 1);
1158ef7224ba09b9320f1417cabbd56109e0408351esewardj     func(value, &bitpos, &modval, &cc);
116b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     if (modval != (value >> 1)) fprintf(stderr, "modval is wrong for %lx\n", value);
117b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value);
118b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     if (cc != 2)          fprintf(stderr, "cc is wrong for %lx\n", value);
119b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   }
120b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj}
121b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
122b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
123b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardjint main()
124b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj{
1258ef7224ba09b9320f1417cabbd56109e0408351esewardj   runtest(flogr1);
1268ef7224ba09b9320f1417cabbd56109e0408351esewardj   runtest(flogr2);
1278ef7224ba09b9320f1417cabbd56109e0408351esewardj   runtest(flogr3);
128b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
129b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   return 0;
130b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj}
131