1 /* Emulate power6 mf[tf]gpr and fri[zpmn] instructions.
2 Copyright (C) 2006 Red Hat, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 It is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 extern double frip (double), friz (double), frin (double), frim (double);
24 asm (".globl frip, friz, frin, frim\n.hidden frip, friz, frin, frim\n\t"
26 ".section \".toc\",\"aw\"\n"
27 "8:" ".tc FD_43300000_0[TC],0x4330000000000000\n"
28 "9:" ".tc FD_3fe00000_0[TC],0x3fe0000000000000\n\t"
33 "8:" ".long 0x59800000\n"
34 "9:" ".long 0x3f000000\n\t"
40 "lfd 13,8b@toc(2)\n\t"
45 "addis 9,9,8b-1b@ha\n\t"
46 "lfs 13,8b-1b@l(9)\n\t"
65 "3:" "mtfsf 0x01,11\n\t"
70 "lfd 13,8b@toc(2)\n\t"
75 "addis 9,9,8b-1b@ha\n\t"
76 "lfs 13,8b-1b@l(9)\n\t"
95 "3:" "mtfsf 0x01,11\n\t"
100 "lfd 13,8b@toc(2)\n\t"
105 "addis 9,9,8b-1b@ha\n\t"
106 "addi 9,9,8b-1b@l\n\t"
117 "lfd 10,9b@toc(2)\n\t"
119 "lfs 10,9b-8b(9)\n\t"
128 "2:" "fsub 9,1,10\n\t"
133 "3:" "mtfsf 0x01,11\n\t"
136 "frim:" "mffs 11\n\t"
138 "lfd 13,8b@toc(2)\n\t"
143 "addis 9,9,8b-1b@ha\n\t"
144 "lfs 13,8b-1b@l(9)\n\t"
163 "3:" "mtfsf 0x01,11\n\t"
167 #define m1 0x5555555555555555L
168 #define m2 0x3333333333333333L
169 #define m3 0x0f0f0f0f0f0f0f0fL
171 #define m1 0x55555555
172 #define m2 0x33333333
173 #define m3 0x0f0f0f0f
176 static inline unsigned long
177 popcntb (unsigned long n
)
180 n
= (n
& m2
) + ((n
>> 2) & m2
);
181 n
= (n
+ (n
>> 4)) & m3
;
186 catch_sigill (int signal
, struct sigcontext
*ctx
)
188 unsigned int insn
= *(unsigned int *) (ctx
->regs
->nip
);
190 if ((insn
& 0xfc1f07ff) == 0x7c0005be) /* mftgpr */
192 unsigned long *regs
= (unsigned long *) ctx
->regs
;
193 unsigned fpr
= (insn
>> 11) & 0x1f;
194 unsigned gpr
= (insn
>> 21) & 0x1f;
195 regs
[gpr
] = regs
[fpr
+ 0x30];
199 if ((insn
& 0xfc1f07ff) == 0x7c0004be) /*mffgpr */
201 unsigned long *regs
= (unsigned long *) ctx
->regs
;
202 unsigned fpr
= (insn
>> 21) & 0x1f;
203 unsigned gpr
= (insn
>> 11) & 0x1f;
204 regs
[fpr
+ 0x30] = regs
[gpr
];
209 if ((insn
& 0xfc1f073f) == 0xfc000310) /* fri[pznm] */
212 double *regs
= (double *) (((char *) ctx
->regs
) + 0x30 * 8);
213 unsigned int *fpscr
= (unsigned int *) (((char *) ctx
->regs
) + 0x50 * 8 + 4);
215 double *regs
= (double *) (((char *) ctx
->regs
) + 0x30 * 4);
216 unsigned int *fpscr
= (unsigned int *) (((char *) ctx
->regs
) + 0x30 * 4 + 0x20 * 8 + 4);
218 unsigned dest
= (insn
>> 21) & 0x1f;
219 unsigned src
= (insn
>> 11) & 0x1f;
223 regs
[dest
] = frin (regs
[src
]);
226 regs
[dest
] = friz (regs
[src
]);
229 regs
[dest
] = frip (regs
[src
]);
232 regs
[dest
] = frim (regs
[src
]);
235 /* Update raised exceptions. */
236 union { unsigned int i
[2]; double d
; } u
;
237 asm volatile ("mffs %0" : "=f" (u
.d
));
238 u
.i
[1] &= 0xfffe0000; /* Is this correct? */
243 if ((insn
& 0xfc00ffff) == 0x7c0000f4) /* popcntb */
245 unsigned long *regs
= (unsigned long *) ctx
->regs
;
246 unsigned dest
= (insn
>> 16) & 0x1f;
247 unsigned src
= (insn
>> 21) & 0x1f;
248 unsigned long res
= 0;
251 regs
[dest
] = popcntb (regs
[src
]);
257 sa
.sa_handler
= SIG_DFL
;
258 sigemptyset (&sa
.sa_mask
);
260 sigaction (signal
, &sa
, NULL
);
265 __attribute__ ((constructor
))
266 install_handler (void)
269 sa
.sa_handler
= (void *) catch_sigill
;
270 sigemptyset (&sa
.sa_mask
);
271 sa
.sa_flags
= SA_RESTART
;
272 sigaction (SIGILL
, &sa
, NULL
);