⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reg_ld_s.c

📁 《汇编源代码大全》
💻 C
📖 第 1 页 / 共 3 页
字号:
/*---------------------------------------------------------------------------+ |  reg_ld_str.c                                                             | |                                                                           | | All of the functions which transfer data between user memory and FPU_REGs.| |                                                                           | | Copyright (C) 1992,1993,1994                                              | |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      | |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    | |                                                                           | |                                                                           | +---------------------------------------------------------------------------*//*---------------------------------------------------------------------------+ | Note:                                                                     | |    The file contains code which accesses user memory.                     | |    Emulator static data may change when user memory is accessed, due to   | |    other processes using the emulator while swapping is in progress.      | +---------------------------------------------------------------------------*/#include <asm/segment.h>#include "fpu_system.h"#include "exception.h"#include "reg_constant.h"#include "fpu_emu.h"#include "control_w.h"#include "status_w.h"#define EXTENDED_Ebias 0x3fff#define EXTENDED_Emin (-0x3ffe)  /* smallest valid exponent */#define DOUBLE_Emax 1023         /* largest valid exponent */#define DOUBLE_Ebias 1023#define DOUBLE_Emin (-1022)      /* smallest valid exponent */#define SINGLE_Emax 127          /* largest valid exponent */#define SINGLE_Ebias 127#define SINGLE_Emin (-126)       /* smallest valid exponent */static void write_to_extended(FPU_REG *rp, char *d);FPU_REG FPU_loaded_data;/* Get a long double from user memory */int reg_load_extended(void){  long double *s = (long double *)FPU_data_address;  unsigned long sigl, sigh, exp;  RE_ENTRANT_CHECK_OFF;  FPU_verify_area(VERIFY_READ, s, 10);  /* Use temporary variables here because FPU_loaded data is     static and hence re-entrancy problems can arise */  sigl = get_fs_long((unsigned long *) s);  sigh = get_fs_long(1 + (unsigned long *) s);  exp = get_fs_word(4 + (unsigned short *) s);  RE_ENTRANT_CHECK_ON;  FPU_loaded_data.tag = TW_Valid;   /* Default */  FPU_loaded_data.sigl = sigl;  FPU_loaded_data.sigh = sigh;  if (exp & 0x8000)    FPU_loaded_data.sign = SIGN_NEG;  else    FPU_loaded_data.sign = SIGN_POS;  exp &= 0x7fff;  FPU_loaded_data.exp = exp - EXTENDED_Ebias + EXP_BIAS;  /* Assume that optimisation can keep sigl, sigh, and exp in     registers, otherwise it would be more efficient to work     with FPU_loaded_data (which is static) here. */  if ( exp == 0 )    {      if ( !(sigh | sigl) )	{	  FPU_loaded_data.tag = TW_Zero;	  return 0;	}      /* The number is a de-normal or pseudodenormal. */      if (sigh & 0x80000000)	{	  /* Is a pseudodenormal. */	  /* Convert it for internal use. */	  /* This is non-80486 behaviour because the number	     loses its 'denormal' identity. */	  FPU_loaded_data.exp++;	  return 1;	}      else	{	  /* Is a denormal. */	  /* Convert it for internal use. */	  FPU_loaded_data.exp++;	  normalize_nuo(&FPU_loaded_data);	  return 0;	}    }  else if ( exp == 0x7fff )    {      if ( !((sigh ^ 0x80000000) | sigl) )	{	  /* Matches the bit pattern for Infinity. */	  FPU_loaded_data.exp = EXP_Infinity;	  FPU_loaded_data.tag = TW_Infinity;	  return 0;	}      FPU_loaded_data.exp = EXP_NaN;      FPU_loaded_data.tag = TW_NaN;      if ( !(sigh & 0x80000000) )	{	  /* NaNs have the ms bit set to 1. */	  /* This is therefore an Unsupported NaN data type. */	  /* This is non 80486 behaviour */	  /* This should generate an Invalid Operand exception	     later, so we convert it to a SNaN */	  FPU_loaded_data.sigh = 0x80000000;	  FPU_loaded_data.sigl = 0x00000001;	  FPU_loaded_data.sign = SIGN_NEG;	  return 1;	}      return 0;    }  if ( !(sigh & 0x80000000) )    {      /* Unsupported data type. */      /* Valid numbers have the ms bit set to 1. */      /* Unnormal. */      /* Convert it for internal use. */      /* This is non-80486 behaviour */      /* This should generate an Invalid Operand exception	 later, so we convert it to a SNaN */      FPU_loaded_data.sigh = 0x80000000;      FPU_loaded_data.sigl = 0x00000001;      FPU_loaded_data.sign = SIGN_NEG;      FPU_loaded_data.exp = EXP_NaN;      FPU_loaded_data.tag = TW_NaN;      return 1;    }  return 0;}/* Get a double from user memory */int reg_load_double(void){  double *dfloat = (double *)FPU_data_address;  int exp;  unsigned m64, l64;  RE_ENTRANT_CHECK_OFF;  FPU_verify_area(VERIFY_READ, dfloat, 8);  m64 = get_fs_long(1 + (unsigned long *) dfloat);  l64 = get_fs_long((unsigned long *) dfloat);  RE_ENTRANT_CHECK_ON;  if (m64 & 0x80000000)    FPU_loaded_data.sign = SIGN_NEG;  else    FPU_loaded_data.sign = SIGN_POS;  exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias;  m64 &= 0xfffff;  if (exp > DOUBLE_Emax)    {      /* Infinity or NaN */      if ((m64 == 0) && (l64 == 0))	{	  /* +- infinity */	  FPU_loaded_data.sigh = 0x80000000;	  FPU_loaded_data.sigl = 0x00000000;	  FPU_loaded_data.exp = EXP_Infinity;	  FPU_loaded_data.tag = TW_Infinity;	  return 0;	}      else	{	  /* Must be a signaling or quiet NaN */	  FPU_loaded_data.exp = EXP_NaN;	  FPU_loaded_data.tag = TW_NaN;	  FPU_loaded_data.sigh = (m64 << 11) | 0x80000000;	  FPU_loaded_data.sigh |= l64 >> 21;	  FPU_loaded_data.sigl = l64 << 11;	  return 0; /* The calling function must look for NaNs */	}    }  else if ( exp < DOUBLE_Emin )    {      /* Zero or de-normal */      if ((m64 == 0) && (l64 == 0))	{	  /* Zero */	  int c = FPU_loaded_data.sign;	  reg_move(&CONST_Z, &FPU_loaded_data);	  FPU_loaded_data.sign = c;	  return 0;	}      else	{	  /* De-normal */	  FPU_loaded_data.exp = DOUBLE_Emin + EXP_BIAS;	  FPU_loaded_data.tag = TW_Valid;	  FPU_loaded_data.sigh = m64 << 11;	  FPU_loaded_data.sigh |= l64 >> 21;	  FPU_loaded_data.sigl = l64 << 11;	  normalize_nuo(&FPU_loaded_data);	  return denormal_operand();	}    }  else    {      FPU_loaded_data.exp = exp + EXP_BIAS;      FPU_loaded_data.tag = TW_Valid;      FPU_loaded_data.sigh = (m64 << 11) | 0x80000000;      FPU_loaded_data.sigh |= l64 >> 21;      FPU_loaded_data.sigl = l64 << 11;      return 0;    }}/* Get a float from user memory */int reg_load_single(void){  float *single = (float *)FPU_data_address;  unsigned m32;  int exp;  RE_ENTRANT_CHECK_OFF;  FPU_verify_area(VERIFY_READ, single, 4);  m32 = get_fs_long((unsigned long *) single);  RE_ENTRANT_CHECK_ON;  if (m32 & 0x80000000)    FPU_loaded_data.sign = SIGN_NEG;  else    FPU_loaded_data.sign = SIGN_POS;  if (!(m32 & 0x7fffffff))    {      /* Zero */      int c = FPU_loaded_data.sign;      reg_move(&CONST_Z, &FPU_loaded_data);      FPU_loaded_data.sign = c;      return 0;    }  exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias;  m32 = (m32 & 0x7fffff) << 8;  if ( exp < SINGLE_Emin )    {      /* De-normals */      FPU_loaded_data.exp = SINGLE_Emin + EXP_BIAS;      FPU_loaded_data.tag = TW_Valid;      FPU_loaded_data.sigh = m32;      FPU_loaded_data.sigl = 0;      normalize_nuo(&FPU_loaded_data);      return denormal_operand();    }  else if ( exp > SINGLE_Emax )    {    /* Infinity or NaN */      if ( m32 == 0 )	{	  /* +- infinity */	  FPU_loaded_data.sigh = 0x80000000;	  FPU_loaded_data.sigl = 0x00000000;	  FPU_loaded_data.exp = EXP_Infinity;	  FPU_loaded_data.tag = TW_Infinity;	  return 0;	}      else	{	  /* Must be a signaling or quiet NaN */	  FPU_loaded_data.exp = EXP_NaN;	  FPU_loaded_data.tag = TW_NaN;	  FPU_loaded_data.sigh = m32 | 0x80000000;	  FPU_loaded_data.sigl = 0;	  return 0; /* The calling function must look for NaNs */	}    }  else    {      FPU_loaded_data.exp = exp + EXP_BIAS;      FPU_loaded_data.sigh = m32 | 0x80000000;      FPU_loaded_data.sigl = 0;      FPU_loaded_data.tag = TW_Valid;      return 0;    }}/* Get a long long from user memory */void reg_load_int64(void){  long long *_s = (long long *)FPU_data_address;  int e;  long long s;  RE_ENTRANT_CHECK_OFF;  FPU_verify_area(VERIFY_READ, _s, 8);  ((unsigned long *)&s)[0] = get_fs_long((unsigned long *) _s);  ((unsigned long *)&s)[1] = get_fs_long(1 + (unsigned long *) _s);  RE_ENTRANT_CHECK_ON;  if (s == 0)    { reg_move(&CONST_Z, &FPU_loaded_data); return; }  if (s > 0)    FPU_loaded_data.sign = SIGN_POS;  else  {    s = -s;    FPU_loaded_data.sign = SIGN_NEG;  }  e = EXP_BIAS + 63;  significand(&FPU_loaded_data) = s;  FPU_loaded_data.exp = e;  FPU_loaded_data.tag = TW_Valid;  normalize_nuo(&FPU_loaded_data);}/* Get a long from user memory */void reg_load_int32(void){  long *_s = (long *)FPU_data_address;  long s;  int e;  RE_ENTRANT_CHECK_OFF;  FPU_verify_area(VERIFY_READ, _s, 4);  s = (long)get_fs_long((unsigned long *) _s);  RE_ENTRANT_CHECK_ON;  if (s == 0)    { reg_move(&CONST_Z, &FPU_loaded_data); return; }  if (s > 0)    FPU_loaded_data.sign = SIGN_POS;  else  {    s = -s;    FPU_loaded_data.sign = SIGN_NEG;  }  e = EXP_BIAS + 31;  FPU_loaded_data.sigh = s;  FPU_loaded_data.sigl = 0;  FPU_loaded_data.exp = e;  FPU_loaded_data.tag = TW_Valid;  normalize_nuo(&FPU_loaded_data);}/* Get a short from user memory */void reg_load_int16(void){  short *_s = (short *)FPU_data_address;  int s, e;  RE_ENTRANT_CHECK_OFF;  FPU_verify_area(VERIFY_READ, _s, 2);  /* Cast as short to get the sign extended. */  s = (short)get_fs_word((unsigned short *) _s);  RE_ENTRANT_CHECK_ON;  if (s == 0)    { reg_move(&CONST_Z, &FPU_loaded_data); return; }  if (s > 0)    FPU_loaded_data.sign = SIGN_POS;  else  {    s = -s;    FPU_loaded_data.sign = SIGN_NEG;  }  e = EXP_BIAS + 15;  FPU_loaded_data.sigh = s << 16;  FPU_loaded_data.sigl = 0;  FPU_loaded_data.exp = e;  FPU_loaded_data.tag = TW_Valid;  normalize_nuo(&FPU_loaded_data);}/* Get a packed bcd array from user memory */void reg_load_bcd(void){  char *s = (char *)FPU_data_address;  int pos;  unsigned char bcd;  long long l=0;  RE_ENTRANT_CHECK_OFF;  FPU_verify_area(VERIFY_READ, s, 10);  RE_ENTRANT_CHECK_ON;  for ( pos = 8; pos >= 0; pos--)    {      l *= 10;      RE_ENTRANT_CHECK_OFF;      bcd = (unsigned char)get_fs_byte((unsigned char *) s+pos);      RE_ENTRANT_CHECK_ON;      l += bcd >> 4;      l *= 10;      l += bcd & 0x0f;    }    /* Finish all access to user memory before putting stuff into     the static FPU_loaded_data */  RE_ENTRANT_CHECK_OFF;  FPU_loaded_data.sign =    ((unsigned char)get_fs_byte((unsigned char *) s+9)) & 0x80 ?      SIGN_NEG : SIGN_POS;  RE_ENTRANT_CHECK_ON;  if (l == 0)    {      char sign = FPU_loaded_data.sign;      reg_move(&CONST_Z, &FPU_loaded_data);      FPU_loaded_data.sign = sign;    }  else    {      significand(&FPU_loaded_data) = l;      FPU_loaded_data.exp = EXP_BIAS + 63;      FPU_loaded_data.tag = TW_Valid;      normalize_nuo(&FPU_loaded_data);    }}/*===========================================================================*//* Put a long double into user memory */int reg_store_extended(void){  /*    The only exception raised by an attempt to store to an    extended format is the Invalid Stack exception, i.e.    attempting to store from an empty register.   */  long double *d = (long double *)FPU_data_address;  if ( FPU_st0_tag != TW_Empty )    {      RE_ENTRANT_CHECK_OFF;      FPU_verify_area(VERIFY_WRITE, d, 10);      RE_ENTRANT_CHECK_ON;      write_to_extended(FPU_st0_ptr, (char *) FPU_data_address);      return 1;    }  /* Empty register (stack underflow) */  EXCEPTION(EX_StackUnder);  if ( control_word & CW_Invalid )    {      /* The masked response */      /* Put out the QNaN indefinite */      RE_ENTRANT_CHECK_OFF;      FPU_verify_area(VERIFY_WRITE,d,10);      put_fs_long(0, (unsigned long *) d);      put_fs_long(0xc0000000, 1 + (unsigned long *) d);      put_fs_word(0xffff, 4 + (short *) d);      RE_ENTRANT_CHECK_ON;      return 1;    }  else    return 0;}/* Put a double into user memory */int reg_store_double(void){  double *dfloat = (double *)FPU_data_address;  unsigned long l[2];  unsigned long increment = 0;	/* avoid gcc warnings */  if (FPU_st0_tag == TW_Valid)    {      int exp;      FPU_REG tmp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -