Blame SPECS/power6emul.c

Packit Service 15db12
/* Emulate power6 mf[tf]gpr and fri[zpmn] instructions.
Packit Service 15db12
   Copyright (C) 2006 Red Hat, Inc.
Packit Service 15db12
   Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
Packit Service 15db12
Packit Service 15db12
   This library is free software; you can redistribute it and/or
Packit Service 15db12
   modify it under the terms of the GNU Lesser General Public
Packit Service 15db12
   License as published by the Free Software Foundation; either
Packit Service 15db12
   version 2.1 of the License, or (at your option) any later version.
Packit Service 15db12
Packit Service 15db12
   It is distributed in the hope that it will be useful,
Packit Service 15db12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 15db12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 15db12
   Lesser General Public License for more details.
Packit Service 15db12
Packit Service 15db12
   You should have received a copy of the GNU Lesser General Public
Packit Service 15db12
   License along with the GNU C Library; if not, write to the Free
Packit Service 15db12
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
Packit Service 15db12
   02111-1307 USA.  */
Packit Service 15db12
Packit Service 15db12
#include <signal.h>
Packit Service 15db12
#include <stdio.h>
Packit Service 15db12
Packit Service 15db12
extern double frip (double), friz (double), frin (double), frim (double);
Packit Service 15db12
asm (".globl frip, friz, frin, frim\n.hidden frip, friz, frin, frim\n\t"
Packit Service 15db12
#ifdef __powerpc64__
Packit Service 15db12
	".section \".toc\",\"aw\"\n"
Packit Service 15db12
"8:"	".tc FD_43300000_0[TC],0x4330000000000000\n"
Packit Service 15db12
"9:"	".tc FD_3fe00000_0[TC],0x3fe0000000000000\n\t"
Packit Service 15db12
	".previous\n\t"
Packit Service 15db12
#else
Packit Service 15db12
	".rodata\n\t"
Packit Service 15db12
	".align 2\n"
Packit Service 15db12
"8:"	".long 0x59800000\n"
Packit Service 15db12
"9:"	".long 0x3f000000\n\t"
Packit Service 15db12
	".previous\n\t"
Packit Service 15db12
#endif
Packit Service 15db12
	"# frip == ceil\n"
Packit Service 15db12
"frip:"	"mffs    11\n\t"
Packit Service 15db12
#ifdef __powerpc64__
Packit Service 15db12
	"lfd     13,8b@toc(2)\n\t"
Packit Service 15db12
#else
Packit Service 15db12
	"mflr    11\n\t"
Packit Service 15db12
	"bcl     20,31,1f\n"
Packit Service 15db12
"1:"	"mflr    9\n\t"
Packit Service 15db12
	"addis   9,9,8b-1b@ha\n\t"
Packit Service 15db12
	"lfs     13,8b-1b@l(9)\n\t"
Packit Service 15db12
	"mtlr    11\n\t"
Packit Service 15db12
#endif
Packit Service 15db12
	"fabs    0,1\n\t"
Packit Service 15db12
	"fsub    12,13,13\n\t"
Packit Service 15db12
	"fcmpu   7,0,13\n\t"
Packit Service 15db12
	"fcmpu   6,1,12\n\t"
Packit Service 15db12
	"bnllr-  7\n\t"
Packit Service 15db12
	"mtfsfi  7,2\n\t"
Packit Service 15db12
	"ble-    6,2f\n\t"
Packit Service 15db12
	"fadd    1,1,13\n\t"
Packit Service 15db12
	"fsub    1,1,13\n\t"
Packit Service 15db12
	"fabs    1,1\n\t"
Packit Service 15db12
	"mtfsf   0x01,11\n\t"
Packit Service 15db12
	"blr\n"
Packit Service 15db12
"2:"	"bge-    6,3f\n\t"
Packit Service 15db12
	"fsub    1,1,13\n\t"
Packit Service 15db12
	"fadd    1,1,13\n\t"
Packit Service 15db12
	"fnabs   1,1\n"
Packit Service 15db12
"3:"	"mtfsf   0x01,11\n\t"
Packit Service 15db12
	"blr\n\t"
Packit Service 15db12
	"# friz == trunc\n"
Packit Service 15db12
"friz:"	"mffs    11\n\t"
Packit Service 15db12
#ifdef __powerpc64__
Packit Service 15db12
	"lfd     13,8b@toc(2)\n\t"
Packit Service 15db12
#else
Packit Service 15db12
	"mflr    11\n\t"
Packit Service 15db12
	"bcl     20,31,1f\n"
Packit Service 15db12
"1:"	"mflr    9\n\t"
Packit Service 15db12
	"addis   9,9,8b-1b@ha\n\t"
Packit Service 15db12
	"lfs     13,8b-1b@l(9)\n\t"
Packit Service 15db12
	"mtlr    11\n\t"
Packit Service 15db12
#endif
Packit Service 15db12
	"fabs    0,1\n\t"
Packit Service 15db12
	"fsub    12,13,13\n\t"
Packit Service 15db12
	"fcmpu   7,0,13\n\t"
Packit Service 15db12
	"fcmpu   6,1,12\n\t"
Packit Service 15db12
	"bnllr-  7\n\t"
Packit Service 15db12
	"mtfsfi  7,1\n\t"
Packit Service 15db12
	"ble-    6,2f\n\t"
Packit Service 15db12
	"fadd    1,1,13\n\t"
Packit Service 15db12
	"fsub    1,1,13\n\t"
Packit Service 15db12
	"fabs    1,1\n\t"
Packit Service 15db12
	"mtfsf   0x01,11\n\t"
Packit Service 15db12
	"blr\n"
Packit Service 15db12
"2:"	"bge-    6,3f\n\t"
Packit Service 15db12
	"fsub    1,1,13\n\t"
Packit Service 15db12
	"fadd    1,1,13\n\t"
Packit Service 15db12
	"fnabs   1,1\n"
Packit Service 15db12
"3:"	"mtfsf   0x01,11\n\t"
Packit Service 15db12
	"blr\n\t"
Packit Service 15db12
	"# frin == round\n"
Packit Service 15db12
"frin:"	"mffs    11\n\t"
Packit Service 15db12
#ifdef __powerpc64__
Packit Service 15db12
	"lfd     13,8b@toc(2)\n\t"
Packit Service 15db12
#else
Packit Service 15db12
	"mflr    11\n\t"
Packit Service 15db12
	"bcl     20,31,1f\n"
Packit Service 15db12
"1:"	"mflr    9\n\t"
Packit Service 15db12
	"addis   9,9,8b-1b@ha\n\t"
Packit Service 15db12
	"addi    9,9,8b-1b@l\n\t"
Packit Service 15db12
	"mtlr    11\n\t"
Packit Service 15db12
	"lfs     13,0(9)\n\t"
Packit Service 15db12
#endif
Packit Service 15db12
	"fabs    0,1\n\t"
Packit Service 15db12
	"fsub    12,13,13\n\t"
Packit Service 15db12
	"fcmpu   7,0,13\n\t"
Packit Service 15db12
	"fcmpu   6,1,12\n\t"
Packit Service 15db12
	"bnllr-  7\n\t"
Packit Service 15db12
	"mtfsfi  7,1\n\t"
Packit Service 15db12
#ifdef __powerpc64__
Packit Service 15db12
	"lfd     10,9b@toc(2)\n\t"
Packit Service 15db12
#else
Packit Service 15db12
	"lfs     10,9b-8b(9)\n\t"
Packit Service 15db12
#endif
Packit Service 15db12
	"ble-    6,2f\n\t"
Packit Service 15db12
	"fadd    1,1,10\n\t"
Packit Service 15db12
	"fadd    1,1,13\n\t"
Packit Service 15db12
	"fsub    1,1,13\n\t"
Packit Service 15db12
	"fabs    1,1\n\t"
Packit Service 15db12
	"mtfsf   0x01,11\n\t"
Packit Service 15db12
	"blr\n"
Packit Service 15db12
"2:"	"fsub    9,1,10\n\t"
Packit Service 15db12
	"bge-    6,3f\n\t"
Packit Service 15db12
	"fsub    1,9,13\n\t"
Packit Service 15db12
	"fadd    1,1,13\n\t"
Packit Service 15db12
	"fnabs   1,1\n"
Packit Service 15db12
"3:"	"mtfsf   0x01,11\n\t"
Packit Service 15db12
	"blr\n\t"
Packit Service 15db12
	"# frim == floor\n"
Packit Service 15db12
"frim:"	"mffs    11\n\t"
Packit Service 15db12
#ifdef __powerpc64__
Packit Service 15db12
	"lfd     13,8b@toc(2)\n\t"
Packit Service 15db12
#else
Packit Service 15db12
	"mflr    11\n\t"
Packit Service 15db12
	"bcl     20,31,1f\n"
Packit Service 15db12
"1:"	"mflr    9\n\t"
Packit Service 15db12
	"addis   9,9,8b-1b@ha\n\t"
Packit Service 15db12
	"lfs     13,8b-1b@l(9)\n\t"
Packit Service 15db12
	"mtlr    11\n\t"
Packit Service 15db12
#endif
Packit Service 15db12
	"fabs    0,1\n\t"
Packit Service 15db12
	"fsub    12,13,13\n\t"
Packit Service 15db12
	"fcmpu   7,0,13\n\t"
Packit Service 15db12
	"fcmpu   6,1,12\n\t"
Packit Service 15db12
	"bnllr-  7\n\t"
Packit Service 15db12
	"mtfsfi  7,3\n\t"
Packit Service 15db12
	"ble-    6,2f\n\t"
Packit Service 15db12
	"fadd    1,1,13\n\t"
Packit Service 15db12
	"fsub    1,1,13\n\t"
Packit Service 15db12
	"fabs    1,1\n\t"
Packit Service 15db12
	"mtfsf   0x01,11\n\t"
Packit Service 15db12
	"blr\n"
Packit Service 15db12
"2:"	"bge-    6,3f\n\t"
Packit Service 15db12
	"fsub    1,1,13\n\t"
Packit Service 15db12
	"fadd    1,1,13\n\t"
Packit Service 15db12
	"fnabs   1,1\n"
Packit Service 15db12
"3:"	"mtfsf   0x01,11\n\t"
Packit Service 15db12
	"blr\n");
