root / targetalpha / op_helper.c @ 866be65d
History  View  Annotate  Download (25.1 kB)
1 
/*


2 
* Alpha emulation cpu microoperations helpers for qemu.

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 "exec.h" 
21 
#include "hostutils.h" 
22 
#include "softfloat.h" 
23 
#include "helper.h" 
24  
25 
/*****************************************************************************/

26 
/* Exceptions processing helpers */

27 
void helper_excp (int excp, int error) 
28 
{ 
29 
env>exception_index = excp; 
30 
env>error_code = error; 
31 
cpu_loop_exit(); 
32 
} 
33  
34 
uint64_t helper_load_pcc (void)

35 
{ 
36 
/* XXX: TODO */

37 
return 0; 
38 
} 
39  
40 
uint64_t helper_load_fpcr (void)

41 
{ 
42 
return cpu_alpha_load_fpcr (env);

43 
} 
44  
45 
void helper_store_fpcr (uint64_t val)

46 
{ 
47 
cpu_alpha_store_fpcr (env, val); 
48 
} 
49  
50 
static spinlock_t intr_cpu_lock = SPIN_LOCK_UNLOCKED;

51  
52 
uint64_t helper_rs(void)

53 
{ 
54 
uint64_t tmp; 
55  
56 
spin_lock(&intr_cpu_lock); 
57 
tmp = env>intr_flag; 
58 
env>intr_flag = 1;

59 
spin_unlock(&intr_cpu_lock); 
60  
61 
return tmp;

62 
} 
63  
64 
uint64_t helper_rc(void)

65 
{ 
66 
uint64_t tmp; 
67  
68 
spin_lock(&intr_cpu_lock); 
69 
tmp = env>intr_flag; 
70 
env>intr_flag = 0;

71 
spin_unlock(&intr_cpu_lock); 
72  
73 
return tmp;

74 
} 
75  
76 
uint64_t helper_addqv (uint64_t op1, uint64_t op2) 
77 
{ 
78 
uint64_t tmp = op1; 
79 
op1 += op2; 
80 
if (unlikely((tmp ^ op2 ^ (1ULL)) & (tmp ^ op1) & (1ULL << 63))) { 
81 
helper_excp(EXCP_ARITH, EXC_M_IOV); 
82 
} 
83 
return op1;

84 
} 
85  
86 
uint64_t helper_addlv (uint64_t op1, uint64_t op2) 
87 
{ 
88 
uint64_t tmp = op1; 
89 
op1 = (uint32_t)(op1 + op2); 
90 
if (unlikely((tmp ^ op2 ^ (1UL)) & (tmp ^ op1) & (1UL << 31))) { 
91 
helper_excp(EXCP_ARITH, EXC_M_IOV); 
92 
} 
93 
return op1;

94 
} 
95  
96 
uint64_t helper_subqv (uint64_t op1, uint64_t op2) 
97 
{ 
98 
uint64_t res; 
99 
res = op1  op2; 
100 
if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) { 
101 
helper_excp(EXCP_ARITH, EXC_M_IOV); 
102 
} 
103 
return res;

104 
} 
105  
106 
uint64_t helper_sublv (uint64_t op1, uint64_t op2) 
107 
{ 
108 
uint32_t res; 
109 
res = op1  op2; 
110 
if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) { 
111 
helper_excp(EXCP_ARITH, EXC_M_IOV); 
112 
} 
113 
return res;

