1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "cpu.h"
22#include "memory.h"
23#include "cputlb.h"
24#include "dyngen-exec.h"
25#include "host-utils.h"
26#include "helper.h"
27#include <string.h>
28#include "kvm.h"
29#include "qemu-timer.h"
30#ifdef CONFIG_KVM
31#include <linux/kvm.h>
32#endif
33
34#if !defined (CONFIG_USER_ONLY)
35#include "sysemu.h"
36#endif
37
38
39
40#if !defined (CONFIG_USER_ONLY)
41#include "softmmu_exec.h"
42
43#define MMUSUFFIX _mmu
44
45#define SHIFT 0
46#include "softmmu_template.h"
47
48#define SHIFT 1
49#include "softmmu_template.h"
50
51#define SHIFT 2
52#include "softmmu_template.h"
53
54#define SHIFT 3
55#include "softmmu_template.h"
56
57
58
59
60
61void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
62 uintptr_t retaddr)
63{
64 TranslationBlock *tb;
65 CPUS390XState *saved_env;
66 int ret;
67
68 saved_env = env;
69 env = env1;
70 ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx);
71 if (unlikely(ret != 0)) {
72 if (likely(retaddr)) {
73
74 tb = tb_find_pc(retaddr);
75 if (likely(tb)) {
76
77
78 cpu_restore_state(tb, env, retaddr);
79 }
80 }
81 cpu_loop_exit(env);
82 }
83 env = saved_env;
84}
85
86#endif
87
88
89#ifdef DEBUG_HELPER
90#define HELPER_LOG(x...) qemu_log(x)
91#else
92#define HELPER_LOG(x...)
93#endif
94
95
96void HELPER(exception)(uint32_t excp)
97{
98 HELPER_LOG("%s: exception %d\n", __FUNCTION__, excp);
99 env->exception_index = excp;
100 cpu_loop_exit(env);
101}
102
103#ifndef CONFIG_USER_ONLY
104static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest,
105 uint8_t byte)
106{
107 target_phys_addr_t dest_phys;
108 target_phys_addr_t len = l;
109 void *dest_p;
110 uint64_t asc = env->psw.mask & PSW_MASK_ASC;
111 int flags;
112
113 if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
114 stb(dest, byte);
115 cpu_abort(env, "should never reach here");
116 }
117 dest_phys |= dest & ~TARGET_PAGE_MASK;
118
119 dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
120
121 memset(dest_p, byte, len);
122
123 cpu_physical_memory_unmap(dest_p, 1, len, len);
124}
125
126static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest,
127 uint64_t src)
128{
129 target_phys_addr_t dest_phys;
130 target_phys_addr_t src_phys;
131 target_phys_addr_t len = l;
132 void *dest_p;
133 void *src_p;
134 uint64_t asc = env->psw.mask & PSW_MASK_ASC;
135 int flags;
136
137 if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
138 stb(dest, 0);
139 cpu_abort(env, "should never reach here");
140 }
141 dest_phys |= dest & ~TARGET_PAGE_MASK;
142
143 if (mmu_translate(env, src, 0, asc, &src_phys, &flags)) {
144 ldub(src);
145 cpu_abort(env, "should never reach here");
146 }
147 src_phys |= src & ~TARGET_PAGE_MASK;
148
149 dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
150 src_p = cpu_physical_memory_map(src_phys, &len, 0);
151
152 memmove(dest_p, src_p, len);
153
154 cpu_physical_memory_unmap(dest_p, 1, len, len);
155 cpu_physical_memory_unmap(src_p, 0, len, len);
156}
157#endif
158
159
160uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src)
161{
162 int i;
163 unsigned char x;
164 uint32_t cc = 0;
165
166 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
167 __FUNCTION__, l, dest, src);
168 for (i = 0; i <= l; i++) {
169 x = ldub(dest + i) & ldub(src + i);
170 if (x) {
171 cc = 1;
172 }
173 stb(dest + i, x);
174 }
175 return cc;
176}
177
178
179uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src)
180{
181 int i;
182 unsigned char x;
183 uint32_t cc = 0;
184
185 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
186 __FUNCTION__, l, dest, src);
187
188#ifndef CONFIG_USER_ONLY
189
190 if ((l > 32) && (src == dest) &&
191 (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK)) {
192 mvc_fast_memset(env, l + 1, dest, 0);
193 return 0;
194 }
195#else
196 if (src == dest) {
197 memset(g2h(dest), 0, l + 1);
198 return 0;
199 }
200#endif
201
202 for (i = 0; i <= l; i++) {
203 x = ldub(dest + i) ^ ldub(src + i);
204 if (x) {
205 cc = 1;
206 }
207 stb(dest + i, x);
208 }
209 return cc;
210}
211
212
213uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src)
214{
215 int i;
216 unsigned char x;
217 uint32_t cc = 0;
218
219 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
220 __FUNCTION__, l, dest, src);
221 for (i = 0; i <= l; i++) {
222 x = ldub(dest + i) | ldub(src + i);
223 if (x) {
224 cc = 1;
225 }
226 stb(dest + i, x);
227 }
228 return cc;
229}
230
231
232void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
233{
234 int i = 0;
235 int x = 0;
236 uint32_t l_64 = (l + 1) / 8;
237
238 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
239 __FUNCTION__, l, dest, src);
240
241#ifndef CONFIG_USER_ONLY
242 if ((l > 32) &&
243 (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) &&
244 (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) {
245 if (dest == (src + 1)) {
246 mvc_fast_memset(env, l + 1, dest, ldub(src));
247 return;
248 } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
249 mvc_fast_memmove(env, l + 1, dest, src);
250 return;
251 }
252 }
253#else
254 if (dest == (src + 1)) {
255 memset(g2h(dest), ldub(src), l + 1);
256 return;
257 } else {
258 memmove(g2h(dest), g2h(src), l + 1);
259 return;
260 }
261#endif
262
263
264 if (dest != (src + 1)) {
265 for (i = 0; i < l_64; i++) {
266 stq(dest + x, ldq(src + x));
267 x += 8;
268 }
269 }
270
271
272 for (i = x; i <= l; i++) {
273 stb(dest + i, ldub(src + i));
274 }
275}
276
277
278uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2)
279{
280 int i;
281 unsigned char x,y;
282 uint32_t cc;
283 HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n",
284 __FUNCTION__, l, s1, s2);
285 for (i = 0; i <= l; i++) {
286 x = ldub(s1 + i);
287 y = ldub(s2 + i);
288 HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y);
289 if (x < y) {
290 cc = 1;
291 goto done;
292 } else if (x > y) {
293 cc = 2;
294 goto done;
295 }
296 }
297 cc = 0;
298done:
299 HELPER_LOG("\n");
300 return cc;
301}
302
303
304uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr)
305{
306 uint8_t r,d;
307 uint32_t cc;
308 HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __FUNCTION__, r1,
309 mask, addr);
310 cc = 0;
311 while (mask) {
312 if (mask & 8) {
313 d = ldub(addr);
314 r = (r1 & 0xff000000UL) >> 24;
315 HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d,
316 addr);
317 if (r < d) {
318 cc = 1;
319 break;
320 } else if (r > d) {
321 cc = 2;
322 break;
323 }
324 addr++;
325 }
326 mask = (mask << 1) & 0xf;
327 r1 <<= 8;
328 }
329 HELPER_LOG("\n");
330 return cc;
331}
332
333
334void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr)
335{
336 uint8_t r;
337 HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __FUNCTION__, r1, mask,
338 addr);
339 while (mask) {
340 if (mask & 8) {
341 r = (r1 & 0xff000000UL) >> 24;
342 stb(addr, r);
343 HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr);
344 addr++;
345 }
346 mask = (mask << 1) & 0xf;
347 r1 <<= 8;
348 }
349 HELPER_LOG("\n");
350}
351
352
353void HELPER(mlg)(uint32_t r1, uint64_t v2)
354{
355#if HOST_LONG_BITS == 64 && defined(__GNUC__)
356
357 __uint128_t res = (__uint128_t)env->regs[r1 + 1];
358 res *= (__uint128_t)v2;
359 env->regs[r1] = (uint64_t)(res >> 64);
360 env->regs[r1 + 1] = (uint64_t)res;
361#else
362 mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2);
363#endif
364}
365
366
367void HELPER(dlg)(uint32_t r1, uint64_t v2)
368{
369 uint64_t divisor = v2;
370
371 if (!env->regs[r1]) {
372
373 env->regs[r1] = env->regs[r1+1] % divisor;
374 env->regs[r1+1] = env->regs[r1+1] / divisor;
375 return;
376 } else {
377
378#if HOST_LONG_BITS == 64 && defined(__GNUC__)
379
380 __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) |
381 (env->regs[r1+1]);
382 __uint128_t quotient = dividend / divisor;
383 env->regs[r1+1] = quotient;
384 __uint128_t remainder = dividend % divisor;
385 env->regs[r1] = remainder;
386#else
387
388
389 cpu_abort(env, "128 -> 64/64 division not implemented\n");
390#endif
391 }
392}
393
394static inline uint64_t get_address(int x2, int b2, int d2)
395{
396 uint64_t r = d2;
397
398 if (x2) {
399 r += env->regs[x2];
400 }
401
402 if (b2) {
403 r += env->regs[b2];
404 }
405
406
407 if (!(env->psw.mask & PSW_MASK_64)) {
408 r &= 0x7fffffff;
409 }
410
411 return r;
412}
413
414static inline uint64_t get_address_31fix(int reg)
415{
416 uint64_t r = env->regs[reg];
417
418
419 if (!(env->psw.mask & PSW_MASK_64)) {
420 r &= 0x7fffffff;
421 }
422
423 return r;
424}
425
426
427uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2)
428{
429 uint64_t i;
430 uint32_t cc = 2;
431 uint64_t str = get_address_31fix(r2);
432 uint64_t end = get_address_31fix(r1);
433
434 HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __FUNCTION__,
435 c, env->regs[r1], env->regs[r2]);
436
437 for (i = str; i != end; i++) {
438 if (ldub(i) == c) {
439 env->regs[r1] = i;
440 cc = 1;
441 break;
442 }
443 }
444
445 return cc;
446}
447
448
449uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2)
450{
451 uint64_t s1 = get_address_31fix(r1);
452 uint64_t s2 = get_address_31fix(r2);
453 uint8_t v1, v2;
454 uint32_t cc;
455 c = c & 0xff;
456#ifdef CONFIG_USER_ONLY
457 if (!c) {
458 HELPER_LOG("%s: comparing '%s' and '%s'\n",
459 __FUNCTION__, (char*)g2h(s1), (char*)g2h(s2));
460 }
461#endif
462 for (;;) {
463 v1 = ldub(s1);
464 v2 = ldub(s2);
465 if ((v1 == c || v2 == c) || (v1 != v2)) {
466 break;
467 }
468 s1++;
469 s2++;
470 }
471
472 if (v1 == v2) {
473 cc = 0;
474 } else {
475 cc = (v1 < v2) ? 1 : 2;
476
477 env->regs[r1] = s1;
478 env->regs[r2] = s2;
479 }
480 return cc;
481}
482
483
484void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2)
485{
486
487#ifdef CONFIG_USER_ONLY
488 int i;
489
490 for (i = 0; i < TARGET_PAGE_SIZE; i++) {
491 stb(r1 + i, ldub(r2 + i));
492 }
493#else
494 mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2);
495#endif
496}
497
498
499void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2)
500{
501 uint64_t dest = get_address_31fix(r1);
502 uint64_t src = get_address_31fix(r2);
503 uint8_t v;
504 c = c & 0xff;
505#ifdef CONFIG_USER_ONLY
506 if (!c) {
507 HELPER_LOG("%s: copy '%s' to 0x%lx\n", __FUNCTION__, (char*)g2h(src),
508 dest);
509 }
510#endif
511 for (;;) {
512 v = ldub(src);
513 stb(dest, v);
514 if (v == c) {
515 break;
516 }
517 src++;
518 dest++;
519 }
520 env->regs[r1] = dest;
521}
522
523
524uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3)
525{
526
527 uint32_t cc;
528 uint64_t v2 = ldq(a2);
529 if (env->regs[r1] == v2) {
530 cc = 0;
531 stq(a2, env->regs[r3]);
532 } else {
533 cc = 1;
534 env->regs[r1] = v2;
535 }
536 return cc;
537}
538
539
540uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3)
541{
542
543 uint32_t cc;
544 uint64_t v2_hi = ldq(a2);
545 uint64_t v2_lo = ldq(a2 + 8);
546 uint64_t v1_hi = env->regs[r1];
547 uint64_t v1_lo = env->regs[r1 + 1];
548
549 if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) {
550 cc = 0;
551 stq(a2, env->regs[r3]);
552 stq(a2 + 8, env->regs[r3 + 1]);
553 } else {
554 cc = 1;
555 env->regs[r1] = v2_hi;
556 env->regs[r1 + 1] = v2_lo;
557 }
558
559 return cc;
560}
561
562
563uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3)
564{
565
566 uint32_t cc;
567 HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __FUNCTION__, r1, a2, r3);
568 uint32_t v2 = ldl(a2);
569 if (((uint32_t)env->regs[r1]) == v2) {
570 cc = 0;
571 stl(a2, (uint32_t)env->regs[r3]);
572 } else {
573 cc = 1;
574 env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2;
575 }
576 return cc;
577}
578
579static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask)
580{
581 int pos = 24;
582 uint64_t rmask = 0xff000000ULL;
583 uint8_t val = 0;
584 int ccd = 0;
585 uint32_t cc = 0;
586
587 while (mask) {
588 if (mask & 8) {
589 env->regs[r1] &= ~rmask;
590 val = ldub(address);
591 if ((val & 0x80) && !ccd) {
592 cc = 1;
593 }
594 ccd = 1;
595 if (val && cc == 0) {
596 cc = 2;
597 }
598 env->regs[r1] |= (uint64_t)val << pos;
599 address++;
600 }
601 mask = (mask << 1) & 0xf;
602 pos -= 8;
603 rmask >>= 8;
604 }
605
606 return cc;
607}
608
609
610
611
612
613
614
615
616uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
617{
618 uint16_t insn = lduw_code(addr);
619 HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __FUNCTION__, v1, addr,
620 insn);
621 if ((insn & 0xf0ff) == 0xd000) {
622 uint32_t l, insn2, b1, b2, d1, d2;
623 l = v1 & 0xff;
624 insn2 = ldl_code(addr + 2);
625 b1 = (insn2 >> 28) & 0xf;
626 b2 = (insn2 >> 12) & 0xf;
627 d1 = (insn2 >> 16) & 0xfff;
628 d2 = insn2 & 0xfff;
629 switch (insn & 0xf00) {
630 case 0x200:
631 helper_mvc(l, get_address(0, b1, d1), get_address(0, b2, d2));
632 break;
633 case 0x500:
634 cc = helper_clc(l, get_address(0, b1, d1), get_address(0, b2, d2));
635 break;
636 case 0x700:
637 cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2));
638 break;
639 case 0xc00:
640 helper_tr(l, get_address(0, b1, d1), get_address(0, b2, d2));
641 break;
642 default:
643 goto abort;
644 break;
645 }
646 } else if ((insn & 0xff00) == 0x0a00) {
647
648 HELPER_LOG("%s: svc %ld via execute\n", __FUNCTION__, (insn|v1) & 0xff);
649 env->psw.addr = ret - 4;
650 env->int_svc_code = (insn|v1) & 0xff;
651 env->int_svc_ilc = 4;
652 helper_exception(EXCP_SVC);
653 } else if ((insn & 0xff00) == 0xbf00) {
654 uint32_t insn2, r1, r3, b2, d2;
655 insn2 = ldl_code(addr + 2);
656 r1 = (insn2 >> 20) & 0xf;
657 r3 = (insn2 >> 16) & 0xf;
658 b2 = (insn2 >> 12) & 0xf;
659 d2 = insn2 & 0xfff;
660 cc = helper_icm(r1, get_address(0, b2, d2), r3);
661 } else {
662abort:
663 cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n",
664 insn);
665 }
666 return cc;
667}
668
669
670uint32_t HELPER(abs_i32)(int32_t val)
671{
672 if (val < 0) {
673 return -val;
674 } else {
675 return val;
676 }
677}
678
679
680int32_t HELPER(nabs_i32)(int32_t val)
681{
682 if (val < 0) {
683 return val;
684 } else {
685 return -val;
686 }
687}
688
689
690uint64_t HELPER(abs_i64)(int64_t val)
691{
692 HELPER_LOG("%s: val 0x%" PRIx64 "\n", __FUNCTION__, val);
693
694 if (val < 0) {
695 return -val;
696 } else {
697 return val;
698 }
699}
700
701
702int64_t HELPER(nabs_i64)(int64_t val)
703{
704 if (val < 0) {
705 return val;
706 } else {
707 return -val;
708 }
709}
710
711
712uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
713{
714 uint32_t res;
715
716 res = v1 + v2;
717 if (cc & 2) {
718 res++;
719 }
720
721 return res;
722}
723
724
725void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask)
726{
727 int pos = 56;
728
729 while (mask) {
730 if (mask & 8) {
731 stb(address, (env->regs[r1] >> pos) & 0xff);
732 address++;
733 }
734 mask = (mask << 1) & 0xf;
735 pos -= 8;
736 }
737}
738
739
740
741uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask)
742{
743 int pos = 56;
744 uint64_t rmask = 0xff00000000000000ULL;
745 uint8_t val = 0;
746 int ccd = 0;
747 uint32_t cc = 0;
748
749 while (mask) {
750 if (mask & 8) {
751 env->regs[r1] &= ~rmask;
752 val = ldub(address);
753 if ((val & 0x80) && !ccd) {
754 cc = 1;
755 }
756 ccd = 1;
757 if (val && cc == 0) {
758 cc = 2;
759 }
760 env->regs[r1] |= (uint64_t)val << pos;
761 address++;
762 }
763 mask = (mask << 1) & 0xf;
764 pos -= 8;
765 rmask >>= 8;
766 }
767
768 return cc;
769}
770
771
772void HELPER(ipm)(uint32_t cc, uint32_t r1)
773{
774 uint64_t r = env->regs[r1];
775
776 r &= 0xffffffff00ffffffULL;
777 r |= (cc << 28) | ( (env->psw.mask >> 40) & 0xf );
778 env->regs[r1] = r;
779 HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __FUNCTION__,
780 cc, env->psw.mask, r);
781}
782
783
784void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3)
785{
786 int i;
787
788 for (i = r1;; i = (i + 1) % 16) {
789 env->aregs[i] = ldl(a2);
790 a2 += 4;
791
792 if (i == r3) {
793 break;
794 }
795 }
796}
797
798
799void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3)
800{
801 int i;
802
803 for (i = r1;; i = (i + 1) % 16) {
804 stl(a2, env->aregs[i]);
805 a2 += 4;
806
807 if (i == r3) {
808 break;
809 }
810 }
811}
812
813
814uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2)
815{
816 uint64_t destlen = env->regs[r1 + 1] & 0xffffff;
817 uint64_t dest = get_address_31fix(r1);
818 uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
819 uint64_t src = get_address_31fix(r2);
820 uint8_t pad = src >> 24;
821 uint8_t v;
822 uint32_t cc;
823
824 if (destlen == srclen) {
825 cc = 0;
826 } else if (destlen < srclen) {
827 cc = 1;
828 } else {
829 cc = 2;
830 }
831
832 if (srclen > destlen) {
833 srclen = destlen;
834 }
835
836 for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
837 v = ldub(src);
838 stb(dest, v);
839 }
840
841 for (; destlen; dest++, destlen--) {
842 stb(dest, pad);
843 }
844
845 env->regs[r1 + 1] = destlen;
846
847 env->regs[r2 + 1] -= src - env->regs[r2];
848 env->regs[r1] = dest;
849 env->regs[r2] = src;
850
851 return cc;
852}
853
854
855uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3)
856{
857 uint64_t destlen = env->regs[r1 + 1];
858 uint64_t dest = env->regs[r1];
859 uint64_t srclen = env->regs[r3 + 1];
860 uint64_t src = env->regs[r3];
861 uint8_t pad = a2 & 0xff;
862 uint8_t v;
863 uint32_t cc;
864
865 if (!(env->psw.mask & PSW_MASK_64)) {
866 destlen = (uint32_t)destlen;
867 srclen = (uint32_t)srclen;
868 dest &= 0x7fffffff;
869 src &= 0x7fffffff;
870 }
871
872 if (destlen == srclen) {
873 cc = 0;
874 } else if (destlen < srclen) {
875 cc = 1;
876 } else {
877 cc = 2;
878 }
879
880 if (srclen > destlen) {
881 srclen = destlen;
882 }
883
884 for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
885 v = ldub(src);
886 stb(dest, v);
887 }
888
889 for (; destlen; dest++, destlen--) {
890 stb(dest, pad);
891 }
892
893 env->regs[r1 + 1] = destlen;
894
895
896 env->regs[r3 + 1] -= src - env->regs[r3];
897 env->regs[r1] = dest;
898 env->regs[r3] = src;
899
900 return cc;
901}
902
903
904uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
905{
906 uint64_t destlen = env->regs[r1 + 1];
907 uint64_t dest = get_address_31fix(r1);
908 uint64_t srclen = env->regs[r3 + 1];
909 uint64_t src = get_address_31fix(r3);
910 uint8_t pad = a2 & 0xff;
911 uint8_t v1 = 0,v2 = 0;
912 uint32_t cc = 0;
913
914 if (!(destlen || srclen)) {
915 return cc;
916 }
917
918 if (srclen > destlen) {
919 srclen = destlen;
920 }
921
922 for (; destlen || srclen; src++, dest++, destlen--, srclen--) {
923 v1 = srclen ? ldub(src) : pad;
924 v2 = destlen ? ldub(dest) : pad;
925 if (v1 != v2) {
926 cc = (v1 < v2) ? 1 : 2;
927 break;
928 }
929 }
930
931 env->regs[r1 + 1] = destlen;
932
933 env->regs[r3 + 1] -= src - env->regs[r3];
934 env->regs[r1] = dest;
935 env->regs[r3] = src;
936
937 return cc;
938}
939
940
941uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
942{
943 uint32_t v1 = env->regs[r1];
944 uint32_t res = v1 + (~v2) + (cc >> 1);
945
946 env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res;
947 if (cc & 2) {
948
949 return v1 ? 1 : 0;
950 } else {
951 return v1 ? 3 : 2;
952 }
953}
954
955
956uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
957{
958 uint64_t res = v1 + (~v2) + (cc >> 1);
959
960 env->regs[r1] = res;
961 if (cc & 2) {
962
963 return v1 ? 1 : 0;
964 } else {
965 return v1 ? 3 : 2;
966 }
967}
968
969static inline int float_comp_to_cc(int float_compare)
970{
971 switch (float_compare) {
972 case float_relation_equal:
973 return 0;
974 case float_relation_less:
975 return 1;
976 case float_relation_greater:
977 return 2;
978 case float_relation_unordered:
979 return 3;
980 default:
981 cpu_abort(env, "unknown return value for float compare\n");
982 }
983}
984
985
986static uint32_t set_cc_f32(float32 v1, float32 v2)
987{
988 return float_comp_to_cc(float32_compare_quiet(v1, v2, &env->fpu_status));
989}
990
991static uint32_t set_cc_f64(float64 v1, float64 v2)
992{
993 return float_comp_to_cc(float64_compare_quiet(v1, v2, &env->fpu_status));
994}
995
996
997static uint32_t set_cc_nz_f32(float32 v)
998{
999 if (float32_is_any_nan(v)) {
1000 return 3;
1001 } else if (float32_is_zero(v)) {
1002 return 0;
1003 } else if (float32_is_neg(v)) {
1004 return 1;
1005 } else {
1006 return 2;
1007 }
1008}
1009
1010static uint32_t set_cc_nz_f64(float64 v)
1011{
1012 if (float64_is_any_nan(v)) {
1013 return 3;
1014 } else if (float64_is_zero(v)) {
1015 return 0;
1016 } else if (float64_is_neg(v)) {
1017 return 1;
1018 } else {
1019 return 2;
1020 }
1021}
1022
1023static uint32_t set_cc_nz_f128(float128 v)
1024{
1025 if (float128_is_any_nan(v)) {
1026 return 3;
1027 } else if (float128_is_zero(v)) {
1028 return 0;
1029 } else if (float128_is_neg(v)) {
1030 return 1;
1031 } else {
1032 return 2;
1033 }
1034}
1035
1036
1037void HELPER(cdfbr)(uint32_t f1, int32_t v2)
1038{
1039 HELPER_LOG("%s: converting %d to f%d\n", __FUNCTION__, v2, f1);
1040 env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
1041}
1042
1043
1044void HELPER(cxfbr)(uint32_t f1, int32_t v2)
1045{
1046 CPU_QuadU v1;
1047 v1.q = int32_to_float128(v2, &env->fpu_status);
1048 env->fregs[f1].ll = v1.ll.upper;
1049 env->fregs[f1 + 2].ll = v1.ll.lower;
1050}
1051
1052
1053void HELPER(cegbr)(uint32_t f1, int64_t v2)
1054{
1055 HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1);
1056 env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
1057}
1058
1059
1060void HELPER(cdgbr)(uint32_t f1, int64_t v2)
1061{
1062 HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1);
1063 env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
1064}
1065
1066
1067void HELPER(cxgbr)(uint32_t f1, int64_t v2)
1068{
1069 CPU_QuadU x1;
1070 x1.q = int64_to_float128(v2, &env->fpu_status);
1071 HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __FUNCTION__, v2,
1072 x1.ll.upper, x1.ll.lower);
1073 env->fregs[f1].ll = x1.ll.upper;
1074 env->fregs[f1 + 2].ll = x1.ll.lower;
1075}
1076
1077
1078void HELPER(cefbr)(uint32_t f1, int32_t v2)
1079{
1080 env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
1081 HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __FUNCTION__, v2,
1082 env->fregs[f1].l.upper, f1);
1083}
1084
1085
1086uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2)
1087{
1088 env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
1089 env->fregs[f2].l.upper,
1090 &env->fpu_status);
1091 HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__,
1092 env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
1093
1094 return set_cc_nz_f32(env->fregs[f1].l.upper);
1095}
1096
1097
1098uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2)
1099{
1100 env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
1101 &env->fpu_status);
1102 HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __FUNCTION__,
1103 env->fregs[f2].d, env->fregs[f1].d, f1);
1104
1105 return set_cc_nz_f64(env->fregs[f1].d);
1106}
1107
1108
1109uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2)
1110{
1111 env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
1112 env->fregs[f2].l.upper,
1113 &env->fpu_status);
1114 HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__,
1115 env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
1116
1117 return set_cc_nz_f32(env->fregs[f1].l.upper);
1118}
1119
1120
1121uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2)
1122{
1123 env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
1124 &env->fpu_status);
1125 HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
1126 __FUNCTION__, env->fregs[f2].d, env->fregs[f1].d, f1);
1127
1128 return set_cc_nz_f64(env->fregs[f1].d);
1129}
1130
1131
1132void HELPER(debr)(uint32_t f1, uint32_t f2)
1133{
1134 env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper,
1135 env->fregs[f2].l.upper,
1136 &env->fpu_status);
1137}
1138
1139
1140void HELPER(dxbr)(uint32_t f1, uint32_t f2)
1141{
1142 CPU_QuadU v1;
1143 v1.ll.upper = env->fregs[f1].ll;
1144 v1.ll.lower = env->fregs[f1 + 2].ll;
1145 CPU_QuadU v2;
1146 v2.ll.upper = env->fregs[f2].ll;
1147 v2.ll.lower = env->fregs[f2 + 2].ll;
1148 CPU_QuadU res;
1149 res.q = float128_div(v1.q, v2.q, &env->fpu_status);
1150 env->fregs[f1].ll = res.ll.upper;
1151 env->fregs[f1 + 2].ll = res.ll.lower;
1152}
1153
1154
1155void HELPER(mdbr)(uint32_t f1, uint32_t f2)
1156{
1157 env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d,
1158 &env->fpu_status);
1159}
1160
1161
1162void HELPER(mxbr)(uint32_t f1, uint32_t f2)
1163{
1164 CPU_QuadU v1;
1165 v1.ll.upper = env->fregs[f1].ll;
1166 v1.ll.lower = env->fregs[f1 + 2].ll;
1167 CPU_QuadU v2;
1168 v2.ll.upper = env->fregs[f2].ll;
1169 v2.ll.lower = env->fregs[f2 + 2].ll;
1170 CPU_QuadU res;
1171 res.q = float128_mul(v1.q, v2.q, &env->fpu_status);
1172 env->fregs[f1].ll = res.ll.upper;
1173 env->fregs[f1 + 2].ll = res.ll.lower;
1174}
1175
1176
1177void HELPER(ldebr)(uint32_t r1, uint32_t r2)
1178{
1179 env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
1180 &env->fpu_status);
1181}
1182
1183
1184void HELPER(ldxbr)(uint32_t f1, uint32_t f2)
1185{
1186 CPU_QuadU x2;
1187 x2.ll.upper = env->fregs[f2].ll;
1188 x2.ll.lower = env->fregs[f2 + 2].ll;
1189 env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status);
1190 HELPER_LOG("%s: to 0x%ld\n", __FUNCTION__, env->fregs[f1].d);
1191}
1192
1193
1194void HELPER(lxdbr)(uint32_t f1, uint32_t f2)
1195{
1196 CPU_QuadU res;
1197 res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status);
1198 env->fregs[f1].ll = res.ll.upper;
1199 env->fregs[f1 + 2].ll = res.ll.lower;
1200}
1201
1202
1203void HELPER(ledbr)(uint32_t f1, uint32_t f2)
1204{
1205 float64 d2 = env->fregs[f2].d;
1206 env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
1207}
1208
1209
1210void HELPER(lexbr)(uint32_t f1, uint32_t f2)
1211{
1212 CPU_QuadU x2;
1213 x2.ll.upper = env->fregs[f2].ll;
1214 x2.ll.lower = env->fregs[f2 + 2].ll;
1215 env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status);
1216 HELPER_LOG("%s: to 0x%d\n", __FUNCTION__, env->fregs[f1].l.upper);
1217}
1218
1219
1220uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2)
1221{
1222 float32 v1;
1223 float32 v2 = env->fregs[f2].d;
1224 v1 = float32_abs(v2);
1225 env->fregs[f1].d = v1;
1226 return set_cc_nz_f32(v1);
1227}
1228
1229
1230uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2)
1231{
1232 float64 v1;
1233 float64 v2 = env->fregs[f2].d;
1234 v1 = float64_abs(v2);
1235 env->fregs[f1].d = v1;
1236 return set_cc_nz_f64(v1);
1237}
1238
1239
1240uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2)
1241{
1242 CPU_QuadU v1;
1243 CPU_QuadU v2;
1244 v2.ll.upper = env->fregs[f2].ll;
1245 v2.ll.lower = env->fregs[f2 + 2].ll;
1246 v1.q = float128_abs(v2.q);
1247 env->fregs[f1].ll = v1.ll.upper;
1248 env->fregs[f1 + 2].ll = v1.ll.lower;
1249 return set_cc_nz_f128(v1.q);
1250}
1251
1252
1253uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2)
1254{
1255 env->fregs[f1].d = env->fregs[f2].d;
1256 return set_cc_nz_f64(env->fregs[f1].d);
1257}
1258
1259
1260uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2)
1261{
1262 env->fregs[f1].l.upper = env->fregs[f2].l.upper;
1263 return set_cc_nz_f32(env->fregs[f1].l.upper);
1264}
1265
1266
1267uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2)
1268{
1269 CPU_QuadU x;
1270 x.ll.upper = env->fregs[f2].ll;
1271 x.ll.lower = env->fregs[f2 + 2].ll;
1272 env->fregs[f1].ll = x.ll.upper;
1273 env->fregs[f1 + 2].ll = x.ll.lower;
1274 return set_cc_nz_f128(x.q);
1275}
1276
1277
1278uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2)
1279{
1280 env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
1281
1282 return set_cc_nz_f32(env->fregs[f1].l.upper);
1283}
1284
1285
1286uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2)
1287{
1288 env->fregs[f1].d = float64_chs(env->fregs[f2].d);
1289
1290 return set_cc_nz_f64(env->fregs[f1].d);
1291}
1292
1293
1294uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2)
1295{
1296 CPU_QuadU x1, x2;
1297 x2.ll.upper = env->fregs[f2].ll;
1298 x2.ll.lower = env->fregs[f2 + 2].ll;
1299 x1.q = float128_chs(x2.q);
1300 env->fregs[f1].ll = x1.ll.upper;
1301 env->fregs[f1 + 2].ll = x1.ll.lower;
1302 return set_cc_nz_f128(x1.q);
1303}
1304
1305
1306void HELPER(aeb)(uint32_t f1, uint32_t val)
1307{
1308 float32 v1 = env->fregs[f1].l.upper;
1309 CPU_FloatU v2;
1310 v2.l = val;
1311 HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __FUNCTION__,
1312 v1, f1, v2.f);
1313 env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
1314}
1315
1316
1317void HELPER(deb)(uint32_t f1, uint32_t val)
1318{
1319 float32 v1 = env->fregs[f1].l.upper;
1320 CPU_FloatU v2;
1321 v2.l = val;
1322 HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __FUNCTION__,
1323 v1, f1, v2.f);
1324 env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
1325}
1326
1327
1328void HELPER(meeb)(uint32_t f1, uint32_t val)
1329{
1330 float32 v1 = env->fregs[f1].l.upper;
1331 CPU_FloatU v2;
1332 v2.l = val;
1333 HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __FUNCTION__,
1334 v1, f1, v2.f);
1335 env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
1336}
1337
1338
1339uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2)
1340{
1341 float32 v1 = env->fregs[f1].l.upper;
1342 float32 v2 = env->fregs[f2].l.upper;
1343 HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __FUNCTION__,
1344 v1, f1, v2);
1345 return set_cc_f32(v1, v2);
1346}
1347
1348
1349uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2)
1350{
1351 float64 v1 = env->fregs[f1].d;
1352 float64 v2 = env->fregs[f2].d;
1353 HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __FUNCTION__,
1354 v1, f1, v2);
1355 return set_cc_f64(v1, v2);
1356}
1357
1358
1359uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2)
1360{
1361 CPU_QuadU v1;
1362 v1.ll.upper = env->fregs[f1].ll;
1363 v1.ll.lower = env->fregs[f1 + 2].ll;
1364 CPU_QuadU v2;
1365 v2.ll.upper = env->fregs[f2].ll;
1366 v2.ll.lower = env->fregs[f2 + 2].ll;
1367
1368 return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q,
1369 &env->fpu_status));
1370}
1371
1372
1373uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2)
1374{
1375 float64 v1 = env->fregs[f1].d;
1376 CPU_DoubleU v2;
1377 v2.ll = ldq(a2);
1378 HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __FUNCTION__, v1,
1379 f1, v2.d);
1380 return set_cc_f64(v1, v2.d);
1381}
1382
1383
1384uint32_t HELPER(adb)(uint32_t f1, uint64_t a2)
1385{
1386 float64 v1 = env->fregs[f1].d;
1387 CPU_DoubleU v2;
1388 v2.ll = ldq(a2);
1389 HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __FUNCTION__,
1390 v1, f1, v2.d);
1391 env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
1392 return set_cc_nz_f64(v1);
1393}
1394
1395
1396void HELPER(seb)(uint32_t f1, uint32_t val)
1397{
1398 float32 v1 = env->fregs[f1].l.upper;
1399 CPU_FloatU v2;
1400 v2.l = val;
1401 env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status);
1402}
1403
1404
1405uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2)
1406{
1407 float64 v1 = env->fregs[f1].d;
1408 CPU_DoubleU v2;
1409 v2.ll = ldq(a2);
1410 env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
1411 return set_cc_nz_f64(v1);
1412}
1413
1414
1415void HELPER(mdb)(uint32_t f1, uint64_t a2)
1416{
1417 float64 v1 = env->fregs[f1].d;
1418 CPU_DoubleU v2;
1419 v2.ll = ldq(a2);
1420 HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __FUNCTION__,
1421 v1, f1, v2.d);
1422 env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
1423}
1424
1425
1426void HELPER(ddb)(uint32_t f1, uint64_t a2)
1427{
1428 float64 v1 = env->fregs[f1].d;
1429 CPU_DoubleU v2;
1430 v2.ll = ldq(a2);
1431 HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __FUNCTION__,
1432 v1, f1, v2.d);
1433 env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
1434}
1435
1436static void set_round_mode(int m3)
1437{
1438 switch (m3) {
1439 case 0:
1440
1441 break;
1442 case 1:
1443
1444 case 4:
1445
1446 set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
1447 break;
1448 case 5:
1449
1450 set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
1451 break;
1452 case 6:
1453
1454 set_float_rounding_mode(float_round_up, &env->fpu_status);
1455 break;
1456 case 7:
1457
1458 set_float_rounding_mode(float_round_down, &env->fpu_status);
1459 break;
1460 }
1461}
1462
1463
1464uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3)
1465{
1466 float32 v2 = env->fregs[f2].l.upper;
1467 set_round_mode(m3);
1468 env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
1469 return set_cc_nz_f32(v2);
1470}
1471
1472
1473uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1474{
1475 float64 v2 = env->fregs[f2].d;
1476 set_round_mode(m3);
1477 env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
1478 return set_cc_nz_f64(v2);
1479}
1480
1481
1482uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1483{
1484 CPU_QuadU v2;
1485 v2.ll.upper = env->fregs[f2].ll;
1486 v2.ll.lower = env->fregs[f2 + 2].ll;
1487 set_round_mode(m3);
1488 env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
1489 if (float128_is_any_nan(v2.q)) {
1490 return 3;
1491 } else if (float128_is_zero(v2.q)) {
1492 return 0;
1493 } else if (float128_is_neg(v2.q)) {
1494 return 1;
1495 } else {
1496 return 2;
1497 }
1498}
1499
1500
1501uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3)
1502{
1503 float32 v2 = env->fregs[f2].l.upper;
1504 set_round_mode(m3);
1505 env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
1506 float32_to_int32(v2, &env->fpu_status);
1507 return set_cc_nz_f32(v2);
1508}
1509
1510
1511uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1512{
1513 float64 v2 = env->fregs[f2].d;
1514 set_round_mode(m3);
1515 env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
1516 float64_to_int32(v2, &env->fpu_status);
1517 return set_cc_nz_f64(v2);
1518}
1519
1520
1521uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1522{
1523 CPU_QuadU v2;
1524 v2.ll.upper = env->fregs[f2].ll;
1525 v2.ll.lower = env->fregs[f2 + 2].ll;
1526 env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
1527 float128_to_int32(v2.q, &env->fpu_status);
1528 return set_cc_nz_f128(v2.q);
1529}
1530
1531
1532void HELPER(lzer)(uint32_t f1)
1533{
1534 env->fregs[f1].l.upper = float32_zero;
1535}
1536
1537
1538void HELPER(lzdr)(uint32_t f1)
1539{
1540 env->fregs[f1].d = float64_zero;
1541}
1542
1543
1544void HELPER(lzxr)(uint32_t f1)
1545{
1546 CPU_QuadU x;
1547 x.q = float64_to_float128(float64_zero, &env->fpu_status);
1548 env->fregs[f1].ll = x.ll.upper;
1549 env->fregs[f1 + 1].ll = x.ll.lower;
1550}
1551
1552
1553uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2)
1554{
1555 CPU_QuadU v1;
1556 v1.ll.upper = env->fregs[f1].ll;
1557 v1.ll.lower = env->fregs[f1 + 2].ll;
1558 CPU_QuadU v2;
1559 v2.ll.upper = env->fregs[f2].ll;
1560 v2.ll.lower = env->fregs[f2 + 2].ll;
1561 CPU_QuadU res;
1562 res.q = float128_sub(v1.q, v2.q, &env->fpu_status);
1563 env->fregs[f1].ll = res.ll.upper;
1564 env->fregs[f1 + 2].ll = res.ll.lower;
1565 return set_cc_nz_f128(res.q);
1566}
1567
1568
1569uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2)
1570{
1571 CPU_QuadU v1;
1572 v1.ll.upper = env->fregs[f1].ll;
1573 v1.ll.lower = env->fregs[f1 + 2].ll;
1574 CPU_QuadU v2;
1575 v2.ll.upper = env->fregs[f2].ll;
1576 v2.ll.lower = env->fregs[f2 + 2].ll;
1577 CPU_QuadU res;
1578 res.q = float128_add(v1.q, v2.q, &env->fpu_status);
1579 env->fregs[f1].ll = res.ll.upper;
1580 env->fregs[f1 + 2].ll = res.ll.lower;
1581 return set_cc_nz_f128(res.q);
1582}
1583
1584
1585void HELPER(meebr)(uint32_t f1, uint32_t f2)
1586{
1587 env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper,
1588 env->fregs[f2].l.upper,
1589 &env->fpu_status);
1590}
1591
1592
1593void HELPER(ddbr)(uint32_t f1, uint32_t f2)
1594{
1595 env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d,
1596 &env->fpu_status);
1597}
1598
1599
1600void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3)
1601{
1602 HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __FUNCTION__, f1, a2, f3);
1603 CPU_DoubleU v2;
1604 v2.ll = ldq(a2);
1605 env->fregs[f1].d = float64_add(env->fregs[f1].d,
1606 float64_mul(v2.d, env->fregs[f3].d,
1607 &env->fpu_status),
1608 &env->fpu_status);
1609}
1610
1611
1612void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2)
1613{
1614 HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3);
1615 env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d,
1616 env->fregs[f3].d,
1617 &env->fpu_status),
1618 env->fregs[f1].d, &env->fpu_status);
1619}
1620
1621
1622void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2)
1623{
1624 HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3);
1625 env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d,
1626 env->fregs[f3].d,
1627 &env->fpu_status),
1628 env->fregs[f1].d, &env->fpu_status);
1629}
1630
1631
1632void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
1633{
1634 env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
1635 float32_mul(env->fregs[f2].l.upper,
1636 env->fregs[f3].l.upper,
1637 &env->fpu_status),
1638 &env->fpu_status);
1639}
1640
1641
1642void HELPER(ldeb)(uint32_t f1, uint64_t a2)
1643{
1644 uint32_t v2;
1645 v2 = ldl(a2);
1646 env->fregs[f1].d = float32_to_float64(v2,
1647 &env->fpu_status);
1648}
1649
1650
1651void HELPER(lxdb)(uint32_t f1, uint64_t a2)
1652{
1653 CPU_DoubleU v2;
1654 v2.ll = ldq(a2);
1655 CPU_QuadU v1;
1656 v1.q = float64_to_float128(v2.d, &env->fpu_status);
1657 env->fregs[f1].ll = v1.ll.upper;
1658 env->fregs[f1 + 2].ll = v1.ll.lower;
1659}
1660
1661
1662uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2)
1663{
1664 float32 v1 = env->fregs[f1].l.upper;
1665 int neg = float32_is_neg(v1);
1666 uint32_t cc = 0;
1667
1668 HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, (long)v1, m2, neg);
1669 if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
1670 (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
1671 (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
1672 (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
1673 cc = 1;
1674 } else if (m2 & (1 << (9-neg))) {
1675
1676 cc = 1;
1677 }
1678
1679
1680 return cc;
1681}
1682
1683
1684uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2)
1685{
1686 float64 v1 = env->fregs[f1].d;
1687 int neg = float64_is_neg(v1);
1688 uint32_t cc = 0;
1689
1690 HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, v1, m2, neg);
1691 if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
1692 (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
1693 (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
1694 (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
1695 cc = 1;
1696 } else if (m2 & (1 << (9-neg))) {
1697
1698 cc = 1;
1699 }
1700
1701 return cc;
1702}
1703
1704
1705uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2)
1706{
1707 CPU_QuadU v1;
1708 uint32_t cc = 0;
1709 v1.ll.upper = env->fregs[f1].ll;
1710 v1.ll.lower = env->fregs[f1 + 2].ll;
1711
1712 int neg = float128_is_neg(v1.q);
1713 if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
1714 (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
1715 (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
1716 (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) {
1717 cc = 1;
1718 } else if (m2 & (1 << (9-neg))) {
1719
1720 cc = 1;
1721 }
1722
1723 return cc;
1724}
1725
1726
1727uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
1728{
1729 uint64_t res = 0;
1730 uint64_t ov2 = v2;
1731
1732 while (!(v2 & 0x8000000000000000ULL) && v2) {
1733 v2 <<= 1;
1734 res++;
1735 }
1736
1737 if (!v2) {
1738 env->regs[r1] = 64;
1739 env->regs[r1 + 1] = 0;
1740 return 0;
1741 } else {
1742 env->regs[r1] = res;
1743 env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res);
1744 return 2;
1745 }
1746}
1747
1748
1749void HELPER(sqdbr)(uint32_t f1, uint32_t f2)
1750{
1751 env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
1752}
1753
1754
1755void HELPER(cksm)(uint32_t r1, uint32_t r2)
1756{
1757 uint64_t src = get_address_31fix(r2);
1758 uint64_t src_len = env->regs[(r2 + 1) & 15];
1759 uint64_t cksm = (uint32_t)env->regs[r1];
1760
1761 while (src_len >= 4) {
1762 cksm += ldl(src);
1763
1764
1765 src_len -= 4;
1766 src += 4;
1767 }
1768
1769 switch (src_len) {
1770 case 0:
1771 break;
1772 case 1:
1773 cksm += ldub(src) << 24;
1774 break;
1775 case 2:
1776 cksm += lduw(src) << 16;
1777 break;
1778 case 3:
1779 cksm += lduw(src) << 16;
1780 cksm += ldub(src + 2) << 8;
1781 break;
1782 }
1783
1784
1785 env->regs[r2] = src + src_len;
1786 env->regs[(r2 + 1) & 15] = 0;
1787
1788
1789 env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
1790 ((uint32_t)cksm + (cksm >> 32));
1791}
1792
1793static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
1794 int32_t dst)
1795{
1796 if (src == dst) {
1797 return 0;
1798 } else if (src < dst) {
1799 return 1;
1800 } else {
1801 return 2;
1802 }
1803}
1804
1805static inline uint32_t cc_calc_ltgt0_32(CPUS390XState *env, int32_t dst)
1806{
1807 return cc_calc_ltgt_32(env, dst, 0);
1808}
1809
1810static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src,
1811 int64_t dst)
1812{
1813 if (src == dst) {
1814 return 0;
1815 } else if (src < dst) {
1816 return 1;
1817 } else {
1818 return 2;
1819 }
1820}
1821
1822static inline uint32_t cc_calc_ltgt0_64(CPUS390XState *env, int64_t dst)
1823{
1824 return cc_calc_ltgt_64(env, dst, 0);
1825}
1826
1827static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src,
1828 uint32_t dst)
1829{
1830 if (src == dst) {
1831 return 0;
1832 } else if (src < dst) {
1833 return 1;
1834 } else {
1835 return 2;
1836 }
1837}
1838
1839static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
1840 uint64_t dst)
1841{
1842 if (src == dst) {
1843 return 0;
1844 } else if (src < dst) {
1845 return 1;
1846 } else {
1847 return 2;
1848 }
1849}
1850
1851static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask)
1852{
1853 HELPER_LOG("%s: val 0x%x mask 0x%x\n", __FUNCTION__, val, mask);
1854 uint16_t r = val & mask;
1855 if (r == 0 || mask == 0) {
1856 return 0;
1857 } else if (r == mask) {
1858 return 3;
1859 } else {
1860 return 1;
1861 }
1862}
1863
1864
1865static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint32_t mask)
1866{
1867 uint16_t r = val & mask;
1868 HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __FUNCTION__, val, mask, r);
1869 if (r == 0 || mask == 0) {
1870 return 0;
1871 } else if (r == mask) {
1872 return 3;
1873 } else {
1874 while (!(mask & 0x8000)) {
1875 mask <<= 1;
1876 val <<= 1;
1877 }
1878 if (val & 0x8000) {
1879 return 2;
1880 } else {
1881 return 1;
1882 }
1883 }
1884}
1885
1886static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst)
1887{
1888 return !!dst;
1889}
1890
1891static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1, int64_t a2,
1892 int64_t ar)
1893{
1894 if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
1895 return 3;
1896 } else {
1897 if (ar < 0) {
1898 return 1;
1899 } else if (ar > 0) {
1900 return 2;
1901 } else {
1902 return 0;
1903 }
1904 }
1905}
1906
1907static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1, uint64_t a2,
1908 uint64_t ar)
1909{
1910 if (ar == 0) {
1911 if (a1) {
1912 return 2;
1913 } else {
1914 return 0;
1915 }
1916 } else {
1917 if (ar < a1 || ar < a2) {
1918 return 3;
1919 } else {
1920 return 1;
1921 }
1922 }
1923}
1924
1925static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1, int64_t a2,
1926 int64_t ar)
1927{
1928 if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
1929 return 3;
1930 } else {
1931 if (ar < 0) {
1932 return 1;
1933 } else if (ar > 0) {
1934 return 2;
1935 } else {
1936 return 0;
1937 }
1938 }
1939}
1940
1941static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1, uint64_t a2,
1942 uint64_t ar)
1943{
1944 if (ar == 0) {
1945 return 2;
1946 } else {
1947 if (a2 > a1) {
1948 return 1;
1949 } else {
1950 return 3;
1951 }
1952 }
1953}
1954
1955static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
1956{
1957 if ((uint64_t)dst == 0x8000000000000000ULL) {
1958 return 3;
1959 } else if (dst) {
1960 return 1;
1961 } else {
1962 return 0;
1963 }
1964}
1965
1966static inline uint32_t cc_calc_nabs_64(CPUS390XState *env, int64_t dst)
1967{
1968 return !!dst;
1969}
1970
1971static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
1972{
1973 if ((uint64_t)dst == 0x8000000000000000ULL) {
1974 return 3;
1975 } else if (dst < 0) {
1976 return 1;
1977 } else if (dst > 0) {
1978 return 2;
1979 } else {
1980 return 0;
1981 }
1982}
1983
1984
1985static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1, int32_t a2,
1986 int32_t ar)
1987{
1988 if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
1989 return 3;
1990 } else {
1991 if (ar < 0) {
1992 return 1;
1993 } else if (ar > 0) {
1994 return 2;
1995 } else {
1996 return 0;
1997 }
1998 }
1999}
2000
2001static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1, uint32_t a2,
2002 uint32_t ar)
2003{
2004 if (ar == 0) {
2005 if (a1) {
2006 return 2;
2007 } else {
2008 return 0;
2009 }
2010 } else {
2011 if (ar < a1 || ar < a2) {
2012 return 3;
2013 } else {
2014 return 1;
2015 }
2016 }
2017}
2018
2019static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1, int32_t a2,
2020 int32_t ar)
2021{
2022 if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
2023 return 3;
2024 } else {
2025 if (ar < 0) {
2026 return 1;
2027 } else if (ar > 0) {
2028 return 2;
2029 } else {
2030 return 0;
2031 }
2032 }
2033}
2034
2035static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1, uint32_t a2,
2036 uint32_t ar)
2037{
2038 if (ar == 0) {
2039 return 2;
2040 } else {
2041 if (a2 > a1) {
2042 return 1;
2043 } else {
2044 return 3;
2045 }
2046 }
2047}
2048
2049static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
2050{
2051 if ((uint32_t)dst == 0x80000000UL) {
2052 return 3;
2053 } else if (dst) {
2054 return 1;
2055 } else {
2056 return 0;
2057 }
2058}
2059
2060static inline uint32_t cc_calc_nabs_32(CPUS390XState *env, int32_t dst)
2061{
2062 return !!dst;
2063}
2064
2065static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
2066{
2067 if ((uint32_t)dst == 0x80000000UL) {
2068 return 3;
2069 } else if (dst < 0) {
2070 return 1;
2071 } else if (dst > 0) {
2072 return 2;
2073 } else {
2074 return 0;
2075 }
2076}
2077
2078
2079static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask, uint32_t val)
2080{
2081 HELPER_LOG("%s: mask 0x%x val %d\n", __FUNCTION__, mask, val);
2082 uint32_t cc;
2083
2084 if (mask == 0xf) {
2085 if (!val) {
2086 return 0;
2087 } else if (val & 0x80000000) {
2088 return 1;
2089 } else {
2090 return 2;
2091 }
2092 }
2093
2094 if (!val || !mask) {
2095 cc = 0;
2096 } else {
2097 while (mask != 1) {
2098 mask >>= 1;
2099 val >>= 8;
2100 }
2101 if (val & 0x80) {
2102 cc = 1;
2103 } else {
2104 cc = 2;
2105 }
2106 }
2107 return cc;
2108}
2109
2110static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src, uint64_t shift)
2111{
2112 uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
2113 uint64_t match, r;
2114
2115
2116 if (src & (1ULL << 63)) {
2117 match = mask;
2118 } else {
2119 match = 0;
2120 }
2121
2122 if ((src & mask) != match) {
2123
2124 return 3;
2125 }
2126
2127 r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63));
2128
2129 if ((int64_t)r == 0) {
2130 return 0;
2131 } else if ((int64_t)r < 0) {
2132 return 1;
2133 }
2134
2135 return 2;
2136}
2137
2138
2139static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src,
2140 uint64_t dst, uint64_t vr)
2141{
2142 uint32_t r = 0;
2143
2144 switch (cc_op) {
2145 case CC_OP_CONST0:
2146 case CC_OP_CONST1:
2147 case CC_OP_CONST2:
2148 case CC_OP_CONST3:
2149
2150 r = cc_op;
2151 break;
2152 case CC_OP_LTGT0_32:
2153 r = cc_calc_ltgt0_32(env, dst);
2154 break;
2155 case CC_OP_LTGT0_64:
2156 r = cc_calc_ltgt0_64(env, dst);
2157 break;
2158 case CC_OP_LTGT_32:
2159 r = cc_calc_ltgt_32(env, src, dst);
2160 break;
2161 case CC_OP_LTGT_64:
2162 r = cc_calc_ltgt_64(env, src, dst);
2163 break;
2164 case CC_OP_LTUGTU_32:
2165 r = cc_calc_ltugtu_32(env, src, dst);
2166 break;
2167 case CC_OP_LTUGTU_64:
2168 r = cc_calc_ltugtu_64(env, src, dst);
2169 break;
2170 case CC_OP_TM_32:
2171 r = cc_calc_tm_32(env, src, dst);
2172 break;
2173 case CC_OP_TM_64:
2174 r = cc_calc_tm_64(env, src, dst);
2175 break;
2176 case CC_OP_NZ:
2177 r = cc_calc_nz(env, dst);
2178 break;
2179 case CC_OP_ADD_64:
2180 r = cc_calc_add_64(env, src, dst, vr);
2181 break;
2182 case CC_OP_ADDU_64:
2183 r = cc_calc_addu_64(env, src, dst, vr);
2184 break;
2185 case CC_OP_SUB_64:
2186 r = cc_calc_sub_64(env, src, dst, vr);
2187 break;
2188 case CC_OP_SUBU_64:
2189 r = cc_calc_subu_64(env, src, dst, vr);
2190 break;
2191 case CC_OP_ABS_64:
2192 r = cc_calc_abs_64(env, dst);
2193 break;
2194 case CC_OP_NABS_64:
2195 r = cc_calc_nabs_64(env, dst);
2196 break;
2197 case CC_OP_COMP_64:
2198 r = cc_calc_comp_64(env, dst);
2199 break;
2200
2201 case CC_OP_ADD_32:
2202 r = cc_calc_add_32(env, src, dst, vr);
2203 break;
2204 case CC_OP_ADDU_32:
2205 r = cc_calc_addu_32(env, src, dst, vr);
2206 break;
2207 case CC_OP_SUB_32:
2208 r = cc_calc_sub_32(env, src, dst, vr);
2209 break;
2210 case CC_OP_SUBU_32:
2211 r = cc_calc_subu_32(env, src, dst, vr);
2212 break;
2213 case CC_OP_ABS_32:
2214 r = cc_calc_abs_64(env, dst);
2215 break;
2216 case CC_OP_NABS_32:
2217 r = cc_calc_nabs_64(env, dst);
2218 break;
2219 case CC_OP_COMP_32:
2220 r = cc_calc_comp_32(env, dst);
2221 break;
2222
2223 case CC_OP_ICM:
2224 r = cc_calc_icm_32(env, src, dst);
2225 break;
2226 case CC_OP_SLAG:
2227 r = cc_calc_slag(env, src, dst);
2228 break;
2229
2230 case CC_OP_LTGT_F32:
2231 r = set_cc_f32(src, dst);
2232 break;
2233 case CC_OP_LTGT_F64:
2234 r = set_cc_f64(src, dst);
2235 break;
2236 case CC_OP_NZ_F32:
2237 r = set_cc_nz_f32(dst);
2238 break;
2239 case CC_OP_NZ_F64:
2240 r = set_cc_nz_f64(dst);
2241 break;
2242
2243 default:
2244 cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op));
2245 }
2246
2247 HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __FUNCTION__,
2248 cc_name(cc_op), src, dst, vr, r);
2249 return r;
2250}
2251
2252uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
2253 uint64_t vr)
2254{
2255 return do_calc_cc(env, cc_op, src, dst, vr);
2256}
2257
2258uint32_t HELPER(calc_cc)(uint32_t cc_op, uint64_t src, uint64_t dst,
2259 uint64_t vr)
2260{
2261 return do_calc_cc(env, cc_op, src, dst, vr);
2262}
2263
2264uint64_t HELPER(cvd)(int32_t bin)
2265{
2266
2267 uint64_t dec = 0x0c;
2268 int shift = 4;
2269
2270 if (bin < 0) {
2271 bin = -bin;
2272 dec = 0x0d;
2273 }
2274
2275 for (shift = 4; (shift < 64) && bin; shift += 4) {
2276 int current_number = bin % 10;
2277
2278 dec |= (current_number) << shift;
2279 bin /= 10;
2280 }
2281
2282 return dec;
2283}
2284
2285void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
2286{
2287 int len_dest = len >> 4;
2288 int len_src = len & 0xf;
2289 uint8_t b;
2290 int second_nibble = 0;
2291
2292 dest += len_dest;
2293 src += len_src;
2294
2295
2296 b = ldub(src);
2297 stb(dest, (b << 4) | (b >> 4));
2298 src--;
2299 len_src--;
2300
2301
2302
2303 while (len_dest > 0) {
2304 uint8_t cur_byte = 0;
2305
2306 if (len_src > 0) {
2307 cur_byte = ldub(src);
2308 }
2309
2310 len_dest--;
2311 dest--;
2312
2313
2314 if (second_nibble) {
2315 cur_byte >>= 4;
2316 len_src--;
2317 src--;
2318 }
2319 second_nibble = !second_nibble;
2320
2321
2322 cur_byte = (cur_byte & 0xf);
2323
2324 cur_byte |= 0xf0;
2325
2326 stb(dest, cur_byte);
2327 }
2328}
2329
2330void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans)
2331{
2332 int i;
2333
2334 for (i = 0; i <= len; i++) {
2335 uint8_t byte = ldub(array + i);
2336 uint8_t new_byte = ldub(trans + byte);
2337 stb(array + i, new_byte);
2338 }
2339}
2340
2341#ifndef CONFIG_USER_ONLY
2342
2343void HELPER(load_psw)(uint64_t mask, uint64_t addr)
2344{
2345 load_psw(env, mask, addr);
2346 cpu_loop_exit(env);
2347}
2348
2349static void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
2350{
2351 qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
2352
2353 if (kvm_enabled()) {
2354#ifdef CONFIG_KVM
2355 kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
2356#endif
2357 } else {
2358 env->int_pgm_code = code;
2359 env->int_pgm_ilc = ilc;
2360 env->exception_index = EXCP_PGM;
2361 cpu_loop_exit(env);
2362 }
2363}
2364
2365
2366
2367
2368int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
2369{
2370 int r = 0;
2371 int shift = 0;
2372
2373#ifdef DEBUG_HELPER
2374 printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code);
2375#endif
2376
2377
2378 if (!memory_region_is_ram(phys_page_find(sccb >> TARGET_PAGE_BITS)->mr)) {
2379 return -PGM_ADDRESSING;
2380 }
2381 if (sccb & ~0x7ffffff8ul) {
2382 return -PGM_SPECIFICATION;
2383 }
2384
2385 switch(code) {
2386 case SCLP_CMDW_READ_SCP_INFO:
2387 case SCLP_CMDW_READ_SCP_INFO_FORCED:
2388 while ((ram_size >> (20 + shift)) > 65535) {
2389 shift++;
2390 }
2391 stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift));
2392 stb_phys(sccb + SCP_INCREMENT, 1 << shift);
2393 stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
2394
2395 s390_sclp_extint(sccb & ~3);
2396 break;
2397 default:
2398#ifdef DEBUG_HELPER
2399 printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
2400#endif
2401 r = 3;
2402 break;
2403 }
2404
2405 return r;
2406}
2407
2408
2409uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
2410{
2411 int r;
2412
2413 r = sclp_service_call(env, r1, r2);
2414 if (r < 0) {
2415 program_interrupt(env, -r, 4);
2416 return 0;
2417 }
2418 return r;
2419}
2420
2421
2422uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
2423{
2424 uint64_t r;
2425
2426 switch (num) {
2427 case 0x500:
2428
2429 r = s390_virtio_hypercall(env, mem, code);
2430 break;
2431 case 0x44:
2432
2433 r = 0;
2434 break;
2435 case 0x308:
2436
2437 r = 0;
2438 break;
2439 default:
2440 r = -1;
2441 break;
2442 }
2443
2444 if (r) {
2445 program_interrupt(env, PGM_OPERATION, ILC_LATER_INC);
2446 }
2447
2448 return r;
2449}
2450
2451
2452void HELPER(stidp)(uint64_t a1)
2453{
2454 stq(a1, env->cpu_num);
2455}
2456
2457
2458void HELPER(spx)(uint64_t a1)
2459{
2460 uint32_t prefix;
2461
2462 prefix = ldl(a1);
2463 env->psa = prefix & 0xfffff000;
2464 qemu_log("prefix: %#x\n", prefix);
2465 tlb_flush_page(env, 0);
2466 tlb_flush_page(env, TARGET_PAGE_SIZE);
2467}
2468
2469
2470uint32_t HELPER(sck)(uint64_t a1)
2471{
2472
2473
2474 return 0;
2475}
2476
2477static inline uint64_t clock_value(CPUS390XState *env)
2478{
2479 uint64_t time;
2480
2481 time = env->tod_offset +
2482 time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
2483
2484 return time;
2485}
2486
2487
2488uint32_t HELPER(stck)(uint64_t a1)
2489{
2490 stq(a1, clock_value(env));
2491
2492 return 0;
2493}
2494
2495
2496uint32_t HELPER(stcke)(uint64_t a1)
2497{
2498 stb(a1, 0);
2499
2500 stq(a1 + 1, clock_value(env) | env->cpu_num);
2501
2502 stq(a1 + 9, 0);
2503
2504 stw(a1 + 17, 0);
2505
2506
2507 return 0;
2508}
2509
2510
2511void HELPER(sckc)(uint64_t a1)
2512{
2513 uint64_t time = ldq(a1);
2514
2515 if (time == -1ULL) {
2516 return;
2517 }
2518
2519
2520 time -= clock_value(env);
2521
2522 time = (time * 125) >> 9;
2523
2524 qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
2525}
2526
2527
2528void HELPER(stckc)(uint64_t a1)
2529{
2530
2531 stq(a1, 0);
2532}
2533
2534
2535void HELPER(spt)(uint64_t a1)
2536{
2537 uint64_t time = ldq(a1);
2538
2539 if (time == -1ULL) {
2540 return;
2541 }
2542
2543
2544 time = (time * 125) >> 9;
2545
2546 qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
2547}
2548
2549
2550void HELPER(stpt)(uint64_t a1)
2551{
2552
2553 stq(a1, 0);
2554}
2555
2556
2557uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
2558{
2559 int cc = 0;
2560 int sel1, sel2;
2561
2562 if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
2563 ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
2564
2565 program_interrupt(env, PGM_SPECIFICATION, 2);
2566 }
2567
2568 sel1 = r0 & STSI_R0_SEL1_MASK;
2569 sel2 = r1 & STSI_R1_SEL2_MASK;
2570
2571
2572
2573 switch (r0 & STSI_LEVEL_MASK) {
2574 case STSI_LEVEL_1:
2575 if ((sel1 == 1) && (sel2 == 1)) {
2576
2577 struct sysib_111 sysib;
2578
2579 memset(&sysib, 0, sizeof(sysib));
2580 ebcdic_put(sysib.manuf, "QEMU ", 16);
2581
2582 ebcdic_put(sysib.type, "QEMU", 4);
2583
2584 ebcdic_put(sysib.model, "QEMU ", 16);
2585 ebcdic_put(sysib.sequence, "QEMU ", 16);
2586 ebcdic_put(sysib.plant, "QEMU", 4);
2587 cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2588 } else if ((sel1 == 2) && (sel2 == 1)) {
2589
2590 struct sysib_121 sysib;
2591
2592 memset(&sysib, 0, sizeof(sysib));
2593
2594 ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
2595 ebcdic_put(sysib.plant, "QEMU", 4);
2596 stw_p(&sysib.cpu_addr, env->cpu_num);
2597 cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2598 } else if ((sel1 == 2) && (sel2 == 2)) {
2599
2600 struct sysib_122 sysib;
2601
2602 memset(&sysib, 0, sizeof(sysib));
2603 stl_p(&sysib.capability, 0x443afc29);
2604
2605 stw_p(&sysib.total_cpus, 1);
2606 stw_p(&sysib.active_cpus, 1);
2607 stw_p(&sysib.standby_cpus, 0);
2608 stw_p(&sysib.reserved_cpus, 0);
2609 cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2610 } else {
2611 cc = 3;
2612 }
2613 break;
2614 case STSI_LEVEL_2:
2615 {
2616 if ((sel1 == 2) && (sel2 == 1)) {
2617
2618 struct sysib_221 sysib;
2619
2620 memset(&sysib, 0, sizeof(sysib));
2621
2622 ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
2623 ebcdic_put(sysib.plant, "QEMU", 4);
2624 stw_p(&sysib.cpu_addr, env->cpu_num);
2625 stw_p(&sysib.cpu_id, 0);
2626 cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2627 } else if ((sel1 == 2) && (sel2 == 2)) {
2628
2629 struct sysib_222 sysib;
2630
2631 memset(&sysib, 0, sizeof(sysib));
2632 stw_p(&sysib.lpar_num, 0);
2633 sysib.lcpuc = 0;
2634
2635 stw_p(&sysib.total_cpus, 1);
2636 stw_p(&sysib.conf_cpus, 1);
2637 stw_p(&sysib.standby_cpus, 0);
2638 stw_p(&sysib.reserved_cpus, 0);
2639 ebcdic_put(sysib.name, "QEMU ", 8);
2640 stl_p(&sysib.caf, 1000);
2641 stw_p(&sysib.dedicated_cpus, 0);
2642 stw_p(&sysib.shared_cpus, 0);
2643 cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2644 } else {
2645 cc = 3;
2646 }
2647 break;
2648 }
2649 case STSI_LEVEL_3:
2650 {
2651 if ((sel1 == 2) && (sel2 == 2)) {
2652
2653 struct sysib_322 sysib;
2654
2655 memset(&sysib, 0, sizeof(sysib));
2656 sysib.count = 1;
2657
2658 stw_p(&sysib.vm[0].total_cpus, 1);
2659 stw_p(&sysib.vm[0].conf_cpus, 1);
2660 stw_p(&sysib.vm[0].standby_cpus, 0);
2661 stw_p(&sysib.vm[0].reserved_cpus, 0);
2662 ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
2663 stl_p(&sysib.vm[0].caf, 1000);
2664 ebcdic_put(sysib.vm[0].cpi, "KVM/Linux ", 16);
2665 cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2666 } else {
2667 cc = 3;
2668 }
2669 break;
2670 }
2671 case STSI_LEVEL_CURRENT:
2672 env->regs[0] = STSI_LEVEL_3;
2673 break;
2674 default:
2675 cc = 3;
2676 break;
2677 }
2678
2679 return cc;
2680}
2681
2682void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3)
2683{
2684 int i;
2685 uint64_t src = a2;
2686
2687 for (i = r1;; i = (i + 1) % 16) {
2688 env->cregs[i] = ldq(src);
2689 HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
2690 i, src, env->cregs[i]);
2691 src += sizeof(uint64_t);
2692
2693 if (i == r3) {
2694 break;
2695 }
2696 }
2697
2698 tlb_flush(env, 1);
2699}
2700
2701void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3)
2702{
2703 int i;
2704 uint64_t src = a2;
2705
2706 for (i = r1;; i = (i + 1) % 16) {
2707 env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | ldl(src);
2708 src += sizeof(uint32_t);
2709
2710 if (i == r3) {
2711 break;
2712 }
2713 }
2714
2715 tlb_flush(env, 1);
2716}
2717
2718void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3)
2719{
2720 int i;
2721 uint64_t dest = a2;
2722
2723 for (i = r1;; i = (i + 1) % 16) {
2724 stq(dest, env->cregs[i]);
2725 dest += sizeof(uint64_t);
2726
2727 if (i == r3) {
2728 break;
2729 }
2730 }
2731}
2732
2733void HELPER(stctl)(uint32_t r1, uint64_t a2, uint32_t r3)
2734{
2735 int i;
2736 uint64_t dest = a2;
2737
2738 for (i = r1;; i = (i + 1) % 16) {
2739 stl(dest, env->cregs[i]);
2740 dest += sizeof(uint32_t);
2741
2742 if (i == r3) {
2743 break;
2744 }
2745 }
2746}
2747
2748uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
2749{
2750
2751
2752 return 0;
2753}
2754
2755
2756uint64_t HELPER(iske)(uint64_t r2)
2757{
2758 uint64_t addr = get_address(0, 0, r2);
2759
2760 if (addr > ram_size) {
2761 return 0;
2762 }
2763
2764 return env->storage_keys[addr / TARGET_PAGE_SIZE];
2765}
2766
2767
2768void HELPER(sske)(uint32_t r1, uint64_t r2)
2769{
2770 uint64_t addr = get_address(0, 0, r2);
2771
2772 if (addr > ram_size) {
2773 return;
2774 }
2775
2776 env->storage_keys[addr / TARGET_PAGE_SIZE] = r1;
2777}
2778
2779
2780uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
2781{
2782 uint8_t re;
2783 uint8_t key;
2784 if (r2 > ram_size) {
2785 return 0;
2786 }
2787
2788 key = env->storage_keys[r2 / TARGET_PAGE_SIZE];
2789 re = key & (SK_R | SK_C);
2790 env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R);
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801 return re >> 1;
2802}
2803
2804
2805uint32_t HELPER(csp)(uint32_t r1, uint32_t r2)
2806{
2807 uint32_t cc;
2808 uint32_t o1 = env->regs[r1];
2809 uint64_t a2 = get_address_31fix(r2) & ~3ULL;
2810 uint32_t o2 = ldl(a2);
2811
2812 if (o1 == o2) {
2813 stl(a2, env->regs[(r1 + 1) & 15]);
2814 if (env->regs[r2] & 0x3) {
2815
2816 tlb_flush(env, 1);
2817 }
2818 cc = 0;
2819 } else {
2820 env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | o2;
2821 cc = 1;
2822 }
2823
2824 return cc;
2825}
2826
2827static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
2828 uint64_t mode2)
2829{
2830 target_ulong src, dest;
2831 int flags, cc = 0, i;
2832
2833 if (!l) {
2834 return 0;
2835 } else if (l > 256) {
2836
2837 l = 256;
2838 cc = 3;
2839 }
2840
2841 if (mmu_translate(env, a1 & TARGET_PAGE_MASK, 1, mode1, &dest, &flags)) {
2842 cpu_loop_exit(env);
2843 }
2844 dest |= a1 & ~TARGET_PAGE_MASK;
2845
2846 if (mmu_translate(env, a2 & TARGET_PAGE_MASK, 0, mode2, &src, &flags)) {
2847 cpu_loop_exit(env);
2848 }
2849 src |= a2 & ~TARGET_PAGE_MASK;
2850
2851
2852 for (i = 0; i < l; i++) {
2853
2854 if ((((dest + i) & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) ||
2855 (((src + i) & TARGET_PAGE_MASK) != (src & TARGET_PAGE_MASK))) {
2856 mvc_asc(l - i, a1 + i, mode1, a2 + i, mode2);
2857 break;
2858 }
2859 stb_phys(dest + i, ldub_phys(src + i));
2860 }
2861
2862 return cc;
2863}
2864
2865uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2)
2866{
2867 HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
2868 __FUNCTION__, l, a1, a2);
2869
2870 return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
2871}
2872
2873uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2)
2874{
2875 HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
2876 __FUNCTION__, l, a1, a2);
2877
2878 return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY);
2879}
2880
2881uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
2882{
2883 int cc = 0;
2884
2885 HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
2886 __FUNCTION__, order_code, r1, cpu_addr);
2887
2888
2889
2890
2891 switch (order_code) {
2892 case SIGP_SET_ARCH:
2893
2894 break;
2895 case SIGP_SENSE:
2896
2897 if (cpu_addr) {
2898
2899 return 3;
2900 }
2901 env->regs[r1] &= 0xffffffff00000000ULL;
2902 cc = 1;
2903 break;
2904#if !defined (CONFIG_USER_ONLY)
2905 case SIGP_RESTART:
2906 qemu_system_reset_request();
2907 cpu_loop_exit(env);
2908 break;
2909 case SIGP_STOP:
2910 qemu_system_shutdown_request();
2911 cpu_loop_exit(env);
2912 break;
2913#endif
2914 default:
2915
2916 fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
2917 cc = 3;
2918 }
2919
2920 return cc;
2921}
2922
2923void HELPER(sacf)(uint64_t a1)
2924{
2925 HELPER_LOG("%s: %16" PRIx64 "\n", __FUNCTION__, a1);
2926
2927 switch (a1 & 0xf00) {
2928 case 0x000:
2929 env->psw.mask &= ~PSW_MASK_ASC;
2930 env->psw.mask |= PSW_ASC_PRIMARY;
2931 break;
2932 case 0x100:
2933 env->psw.mask &= ~PSW_MASK_ASC;
2934 env->psw.mask |= PSW_ASC_SECONDARY;
2935 break;
2936 case 0x300:
2937 env->psw.mask &= ~PSW_MASK_ASC;
2938 env->psw.mask |= PSW_ASC_HOME;
2939 break;
2940 default:
2941 qemu_log("unknown sacf mode: %" PRIx64 "\n", a1);
2942 program_interrupt(env, PGM_SPECIFICATION, 2);
2943 break;
2944 }
2945}
2946
2947
2948void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
2949{
2950 uint64_t page = vaddr & TARGET_PAGE_MASK;
2951 uint64_t pte = 0;
2952
2953
2954
2955
2956
2957
2958
2959 stq_phys(pte_addr, pte | _PAGE_INVALID);
2960
2961
2962
2963 tlb_flush_page(env, page);
2964
2965
2966 if (page & 0x80000000) {
2967 tlb_flush_page(env, page & ~0x80000000);
2968 } else {
2969 tlb_flush_page(env, page | 0x80000000);
2970 }
2971}
2972
2973
2974void HELPER(ptlb)(void)
2975{
2976 tlb_flush(env, 1);
2977}
2978
2979
2980void HELPER(stura)(uint64_t addr, uint32_t v1)
2981{
2982 stw_phys(get_address(0, 0, addr), v1);
2983}
2984
2985
2986uint32_t HELPER(lra)(uint64_t addr, uint32_t r1)
2987{
2988 uint32_t cc = 0;
2989 int old_exc = env->exception_index;
2990 uint64_t asc = env->psw.mask & PSW_MASK_ASC;
2991 uint64_t ret;
2992 int flags;
2993
2994
2995 if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) {
2996 program_interrupt(env, PGM_SPECIAL_OP, 2);
2997 }
2998
2999 env->exception_index = old_exc;
3000 if (mmu_translate(env, addr, 0, asc, &ret, &flags)) {
3001 cc = 3;
3002 }
3003 if (env->exception_index == EXCP_PGM) {
3004 ret = env->int_pgm_code | 0x80000000;
3005 } else {
3006 ret |= addr & ~TARGET_PAGE_MASK;
3007 }
3008 env->exception_index = old_exc;
3009
3010 if (!(env->psw.mask & PSW_MASK_64)) {
3011 env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (ret & 0xffffffffULL);
3012 } else {
3013 env->regs[r1] = ret;
3014 }
3015
3016 return cc;
3017}
3018
3019#endif
3020