2.11.1-7
[glibc.git] / fedora / power6emul.c
blob1b0187bddd961ab7a5250184f739af3588a12b7f
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
18 02111-1307 USA. */
20 #include <signal.h>
21 #include <stdio.h>
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"
25 #ifdef __powerpc64__
26 ".section \".toc\",\"aw\"\n"
27 "8:" ".tc FD_43300000_0[TC],0x4330000000000000\n"
28 "9:" ".tc FD_3fe00000_0[TC],0x3fe0000000000000\n\t"
29 ".previous\n\t"
30 #else
31 ".rodata\n\t"
32 ".align 2\n"
33 "8:" ".long 0x59800000\n"
34 "9:" ".long 0x3f000000\n\t"
35 ".previous\n\t"
36 #endif
37 "# frip == ceil\n"
38 "frip:" "mffs 11\n\t"
39 #ifdef __powerpc64__
40 "lfd 13,8b@toc(2)\n\t"
41 #else
42 "mflr 11\n\t"
43 "bcl 20,31,1f\n"
44 "1:" "mflr 9\n\t"
45 "addis 9,9,8b-1b@ha\n\t"
46 "lfs 13,8b-1b@l(9)\n\t"
47 "mtlr 11\n\t"
48 #endif
49 "fabs 0,1\n\t"
50 "fsub 12,13,13\n\t"
51 "fcmpu 7,0,13\n\t"
52 "fcmpu 6,1,12\n\t"
53 "bnllr- 7\n\t"
54 "mtfsfi 7,2\n\t"
55 "ble- 6,2f\n\t"
56 "fadd 1,1,13\n\t"
57 "fsub 1,1,13\n\t"
58 "fabs 1,1\n\t"
59 "mtfsf 0x01,11\n\t"
60 "blr\n"
61 "2:" "bge- 6,3f\n\t"
62 "fsub 1,1,13\n\t"
63 "fadd 1,1,13\n\t"
64 "fnabs 1,1\n"
65 "3:" "mtfsf 0x01,11\n\t"
66 "blr\n\t"
67 "# friz == trunc\n"
68 "friz:" "mffs 11\n\t"
69 #ifdef __powerpc64__
70 "lfd 13,8b@toc(2)\n\t"
71 #else
72 "mflr 11\n\t"
73 "bcl 20,31,1f\n"
74 "1:" "mflr 9\n\t"
75 "addis 9,9,8b-1b@ha\n\t"
76 "lfs 13,8b-1b@l(9)\n\t"
77 "mtlr 11\n\t"
78 #endif
79 "fabs 0,1\n\t"
80 "fsub 12,13,13\n\t"
81 "fcmpu 7,0,13\n\t"
82 "fcmpu 6,1,12\n\t"
83 "bnllr- 7\n\t"
84 "mtfsfi 7,1\n\t"
85 "ble- 6,2f\n\t"
86 "fadd 1,1,13\n\t"
87 "fsub 1,1,13\n\t"
88 "fabs 1,1\n\t"
89 "mtfsf 0x01,11\n\t"
90 "blr\n"
91 "2:" "bge- 6,3f\n\t"
92 "fsub 1,1,13\n\t"
93 "fadd 1,1,13\n\t"
94 "fnabs 1,1\n"
95 "3:" "mtfsf 0x01,11\n\t"
96 "blr\n\t"
97 "# frin == round\n"
98 "frin:" "mffs 11\n\t"
99 #ifdef __powerpc64__
100 "lfd 13,8b@toc(2)\n\t"
101 #else
102 "mflr 11\n\t"
103 "bcl 20,31,1f\n"
104 "1:" "mflr 9\n\t"
105 "addis 9,9,8b-1b@ha\n\t"
106 "addi 9,9,8b-1b@l\n\t"
107 "mtlr 11\n\t"
108 "lfs 13,0(9)\n\t"
109 #endif
110 "fabs 0,1\n\t"
111 "fsub 12,13,13\n\t"
112 "fcmpu 7,0,13\n\t"
113 "fcmpu 6,1,12\n\t"
114 "bnllr- 7\n\t"
115 "mtfsfi 7,1\n\t"
116 #ifdef __powerpc64__
117 "lfd 10,9b@toc(2)\n\t"
118 #else
119 "lfs 10,9b-8b(9)\n\t"
120 #endif
121 "ble- 6,2f\n\t"
122 "fadd 1,1,10\n\t"
123 "fadd 1,1,13\n\t"
124 "fsub 1,1,13\n\t"
125 "fabs 1,1\n\t"
126 "mtfsf 0x01,11\n\t"
127 "blr\n"
128 "2:" "fsub 9,1,10\n\t"
129 "bge- 6,3f\n\t"
130 "fsub 1,9,13\n\t"
131 "fadd 1,1,13\n\t"
132 "fnabs 1,1\n"
133 "3:" "mtfsf 0x01,11\n\t"
134 "blr\n\t"
135 "# frim == floor\n"
136 "frim:" "mffs 11\n\t"
137 #ifdef __powerpc64__
138 "lfd 13,8b@toc(2)\n\t"
139 #else
140 "mflr 11\n\t"
141 "bcl 20,31,1f\n"
142 "1:" "mflr 9\n\t"
143 "addis 9,9,8b-1b@ha\n\t"
144 "lfs 13,8b-1b@l(9)\n\t"
145 "mtlr 11\n\t"
146 #endif
147 "fabs 0,1\n\t"
148 "fsub 12,13,13\n\t"
149 "fcmpu 7,0,13\n\t"
150 "fcmpu 6,1,12\n\t"
151 "bnllr- 7\n\t"
152 "mtfsfi 7,3\n\t"
153 "ble- 6,2f\n\t"
154 "fadd 1,1,13\n\t"
155 "fsub 1,1,13\n\t"
156 "fabs 1,1\n\t"
157 "mtfsf 0x01,11\n\t"
158 "blr\n"
159 "2:" "bge- 6,3f\n\t"
160 "fsub 1,1,13\n\t"
161 "fadd 1,1,13\n\t"
162 "fnabs 1,1\n"
163 "3:" "mtfsf 0x01,11\n\t"
164 "blr\n");
166 #ifdef __powerpc64__
167 #define m1 0x5555555555555555L
168 #define m2 0x3333333333333333L
169 #define m3 0x0f0f0f0f0f0f0f0fL
170 #else
171 #define m1 0x55555555
172 #define m2 0x33333333
173 #define m3 0x0f0f0f0f
174 #endif
176 static inline unsigned long
177 popcntb (unsigned long n)
179 n -= (n >> 1) & m1;
180 n = (n & m2) + ((n >> 2) & m2);
181 n = (n + (n >> 4)) & m3;
182 return n;
185 static void
186 catch_sigill (int signal, struct sigcontext *ctx)
188 unsigned int insn = *(unsigned int *) (ctx->regs->nip);
189 #ifdef __powerpc64__
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];
196 ctx->regs->nip += 4;
197 return;
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];
205 ctx->regs->nip += 4;
206 return;
208 #endif
209 if ((insn & 0xfc1f073f) == 0xfc000310) /* fri[pznm] */
211 #ifdef __powerpc64__
212 double *regs = (double *) (((char *) ctx->regs) + 0x30 * 8);
213 unsigned int *fpscr = (unsigned int *) (((char *) ctx->regs) + 0x50 * 8 + 4);
214 #else
215 double *regs = (double *) (((char *) ctx->regs) + 0x30 * 4);
216 unsigned int *fpscr = (unsigned int *) (((char *) ctx->regs) + 0x30 * 4 + 0x20 * 8 + 4);
217 #endif
218 unsigned dest = (insn >> 21) & 0x1f;
219 unsigned src = (insn >> 11) & 0x1f;
220 switch (insn & 0xc0)
222 case 0:
223 regs[dest] = frin (regs[src]);
224 break;
225 case 0x40:
226 regs[dest] = friz (regs[src]);
227 break;
228 case 0x80:
229 regs[dest] = frip (regs[src]);
230 break;
231 case 0xc0:
232 regs[dest] = frim (regs[src]);
233 break;
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? */
239 *fpscr |= u.i[1];
240 ctx->regs->nip += 4;
241 return;
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;
249 int i;
251 regs[dest] = popcntb (regs[src]);
252 ctx->regs->nip += 4;
253 return;
256 struct sigaction sa;
257 sa.sa_handler = SIG_DFL;
258 sigemptyset (&sa.sa_mask);
259 sa.sa_flags = 0;
260 sigaction (signal, &sa, NULL);
261 raise (signal);
264 static void
265 __attribute__ ((constructor))
266 install_handler (void)
268 struct sigaction sa;
269 sa.sa_handler = (void *) catch_sigill;
270 sigemptyset (&sa.sa_mask);
271 sa.sa_flags = SA_RESTART;
272 sigaction (SIGILL, &sa, NULL);