114 
} 
115  
116 
uint64_t helper_mullv (uint64_t op1, uint64_t op2) 
117 
{ 
118 
int64_t res = (int64_t)op1 * (int64_t)op2; 
119  
120 
if (unlikely((int32_t)res != res)) {

121 
helper_excp(EXCP_ARITH, EXC_M_IOV); 
122 
} 
123 
return (int64_t)((int32_t)res);

124 
} 
125  
126 
uint64_t helper_mulqv (uint64_t op1, uint64_t op2) 
127 
{ 
128 
uint64_t tl, th; 
129  
130 
muls64(&tl, &th, op1, op2); 
131 
/* If th != 0 && th != 1, then we had an overflow */

132 
if (unlikely((th + 1) > 1)) { 
133 
helper_excp(EXCP_ARITH, EXC_M_IOV); 
134 
} 
135 
return tl;

136 
} 
137  
138 
uint64_t helper_umulh (uint64_t op1, uint64_t op2) 
139 
{ 
140 
uint64_t tl, th; 
141  
142 
mulu64(&tl, &th, op1, op2); 
143 
return th;

144 
} 
145  
146 
uint64_t helper_ctpop (uint64_t arg) 
147 
{ 
148 
return ctpop64(arg);

149 
} 
150  
151 
uint64_t helper_ctlz (uint64_t arg) 
152 
{ 
153 
return clz64(arg);

154 
} 
155  
156 
uint64_t helper_cttz (uint64_t arg) 
157 
{ 
158 
return ctz64(arg);

159 
} 
160  
161 
static inline uint64_t byte_zap(uint64_t op, uint8_t mskb) 
162 
{ 
163 
uint64_t mask; 
164  
165 
mask = 0;

166 
mask = ((mskb >> 0) & 1) * 0x00000000000000FFULL; 
167 
mask = ((mskb >> 1) & 1) * 0x000000000000FF00ULL; 
168 
mask = ((mskb >> 2) & 1) * 0x0000000000FF0000ULL; 
169 
mask = ((mskb >> 3) & 1) * 0x00000000FF000000ULL; 
170 
mask = ((mskb >> 4) & 1) * 0x000000FF00000000ULL; 
171 
mask = ((mskb >> 5) & 1) * 0x0000FF0000000000ULL; 
172 
mask = ((mskb >> 6) & 1) * 0x00FF000000000000ULL; 
173 
mask = ((mskb >> 7) & 1) * 0xFF00000000000000ULL; 
174  
175 
return op & ~mask;

176 
} 
177  
178 
uint64_t helper_zap(uint64_t val, uint64_t mask) 
179 
{ 
180 
return byte_zap(val, mask);

181 
} 
182  
183 
uint64_t helper_zapnot(uint64_t val, uint64_t mask) 
184 
{ 
185 
return byte_zap(val, ~mask);

186 
} 
187  
188 
uint64_t helper_cmpbge (uint64_t op1, uint64_t op2) 
189 
{ 
190 
uint8_t opa, opb, res; 
191 
int i;

192  
193 
res = 0;

194 
for (i = 0; i < 8; i++) { 
195 
opa = op1 >> (i * 8);

196 
opb = op2 >> (i * 8);

197 
if (opa >= opb)

198 
res = 1 << i;

199 
} 
200 
return res;

201 
} 
202  
203 
uint64_t helper_minub8 (uint64_t op1, uint64_t op2) 
204 
{ 
205 
uint64_t res = 0;

206 
uint8_t opa, opb, opr; 
207 
int i;

208  
209 
for (i = 0; i < 8; ++i) { 
210 
opa = op1 >> (i * 8);

211 
opb = op2 >> (i * 8);

212 
opr = opa < opb ? opa : opb; 
213 
res = (uint64_t)opr << (i * 8);

214 
} 
215 
return res;

216 
} 
217  
218 
uint64_t helper_minsb8 (uint64_t op1, uint64_t op2) 
219 
{ 
220 
uint64_t res = 0;

221 
int8_t opa, opb; 
222 
uint8_t opr; 
223 
int i;

224  
225 
for (i = 0; i < 8; ++i) { 
226 
opa = op1 >> (i * 8);

227 
opb = op2 >> (i * 8);

228 
opr = opa < opb ? opa : opb; 
229 
res = (uint64_t)opr << (i * 8);

230 
} 
231 
return res;

232 
} 
233  
234 
uint64_t helper_minuw4 (uint64_t op1, uint64_t op2) 
235 
{ 
236 
uint64_t res = 0;

237 
uint16_t opa, opb, opr; 
238 
int i;

239  
240 
for (i = 0; i < 4; ++i) { 
241 
opa = op1 >> (i * 16);

242 
opb = op2 >> (i * 16);

243 
opr = opa < opb ? opa : opb; 
244 
res = (uint64_t)opr << (i * 16);

245 
} 
246 
return res;

247 
} 
248  
249 
uint64_t helper_minsw4 (uint64_t op1, uint64_t op2) 
250 
{ 
251 
uint64_t res = 0;

252 
int16_t opa, opb; 
253 
uint16_t opr; 
254 
int i;

255  
256 
for (i = 0; i < 4; ++i) { 
257 
opa = op1 >> (i * 16);

258 
opb = op2 >> (i * 16);

259 
opr = opa < opb ? opa : opb; 
260 
res = (uint64_t)opr << (i * 16);

261 
} 
262 
return res;

263 
} 
264  
265 
uint64_t helper_maxub8 (uint64_t op1, uint64_t op2) 
266 
{ 
267 
uint64_t res = 0;

268 
uint8_t opa, opb, opr; 
269 
int i;

270  
271 
for (i = 0; i < 8; ++i) { 
272 
opa = op1 >> (i * 8);

273 
opb = op2 >> (i * 8);

274 
opr = opa > opb ? opa : opb; 
275 
res = (uint64_t)opr << (i * 8);

276 
} 
277 
return res;

278 
} 
279  
280 
uint64_t helper_maxsb8 (uint64_t op1, uint64_t op2) 
281 
{ 
282 
uint64_t res = 0;

283 
int8_t opa, opb; 
284 
uint8_t opr; 
285 
int i;

286  
287 
for (i = 0; i < 8; ++i) { 
288 
opa = op1 >> (i * 8);

289 
opb = op2 >> (i * 8);

290 
opr = opa > opb ? opa : opb; 
291 
res = (uint64_t)opr << (i * 8);

292 
} 
293 
return res;

294 
} 
295  
296 
uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2) 
297 
{ 
298 
uint64_t res = 0;

299 
uint16_t opa, opb, opr; 
300 
int i;

301  
302 
for (i = 0; i < 4; ++i) { 
303 
opa = op1 >> (i * 16);

304 
opb = op2 >> (i * 16);

305 
opr = opa > opb ? opa : opb; 
306 
res = (uint64_t)opr << (i * 16);

307 
} 
308 
return res;

309 
} 
310  
311 
uint64_t helper_maxsw4 (uint64_t op1, uint64_t op2) 
312 
{ 
313 
uint64_t res = 0;

314 
int16_t opa, opb; 
315 
uint16_t opr; 
316 
int i;

317  
318 
for (i = 0; i < 4; ++i) { 
319 
opa = op1 >> (i * 16);

320 
opb = op2 >> (i * 16);

321 
opr = opa > opb ? opa : opb; 
322 
res = (uint64_t)opr << (i * 16);

323 
} 
324 
return res;

325 
} 
326  
327 
uint64_t helper_perr (uint64_t op1, uint64_t op2) 
328 
{ 
329 
uint64_t res = 0;

330 
uint8_t opa, opb, opr; 
331 
int i;

332  
333 
for (i = 0; i < 8; ++i) { 
334 
opa = op1 >> (i * 8);

335 
opb = op2 >> (i * 8);

336 
if (opa >= opb)

337 
opr = opa  opb; 
338 
else

339 
opr = opb  opa; 
340 
res += opr; 
341 
} 
342 
return res;

343 
} 
344  
345 
uint64_t helper_pklb (uint64_t op1) 
346 
{ 
347 
return (op1 & 0xff)  ((op1 >> 24) & 0xff00); 
348 
} 
349  
350 
uint64_t helper_pkwb (uint64_t op1) 
351 
{ 
352 
return ((op1 & 0xff) 
353 
 ((op1 >> 8) & 0xff00) 
354 
 ((op1 >> 16) & 0xff0000) 
355 
 ((op1 >> 24) & 0xff000000)); 
356 
} 
357  
358 
uint64_t helper_unpkbl (uint64_t op1) 
359 
{ 
360 
return (op1 & 0xff)  ((op1 & 0xff00) << 24); 
361 
} 
362  
363 
uint64_t helper_unpkbw (uint64_t op1) 
364 
{ 
365 
return ((op1 & 0xff) 
366 
 ((op1 & 0xff00) << 8) 
367 
 ((op1 & 0xff0000) << 16) 
368 
 ((op1 & 0xff000000) << 24)); 
369 
} 
370  
371 
/* Floating point helpers */

