Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/arch/powerpc/math-emu/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 11 kB image not shown  

Quelle  math.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 1999  Eddie C. Dost  (ecd@atecom.com)
 */


#include <linux/types.h>
#include <linux/sched.h>

#include <linux/uaccess.h>
#include <asm/reg.h>
#include <asm/switch_to.h>

#include <asm/sfp-machine.h>
#include <math-emu/double.h>

#define FLOATFUNC(x) extern int x(void *, void *, void *, void *)

/* The instructions list which may be not implemented by a hardware FPU */
FLOATFUNC(fre);
FLOATFUNC(frsqrtes);
FLOATFUNC(fsqrt);
FLOATFUNC(fsqrts);
FLOATFUNC(mtfsf);
FLOATFUNC(mtfsfi);

#ifdef CONFIG_MATH_EMULATION_HW_UNIMPLEMENTED
#undef FLOATFUNC
#define FLOATFUNC(x) static inline int x(void *op1, void *op2, void *op3, \
       void *op4) { return 0; }
#endif

FLOATFUNC(fadd);
FLOATFUNC(fadds);
FLOATFUNC(fdiv);
FLOATFUNC(fdivs);
FLOATFUNC(fmul);
FLOATFUNC(fmuls);
FLOATFUNC(fsub);
FLOATFUNC(fsubs);

FLOATFUNC(fmadd);
FLOATFUNC(fmadds);
FLOATFUNC(fmsub);
FLOATFUNC(fmsubs);
FLOATFUNC(fnmadd);
FLOATFUNC(fnmadds);
FLOATFUNC(fnmsub);
FLOATFUNC(fnmsubs);

FLOATFUNC(fctiw);
FLOATFUNC(fctiwz);
FLOATFUNC(frsp);

FLOATFUNC(fcmpo);
FLOATFUNC(fcmpu);

FLOATFUNC(mcrfs);
FLOATFUNC(mffs);
FLOATFUNC(mtfsb0);
FLOATFUNC(mtfsb1);

FLOATFUNC(lfd);
FLOATFUNC(lfs);

FLOATFUNC(stfd);
FLOATFUNC(stfs);
FLOATFUNC(stfiwx);

FLOATFUNC(fabs);
FLOATFUNC(fmr);
FLOATFUNC(fnabs);
FLOATFUNC(fneg);

/* Optional */
FLOATFUNC(fres);
FLOATFUNC(frsqrte);
FLOATFUNC(fsel);


#define OP31  0x1f  /*   31 */
#define LFS  0x30  /*   48 */
#define LFSU  0x31  /*   49 */
#define LFD  0x32  /*   50 */
#define LFDU  0x33  /*   51 */
#define STFS  0x34  /*   52 */
#define STFSU  0x35  /*   53 */
#define STFD  0x36  /*   54 */
#define STFDU  0x37  /*   55 */
#define OP59  0x3b  /*   59 */
#define OP63  0x3f  /*   63 */

/* Opcode 31: */
/* X-Form: */
#define LFSX  0x217  /*  535 */
#define LFSUX  0x237  /*  567 */
#define LFDX  0x257  /*  599 */
#define LFDUX  0x277  /*  631 */
#define STFSX  0x297  /*  663 */
#define STFSUX  0x2b7  /*  695 */
#define STFDX  0x2d7  /*  727 */
#define STFDUX  0x2f7  /*  759 */
#define STFIWX  0x3d7  /*  983 */

/* Opcode 59: */
/* A-Form: */
#define FDIVS  0x012  /*   18 */
#define FSUBS  0x014  /*   20 */
#define FADDS  0x015  /*   21 */
#define FSQRTS  0x016  /*   22 */
#define FRES  0x018  /*   24 */
#define FMULS  0x019  /*   25 */
#define FRSQRTES 0x01a  /*   26 */
#define FMSUBS  0x01c  /*   28 */
#define FMADDS  0x01d  /*   29 */
#define FNMSUBS  0x01e  /*   30 */
#define FNMADDS  0x01f  /*   31 */

