root/kernel/FPU-emu/load_store.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. load_store_instr

   1 /*---------------------------------------------------------------------------+
   2  |  load_store.c                                                             |
   3  |                                                                           |
   4  | This file contains most of the code to interpret the FPU instructions     |
   5  | which load and store from user memory.                                    |
   6  |                                                                           |
   7  | Copyright (C) 1992,1993                                                   |
   8  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
   9  |                       Australia.  E-mail apm233m@vaxc.cc.monash.edu.au    |
  10  |                                                                           |
  11  |                                                                           |
  12  +---------------------------------------------------------------------------*/
  13 
  14 /*---------------------------------------------------------------------------+
  15  | Note:                                                                     |
  16  |    The file contains code which accesses user memory.                     |
  17  |    Emulator static data may change when user memory is accessed, due to   |
  18  |    other processes using the emulator while swapping is in progress.      |
  19  +---------------------------------------------------------------------------*/
  20 
  21 #include <asm/segment.h>
  22 
  23 #include "fpu_system.h"
  24 #include "exception.h"
  25 #include "fpu_emu.h"
  26 #include "status_w.h"
  27 #include "control_w.h"
  28 
  29 
  30 #define _NONE_ 0   /* FPU_st0_ptr etc not needed */
  31 #define _REG0_ 1   /* Will be storing st(0) */
  32 #define _PUSH_ 3   /* Need to check for space to push onto stack */
  33 #define _null_ 4   /* Function illegal or not implemented */
  34 
  35 #define pop_0() { pop_ptr->tag = TW_Empty; top++; }
  36 
  37 
  38 static unsigned char type_table[32] = {
  39   _PUSH_, _PUSH_, _PUSH_, _PUSH_,
  40   _null_, _null_, _null_, _null_,
  41   _REG0_, _REG0_, _REG0_, _REG0_,
  42   _REG0_, _REG0_, _REG0_, _REG0_,
  43   _NONE_, _null_, _NONE_, _PUSH_,
  44   _NONE_, _PUSH_, _null_, _PUSH_,
  45   _NONE_, _null_, _NONE_, _REG0_,
  46   _NONE_, _REG0_, _NONE_, _REG0_
  47   };
  48 
  49 void load_store_instr(char type)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51   FPU_REG *pop_ptr;  /* We need a version of FPU_st0_ptr which won't
  52                         change if the emulator is re-entered. */
  53 
  54   pop_ptr = NULL;    /* Initialized just to stop compiler warnings. */
  55   switch ( type_table[(int) (unsigned) type] )
  56     {
  57     case _NONE_:
  58       break;
  59     case _REG0_:
  60       pop_ptr = &st(0);       /* Some of these instructions pop after
  61                                  storing */
  62 
  63       FPU_st0_ptr = pop_ptr;      /* Set the global variables. */
  64       FPU_st0_tag = FPU_st0_ptr->tag;
  65       break;
  66     case _PUSH_:
  67       {
  68         pop_ptr = &st(-1);
  69         if ( pop_ptr->tag != TW_Empty )
  70           { stack_overflow(); return; }
  71         top--;
  72       }
  73       break;
  74     case _null_:
  75       Un_impl();
  76       return;
  77 #ifdef PARANOID
  78     default:
  79       EXCEPTION(EX_INTERNAL);
  80       return;
  81 #endif PARANOID
  82     }
  83 
  84 switch ( type )
  85   {
  86   case 000:       /* fld m32real */
  87 #ifdef PECULIAR_486
  88     /* Default, this conveys no information, but an 80486 does it. */
  89     clear_C1();
  90 #endif PECULIAR_486
  91     reg_load_single();
  92     if ( (FPU_loaded_data.tag == TW_NaN) &&
  93         real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
  94       {
  95         top++;
  96         break;
  97       }
  98     reg_move(&FPU_loaded_data, pop_ptr);
  99     break;
 100   case 001:      /* fild m32int */
 101 #ifdef PECULIAR_486
 102     /* Default, this conveys no information, but an 80486 does it. */
 103     clear_C1();
 104 #endif PECULIAR_486
 105     reg_load_int32();
 106     reg_move(&FPU_loaded_data, pop_ptr);
 107     break;
 108   case 002:      /* fld m64real */
 109 #ifdef PECULIAR_486
 110     /* Default, this conveys no information, but an 80486 does it. */
 111     clear_C1();
 112 #endif PECULIAR_486
 113     reg_load_double();
 114     if ( (FPU_loaded_data.tag == TW_NaN) &&
 115         real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
 116       {
 117         top++;
 118         break;
 119       }
 120     reg_move(&FPU_loaded_data, pop_ptr);
 121     break;
 122   case 003:      /* fild m16int */
 123 #ifdef PECULIAR_486
 124     /* Default, this conveys no information, but an 80486 does it. */
 125     clear_C1();
 126 #endif PECULIAR_486
 127     reg_load_int16();
 128     reg_move(&FPU_loaded_data, pop_ptr);
 129     break;
 130   case 010:      /* fst m32real */
 131 #ifdef PECULIAR_486
 132     /* Default, this conveys no information, but an 80486 does it. */
 133     clear_C1();
 134 #endif PECULIAR_486
 135     reg_store_single();
 136     break;
 137   case 011:      /* fist m32int */
 138 #ifdef PECULIAR_486
 139     /* Default, this conveys no information, but an 80486 does it. */
 140     clear_C1();
 141 #endif PECULIAR_486
 142     reg_store_int32();
 143     break;
 144   case 012:     /* fst m64real */
 145 #ifdef PECULIAR_486
 146     /* Default, this conveys no information, but an 80486 does it. */
 147     clear_C1();
 148 #endif PECULIAR_486
 149     reg_store_double();
 150     break;
 151   case 013:     /* fist m16int */
 152 #ifdef PECULIAR_486
 153     /* Default, this conveys no information, but an 80486 does it. */
 154     clear_C1();
 155 #endif PECULIAR_486
 156     reg_store_int16();
 157     break;
 158   case 014:     /* fstp m32real */
 159 #ifdef PECULIAR_486
 160     /* Default, this conveys no information, but an 80486 does it. */
 161     clear_C1();
 162 #endif PECULIAR_486
 163     if ( reg_store_single() )
 164       pop_0();  /* pop only if the number was actually stored
 165                  (see the 80486 manual p16-28) */
 166     break;
 167   case 015:     /* fistp m32int */
 168 #ifdef PECULIAR_486
 169     /* Default, this conveys no information, but an 80486 does it. */
 170     clear_C1();
 171 #endif PECULIAR_486
 172     if ( reg_store_int32() )
 173       pop_0();  /* pop only if the number was actually stored
 174                  (see the 80486 manual p16-28) */
 175     break;
 176   case 016:     /* fstp m64real */
 177 #ifdef PECULIAR_486
 178     /* Default, this conveys no information, but an 80486 does it. */
 179     clear_C1();
 180 #endif PECULIAR_486
 181     if ( reg_store_double() )
 182       pop_0();  /* pop only if the number was actually stored
 183                  (see the 80486 manual p16-28) */
 184     break;
 185   case 017:     /* fistp m16int */
 186 #ifdef PECULIAR_486
 187     /* Default, this conveys no information, but an 80486 does it. */
 188     clear_C1();
 189 #endif PECULIAR_486
 190     if ( reg_store_int16() )
 191       pop_0();  /* pop only if the number was actually stored
 192                  (see the 80486 manual p16-28) */
 193     break;
 194   case 020:     /* fldenv  m14/28byte */
 195     fldenv();
 196     break;
 197   case 022:     /* frstor m94/108byte */
 198     frstor();
 199     break;
 200   case 023:     /* fbld m80dec */
 201 #ifdef PECULIAR_486
 202     /* Default, this conveys no information, but an 80486 does it. */
 203     clear_C1();
 204 #endif PECULIAR_486
 205     reg_load_bcd();
 206     reg_move(&FPU_loaded_data, pop_ptr);
 207     break;
 208   case 024:     /* fldcw */
 209     RE_ENTRANT_CHECK_OFF;
 210     control_word = get_fs_word((unsigned short *) FPU_data_address);
 211     RE_ENTRANT_CHECK_ON;
 212     if ( partial_status & ~control_word & CW_Exceptions )
 213       partial_status |= (SW_Summary | SW_Backward);
 214     else
 215       partial_status &= ~(SW_Summary | SW_Backward);
 216 #ifdef PECULIAR_486
 217     control_word |= 0x40;  /* An 80486 appears to always set this bit */
 218 #endif PECULIAR_486
 219     NO_NET_DATA_EFFECT;
 220     NO_NET_INSTR_EFFECT;
 221     break;
 222   case 025:      /* fld m80real */
 223 #ifdef PECULIAR_486
 224     /* Default, this conveys no information, but an 80486 does it. */
 225     clear_C1();
 226 #endif PECULIAR_486
 227     reg_load_extended();
 228     reg_move(&FPU_loaded_data, pop_ptr);
 229     break;
 230   case 027:      /* fild m64int */
 231 #ifdef PECULIAR_486
 232     /* Default, this conveys no information, but an 80486 does it. */
 233     clear_C1();
 234 #endif PECULIAR_486
 235     reg_load_int64();
 236     reg_move(&FPU_loaded_data, pop_ptr);
 237     break;
 238   case 030:     /* fstenv  m14/28byte */
 239     fstenv();
 240     NO_NET_DATA_EFFECT;
 241     break;
 242   case 032:      /* fsave */
 243     fsave();
 244     NO_NET_DATA_EFFECT;
 245     break;
 246   case 033:      /* fbstp m80dec */
 247 #ifdef PECULIAR_486
 248     /* Default, this conveys no information, but an 80486 does it. */
 249     clear_C1();
 250 #endif PECULIAR_486
 251     if ( reg_store_bcd() )
 252       pop_0();  /* pop only if the number was actually stored
 253                  (see the 80486 manual p16-28) */
 254     break;
 255   case 034:      /* fstcw m16int */
 256     RE_ENTRANT_CHECK_OFF;
 257     verify_area(VERIFY_WRITE,FPU_data_address,2);
 258     put_fs_word(control_word, (short *) FPU_data_address);
 259     RE_ENTRANT_CHECK_ON;
 260     NO_NET_DATA_EFFECT;
 261     NO_NET_INSTR_EFFECT;
 262     break;
 263   case 035:      /* fstp m80real */
 264 #ifdef PECULIAR_486
 265     /* Default, this conveys no information, but an 80486 does it. */
 266     clear_C1();
 267 #endif PECULIAR_486
 268     if ( reg_store_extended() )
 269       pop_0();  /* pop only if the number was actually stored
 270                  (see the 80486 manual p16-28) */
 271     break;
 272   case 036:      /* fstsw m2byte */
 273     RE_ENTRANT_CHECK_OFF;
 274     verify_area(VERIFY_WRITE,FPU_data_address,2);
 275     put_fs_word(status_word(),(short *) FPU_data_address);
 276     RE_ENTRANT_CHECK_ON;
 277     NO_NET_DATA_EFFECT;
 278     NO_NET_INSTR_EFFECT;
 279     break;
 280   case 037:      /* fistp m64int */
 281 #ifdef PECULIAR_486
 282     /* Default, this conveys no information, but an 80486 does it. */
 283     clear_C1();
 284 #endif PECULIAR_486
 285     if ( reg_store_int64() )
 286       pop_0();  /* pop only if the number was actually stored
 287                  (see the 80486 manual p16-28) */
 288     break;
 289   }
 290 }

/* [previous][next][first][last][top][bottom][index][help] */