~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to target-alpha/vax_helper.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Helpers for vax floating point instructions.
3
 
 *
4
 
 *  Copyright (c) 2007 Jocelyn Mayer
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2 of the License, or (at your option) any later version.
10
 
 *
11
 
 * This library is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include "qemu/osdep.h"
21
 
#include "cpu.h"
22
 
#include "exec/exec-all.h"
23
 
#include "exec/helper-proto.h"
24
 
#include "fpu/softfloat.h"
25
 
 
26
 
#define FP_STATUS (env->fp_status)
27
 
 
28
 
 
29
 
/* F floating (VAX) */
30
 
static uint64_t float32_to_f(float32 fa)
31
 
{
32
 
    uint64_t r, exp, mant, sig;
33
 
    CPU_FloatU a;
34
 
 
35
 
    a.f = fa;
36
 
    sig = ((uint64_t)a.l & 0x80000000) << 32;
37
 
    exp = (a.l >> 23) & 0xff;
38
 
    mant = ((uint64_t)a.l & 0x007fffff) << 29;
39
 
 
40
 
    if (exp == 255) {
41
 
        /* NaN or infinity */
42
 
        r = 1; /* VAX dirty zero */
43
 
    } else if (exp == 0) {
44
 
        if (mant == 0) {
45
 
            /* Zero */
46
 
            r = 0;
47
 
        } else {
48
 
            /* Denormalized */
49
 
            r = sig | ((exp + 1) << 52) | mant;
50
 
        }
51
 
    } else {
52
 
        if (exp >= 253) {
53
 
            /* Overflow */
54
 
            r = 1; /* VAX dirty zero */
55
 
        } else {
56
 
            r = sig | ((exp + 2) << 52);
57
 
        }
58
 
    }
59
 
 
60
 
    return r;
61
 
}
62
 
 
63
 
static float32 f_to_float32(CPUAlphaState *env, uintptr_t retaddr, uint64_t a)
64
 
{
65
 
    uint32_t exp, mant_sig;
66
 
    CPU_FloatU r;
67
 
 
68
 
    exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
69
 
    mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
70
 
 
71
 
    if (unlikely(!exp && mant_sig)) {
72
 
        /* Reserved operands / Dirty zero */
73
 
        dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
74
 
    }
75
 
 
76
 
    if (exp < 3) {
77
 
        /* Underflow */
78
 
        r.l = 0;
79
 
    } else {
80
 
        r.l = ((exp - 2) << 23) | mant_sig;
81
 
    }
82
 
 
83
 
    return r.f;
84
 
}
85
 
 
86
 
uint32_t helper_f_to_memory(uint64_t a)
87
 
{
88
 
    uint32_t r;
89
 
    r =  (a & 0x00001fffe0000000ull) >> 13;
90
 
    r |= (a & 0x07ffe00000000000ull) >> 45;
91
 
    r |= (a & 0xc000000000000000ull) >> 48;
92
 
    return r;
93
 
}
94
 
 
95
 
uint64_t helper_memory_to_f(uint32_t a)
96
 
{
97
 
    uint64_t r;
98
 
    r =  ((uint64_t)(a & 0x0000c000)) << 48;
99
 
    r |= ((uint64_t)(a & 0x003fffff)) << 45;
100
 
    r |= ((uint64_t)(a & 0xffff0000)) << 13;
101
 
    if (!(a & 0x00004000)) {
102
 
        r |= 0x7ll << 59;
103
 
    }
104
 
    return r;
105
 
}
106
 
 
107
 
/* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong.  We should
108
 
   either implement VAX arithmetic properly or just signal invalid opcode.  */
109
 
 
110
 
uint64_t helper_addf(CPUAlphaState *env, uint64_t a, uint64_t b)
111
 
{
112
 
    float32 fa, fb, fr;
113
 
 
114
 
    fa = f_to_float32(env, GETPC(), a);
115
 
    fb = f_to_float32(env, GETPC(), b);
116
 
    fr = float32_add(fa, fb, &FP_STATUS);
117
 
    return float32_to_f(fr);
118
 
}
119
 
 
120
 
uint64_t helper_subf(CPUAlphaState *env, uint64_t a, uint64_t b)
121
 
{
122
 
    float32 fa, fb, fr;
123
 
 
124
 
    fa = f_to_float32(env, GETPC(), a);
125
 
    fb = f_to_float32(env, GETPC(), b);
126
 
    fr = float32_sub(fa, fb, &FP_STATUS);
127
 
    return float32_to_f(fr);
128
 
}
129
 
 
130
 
