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

Quelle  decode_exc.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
 *
 * Floating-point emulation code
 *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
 */

/*
 * BEGIN_DESC
 *
 *  File:
 * @(#) pa/fp/decode_exc.c $ Revision: $
 *
 *  Purpose:
 * <<please update with a synopsis of the functionality provided by this file>>
 *
 *  External Interfaces:
 * <<the following list was autogenerated, please review>>
 * decode_fpu(Fpu_register, trap_counts)
 *
 *  Internal Interfaces:
 * <<please update>>
 *
 *  Theory:
 * <<please update with a overview of the operation of this file>>
 *
 * END_DESC
*/


#include <linux/kernel.h>
#include "float.h"
#include "sgl_float.h"
#include "dbl_float.h"
#include "cnv_float.h"
/* #include "types.h" */
#include <asm/signal.h>
#include <asm/siginfo.h>
/* #include <machine/sys/mdep_private.h> */

#undef Fpustatus_register
#define Fpustatus_register Fpu_register[0]

/* General definitions */
#define DOESTRAP 1
#define NOTRAP 0
#define SIGNALCODE(signal, code) ((signal) << 24 | (code))
#define copropbit 1<<31-2 /* bit position 2 */
#define opclass  9 /* bits 21 & 22 */
#define fmtbits  11 /* bits 19 & 20 */
#define df  13 /* bits 17 & 18 */
#define twobits  3 /* mask low-order 2 bits */
#define fivebits 31 /* mask low-order 5 bits */
#define MAX_EXCP_REG 7 /* number of excpeption registers to check */

/* Exception register definitions */
#define Excp_type(index) Exceptiontype(Fpu_register[index])
#define Excp_instr(index) Instructionfield(Fpu_register[index])
#define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0
#define Excp_format() \
 (current_ir >> ((current_ir>>opclass & twobits) == 1 ? df : fmtbits) & twobits)

/* Miscellaneous definitions */
#define Fpu_sgl(index) Fpu_register[index*2]

#define Fpu_dblp1(index) Fpu_register[index*2]
#define Fpu_dblp2(index) Fpu_register[(index*2)+1]

#define Fpu_quadp1(index) Fpu_register[index*2]
#define Fpu_quadp2(index) Fpu_register[(index*2)+1]
#define Fpu_quadp3(index) Fpu_register[(index*2)+2]
#define Fpu_quadp4(index) Fpu_register[(index*2)+3]

/* Single precision floating-point definitions */
#ifndef Sgl_decrement
define Sgl_decrement(sgl_value) Sall(sgl_value)--
#endif

/* Double precision floating-point definitions */
#ifndef Dbl_decrement
define Dbl_decrement(dbl_valuep1,dbl_valuep2) \
    if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)-- 
#endif


#define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) { \
 aflags=(Fpu_register[0])>>27; /* assumes zero fill. 32 bit */ \
 Fpu_register[0] |= bflags;     \
}

