OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [i386/] [math-emu/] [load_store.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1623 jcastillo
/*---------------------------------------------------------------------------+
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,1994                                              |
8
 |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
9
 |                       Australia.  E-mail   billm@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   /* 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() { st0_ptr->tag = TW_Empty; top++; }
36
 
37
 
38
static unsigned char const 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
unsigned char const data_sizes_16[32] = {
50
  4,  4,  8,  2,  0,  0,  0,  0,
51
  4,  4,  8,  2,  4,  4,  8,  2,
52
  14, 0, 94, 10,  2, 10,  0,  8,
53
  14, 0, 94, 10,  2, 10,  2,  8
54
};
55
 
56
unsigned char const data_sizes_32[32] = {
57
  4,  4,  8,  2,  0,  0,  0,  0,
58
  4,  4,  8,  2,  4,  4,  8,  2,
59
  28, 0,108, 10,  2, 10,  0,  8,
60
  28, 0,108, 10,  2, 10,  2,  8
61
};
62
 
63
int load_store_instr(unsigned char type, fpu_addr_modes addr_modes,
64
                     void *data_address)
65
{
66
  FPU_REG loaded_data;
67
  FPU_REG *st0_ptr;
68
 
69
  st0_ptr = NULL;    /* Initialized just to stop compiler warnings. */
70
 
71
  if ( addr_modes.default_mode & PROTECTED )
72
    {
73
      if ( addr_modes.default_mode == SEG32 )
74
        {
75
          if ( access_limit < data_sizes_32[type] )
76
            math_abort(FPU_info,SIGSEGV);
77
        }
78
      else if ( addr_modes.default_mode == PM16 )
79
        {
80
          if ( access_limit < data_sizes_16[type] )
81
            math_abort(FPU_info,SIGSEGV);
82
        }
83
#ifdef PARANOID
84
      else
85
        EXCEPTION(EX_INTERNAL|0x140);
86
#endif PARANOID
87
    }
88
 
89
  switch ( type_table[type] )
90
    {
91
    case _NONE_:
92
      break;
93
    case _REG0_:
94
      st0_ptr = &st(0);       /* Some of these instructions pop after
95
                                 storing */
96
      break;
97
    case _PUSH_:
98
      {
99
        st0_ptr = &st(-1);
100
        if ( st0_ptr->tag != TW_Empty )
101
          { stack_overflow(); return 0; }
102
        top--;
103
      }
104
      break;
105
    case _null_:
106
      FPU_illegal();
107
      return 0;
108
#ifdef PARANOID
109
    default:
110
      EXCEPTION(EX_INTERNAL|0x141);
111
      return 0;
112
#endif PARANOID
113
    }
114
 
115
  switch ( type )
116
    {
117
    case 000:       /* fld m32real */
118
      clear_C1();
119
      reg_load_single((float *)data_address, &loaded_data);
120
      if ( (loaded_data.tag == TW_NaN) &&
121
          real_2op_NaN(&loaded_data, &loaded_data, &loaded_data) )
122
        {
123
          top++;
124
          break;
125
        }
126
      reg_move(&loaded_data, st0_ptr);
127
      break;
128
    case 001:      /* fild m32int */
129
      clear_C1();
130
      reg_load_int32((long *)data_address, st0_ptr);
131
      break;
132
    case 002:      /* fld m64real */
133
      clear_C1();
134
      reg_load_double((double *)data_address, &loaded_data);
135
      if ( (loaded_data.tag == TW_NaN) &&
136
          real_2op_NaN(&loaded_data, &loaded_data, &loaded_data) )
137
        {
138
          top++;
139
          break;
140
        }
141
      reg_move(&loaded_data, st0_ptr);
142
      break;
143
    case 003:      /* fild m16int */
144
      clear_C1();
145
      reg_load_int16((short *)data_address, st0_ptr);
146
      break;
147
    case 010:      /* fst m32real */
148
      clear_C1();
149
      reg_store_single((float *)data_address, st0_ptr);
150
      break;
151
    case 011:      /* fist m32int */
152
      clear_C1();
153
      reg_store_int32((long *)data_address, st0_ptr);
154
      break;
155
    case 012:     /* fst m64real */
156
      clear_C1();
157
      reg_store_double((double *)data_address, st0_ptr);
158
      break;
159
    case 013:     /* fist m16int */
160
      clear_C1();
161
      reg_store_int16((short *)data_address, st0_ptr);
162
      break;
163
    case 014:     /* fstp m32real */
164
      clear_C1();
165
      if ( reg_store_single((float *)data_address, st0_ptr) )
166
        pop_0();  /* pop only if the number was actually stored
167
                     (see the 80486 manual p16-28) */
168
      break;
169
    case 015:     /* fistp m32int */
170
      clear_C1();
171
      if ( reg_store_int32((long *)data_address, st0_ptr) )
172
        pop_0();  /* pop only if the number was actually stored
173
                     (see the 80486 manual p16-28) */
174
      break;
175
    case 016:     /* fstp m64real */
176
      clear_C1();
177
      if ( reg_store_double((double *)data_address, st0_ptr) )
178
        pop_0();  /* pop only if the number was actually stored
179
                     (see the 80486 manual p16-28) */
180
      break;
181
    case 017:     /* fistp m16int */
182
      clear_C1();
183
      if ( reg_store_int16((short *)data_address, st0_ptr) )
184
        pop_0();  /* pop only if the number was actually stored
185
                     (see the 80486 manual p16-28) */
186
      break;
187
    case 020:     /* fldenv  m14/28byte */
188
      fldenv(addr_modes, (char *)data_address);
189
      /* Ensure that the values just loaded are not changed by
190
         fix-up operations. */
191
      return 1;
192
    case 022:     /* frstor m94/108byte */
193
      frstor(addr_modes, (char *)data_address);
194
      /* Ensure that the values just loaded are not changed by
195
         fix-up operations. */
196
      return 1;
197
    case 023:     /* fbld m80dec */
198
      clear_C1();
199
      reg_load_bcd((char *)data_address, st0_ptr);
200
      break;
201
    case 024:     /* fldcw */
202
      RE_ENTRANT_CHECK_OFF;
203
      FPU_verify_area(VERIFY_READ, data_address, 2);
204
      control_word = get_fs_word((unsigned short *) data_address);
205
      RE_ENTRANT_CHECK_ON;
206
      if ( partial_status & ~control_word & CW_Exceptions )
207
        partial_status |= (SW_Summary | SW_Backward);
208
      else
209
        partial_status &= ~(SW_Summary | SW_Backward);
210
#ifdef PECULIAR_486
211
      control_word |= 0x40;  /* An 80486 appears to always set this bit */
212
#endif PECULIAR_486
213
      return 1;
214
    case 025:      /* fld m80real */
215
      clear_C1();
216
      reg_load_extended((long double *)data_address, st0_ptr);
217
      break;
218
    case 027:      /* fild m64int */
219
      clear_C1();
220
      reg_load_int64((long long *)data_address, st0_ptr);
221
      break;
222
    case 030:     /* fstenv  m14/28byte */
223
      fstenv(addr_modes, (char *)data_address);
224
      return 1;
225
    case 032:      /* fsave */
226
      fsave(addr_modes, (char *)data_address);
227
      return 1;
228
    case 033:      /* fbstp m80dec */
229
      clear_C1();
230
      if ( reg_store_bcd((char *)data_address, st0_ptr) )
231
        pop_0();  /* pop only if the number was actually stored
232
                     (see the 80486 manual p16-28) */
233
      break;
234
    case 034:      /* fstcw m16int */
235
      RE_ENTRANT_CHECK_OFF;
236
      FPU_verify_area(VERIFY_WRITE,data_address,2);
237
      put_fs_word(control_word, (short *) data_address);
238
      RE_ENTRANT_CHECK_ON;
239
      return 1;
240
    case 035:      /* fstp m80real */
241
      clear_C1();
242
      if ( reg_store_extended((long double *)data_address, st0_ptr) )
243
        pop_0();  /* pop only if the number was actually stored
244
                     (see the 80486 manual p16-28) */
245
      break;
246
    case 036:      /* fstsw m2byte */
247
      RE_ENTRANT_CHECK_OFF;
248
      FPU_verify_area(VERIFY_WRITE,data_address,2);
249
      put_fs_word(status_word(),(short *) data_address);
250
      RE_ENTRANT_CHECK_ON;
251
      return 1;
252
    case 037:      /* fistp m64int */
253
      clear_C1();
254
      if ( reg_store_int64((long long *)data_address, st0_ptr) )
255
        pop_0();  /* pop only if the number was actually stored
256
                     (see the 80486 manual p16-28) */
257
      break;
258
    }
259
  return 0;
260
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.