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