u_int
decode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[])
{
    unsigned int current_ir, excp;
    int target, exception_index = 1;
    boolean inexact;
    unsigned int aflags;
    unsigned int bflags;
    unsigned int excptype;


    /* Keep stats on how many floating point exceptions (based on type)
     * that happen.  Want to keep this overhead low, but still provide
     * some information to the customer.  All exits from this routine
     * need to restore Fpu_register[0]
     */


    bflags=(Fpu_register[0] & 0xf8000000);
    Fpu_register[0] &= 0x07ffffff;

    /* exception_index is used to index the exception register queue.  It
     *   always points at the last register that contains a valid exception.  A
     *   zero value implies no exceptions (also the initialized value).  Setting
     *   the T-bit resets the exception_index to zero.
     */


    /*
     * Check for reserved-op exception.  A reserved-op exception does not 
     * set any exception registers nor does it set the T-bit.  If the T-bit
     * is not set then a reserved-op exception occurred.
     *
     * At some point, we may want to report reserved op exceptions as
     * illegal instructions.
     */

    
    if (!Is_tbit_set()) {
 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
 return SIGNALCODE(SIGILL, ILL_COPROC);
    }

    /* 
     * Is a coprocessor op. 
     *
     * Now we need to determine what type of exception occurred.
     */

    for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) {
 current_ir = Excp_instr(exception_index);
   /*
   * On PA89: there are 5 different unimplemented exception
   * codes: 0x1, 0x9, 0xb, 0x3, and 0x23.  PA-RISC 2.0 adds
   * another, 0x2b.  Only these have the low order bit set.
   */

 excptype = Excp_type(exception_index);
 if (excptype & UNIMPLEMENTEDEXCEPTION) {
  /*
 * Clear T-bit and exception register so that
 * we can tell if a trap really occurs while 
 * emulating the instruction.
 */

  Clear_tbit();
  Clear_excp_register(exception_index);
  /*
 * Now emulate this instruction.  If a trap occurs,
 * fpudispatch will return a non-zero number 
 */

  excp = fpudispatch(current_ir,excptype,0,Fpu_register);
  /* accumulate the status flags, don't lose them as in hpux */
  if (excp) {
   /*
 * We now need to make sure that the T-bit and the
 * exception register contain the correct values
 * before continuing.
 */

   /*
 * Set t-bit since it might still be needed for a
 * subsequent real trap (I don't understand fully -PB)
 */

   Set_tbit();
   /* some of the following code uses
 * Excp_type(exception_index) so fix that up */

   Set_exceptiontype_and_instr_field(excp,current_ir,
    Fpu_register[exception_index]);
   if (excp == UNIMPLEMENTEDEXCEPTION) {
    /*
   * it is really unimplemented, so restore the
   * TIMEX extended unimplemented exception code
   */

    excp = excptype;
    update_trap_counts(Fpu_register, aflags, bflags, 
        trap_counts);
    return SIGNALCODE(SIGILL, ILL_COPROC);
   }
   /* some of the following code uses excptype, so
 * fix that up too */

   excptype = excp;
  }
  /* handle exceptions other than the real UNIMPLIMENTED the
 * same way as if the hardware had caused them */

  if (excp == NOEXCEPTION)
   /* For now use 'break', should technically be 'continue' */
   break;
 }

   /*
   * In PA89, the underflow exception has been extended to encode
   * additional information.  The exception looks like pp01x0,
   * where x is 1 if inexact and pp represent the inexact bit (I)
   * and the round away bit (RA)
   */

 if (excptype & UNDERFLOWEXCEPTION) {
  /* check for underflow trap enabled */
  if (Is_underflowtrap_enabled()) {
   update_trap_counts(Fpu_register, aflags, bflags, 
        trap_counts);
   return SIGNALCODE(SIGFPE, FPE_FLTUND);
  } else {
      /*
     * Isn't a real trap; we need to 
     * return the default value.
     */

      target = current_ir & fivebits;
#ifndef lint
      if (Ibit(Fpu_register[exception_index])) inexact = TRUE;
      else inexact = FALSE;
#endif
      switch (Excp_format()) {
        case SGL:
          /*
         * If ra (round-away) is set, will 
         * want to undo the rounding done
         * by the hardware.
         */

          if (Rabit(Fpu_register[exception_index])) 
    Sgl_decrement(Fpu_sgl(target));

   /* now denormalize */
   sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode());
       break;
        case DBL:
       /*
      * If ra (round-away) is set, will 
      * want to undo the rounding done
      * by the hardware.
      */

       if (Rabit(Fpu_register[exception_index])) 
    Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target));

   /* now denormalize */
   dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target),
     &inexact,Rounding_mode());
       break;
      }
      if (inexact) Set_underflowflag();
      /* 
     * Underflow can generate an inexact
     * exception.  If inexact trap is enabled,
     * want to do an inexact trap, otherwise 
     * set inexact flag.
     */

      if (inexact && Is_inexacttrap_enabled()) {
       /*
      * Set exception field of exception register
      * to inexact, parm field to zero.
 * Underflow bit should be cleared.
      */

       Set_exceptiontype(Fpu_register[exception_index],
    INEXACTEXCEPTION);
   Set_parmfield(Fpu_register[exception_index],0);
   update_trap_counts(Fpu_register, aflags, bflags, 
        trap_counts);
   return SIGNALCODE(SIGFPE, FPE_FLTRES);
      }
      else {
       /*
      * Exception register needs to be cleared.  
 * Inexact flag needs to be set if inexact.
      */

       Clear_excp_register(exception_index);
       if (inexact) Set_inexactflag();
      }
  }
  continue;
 }
 switch(Excp_type(exception_index)) {
   case OVERFLOWEXCEPTION:
   case OVERFLOWEXCEPTION | INEXACTEXCEPTION:
  /* check for overflow trap enabled */
   update_trap_counts(Fpu_register, aflags, bflags, 
        trap_counts);
  if (Is_overflowtrap_enabled()) {
   update_trap_counts(Fpu_register, aflags, bflags, 
        trap_counts);
   return SIGNALCODE(SIGFPE, FPE_FLTOVF);
  } else {
   /*
 * Isn't a real trap; we need to 
 * return the default value.
 */

   target = current_ir & fivebits;
   switch (Excp_format()) {
     case SGL: 
    Sgl_setoverflow(Fpu_sgl(target));
    break;
     case DBL:
    Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target));
    break;
   }
   Set_overflowflag();
   /* 
 * Overflow always generates an inexact
 * exception.  If inexact trap is enabled,
 * want to do an inexact trap, otherwise 
 * set inexact flag.
 */

   if (Is_inexacttrap_enabled()) {
    /*
 * Set exception field of exception
 * register to inexact.  Overflow
 * bit should be cleared.
 */

    Set_exceptiontype(Fpu_register[exception_index],
     INEXACTEXCEPTION);
    update_trap_counts(Fpu_register, aflags, bflags,
        trap_counts);
    return SIGNALCODE(SIGFPE, FPE_FLTRES);
   }
   else {
    /*
 * Exception register needs to be cleared.  
 * Inexact flag needs to be set.
 */

    Clear_excp_register(exception_index);
    Set_inexactflag();
   }
  }
  break;
   case INVALIDEXCEPTION:
   case OPC_2E_INVALIDEXCEPTION:
  update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
  return SIGNALCODE(SIGFPE, FPE_FLTINV);
   case DIVISIONBYZEROEXCEPTION:
  update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
  Clear_excp_register(exception_index);
    return SIGNALCODE(SIGFPE, FPE_FLTDIV);
   case INEXACTEXCEPTION:
  update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
  return SIGNALCODE(SIGFPE, FPE_FLTRES);
   default:
  update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
  printk("%s(%d) Unknown FPU exception 0x%x\n", __FILE__,
   __LINE__, Excp_type(exception_index));
  return SIGNALCODE(SIGILL, ILL_COPROC);
   case NOEXCEPTION: /* no exception */
  /*
 * Clear exception register in case 
 * other fields are non-zero.
 */

  Clear_excp_register(exception_index);
  break;
 }
    }
    /*
     * No real exceptions occurred.
     */

    Clear_tbit();
    update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
    return(NOTRAP);
}

Messung V0.5
C=98 H=90 G=94

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© 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.