/* Opcode 63: */
/* A-Form: */
#define FDIV  0x012  /*   18 */
#define FSUB  0x014  /*   20 */
#define FADD  0x015  /*   21 */
#define FSQRT  0x016  /*   22 */
#define FSEL  0x017  /*   23 */
#define FRE  0x018  /*   24 */
#define FMUL  0x019  /*   25 */
#define FRSQRTE  0x01a  /*   26 */
#define FMSUB  0x01c  /*   28 */
#define FMADD  0x01d  /*   29 */
#define FNMSUB  0x01e  /*   30 */
#define FNMADD  0x01f  /*   31 */

/* X-Form: */
#define FCMPU  0x000  /*    0 */
#define FRSP  0x00c  /*   12 */
#define FCTIW  0x00e  /*   14 */
#define FCTIWZ  0x00f  /*   15 */
#define FCMPO  0x020  /*   32 */
#define MTFSB1  0x026  /*   38 */
#define FNEG  0x028  /*   40 */
#define MCRFS  0x040  /*   64 */
#define MTFSB0  0x046  /*   70 */
#define FMR  0x048  /*   72 */
#define MTFSFI  0x086  /*  134 */
#define FNABS  0x088  /*  136 */
#define FABS  0x108  /*  264 */
#define MFFS  0x247  /*  583 */
#define MTFSF  0x2c7  /*  711 */


#define AB 2
#define AC 3
#define ABC 4
#define D 5
#define DU 6
#define X 7
#define XA 8
#define XB 9
#define XCR 11
#define XCRB 12
#define XCRI 13
#define XCRL 16
#define XE 14
#define XEU 15
#define XFLB 10

static int
record_exception(struct pt_regs *regs, int eflag)
{
 u32 fpscr;

 fpscr = __FPU_FPSCR;

 if (eflag) {
  fpscr |= FPSCR_FX;
  if (eflag & EFLAG_OVERFLOW)
   fpscr |= FPSCR_OX;
  if (eflag & EFLAG_UNDERFLOW)
   fpscr |= FPSCR_UX;
  if (eflag & EFLAG_DIVZERO)
   fpscr |= FPSCR_ZX;
  if (eflag & EFLAG_INEXACT)
   fpscr |= FPSCR_XX;
  if (eflag & EFLAG_INVALID)
   fpscr |= FPSCR_VX;
  if (eflag & EFLAG_VXSNAN)
   fpscr |= FPSCR_VXSNAN;
  if (eflag & EFLAG_VXISI)
   fpscr |= FPSCR_VXISI;
  if (eflag & EFLAG_VXIDI)
   fpscr |= FPSCR_VXIDI;
  if (eflag & EFLAG_VXZDZ)
   fpscr |= FPSCR_VXZDZ;
  if (eflag & EFLAG_VXIMZ)
   fpscr |= FPSCR_VXIMZ;
  if (eflag & EFLAG_VXVC)
   fpscr |= FPSCR_VXVC;
  if (eflag & EFLAG_VXSOFT)
   fpscr |= FPSCR_VXSOFT;
  if (eflag & EFLAG_VXSQRT)
   fpscr |= FPSCR_VXSQRT;
  if (eflag & EFLAG_VXCVI)
   fpscr |= FPSCR_VXCVI;
 }

// fpscr &= ~(FPSCR_VX);
 if (fpscr & (FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI |
       FPSCR_VXZDZ | FPSCR_VXIMZ | FPSCR_VXVC |
       FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI))
  fpscr |= FPSCR_VX;

 fpscr &= ~(FPSCR_FEX);
 if (((fpscr & FPSCR_VX) && (fpscr & FPSCR_VE)) ||
     ((fpscr & FPSCR_OX) && (fpscr & FPSCR_OE)) ||
     ((fpscr & FPSCR_UX) && (fpscr & FPSCR_UE)) ||
     ((fpscr & FPSCR_ZX) && (fpscr & FPSCR_ZE)) ||
     ((fpscr & FPSCR_XX) && (fpscr & FPSCR_XE)))
  fpscr |= FPSCR_FEX;

 __FPU_FPSCR = fpscr;

 return (fpscr & FPSCR_FEX) ? 1 : 0;
}

