|
|
1.1 root 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, write to the Free Software
18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19: */
20:
21: #include "exec.h"
22: #include "host-utils.h"
23: #include "softfloat.h"
24:
25: #include "op_helper.h"
26:
27: #define MEMSUFFIX _raw
28: #include "op_helper_mem.h"
29:
30: #if !defined(CONFIG_USER_ONLY)
31: #define MEMSUFFIX _kernel
32: #include "op_helper_mem.h"
33:
34: #define MEMSUFFIX _executive
35: #include "op_helper_mem.h"
36:
37: #define MEMSUFFIX _supervisor
38: #include "op_helper_mem.h"
39:
40: #define MEMSUFFIX _user
41: #include "op_helper_mem.h"
42:
43: /* This is used for pal modes */
44: #define MEMSUFFIX _data
45: #include "op_helper_mem.h"
46: #endif
47:
48: void helper_tb_flush (void)
49: {
50: tlb_flush(env, 1);
51: }
52:
53: void cpu_dump_EA (target_ulong EA);
54: void helper_print_mem_EA (target_ulong EA)
55: {
56: cpu_dump_EA(EA);
57: }
58:
59: /*****************************************************************************/
60: /* Exceptions processing helpers */
61: void helper_excp (uint32_t excp, uint32_t error)
62: {
63: env->exception_index = excp;
64: env->error_code = error;
65: cpu_loop_exit();
66: }
67:
68: void helper_amask (void)
69: {
70: switch (env->implver) {
71: case IMPLVER_2106x:
72: /* EV4, EV45, LCA, LCA45 & EV5 */
73: break;
74: case IMPLVER_21164:
75: case IMPLVER_21264:
76: case IMPLVER_21364:
77: T0 &= ~env->amask;
78: break;
79: }
80: }
81:
82: void helper_load_pcc (void)
83: {
84: /* XXX: TODO */
85: T0 = 0;
86: }
87:
88: void helper_load_implver (void)
89: {
90: T0 = env->implver;
91: }
92:
93: void helper_load_fpcr (void)
94: {
95: T0 = 0;
96: #ifdef CONFIG_SOFTFLOAT
97: T0 |= env->fp_status.float_exception_flags << 52;
98: if (env->fp_status.float_exception_flags)
99: T0 |= 1ULL << 63;
100: env->ipr[IPR_EXC_SUM] &= ~0x3E:
101: env->ipr[IPR_EXC_SUM] |= env->fp_status.float_exception_flags << 1;
102: #endif
103: switch (env->fp_status.float_rounding_mode) {
104: case float_round_nearest_even:
105: T0 |= 2ULL << 58;
106: break;
107: case float_round_down:
108: T0 |= 1ULL << 58;
109: break;
110: case float_round_up:
111: T0 |= 3ULL << 58;
112: break;
113: case float_round_to_zero:
114: break;
115: }
116: }
117:
118: void helper_store_fpcr (void)
119: {
120: #ifdef CONFIG_SOFTFLOAT
121: set_float_exception_flags((T0 >> 52) & 0x3F, &FP_STATUS);
122: #endif
123: switch ((T0 >> 58) & 3) {
124: case 0:
125: set_float_rounding_mode(float_round_to_zero, &FP_STATUS);
126: break;
127: case 1:
128: set_float_rounding_mode(float_round_down, &FP_STATUS);
129: break;
130: case 2:
131: set_float_rounding_mode(float_round_nearest_even, &FP_STATUS);
132: break;
133: case 3:
134: set_float_rounding_mode(float_round_up, &FP_STATUS);
135: break;
136: }
137: }
138:
139: void helper_load_irf (void)
140: {
141: /* XXX: TODO */
142: T0 = 0;
143: }
144:
145: void helper_set_irf (void)
146: {
147: /* XXX: TODO */
148: }
149:
150: void helper_clear_irf (void)
151: {
152: /* XXX: TODO */
153: }
154:
155: void helper_addqv (void)
156: {
157: T2 = T0;
158: T0 += T1;
159: if (unlikely((T2 ^ T1 ^ (-1ULL)) & (T2 ^ T0) & (1ULL << 63))) {
160: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
161: }
162: }
163:
164: void helper_addlv (void)
165: {
166: T2 = T0;
167: T0 = (uint32_t)(T0 + T1);
168: if (unlikely((T2 ^ T1 ^ (-1UL)) & (T2 ^ T0) & (1UL << 31))) {
169: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
170: }
171: }
172:
173: void helper_subqv (void)
174: {
175: T2 = T0;
176: T0 -= T1;
177: if (unlikely(((~T2) ^ T0 ^ (-1ULL)) & ((~T2) ^ T1) & (1ULL << 63))) {
178: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
179: }
180: }
181:
182: void helper_sublv (void)
183: {
184: T2 = T0;
185: T0 = (uint32_t)(T0 - T1);
186: if (unlikely(((~T2) ^ T0 ^ (-1UL)) & ((~T2) ^ T1) & (1UL << 31))) {
187: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
188: }
189: }
190:
191: void helper_mullv (void)
192: {
193: int64_t res = (int64_t)T0 * (int64_t)T1;
194:
195: if (unlikely((int32_t)res != res)) {
196: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
197: }
198: T0 = (int64_t)((int32_t)res);
199: }
200:
201: void helper_mulqv ()
202: {
203: uint64_t tl, th;
204:
205: muls64(&tl, &th, T0, T1);
206: /* If th != 0 && th != -1, then we had an overflow */
207: if (unlikely((th + 1) > 1)) {
208: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
209: }
210: T0 = tl;
211: }
212:
213: void helper_ctpop (void)
214: {
215: T0 = ctpop64(T0);
216: }
217:
218: void helper_ctlz (void)
219: {
220: T0 = clz64(T0);
221: }
222:
223: void helper_cttz (void)
224: {
225: T0 = ctz64(T0);
226: }
227:
228: static always_inline uint64_t byte_zap (uint64_t op, uint8_t mskb)
229: {
230: uint64_t mask;
231:
232: mask = 0;
233: mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
234: mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
235: mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
236: mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
237: mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
238: mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
239: mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
240: mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
241:
242: return op & ~mask;
243: }
244:
245: void helper_mskbl (void)
246: {
247: T0 = byte_zap(T0, 0x01 << (T1 & 7));
248: }
249:
250: void helper_extbl (void)
251: {
252: T0 >>= (T1 & 7) * 8;
253: T0 = byte_zap(T0, 0xFE);
254: }
255:
256: void helper_insbl (void)
257: {
258: T0 <<= (T1 & 7) * 8;
259: T0 = byte_zap(T0, ~(0x01 << (T1 & 7)));
260: }
261:
262: void helper_mskwl (void)
263: {
264: T0 = byte_zap(T0, 0x03 << (T1 & 7));
265: }
266:
267: void helper_extwl (void)
268: {
269: T0 >>= (T1 & 7) * 8;
270: T0 = byte_zap(T0, 0xFC);
271: }
272:
273: void helper_inswl (void)
274: {
275: T0 <<= (T1 & 7) * 8;
276: T0 = byte_zap(T0, ~(0x03 << (T1 & 7)));
277: }
278:
279: void helper_mskll (void)
280: {
281: T0 = byte_zap(T0, 0x0F << (T1 & 7));
282: }
283:
284: void helper_extll (void)
285: {
286: T0 >>= (T1 & 7) * 8;
287: T0 = byte_zap(T0, 0xF0);
288: }
289:
290: void helper_insll (void)
291: {
292: T0 <<= (T1 & 7) * 8;
293: T0 = byte_zap(T0, ~(0x0F << (T1 & 7)));
294: }
295:
296: void helper_zap (void)
297: {
298: T0 = byte_zap(T0, T1);
299: }
300:
301: void helper_zapnot (void)
302: {
303: T0 = byte_zap(T0, ~T1);
304: }
305:
306: void helper_mskql (void)
307: {
308: T0 = byte_zap(T0, 0xFF << (T1 & 7));
309: }
310:
311: void helper_extql (void)
312: {
313: T0 >>= (T1 & 7) * 8;
314: T0 = byte_zap(T0, 0x00);
315: }
316:
317: void helper_insql (void)
318: {
319: T0 <<= (T1 & 7) * 8;
320: T0 = byte_zap(T0, ~(0xFF << (T1 & 7)));
321: }
322:
323: void helper_mskwh (void)
324: {
325: T0 = byte_zap(T0, (0x03 << (T1 & 7)) >> 8);
326: }
327:
328: void helper_inswh (void)
329: {
330: T0 >>= 64 - ((T1 & 7) * 8);
331: T0 = byte_zap(T0, ~((0x03 << (T1 & 7)) >> 8));
332: }
333:
334: void helper_extwh (void)
335: {
336: T0 <<= 64 - ((T1 & 7) * 8);
337: T0 = byte_zap(T0, ~0x07);
338: }
339:
340: void helper_msklh (void)
341: {
342: T0 = byte_zap(T0, (0x0F << (T1 & 7)) >> 8);
343: }
344:
345: void helper_inslh (void)
346: {
347: T0 >>= 64 - ((T1 & 7) * 8);
348: T0 = byte_zap(T0, ~((0x0F << (T1 & 7)) >> 8));
349: }
350:
351: void helper_extlh (void)
352: {
353: T0 <<= 64 - ((T1 & 7) * 8);
354: T0 = byte_zap(T0, ~0x0F);
355: }
356:
357: void helper_mskqh (void)
358: {
359: T0 = byte_zap(T0, (0xFF << (T1 & 7)) >> 8);
360: }
361:
362: void helper_insqh (void)
363: {
364: T0 >>= 64 - ((T1 & 7) * 8);
365: T0 = byte_zap(T0, ~((0xFF << (T1 & 7)) >> 8));
366: }
367:
368: void helper_extqh (void)
369: {
370: T0 <<= 64 - ((T1 & 7) * 8);
371: T0 = byte_zap(T0, 0x00);
372: }
373:
374: void helper_cmpbge (void)
375: {
376: uint8_t opa, opb, res;
377: int i;
378:
379: res = 0;
380: for (i = 0; i < 7; i++) {
381: opa = T0 >> (i * 8);
382: opb = T1 >> (i * 8);
383: if (opa >= opb)
384: res |= 1 << i;
385: }
386: T0 = res;
387: }
388:
389: void helper_cmov_fir (int freg)
390: {
391: if (FT0 != 0)
392: env->fir[freg] = FT1;
393: }
394:
395: void helper_sqrts (void)
396: {
397: FT0 = float32_sqrt(FT0, &FP_STATUS);
398: }
399:
400: void helper_cpys (void)
401: {
402: union {
403: double d;
404: uint64_t i;
405: } p, q, r;
406:
407: p.d = FT0;
408: q.d = FT1;
409: r.i = p.i & 0x8000000000000000ULL;
410: r.i |= q.i & ~0x8000000000000000ULL;
411: FT0 = r.d;
412: }
413:
414: void helper_cpysn (void)
415: {
416: union {
417: double d;
418: uint64_t i;
419: } p, q, r;
420:
421: p.d = FT0;
422: q.d = FT1;
423: r.i = (~p.i) & 0x8000000000000000ULL;
424: r.i |= q.i & ~0x8000000000000000ULL;
425: FT0 = r.d;
426: }
427:
428: void helper_cpyse (void)
429: {
430: union {
431: double d;
432: uint64_t i;
433: } p, q, r;
434:
435: p.d = FT0;
436: q.d = FT1;
437: r.i = p.i & 0xFFF0000000000000ULL;
438: r.i |= q.i & ~0xFFF0000000000000ULL;
439: FT0 = r.d;
440: }
441:
442: void helper_itofs (void)
443: {
444: union {
445: double d;
446: uint64_t i;
447: } p;
448:
449: p.d = FT0;
450: FT0 = int64_to_float32(p.i, &FP_STATUS);
451: }
452:
453: void helper_ftois (void)
454: {
455: union {
456: double d;
457: uint64_t i;
458: } p;
459:
460: p.i = float32_to_int64(FT0, &FP_STATUS);
461: FT0 = p.d;
462: }
463:
464: void helper_sqrtt (void)
465: {
466: FT0 = float64_sqrt(FT0, &FP_STATUS);
467: }
468:
469: void helper_cmptun (void)
470: {
471: union {
472: double d;
473: uint64_t i;
474: } p;
475:
476: p.i = 0;
477: if (float64_is_nan(FT0) || float64_is_nan(FT1))
478: p.i = 0x4000000000000000ULL;
479: FT0 = p.d;
480: }
481:
482: void helper_cmpteq (void)
483: {
484: union {
485: double d;
486: uint64_t i;
487: } p;
488:
489: p.i = 0;
490: if (float64_eq(FT0, FT1, &FP_STATUS))
491: p.i = 0x4000000000000000ULL;
492: FT0 = p.d;
493: }
494:
495: void helper_cmptle (void)
496: {
497: union {
498: double d;
499: uint64_t i;
500: } p;
501:
502: p.i = 0;
503: if (float64_le(FT0, FT1, &FP_STATUS))
504: p.i = 0x4000000000000000ULL;
505: FT0 = p.d;
506: }
507:
508: void helper_cmptlt (void)
509: {
510: union {
511: double d;
512: uint64_t i;
513: } p;
514:
515: p.i = 0;
516: if (float64_lt(FT0, FT1, &FP_STATUS))
517: p.i = 0x4000000000000000ULL;
518: FT0 = p.d;
519: }
520:
521: void helper_itoft (void)
522: {
523: union {
524: double d;
525: uint64_t i;
526: } p;
527:
528: p.d = FT0;
529: FT0 = int64_to_float64(p.i, &FP_STATUS);
530: }
531:
532: void helper_ftoit (void)
533: {
534: union {
535: double d;
536: uint64_t i;
537: } p;
538:
539: p.i = float64_to_int64(FT0, &FP_STATUS);
540: FT0 = p.d;
541: }
542:
543: static always_inline int vaxf_is_valid (float ff)
544: {
545: union {
546: float f;
547: uint32_t i;
548: } p;
549: uint32_t exp, mant;
550:
551: p.f = ff;
552: exp = (p.i >> 23) & 0xFF;
553: mant = p.i & 0x007FFFFF;
554: if (exp == 0 && ((p.i & 0x80000000) || mant != 0)) {
555: /* Reserved operands / Dirty zero */
556: return 0;
557: }
558:
559: return 1;
560: }
561:
562: static always_inline float vaxf_to_ieee32 (float ff)
563: {
564: union {
565: float f;
566: uint32_t i;
567: } p;
568: uint32_t exp;
569:
570: p.f = ff;
571: exp = (p.i >> 23) & 0xFF;
572: if (exp < 3) {
573: /* Underflow */
574: p.f = 0.0;
575: } else {
576: p.f *= 0.25;
577: }
578:
579: return p.f;
580: }
581:
582: static always_inline float ieee32_to_vaxf (float fi)
583: {
584: union {
585: float f;
586: uint32_t i;
587: } p;
588: uint32_t exp, mant;
589:
590: p.f = fi;
591: exp = (p.i >> 23) & 0xFF;
592: mant = p.i & 0x007FFFFF;
593: if (exp == 255) {
594: /* NaN or infinity */
595: p.i = 1;
596: } else if (exp == 0) {
597: if (mant == 0) {
598: /* Zero */
599: p.i = 0;
600: } else {
601: /* Denormalized */
602: p.f *= 2.0;
603: }
604: } else {
605: if (exp >= 253) {
606: /* Overflow */
607: p.i = 1;
608: } else {
609: p.f *= 4.0;
610: }
611: }
612:
613: return p.f;
614: }
615:
616: void helper_addf (void)
617: {
618: float ft0, ft1, ft2;
619:
620: if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
621: /* XXX: TODO */
622: }
623: ft0 = vaxf_to_ieee32(FT0);
624: ft1 = vaxf_to_ieee32(FT1);
625: ft2 = float32_add(ft0, ft1, &FP_STATUS);
626: FT0 = ieee32_to_vaxf(ft2);
627: }
628:
629: void helper_subf (void)
630: {
631: float ft0, ft1, ft2;
632:
633: if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
634: /* XXX: TODO */
635: }
636: ft0 = vaxf_to_ieee32(FT0);
637: ft1 = vaxf_to_ieee32(FT1);
638: ft2 = float32_sub(ft0, ft1, &FP_STATUS);
639: FT0 = ieee32_to_vaxf(ft2);
640: }
641:
642: void helper_mulf (void)
643: {
644: float ft0, ft1, ft2;
645:
646: if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
647: /* XXX: TODO */
648: }
649: ft0 = vaxf_to_ieee32(FT0);
650: ft1 = vaxf_to_ieee32(FT1);
651: ft2 = float32_mul(ft0, ft1, &FP_STATUS);
652: FT0 = ieee32_to_vaxf(ft2);
653: }
654:
655: void helper_divf (void)
656: {
657: float ft0, ft1, ft2;
658:
659: if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
660: /* XXX: TODO */
661: }
662: ft0 = vaxf_to_ieee32(FT0);
663: ft1 = vaxf_to_ieee32(FT1);
664: ft2 = float32_div(ft0, ft1, &FP_STATUS);
665: FT0 = ieee32_to_vaxf(ft2);
666: }
667:
668: void helper_sqrtf (void)
669: {
670: float ft0, ft1;
671:
672: if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
673: /* XXX: TODO */
674: }
675: ft0 = vaxf_to_ieee32(FT0);
676: ft1 = float32_sqrt(ft0, &FP_STATUS);
677: FT0 = ieee32_to_vaxf(ft1);
678: }
679:
680: void helper_itoff (void)
681: {
682: /* XXX: TODO */
683: }
684:
685: static always_inline int vaxg_is_valid (double ff)
686: {
687: union {
688: double f;
689: uint64_t i;
690: } p;
691: uint64_t exp, mant;
692:
693: p.f = ff;
694: exp = (p.i >> 52) & 0x7FF;
695: mant = p.i & 0x000FFFFFFFFFFFFFULL;
696: if (exp == 0 && ((p.i & 0x8000000000000000ULL) || mant != 0)) {
697: /* Reserved operands / Dirty zero */
698: return 0;
699: }
700:
701: return 1;
702: }
703:
704: static always_inline double vaxg_to_ieee64 (double fg)
705: {
706: union {
707: double f;
708: uint64_t i;
709: } p;
710: uint32_t exp;
711:
712: p.f = fg;
713: exp = (p.i >> 52) & 0x7FF;
714: if (exp < 3) {
715: /* Underflow */
716: p.f = 0.0;
717: } else {
718: p.f *= 0.25;
719: }
720:
721: return p.f;
722: }
723:
724: static always_inline double ieee64_to_vaxg (double fi)
725: {
726: union {
727: double f;
728: uint64_t i;
729: } p;
730: uint64_t mant;
731: uint32_t exp;
732:
733: p.f = fi;
734: exp = (p.i >> 52) & 0x7FF;
735: mant = p.i & 0x000FFFFFFFFFFFFFULL;
736: if (exp == 255) {
737: /* NaN or infinity */
738: p.i = 1; /* VAX dirty zero */
739: } else if (exp == 0) {
740: if (mant == 0) {
741: /* Zero */
742: p.i = 0;
743: } else {
744: /* Denormalized */
745: p.f *= 2.0;
746: }
747: } else {
748: if (exp >= 2045) {
749: /* Overflow */
750: p.i = 1; /* VAX dirty zero */
751: } else {
752: p.f *= 4.0;
753: }
754: }
755:
756: return p.f;
757: }
758:
759: void helper_addg (void)
760: {
761: double ft0, ft1, ft2;
762:
763: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
764: /* XXX: TODO */
765: }
766: ft0 = vaxg_to_ieee64(FT0);
767: ft1 = vaxg_to_ieee64(FT1);
768: ft2 = float64_add(ft0, ft1, &FP_STATUS);
769: FT0 = ieee64_to_vaxg(ft2);
770: }
771:
772: void helper_subg (void)
773: {
774: double ft0, ft1, ft2;
775:
776: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
777: /* XXX: TODO */
778: }
779: ft0 = vaxg_to_ieee64(FT0);
780: ft1 = vaxg_to_ieee64(FT1);
781: ft2 = float64_sub(ft0, ft1, &FP_STATUS);
782: FT0 = ieee64_to_vaxg(ft2);
783: }
784:
785: void helper_mulg (void)
786: {
787: double ft0, ft1, ft2;
788:
789: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
790: /* XXX: TODO */
791: }
792: ft0 = vaxg_to_ieee64(FT0);
793: ft1 = vaxg_to_ieee64(FT1);
794: ft2 = float64_mul(ft0, ft1, &FP_STATUS);
795: FT0 = ieee64_to_vaxg(ft2);
796: }
797:
798: void helper_divg (void)
799: {
800: double ft0, ft1, ft2;
801:
802: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
803: /* XXX: TODO */
804: }
805: ft0 = vaxg_to_ieee64(FT0);
806: ft1 = vaxg_to_ieee64(FT1);
807: ft2 = float64_div(ft0, ft1, &FP_STATUS);
808: FT0 = ieee64_to_vaxg(ft2);
809: }
810:
811: void helper_sqrtg (void)
812: {
813: double ft0, ft1;
814:
815: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
816: /* XXX: TODO */
817: }
818: ft0 = vaxg_to_ieee64(FT0);
819: ft1 = float64_sqrt(ft0, &FP_STATUS);
820: FT0 = ieee64_to_vaxg(ft1);
821: }
822:
823: void helper_cmpgeq (void)
824: {
825: union {
826: double d;
827: uint64_t u;
828: } p;
829: double ft0, ft1;
830:
831: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
832: /* XXX: TODO */
833: }
834: ft0 = vaxg_to_ieee64(FT0);
835: ft1 = vaxg_to_ieee64(FT1);
836: p.u = 0;
837: if (float64_eq(ft0, ft1, &FP_STATUS))
838: p.u = 0x4000000000000000ULL;
839: FT0 = p.d;
840: }
841:
842: void helper_cmpglt (void)
843: {
844: union {
845: double d;
846: uint64_t u;
847: } p;
848: double ft0, ft1;
849:
850: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
851: /* XXX: TODO */
852: }
853: ft0 = vaxg_to_ieee64(FT0);
854: ft1 = vaxg_to_ieee64(FT1);
855: p.u = 0;
856: if (float64_lt(ft0, ft1, &FP_STATUS))
857: p.u = 0x4000000000000000ULL;
858: FT0 = p.d;
859: }
860:
861: void helper_cmpgle (void)
862: {
863: union {
864: double d;
865: uint64_t u;
866: } p;
867: double ft0, ft1;
868:
869: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
870: /* XXX: TODO */
871: }
872: ft0 = vaxg_to_ieee64(FT0);
873: ft1 = vaxg_to_ieee64(FT1);
874: p.u = 0;
875: if (float64_le(ft0, ft1, &FP_STATUS))
876: p.u = 0x4000000000000000ULL;
877: FT0 = p.d;
878: }
879:
880: void helper_cvtqs (void)
881: {
882: union {
883: double d;
884: uint64_t u;
885: } p;
886:
887: p.d = FT0;
888: FT0 = (float)p.u;
889: }
890:
891: void helper_cvttq (void)
892: {
893: union {
894: double d;
895: uint64_t u;
896: } p;
897:
898: p.u = FT0;
899: FT0 = p.d;
900: }
901:
902: void helper_cvtqt (void)
903: {
904: union {
905: double d;
906: uint64_t u;
907: } p;
908:
909: p.d = FT0;
910: FT0 = p.u;
911: }
912:
913: void helper_cvtqf (void)
914: {
915: union {
916: double d;
917: uint64_t u;
918: } p;
919:
920: p.d = FT0;
921: FT0 = ieee32_to_vaxf(p.u);
922: }
923:
924: void helper_cvtgf (void)
925: {
926: double ft0;
927:
928: ft0 = vaxg_to_ieee64(FT0);
929: FT0 = ieee32_to_vaxf(ft0);
930: }
931:
932: void helper_cvtgd (void)
933: {
934: /* XXX: TODO */
935: }
936:
937: void helper_cvtgq (void)
938: {
939: union {
940: double d;
941: uint64_t u;
942: } p;
943:
944: p.u = vaxg_to_ieee64(FT0);
945: FT0 = p.d;
946: }
947:
948: void helper_cvtqg (void)
949: {
950: union {
951: double d;
952: uint64_t u;
953: } p;
954:
955: p.d = FT0;
956: FT0 = ieee64_to_vaxg(p.u);
957: }
958:
959: void helper_cvtdg (void)
960: {
961: /* XXX: TODO */
962: }
963:
964: void helper_cvtlq (void)
965: {
966: union {
967: double d;
968: uint64_t u;
969: } p, q;
970:
971: p.d = FT0;
972: q.u = (p.u >> 29) & 0x3FFFFFFF;
973: q.u |= (p.u >> 32);
974: q.u = (int64_t)((int32_t)q.u);
975: FT0 = q.d;
976: }
977:
978: static always_inline void __helper_cvtql (int s, int v)
979: {
980: union {
981: double d;
982: uint64_t u;
983: } p, q;
984:
985: p.d = FT0;
986: q.u = ((uint64_t)(p.u & 0xC0000000)) << 32;
987: q.u |= ((uint64_t)(p.u & 0x7FFFFFFF)) << 29;
988: FT0 = q.d;
989: if (v && (int64_t)((int32_t)p.u) != (int64_t)p.u) {
990: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
991: }
992: if (s) {
993: /* TODO */
994: }
995: }
996:
997: void helper_cvtql (void)
998: {
999: __helper_cvtql(0, 0);
1000: }
1001:
1002: void helper_cvtqlv (void)
1003: {
1004: __helper_cvtql(0, 1);
1005: }
1006:
1007: void helper_cvtqlsv (void)
1008: {
1009: __helper_cvtql(1, 1);
1010: }
1011:
1012: void helper_cmpfeq (void)
1013: {
1014: if (float64_eq(FT0, FT1, &FP_STATUS))
1015: T0 = 1;
1016: else
1017: T0 = 0;
1018: }
1019:
1020: void helper_cmpfne (void)
1021: {
1022: if (float64_eq(FT0, FT1, &FP_STATUS))
1023: T0 = 0;
1024: else
1025: T0 = 1;
1026: }
1027:
1028: void helper_cmpflt (void)
1029: {
1030: if (float64_lt(FT0, FT1, &FP_STATUS))
1031: T0 = 1;
1032: else
1033: T0 = 0;
1034: }
1035:
1036: void helper_cmpfle (void)
1037: {
1038: if (float64_lt(FT0, FT1, &FP_STATUS))
1039: T0 = 1;
1040: else
1041: T0 = 0;
1042: }
1043:
1044: void helper_cmpfgt (void)
1045: {
1046: if (float64_le(FT0, FT1, &FP_STATUS))
1047: T0 = 0;
1048: else
1049: T0 = 1;
1050: }
1051:
1052: void helper_cmpfge (void)
1053: {
1054: if (float64_lt(FT0, FT1, &FP_STATUS))
1055: T0 = 0;
1056: else
1057: T0 = 1;
1058: }
1059:
1060: #if !defined (CONFIG_USER_ONLY)
1061: void helper_mfpr (int iprn)
1062: {
1063: uint64_t val;
1064:
1065: if (cpu_alpha_mfpr(env, iprn, &val) == 0)
1066: T0 = val;
1067: }
1068:
1069: void helper_mtpr (int iprn)
1070: {
1071: cpu_alpha_mtpr(env, iprn, T0, NULL);
1072: }
1073: #endif
1074:
1075: #if defined(HOST_SPARC) || defined(HOST_SPARC64)
1076: void helper_reset_FT0 (void)
1077: {
1078: FT0 = 0;
1079: }
1080:
1081: void helper_reset_FT1 (void)
1082: {
1083: FT1 = 0;
1084: }
1085:
1086: void helper_reset_FT2 (void)
1087: {
1088: FT2 = 0;
1089: }
1090: #endif
1091:
1092: /*****************************************************************************/
1093: /* Softmmu support */
1094: #if !defined (CONFIG_USER_ONLY)
1095:
1096: #ifdef __s390__
1097: # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
1098: #else
1099: # define GETPC() (__builtin_return_address(0))
1100: #endif
1101:
1102: /* XXX: the two following helpers are pure hacks.
1103: * Hopefully, we emulate the PALcode, then we should never see
1104: * HW_LD / HW_ST instructions.
1105: */
1106: void helper_ld_phys_to_virt (void)
1107: {
1108: uint64_t tlb_addr, physaddr;
1109: int index, mmu_idx;
1110: void *retaddr;
1111:
1112: mmu_idx = cpu_mmu_index(env);
1113: index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1114: redo:
1115: tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
1116: if ((T0 & TARGET_PAGE_MASK) ==
1117: (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1118: physaddr = T0 + env->tlb_table[mmu_idx][index].addend;
1119: } else {
1120: /* the page is not in the TLB : fill it */
1121: retaddr = GETPC();
1122: tlb_fill(T0, 0, mmu_idx, retaddr);
1123: goto redo;
1124: }
1125: T0 = physaddr;
1126: }
1127:
1128: void helper_st_phys_to_virt (void)
1129: {
1130: uint64_t tlb_addr, physaddr;
1131: int index, mmu_idx;
1132: void *retaddr;
1133:
1134: mmu_idx = cpu_mmu_index(env);
1135: index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1136: redo:
1137: tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
1138: if ((T0 & TARGET_PAGE_MASK) ==
1139: (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1140: physaddr = T0 + env->tlb_table[mmu_idx][index].addend;
1141: } else {
1142: /* the page is not in the TLB : fill it */
1143: retaddr = GETPC();
1144: tlb_fill(T0, 1, mmu_idx, retaddr);
1145: goto redo;
1146: }
1147: T0 = physaddr;
1148: }
1149:
1150: #define MMUSUFFIX _mmu
1151:
1152: #define SHIFT 0
1153: #include "softmmu_template.h"
1154:
1155: #define SHIFT 1
1156: #include "softmmu_template.h"
1157:
1158: #define SHIFT 2
1159: #include "softmmu_template.h"
1160:
1161: #define SHIFT 3
1162: #include "softmmu_template.h"
1163:
1164: /* try to fill the TLB and return an exception if error. If retaddr is
1165: NULL, it means that the function was called in C code (i.e. not
1166: from generated code or from helper.c) */
1167: /* XXX: fix it to restore all registers */
1168: void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1169: {
1170: TranslationBlock *tb;
1171: CPUState *saved_env;
1172: unsigned long pc;
1173: int ret;
1174:
1175: /* XXX: hack to restore env in all cases, even if not called from
1176: generated code */
1177: saved_env = env;
1178: env = cpu_single_env;
1179: ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1180: if (!likely(ret == 0)) {
1181: if (likely(retaddr)) {
1182: /* now we have a real cpu fault */
1183: pc = (unsigned long)retaddr;
1184: tb = tb_find_pc(pc);
1185: if (likely(tb)) {
1186: /* the PC is inside the translated code. It means that we have
1187: a virtual CPU fault */
1188: cpu_restore_state(tb, env, pc, NULL);
1189: }
1190: }
1191: /* Exception index and error code are already set */
1192: cpu_loop_exit();
1193: }
1194: env = saved_env;
1195: }
1196:
1197: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.