Packit Service 15db12
Packit Service 15db12
#ifdef __powerpc64__
Packit Service 15db12
#define m1 0x5555555555555555L
Packit Service 15db12
#define m2 0x3333333333333333L
Packit Service 15db12
#define m3 0x0f0f0f0f0f0f0f0fL
Packit Service 15db12
#else
Packit Service 15db12
#define m1 0x55555555
Packit Service 15db12
#define m2 0x33333333
Packit Service 15db12
#define m3 0x0f0f0f0f
Packit Service 15db12
#endif
Packit Service 15db12
Packit Service 15db12
static inline unsigned long
Packit Service 15db12
popcntb (unsigned long n)
Packit Service 15db12
{
Packit Service 15db12
  n -= (n >> 1) & m1;
Packit Service 15db12
  n = (n & m2) + ((n >> 2) & m2);
Packit Service 15db12
  n = (n + (n >> 4)) & m3;
Packit Service 15db12
  return n;
Packit Service 15db12
}
Packit Service 15db12
Packit Service 15db12
static void
Packit Service 15db12
catch_sigill (int signal, struct sigcontext *ctx)
Packit Service 15db12
{
Packit Service 15db12
  unsigned int insn = *(unsigned int *) (ctx->regs->nip);
Packit Service 15db12
#ifdef __powerpc64__
Packit Service 15db12
  if ((insn & 0xfc1f07ff) == 0x7c0005be) /* mftgpr */
Packit Service 15db12
    {
Packit Service 15db12
      unsigned long *regs = (unsigned long *) ctx->regs;
Packit Service 15db12
      unsigned fpr = (insn >> 11) & 0x1f;
Packit Service 15db12
      unsigned gpr = (insn >> 21) & 0x1f;
Packit Service 15db12
      regs[gpr] = regs[fpr + 0x30];
Packit Service 15db12
      ctx->regs->nip += 4;
Packit Service 15db12
      return;
Packit Service 15db12
    }
Packit Service 15db12
  if ((insn & 0xfc1f07ff) == 0x7c0004be) /*mffgpr */
Packit Service 15db12
    {
Packit Service 15db12
      unsigned long *regs = (unsigned long *) ctx->regs;
Packit Service 15db12
      unsigned fpr = (insn >> 21) & 0x1f;
Packit Service 15db12
      unsigned gpr = (insn >> 11) & 0x1f;
Packit Service 15db12
      regs[fpr + 0x30] = regs[gpr];
Packit Service 15db12
      ctx->regs->nip += 4;
Packit Service 15db12
      return;
Packit Service 15db12
    }
Packit Service 15db12
#endif
Packit Service 15db12
  if ((insn & 0xfc1f073f) == 0xfc000310) /* fri[pznm] */
Packit Service 15db12
    {
Packit Service 15db12
#ifdef __powerpc64__
Packit Service 15db12
      double *regs = (double *) (((char *) ctx->regs) + 0x30 * 8);
Packit Service 15db12
      unsigned int *fpscr = (unsigned int *) (((char *) ctx->regs) + 0x50 * 8 + 4);
Packit Service 15db12
#else
Packit Service 15db12
      double *regs = (double *) (((char *) ctx->regs) + 0x30 * 4);
Packit Service 15db12
      unsigned int *fpscr = (unsigned int *) (((char *) ctx->regs) + 0x30 * 4 + 0x20 * 8 + 4);
Packit Service 15db12
#endif
Packit Service 15db12
      unsigned dest = (insn >> 21) & 0x1f;
Packit Service 15db12
      unsigned src = (insn >> 11) & 0x1f;
Packit Service 15db12
      switch (insn & 0xc0)
Packit Service 15db12
	{
Packit Service 15db12
	case 0:
Packit Service 15db12
	  regs[dest] = frin (regs[src]);
Packit Service 15db12
	  break;
Packit Service 15db12
	case 0x40:
Packit Service 15db12
	  regs[dest] = friz (regs[src]);
Packit Service 15db12
	  break;
Packit Service 15db12
	case 0x80:
Packit Service 15db12
	  regs[dest] = frip (regs[src]);
Packit Service 15db12
	  break;
Packit Service 15db12
	case 0xc0:
Packit Service 15db12
	  regs[dest] = frim (regs[src]);
Packit Service 15db12
	  break;
Packit Service 15db12
	}
Packit Service 15db12
      /* Update raised exceptions.  */
Packit Service 15db12
      union { unsigned int i[2]; double d; } u;
Packit Service 15db12
      asm volatile ("mffs %0" : "=f" (u.d));
Packit Service 15db12
      u.i[1] &= 0xfffe0000; /* Is this correct?  */
Packit Service 15db12
      *fpscr |= u.i[1];
Packit Service 15db12
      ctx->regs->nip += 4;
Packit Service 15db12
      return;
Packit Service 15db12
    }
Packit Service 15db12
  if ((insn & 0xfc00ffff) == 0x7c0000f4) /* popcntb */
Packit Service 15db12
    {
Packit Service 15db12
      unsigned long *regs = (unsigned long *) ctx->regs;
Packit Service 15db12
      unsigned dest = (insn >> 16) & 0x1f;
Packit Service 15db12
      unsigned src = (insn >> 21) & 0x1f;
Packit Service 15db12
      unsigned long res = 0;
Packit Service 15db12
      int i;
Packit Service 15db12
Packit Service 15db12
      regs[dest] = popcntb (regs[src]);
Packit Service 15db12
      ctx->regs->nip += 4;
Packit Service 15db12
      return;
Packit Service 15db12
    }
Packit Service 15db12
Packit Service 15db12
  struct sigaction sa;
Packit Service 15db12
  sa.sa_handler = SIG_DFL;
Packit Service 15db12
  sigemptyset (&sa.sa_mask);
Packit Service 15db12
  sa.sa_flags = 0;
Packit Service 15db12
  sigaction (signal, &sa, NULL);
Packit Service 15db12
  raise (signal);
Packit Service 15db12
}
Packit Service 15db12
Packit Service 15db12
static void
Packit Service 15db12
__attribute__ ((constructor))
Packit Service 15db12
install_handler (void)
Packit Service 15db12
{
Packit Service 15db12
  struct sigaction sa;
Packit Service 15db12
  sa.sa_handler = (void *) catch_sigill;
Packit Service 15db12
  sigemptyset (&sa.sa_mask);
Packit Service 15db12
  sa.sa_flags = SA_RESTART;
Packit Service 15db12
  sigaction (SIGILL, &sa, NULL);
Packit Service 15db12
}