67 #include <linux/types.h>
68 #include <linux/sched.h>
70 #include <linux/perf_event.h>
71 #include <asm/uaccess.h>
79 #define FLOATFUNC(x) extern int x(void *,void *,void *)
125 #define FSR_TEM_SHIFT 23UL
126 #define FSR_TEM_MASK (0x1fUL << FSR_TEM_SHIFT)
127 #define FSR_AEXC_SHIFT 5UL
128 #define FSR_AEXC_MASK (0x1fUL << FSR_AEXC_SHIFT)
129 #define FSR_CEXC_SHIFT 0UL
130 #define FSR_CEXC_MASK (0x1fUL << FSR_CEXC_SHIFT)
132 static int do_one_mathemu(
u32 insn,
unsigned long *fsr,
unsigned long *fregs);
170 printk(
"In do_mathemu()... pc is %08lx\n", regs->
pc);
172 for (i = 0; i < fpt->
thread.fpqdepth; i++)
173 printk(
"%d: %08lx at %08lx\n", i, fpt->
thread.fpqueue[i].insn,
174 (
unsigned long)fpt->
thread.fpqueue[i].insn_addr);
177 if (fpt->
thread.fpqdepth == 0) {
179 printk(
"precise trap at %08lx\n", regs->
pc);
182 retcode = do_one_mathemu(insn, &fpt->
thread.fsr, fpt->
thread.float_regs);
185 regs->
pc = regs->
npc;
193 for (i = 0; i < fpt->
thread.fpqdepth; i++) {
194 retcode = do_one_mathemu(fpt->
thread.fpqueue[i].insn, &(fpt->
thread.fsr), fpt->
thread.float_regs);
202 fpt->
thread.fsr &= ~0x3000;
216 static inline int record_exception(
unsigned long *pfsr,
int eflag)
218 unsigned long fsr = *pfsr;
225 if (would_trap != 0) {
227 if ((eflag & (eflag - 1)) != 0) {
265 return (would_trap ? 0 : 1);
274 static int do_one_mathemu(
u32 insn,
unsigned long *pfsr,
unsigned long *fregs)
281 #define TYPE(dummy, r, ru, b, bu, a, au) type = (au << 2) | (a << 0) | (bu << 5) | (b << 3) | (ru << 8) | (r << 6)
292 printk(
"In do_mathemu(), emulating %08lx\n", insn);
295 if ((insn & 0xc1f80000) == 0x81a00000) {
296 switch ((insn >> 5) & 0x1ff) {
330 }
else if ((insn & 0xc1f80000) == 0x81a80000) {
331 switch ((insn >> 5) & 0x1ff) {
343 printk(
"attempt to emulate unrecognised FPop!\n");
349 freg = (*pfsr >> 14) & 0xf;
353 freg = ((insn >> 14) & 0x1f);
354 switch (type & 0x3) {
368 rs1 = (
argp)&fregs[freg];
369 switch (type & 0x7) {
374 freg = (insn & 0x1f);
375 switch ((type >> 3) & 0x3) {
389 rs2 = (
argp)&fregs[freg];
390 switch ((type >> 3) & 0x7) {
395 freg = ((insn >> 25) & 0x1f);
396 switch ((type >> 6) & 0x3) {
418 rd = (
void *)&fregs[freg];
422 printk(
"executing insn...\n");
425 switch ((insn >> 5) & 0x1ff) {
451 case FMOVS: rd->s = rs2->s;
break;
452 case FABSS: rd->s = rs2->s & 0x7fffffff;
break;
453 case FNEGS: rd->s = rs2->s ^ 0x80000000;
break;
474 (((insn >> 5) & 0x1ff) ==
FCMPES ||
483 (((insn >> 5) & 0x1ff) ==
FCMPED ||
492 (((insn >> 5) & 0x1ff) ==
FCMPEQ ||
498 switch ((type >> 6) & 0x7) {
500 if (IR == -1) IR = 2;
502 fsr &= ~0xc00; fsr |= (IR << 10);
break;
505 case 1: rd->s =
IR;
break;
513 return record_exception(pfsr, _fex);