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