372  
373 
/* F floating (VAX) */

374 
static inline uint64_t float32_to_f(float32 fa) 
375 
{ 
376 
uint64_t r, exp, mant, sig; 
377 
CPU_FloatU a; 
378  
379 
a.f = fa; 
380 
sig = ((uint64_t)a.l & 0x80000000) << 32; 
381 
exp = (a.l >> 23) & 0xff; 
382 
mant = ((uint64_t)a.l & 0x007fffff) << 29; 
383  
384 
if (exp == 255) { 
385 
/* NaN or infinity */

386 
r = 1; /* VAX dirty zero */ 
387 
} else if (exp == 0) { 
388 
if (mant == 0) { 
389 
/* Zero */

390 
r = 0;

391 
} else {

392 
/* Denormalized */

393 
r = sig  ((exp + 1) << 52)  mant; 
394 
} 
395 
} else {

396 
if (exp >= 253) { 
397 
/* Overflow */

398 
r = 1; /* VAX dirty zero */ 
399 
} else {

400 
r = sig  ((exp + 2) << 52); 
401 
} 
402 
} 
403  
404 
return r;

405 
} 
406  
407 
static inline float32 f_to_float32(uint64_t a) 
408 
{ 
409 
uint32_t exp, mant_sig; 
410 
CPU_FloatU r; 
411  
412 
exp = ((a >> 55) & 0x80)  ((a >> 52) & 0x7f); 
413 
mant_sig = ((a >> 32) & 0x80000000)  ((a >> 29) & 0x007fffff); 
414  
415 
if (unlikely(!exp && mant_sig)) {

416 
/* Reserved operands / Dirty zero */

417 
helper_excp(EXCP_OPCDEC, 0);

418 
} 
419  
420 
if (exp < 3) { 
421 
/* Underflow */

422 
r.l = 0;

423 
} else {

424 
r.l = ((exp  2) << 23)  mant_sig; 
425 
} 
426  
427 
return r.f;

428 
} 
429  
430 
uint32_t helper_f_to_memory (uint64_t a) 
431 
{ 
432 
uint32_t r; 
433 
r = (a & 0x00001fffe0000000ull) >> 13; 
434 
r = (a & 0x07ffe00000000000ull) >> 45; 
435 
r = (a & 0xc000000000000000ull) >> 48; 
436 
return r;

437 
} 
438  
439 
uint64_t helper_memory_to_f (uint32_t a) 
440 
{ 
441 
uint64_t r; 
442 
r = ((uint64_t)(a & 0x0000c000)) << 48; 
443 
r = ((uint64_t)(a & 0x003fffff)) << 45; 
444 
r = ((uint64_t)(a & 0xffff0000)) << 13; 
445 
if (!(a & 0x00004000)) 
446 
r = 0x7ll << 59; 
447 
return r;

448 
} 
449  
450 
uint64_t helper_addf (uint64_t a, uint64_t b) 
451 
{ 
452 
float32 fa, fb, fr; 
453  
454 
fa = f_to_float32(a); 
455 
fb = f_to_float32(b); 
456 
fr = float32_add(fa, fb, &FP_STATUS); 
457 
return float32_to_f(fr);

458 
} 
459  
460 
uint64_t helper_subf (uint64_t a, uint64_t b) 
461 
{ 
462 
float32 fa, fb, fr; 
463  
464 
fa = f_to_float32(a); 
465 
fb = f_to_float32(b); 
466 
fr = float32_sub(fa, fb, &FP_STATUS); 
467 
return float32_to_f(fr);

468 
} 
469  
470 
uint64_t helper_mulf (uint64_t a, uint64_t b) 
471 
{ 
472 
float32 fa, fb, fr; 
473  
474 
fa = f_to_float32(a); 
475 
fb = f_to_float32(b); 
476 
fr = float32_mul(fa, fb, &FP_STATUS); 
477 
return float32_to_f(fr);

478 
} 
479  
480 
uint64_t helper_divf (uint64_t a, uint64_t b) 
481 
{ 
482 
float32 fa, fb, fr; 
483  
484 
fa = f_to_float32(a); 
485 
fb = f_to_float32(b); 
486 
fr = float32_div(fa, fb, &FP_STATUS); 
487 
return float32_to_f(fr);

488 
} 
489  
490 
uint64_t helper_sqrtf (uint64_t t) 
491 
{ 
492 
float32 ft, fr; 
493  
494 
ft = f_to_float32(t); 
495 
fr = float32_sqrt(ft, &FP_STATUS); 
496 
return float32_to_f(fr);

497 
} 
498  
499  
500 
/* G floating (VAX) */