uint64_t helper_mulf(CPUAlphaState *env, uint64_t a, uint64_t b)
131
 
{
132
 
    float32 fa, fb, fr;
133
 
 
134
 
    fa = f_to_float32(env, GETPC(), a);
135
 
    fb = f_to_float32(env, GETPC(), b);
136
 
    fr = float32_mul(fa, fb, &FP_STATUS);
137
 
    return float32_to_f(fr);
138
 
}
139
 
 
140
 
uint64_t helper_divf(CPUAlphaState *env, uint64_t a, uint64_t b)
141
 
{
142
 
    float32 fa, fb, fr;
143
 
 
144
 
    fa = f_to_float32(env, GETPC(), a);
145
 
    fb = f_to_float32(env, GETPC(), b);
146
 
    fr = float32_div(fa, fb, &FP_STATUS);
147
 
    return float32_to_f(fr);
148
 
}
149
 
 
150
 
uint64_t helper_sqrtf(CPUAlphaState *env, uint64_t t)
151
 
{
152
 
    float32 ft, fr;
153
 
 
154
 
    ft = f_to_float32(env, GETPC(), t);
155
 
    fr = float32_sqrt(ft, &FP_STATUS);
156
 
    return float32_to_f(fr);
157
 
}
158
 
 
159
 
 
160
 
/* G floating (VAX) */
161
 
static uint64_t float64_to_g(float64 fa)
162
 
{
163
 
    uint64_t r, exp, mant, sig;
164
 
    CPU_DoubleU a;
165
 
 
166
 
    a.d = fa;
167
 
    sig = a.ll & 0x8000000000000000ull;
168
 
    exp = (a.ll >> 52) & 0x7ff;
169
 
    mant = a.ll & 0x000fffffffffffffull;
170
 
 
171
 
    if (exp == 2047) {
172
 
        /* NaN or infinity */
173
 
        r = 1; /* VAX dirty zero */
174
 
    } else if (exp == 0) {
175
 
        if (mant == 0) {
176
 
            /* Zero */
177
 
            r = 0;
178
 
        } else {
179
 
            /* Denormalized */
180
 
            r = sig | ((exp + 1) << 52) | mant;
181
 
        }
182
 
    } else {
183
 
        if (exp >= 2045) {
184
 
            /* Overflow */
185
 
            r = 1; /* VAX dirty zero */
186
 
        } else {
187
 
            r = sig | ((exp + 2) << 52);
188
 
        }
189
 
    }
190
 
 
191
 
    return r;
192
 
}
193
 
 
194
 
static float64 g_to_float64(CPUAlphaState *env, uintptr_t retaddr, uint64_t a)
195
 
{
196
 
    uint64_t exp, mant_sig;
197
 
    CPU_DoubleU r;
198
 
 
199
 
    exp = (a >> 52) & 0x7ff;
200
 
    mant_sig = a & 0x800fffffffffffffull;
201
 
 
202
 
    if (!exp && mant_sig) {
203
 
        /* Reserved operands / Dirty zero */
204
 
        dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
205
 
    }
206
 
 
207
 
    if (exp < 3) {
208
 
        /* Underflow */
209
 
        r.ll = 0;
210
 
    } else {
211
 
        r.ll = ((exp - 2) << 52) | mant_sig;
212
 
    }
213
 
 
214
 
    return r.d;
215
 
}
216
 
 
217
 
uint64_t helper_g_to_memory(uint64_t a)
218
 
{
219
 
    uint64_t r;
220
 
    r =  (a & 0x000000000000ffffull) << 48;
221
 
    r |= (a & 0x00000000ffff0000ull) << 16;
222
 
    r |= (a & 0x0000ffff00000000ull) >> 16;
223
 
    r |= (a & 0xffff000000000000ull) >> 48;
224
 
    return r;
225
 
}
226
 
 
227
 
uint64_t helper_memory_to_g(uint64_t a)
228
 
{
229
 
    uint64_t r;
230
 
    r =  (a & 0x000000000000ffffull) << 48;
231
 
    r |= (a & 0x00000000ffff0000ull) << 16;
232
 
    r |= (a & 0x0000ffff00000000ull) >> 16;
233
 
    r |= (a & 0xffff000000000000ull) >> 48;
234
 
    return r;
235
 
}
236
 
 
237
 
uint64_t helper_addg(CPUAlphaState *env, uint64_t a, uint64_t b)
238
 
{
239
 
    float64 fa, fb, fr;
240
 
 
241
 
    fa = g_to_float64(env, GETPC(), a);
242
 
    fb = g_to_float64(env, GETPC(), b);
243
 
    fr = float64_add(fa, fb, &FP_STATUS);
244
 
    return float64_to_g(fr);
245
 
}
246
 
 
247
 
