fpu_aux.c 2.73 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
/*---------------------------------------------------------------------------+
 |  fpu_aux.c                                                                |
 |                                                                           |
 | Code to implement some of the FPU auxiliary instructions.                 |
 |                                                                           |
 | Copyright (C) 1992    W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
 |                       Australia.  E-mail apm233m@vaxc.cc.monash.edu.au    |
 |                                                                           |
 |                                                                           |
 +---------------------------------------------------------------------------*/

#include "fpu_system.h"
#include "exception.h"
#include "fpu_emu.h"
#include "status_w.h"



static void fclex()
{
  status_word &= ~(SW_B|SW_ES|SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE);
  FPU_entry_eip = ip_offset;               /* We want no net effect */
}

/* Needs to be externally visible */
void finit()
{
  int r;
  control_word = 0x037e;
  status_word = 0;
  top = 0;
  for (r = 0; r < 8; r++)
    {
      regs[r].sign = 0;
      regs[r].tag = TW_Empty;
      regs[r].exp = 0;
      regs[r].sigh = 0;
      regs[r].sigl = 0;
    }
  FPU_entry_eip = ip_offset;               /* We want no net effect */
}

static FUNC finit_table[] = {
  Un_impl, Un_impl, fclex, finit, Un_impl, Un_impl, Un_impl, Un_impl
};

void finit_()
{
  (finit_table[FPU_rm])();
}


static void fstsw_ax()
{

  status_word &= ~SW_TOP;
  status_word |= (top&7) << SW_TOPS;

59
  *(short *) &FPU_EAX = status_word;
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

}

static FUNC fstsw_table[] = {
  fstsw_ax, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl
};

void fstsw_()
{
  (fstsw_table[FPU_rm])();
}



static void fnop()
{
}

FUNC fp_nop_table[] = {
  fnop, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl
};

void fp_nop()
{
  (fp_nop_table[FPU_rm])();
}


void fld_i_()
{
90
  FPU_REG *st_new_ptr;
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115

  if ( STACK_OVERFLOW )
    { stack_overflow(); return; }

  /* fld st(i) */
  if ( NOT_EMPTY(FPU_rm) )
    { reg_move(&st(FPU_rm), st_new_ptr); push(); }
  else
    {
      if ( control_word & EX_Invalid )
	{
	  /* The masked response */
	  push();
	  stack_underflow();
	}
      else
	EXCEPTION(EX_StackUnder);
    }

}


void fxch_i()
{
  /* fxch st(i) */
116 117 118 119
  FPU_REG t;
  register FPU_REG *sti_ptr = &st(FPU_rm);
  reg_move(FPU_st0_ptr, &t);
  reg_move(sti_ptr, FPU_st0_ptr);
120 121 122 123 124 125 126 127 128 129 130 131 132 133
  reg_move(&t, sti_ptr);
}


void ffree_()
{
  /* ffree st(i) */
  st(FPU_rm).tag = TW_Empty;
}


void fst_i_()
{
  /* fst st(i) */
134
  reg_move(FPU_st0_ptr, &st(FPU_rm));
135 136 137 138 139 140
}


void fstp_i()
{
  /* fstp st(i) */
141
  reg_move(FPU_st0_ptr, &st(FPU_rm));
142 143 144
  pop();
}