501 
static inline uint64_t float64_to_g(float64 fa) 
502 
{ 
503 
uint64_t r, exp, mant, sig; 
504 
CPU_DoubleU a; 
505  
506 
a.d = fa; 
507 
sig = a.ll & 0x8000000000000000ull;

508 
exp = (a.ll >> 52) & 0x7ff; 
509 
mant = a.ll & 0x000fffffffffffffull;

510  
511 
if (exp == 2047) { 
512 
/* NaN or infinity */

513 
r = 1; /* VAX dirty zero */ 
514 
} else if (exp == 0) { 
515 
if (mant == 0) { 
516 
/* Zero */

517 
r = 0;

518 
} else {

519 
/* Denormalized */

520 
r = sig  ((exp + 1) << 52)  mant; 
521 
} 
522 
} else {

523 
if (exp >= 2045) { 
524 
/* Overflow */

525 
r = 1; /* VAX dirty zero */ 
526 
} else {

527 
r = sig  ((exp + 2) << 52); 
528 
} 
529 
} 
530  
531 
return r;

532 
} 
533  
534 
static inline float64 g_to_float64(uint64_t a) 
535 
{ 
536 
uint64_t exp, mant_sig; 
537 
CPU_DoubleU r; 
538  
539 
exp = (a >> 52) & 0x7ff; 
540 
mant_sig = a & 0x800fffffffffffffull;

541  
542 
if (!exp && mant_sig) {

543 
/* Reserved operands / Dirty zero */

544 
helper_excp(EXCP_OPCDEC, 0);

545 
} 
546  
547 
if (exp < 3) { 
548 
/* Underflow */

549 
r.ll = 0;

550 
} else {

551 
r.ll = ((exp  2) << 52)  mant_sig; 
552 
} 
553  
554 
return r.d;

555 
} 
556  
557 
uint64_t helper_g_to_memory (uint64_t a) 
558 
{ 
559 
uint64_t r; 
560 
r = (a & 0x000000000000ffffull) << 48; 
561 
r = (a & 0x00000000ffff0000ull) << 16; 
562 
r = (a & 0x0000ffff00000000ull) >> 16; 
563 
r = (a & 0xffff000000000000ull) >> 48; 
564 
return r;

565 
} 
566  
567 
uint64_t helper_memory_to_g (uint64_t a) 
568 
{ 
569 
uint64_t r; 
570 
r = (a & 0x000000000000ffffull) << 48; 
571 
r = (a & 0x00000000ffff0000ull) << 16; 
572 
r = (a & 0x0000ffff00000000ull) >> 16; 
573 
r = (a & 0xffff000000000000ull) >> 48; 
574 
return r;

575 
} 
576  
577 
uint64_t helper_addg (uint64_t a, uint64_t b) 
578 
{ 
579 
float64 fa, fb, fr; 
580  
581 
fa = g_to_float64(a); 
582 
fb = g_to_float64(b); 
583 
fr = float64_add(fa, fb, &FP_STATUS); 
584 
return float64_to_g(fr);

585 
} 
586  
587 
uint64_t helper_subg (uint64_t a, uint64_t b) 
588 
{ 
589 
float64 fa, fb, fr; 
590  
591 
fa = g_to_float64(a); 
592 
fb = g_to_float64(b); 
593 
fr = float64_sub(fa, fb, &FP_STATUS); 
594 
return float64_to_g(fr);

595 
} 
596  
597 
uint64_t helper_mulg (uint64_t a, uint64_t b) 
598 
{ 
599 
float64 fa, fb, fr; 
600  
601 
fa = g_to_float64(a); 
602 
fb = g_to_float64(b); 
603 
fr = float64_mul(fa, fb, &FP_STATUS); 
604 
return float64_to_g(fr);

605 
} 
606  
607 
uint64_t helper_divg (uint64_t a, uint64_t b) 
608 
{ 
609 
float64 fa, fb, fr; 
610  
611 
fa = g_to_float64(a); 
612 
fb = g_to_float64(b); 
613 
fr = float64_div(fa, fb, &FP_STATUS); 
614 
return float64_to_g(fr);

615 
} 
616  
617 
uint64_t helper_sqrtg (uint64_t a) 
618 
{ 
619 
float64 fa, fr; 
620  
621 
fa = g_to_float64(a); 
622 
fr = float64_sqrt(fa, &FP_STATUS); 
623 
return float64_to_g(fr);

624 
} 
625  
626  
627 
/* S floating (single) */

628  
629 
/* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg. */