uint64_t helper_subg(CPUAlphaState *env, uint64_t a, uint64_t b)
248
 
{
249
 
    float64 fa, fb, fr;
250
 
 
251
 
    fa = g_to_float64(env, GETPC(), a);
252
 
    fb = g_to_float64(env, GETPC(), b);
253
 
    fr = float64_sub(fa, fb, &FP_STATUS);
254
 
    return float64_to_g(fr);
255
 
}
256
 
 
257
 
uint64_t helper_mulg(CPUAlphaState *env, uint64_t a, uint64_t b)
258
 
{
259
 
    float64 fa, fb, fr;
260
 
 
261
 
    fa = g_to_float64(env, GETPC(), a);
262
 
    fb = g_to_float64(env, GETPC(), b);
263
 
    fr = float64_mul(fa, fb, &FP_STATUS);
264
 
    return float64_to_g(fr);
265
 
}
266
 
 
267
 
uint64_t helper_divg(CPUAlphaState *env, uint64_t a, uint64_t b)
268
 
{
269
 
    float64 fa, fb, fr;
270
 
 
271
 
    fa = g_to_float64(env, GETPC(), a);
272
 
    fb = g_to_float64(env, GETPC(), b);
273
 
    fr = float64_div(fa, fb, &FP_STATUS);
274
 
    return float64_to_g(fr);
275
 
}
276
 
 
277
 
uint64_t helper_sqrtg(CPUAlphaState *env, uint64_t a)
278
 
{
279
 
    float64 fa, fr;
280
 
 
281
 
    fa = g_to_float64(env, GETPC(), a);
282
 
    fr = float64_sqrt(fa, &FP_STATUS);
283
 
    return float64_to_g(fr);
284
 
}
285
 
 
286
 
uint64_t helper_cmpgeq(CPUAlphaState *env, uint64_t a, uint64_t b)
287
 
{
288
 
    float64 fa, fb;
289
 
 
290
 
    fa = g_to_float64(env, GETPC(), a);
291
 
    fb = g_to_float64(env, GETPC(), b);
292
 
 
293
 
    if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
294
 
        return 0x4000000000000000ULL;
295
 
    } else {
296
 
        return 0;
297
 
    }
298
 
}
299
 
 
300
 
uint64_t helper_cmpgle(CPUAlphaState *env, uint64_t a, uint64_t b)
301
 
{
302
 
    float64 fa, fb;
303
 
 
304
 
    fa = g_to_float64(env, GETPC(), a);
305
 
    fb = g_to_float64(env, GETPC(), b);
306
 
 
307
 
    if (float64_le(fa, fb, &FP_STATUS)) {
308
 
        return 0x4000000000000000ULL;
309
 
    } else {
310
 
        return 0;
311
 
    }
312
 
}
313
 
 
314
 
uint64_t helper_cmpglt(CPUAlphaState *env, uint64_t a, uint64_t b)
315
 
{
316
 
    float64 fa, fb;
317
 
 
318
 
    fa = g_to_float64(env, GETPC(), a);
319
 
    fb = g_to_float64(env, GETPC(), b);
320
 
 
321
 
    if (float64_lt(fa, fb, &FP_STATUS)) {
322
 
        return 0x4000000000000000ULL;
323
 
    } else {
324
 
        return 0;
325
 
    }
326
 
}
327
 
 
328
 
uint64_t helper_cvtqf(CPUAlphaState *env, uint64_t a)
329
 
{
330
 
    float32 fr = int64_to_float32(a, &FP_STATUS);
331
 
    return float32_to_f(fr);
332
 
}
333
 
 
334
 
uint64_t helper_cvtgf(CPUAlphaState *env, uint64_t a)
335
 
{
336
 
    float64 fa;
337
 
    float32 fr;
338
 
 
339
 
    fa = g_to_float64(env, GETPC(), a);
340
 
    fr = float64_to_float32(fa, &FP_STATUS);
341
 
    return float32_to_f(fr);
342
 
}
343
 
 
344
 
uint64_t helper_cvtgq(CPUAlphaState *env, uint64_t a)
345
 
{
346
 
    float64 fa = g_to_float64(env, GETPC(), a);
347
 
    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
348
 
}
349
 
 
350
 
uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a)
351
 
{
352
 
    float64 fr;
353
 
    fr = int64_to_float64(a, &FP_STATUS);
354
 
    return float64_to_g(fr);
355
 
}