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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [tags/] [linux-2.6/] [linux-2.6.24_or32_unified_v2.3/] [arch/] [arm/] [nwfpe/] [fpa11_cpdt.c] - Blame information for rev 3

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

Line No. Rev Author Line
1 3 xianfeng
/*
2
    NetWinder Floating Point Emulator
3
    (c) Rebel.com, 1998-1999
4
    (c) Philip Blundell, 1998, 2001
5
 
6
    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7
 
8
    This program is free software; you can redistribute it and/or modify
9
    it under the terms of the GNU General Public License as published by
10
    the Free Software Foundation; either version 2 of the License, or
11
    (at your option) any later version.
12
 
13
    This program is distributed in the hope that it will be useful,
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
    GNU General Public License for more details.
17
 
18
    You should have received a copy of the GNU General Public License
19
    along with this program; if not, write to the Free Software
20
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
*/
22
 
23
#include "fpa11.h"
24
#include "softfloat.h"
25
#include "fpopcode.h"
26
#include "fpmodule.h"
27
#include "fpmodule.inl"
28
 
29
#include <asm/uaccess.h>
30
 
31
static inline void loadSingle(const unsigned int Fn, const unsigned int __user *pMem)
32
{
33
        FPA11 *fpa11 = GET_FPA11();
34
        fpa11->fType[Fn] = typeSingle;
35
        get_user(fpa11->fpreg[Fn].fSingle, pMem);
36
}
37
 
38
static inline void loadDouble(const unsigned int Fn, const unsigned int __user *pMem)
39
{
40
        FPA11 *fpa11 = GET_FPA11();
41
        unsigned int *p;
42
        p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
43
        fpa11->fType[Fn] = typeDouble;
44
#ifdef __ARMEB__
45
        get_user(p[0], &pMem[0]); /* sign & exponent */
46
        get_user(p[1], &pMem[1]);
47
#else
48
        get_user(p[0], &pMem[1]);
49
        get_user(p[1], &pMem[0]);        /* sign & exponent */
50
#endif
51
}
52
 
53
#ifdef CONFIG_FPE_NWFPE_XP
54
static inline void loadExtended(const unsigned int Fn, const unsigned int __user *pMem)
55
{
56
        FPA11 *fpa11 = GET_FPA11();
57
        unsigned int *p;
58
        p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
59
        fpa11->fType[Fn] = typeExtended;
60
        get_user(p[0], &pMem[0]); /* sign & exponent */
61
#ifdef __ARMEB__
62
        get_user(p[1], &pMem[1]);       /* ms bits */
63
        get_user(p[2], &pMem[2]);       /* ls bits */
64
#else
65
        get_user(p[1], &pMem[2]);       /* ls bits */
66
        get_user(p[2], &pMem[1]);       /* ms bits */
67
#endif
68
}
69
#endif
70
 
71
static inline void loadMultiple(const unsigned int Fn, const unsigned int __user *pMem)
72
{
73
        FPA11 *fpa11 = GET_FPA11();
74
        register unsigned int *p;
75
        unsigned long x;
76
 
77
        p = (unsigned int *) &(fpa11->fpreg[Fn]);
78
        get_user(x, &pMem[0]);
79
        fpa11->fType[Fn] = (x >> 14) & 0x00000003;
80
 
81
        switch (fpa11->fType[Fn]) {
82
        case typeSingle:
83
        case typeDouble:
84
                {
85
                        get_user(p[0], &pMem[2]);        /* Single */
86
                        get_user(p[1], &pMem[1]);       /* double msw */
87
                        p[2] = 0;                        /* empty */
88
                }
89
                break;
90
 
91
#ifdef CONFIG_FPE_NWFPE_XP
92
        case typeExtended:
93
                {
94
                        get_user(p[1], &pMem[2]);
95
                        get_user(p[2], &pMem[1]);       /* msw */
96
                        p[0] = (x & 0x80003fff);
97
                }
98
                break;
99
#endif
100
        }
101
}
102
 
103
static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
104
{
105
        FPA11 *fpa11 = GET_FPA11();
106
        union {
107
                float32 f;
108
                unsigned int i[1];
109
        } val;
110
 
111
        switch (fpa11->fType[Fn]) {
112
        case typeDouble:
113
                val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
114
                break;
115
 
116
#ifdef CONFIG_FPE_NWFPE_XP
117
        case typeExtended:
118
                val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
119
                break;
120
#endif
121
 
122
        default:
123
                val.f = fpa11->fpreg[Fn].fSingle;
124
        }
125
 
126
        put_user(val.i[0], pMem);
127
}
128
 
