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