630 
static inline uint64_t float32_to_s_int(uint32_t fi) 
631 
{ 
632 
uint32_t frac = fi & 0x7fffff;

633 
uint32_t sign = fi >> 31;

634 
uint32_t exp_msb = (fi >> 30) & 1; 
635 
uint32_t exp_low = (fi >> 23) & 0x7f; 
636 
uint32_t exp; 
637  
638 
exp = (exp_msb << 10)  exp_low;

639 
if (exp_msb) {

640 
if (exp_low == 0x7f) 
641 
exp = 0x7ff;

642 
} else {

643 
if (exp_low != 0x00) 
644 
exp = 0x380;

645 
} 
646  
647 
return (((uint64_t)sign << 63) 
648 
 ((uint64_t)exp << 52)

649 
 ((uint64_t)frac << 29));

650 
} 
651  
652 
static inline uint64_t float32_to_s(float32 fa) 
653 
{ 
654 
CPU_FloatU a; 
655 
a.f = fa; 
656 
return float32_to_s_int(a.l);

657 
} 
658  
659 
static inline uint32_t s_to_float32_int(uint64_t a) 
660 
{ 
661 
return ((a >> 32) & 0xc0000000)  ((a >> 29) & 0x3fffffff); 
662 
} 
663  
664 
static inline float32 s_to_float32(uint64_t a) 
665 
{ 
666 
CPU_FloatU r; 
667 
r.l = s_to_float32_int(a); 
668 
return r.f;

669 
} 
670  
671 
uint32_t helper_s_to_memory (uint64_t a) 
672 
{ 
673 
return s_to_float32_int(a);

674 
} 
675  
676 
uint64_t helper_memory_to_s (uint32_t a) 
677 
{ 
678 
return float32_to_s_int(a);

679 
} 
680  
681 
uint64_t helper_adds (uint64_t a, uint64_t b) 
682 
{ 
683 
float32 fa, fb, fr; 
684  
685 
fa = s_to_float32(a); 
686 
fb = s_to_float32(b); 
687 
fr = float32_add(fa, fb, &FP_STATUS); 
688 
return float32_to_s(fr);

689 
} 
690  
691 
uint64_t helper_subs (uint64_t a, uint64_t b) 
692 
{ 
693 
float32 fa, fb, fr; 
694  
695 
fa = s_to_float32(a); 
696 
fb = s_to_float32(b); 
697 
fr = float32_sub(fa, fb, &FP_STATUS); 
698 
return float32_to_s(fr);

699 
} 
700  
701 
uint64_t helper_muls (uint64_t a, uint64_t b) 
702 
{ 
703 
float32 fa, fb, fr; 
704  
705 
fa = s_to_float32(a); 
706 
fb = s_to_float32(b); 
707 
fr = float32_mul(fa, fb, &FP_STATUS); 
708 
return float32_to_s(fr);

709 
} 
710  
711 
uint64_t helper_divs (uint64_t a, uint64_t b) 
712 
{ 
713 
float32 fa, fb, fr; 
714  
715 
fa = s_to_float32(a); 
716 
fb = s_to_float32(b); 
717 
fr = float32_div(fa, fb, &FP_STATUS); 
718 
return float32_to_s(fr);

719 
} 
720  
721 
uint64_t helper_sqrts (uint64_t a) 
722 
{ 
723 
float32 fa, fr; 
724  
725 
fa = s_to_float32(a); 
726 
fr = float32_sqrt(fa, &FP_STATUS); 
727 
return float32_to_s(fr);

728 
} 
729  
730  
731 
/* T floating (double) */

732 
static inline float64 t_to_float64(uint64_t a) 
733 
{ 
734 
/* Memory format is the same as float64 */

735 
CPU_DoubleU r; 
736 
r.ll = a; 
737 
return r.d;

738 
} 
739  
740 
static inline uint64_t float64_to_t(float64 fa) 
741 
{ 
742 
/* Memory format is the same as float64 */

743 
CPU_DoubleU r; 
744 
r.d = fa; 
745 
return r.ll;

746 
} 
747  
748 
uint64_t helper_addt (uint64_t a, uint64_t b) 
749 
{ 
750 
float64 fa, fb, fr; 
751  
752 
fa = t_to_float64(a); 
753 
fb = t_to_float64(b); 
754 
fr = float64_add(fa, fb, &FP_STATUS); 
755 
return float64_to_t(fr);

756 
} 
757  
758 
uint64_t helper_subt (uint64_t a, uint64_t b) 
759 
{ 
760 
float64 fa, fb, fr; 
761  
762 
fa = t_to_float64(a); 
763 
fb = t_to_float64(b); 
764 
fr = float64_sub(fa, fb, &FP_STATUS); 
765 
return float64_to_t(fr);

766 
} 
767  
768 
uint64_t helper_mult (uint64_t a, uint64_t b) 
769 
{ 
770 
float64 fa, fb, fr; 
771  
772 
fa = t_to_float64(a); 
773 
fb = t_to_float64(b); 
774 
fr = float64_mul(fa, fb, &FP_STATUS); 
775 
return float64_to_t(fr);

776 
} 
777  
778 
uint64_t helper_divt (uint64_t a, uint64_t b) 
779 
{ 
780 
float64 fa, fb, fr; 
781  
782 
fa = t_to_float64(a); 
783 
fb = t_to_float64(b); 
784 
fr = float64_div(fa, fb, &FP_STATUS); 
785 
return float64_to_t(fr);

786 
} 
787  
788 
uint64_t helper_sqrtt (uint64_t a) 
789 
{ 
790 
float64 fa, fr; 
791  
792 
fa = t_to_float64(a); 
793 
fr = float64_sqrt(fa, &FP_STATUS); 
794 
return float64_to_t(fr);

795 
} 
796  
797  
798 
/* Sign copy */