129
static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
130
{
131
        FPA11 *fpa11 = GET_FPA11();
132
        union {
133
                float64 f;
134
                unsigned int i[2];
135
        } val;
136
 
137
        switch (fpa11->fType[Fn]) {
138
        case typeSingle:
139
                val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
140
                break;
141
 
142
#ifdef CONFIG_FPE_NWFPE_XP
143
        case typeExtended:
144
                val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
145
                break;
146
#endif
147
 
148
        default:
149
                val.f = fpa11->fpreg[Fn].fDouble;
150
        }
151
 
152
#ifdef __ARMEB__
153
        put_user(val.i[0], &pMem[0]);     /* msw */
154
        put_user(val.i[1], &pMem[1]);   /* lsw */
155
#else
156
        put_user(val.i[1], &pMem[0]);    /* msw */
157
        put_user(val.i[0], &pMem[1]);    /* lsw */
158
#endif
159
}
160
 
161
#ifdef CONFIG_FPE_NWFPE_XP
162
static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMem)
163
{
164
        FPA11 *fpa11 = GET_FPA11();
165
        union {
166
                floatx80 f;
167
                unsigned int i[3];
168
        } val;
169
 
170
        switch (fpa11->fType[Fn]) {
171
        case typeSingle:
172
                val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
173
                break;
174
 
175
        case typeDouble:
176
                val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
177
                break;
178
 
179
        default:
180
                val.f = fpa11->fpreg[Fn].fExtended;
181
        }
182
 
183
        put_user(val.i[0], &pMem[0]);     /* sign & exp */
184
#ifdef __ARMEB__
185
        put_user(val.i[1], &pMem[1]);   /* msw */
186
        put_user(val.i[2], &pMem[2]);
187
#else
188
        put_user(val.i[1], &pMem[2]);
189
        put_user(val.i[2], &pMem[1]);   /* msw */
190
#endif
191
}
192
#endif
193
 
194
static inline void storeMultiple(const unsigned int Fn, unsigned int __user *pMem)
195
{
196
        FPA11 *fpa11 = GET_FPA11();
197
        register unsigned int nType, *p;
198
 
199
        p = (unsigned int *) &(fpa11->fpreg[Fn]);
200
        nType = fpa11->fType[Fn];
201
 
202
        switch (nType) {
203
        case typeSingle:
204
        case typeDouble:
205
                {
206
                        put_user(p[0], &pMem[2]);        /* single */
207
                        put_user(p[1], &pMem[1]);       /* double msw */
208
                        put_user(nType << 14, &pMem[0]);
209
                }
210
                break;
211
 
212
#ifdef CONFIG_FPE_NWFPE_XP
213
        case typeExtended:
214
                {
215
                        put_user(p[2], &pMem[1]);       /* msw */
216
                        put_user(p[1], &pMem[2]);
217
                        put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
218
                }
219
                break;
220
#endif
221
        }
222
}
223
 
224
unsigned int PerformLDF(const unsigned int opcode)
225
{
226
        unsigned int __user *pBase, *pAddress, *pFinal;
227
        unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
228
 
229
        pBase = (unsigned int __user *) readRegister(getRn(opcode));
230
        if (REG_PC == getRn(opcode)) {
231
                pBase += 2;
232
                write_back = 0;
233
        }
234
 
235
        pFinal = pBase;
236
        if (BIT_UP_SET(opcode))
237
                pFinal += getOffset(opcode);
238
        else
239
                pFinal -= getOffset(opcode);
240
 
241
        if (PREINDEXED(opcode))
242
                pAddress = pFinal;
243
        else
244
                pAddress = pBase;
245
 
246
        switch (opcode & MASK_TRANSFER_LENGTH) {
247
        case TRANSFER_SINGLE:
248
                loadSingle(getFd(opcode), pAddress);
249
                break;
250
        case TRANSFER_DOUBLE:
251
                loadDouble(getFd(opcode), pAddress);
252
                break;
253
#ifdef CONFIG_FPE_NWFPE_XP
254
        case TRANSFER_EXTENDED:
255
                loadExtended(getFd(opcode), pAddress);
256
                break;
257
#endif
258
        default:
259
                nRc = 0;
260
        }
261
 
262
        if (write_back)
263
                writeRegister(getRn(opcode), (unsigned long) pFinal);
264
        return nRc;
265
}
266
 
