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