799 
uint64_t helper_cpys(uint64_t a, uint64_t b) 
800 
{ 
801 
return (a & 0x8000000000000000ULL)  (b & ~0x8000000000000000ULL); 
802 
} 
803  
804 
uint64_t helper_cpysn(uint64_t a, uint64_t b) 
805 
{ 
806 
return ((~a) & 0x8000000000000000ULL)  (b & ~0x8000000000000000ULL); 
807 
} 
808  
809 
uint64_t helper_cpyse(uint64_t a, uint64_t b) 
810 
{ 
811 
return (a & 0xFFF0000000000000ULL)  (b & ~0xFFF0000000000000ULL); 
812 
} 
813  
814  
815 
/* Comparisons */

816 
uint64_t helper_cmptun (uint64_t a, uint64_t b) 
817 
{ 
818 
float64 fa, fb; 
819  
820 
fa = t_to_float64(a); 
821 
fb = t_to_float64(b); 
822  
823 
if (float64_is_nan(fa)  float64_is_nan(fb))

824 
return 0x4000000000000000ULL; 
825 
else

826 
return 0; 
827 
} 
828  
829 
uint64_t helper_cmpteq(uint64_t a, uint64_t b) 
830 
{ 
831 
float64 fa, fb; 
832  
833 
fa = t_to_float64(a); 
834 
fb = t_to_float64(b); 
835  
836 
if (float64_eq(fa, fb, &FP_STATUS))

837 
return 0x4000000000000000ULL; 
838 
else

839 
return 0; 
840 
} 
841  
842 
uint64_t helper_cmptle(uint64_t a, uint64_t b) 
843 
{ 
844 
float64 fa, fb; 
845  
846 
fa = t_to_float64(a); 
847 
fb = t_to_float64(b); 
848  
849 
if (float64_le(fa, fb, &FP_STATUS))

850 
return 0x4000000000000000ULL; 
851 
else

852 
return 0; 
853 
} 
854  
855 
uint64_t helper_cmptlt(uint64_t a, uint64_t b) 
856 
{ 
857 
float64 fa, fb; 
858  
859 
fa = t_to_float64(a); 
860 
fb = t_to_float64(b); 
861  
862 
if (float64_lt(fa, fb, &FP_STATUS))

863 
return 0x4000000000000000ULL; 
864 
else

865 
return 0; 
866 
} 
867  
868 
uint64_t helper_cmpgeq(uint64_t a, uint64_t b) 
869 
{ 
870 
float64 fa, fb; 
871  
872 
fa = g_to_float64(a); 
873 
fb = g_to_float64(b); 
874  
875 
if (float64_eq(fa, fb, &FP_STATUS))

876 
return 0x4000000000000000ULL; 
877 
else

878 
return 0; 
879 
} 
880  
881 
uint64_t helper_cmpgle(uint64_t a, uint64_t b) 
882 
{ 
883 
float64 fa, fb; 
884  
885 
fa = g_to_float64(a); 
886 
fb = g_to_float64(b); 
887  
888 
if (float64_le(fa, fb, &FP_STATUS))

889 
return 0x4000000000000000ULL; 
890 
else

891 
return 0; 
892 
} 
893  
894 
uint64_t helper_cmpglt(uint64_t a, uint64_t b) 
895 
{ 
896 
float64 fa, fb; 
897  
898 
fa = g_to_float64(a); 
899 
fb = g_to_float64(b); 
900  
901 
if (float64_lt(fa, fb, &FP_STATUS))

902 
return 0x4000000000000000ULL; 
903 
else

904 
return 0; 
905 
} 
906  
907 
/* Floating point format conversion */