267
unsigned int PerformSTF(const unsigned int opcode)
268
{
269
        unsigned int __user *pBase, *pAddress, *pFinal;
270
        unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
271
        struct roundingData roundData;
272
 
273
        roundData.mode = SetRoundingMode(opcode);
274
        roundData.precision = SetRoundingPrecision(opcode);
275
        roundData.exception = 0;
276
 
277
        pBase = (unsigned int __user *) readRegister(getRn(opcode));
278
        if (REG_PC == getRn(opcode)) {
279
                pBase += 2;
280
                write_back = 0;
281
        }
282
 
283
        pFinal = pBase;
284
        if (BIT_UP_SET(opcode))
285
                pFinal += getOffset(opcode);
286
        else
287
                pFinal -= getOffset(opcode);
288
 
289
        if (PREINDEXED(opcode))
290
                pAddress = pFinal;
291
        else
292
                pAddress = pBase;
293
 
294
        switch (opcode & MASK_TRANSFER_LENGTH) {
295
        case TRANSFER_SINGLE:
296
                storeSingle(&roundData, getFd(opcode), pAddress);
297
                break;
298
        case TRANSFER_DOUBLE:
299
                storeDouble(&roundData, getFd(opcode), pAddress);
300
                break;
301
#ifdef CONFIG_FPE_NWFPE_XP
302
        case TRANSFER_EXTENDED:
303
                storeExtended(getFd(opcode), pAddress);
304
                break;
305
#endif
306
        default:
307
                nRc = 0;
308
        }
309
 
310
        if (roundData.exception)
311
                float_raise(roundData.exception);
312
 
313
        if (write_back)
314
                writeRegister(getRn(opcode), (unsigned long) pFinal);
315
        return nRc;
316
}
317
 
318
unsigned int PerformLFM(const unsigned int opcode)
319
{
320
        unsigned int __user *pBase, *pAddress, *pFinal;
321
        unsigned int i, Fd, write_back = WRITE_BACK(opcode);
322
 
323
        pBase = (unsigned int __user *) readRegister(getRn(opcode));
324
        if (REG_PC == getRn(opcode)) {
325
                pBase += 2;
326
                write_back = 0;
327
        }
328
 
329
        pFinal = pBase;
330
        if (BIT_UP_SET(opcode))
331
                pFinal += getOffset(opcode);
332
        else
333
                pFinal -= getOffset(opcode);
334
 
335
        if (PREINDEXED(opcode))
336
                pAddress = pFinal;
337
        else
338
                pAddress = pBase;
339
 
340
        Fd = getFd(opcode);
341
        for (i = getRegisterCount(opcode); i > 0; i--) {
342
                loadMultiple(Fd, pAddress);
343
                pAddress += 3;
344
                Fd++;
345
                if (Fd == 8)
346
                        Fd = 0;
347
        }
348
 
349
        if (write_back)
350
                writeRegister(getRn(opcode), (unsigned long) pFinal);
351
        return 1;
352
}
353
 
354
unsigned int PerformSFM(const unsigned int opcode)
355
{
356
        unsigned int __user *pBase, *pAddress, *pFinal;
357
        unsigned int i, Fd, write_back = WRITE_BACK(opcode);
358
 
359
        pBase = (unsigned int __user *) readRegister(getRn(opcode));
360
        if (REG_PC == getRn(opcode)) {
361
                pBase += 2;
362
                write_back = 0;
363
        }
364
 
365
        pFinal = pBase;
366
        if (BIT_UP_SET(opcode))
367
                pFinal += getOffset(opcode);
368
        else
369
                pFinal -= getOffset(opcode);
370
 
371
        if (PREINDEXED(opcode))
372
                pAddress = pFinal;
373
        else
374
                pAddress = pBase;
375
 
376
        Fd = getFd(opcode);
377
        for (i = getRegisterCount(opcode); i > 0; i--) {
378
                storeMultiple(Fd, pAddress);
379
                pAddress += 3;
380
                Fd++;
381
                if (Fd == 8)
382
                        Fd = 0;
383
        }
384
 
385
        if (write_back)
386
                writeRegister(getRn(opcode), (unsigned long) pFinal);
387
        return 1;
388
}
389
 
390
unsigned int EmulateCPDT(const unsigned int opcode)
391
{
392
        unsigned int nRc = 0;
393
 
394
        if (LDF_OP(opcode)) {
395
                nRc = PerformLDF(opcode);
396
        } else if (LFM_OP(opcode)) {
397
                nRc = PerformLFM(opcode);
398
        } else if (STF_OP(opcode)) {
399
                nRc = PerformSTF(opcode);
400
        } else if (SFM_OP(opcode)) {
401
                nRc = PerformSFM(opcode);
402
        } else {
403
                nRc = 0;
404
        }
405
 
406
        return nRc;
407
}

powered by: WebSVN 2.1.0

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