]> git.proxmox.com Git - qemu.git/blob - target-alpha/op_helper.c
target-alpha: Add flags markups to helpers.h.
[qemu.git] / target-alpha / op_helper.c
1 /*
2 * Alpha emulation cpu micro-operations 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 "host-utils.h"
22 #include "softfloat.h"
23 #include "helper.h"
24
25 /*****************************************************************************/
26 /* Exceptions processing helpers */
27 void QEMU_NORETURN 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 void helper_setroundmode (uint32_t val)
374 {
375 set_float_rounding_mode(val, &FP_STATUS);
376 }
377
378 void helper_setflushzero (uint32_t val)
379 {
380 set_flush_to_zero(val, &FP_STATUS);
381 }
382
383 void helper_fp_exc_clear (void)
384 {
385 set_float_exception_flags(0, &FP_STATUS);
386 }
387
388 uint32_t helper_fp_exc_get (void)
389 {
390 return get_float_exception_flags(&FP_STATUS);
391 }
392
393 /* Raise exceptions for ieee fp insns without software completion.
394 In that case there are no exceptions that don't trap; the mask
395 doesn't apply. */
396 void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
397 {
398 if (exc) {
399 uint32_t hw_exc = 0;
400
401 env->ipr[IPR_EXC_MASK] |= 1ull << regno;
402
403 if (exc & float_flag_invalid) {
404 hw_exc |= EXC_M_INV;
405 }
406 if (exc & float_flag_divbyzero) {
407 hw_exc |= EXC_M_DZE;
408 }
409 if (exc & float_flag_overflow) {
410 hw_exc |= EXC_M_FOV;
411 }
412 if (exc & float_flag_underflow) {
413 hw_exc |= EXC_M_UNF;
414 }
415 if (exc & float_flag_inexact) {
416 hw_exc |= EXC_M_INE;
417 }
418 helper_excp(EXCP_ARITH, hw_exc);
419 }
420 }
421
422 /* Raise exceptions for ieee fp insns with software completion. */
423 void helper_fp_exc_raise_s(uint32_t exc, uint32_t regno)
424 {
425 if (exc) {
426 env->fpcr_exc_status |= exc;
427
428 exc &= ~env->fpcr_exc_mask;
429 if (exc) {
430 helper_fp_exc_raise(exc, regno);
431 }
432 }
433 }
434
435 /* Input remapping without software completion. Handle denormal-map-to-zero
436 and trap for all other non-finite numbers. */
437 uint64_t helper_ieee_input(uint64_t val)
438 {
439 uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
440 uint64_t frac = val & 0xfffffffffffffull;
441
442 if (exp == 0) {
443 if (frac != 0) {
444 /* If DNZ is set flush denormals to zero on input. */
445 if (env->fpcr_dnz) {
446 val &= 1ull << 63;
447 } else {
448 helper_excp(EXCP_ARITH, EXC_M_UNF);
449 }
450 }
451 } else if (exp == 0x7ff) {
452 /* Infinity or NaN. */
453 /* ??? I'm not sure these exception bit flags are correct. I do
454 know that the Linux kernel, at least, doesn't rely on them and
455 just emulates the insn to figure out what exception to use. */
456 helper_excp(EXCP_ARITH, frac ? EXC_M_INV : EXC_M_FOV);
457 }
458 return val;
459 }
460
461 /* Similar, but does not trap for infinities. Used for comparisons. */
462 uint64_t helper_ieee_input_cmp(uint64_t val)
463 {
464 uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
465 uint64_t frac = val & 0xfffffffffffffull;
466
467 if (exp == 0) {
468 if (frac != 0) {
469 /* If DNZ is set flush denormals to zero on input. */
470 if (env->fpcr_dnz) {
471 val &= 1ull << 63;
472 } else {
473 helper_excp(EXCP_ARITH, EXC_M_UNF);
474 }
475 }
476 } else if (exp == 0x7ff && frac) {
477 /* NaN. */
478 helper_excp(EXCP_ARITH, EXC_M_INV);
479 }
480 return val;
481 }
482
483 /* Input remapping with software completion enabled. All we have to do
484 is handle denormal-map-to-zero; all other inputs get exceptions as
485 needed from the actual operation. */
486 uint64_t helper_ieee_input_s(uint64_t val)
487 {
488 if (env->fpcr_dnz) {
489 uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
490 if (exp == 0) {
491 val &= 1ull << 63;
492 }
493 }
494 return val;
495 }
496
497 /* F floating (VAX) */
498 static inline uint64_t float32_to_f(float32 fa)
499 {
500 uint64_t r, exp, mant, sig;
501 CPU_FloatU a;
502
503 a.f = fa;
504 sig = ((uint64_t)a.l & 0x80000000) << 32;
505 exp = (a.l >> 23) & 0xff;
506 mant = ((uint64_t)a.l & 0x007fffff) << 29;
507
508 if (exp == 255) {
509 /* NaN or infinity */
510 r = 1; /* VAX dirty zero */
511 } else if (exp == 0) {
512 if (mant == 0) {
513 /* Zero */
514 r = 0;
515 } else {
516 /* Denormalized */
517 r = sig | ((exp + 1) << 52) | mant;
518 }
519 } else {
520 if (exp >= 253) {
521 /* Overflow */
522 r = 1; /* VAX dirty zero */
523 } else {
524 r = sig | ((exp + 2) << 52);
525 }
526 }
527
528 return r;
529 }
530
531 static inline float32 f_to_float32(uint64_t a)
532 {
533 uint32_t exp, mant_sig;
534 CPU_FloatU r;
535
536 exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
537 mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
538
539 if (unlikely(!exp && mant_sig)) {
540 /* Reserved operands / Dirty zero */
541 helper_excp(EXCP_OPCDEC, 0);
542 }
543
544 if (exp < 3) {
545 /* Underflow */
546 r.l = 0;
547 } else {
548 r.l = ((exp - 2) << 23) | mant_sig;
549 }
550
551 return r.f;
552 }
553
554 uint32_t helper_f_to_memory (uint64_t a)
555 {
556 uint32_t r;
557 r = (a & 0x00001fffe0000000ull) >> 13;
558 r |= (a & 0x07ffe00000000000ull) >> 45;
559 r |= (a & 0xc000000000000000ull) >> 48;
560 return r;
561 }
562
563 uint64_t helper_memory_to_f (uint32_t a)
564 {
565 uint64_t r;
566 r = ((uint64_t)(a & 0x0000c000)) << 48;
567 r |= ((uint64_t)(a & 0x003fffff)) << 45;
568 r |= ((uint64_t)(a & 0xffff0000)) << 13;
569 if (!(a & 0x00004000))
570 r |= 0x7ll << 59;
571 return r;
572 }
573
574 /* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong. We should
575 either implement VAX arithmetic properly or just signal invalid opcode. */
576
577 uint64_t helper_addf (uint64_t a, uint64_t b)
578 {
579 float32 fa, fb, fr;
580
581 fa = f_to_float32(a);
582 fb = f_to_float32(b);
583 fr = float32_add(fa, fb, &FP_STATUS);
584 return float32_to_f(fr);
585 }
586
587 uint64_t helper_subf (uint64_t a, uint64_t b)
588 {
589 float32 fa, fb, fr;
590
591 fa = f_to_float32(a);
592 fb = f_to_float32(b);
593 fr = float32_sub(fa, fb, &FP_STATUS);
594 return float32_to_f(fr);
595 }
596
597 uint64_t helper_mulf (uint64_t a, uint64_t b)
598 {
599 float32 fa, fb, fr;
600
601 fa = f_to_float32(a);
602 fb = f_to_float32(b);
603 fr = float32_mul(fa, fb, &FP_STATUS);
604 return float32_to_f(fr);
605 }
606
607 uint64_t helper_divf (uint64_t a, uint64_t b)
608 {
609 float32 fa, fb, fr;
610
611 fa = f_to_float32(a);
612 fb = f_to_float32(b);
613 fr = float32_div(fa, fb, &FP_STATUS);
614 return float32_to_f(fr);
615 }
616
617 uint64_t helper_sqrtf (uint64_t t)
618 {
619 float32 ft, fr;
620
621 ft = f_to_float32(t);
622 fr = float32_sqrt(ft, &FP_STATUS);
623 return float32_to_f(fr);
624 }
625
626
627 /* G floating (VAX) */
628 static inline uint64_t float64_to_g(float64 fa)
629 {
630 uint64_t r, exp, mant, sig;
631 CPU_DoubleU a;
632
633 a.d = fa;
634 sig = a.ll & 0x8000000000000000ull;
635 exp = (a.ll >> 52) & 0x7ff;
636 mant = a.ll & 0x000fffffffffffffull;
637
638 if (exp == 2047) {
639 /* NaN or infinity */
640 r = 1; /* VAX dirty zero */
641 } else if (exp == 0) {
642 if (mant == 0) {
643 /* Zero */
644 r = 0;
645 } else {
646 /* Denormalized */
647 r = sig | ((exp + 1) << 52) | mant;
648 }
649 } else {
650 if (exp >= 2045) {
651 /* Overflow */
652 r = 1; /* VAX dirty zero */
653 } else {
654 r = sig | ((exp + 2) << 52);
655 }
656 }
657
658 return r;
659 }
660
661 static inline float64 g_to_float64(uint64_t a)
662 {
663 uint64_t exp, mant_sig;
664 CPU_DoubleU r;
665
666 exp = (a >> 52) & 0x7ff;
667 mant_sig = a & 0x800fffffffffffffull;
668
669 if (!exp && mant_sig) {
670 /* Reserved operands / Dirty zero */
671 helper_excp(EXCP_OPCDEC, 0);
672 }
673
674 if (exp < 3) {
675 /* Underflow */
676 r.ll = 0;
677 } else {
678 r.ll = ((exp - 2) << 52) | mant_sig;
679 }
680
681 return r.d;
682 }
683
684 uint64_t helper_g_to_memory (uint64_t a)
685 {
686 uint64_t r;
687 r = (a & 0x000000000000ffffull) << 48;
688 r |= (a & 0x00000000ffff0000ull) << 16;
689 r |= (a & 0x0000ffff00000000ull) >> 16;
690 r |= (a & 0xffff000000000000ull) >> 48;
691 return r;
692 }
693
694 uint64_t helper_memory_to_g (uint64_t a)
695 {
696 uint64_t r;
697 r = (a & 0x000000000000ffffull) << 48;
698 r |= (a & 0x00000000ffff0000ull) << 16;
699 r |= (a & 0x0000ffff00000000ull) >> 16;
700 r |= (a & 0xffff000000000000ull) >> 48;
701 return r;
702 }
703
704 uint64_t helper_addg (uint64_t a, uint64_t b)
705 {
706 float64 fa, fb, fr;
707
708 fa = g_to_float64(a);
709 fb = g_to_float64(b);
710 fr = float64_add(fa, fb, &FP_STATUS);
711 return float64_to_g(fr);
712 }
713
714 uint64_t helper_subg (uint64_t a, uint64_t b)
715 {
716 float64 fa, fb, fr;
717
718 fa = g_to_float64(a);
719 fb = g_to_float64(b);
720 fr = float64_sub(fa, fb, &FP_STATUS);
721 return float64_to_g(fr);
722 }
723
724 uint64_t helper_mulg (uint64_t a, uint64_t b)
725 {
726 float64 fa, fb, fr;
727
728 fa = g_to_float64(a);
729 fb = g_to_float64(b);
730 fr = float64_mul(fa, fb, &FP_STATUS);
731 return float64_to_g(fr);
732 }
733
734 uint64_t helper_divg (uint64_t a, uint64_t b)
735 {
736 float64 fa, fb, fr;
737
738 fa = g_to_float64(a);
739 fb = g_to_float64(b);
740 fr = float64_div(fa, fb, &FP_STATUS);
741 return float64_to_g(fr);
742 }
743
744 uint64_t helper_sqrtg (uint64_t a)
745 {
746 float64 fa, fr;
747
748 fa = g_to_float64(a);
749 fr = float64_sqrt(fa, &FP_STATUS);
750 return float64_to_g(fr);
751 }
752
753
754 /* S floating (single) */
755
756 /* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg. */
757 static inline uint64_t float32_to_s_int(uint32_t fi)
758 {
759 uint32_t frac = fi & 0x7fffff;
760 uint32_t sign = fi >> 31;
761 uint32_t exp_msb = (fi >> 30) & 1;
762 uint32_t exp_low = (fi >> 23) & 0x7f;
763 uint32_t exp;
764
765 exp = (exp_msb << 10) | exp_low;
766 if (exp_msb) {
767 if (exp_low == 0x7f)
768 exp = 0x7ff;
769 } else {
770 if (exp_low != 0x00)
771 exp |= 0x380;
772 }
773
774 return (((uint64_t)sign << 63)
775 | ((uint64_t)exp << 52)
776 | ((uint64_t)frac << 29));
777 }
778
779 static inline uint64_t float32_to_s(float32 fa)
780 {
781 CPU_FloatU a;
782 a.f = fa;
783 return float32_to_s_int(a.l);
784 }
785
786 static inline uint32_t s_to_float32_int(uint64_t a)
787 {
788 return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
789 }
790
791 static inline float32 s_to_float32(uint64_t a)
792 {
793 CPU_FloatU r;
794 r.l = s_to_float32_int(a);
795 return r.f;
796 }
797
798 uint32_t helper_s_to_memory (uint64_t a)
799 {
800 return s_to_float32_int(a);
801 }
802
803 uint64_t helper_memory_to_s (uint32_t a)
804 {
805 return float32_to_s_int(a);
806 }
807
808 uint64_t helper_adds (uint64_t a, uint64_t b)
809 {
810 float32 fa, fb, fr;
811
812 fa = s_to_float32(a);
813 fb = s_to_float32(b);
814 fr = float32_add(fa, fb, &FP_STATUS);
815 return float32_to_s(fr);
816 }
817
818 uint64_t helper_subs (uint64_t a, uint64_t b)
819 {
820 float32 fa, fb, fr;
821
822 fa = s_to_float32(a);
823 fb = s_to_float32(b);
824 fr = float32_sub(fa, fb, &FP_STATUS);
825 return float32_to_s(fr);
826 }
827
828 uint64_t helper_muls (uint64_t a, uint64_t b)
829 {
830 float32 fa, fb, fr;
831
832 fa = s_to_float32(a);
833 fb = s_to_float32(b);
834 fr = float32_mul(fa, fb, &FP_STATUS);
835 return float32_to_s(fr);
836 }
837
838 uint64_t helper_divs (uint64_t a, uint64_t b)
839 {
840 float32 fa, fb, fr;
841
842 fa = s_to_float32(a);
843 fb = s_to_float32(b);
844 fr = float32_div(fa, fb, &FP_STATUS);
845 return float32_to_s(fr);
846 }
847
848 uint64_t helper_sqrts (uint64_t a)
849 {
850 float32 fa, fr;
851
852 fa = s_to_float32(a);
853 fr = float32_sqrt(fa, &FP_STATUS);
854 return float32_to_s(fr);
855 }
856
857
858 /* T floating (double) */
859 static inline float64 t_to_float64(uint64_t a)
860 {
861 /* Memory format is the same as float64 */
862 CPU_DoubleU r;
863 r.ll = a;
864 return r.d;
865 }
866
867 static inline uint64_t float64_to_t(float64 fa)
868 {
869 /* Memory format is the same as float64 */
870 CPU_DoubleU r;
871 r.d = fa;
872 return r.ll;
873 }
874
875 uint64_t helper_addt (uint64_t a, uint64_t b)
876 {
877 float64 fa, fb, fr;
878
879 fa = t_to_float64(a);
880 fb = t_to_float64(b);
881 fr = float64_add(fa, fb, &FP_STATUS);
882 return float64_to_t(fr);
883 }
884
885 uint64_t helper_subt (uint64_t a, uint64_t b)
886 {
887 float64 fa, fb, fr;
888
889 fa = t_to_float64(a);
890 fb = t_to_float64(b);
891 fr = float64_sub(fa, fb, &FP_STATUS);
892 return float64_to_t(fr);
893 }
894
895 uint64_t helper_mult (uint64_t a, uint64_t b)
896 {
897 float64 fa, fb, fr;
898
899 fa = t_to_float64(a);
900 fb = t_to_float64(b);
901 fr = float64_mul(fa, fb, &FP_STATUS);
902 return float64_to_t(fr);
903 }
904
905 uint64_t helper_divt (uint64_t a, uint64_t b)
906 {
907 float64 fa, fb, fr;
908
909 fa = t_to_float64(a);
910 fb = t_to_float64(b);
911 fr = float64_div(fa, fb, &FP_STATUS);
912 return float64_to_t(fr);
913 }
914
915 uint64_t helper_sqrtt (uint64_t a)
916 {
917 float64 fa, fr;
918
919 fa = t_to_float64(a);
920 fr = float64_sqrt(fa, &FP_STATUS);
921 return float64_to_t(fr);
922 }
923
924
925 /* Sign copy */
926 uint64_t helper_cpys(uint64_t a, uint64_t b)
927 {
928 return (a & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
929 }
930
931 uint64_t helper_cpysn(uint64_t a, uint64_t b)
932 {
933 return ((~a) & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
934 }
935
936 uint64_t helper_cpyse(uint64_t a, uint64_t b)
937 {
938 return (a & 0xFFF0000000000000ULL) | (b & ~0xFFF0000000000000ULL);
939 }
940
941
942 /* Comparisons */
943 uint64_t helper_cmptun (uint64_t a, uint64_t b)
944 {
945 float64 fa, fb;
946
947 fa = t_to_float64(a);
948 fb = t_to_float64(b);
949
950 if (float64_is_nan(fa) || float64_is_nan(fb))
951 return 0x4000000000000000ULL;
952 else
953 return 0;
954 }
955
956 uint64_t helper_cmpteq(uint64_t a, uint64_t b)
957 {
958 float64 fa, fb;
959
960 fa = t_to_float64(a);
961 fb = t_to_float64(b);
962
963 if (float64_eq(fa, fb, &FP_STATUS))
964 return 0x4000000000000000ULL;
965 else
966 return 0;
967 }
968
969 uint64_t helper_cmptle(uint64_t a, uint64_t b)
970 {
971 float64 fa, fb;
972
973 fa = t_to_float64(a);
974 fb = t_to_float64(b);
975
976 if (float64_le(fa, fb, &FP_STATUS))
977 return 0x4000000000000000ULL;
978 else
979 return 0;
980 }
981
982 uint64_t helper_cmptlt(uint64_t a, uint64_t b)
983 {
984 float64 fa, fb;
985
986 fa = t_to_float64(a);
987 fb = t_to_float64(b);
988
989 if (float64_lt(fa, fb, &FP_STATUS))
990 return 0x4000000000000000ULL;
991 else
992 return 0;
993 }
994
995 uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
996 {
997 float64 fa, fb;
998
999 fa = g_to_float64(a);
1000 fb = g_to_float64(b);
1001
1002 if (float64_eq(fa, fb, &FP_STATUS))
1003 return 0x4000000000000000ULL;
1004 else
1005 return 0;
1006 }
1007
1008 uint64_t helper_cmpgle(uint64_t a, uint64_t b)
1009 {
1010 float64 fa, fb;
1011
1012 fa = g_to_float64(a);
1013 fb = g_to_float64(b);
1014
1015 if (float64_le(fa, fb, &FP_STATUS))
1016 return 0x4000000000000000ULL;
1017 else
1018 return 0;
1019 }
1020
1021 uint64_t helper_cmpglt(uint64_t a, uint64_t b)
1022 {
1023 float64 fa, fb;
1024
1025 fa = g_to_float64(a);
1026 fb = g_to_float64(b);
1027
1028 if (float64_lt(fa, fb, &FP_STATUS))
1029 return 0x4000000000000000ULL;
1030 else
1031 return 0;
1032 }
1033
1034 /* Floating point format conversion */
1035 uint64_t helper_cvtts (uint64_t a)
1036 {
1037 float64 fa;
1038 float32 fr;
1039
1040 fa = t_to_float64(a);
1041 fr = float64_to_float32(fa, &FP_STATUS);
1042 return float32_to_s(fr);
1043 }
1044
1045 uint64_t helper_cvtst (uint64_t a)
1046 {
1047 float32 fa;
1048 float64 fr;
1049
1050 fa = s_to_float32(a);
1051 fr = float32_to_float64(fa, &FP_STATUS);
1052 return float64_to_t(fr);
1053 }
1054
1055 uint64_t helper_cvtqs (uint64_t a)
1056 {
1057 float32 fr = int64_to_float32(a, &FP_STATUS);
1058 return float32_to_s(fr);
1059 }
1060
1061 /* Implement float64 to uint64 conversion without saturation -- we must
1062 supply the truncated result. This behaviour is used by the compiler
1063 to get unsigned conversion for free with the same instruction.
1064
1065 The VI flag is set when overflow or inexact exceptions should be raised. */
1066
1067 static inline uint64_t helper_cvttq_internal(uint64_t a, int roundmode, int VI)
1068 {
1069 uint64_t frac, ret = 0;
1070 uint32_t exp, sign, exc = 0;
1071 int shift;
1072
1073 sign = (a >> 63);
1074 exp = (uint32_t)(a >> 52) & 0x7ff;
1075 frac = a & 0xfffffffffffffull;
1076
1077 if (exp == 0) {
1078 if (unlikely(frac != 0)) {
1079 goto do_underflow;
1080 }
1081 } else if (exp == 0x7ff) {
1082 exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
1083 } else {
1084 /* Restore implicit bit. */
1085 frac |= 0x10000000000000ull;
1086
1087 shift = exp - 1023 - 52;
1088 if (shift >= 0) {
1089 /* In this case the number is so large that we must shift
1090 the fraction left. There is no rounding to do. */
1091 if (shift < 63) {
1092 ret = frac << shift;
1093 if (VI && (ret >> shift) != frac) {
1094 exc = float_flag_overflow;
1095 }
1096 }
1097 } else {
1098 uint64_t round;
1099
1100 /* In this case the number is smaller than the fraction as
1101 represented by the 52 bit number. Here we must think
1102 about rounding the result. Handle this by shifting the
1103 fractional part of the number into the high bits of ROUND.
1104 This will let us efficiently handle round-to-nearest. */
1105 shift = -shift;
1106 if (shift < 63) {
1107 ret = frac >> shift;
1108 round = frac << (64 - shift);
1109 } else {
1110 /* The exponent is so small we shift out everything.
1111 Leave a sticky bit for proper rounding below. */
1112 do_underflow:
1113 round = 1;
1114 }
1115
1116 if (round) {
1117 exc = (VI ? float_flag_inexact : 0);
1118 switch (roundmode) {
1119 case float_round_nearest_even:
1120 if (round == (1ull << 63)) {
1121 /* Fraction is exactly 0.5; round to even. */
1122 ret += (ret & 1);
1123 } else if (round > (1ull << 63)) {
1124 ret += 1;
1125 }
1126 break;
1127 case float_round_to_zero:
1128 break;
1129 case float_round_up:
1130 ret += 1 - sign;
1131 break;
1132 case float_round_down:
1133 ret += sign;
1134 break;
1135 }
1136 }
1137 }
1138 if (sign) {
1139 ret = -ret;
1140 }
1141 }
1142 if (unlikely(exc)) {
1143 float_raise(exc, &FP_STATUS);
1144 }
1145
1146 return ret;
1147 }
1148
1149 uint64_t helper_cvttq(uint64_t a)
1150 {
1151 return helper_cvttq_internal(a, FP_STATUS.float_rounding_mode, 1);
1152 }
1153
1154 uint64_t helper_cvttq_c(uint64_t a)
1155 {
1156 return helper_cvttq_internal(a, float_round_to_zero, 0);
1157 }
1158
1159 uint64_t helper_cvttq_svic(uint64_t a)
1160 {
1161 return helper_cvttq_internal(a, float_round_to_zero, 1);
1162 }
1163
1164 uint64_t helper_cvtqt (uint64_t a)
1165 {
1166 float64 fr = int64_to_float64(a, &FP_STATUS);
1167 return float64_to_t(fr);
1168 }
1169
1170 uint64_t helper_cvtqf (uint64_t a)
1171 {
1172 float32 fr = int64_to_float32(a, &FP_STATUS);
1173 return float32_to_f(fr);
1174 }
1175
1176 uint64_t helper_cvtgf (uint64_t a)
1177 {
1178 float64 fa;
1179 float32 fr;
1180
1181 fa = g_to_float64(a);
1182 fr = float64_to_float32(fa, &FP_STATUS);
1183 return float32_to_f(fr);
1184 }
1185
1186 uint64_t helper_cvtgq (uint64_t a)
1187 {
1188 float64 fa = g_to_float64(a);
1189 return float64_to_int64_round_to_zero(fa, &FP_STATUS);
1190 }
1191
1192 uint64_t helper_cvtqg (uint64_t a)
1193 {
1194 float64 fr;
1195 fr = int64_to_float64(a, &FP_STATUS);
1196 return float64_to_g(fr);
1197 }
1198
1199 uint64_t helper_cvtlq (uint64_t a)
1200 {
1201 int32_t lo = a >> 29;
1202 int32_t hi = a >> 32;
1203 return (lo & 0x3FFFFFFF) | (hi & 0xc0000000);
1204 }
1205
1206 uint64_t helper_cvtql (uint64_t a)
1207 {
1208 return ((a & 0xC0000000) << 32) | ((a & 0x7FFFFFFF) << 29);
1209 }
1210
1211 uint64_t helper_cvtql_v (uint64_t a)
1212 {
1213 if ((int32_t)a != (int64_t)a)
1214 helper_excp(EXCP_ARITH, EXC_M_IOV);
1215 return helper_cvtql(a);
1216 }
1217
1218 uint64_t helper_cvtql_sv (uint64_t a)
1219 {
1220 /* ??? I'm pretty sure there's nothing that /sv needs to do that /v
1221 doesn't do. The only thing I can think is that /sv is a valid
1222 instruction merely for completeness in the ISA. */
1223 return helper_cvtql_v(a);
1224 }
1225
1226 /* PALcode support special instructions */
1227 #if !defined (CONFIG_USER_ONLY)
1228 void helper_hw_rei (void)
1229 {
1230 env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
1231 env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
1232 /* XXX: re-enable interrupts and memory mapping */
1233 }
1234
1235 void helper_hw_ret (uint64_t a)
1236 {
1237 env->pc = a & ~3;
1238 env->ipr[IPR_EXC_ADDR] = a & 1;
1239 /* XXX: re-enable interrupts and memory mapping */
1240 }
1241
1242 uint64_t helper_mfpr (int iprn, uint64_t val)
1243 {
1244 uint64_t tmp;
1245
1246 if (cpu_alpha_mfpr(env, iprn, &tmp) == 0)
1247 val = tmp;
1248
1249 return val;
1250 }
1251
1252 void helper_mtpr (int iprn, uint64_t val)
1253 {
1254 cpu_alpha_mtpr(env, iprn, val, NULL);
1255 }
1256
1257 void helper_set_alt_mode (void)
1258 {
1259 env->saved_mode = env->ps & 0xC;
1260 env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC);
1261 }
1262
1263 void helper_restore_mode (void)
1264 {
1265 env->ps = (env->ps & ~0xC) | env->saved_mode;
1266 }
1267
1268 #endif
1269
1270 /*****************************************************************************/
1271 /* Softmmu support */
1272 #if !defined (CONFIG_USER_ONLY)
1273
1274 /* XXX: the two following helpers are pure hacks.
1275 * Hopefully, we emulate the PALcode, then we should never see
1276 * HW_LD / HW_ST instructions.
1277 */
1278 uint64_t helper_ld_virt_to_phys (uint64_t virtaddr)
1279 {
1280 uint64_t tlb_addr, physaddr;
1281 int index, mmu_idx;
1282 void *retaddr;
1283
1284 mmu_idx = cpu_mmu_index(env);
1285 index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1286 redo:
1287 tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
1288 if ((virtaddr & TARGET_PAGE_MASK) ==
1289 (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1290 physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
1291 } else {
1292 /* the page is not in the TLB : fill it */
1293 retaddr = GETPC();
1294 tlb_fill(virtaddr, 0, mmu_idx, retaddr);
1295 goto redo;
1296 }
1297 return physaddr;
1298 }
1299
1300 uint64_t helper_st_virt_to_phys (uint64_t virtaddr)
1301 {
1302 uint64_t tlb_addr, physaddr;
1303 int index, mmu_idx;
1304 void *retaddr;
1305
1306 mmu_idx = cpu_mmu_index(env);
1307 index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1308 redo:
1309 tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
1310 if ((virtaddr & TARGET_PAGE_MASK) ==
1311 (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1312 physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
1313 } else {
1314 /* the page is not in the TLB : fill it */
1315 retaddr = GETPC();
1316 tlb_fill(virtaddr, 1, mmu_idx, retaddr);
1317 goto redo;
1318 }
1319 return physaddr;
1320 }
1321
1322 void helper_ldl_raw(uint64_t t0, uint64_t t1)
1323 {
1324 ldl_raw(t1, t0);
1325 }
1326
1327 void helper_ldq_raw(uint64_t t0, uint64_t t1)
1328 {
1329 ldq_raw(t1, t0);
1330 }
1331
1332 void helper_ldl_l_raw(uint64_t t0, uint64_t t1)
1333 {
1334 env->lock = t1;
1335 ldl_raw(t1, t0);
1336 }
1337
1338 void helper_ldq_l_raw(uint64_t t0, uint64_t t1)
1339 {
1340 env->lock = t1;
1341 ldl_raw(t1, t0);
1342 }
1343
1344 void helper_ldl_kernel(uint64_t t0, uint64_t t1)
1345 {
1346 ldl_kernel(t1, t0);
1347 }
1348
1349 void helper_ldq_kernel(uint64_t t0, uint64_t t1)
1350 {
1351 ldq_kernel(t1, t0);
1352 }
1353
1354 void helper_ldl_data(uint64_t t0, uint64_t t1)
1355 {
1356 ldl_data(t1, t0);
1357 }
1358
1359 void helper_ldq_data(uint64_t t0, uint64_t t1)
1360 {
1361 ldq_data(t1, t0);
1362 }
1363
1364 void helper_stl_raw(uint64_t t0, uint64_t t1)
1365 {
1366 stl_raw(t1, t0);
1367 }
1368
1369 void helper_stq_raw(uint64_t t0, uint64_t t1)
1370 {
1371 stq_raw(t1, t0);
1372 }
1373
1374 uint64_t helper_stl_c_raw(uint64_t t0, uint64_t t1)
1375 {
1376 uint64_t ret;
1377
1378 if (t1 == env->lock) {
1379 stl_raw(t1, t0);
1380 ret = 0;
1381 } else
1382 ret = 1;
1383
1384 env->lock = 1;
1385
1386 return ret;
1387 }
1388
1389 uint64_t helper_stq_c_raw(uint64_t t0, uint64_t t1)
1390 {
1391 uint64_t ret;
1392
1393 if (t1 == env->lock) {
1394 stq_raw(t1, t0);
1395 ret = 0;
1396 } else
1397 ret = 1;
1398
1399 env->lock = 1;
1400
1401 return ret;
1402 }
1403
1404 #define MMUSUFFIX _mmu
1405
1406 #define SHIFT 0
1407 #include "softmmu_template.h"
1408
1409 #define SHIFT 1
1410 #include "softmmu_template.h"
1411
1412 #define SHIFT 2
1413 #include "softmmu_template.h"
1414
1415 #define SHIFT 3
1416 #include "softmmu_template.h"
1417
1418 /* try to fill the TLB and return an exception if error. If retaddr is
1419 NULL, it means that the function was called in C code (i.e. not
1420 from generated code or from helper.c) */
1421 /* XXX: fix it to restore all registers */
1422 void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1423 {
1424 TranslationBlock *tb;
1425 CPUState *saved_env;
1426 unsigned long pc;
1427 int ret;
1428
1429 /* XXX: hack to restore env in all cases, even if not called from
1430 generated code */
1431 saved_env = env;
1432 env = cpu_single_env;
1433 ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1434 if (!likely(ret == 0)) {
1435 if (likely(retaddr)) {
1436 /* now we have a real cpu fault */
1437 pc = (unsigned long)retaddr;
1438 tb = tb_find_pc(pc);
1439 if (likely(tb)) {
1440 /* the PC is inside the translated code. It means that we have
1441 a virtual CPU fault */
1442 cpu_restore_state(tb, env, pc, NULL);
1443 }
1444 }
1445 /* Exception index and error code are already set */
1446 cpu_loop_exit();
1447 }
1448 env = saved_env;
1449 }
1450
1451 #endif