908 
uint64_t helper_cvtts (uint64_t a) 
909 
{ 
910 
float64 fa; 
911 
float32 fr; 
912  
913 
fa = t_to_float64(a); 
914 
fr = float64_to_float32(fa, &FP_STATUS); 
915 
return float32_to_s(fr);

916 
} 
917  
918 
uint64_t helper_cvtst (uint64_t a) 
919 
{ 
920 
float32 fa; 
921 
float64 fr; 
922  
923 
fa = s_to_float32(a); 
924 
fr = float32_to_float64(fa, &FP_STATUS); 
925 
return float64_to_t(fr);

926 
} 
927  
928 
uint64_t helper_cvtqs (uint64_t a) 
929 
{ 
930 
float32 fr = int64_to_float32(a, &FP_STATUS); 
931 
return float32_to_s(fr);

932 
} 
933  
934 
uint64_t helper_cvttq (uint64_t a) 
935 
{ 
936 
float64 fa = t_to_float64(a); 
937 
return float64_to_int64_round_to_zero(fa, &FP_STATUS);

938 
} 
939  
940 
uint64_t helper_cvtqt (uint64_t a) 
941 
{ 
942 
float64 fr = int64_to_float64(a, &FP_STATUS); 
943 
return float64_to_t(fr);

944 
} 
945  
946 
uint64_t helper_cvtqf (uint64_t a) 
947 
{ 
948 
float32 fr = int64_to_float32(a, &FP_STATUS); 
949 
return float32_to_f(fr);

950 
} 
951  
952 
uint64_t helper_cvtgf (uint64_t a) 
953 
{ 
954 
float64 fa; 
955 
float32 fr; 
956  
957 
fa = g_to_float64(a); 
958 
fr = float64_to_float32(fa, &FP_STATUS); 
959 
return float32_to_f(fr);

960 
} 
961  
962 
uint64_t helper_cvtgq (uint64_t a) 
963 
{ 
964 
float64 fa = g_to_float64(a); 
965 
return float64_to_int64_round_to_zero(fa, &FP_STATUS);

966 
} 
967  
968 
uint64_t helper_cvtqg (uint64_t a) 
969 
{ 
970 
float64 fr; 
971 
fr = int64_to_float64(a, &FP_STATUS); 
972 
return float64_to_g(fr);

973 
} 
974  
975 
uint64_t helper_cvtlq (uint64_t a) 
976 
{ 
977 
int32_t lo = a >> 29;

978 
int32_t hi = a >> 32;

979 
return (lo & 0x3FFFFFFF)  (hi & 0xc0000000); 
980 
} 
981  
982 
static inline uint64_t __helper_cvtql(uint64_t a, int s, int v) 
983 
{ 
984 
uint64_t r; 
985  
986 
r = ((uint64_t)(a & 0xC0000000)) << 32; 
987 
r = ((uint64_t)(a & 0x7FFFFFFF)) << 29; 
988  
989 
if (v && (int64_t)((int32_t)r) != (int64_t)r) {

990 
helper_excp(EXCP_ARITH, EXC_M_IOV); 
991 
} 
992 
if (s) {

993 
/* TODO */

994 
} 
995 
return r;

996 
} 
997  
998 
uint64_t helper_cvtql (uint64_t a) 
999 
{ 
1000 
return __helper_cvtql(a, 0, 0); 
1001 
} 
1002  
1003 
uint64_t helper_cvtqlv (uint64_t a) 
1004 
{ 
1005 
return __helper_cvtql(a, 0, 1); 
1006 
} 
1007  
1008 
uint64_t helper_cvtqlsv (uint64_t a) 
1009 
{ 
1010 
return __helper_cvtql(a, 1, 1); 
1011 
} 
1012  
1013 
/* PALcode support special instructions */

1014 
#if !defined (CONFIG_USER_ONLY)

1015 
void helper_hw_rei (void) 
1016 
{ 
1017 
env>pc = env>ipr[IPR_EXC_ADDR] & ~3;

1018 
env>ipr[IPR_EXC_ADDR] = env>ipr[IPR_EXC_ADDR] & 1;

1019 
/* XXX: reenable interrupts and memory mapping */

1020 
} 
1021  
1022 
void helper_hw_ret (uint64_t a)

1023 
{ 
1024 
env>pc = a & ~3;

1025 
env>ipr[IPR_EXC_ADDR] = a & 1;

1026 
/* XXX: reenable interrupts and memory mapping */

1027 
} 
1028  
1029 
uint64_t helper_mfpr (int iprn, uint64_t val)

1030 
{ 
1031 
uint64_t tmp; 
1032  
1033 
if (cpu_alpha_mfpr(env, iprn, &tmp) == 0) 
1034 
val = tmp; 
1035  
1036 
return val;

1037 
} 
1038  
1039 
void helper_mtpr (int iprn, uint64_t val) 
1040 
{ 
1041 
cpu_alpha_mtpr(env, iprn, val, NULL);

1042 
} 
1043  
1044 
void helper_set_alt_mode (void) 
1045 
{ 
1046 
env>saved_mode = env>ps & 0xC;

1047 
env>ps = (env>ps & ~0xC)  (env>ipr[IPR_ALT_MODE] & 0xC); 
1048 
} 
1049  
1050 
void helper_restore_mode (void) 
1051 
{ 
1052 
env>ps = (env>ps & ~0xC)  env>saved_mode;

1053 
} 
1054  
1055 
#endif

1056  
1057 
/*****************************************************************************/

1058 
/* Softmmu support */

1059 
#if !defined (CONFIG_USER_ONLY)

1060  
1061 
/* XXX: the two following helpers are pure hacks.

1062 
* Hopefully, we emulate the PALcode, then we should never see

1063 
* HW_LD / HW_ST instructions.

1064 
*/

1065 
uint64_t helper_ld_virt_to_phys (uint64_t virtaddr) 
1066 
{ 
1067 
uint64_t tlb_addr, physaddr; 
1068 
int index, mmu_idx;

1069 
void *retaddr;

1070  
1071 
mmu_idx = cpu_mmu_index(env); 
1072 
index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE  1);

1073 
redo:

1074 
tlb_addr = env>tlb_table[mmu_idx][index].addr_read; 
1075 
if ((virtaddr & TARGET_PAGE_MASK) ==

1076 
(tlb_addr & (TARGET_PAGE_MASK  TLB_INVALID_MASK))) { 
1077 
physaddr = virtaddr + env>tlb_table[mmu_idx][index].addend; 
1078 
} else {

1079 
/* the page is not in the TLB : fill it */

1080 
retaddr = GETPC(); 
1081 
tlb_fill(virtaddr, 0, mmu_idx, retaddr);

1082 
goto redo;

1083 
} 
1084 
return physaddr;

