2
* Helpers for vax floating point instructions.
4
* Copyright (c) 2007 Jocelyn Mayer
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.
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.
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/>.
20
#include "qemu/osdep.h"
22
#include "exec/exec-all.h"
23
#include "exec/helper-proto.h"
24
#include "fpu/softfloat.h"
26
#define FP_STATUS (env->fp_status)
29
/* F floating (VAX) */
30
static uint64_t float32_to_f(float32 fa)
32
uint64_t r, exp, mant, sig;
36
sig = ((uint64_t)a.l & 0x80000000) << 32;
37
exp = (a.l >> 23) & 0xff;
38
mant = ((uint64_t)a.l & 0x007fffff) << 29;
42
r = 1; /* VAX dirty zero */
43
} else if (exp == 0) {
49
r = sig | ((exp + 1) << 52) | mant;
54
r = 1; /* VAX dirty zero */
56
r = sig | ((exp + 2) << 52);
63
static float32 f_to_float32(CPUAlphaState *env, uintptr_t retaddr, uint64_t a)
65
uint32_t exp, mant_sig;
68
exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
69
mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
71
if (unlikely(!exp && mant_sig)) {
72
/* Reserved operands / Dirty zero */
73
dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
80
r.l = ((exp - 2) << 23) | mant_sig;
86
uint32_t helper_f_to_memory(uint64_t a)
89
r = (a & 0x00001fffe0000000ull) >> 13;
90
r |= (a & 0x07ffe00000000000ull) >> 45;
91
r |= (a & 0xc000000000000000ull) >> 48;
95
uint64_t helper_memory_to_f(uint32_t a)
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)) {
107
/* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong. We should
108
either implement VAX arithmetic properly or just signal invalid opcode. */
110
uint64_t helper_addf(CPUAlphaState *env, uint64_t a, uint64_t b)
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);
120
uint64_t helper_subf(CPUAlphaState *env, uint64_t a, uint64_t b)
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);
130
uint64_t helper_mulf(CPUAlphaState *env, uint64_t a, uint64_t b)
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);
140
uint64_t helper_divf(CPUAlphaState *env, uint64_t a, uint64_t b)
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);
150
uint64_t helper_sqrtf(CPUAlphaState *env, uint64_t t)
154
ft = f_to_float32(env, GETPC(), t);
155
fr = float32_sqrt(ft, &FP_STATUS);
156
return float32_to_f(fr);
160
/* G floating (VAX) */
161
static uint64_t float64_to_g(float64 fa)
163
uint64_t r, exp, mant, sig;
167
sig = a.ll & 0x8000000000000000ull;
168
exp = (a.ll >> 52) & 0x7ff;
169
mant = a.ll & 0x000fffffffffffffull;
172
/* NaN or infinity */
173
r = 1; /* VAX dirty zero */
174
} else if (exp == 0) {
180
r = sig | ((exp + 1) << 52) | mant;
185
r = 1; /* VAX dirty zero */
187
r = sig | ((exp + 2) << 52);
194
static float64 g_to_float64(CPUAlphaState *env, uintptr_t retaddr, uint64_t a)
196
uint64_t exp, mant_sig;
199
exp = (a >> 52) & 0x7ff;
200
mant_sig = a & 0x800fffffffffffffull;
202
if (!exp && mant_sig) {
203
/* Reserved operands / Dirty zero */
204
dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
211
r.ll = ((exp - 2) << 52) | mant_sig;
217
uint64_t helper_g_to_memory(uint64_t a)
220
r = (a & 0x000000000000ffffull) << 48;
221
r |= (a & 0x00000000ffff0000ull) << 16;
222
r |= (a & 0x0000ffff00000000ull) >> 16;
223
r |= (a & 0xffff000000000000ull) >> 48;
227
uint64_t helper_memory_to_g(uint64_t a)
230
r = (a & 0x000000000000ffffull) << 48;
231
r |= (a & 0x00000000ffff0000ull) << 16;
232
r |= (a & 0x0000ffff00000000ull) >> 16;
233
r |= (a & 0xffff000000000000ull) >> 48;
237
uint64_t helper_addg(CPUAlphaState *env, uint64_t a, uint64_t b)
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);
247
uint64_t helper_subg(CPUAlphaState *env, uint64_t a, uint64_t b)
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);
257
uint64_t helper_mulg(CPUAlphaState *env, uint64_t a, uint64_t b)
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);
267
uint64_t helper_divg(CPUAlphaState *env, uint64_t a, uint64_t b)
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);
277
uint64_t helper_sqrtg(CPUAlphaState *env, uint64_t a)
281
fa = g_to_float64(env, GETPC(), a);
282
fr = float64_sqrt(fa, &FP_STATUS);
283
return float64_to_g(fr);
286
uint64_t helper_cmpgeq(CPUAlphaState *env, uint64_t a, uint64_t b)
290
fa = g_to_float64(env, GETPC(), a);
291
fb = g_to_float64(env, GETPC(), b);
293
if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
294
return 0x4000000000000000ULL;
300
uint64_t helper_cmpgle(CPUAlphaState *env, uint64_t a, uint64_t b)
304
fa = g_to_float64(env, GETPC(), a);
305
fb = g_to_float64(env, GETPC(), b);
307
if (float64_le(fa, fb, &FP_STATUS)) {
308
return 0x4000000000000000ULL;
314
uint64_t helper_cmpglt(CPUAlphaState *env, uint64_t a, uint64_t b)
318
fa = g_to_float64(env, GETPC(), a);
319
fb = g_to_float64(env, GETPC(), b);
321
if (float64_lt(fa, fb, &FP_STATUS)) {
322
return 0x4000000000000000ULL;
328
uint64_t helper_cvtqf(CPUAlphaState *env, uint64_t a)
330
float32 fr = int64_to_float32(a, &FP_STATUS);
331
return float32_to_f(fr);
334
uint64_t helper_cvtgf(CPUAlphaState *env, uint64_t a)
339
fa = g_to_float64(env, GETPC(), a);
340
fr = float64_to_float32(fa, &FP_STATUS);
341
return float32_to_f(fr);
344
uint64_t helper_cvtgq(CPUAlphaState *env, uint64_t a)
346
float64 fa = g_to_float64(env, GETPC(), a);
347
return float64_to_int64_round_to_zero(fa, &FP_STATUS);
350
uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a)
353
fr = int64_to_float64(a, &FP_STATUS);
354
return float64_to_g(fr);