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 catch_sigill (int signal
, struct sigcontext
*ctx
)
169 unsigned int insn
= *(unsigned int *) (ctx
->regs
->nip
);
171 if ((insn
& 0xfc1f07ff) == 0x7c0005be) /* mftgpr */
173 unsigned long *regs
= (unsigned long *) ctx
->regs
;
174 unsigned fpr
= (insn
>> 11) & 0x1f;
175 unsigned gpr
= (insn
>> 21) & 0x1f;
176 regs
[gpr
] = regs
[fpr
+ 0x30];
180 if ((insn
& 0xfc1f07ff) == 0x7c0004be) /*mffgpr */
182 unsigned long *regs
= (unsigned long *) ctx
->regs
;
183 unsigned fpr
= (insn
>> 21) & 0x1f;
184 unsigned gpr
= (insn
>> 11) & 0x1f;
185 regs
[fpr
+ 0x30] = regs
[gpr
];
190 if ((insn
& 0xfc1f073f) == 0xfc000310) /* fri[pznm] */
193 double *regs
= (double *) (((char *) ctx
->regs
) + 0x30 * 8);
194 unsigned int *fpscr
= (unsigned int *) (((char *) ctx
->regs
) + 0x50 * 8 + 4);
196 double *regs
= (double *) (((char *) ctx
->regs
) + 0x30 * 4);
197 unsigned int *fpscr
= (unsigned int *) (((char *) ctx
->regs
) + 0x30 * 4 + 0x20 * 8 + 4);
199 unsigned dest
= (insn
>> 21) & 0x1f;
200 unsigned src
= (insn
>> 11) & 0x1f;
204 regs
[dest
] = frin (regs
[src
]);
207 regs
[dest
] = friz (regs
[src
]);
210 regs
[dest
] = frip (regs
[src
]);
213 regs
[dest
] = frim (regs
[src
]);
216 /* Update raised exceptions. */
217 union { unsigned int i
[2]; double d
; } u
;
218 asm volatile ("mffs %0" : "=f" (u
.d
));
219 u
.i
[1] &= 0xfffe0000; /* Is this correct? */
226 sa
.sa_handler
= SIG_DFL
;
227 sigemptyset (&sa
.sa_mask
);
229 sigaction (signal
, &sa
, NULL
);
234 __attribute__ ((constructor
))
235 install_handler (void)
238 sa
.sa_handler
= (void *) catch_sigill
;
239 sigemptyset (&sa
.sa_mask
);
240 sa
.sa_flags
= SA_RESTART
;
241 sigaction (SIGILL
, &sa
, NULL
);