1085 
} 
1086  
1087 
uint64_t helper_st_virt_to_phys (uint64_t virtaddr) 
1088 
{ 
1089 
uint64_t tlb_addr, physaddr; 
1090 
int index, mmu_idx;

1091 
void *retaddr;

1092  
1093 
mmu_idx = cpu_mmu_index(env); 
1094 
index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE  1);

1095 
redo:

1096 
tlb_addr = env>tlb_table[mmu_idx][index].addr_write; 
1097 
if ((virtaddr & TARGET_PAGE_MASK) ==

1098 
(tlb_addr & (TARGET_PAGE_MASK  TLB_INVALID_MASK))) { 
1099 
physaddr = virtaddr + env>tlb_table[mmu_idx][index].addend; 
1100 
} else {

1101 
/* the page is not in the TLB : fill it */

1102 
retaddr = GETPC(); 
1103 
tlb_fill(virtaddr, 1, mmu_idx, retaddr);

1104 
goto redo;

1105 
} 
1106 
return physaddr;

1107 
} 
1108  
1109 
void helper_ldl_raw(uint64_t t0, uint64_t t1)

1110 
{ 
1111 
ldl_raw(t1, t0); 
1112 
} 
1113  
1114 
void helper_ldq_raw(uint64_t t0, uint64_t t1)

1115 
{ 
1116 
ldq_raw(t1, t0); 
1117 
} 
1118  
1119 
void helper_ldl_l_raw(uint64_t t0, uint64_t t1)

1120 
{ 
1121 
env>lock = t1; 
1122 
ldl_raw(t1, t0); 
1123 
} 
1124  
1125 
void helper_ldq_l_raw(uint64_t t0, uint64_t t1)

1126 
{ 
1127 
env>lock = t1; 
1128 
ldl_raw(t1, t0); 
1129 
} 
1130  
1131 
void helper_ldl_kernel(uint64_t t0, uint64_t t1)

1132 
{ 
1133 
ldl_kernel(t1, t0); 
1134 
} 
1135  
1136 
void helper_ldq_kernel(uint64_t t0, uint64_t t1)

1137 
{ 
1138 
ldq_kernel(t1, t0); 
1139 
} 
1140  
1141 
void helper_ldl_data(uint64_t t0, uint64_t t1)

1142 
{ 
1143 
ldl_data(t1, t0); 
1144 
} 
1145  
1146 
void helper_ldq_data(uint64_t t0, uint64_t t1)

1147 
{ 
1148 
ldq_data(t1, t0); 
1149 
} 
1150  
1151 
void helper_stl_raw(uint64_t t0, uint64_t t1)

1152 
{ 
1153 
stl_raw(t1, t0); 
1154 
} 
1155  
1156 
void helper_stq_raw(uint64_t t0, uint64_t t1)

1157 
{ 
1158 
stq_raw(t1, t0); 
1159 
} 
1160  
1161 
uint64_t helper_stl_c_raw(uint64_t t0, uint64_t t1) 
1162 
{ 
1163 
uint64_t ret; 
1164  
1165 
if (t1 == env>lock) {

1166 
stl_raw(t1, t0); 
1167 
ret = 0;

1168 
} else

1169 
ret = 1;

1170  
1171 
env>lock = 1;

1172  
1173 
return ret;

1174 
} 
1175  
1176 
uint64_t helper_stq_c_raw(uint64_t t0, uint64_t t1) 
1177 
{ 
1178 
uint64_t ret; 
1179  
1180 
if (t1 == env>lock) {

1181 
stq_raw(t1, t0); 
1182 
ret = 0;

1183 
} else

1184 
ret = 1;

1185  
1186 
env>lock = 1;

1187  
1188 
return ret;

1189 
} 
1190  
1191 
#define MMUSUFFIX _mmu

1192  
1193 
#define SHIFT 0 
1194 
#include "softmmu_template.h" 
1195  
1196 
#define SHIFT 1 
1197 
#include "softmmu_template.h" 
1198  
1199 
#define SHIFT 2 
1200 
#include "softmmu_template.h" 
1201  
1202 
#define SHIFT 3 
1203 
#include "softmmu_template.h" 
1204  
1205 
/* try to fill the TLB and return an exception if error. If retaddr is

1206 
NULL, it means that the function was called in C code (i.e. not

1207 
from generated code or from helper.c) */

1208 
/* XXX: fix it to restore all registers */

1209 
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) 
1210 
{ 
1211 
TranslationBlock *tb; 
1212 
CPUState *saved_env; 
1213 
unsigned long pc; 
1214 
int ret;

1215  
1216 
/* XXX: hack to restore env in all cases, even if not called from

1217 
generated code */

1218 
saved_env = env; 
1219 
env = cpu_single_env; 
1220 
ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);

1221 
if (!likely(ret == 0)) { 
1222 
if (likely(retaddr)) {

1223 
/* now we have a real cpu fault */

1224 
pc = (unsigned long)retaddr; 
1225 
tb = tb_find_pc(pc); 
1226 
if (likely(tb)) {

1227 
/* the PC is inside the translated code. It means that we have

1228 
a virtual CPU fault */

1229 
cpu_restore_state(tb, env, pc, NULL);

1230 
} 
1231 
} 
1232 
/* Exception index and error code are already set */

1233 
cpu_loop_exit(); 
1234 
} 
1235 
env = saved_env; 
1236 
} 
1237  
1238 
#endif