int
do_mathemu(struct pt_regs *regs)
{
 void *op0 = NULL, *op1 = NULL, *op2 = NULL, *op3 = NULL;
 unsigned long pc = regs->nip;
 signed short sdisp;
 u32 insn = 0;
 int idx = 0;
 int (*func)(void *, void *, void *, void *);
 int type = 0;
 int eflag, trap;

 if (get_user(insn, (u32 __user *)pc))
  return -EFAULT;

 switch (insn >> 26) {
 case LFS: func = lfs; type = D; break;
 case LFSU: func = lfs; type = DU; break;
 case LFD: func = lfd; type = D; break;
 case LFDU: func = lfd; type = DU; break;
 case STFS: func = stfs; type = D; break;
 case STFSU: func = stfs; type = DU; break;
 case STFD: func = stfd; type = D; break;
 case STFDU: func = stfd; type = DU; break;

 case OP31:
  switch ((insn >> 1) & 0x3ff) {
  case LFSX: func = lfs; type = XE; break;
  case LFSUX: func = lfs; type = XEU; break;
  case LFDX: func = lfd; type = XE; break;
  case LFDUX: func = lfd; type = XEU; break;
  case STFSX: func = stfs; type = XE; break;
  case STFSUX: func = stfs; type = XEU; break;
  case STFDX: func = stfd; type = XE; break;
  case STFDUX: func = stfd; type = XEU; break;
  case STFIWX: func = stfiwx; type = XE; break;
  default:
   goto illegal;
  }
  break;

 case OP59:
  switch ((insn >> 1) & 0x1f) {
  case FDIVS: func = fdivs; type = AB; break;
  case FSUBS: func = fsubs; type = AB; break;
  case FADDS: func = fadds; type = AB; break;
  case FSQRTS: func = fsqrts; type = XB; break;
  case FRES: func = fres; type = XB; break;
  case FMULS: func = fmuls; type = AC; break;
  case FRSQRTES: func = frsqrtes;type = XB; break;
  case FMSUBS: func = fmsubs; type = ABC; break;
  case FMADDS: func = fmadds; type = ABC; break;
  case FNMSUBS: func = fnmsubs; type = ABC; break;
  case FNMADDS: func = fnmadds; type = ABC; break;
  default:
   goto illegal;
  }
  break;

 case OP63:
  if (insn & 0x20) {
   switch ((insn >> 1) & 0x1f) {
   case FDIV: func = fdiv; type = AB; break;
   case FSUB: func = fsub; type = AB; break;
   case FADD: func = fadd; type = AB; break;
   case FSQRT: func = fsqrt; type = XB; break;
   case FRE: func = fre; type = XB; break;
   case FSEL: func = fsel; type = ABC; break;
   case FMUL: func = fmul; type = AC; break;
   case FRSQRTE: func = frsqrte; type = XB; break;
   case FMSUB: func = fmsub; type = ABC; break;
   case FMADD: func = fmadd; type = ABC; break;
   case FNMSUB: func = fnmsub; type = ABC; break;
   case FNMADD: func = fnmadd; type = ABC; break;
   default:
    goto illegal;
   }
   break;
  }

  switch ((insn >> 1) & 0x3ff) {
  case FCMPU: func = fcmpu; type = XCR; break;
  case FRSP: func = frsp; type = XB; break;
  case FCTIW: func = fctiw; type = XB; break;
  case FCTIWZ: func = fctiwz; type = XB; break;
  case FCMPO: func = fcmpo; type = XCR; break;
  case MTFSB1: func = mtfsb1; type = XCRB; break;
  case FNEG: func = fneg; type = XB; break;
  case MCRFS: func = mcrfs; type = XCRL; break;
  case MTFSB0: func = mtfsb0; type = XCRB; break;
  case FMR: func = fmr; type = XB; break;
  case MTFSFI: func = mtfsfi; type = XCRI; break;
  case FNABS: func = fnabs; type = XB; break;
  case FABS: func = fabs; type = XB; break;
  case MFFS: func = mffs; type = X; break;
  case MTFSF: func = mtfsf; type = XFLB; break;
  default:
   goto illegal;
  }
  break;

 default:
  goto illegal;
 }

 switch (type) {
 case AB:
  op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f);
  op1 = (void *)¤t->thread.TS_FPR((insn >> 16) & 0x1f);
  op2 = (void *)¤t->thread.TS_FPR((insn >> 11) & 0x1f);
  break;

 case AC:
  op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f);
  op1 = (void *)¤t->thread.TS_FPR((insn >> 16) & 0x1f);
  op2 = (void *)¤t->thread.TS_FPR((insn >>  6) & 0x1f);
  break;

 case ABC:
  op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f);
  op1 = (void *)¤t->thread.TS_FPR((insn >> 16) & 0x1f);
  op2 = (void *)¤t->thread.TS_FPR((insn >> 11) & 0x1f);
  op3 = (void *)¤t->thread.TS_FPR((insn >>  6) & 0x1f);
  break;

 case D:
  idx = (insn >> 16) & 0x1f;
  sdisp = (insn & 0xffff);
  op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f);
  op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp);
  break;

 case DU:
  idx = (insn >> 16) & 0x1f;
  if (!idx)
   goto illegal;

  sdisp = (insn & 0xffff);
  op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f);
  op1 = (void *)(regs->gpr[idx] + sdisp);
  break;

 case X:
  op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f);
  break;

 case XA:
  op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f);
  op1 = (void *)¤t->thread.TS_FPR((insn >> 16) & 0x1f);
  break;

 case XB:
  op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f);
  op1 = (void *)¤t->thread.TS_FPR((insn >> 11) & 0x1f);
  break;

 case XE:
  idx = (insn >> 16) & 0x1f;
  op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f);
  op1 = (void *)((idx ? regs->gpr[idx] : 0)
    + regs->gpr[(insn >> 11) & 0x1f]);
  break;

 case XEU:
  idx = (insn >> 16) & 0x1f;
  if (!idx)
   goto illegal;
  op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f);
  op1 = (void *)(regs->gpr[idx]
    + regs->gpr[(insn >> 11) & 0x1f]);
  break;

 case XCR:
  op0 = (void *)®s->ccr;
  op1 = (void *)(long)((insn >> 23) & 0x7);
  op2 = (void *)¤t->thread.TS_FPR((insn >> 16) & 0x1f);
  op3 = (void *)¤t->thread.TS_FPR((insn >> 11) & 0x1f);
  break;

 case XCRL:
  op0 = (void *)®s->ccr;
  op1 = (void *)(long)((insn >> 23) & 0x7);
  op2 = (void *)(long)((insn >> 18) & 0x7);
  break;

 case XCRB:
  op0 = (void *)(long)((insn >> 21) & 0x1f);
  break;

 case XCRI:
  op0 = (void *)(long)((insn >> 23) & 0x7);
  op1 = (void *)(long)((insn >> 12) & 0xf);
  break;

 case XFLB:
  op0 = (void *)(long)((insn >> 17) & 0xff);
  op1 = (void *)¤t->thread.TS_FPR((insn >> 11) & 0x1f);
  break;

 default:
  goto illegal;
 }

 /*
 * If we support a HW FPU, we need to ensure the FP state
 * is flushed into the thread_struct before attempting
 * emulation
 */

 flush_fp_to_thread(current);

 eflag = func(op0, op1, op2, op3);

 if (insn & 1) {
  regs->ccr &= ~(0x0f000000);
  regs->ccr |= (__FPU_FPSCR >> 4) & 0x0f000000;
 }

 trap = record_exception(regs, eflag);
 if (trap)
  return 1;

 switch (type) {
 case DU:
 case XEU:
  regs->gpr[idx] = (unsigned long)op1;
  break;

 default:
  break;
 }

 regs_add_return_ip(regs, 4);
 return 0;

illegal:
 return -ENOSYS;
}

Messung V0.5
C=85 H=93 G=88

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.