|
|
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:
1.1.1.9 ! root 20: #include "cpu.h"
! 21: #include "dyngen-exec.h"
1.1 root 22: #include "host-utils.h"
23: #include "softfloat.h"
1.1.1.2 root 24: #include "helper.h"
1.1.1.9 ! root 25: #include "sysemu.h"
1.1.1.6 root 26: #include "qemu-timer.h"
1.1 root 27:
1.1.1.9 ! root 28: #define FP_STATUS (env->fp_status)
! 29:
1.1 root 30: /*****************************************************************************/
31: /* Exceptions processing helpers */
1.1.1.8 root 32:
33: /* This should only be called from translate, via gen_excp.
34: We expect that ENV->PC has already been updated. */
35: void QEMU_NORETURN helper_excp(int excp, int error)
1.1 root 36: {
37: env->exception_index = excp;
38: env->error_code = error;
1.1.1.8 root 39: cpu_loop_exit(env);
40: }
41:
42: static void do_restore_state(void *retaddr)
43: {
44: unsigned long pc = (unsigned long)retaddr;
45:
46: if (pc) {
47: TranslationBlock *tb = tb_find_pc(pc);
48: if (tb) {
49: cpu_restore_state(tb, env, pc);
50: }
51: }
52: }
53:
54: /* This may be called from any of the helpers to set up EXCEPTION_INDEX. */
55: static void QEMU_NORETURN dynamic_excp(int excp, int error)
56: {
57: env->exception_index = excp;
58: env->error_code = error;
59: do_restore_state(GETPC());
60: cpu_loop_exit(env);
61: }
62:
63: static void QEMU_NORETURN arith_excp(int exc, uint64_t mask)
64: {
65: env->trap_arg0 = exc;
66: env->trap_arg1 = mask;
67: dynamic_excp(EXCP_ARITH, 0);
1.1 root 68: }
69:
1.1.1.2 root 70: uint64_t helper_load_pcc (void)
1.1 root 71: {
1.1.1.8 root 72: #ifndef CONFIG_USER_ONLY
73: /* In system mode we have access to a decent high-resolution clock.
74: In order to make OS-level time accounting work with the RPCC,
75: present it with a well-timed clock fixed at 250MHz. */
76: return (((uint64_t)env->pcc_ofs << 32)
77: | (uint32_t)(qemu_get_clock_ns(vm_clock) >> 2));
78: #else
79: /* In user-mode, vm_clock doesn't exist. Just pass through the host cpu
80: clock ticks. Also, don't bother taking PCC_OFS into account. */
1.1.1.6 root 81: return (uint32_t)cpu_get_real_ticks();
1.1.1.8 root 82: #endif
1.1 root 83: }
84:
1.1.1.2 root 85: uint64_t helper_load_fpcr (void)
1.1 root 86: {
1.1.1.6 root 87: return cpu_alpha_load_fpcr (env);
1.1 root 88: }
89:
1.1.1.2 root 90: void helper_store_fpcr (uint64_t val)
1.1 root 91: {
1.1.1.6 root 92: cpu_alpha_store_fpcr (env, val);
1.1 root 93: }
94:
1.1.1.2 root 95: uint64_t helper_addqv (uint64_t op1, uint64_t op2)
1.1 root 96: {
1.1.1.2 root 97: uint64_t tmp = op1;
98: op1 += op2;
99: if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
1.1.1.8 root 100: arith_excp(EXC_M_IOV, 0);
1.1 root 101: }
1.1.1.2 root 102: return op1;
1.1 root 103: }
104:
1.1.1.2 root 105: uint64_t helper_addlv (uint64_t op1, uint64_t op2)
1.1 root 106: {
1.1.1.2 root 107: uint64_t tmp = op1;
108: op1 = (uint32_t)(op1 + op2);
109: if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
1.1.1.8 root 110: arith_excp(EXC_M_IOV, 0);
1.1 root 111: }
1.1.1.2 root 112: return op1;
1.1 root 113: }
114:
1.1.1.2 root 115: uint64_t helper_subqv (uint64_t op1, uint64_t op2)
1.1 root 116: {
1.1.1.3 root 117: uint64_t res;
118: res = op1 - op2;
119: if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
1.1.1.8 root 120: arith_excp(EXC_M_IOV, 0);
1.1 root 121: }
1.1.1.3 root 122: return res;
1.1 root 123: }
124:
1.1.1.2 root 125: uint64_t helper_sublv (uint64_t op1, uint64_t op2)
1.1 root 126: {
1.1.1.3 root 127: uint32_t res;
128: res = op1 - op2;
129: if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
1.1.1.8 root 130: arith_excp(EXC_M_IOV, 0);
1.1 root 131: }
1.1.1.3 root 132: return res;
1.1 root 133: }
134:
1.1.1.2 root 135: uint64_t helper_mullv (uint64_t op1, uint64_t op2)
1.1 root 136: {
1.1.1.2 root 137: int64_t res = (int64_t)op1 * (int64_t)op2;
1.1 root 138:
139: if (unlikely((int32_t)res != res)) {
1.1.1.8 root 140: arith_excp(EXC_M_IOV, 0);
1.1 root 141: }
1.1.1.2 root 142: return (int64_t)((int32_t)res);
1.1 root 143: }
144:
1.1.1.2 root 145: uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
1.1 root 146: {
147: uint64_t tl, th;
148:
1.1.1.2 root 149: muls64(&tl, &th, op1, op2);
1.1 root 150: /* If th != 0 && th != -1, then we had an overflow */
151: if (unlikely((th + 1) > 1)) {
1.1.1.8 root 152: arith_excp(EXC_M_IOV, 0);
1.1 root 153: }
1.1.1.2 root 154: return tl;
1.1 root 155: }
156:
1.1.1.2 root 157: uint64_t helper_umulh (uint64_t op1, uint64_t op2)
1.1 root 158: {
1.1.1.2 root 159: uint64_t tl, th;
160:
161: mulu64(&tl, &th, op1, op2);
162: return th;
1.1 root 163: }
164:
1.1.1.2 root 165: uint64_t helper_ctpop (uint64_t arg)
1.1 root 166: {
1.1.1.2 root 167: return ctpop64(arg);
1.1 root 168: }
169:
1.1.1.2 root 170: uint64_t helper_ctlz (uint64_t arg)
1.1 root 171: {
1.1.1.2 root 172: return clz64(arg);
173: }
174:
175: uint64_t helper_cttz (uint64_t arg)
176: {
177: return ctz64(arg);
1.1 root 178: }
179:
1.1.1.4 root 180: static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
1.1 root 181: {
182: uint64_t mask;
183:
184: mask = 0;
185: mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
186: mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
187: mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
188: mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
189: mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
190: mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
191: mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
192: mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
193:
194: return op & ~mask;
195: }
196:
1.1.1.6 root 197: uint64_t helper_zap(uint64_t val, uint64_t mask)
1.1 root 198: {
1.1.1.6 root 199: return byte_zap(val, mask);
1.1 root 200: }
201:
1.1.1.6 root 202: uint64_t helper_zapnot(uint64_t val, uint64_t mask)
1.1 root 203: {
1.1.1.6 root 204: return byte_zap(val, ~mask);
1.1 root 205: }
206:
1.1.1.6 root 207: uint64_t helper_cmpbge (uint64_t op1, uint64_t op2)
1.1 root 208: {
1.1.1.6 root 209: uint8_t opa, opb, res;
210: int i;
211:
212: res = 0;
213: for (i = 0; i < 8; i++) {
214: opa = op1 >> (i * 8);
215: opb = op2 >> (i * 8);
216: if (opa >= opb)
217: res |= 1 << i;
218: }
219: return res;
1.1 root 220: }
221:
1.1.1.6 root 222: uint64_t helper_minub8 (uint64_t op1, uint64_t op2)
1.1 root 223: {
1.1.1.6 root 224: uint64_t res = 0;
225: uint8_t opa, opb, opr;
226: int i;
227:
228: for (i = 0; i < 8; ++i) {
229: opa = op1 >> (i * 8);
230: opb = op2 >> (i * 8);
231: opr = opa < opb ? opa : opb;
232: res |= (uint64_t)opr << (i * 8);
233: }
234: return res;
1.1 root 235: }
236:
1.1.1.6 root 237: uint64_t helper_minsb8 (uint64_t op1, uint64_t op2)
1.1 root 238: {
1.1.1.6 root 239: uint64_t res = 0;
240: int8_t opa, opb;
241: uint8_t opr;
242: int i;
243:
244: for (i = 0; i < 8; ++i) {
245: opa = op1 >> (i * 8);
246: opb = op2 >> (i * 8);
247: opr = opa < opb ? opa : opb;
248: res |= (uint64_t)opr << (i * 8);
249: }
250: return res;
1.1 root 251: }
252:
1.1.1.6 root 253: uint64_t helper_minuw4 (uint64_t op1, uint64_t op2)
1.1 root 254: {
1.1.1.6 root 255: uint64_t res = 0;
256: uint16_t opa, opb, opr;
257: int i;
258:
259: for (i = 0; i < 4; ++i) {
260: opa = op1 >> (i * 16);
261: opb = op2 >> (i * 16);
262: opr = opa < opb ? opa : opb;
263: res |= (uint64_t)opr << (i * 16);
264: }
265: return res;
1.1 root 266: }
267:
1.1.1.6 root 268: uint64_t helper_minsw4 (uint64_t op1, uint64_t op2)
1.1 root 269: {
1.1.1.6 root 270: uint64_t res = 0;
271: int16_t opa, opb;
272: uint16_t opr;
273: int i;
274:
275: for (i = 0; i < 4; ++i) {
276: opa = op1 >> (i * 16);
277: opb = op2 >> (i * 16);
278: opr = opa < opb ? opa : opb;
279: res |= (uint64_t)opr << (i * 16);
280: }
281: return res;
1.1 root 282: }
283:
1.1.1.6 root 284: uint64_t helper_maxub8 (uint64_t op1, uint64_t op2)
1.1 root 285: {
1.1.1.6 root 286: uint64_t res = 0;
287: uint8_t opa, opb, opr;
288: int i;
289:
290: for (i = 0; i < 8; ++i) {
291: opa = op1 >> (i * 8);
292: opb = op2 >> (i * 8);
293: opr = opa > opb ? opa : opb;
294: res |= (uint64_t)opr << (i * 8);
295: }
296: return res;
1.1 root 297: }
298:
1.1.1.6 root 299: uint64_t helper_maxsb8 (uint64_t op1, uint64_t op2)
1.1 root 300: {
1.1.1.6 root 301: uint64_t res = 0;
302: int8_t opa, opb;
303: uint8_t opr;
304: int i;
305:
306: for (i = 0; i < 8; ++i) {
307: opa = op1 >> (i * 8);
308: opb = op2 >> (i * 8);
309: opr = opa > opb ? opa : opb;
310: res |= (uint64_t)opr << (i * 8);
311: }
312: return res;
1.1 root 313: }
314:
1.1.1.6 root 315: uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2)
1.1 root 316: {
1.1.1.6 root 317: uint64_t res = 0;
318: uint16_t opa, opb, opr;
319: int i;
320:
321: for (i = 0; i < 4; ++i) {
322: opa = op1 >> (i * 16);
323: opb = op2 >> (i * 16);
324: opr = opa > opb ? opa : opb;
325: res |= (uint64_t)opr << (i * 16);
326: }
327: return res;
1.1 root 328: }
329:
1.1.1.6 root 330: uint64_t helper_maxsw4 (uint64_t op1, uint64_t op2)
1.1 root 331: {
1.1.1.6 root 332: uint64_t res = 0;
333: int16_t opa, opb;
334: uint16_t opr;
335: int i;
336:
337: for (i = 0; i < 4; ++i) {
338: opa = op1 >> (i * 16);
339: opb = op2 >> (i * 16);
340: opr = opa > opb ? opa : opb;
341: res |= (uint64_t)opr << (i * 16);
342: }
343: return res;
1.1 root 344: }
345:
1.1.1.6 root 346: uint64_t helper_perr (uint64_t op1, uint64_t op2)
1.1 root 347: {
1.1.1.6 root 348: uint64_t res = 0;
349: uint8_t opa, opb, opr;
350: int i;
351:
352: for (i = 0; i < 8; ++i) {
353: opa = op1 >> (i * 8);
354: opb = op2 >> (i * 8);
355: if (opa >= opb)
356: opr = opa - opb;
357: else
358: opr = opb - opa;
359: res += opr;
360: }
361: return res;
1.1 root 362: }
363:
1.1.1.6 root 364: uint64_t helper_pklb (uint64_t op1)
1.1 root 365: {
1.1.1.6 root 366: return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
1.1 root 367: }
368:
1.1.1.6 root 369: uint64_t helper_pkwb (uint64_t op1)
1.1 root 370: {
1.1.1.6 root 371: return ((op1 & 0xff)
372: | ((op1 >> 8) & 0xff00)
373: | ((op1 >> 16) & 0xff0000)
374: | ((op1 >> 24) & 0xff000000));
1.1 root 375: }
376:
1.1.1.6 root 377: uint64_t helper_unpkbl (uint64_t op1)
1.1 root 378: {
1.1.1.6 root 379: return (op1 & 0xff) | ((op1 & 0xff00) << 24);
1.1 root 380: }
381:
1.1.1.6 root 382: uint64_t helper_unpkbw (uint64_t op1)
1.1 root 383: {
1.1.1.6 root 384: return ((op1 & 0xff)
385: | ((op1 & 0xff00) << 8)
386: | ((op1 & 0xff0000) << 16)
387: | ((op1 & 0xff000000) << 24));
1.1 root 388: }
389:
1.1.1.6 root 390: /* Floating point helpers */
391:
392: void helper_setroundmode (uint32_t val)
1.1 root 393: {
1.1.1.6 root 394: set_float_rounding_mode(val, &FP_STATUS);
395: }
1.1 root 396:
1.1.1.6 root 397: void helper_setflushzero (uint32_t val)
398: {
399: set_flush_to_zero(val, &FP_STATUS);
400: }
401:
402: void helper_fp_exc_clear (void)
403: {
404: set_float_exception_flags(0, &FP_STATUS);
405: }
406:
407: uint32_t helper_fp_exc_get (void)
408: {
409: return get_float_exception_flags(&FP_STATUS);
410: }
411:
412: /* Raise exceptions for ieee fp insns without software completion.
413: In that case there are no exceptions that don't trap; the mask
414: doesn't apply. */
415: void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
416: {
417: if (exc) {
418: uint32_t hw_exc = 0;
419:
420: if (exc & float_flag_invalid) {
421: hw_exc |= EXC_M_INV;
422: }
423: if (exc & float_flag_divbyzero) {
424: hw_exc |= EXC_M_DZE;
425: }
426: if (exc & float_flag_overflow) {
427: hw_exc |= EXC_M_FOV;
428: }
429: if (exc & float_flag_underflow) {
430: hw_exc |= EXC_M_UNF;
431: }
432: if (exc & float_flag_inexact) {
433: hw_exc |= EXC_M_INE;
434: }
1.1.1.8 root 435:
436: arith_excp(hw_exc, 1ull << regno);
1.1.1.2 root 437: }
1.1 root 438: }
439:
1.1.1.6 root 440: /* Raise exceptions for ieee fp insns with software completion. */
441: void helper_fp_exc_raise_s(uint32_t exc, uint32_t regno)
442: {
443: if (exc) {
444: env->fpcr_exc_status |= exc;
445:
446: exc &= ~env->fpcr_exc_mask;
447: if (exc) {
448: helper_fp_exc_raise(exc, regno);
449: }
450: }
451: }
452:
453: /* Input remapping without software completion. Handle denormal-map-to-zero
454: and trap for all other non-finite numbers. */
455: uint64_t helper_ieee_input(uint64_t val)
456: {
457: uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
458: uint64_t frac = val & 0xfffffffffffffull;
459:
460: if (exp == 0) {
461: if (frac != 0) {
462: /* If DNZ is set flush denormals to zero on input. */
463: if (env->fpcr_dnz) {
464: val &= 1ull << 63;
465: } else {
1.1.1.8 root 466: arith_excp(EXC_M_UNF, 0);
1.1.1.6 root 467: }
468: }
469: } else if (exp == 0x7ff) {
470: /* Infinity or NaN. */
471: /* ??? I'm not sure these exception bit flags are correct. I do
472: know that the Linux kernel, at least, doesn't rely on them and
473: just emulates the insn to figure out what exception to use. */
1.1.1.8 root 474: arith_excp(frac ? EXC_M_INV : EXC_M_FOV, 0);
1.1.1.6 root 475: }
476: return val;
477: }
478:
479: /* Similar, but does not trap for infinities. Used for comparisons. */
480: uint64_t helper_ieee_input_cmp(uint64_t val)
481: {
482: uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
483: uint64_t frac = val & 0xfffffffffffffull;
484:
485: if (exp == 0) {
486: if (frac != 0) {
487: /* If DNZ is set flush denormals to zero on input. */
488: if (env->fpcr_dnz) {
489: val &= 1ull << 63;
490: } else {
1.1.1.8 root 491: arith_excp(EXC_M_UNF, 0);
1.1.1.6 root 492: }
493: }
494: } else if (exp == 0x7ff && frac) {
495: /* NaN. */
1.1.1.8 root 496: arith_excp(EXC_M_INV, 0);
1.1.1.6 root 497: }
498: return val;
499: }
500:
501: /* Input remapping with software completion enabled. All we have to do
502: is handle denormal-map-to-zero; all other inputs get exceptions as
503: needed from the actual operation. */
504: uint64_t helper_ieee_input_s(uint64_t val)
505: {
506: if (env->fpcr_dnz) {
507: uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
508: if (exp == 0) {
509: val &= 1ull << 63;
510: }
511: }
512: return val;
513: }
1.1 root 514:
1.1.1.2 root 515: /* F floating (VAX) */
1.1.1.4 root 516: static inline uint64_t float32_to_f(float32 fa)
1.1 root 517: {
1.1.1.2 root 518: uint64_t r, exp, mant, sig;
519: CPU_FloatU a;
520:
521: a.f = fa;
522: sig = ((uint64_t)a.l & 0x80000000) << 32;
523: exp = (a.l >> 23) & 0xff;
524: mant = ((uint64_t)a.l & 0x007fffff) << 29;
525:
526: if (exp == 255) {
527: /* NaN or infinity */
528: r = 1; /* VAX dirty zero */
529: } else if (exp == 0) {
530: if (mant == 0) {
531: /* Zero */
532: r = 0;
533: } else {
534: /* Denormalized */
535: r = sig | ((exp + 1) << 52) | mant;
536: }
537: } else {
538: if (exp >= 253) {
539: /* Overflow */
540: r = 1; /* VAX dirty zero */
541: } else {
542: r = sig | ((exp + 2) << 52);
543: }
544: }
545:
546: return r;
1.1 root 547: }
548:
1.1.1.4 root 549: static inline float32 f_to_float32(uint64_t a)
1.1 root 550: {
1.1.1.2 root 551: uint32_t exp, mant_sig;
552: CPU_FloatU r;
553:
554: exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
555: mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
556:
557: if (unlikely(!exp && mant_sig)) {
558: /* Reserved operands / Dirty zero */
1.1.1.8 root 559: dynamic_excp(EXCP_OPCDEC, 0);
1.1.1.2 root 560: }
561:
562: if (exp < 3) {
563: /* Underflow */
564: r.l = 0;
565: } else {
566: r.l = ((exp - 2) << 23) | mant_sig;
567: }
568:
569: return r.f;
1.1 root 570: }
571:
1.1.1.2 root 572: uint32_t helper_f_to_memory (uint64_t a)
1.1 root 573: {
1.1.1.2 root 574: uint32_t r;
575: r = (a & 0x00001fffe0000000ull) >> 13;
576: r |= (a & 0x07ffe00000000000ull) >> 45;
577: r |= (a & 0xc000000000000000ull) >> 48;
578: return r;
1.1 root 579: }
580:
1.1.1.2 root 581: uint64_t helper_memory_to_f (uint32_t a)
1.1 root 582: {
1.1.1.2 root 583: uint64_t r;
584: r = ((uint64_t)(a & 0x0000c000)) << 48;
585: r |= ((uint64_t)(a & 0x003fffff)) << 45;
586: r |= ((uint64_t)(a & 0xffff0000)) << 13;
587: if (!(a & 0x00004000))
588: r |= 0x7ll << 59;
589: return r;
1.1 root 590: }
591:
1.1.1.6 root 592: /* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong. We should
593: either implement VAX arithmetic properly or just signal invalid opcode. */
594:
1.1.1.2 root 595: uint64_t helper_addf (uint64_t a, uint64_t b)
1.1 root 596: {
1.1.1.2 root 597: float32 fa, fb, fr;
1.1 root 598:
1.1.1.2 root 599: fa = f_to_float32(a);
600: fb = f_to_float32(b);
601: fr = float32_add(fa, fb, &FP_STATUS);
602: return float32_to_f(fr);
1.1 root 603: }
604:
1.1.1.2 root 605: uint64_t helper_subf (uint64_t a, uint64_t b)
1.1 root 606: {
1.1.1.2 root 607: float32 fa, fb, fr;
1.1 root 608:
1.1.1.2 root 609: fa = f_to_float32(a);
610: fb = f_to_float32(b);
611: fr = float32_sub(fa, fb, &FP_STATUS);
612: return float32_to_f(fr);
1.1 root 613: }
614:
1.1.1.2 root 615: uint64_t helper_mulf (uint64_t a, uint64_t b)
1.1 root 616: {
1.1.1.2 root 617: float32 fa, fb, fr;
1.1 root 618:
1.1.1.2 root 619: fa = f_to_float32(a);
620: fb = f_to_float32(b);
621: fr = float32_mul(fa, fb, &FP_STATUS);
622: return float32_to_f(fr);
1.1 root 623: }
624:
1.1.1.2 root 625: uint64_t helper_divf (uint64_t a, uint64_t b)
1.1 root 626: {
1.1.1.2 root 627: float32 fa, fb, fr;
1.1 root 628:
1.1.1.2 root 629: fa = f_to_float32(a);
630: fb = f_to_float32(b);
631: fr = float32_div(fa, fb, &FP_STATUS);
632: return float32_to_f(fr);
1.1 root 633: }
634:
1.1.1.2 root 635: uint64_t helper_sqrtf (uint64_t t)
1.1 root 636: {
1.1.1.2 root 637: float32 ft, fr;
1.1 root 638:
1.1.1.2 root 639: ft = f_to_float32(t);
640: fr = float32_sqrt(ft, &FP_STATUS);
641: return float32_to_f(fr);
1.1 root 642: }
643:
1.1.1.2 root 644:
645: /* G floating (VAX) */
1.1.1.4 root 646: static inline uint64_t float64_to_g(float64 fa)
1.1 root 647: {
1.1.1.2 root 648: uint64_t r, exp, mant, sig;
649: CPU_DoubleU a;
650:
651: a.d = fa;
652: sig = a.ll & 0x8000000000000000ull;
653: exp = (a.ll >> 52) & 0x7ff;
654: mant = a.ll & 0x000fffffffffffffull;
655:
656: if (exp == 2047) {
657: /* NaN or infinity */
658: r = 1; /* VAX dirty zero */
659: } else if (exp == 0) {
660: if (mant == 0) {
661: /* Zero */
662: r = 0;
663: } else {
664: /* Denormalized */
665: r = sig | ((exp + 1) << 52) | mant;
666: }
667: } else {
668: if (exp >= 2045) {
669: /* Overflow */
670: r = 1; /* VAX dirty zero */
671: } else {
672: r = sig | ((exp + 2) << 52);
673: }
674: }
1.1 root 675:
1.1.1.2 root 676: return r;
1.1 root 677: }
678:
1.1.1.4 root 679: static inline float64 g_to_float64(uint64_t a)
1.1 root 680: {
1.1.1.2 root 681: uint64_t exp, mant_sig;
682: CPU_DoubleU r;
683:
684: exp = (a >> 52) & 0x7ff;
685: mant_sig = a & 0x800fffffffffffffull;
686:
687: if (!exp && mant_sig) {
688: /* Reserved operands / Dirty zero */
1.1.1.8 root 689: dynamic_excp(EXCP_OPCDEC, 0);
1.1.1.2 root 690: }
1.1 root 691:
1.1.1.2 root 692: if (exp < 3) {
693: /* Underflow */
694: r.ll = 0;
695: } else {
696: r.ll = ((exp - 2) << 52) | mant_sig;
697: }
698:
699: return r.d;
1.1 root 700: }
701:
1.1.1.2 root 702: uint64_t helper_g_to_memory (uint64_t a)
1.1 root 703: {
1.1.1.2 root 704: uint64_t r;
705: r = (a & 0x000000000000ffffull) << 48;
706: r |= (a & 0x00000000ffff0000ull) << 16;
707: r |= (a & 0x0000ffff00000000ull) >> 16;
708: r |= (a & 0xffff000000000000ull) >> 48;
709: return r;
1.1 root 710: }
711:
1.1.1.2 root 712: uint64_t helper_memory_to_g (uint64_t a)
1.1 root 713: {
1.1.1.2 root 714: uint64_t r;
715: r = (a & 0x000000000000ffffull) << 48;
716: r |= (a & 0x00000000ffff0000ull) << 16;
717: r |= (a & 0x0000ffff00000000ull) >> 16;
718: r |= (a & 0xffff000000000000ull) >> 48;
719: return r;
1.1 root 720: }
721:
1.1.1.2 root 722: uint64_t helper_addg (uint64_t a, uint64_t b)
1.1 root 723: {
1.1.1.2 root 724: float64 fa, fb, fr;
1.1 root 725:
1.1.1.2 root 726: fa = g_to_float64(a);
727: fb = g_to_float64(b);
728: fr = float64_add(fa, fb, &FP_STATUS);
729: return float64_to_g(fr);
1.1 root 730: }
731:
1.1.1.2 root 732: uint64_t helper_subg (uint64_t a, uint64_t b)
1.1 root 733: {
1.1.1.2 root 734: float64 fa, fb, fr;
1.1 root 735:
1.1.1.2 root 736: fa = g_to_float64(a);
737: fb = g_to_float64(b);
738: fr = float64_sub(fa, fb, &FP_STATUS);
739: return float64_to_g(fr);
1.1 root 740: }
741:
1.1.1.2 root 742: uint64_t helper_mulg (uint64_t a, uint64_t b)
1.1 root 743: {
1.1.1.2 root 744: float64 fa, fb, fr;
1.1 root 745:
1.1.1.2 root 746: fa = g_to_float64(a);
747: fb = g_to_float64(b);
748: fr = float64_mul(fa, fb, &FP_STATUS);
749: return float64_to_g(fr);
1.1 root 750: }
751:
1.1.1.2 root 752: uint64_t helper_divg (uint64_t a, uint64_t b)
1.1 root 753: {
1.1.1.2 root 754: float64 fa, fb, fr;
1.1 root 755:
1.1.1.2 root 756: fa = g_to_float64(a);
757: fb = g_to_float64(b);
758: fr = float64_div(fa, fb, &FP_STATUS);
759: return float64_to_g(fr);
1.1 root 760: }
761:
1.1.1.2 root 762: uint64_t helper_sqrtg (uint64_t a)
1.1 root 763: {
1.1.1.2 root 764: float64 fa, fr;
1.1 root 765:
1.1.1.2 root 766: fa = g_to_float64(a);
767: fr = float64_sqrt(fa, &FP_STATUS);
768: return float64_to_g(fr);
1.1 root 769: }
770:
1.1.1.2 root 771:
772: /* S floating (single) */
1.1.1.6 root 773:
774: /* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg. */
775: static inline uint64_t float32_to_s_int(uint32_t fi)
776: {
777: uint32_t frac = fi & 0x7fffff;
778: uint32_t sign = fi >> 31;
779: uint32_t exp_msb = (fi >> 30) & 1;
780: uint32_t exp_low = (fi >> 23) & 0x7f;
781: uint32_t exp;
782:
783: exp = (exp_msb << 10) | exp_low;
784: if (exp_msb) {
785: if (exp_low == 0x7f)
786: exp = 0x7ff;
787: } else {
788: if (exp_low != 0x00)
789: exp |= 0x380;
790: }
791:
792: return (((uint64_t)sign << 63)
793: | ((uint64_t)exp << 52)
794: | ((uint64_t)frac << 29));
795: }
796:
1.1.1.4 root 797: static inline uint64_t float32_to_s(float32 fa)
1.1 root 798: {
1.1.1.2 root 799: CPU_FloatU a;
800: a.f = fa;
1.1.1.6 root 801: return float32_to_s_int(a.l);
802: }
1.1 root 803:
1.1.1.6 root 804: static inline uint32_t s_to_float32_int(uint64_t a)
805: {
806: return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
1.1 root 807: }
808:
1.1.1.4 root 809: static inline float32 s_to_float32(uint64_t a)
1.1 root 810: {
1.1.1.2 root 811: CPU_FloatU r;
1.1.1.6 root 812: r.l = s_to_float32_int(a);
1.1.1.2 root 813: return r.f;
814: }
1.1 root 815:
1.1.1.2 root 816: uint32_t helper_s_to_memory (uint64_t a)
817: {
1.1.1.6 root 818: return s_to_float32_int(a);
1.1 root 819: }
820:
1.1.1.2 root 821: uint64_t helper_memory_to_s (uint32_t a)
1.1 root 822: {
1.1.1.6 root 823: return float32_to_s_int(a);
1.1.1.2 root 824: }
1.1 root 825:
1.1.1.2 root 826: uint64_t helper_adds (uint64_t a, uint64_t b)
827: {
828: float32 fa, fb, fr;
1.1 root 829:
1.1.1.2 root 830: fa = s_to_float32(a);
831: fb = s_to_float32(b);
832: fr = float32_add(fa, fb, &FP_STATUS);
833: return float32_to_s(fr);
1.1 root 834: }
835:
1.1.1.2 root 836: uint64_t helper_subs (uint64_t a, uint64_t b)
1.1 root 837: {
1.1.1.2 root 838: float32 fa, fb, fr;
1.1 root 839:
1.1.1.2 root 840: fa = s_to_float32(a);
841: fb = s_to_float32(b);
842: fr = float32_sub(fa, fb, &FP_STATUS);
843: return float32_to_s(fr);
1.1 root 844: }
845:
1.1.1.2 root 846: uint64_t helper_muls (uint64_t a, uint64_t b)
1.1 root 847: {
1.1.1.2 root 848: float32 fa, fb, fr;
1.1 root 849:
1.1.1.2 root 850: fa = s_to_float32(a);
851: fb = s_to_float32(b);
852: fr = float32_mul(fa, fb, &FP_STATUS);
853: return float32_to_s(fr);
1.1 root 854: }
855:
1.1.1.2 root 856: uint64_t helper_divs (uint64_t a, uint64_t b)
1.1 root 857: {
1.1.1.2 root 858: float32 fa, fb, fr;
1.1 root 859:
1.1.1.2 root 860: fa = s_to_float32(a);
861: fb = s_to_float32(b);
862: fr = float32_div(fa, fb, &FP_STATUS);
863: return float32_to_s(fr);
1.1 root 864: }
865:
1.1.1.2 root 866: uint64_t helper_sqrts (uint64_t a)
1.1 root 867: {
1.1.1.2 root 868: float32 fa, fr;
1.1 root 869:
1.1.1.2 root 870: fa = s_to_float32(a);
871: fr = float32_sqrt(fa, &FP_STATUS);
872: return float32_to_s(fr);
1.1 root 873: }
874:
875:
1.1.1.2 root 876: /* T floating (double) */
1.1.1.4 root 877: static inline float64 t_to_float64(uint64_t a)
1.1.1.2 root 878: {
879: /* Memory format is the same as float64 */
880: CPU_DoubleU r;
881: r.ll = a;
882: return r.d;
1.1 root 883: }
884:
1.1.1.4 root 885: static inline uint64_t float64_to_t(float64 fa)
1.1 root 886: {
1.1.1.2 root 887: /* Memory format is the same as float64 */
888: CPU_DoubleU r;
889: r.d = fa;
890: return r.ll;
1.1 root 891: }
892:
1.1.1.2 root 893: uint64_t helper_addt (uint64_t a, uint64_t b)
1.1 root 894: {
1.1.1.2 root 895: float64 fa, fb, fr;
1.1 root 896:
1.1.1.2 root 897: fa = t_to_float64(a);
898: fb = t_to_float64(b);
899: fr = float64_add(fa, fb, &FP_STATUS);
900: return float64_to_t(fr);
1.1 root 901: }
902:
1.1.1.2 root 903: uint64_t helper_subt (uint64_t a, uint64_t b)
1.1 root 904: {
1.1.1.2 root 905: float64 fa, fb, fr;
1.1 root 906:
1.1.1.2 root 907: fa = t_to_float64(a);
908: fb = t_to_float64(b);
909: fr = float64_sub(fa, fb, &FP_STATUS);
910: return float64_to_t(fr);
1.1 root 911: }
912:
1.1.1.2 root 913: uint64_t helper_mult (uint64_t a, uint64_t b)
1.1 root 914: {
1.1.1.2 root 915: float64 fa, fb, fr;
1.1 root 916:
1.1.1.2 root 917: fa = t_to_float64(a);
918: fb = t_to_float64(b);
919: fr = float64_mul(fa, fb, &FP_STATUS);
920: return float64_to_t(fr);
1.1 root 921: }
922:
1.1.1.2 root 923: uint64_t helper_divt (uint64_t a, uint64_t b)
1.1 root 924: {
1.1.1.2 root 925: float64 fa, fb, fr;
1.1 root 926:
1.1.1.2 root 927: fa = t_to_float64(a);
928: fb = t_to_float64(b);
929: fr = float64_div(fa, fb, &FP_STATUS);
930: return float64_to_t(fr);
1.1 root 931: }
932:
1.1.1.2 root 933: uint64_t helper_sqrtt (uint64_t a)
1.1 root 934: {
1.1.1.2 root 935: float64 fa, fr;
1.1 root 936:
1.1.1.2 root 937: fa = t_to_float64(a);
938: fr = float64_sqrt(fa, &FP_STATUS);
939: return float64_to_t(fr);
1.1 root 940: }
941:
1.1.1.2 root 942: /* Comparisons */
943: uint64_t helper_cmptun (uint64_t a, uint64_t b)
1.1 root 944: {
1.1.1.2 root 945: float64 fa, fb;
1.1 root 946:
1.1.1.2 root 947: fa = t_to_float64(a);
948: fb = t_to_float64(b);
949:
1.1.1.8 root 950: if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
1.1.1.2 root 951: return 0x4000000000000000ULL;
1.1.1.8 root 952: } else {
1.1.1.2 root 953: return 0;
1.1.1.8 root 954: }
1.1 root 955: }
956:
1.1.1.2 root 957: uint64_t helper_cmpteq(uint64_t a, uint64_t b)
1.1 root 958: {
1.1.1.2 root 959: float64 fa, fb;
1.1 root 960:
1.1.1.2 root 961: fa = t_to_float64(a);
962: fb = t_to_float64(b);
963:
1.1.1.8 root 964: if (float64_eq_quiet(fa, fb, &FP_STATUS))
1.1.1.2 root 965: return 0x4000000000000000ULL;
966: else
967: return 0;
1.1 root 968: }
969:
1.1.1.2 root 970: uint64_t helper_cmptle(uint64_t a, uint64_t b)
1.1 root 971: {
1.1.1.2 root 972: float64 fa, fb;
1.1 root 973:
1.1.1.2 root 974: fa = t_to_float64(a);
975: fb = t_to_float64(b);
976:
977: if (float64_le(fa, fb, &FP_STATUS))
978: return 0x4000000000000000ULL;
979: else
980: return 0;
1.1 root 981: }
982:
1.1.1.2 root 983: uint64_t helper_cmptlt(uint64_t a, uint64_t b)
1.1 root 984: {
1.1.1.2 root 985: float64 fa, fb;
1.1 root 986:
1.1.1.2 root 987: fa = t_to_float64(a);
988: fb = t_to_float64(b);
989:
990: if (float64_lt(fa, fb, &FP_STATUS))
991: return 0x4000000000000000ULL;
992: else
993: return 0;
1.1 root 994: }
995:
1.1.1.2 root 996: uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
1.1 root 997: {
1.1.1.2 root 998: float64 fa, fb;
999:
1000: fa = g_to_float64(a);
1001: fb = g_to_float64(b);
1.1 root 1002:
1.1.1.8 root 1003: if (float64_eq_quiet(fa, fb, &FP_STATUS))
1.1.1.2 root 1004: return 0x4000000000000000ULL;
1005: else
1006: return 0;
1.1 root 1007: }
1008:
1.1.1.2 root 1009: uint64_t helper_cmpgle(uint64_t a, uint64_t b)
1.1 root 1010: {
1.1.1.2 root 1011: float64 fa, fb;
1.1 root 1012:
1.1.1.2 root 1013: fa = g_to_float64(a);
1014: fb = g_to_float64(b);
1015:
1016: if (float64_le(fa, fb, &FP_STATUS))
1017: return 0x4000000000000000ULL;
1018: else
1019: return 0;
1.1 root 1020: }
1021:
1.1.1.2 root 1022: uint64_t helper_cmpglt(uint64_t a, uint64_t b)
1.1 root 1023: {
1.1.1.2 root 1024: float64 fa, fb;
1025:
1026: fa = g_to_float64(a);
1027: fb = g_to_float64(b);
1.1 root 1028:
1.1.1.2 root 1029: if (float64_lt(fa, fb, &FP_STATUS))
1030: return 0x4000000000000000ULL;
1031: else
1032: return 0;
1.1 root 1033: }
1034:
1.1.1.2 root 1035: /* Floating point format conversion */
1036: uint64_t helper_cvtts (uint64_t a)
1037: {
1038: float64 fa;
1039: float32 fr;
1040:
1041: fa = t_to_float64(a);
1042: fr = float64_to_float32(fa, &FP_STATUS);
1043: return float32_to_s(fr);
1.1 root 1044: }
1045:
1.1.1.2 root 1046: uint64_t helper_cvtst (uint64_t a)
1.1 root 1047: {
1.1.1.2 root 1048: float32 fa;
1049: float64 fr;
1.1 root 1050:
1.1.1.2 root 1051: fa = s_to_float32(a);
1052: fr = float32_to_float64(fa, &FP_STATUS);
1053: return float64_to_t(fr);
1.1 root 1054: }
1055:
1.1.1.2 root 1056: uint64_t helper_cvtqs (uint64_t a)
1.1 root 1057: {
1.1.1.2 root 1058: float32 fr = int64_to_float32(a, &FP_STATUS);
1059: return float32_to_s(fr);
1.1 root 1060: }
1061:
1.1.1.6 root 1062: /* Implement float64 to uint64 conversion without saturation -- we must
1063: supply the truncated result. This behaviour is used by the compiler
1064: to get unsigned conversion for free with the same instruction.
1065:
1066: The VI flag is set when overflow or inexact exceptions should be raised. */
1067:
1068: static inline uint64_t helper_cvttq_internal(uint64_t a, int roundmode, int VI)
1.1 root 1069: {
1.1.1.6 root 1070: uint64_t frac, ret = 0;
1071: uint32_t exp, sign, exc = 0;
1072: int shift;
1073:
1074: sign = (a >> 63);
1075: exp = (uint32_t)(a >> 52) & 0x7ff;
1076: frac = a & 0xfffffffffffffull;
1077:
1078: if (exp == 0) {
1079: if (unlikely(frac != 0)) {
1080: goto do_underflow;
1081: }
1082: } else if (exp == 0x7ff) {
1083: exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
1084: } else {
1085: /* Restore implicit bit. */
1086: frac |= 0x10000000000000ull;
1087:
1088: shift = exp - 1023 - 52;
1089: if (shift >= 0) {
1090: /* In this case the number is so large that we must shift
1091: the fraction left. There is no rounding to do. */
1092: if (shift < 63) {
1093: ret = frac << shift;
1094: if (VI && (ret >> shift) != frac) {
1095: exc = float_flag_overflow;
1096: }
1097: }
1098: } else {
1099: uint64_t round;
1100:
1101: /* In this case the number is smaller than the fraction as
1102: represented by the 52 bit number. Here we must think
1103: about rounding the result. Handle this by shifting the
1104: fractional part of the number into the high bits of ROUND.
1105: This will let us efficiently handle round-to-nearest. */
1106: shift = -shift;
1107: if (shift < 63) {
1108: ret = frac >> shift;
1109: round = frac << (64 - shift);
1110: } else {
1111: /* The exponent is so small we shift out everything.
1112: Leave a sticky bit for proper rounding below. */
1113: do_underflow:
1114: round = 1;
1115: }
1116:
1117: if (round) {
1118: exc = (VI ? float_flag_inexact : 0);
1119: switch (roundmode) {
1120: case float_round_nearest_even:
1121: if (round == (1ull << 63)) {
1122: /* Fraction is exactly 0.5; round to even. */
1123: ret += (ret & 1);
1124: } else if (round > (1ull << 63)) {
1125: ret += 1;
1126: }
1127: break;
1128: case float_round_to_zero:
1129: break;
1130: case float_round_up:
1131: ret += 1 - sign;
1132: break;
1133: case float_round_down:
1134: ret += sign;
1135: break;
1136: }
1137: }
1138: }
1139: if (sign) {
1140: ret = -ret;
1141: }
1142: }
1143: if (unlikely(exc)) {
1144: float_raise(exc, &FP_STATUS);
1145: }
1146:
1147: return ret;
1148: }
1149:
1150: uint64_t helper_cvttq(uint64_t a)
1151: {
1152: return helper_cvttq_internal(a, FP_STATUS.float_rounding_mode, 1);
1153: }
1154:
1155: uint64_t helper_cvttq_c(uint64_t a)
1156: {
1157: return helper_cvttq_internal(a, float_round_to_zero, 0);
1158: }
1159:
1160: uint64_t helper_cvttq_svic(uint64_t a)
1161: {
1162: return helper_cvttq_internal(a, float_round_to_zero, 1);
1.1 root 1163: }
1164:
1.1.1.2 root 1165: uint64_t helper_cvtqt (uint64_t a)
1.1 root 1166: {
1.1.1.2 root 1167: float64 fr = int64_to_float64(a, &FP_STATUS);
1168: return float64_to_t(fr);
1.1 root 1169: }
1170:
1.1.1.2 root 1171: uint64_t helper_cvtqf (uint64_t a)
1.1 root 1172: {
1.1.1.2 root 1173: float32 fr = int64_to_float32(a, &FP_STATUS);
1174: return float32_to_f(fr);
1.1 root 1175: }
1176:
1.1.1.2 root 1177: uint64_t helper_cvtgf (uint64_t a)
1.1 root 1178: {
1.1.1.2 root 1179: float64 fa;
1180: float32 fr;
1181:
1182: fa = g_to_float64(a);
1183: fr = float64_to_float32(fa, &FP_STATUS);
1184: return float32_to_f(fr);
1.1 root 1185: }
1186:
1.1.1.2 root 1187: uint64_t helper_cvtgq (uint64_t a)
1.1 root 1188: {
1.1.1.2 root 1189: float64 fa = g_to_float64(a);
1190: return float64_to_int64_round_to_zero(fa, &FP_STATUS);
1.1 root 1191: }
1192:
1.1.1.2 root 1193: uint64_t helper_cvtqg (uint64_t a)
1.1 root 1194: {
1.1.1.2 root 1195: float64 fr;
1196: fr = int64_to_float64(a, &FP_STATUS);
1197: return float64_to_g(fr);
1.1 root 1198: }
1199:
1.1.1.2 root 1200: /* PALcode support special instructions */
1.1 root 1201: #if !defined (CONFIG_USER_ONLY)
1.1.1.2 root 1202: void helper_hw_ret (uint64_t a)
1203: {
1204: env->pc = a & ~3;
1.1.1.6 root 1205: env->intr_flag = 0;
1206: env->lock_addr = -1;
1.1.1.8 root 1207: if ((a & 1) == 0) {
1208: env->pal_mode = 0;
1209: swap_shadow_regs(env);
1210: }
1.1 root 1211: }
1212:
1.1.1.8 root 1213: void helper_tbia(void)
1.1 root 1214: {
1.1.1.8 root 1215: tlb_flush(env, 1);
1.1 root 1216: }
1217:
1.1.1.8 root 1218: void helper_tbis(uint64_t p)
1.1 root 1219: {
1.1.1.8 root 1220: tlb_flush_page(env, p);
1.1 root 1221: }
1.1.1.9 ! root 1222:
! 1223: void helper_halt(uint64_t restart)
! 1224: {
! 1225: if (restart) {
! 1226: qemu_system_reset_request();
! 1227: } else {
! 1228: qemu_system_shutdown_request();
! 1229: }
! 1230: }
! 1231:
! 1232: uint64_t helper_get_time(void)
! 1233: {
! 1234: return qemu_get_clock_ns(rtc_clock);
! 1235: }
! 1236:
! 1237: void helper_set_alarm(uint64_t expire)
! 1238: {
! 1239: if (expire) {
! 1240: env->alarm_expire = expire;
! 1241: qemu_mod_timer(env->alarm_timer, expire);
! 1242: } else {
! 1243: qemu_del_timer(env->alarm_timer);
! 1244: }
! 1245: }
1.1 root 1246: #endif
1247:
1248: /*****************************************************************************/
1249: /* Softmmu support */
1250: #if !defined (CONFIG_USER_ONLY)
1.1.1.8 root 1251: uint64_t helper_ldl_phys(uint64_t p)
1.1.1.2 root 1252: {
1.1.1.8 root 1253: return (int32_t)ldl_phys(p);
1.1.1.2 root 1254: }
1255:
1.1.1.8 root 1256: uint64_t helper_ldq_phys(uint64_t p)
1.1.1.2 root 1257: {
1.1.1.8 root 1258: return ldq_phys(p);
1.1.1.2 root 1259: }
1260:
1.1.1.8 root 1261: uint64_t helper_ldl_l_phys(uint64_t p)
1.1.1.2 root 1262: {
1.1.1.8 root 1263: env->lock_addr = p;
1264: return env->lock_value = (int32_t)ldl_phys(p);
1.1.1.2 root 1265: }
1266:
1.1.1.8 root 1267: uint64_t helper_ldq_l_phys(uint64_t p)
1.1.1.2 root 1268: {
1.1.1.8 root 1269: env->lock_addr = p;
1270: return env->lock_value = ldl_phys(p);
1.1.1.2 root 1271: }
1272:
1.1.1.8 root 1273: void helper_stl_phys(uint64_t p, uint64_t v)
1.1.1.2 root 1274: {
1.1.1.8 root 1275: stl_phys(p, v);
1.1.1.2 root 1276: }
1277:
1.1.1.8 root 1278: void helper_stq_phys(uint64_t p, uint64_t v)
1.1.1.2 root 1279: {
1.1.1.8 root 1280: stq_phys(p, v);
1.1.1.2 root 1281: }
1282:
1.1.1.8 root 1283: uint64_t helper_stl_c_phys(uint64_t p, uint64_t v)
1.1.1.2 root 1284: {
1.1.1.8 root 1285: uint64_t ret = 0;
1.1.1.2 root 1286:
1.1.1.8 root 1287: if (p == env->lock_addr) {
1288: int32_t old = ldl_phys(p);
1289: if (old == (int32_t)env->lock_value) {
1290: stl_phys(p, v);
1291: ret = 1;
1292: }
1293: }
1294: env->lock_addr = -1;
1.1.1.2 root 1295:
1.1.1.8 root 1296: return ret;
1.1.1.2 root 1297: }
1298:
1.1.1.8 root 1299: uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
1.1.1.2 root 1300: {
1.1.1.8 root 1301: uint64_t ret = 0;
1.1.1.2 root 1302:
1.1.1.8 root 1303: if (p == env->lock_addr) {
1304: uint64_t old = ldq_phys(p);
1305: if (old == env->lock_value) {
1306: stq_phys(p, v);
1307: ret = 1;
1308: }
1309: }
1310: env->lock_addr = -1;
1.1.1.2 root 1311:
1312: return ret;
1313: }
1314:
1.1.1.8 root 1315: static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
1316: int is_user, void *retaddr)
1.1.1.2 root 1317: {
1.1.1.8 root 1318: uint64_t pc;
1319: uint32_t insn;
1.1.1.2 root 1320:
1.1.1.8 root 1321: do_restore_state(retaddr);
1.1.1.2 root 1322:
1.1.1.8 root 1323: pc = env->pc;
1324: insn = ldl_code(pc);
1.1.1.2 root 1325:
1.1.1.8 root 1326: env->trap_arg0 = addr;
1327: env->trap_arg1 = insn >> 26; /* opcode */
1328: env->trap_arg2 = (insn >> 21) & 31; /* dest regno */
1329: helper_excp(EXCP_UNALIGN, 0);
1330: }
1331:
1332: void QEMU_NORETURN cpu_unassigned_access(CPUState *env1,
1333: target_phys_addr_t addr, int is_write,
1334: int is_exec, int unused, int size)
1335: {
1336: env = env1;
1337: env->trap_arg0 = addr;
1338: env->trap_arg1 = is_write;
1339: dynamic_excp(EXCP_MCHK, 0);
1.1 root 1340: }
1341:
1.1.1.9 ! root 1342: #include "softmmu_exec.h"
! 1343:
1.1 root 1344: #define MMUSUFFIX _mmu
1.1.1.8 root 1345: #define ALIGNED_ONLY
1.1 root 1346:
1347: #define SHIFT 0
1348: #include "softmmu_template.h"
1349:
1350: #define SHIFT 1
1351: #include "softmmu_template.h"
1352:
1353: #define SHIFT 2
1354: #include "softmmu_template.h"
1355:
1356: #define SHIFT 3
1357: #include "softmmu_template.h"
1358:
1359: /* try to fill the TLB and return an exception if error. If retaddr is
1360: NULL, it means that the function was called in C code (i.e. not
1361: from generated code or from helper.c) */
1362: /* XXX: fix it to restore all registers */
1.1.1.9 ! root 1363: void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
! 1364: void *retaddr)
1.1 root 1365: {
1366: CPUState *saved_env;
1367: int ret;
1368:
1369: saved_env = env;
1.1.1.9 ! root 1370: env = env1;
! 1371: ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx);
1.1.1.8 root 1372: if (unlikely(ret != 0)) {
1373: do_restore_state(retaddr);
1.1 root 1374: /* Exception index and error code are already set */
1.1.1.8 root 1375: cpu_loop_exit(env);
1.1 root 1376: }
1377: env = saved_env;
1378: }
1379: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.