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