Statistics
| Branch: | Revision:

root / target-s390x / op_helper.c @ 20503968

History | View | Annotate | Download (74.6 kB)

1
/*
2
 *  S/390 helper routines
3
 *
4
 *  Copyright (c) 2009 Ulrich Hecht
5
 *  Copyright (c) 2009 Alexander Graf
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19
 */
20

    
21
#include "cpu.h"
22
#include "dyngen-exec.h"
23
#include "host-utils.h"
24
#include "helper.h"
25
#include <string.h>
26
#include "kvm.h"
27
#include "qemu-timer.h"
28
#ifdef CONFIG_KVM
29
#include <linux/kvm.h>
30
#endif
31

    
32
#if !defined (CONFIG_USER_ONLY)
33
#include "sysemu.h"
34
#endif
35

    
36
/*****************************************************************************/
37
/* Softmmu support */
38
#if !defined (CONFIG_USER_ONLY)
39
#include "softmmu_exec.h"
40

    
41
#define MMUSUFFIX _mmu
42

    
43
#define SHIFT 0
44
#include "softmmu_template.h"
45

    
46
#define SHIFT 1
47
#include "softmmu_template.h"
48

    
49
#define SHIFT 2
50
#include "softmmu_template.h"
51

    
52
#define SHIFT 3
53
#include "softmmu_template.h"
54

    
55
/* try to fill the TLB and return an exception if error. If retaddr is
56
   NULL, it means that the function was called in C code (i.e. not
57
   from generated code or from helper.c) */
58
/* XXX: fix it to restore all registers */
59
void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
60
              uintptr_t retaddr)
61
{
62
    TranslationBlock *tb;
63
    CPUS390XState *saved_env;
64
    int ret;
65

    
66
    saved_env = env;
67
    env = env1;
68
    ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx);
69
    if (unlikely(ret != 0)) {
70
        if (likely(retaddr)) {
71
            /* now we have a real cpu fault */
72
            tb = tb_find_pc(retaddr);
73
            if (likely(tb)) {
74
                /* the PC is inside the translated code. It means that we have
75
                   a virtual CPU fault */
76
                cpu_restore_state(tb, env, retaddr);
77
            }
78
        }
79
        cpu_loop_exit(env);
80
    }
81
    env = saved_env;
82
}
83

    
84
#endif
85

    
86
/* #define DEBUG_HELPER */
87
#ifdef DEBUG_HELPER
88
#define HELPER_LOG(x...) qemu_log(x)
89
#else
90
#define HELPER_LOG(x...)
91
#endif
92

    
93
/* raise an exception */
94
void HELPER(exception)(uint32_t excp)
95
{
96
    HELPER_LOG("%s: exception %d\n", __FUNCTION__, excp);
97
    env->exception_index = excp;
98
    cpu_loop_exit(env);
99
}
100

    
101
#ifndef CONFIG_USER_ONLY
102
static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest,
103
                            uint8_t byte)
104
{
105
    target_phys_addr_t dest_phys;
106
    target_phys_addr_t len = l;
107
    void *dest_p;
108
    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
109
    int flags;
110

    
111
    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
112
        stb(dest, byte);
113
        cpu_abort(env, "should never reach here");
114
    }
115
    dest_phys |= dest & ~TARGET_PAGE_MASK;
116

    
117
    dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
118

    
119
    memset(dest_p, byte, len);
120

    
121
    cpu_physical_memory_unmap(dest_p, 1, len, len);
122
}
123

    
124
static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest,
125
                             uint64_t src)
126
{
127
    target_phys_addr_t dest_phys;
128
    target_phys_addr_t src_phys;
129
    target_phys_addr_t len = l;
130
    void *dest_p;
131
    void *src_p;
132
    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
133
    int flags;
134

    
135
    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
136
        stb(dest, 0);
137
        cpu_abort(env, "should never reach here");
138
    }
139
    dest_phys |= dest & ~TARGET_PAGE_MASK;
140

    
141
    if (mmu_translate(env, src, 0, asc, &src_phys, &flags)) {
142
        ldub(src);
143
        cpu_abort(env, "should never reach here");
144
    }
145
    src_phys |= src & ~TARGET_PAGE_MASK;
146

    
147
    dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
148
    src_p = cpu_physical_memory_map(src_phys, &len, 0);
149

    
150
    memmove(dest_p, src_p, len);
151

    
152
    cpu_physical_memory_unmap(dest_p, 1, len, len);
153
    cpu_physical_memory_unmap(src_p, 0, len, len);
154
}
155
#endif
156

    
157
/* and on array */
158
uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src)
159
{
160
    int i;
161
    unsigned char x;
162
    uint32_t cc = 0;
163

    
164
    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
165
               __FUNCTION__, l, dest, src);
166
    for (i = 0; i <= l; i++) {
167
        x = ldub(dest + i) & ldub(src + i);
168
        if (x) {
169
            cc = 1;
170
        }
171
        stb(dest + i, x);
172
    }
173
    return cc;
174
}
175

    
176
/* xor on array */
177
uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src)
178
{
179
    int i;
180
    unsigned char x;
181
    uint32_t cc = 0;
182

    
183
    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
184
               __FUNCTION__, l, dest, src);
185

    
186
#ifndef CONFIG_USER_ONLY
187
    /* xor with itself is the same as memset(0) */
188
    if ((l > 32) && (src == dest) &&
189
        (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK)) {
190
        mvc_fast_memset(env, l + 1, dest, 0);
191
        return 0;
192
    }
193
#else
194
    if (src == dest) {
195
        memset(g2h(dest), 0, l + 1);
196
        return 0;
197
    }
198
#endif
199

    
200
    for (i = 0; i <= l; i++) {
201
        x = ldub(dest + i) ^ ldub(src + i);
202
        if (x) {
203
            cc = 1;
204
        }
205
        stb(dest + i, x);
206
    }
207
    return cc;
208
}
209

    
210
/* or on array */
211
uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src)
212
{
213
    int i;
214
    unsigned char x;
215
    uint32_t cc = 0;
216

    
217
    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
218
               __FUNCTION__, l, dest, src);
219
    for (i = 0; i <= l; i++) {
220
        x = ldub(dest + i) | ldub(src + i);
221
        if (x) {
222
            cc = 1;
223
        }
224
        stb(dest + i, x);
225
    }
226
    return cc;
227
}
228

    
229
/* memmove */
230
void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
231
{
232
    int i = 0;
233
    int x = 0;
234
    uint32_t l_64 = (l + 1) / 8;
235

    
236
    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
237
               __FUNCTION__, l, dest, src);
238

    
239
#ifndef CONFIG_USER_ONLY
240
    if ((l > 32) &&
241
        (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) &&
242
        (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) {
243
        if (dest == (src + 1)) {
244
            mvc_fast_memset(env, l + 1, dest, ldub(src));
245
            return;
246
        } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
247
            mvc_fast_memmove(env, l + 1, dest, src);
248
            return;
249
        }
250
    }
251
#else
252
    if (dest == (src + 1)) {
253
        memset(g2h(dest), ldub(src), l + 1);
254
        return;
255
    } else {
256
        memmove(g2h(dest), g2h(src), l + 1);
257
        return;
258
    }
259
#endif
260

    
261
    /* handle the parts that fit into 8-byte loads/stores */
262
    if (dest != (src + 1)) {
263
        for (i = 0; i < l_64; i++) {
264
            stq(dest + x, ldq(src + x));
265
            x += 8;
266
        }
267
    }
268

    
269
    /* slow version crossing pages with byte accesses */
270
    for (i = x; i <= l; i++) {
271
        stb(dest + i, ldub(src + i));
272
    }
273
}
274

    
275
/* compare unsigned byte arrays */
276
uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2)
277
{
278
    int i;
279
    unsigned char x,y;
280
    uint32_t cc;
281
    HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n",
282
               __FUNCTION__, l, s1, s2);
283
    for (i = 0; i <= l; i++) {
284
        x = ldub(s1 + i);
285
        y = ldub(s2 + i);
286
        HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y);
287
        if (x < y) {
288
            cc = 1;
289
            goto done;
290
        } else if (x > y) {
291
            cc = 2;
292
            goto done;
293
        }
294
    }
295
    cc = 0;
296
done:
297
    HELPER_LOG("\n");
298
    return cc;
299
}
300

    
301
/* compare logical under mask */
302
uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr)
303
{
304
    uint8_t r,d;
305
    uint32_t cc;
306
    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __FUNCTION__, r1,
307
               mask, addr);
308
    cc = 0;
309
    while (mask) {
310
        if (mask & 8) {
311
            d = ldub(addr);
312
            r = (r1 & 0xff000000UL) >> 24;
313
            HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d,
314
                        addr);
315
            if (r < d) {
316
                cc = 1;
317
                break;
318
            } else if (r > d) {
319
                cc = 2;
320
                break;
321
            }
322
            addr++;
323
        }
324
        mask = (mask << 1) & 0xf;
325
        r1 <<= 8;
326
    }
327
    HELPER_LOG("\n");
328
    return cc;
329
}
330

    
331
/* store character under mask */
332
void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr)
333
{
334
    uint8_t r;
335
    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __FUNCTION__, r1, mask,
336
               addr);
337
    while (mask) {
338
        if (mask & 8) {
339
            r = (r1 & 0xff000000UL) >> 24;
340
            stb(addr, r);
341
            HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr);
342
            addr++;
343
        }
344
        mask = (mask << 1) & 0xf;
345
        r1 <<= 8;
346
    }
347
    HELPER_LOG("\n");
348
}
349

    
350
/* 64/64 -> 128 unsigned multiplication */
351
void HELPER(mlg)(uint32_t r1, uint64_t v2)
352
{
353
#if HOST_LONG_BITS == 64 && defined(__GNUC__)
354
    /* assuming 64-bit hosts have __uint128_t */
355
    __uint128_t res = (__uint128_t)env->regs[r1 + 1];
356
    res *= (__uint128_t)v2;
357
    env->regs[r1] = (uint64_t)(res >> 64);
358
    env->regs[r1 + 1] = (uint64_t)res;
359
#else
360
    mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2);
361
#endif
362
}
363

    
364
/* 128 -> 64/64 unsigned division */
365
void HELPER(dlg)(uint32_t r1, uint64_t v2)
366
{
367
    uint64_t divisor = v2;
368

    
369
    if (!env->regs[r1]) {
370
        /* 64 -> 64/64 case */
371
        env->regs[r1] = env->regs[r1+1] % divisor;
372
        env->regs[r1+1] = env->regs[r1+1] / divisor;
373
        return;
374
    } else {
375

    
376
#if HOST_LONG_BITS == 64 && defined(__GNUC__)
377
        /* assuming 64-bit hosts have __uint128_t */
378
        __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) |
379
                               (env->regs[r1+1]);
380
        __uint128_t quotient = dividend / divisor;
381
        env->regs[r1+1] = quotient;
382
        __uint128_t remainder = dividend % divisor;
383
        env->regs[r1] = remainder;
384
#else
385
        /* 32-bit hosts would need special wrapper functionality - just abort if
386
           we encounter such a case; it's very unlikely anyways. */
387
        cpu_abort(env, "128 -> 64/64 division not implemented\n");
388
#endif
389
    }
390
}
391

    
392
static inline uint64_t get_address(int x2, int b2, int d2)
393
{
394
    uint64_t r = d2;
395

    
396
    if (x2) {
397
        r += env->regs[x2];
398
    }
399

    
400
    if (b2) {
401
        r += env->regs[b2];
402
    }
403

    
404
    /* 31-Bit mode */
405
    if (!(env->psw.mask & PSW_MASK_64)) {
406
        r &= 0x7fffffff;
407
    }
408

    
409
    return r;
410
}
411

    
412
static inline uint64_t get_address_31fix(int reg)
413
{
414
    uint64_t r = env->regs[reg];
415

    
416
    /* 31-Bit mode */
417
    if (!(env->psw.mask & PSW_MASK_64)) {
418
        r &= 0x7fffffff;
419
    }
420

    
421
    return r;
422
}
423

    
424
/* search string (c is byte to search, r2 is string, r1 end of string) */
425
uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2)
426
{
427
    uint64_t i;
428
    uint32_t cc = 2;
429
    uint64_t str = get_address_31fix(r2);
430
    uint64_t end = get_address_31fix(r1);
431

    
432
    HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __FUNCTION__,
433
               c, env->regs[r1], env->regs[r2]);
434

    
435
    for (i = str; i != end; i++) {
436
        if (ldub(i) == c) {
437
            env->regs[r1] = i;
438
            cc = 1;
439
            break;
440
        }
441
    }
442

    
443
    return cc;
444
}
445

    
446
/* unsigned string compare (c is string terminator) */
447
uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2)
448
{
449
    uint64_t s1 = get_address_31fix(r1);
450
    uint64_t s2 = get_address_31fix(r2);
451
    uint8_t v1, v2;
452
    uint32_t cc;
453
    c = c & 0xff;
454
#ifdef CONFIG_USER_ONLY
455
    if (!c) {
456
        HELPER_LOG("%s: comparing '%s' and '%s'\n",
457
                   __FUNCTION__, (char*)g2h(s1), (char*)g2h(s2));
458
    }
459
#endif
460
    for (;;) {
461
        v1 = ldub(s1);
462
        v2 = ldub(s2);
463
        if ((v1 == c || v2 == c) || (v1 != v2)) {
464
            break;
465
        }
466
        s1++;
467
        s2++;
468
    }
469

    
470
    if (v1 == v2) {
471
        cc = 0;
472
    } else {
473
        cc = (v1 < v2) ? 1 : 2;
474
        /* FIXME: 31-bit mode! */
475
        env->regs[r1] = s1;
476
        env->regs[r2] = s2;
477
    }
478
    return cc;
479
}
480

    
481
/* move page */
482
void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2)
483
{
484
    /* XXX missing r0 handling */
485
#ifdef CONFIG_USER_ONLY
486
    int i;
487

    
488
    for (i = 0; i < TARGET_PAGE_SIZE; i++) {
489
        stb(r1 + i, ldub(r2 + i));
490
    }
491
#else
492
    mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2);
493
#endif
494
}
495

    
496
/* string copy (c is string terminator) */
497
void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2)
498
{
499
    uint64_t dest = get_address_31fix(r1);
500
    uint64_t src = get_address_31fix(r2);
501
    uint8_t v;
502
    c = c & 0xff;
503
#ifdef CONFIG_USER_ONLY
504
    if (!c) {
505
        HELPER_LOG("%s: copy '%s' to 0x%lx\n", __FUNCTION__, (char*)g2h(src),
506
                   dest);
507
    }
508
#endif
509
    for (;;) {
510
        v = ldub(src);
511
        stb(dest, v);
512
        if (v == c) {
513
            break;
514
        }
515
        src++;
516
        dest++;
517
    }
518
    env->regs[r1] = dest; /* FIXME: 31-bit mode! */
519
}
520

    
521
/* compare and swap 64-bit */
522
uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3)
523
{
524
    /* FIXME: locking? */
525
    uint32_t cc;
526
    uint64_t v2 = ldq(a2);
527
    if (env->regs[r1] == v2) {
528
        cc = 0;
529
        stq(a2, env->regs[r3]);
530
    } else {
531
        cc = 1;
532
        env->regs[r1] = v2;
533
    }
534
    return cc;
535
}
536

    
537
/* compare double and swap 64-bit */
538
uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3)
539
{
540
    /* FIXME: locking? */
541
    uint32_t cc;
542
    uint64_t v2_hi = ldq(a2);
543
    uint64_t v2_lo = ldq(a2 + 8);
544
    uint64_t v1_hi = env->regs[r1];
545
    uint64_t v1_lo = env->regs[r1 + 1];
546

    
547
    if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) {
548
        cc = 0;
549
        stq(a2, env->regs[r3]);
550
        stq(a2 + 8, env->regs[r3 + 1]);
551
    } else {
552
        cc = 1;
553
        env->regs[r1] = v2_hi;
554
        env->regs[r1 + 1] = v2_lo;
555
    }
556

    
557
    return cc;
558
}
559

    
560
/* compare and swap 32-bit */
561
uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3)
562
{
563
    /* FIXME: locking? */
564
    uint32_t cc;
565
    HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __FUNCTION__, r1, a2, r3);
566
    uint32_t v2 = ldl(a2);
567
    if (((uint32_t)env->regs[r1]) == v2) {
568
        cc = 0;
569
        stl(a2, (uint32_t)env->regs[r3]);
570
    } else {
571
        cc = 1;
572
        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2;
573
    }
574
    return cc;
575
}
576

    
577
static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask)
578
{
579
    int pos = 24; /* top of the lower half of r1 */
580
    uint64_t rmask = 0xff000000ULL;
581
    uint8_t val = 0;
582
    int ccd = 0;
583
    uint32_t cc = 0;
584

    
585
    while (mask) {
586
        if (mask & 8) {
587
            env->regs[r1] &= ~rmask;
588
            val = ldub(address);
589
            if ((val & 0x80) && !ccd) {
590
                cc = 1;
591
            }
592
            ccd = 1;
593
            if (val && cc == 0) {
594
                cc = 2;
595
            }
596
            env->regs[r1] |= (uint64_t)val << pos;
597
            address++;
598
        }
599
        mask = (mask << 1) & 0xf;
600
        pos -= 8;
601
        rmask >>= 8;
602
    }
603

    
604
    return cc;
605
}
606

    
607
/* execute instruction
608
   this instruction executes an insn modified with the contents of r1
609
   it does not change the executed instruction in memory
610
   it does not change the program counter
611
   in other words: tricky...
612
   currently implemented by interpreting the cases it is most commonly used in
613
 */
614
uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
615
{
616
    uint16_t insn = lduw_code(addr);
617
    HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __FUNCTION__, v1, addr,
618
             insn);
619
    if ((insn & 0xf0ff) == 0xd000) {
620
        uint32_t l, insn2, b1, b2, d1, d2;
621
        l = v1 & 0xff;
622
        insn2 = ldl_code(addr + 2);
623
        b1 = (insn2 >> 28) & 0xf;
624
        b2 = (insn2 >> 12) & 0xf;
625
        d1 = (insn2 >> 16) & 0xfff;
626
        d2 = insn2 & 0xfff;
627
        switch (insn & 0xf00) {
628
        case 0x200:
629
            helper_mvc(l, get_address(0, b1, d1), get_address(0, b2, d2));
630
            break;
631
        case 0x500:
632
            cc = helper_clc(l, get_address(0, b1, d1), get_address(0, b2, d2));
633
            break;
634
        case 0x700:
635
            cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2));
636
            break;
637
        case 0xc00:
638
            helper_tr(l, get_address(0, b1, d1), get_address(0, b2, d2));
639
            break;
640
        default:
641
            goto abort;
642
            break;
643
        }
644
    } else if ((insn & 0xff00) == 0x0a00) {
645
        /* supervisor call */
646
        HELPER_LOG("%s: svc %ld via execute\n", __FUNCTION__, (insn|v1) & 0xff);
647
        env->psw.addr = ret - 4;
648
        env->int_svc_code = (insn|v1) & 0xff;
649
        env->int_svc_ilc = 4;
650
        helper_exception(EXCP_SVC);
651
    } else if ((insn & 0xff00) == 0xbf00) {
652
        uint32_t insn2, r1, r3, b2, d2;
653
        insn2 = ldl_code(addr + 2);
654
        r1 = (insn2 >> 20) & 0xf;
655
        r3 = (insn2 >> 16) & 0xf;
656
        b2 = (insn2 >> 12) & 0xf;
657
        d2 = insn2 & 0xfff;
658
        cc = helper_icm(r1, get_address(0, b2, d2), r3);
659
    } else {
660
abort:
661
        cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n",
662
                  insn);
663
    }
664
    return cc;
665
}
666

    
667
/* absolute value 32-bit */
668
uint32_t HELPER(abs_i32)(int32_t val)
669
{
670
    if (val < 0) {
671
        return -val;
672
    } else {
673
        return val;
674
    }
675
}
676

    
677
/* negative absolute value 32-bit */
678
int32_t HELPER(nabs_i32)(int32_t val)
679
{
680
    if (val < 0) {
681
        return val;
682
    } else {
683
        return -val;
684
    }
685
}
686

    
687
/* absolute value 64-bit */
688
uint64_t HELPER(abs_i64)(int64_t val)
689
{
690
    HELPER_LOG("%s: val 0x%" PRIx64 "\n", __FUNCTION__, val);
691

    
692
    if (val < 0) {
693
        return -val;
694
    } else {
695
        return val;
696
    }
697
}
698

    
699
/* negative absolute value 64-bit */
700
int64_t HELPER(nabs_i64)(int64_t val)
701
{
702
    if (val < 0) {
703
        return val;
704
    } else {
705
        return -val;
706
    }
707
}
708

    
709
/* add with carry 32-bit unsigned */
710
uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
711
{
712
    uint32_t res;
713

    
714
    res = v1 + v2;
715
    if (cc & 2) {
716
        res++;
717
    }
718

    
719
    return res;
720
}
721

    
722
/* store character under mask high operates on the upper half of r1 */
723
void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask)
724
{
725
    int pos = 56; /* top of the upper half of r1 */
726

    
727
    while (mask) {
728
        if (mask & 8) {
729
            stb(address, (env->regs[r1] >> pos) & 0xff);
730
            address++;
731
        }
732
        mask = (mask << 1) & 0xf;
733
        pos -= 8;
734
    }
735
}
736

    
737
/* insert character under mask high; same as icm, but operates on the
738
   upper half of r1 */
739
uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask)
740
{
741
    int pos = 56; /* top of the upper half of r1 */
742
    uint64_t rmask = 0xff00000000000000ULL;
743
    uint8_t val = 0;
744
    int ccd = 0;
745
    uint32_t cc = 0;
746

    
747
    while (mask) {
748
        if (mask & 8) {
749
            env->regs[r1] &= ~rmask;
750
            val = ldub(address);
751
            if ((val & 0x80) && !ccd) {
752
                cc = 1;
753
            }
754
            ccd = 1;
755
            if (val && cc == 0) {
756
                cc = 2;
757
            }
758
            env->regs[r1] |= (uint64_t)val << pos;
759
            address++;
760
        }
761
        mask = (mask << 1) & 0xf;
762
        pos -= 8;
763
        rmask >>= 8;
764
    }
765

    
766
    return cc;
767
}
768

    
769
/* insert psw mask and condition code into r1 */
770
void HELPER(ipm)(uint32_t cc, uint32_t r1)
771
{
772
    uint64_t r = env->regs[r1];
773

    
774
    r &= 0xffffffff00ffffffULL;
775
    r |= (cc << 28) | ( (env->psw.mask >> 40) & 0xf );
776
    env->regs[r1] = r;
777
    HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __FUNCTION__,
778
               cc, env->psw.mask, r);
779
}
780

    
781
/* load access registers r1 to r3 from memory at a2 */
782
void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3)
783
{
784
    int i;
785

    
786
    for (i = r1;; i = (i + 1) % 16) {
787
        env->aregs[i] = ldl(a2);
788
        a2 += 4;
789

    
790
        if (i == r3) {
791
            break;
792
        }
793
    }
794
}
795

    
796
/* store access registers r1 to r3 in memory at a2 */
797
void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3)
798
{
799
    int i;
800

    
801
    for (i = r1;; i = (i + 1) % 16) {
802
        stl(a2, env->aregs[i]);
803
        a2 += 4;
804

    
805
        if (i == r3) {
806
            break;
807
        }
808
    }
809
}
810

    
811
/* move long */
812
uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2)
813
{
814
    uint64_t destlen = env->regs[r1 + 1] & 0xffffff;
815
    uint64_t dest = get_address_31fix(r1);
816
    uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
817
    uint64_t src = get_address_31fix(r2);
818
    uint8_t pad = src >> 24;
819
    uint8_t v;
820
    uint32_t cc;
821

    
822
    if (destlen == srclen) {
823
        cc = 0;
824
    } else if (destlen < srclen) {
825
        cc = 1;
826
    } else {
827
        cc = 2;
828
    }
829

    
830
    if (srclen > destlen) {
831
        srclen = destlen;
832
    }
833

    
834
    for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
835
        v = ldub(src);
836
        stb(dest, v);
837
    }
838

    
839
    for (; destlen; dest++, destlen--) {
840
        stb(dest, pad);
841
    }
842

    
843
    env->regs[r1 + 1] = destlen;
844
    /* can't use srclen here, we trunc'ed it */
845
    env->regs[r2 + 1] -= src - env->regs[r2];
846
    env->regs[r1] = dest;
847
    env->regs[r2] = src;
848

    
849
    return cc;
850
}
851

    
852
/* move long extended another memcopy insn with more bells and whistles */
853
uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3)
854
{
855
    uint64_t destlen = env->regs[r1 + 1];
856
    uint64_t dest = env->regs[r1];
857
    uint64_t srclen = env->regs[r3 + 1];
858
    uint64_t src = env->regs[r3];
859
    uint8_t pad = a2 & 0xff;
860
    uint8_t v;
861
    uint32_t cc;
862

    
863
    if (!(env->psw.mask & PSW_MASK_64)) {
864
        destlen = (uint32_t)destlen;
865
        srclen = (uint32_t)srclen;
866
        dest &= 0x7fffffff;
867
        src &= 0x7fffffff;
868
    }
869

    
870
    if (destlen == srclen) {
871
        cc = 0;
872
    } else if (destlen < srclen) {
873
        cc = 1;
874
    } else {
875
        cc = 2;
876
    }
877

    
878
    if (srclen > destlen) {
879
        srclen = destlen;
880
    }
881

    
882
    for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
883
        v = ldub(src);
884
        stb(dest, v);
885
    }
886

    
887
    for (; destlen; dest++, destlen--) {
888
        stb(dest, pad);
889
    }
890

    
891
    env->regs[r1 + 1] = destlen;
892
    /* can't use srclen here, we trunc'ed it */
893
    /* FIXME: 31-bit mode! */
894
    env->regs[r3 + 1] -= src - env->regs[r3];
895
    env->regs[r1] = dest;
896
    env->regs[r3] = src;
897

    
898
    return cc;
899
}
900

    
901
/* compare logical long extended memcompare insn with padding */
902
uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
903
{
904
    uint64_t destlen = env->regs[r1 + 1];
905
    uint64_t dest = get_address_31fix(r1);
906
    uint64_t srclen = env->regs[r3 + 1];
907
    uint64_t src = get_address_31fix(r3);
908
    uint8_t pad = a2 & 0xff;
909
    uint8_t v1 = 0,v2 = 0;
910
    uint32_t cc = 0;
911

    
912
    if (!(destlen || srclen)) {
913
        return cc;
914
    }
915

    
916
    if (srclen > destlen) {
917
        srclen = destlen;
918
    }
919

    
920
    for (; destlen || srclen; src++, dest++, destlen--, srclen--) {
921
        v1 = srclen ? ldub(src) : pad;
922
        v2 = destlen ? ldub(dest) : pad;
923
        if (v1 != v2) {
924
            cc = (v1 < v2) ? 1 : 2;
925
            break;
926
        }
927
    }
928

    
929
    env->regs[r1 + 1] = destlen;
930
    /* can't use srclen here, we trunc'ed it */
931
    env->regs[r3 + 1] -= src - env->regs[r3];
932
    env->regs[r1] = dest;
933
    env->regs[r3] = src;
934

    
935
    return cc;
936
}
937

    
938
/* subtract unsigned v2 from v1 with borrow */
939
uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
940
{
941
    uint32_t v1 = env->regs[r1];
942
    uint32_t res = v1 + (~v2) + (cc >> 1);
943

    
944
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res;
945
    if (cc & 2) {
946
        /* borrow */
947
        return v1 ? 1 : 0;
948
    } else {
949
        return v1 ? 3 : 2;
950
    }
951
}
952

    
953
/* subtract unsigned v2 from v1 with borrow */
954
uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
955
{
956
    uint64_t res = v1 + (~v2) + (cc >> 1);
957

    
958
    env->regs[r1] = res;
959
    if (cc & 2) {
960
        /* borrow */
961
        return v1 ? 1 : 0;
962
    } else {
963
        return v1 ? 3 : 2;
964
    }
965
}
966

    
967
static inline int float_comp_to_cc(int float_compare)
968
{
969
    switch (float_compare) {
970
    case float_relation_equal:
971
        return 0;
972
    case float_relation_less:
973
        return 1;
974
    case float_relation_greater:
975
        return 2;
976
    case float_relation_unordered:
977
        return 3;
978
    default:
979
        cpu_abort(env, "unknown return value for float compare\n");
980
    }
981
}
982

    
983
/* condition codes for binary FP ops */
984
static uint32_t set_cc_f32(float32 v1, float32 v2)
985
{
986
    return float_comp_to_cc(float32_compare_quiet(v1, v2, &env->fpu_status));
987
}
988

    
989
static uint32_t set_cc_f64(float64 v1, float64 v2)
990
{
991
    return float_comp_to_cc(float64_compare_quiet(v1, v2, &env->fpu_status));
992
}
993

    
994
/* condition codes for unary FP ops */
995
static uint32_t set_cc_nz_f32(float32 v)
996
{
997
    if (float32_is_any_nan(v)) {
998
        return 3;
999
    } else if (float32_is_zero(v)) {
1000
        return 0;
1001
    } else if (float32_is_neg(v)) {
1002
        return 1;
1003
    } else {
1004
        return 2;
1005
    }
1006
}
1007

    
1008
static uint32_t set_cc_nz_f64(float64 v)
1009
{
1010
    if (float64_is_any_nan(v)) {
1011
        return 3;
1012
    } else if (float64_is_zero(v)) {
1013
        return 0;
1014
    } else if (float64_is_neg(v)) {
1015
        return 1;
1016
    } else {
1017
        return 2;
1018
    }
1019
}
1020

    
1021
static uint32_t set_cc_nz_f128(float128 v)
1022
{
1023
    if (float128_is_any_nan(v)) {
1024
        return 3;
1025
    } else if (float128_is_zero(v)) {
1026
        return 0;
1027
    } else if (float128_is_neg(v)) {
1028
        return 1;
1029
    } else {
1030
        return 2;
1031
    }
1032
}
1033

    
1034
/* convert 32-bit int to 64-bit float */
1035
void HELPER(cdfbr)(uint32_t f1, int32_t v2)
1036
{
1037
    HELPER_LOG("%s: converting %d to f%d\n", __FUNCTION__, v2, f1);
1038
    env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
1039
}
1040

    
1041
/* convert 32-bit int to 128-bit float */
1042
void HELPER(cxfbr)(uint32_t f1, int32_t v2)
1043
{
1044
    CPU_QuadU v1;
1045
    v1.q = int32_to_float128(v2, &env->fpu_status);
1046
    env->fregs[f1].ll = v1.ll.upper;
1047
    env->fregs[f1 + 2].ll = v1.ll.lower;
1048
}
1049

    
1050
/* convert 64-bit int to 32-bit float */
1051
void HELPER(cegbr)(uint32_t f1, int64_t v2)
1052
{
1053
    HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1);
1054
    env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
1055
}
1056

    
1057
/* convert 64-bit int to 64-bit float */
1058
void HELPER(cdgbr)(uint32_t f1, int64_t v2)
1059
{
1060
    HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1);
1061
    env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
1062
}
1063

    
1064
/* convert 64-bit int to 128-bit float */
1065
void HELPER(cxgbr)(uint32_t f1, int64_t v2)
1066
{
1067
    CPU_QuadU x1;
1068
    x1.q = int64_to_float128(v2, &env->fpu_status);
1069
    HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __FUNCTION__, v2,
1070
               x1.ll.upper, x1.ll.lower);
1071
    env->fregs[f1].ll = x1.ll.upper;
1072
    env->fregs[f1 + 2].ll = x1.ll.lower;
1073
}
1074

    
1075
/* convert 32-bit int to 32-bit float */
1076
void HELPER(cefbr)(uint32_t f1, int32_t v2)
1077
{
1078
    env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
1079
    HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __FUNCTION__, v2,
1080
               env->fregs[f1].l.upper, f1);
1081
}
1082

    
1083
/* 32-bit FP addition RR */
1084
uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2)
1085
{
1086
    env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
1087
                                         env->fregs[f2].l.upper,
1088
                                         &env->fpu_status);
1089
    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__,
1090
               env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
1091

    
1092
    return set_cc_nz_f32(env->fregs[f1].l.upper);
1093
}
1094

    
1095
/* 64-bit FP addition RR */
1096
uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2)
1097
{
1098
    env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
1099
                                   &env->fpu_status);
1100
    HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __FUNCTION__,
1101
               env->fregs[f2].d, env->fregs[f1].d, f1);
1102

    
1103
    return set_cc_nz_f64(env->fregs[f1].d);
1104
}
1105

    
1106
/* 32-bit FP subtraction RR */
1107
uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2)
1108
{
1109
    env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
1110
                                         env->fregs[f2].l.upper,
1111
                                         &env->fpu_status);
1112
    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__,
1113
               env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
1114

    
1115
    return set_cc_nz_f32(env->fregs[f1].l.upper);
1116
}
1117

    
1118
/* 64-bit FP subtraction RR */
1119
uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2)
1120
{
1121
    env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
1122
                                   &env->fpu_status);
1123
    HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
1124
               __FUNCTION__, env->fregs[f2].d, env->fregs[f1].d, f1);
1125

    
1126
    return set_cc_nz_f64(env->fregs[f1].d);
1127
}
1128

    
1129
/* 32-bit FP division RR */
1130
void HELPER(debr)(uint32_t f1, uint32_t f2)
1131
{
1132
    env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper,
1133
                                         env->fregs[f2].l.upper,
1134
                                         &env->fpu_status);
1135
}
1136

    
1137
/* 128-bit FP division RR */
1138
void HELPER(dxbr)(uint32_t f1, uint32_t f2)
1139
{
1140
    CPU_QuadU v1;
1141
    v1.ll.upper = env->fregs[f1].ll;
1142
    v1.ll.lower = env->fregs[f1 + 2].ll;
1143
    CPU_QuadU v2;
1144
    v2.ll.upper = env->fregs[f2].ll;
1145
    v2.ll.lower = env->fregs[f2 + 2].ll;
1146
    CPU_QuadU res;
1147
    res.q = float128_div(v1.q, v2.q, &env->fpu_status);
1148
    env->fregs[f1].ll = res.ll.upper;
1149
    env->fregs[f1 + 2].ll = res.ll.lower;
1150
}
1151

    
1152
/* 64-bit FP multiplication RR */
1153
void HELPER(mdbr)(uint32_t f1, uint32_t f2)
1154
{
1155
    env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d,
1156
                                   &env->fpu_status);
1157
}
1158

    
1159
/* 128-bit FP multiplication RR */
1160
void HELPER(mxbr)(uint32_t f1, uint32_t f2)
1161
{
1162
    CPU_QuadU v1;
1163
    v1.ll.upper = env->fregs[f1].ll;
1164
    v1.ll.lower = env->fregs[f1 + 2].ll;
1165
    CPU_QuadU v2;
1166
    v2.ll.upper = env->fregs[f2].ll;
1167
    v2.ll.lower = env->fregs[f2 + 2].ll;
1168
    CPU_QuadU res;
1169
    res.q = float128_mul(v1.q, v2.q, &env->fpu_status);
1170
    env->fregs[f1].ll = res.ll.upper;
1171
    env->fregs[f1 + 2].ll = res.ll.lower;
1172
}
1173

    
1174
/* convert 32-bit float to 64-bit float */
1175
void HELPER(ldebr)(uint32_t r1, uint32_t r2)
1176
{
1177
    env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
1178
                                          &env->fpu_status);
1179
}
1180

    
1181
/* convert 128-bit float to 64-bit float */
1182
void HELPER(ldxbr)(uint32_t f1, uint32_t f2)
1183
{
1184
    CPU_QuadU x2;
1185
    x2.ll.upper = env->fregs[f2].ll;
1186
    x2.ll.lower = env->fregs[f2 + 2].ll;
1187
    env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status);
1188
    HELPER_LOG("%s: to 0x%ld\n", __FUNCTION__, env->fregs[f1].d);
1189
}
1190

    
1191
/* convert 64-bit float to 128-bit float */
1192
void HELPER(lxdbr)(uint32_t f1, uint32_t f2)
1193
{
1194
    CPU_QuadU res;
1195
    res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status);
1196
    env->fregs[f1].ll = res.ll.upper;
1197
    env->fregs[f1 + 2].ll = res.ll.lower;
1198
}
1199

    
1200
/* convert 64-bit float to 32-bit float */
1201
void HELPER(ledbr)(uint32_t f1, uint32_t f2)
1202
{
1203
    float64 d2 = env->fregs[f2].d;
1204
    env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
1205
}
1206

    
1207
/* convert 128-bit float to 32-bit float */
1208
void HELPER(lexbr)(uint32_t f1, uint32_t f2)
1209
{
1210
    CPU_QuadU x2;
1211
    x2.ll.upper = env->fregs[f2].ll;
1212
    x2.ll.lower = env->fregs[f2 + 2].ll;
1213
    env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status);
1214
    HELPER_LOG("%s: to 0x%d\n", __FUNCTION__, env->fregs[f1].l.upper);
1215
}
1216

    
1217
/* absolute value of 32-bit float */
1218
uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2)
1219
{
1220
    float32 v1;
1221
    float32 v2 = env->fregs[f2].d;
1222
    v1 = float32_abs(v2);
1223
    env->fregs[f1].d = v1;
1224
    return set_cc_nz_f32(v1);
1225
}
1226

    
1227
/* absolute value of 64-bit float */
1228
uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2)
1229
{
1230
    float64 v1;
1231
    float64 v2 = env->fregs[f2].d;
1232
    v1 = float64_abs(v2);
1233
    env->fregs[f1].d = v1;
1234
    return set_cc_nz_f64(v1);
1235
}
1236

    
1237
/* absolute value of 128-bit float */
1238
uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2)
1239
{
1240
    CPU_QuadU v1;
1241
    CPU_QuadU v2;
1242
    v2.ll.upper = env->fregs[f2].ll;
1243
    v2.ll.lower = env->fregs[f2 + 2].ll;
1244
    v1.q = float128_abs(v2.q);
1245
    env->fregs[f1].ll = v1.ll.upper;
1246
    env->fregs[f1 + 2].ll = v1.ll.lower;
1247
    return set_cc_nz_f128(v1.q);
1248
}
1249

    
1250
/* load and test 64-bit float */
1251
uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2)
1252
{
1253
    env->fregs[f1].d = env->fregs[f2].d;
1254
    return set_cc_nz_f64(env->fregs[f1].d);
1255
}
1256

    
1257
/* load and test 32-bit float */
1258
uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2)
1259
{
1260
    env->fregs[f1].l.upper = env->fregs[f2].l.upper;
1261
    return set_cc_nz_f32(env->fregs[f1].l.upper);
1262
}
1263

    
1264
/* load and test 128-bit float */
1265
uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2)
1266
{
1267
    CPU_QuadU x;
1268
    x.ll.upper = env->fregs[f2].ll;
1269
    x.ll.lower = env->fregs[f2 + 2].ll;
1270
    env->fregs[f1].ll = x.ll.upper;
1271
    env->fregs[f1 + 2].ll = x.ll.lower;
1272
    return set_cc_nz_f128(x.q);
1273
}
1274

    
1275
/* load complement of 32-bit float */
1276
uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2)
1277
{
1278
    env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
1279

    
1280
    return set_cc_nz_f32(env->fregs[f1].l.upper);
1281
}
1282

    
1283
/* load complement of 64-bit float */
1284
uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2)
1285
{
1286
    env->fregs[f1].d = float64_chs(env->fregs[f2].d);
1287

    
1288
    return set_cc_nz_f64(env->fregs[f1].d);
1289
}
1290

    
1291
/* load complement of 128-bit float */
1292
uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2)
1293
{
1294
    CPU_QuadU x1, x2;
1295
    x2.ll.upper = env->fregs[f2].ll;
1296
    x2.ll.lower = env->fregs[f2 + 2].ll;
1297
    x1.q = float128_chs(x2.q);
1298
    env->fregs[f1].ll = x1.ll.upper;
1299
    env->fregs[f1 + 2].ll = x1.ll.lower;
1300
    return set_cc_nz_f128(x1.q);
1301
}
1302

    
1303
/* 32-bit FP addition RM */
1304
void HELPER(aeb)(uint32_t f1, uint32_t val)
1305
{
1306
    float32 v1 = env->fregs[f1].l.upper;
1307
    CPU_FloatU v2;
1308
    v2.l = val;
1309
    HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __FUNCTION__,
1310
               v1, f1, v2.f);
1311
    env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
1312
}
1313

    
1314
/* 32-bit FP division RM */
1315
void HELPER(deb)(uint32_t f1, uint32_t val)
1316
{
1317
    float32 v1 = env->fregs[f1].l.upper;
1318
    CPU_FloatU v2;
1319
    v2.l = val;
1320
    HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __FUNCTION__,
1321
               v1, f1, v2.f);
1322
    env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
1323
}
1324

    
1325
/* 32-bit FP multiplication RM */
1326
void HELPER(meeb)(uint32_t f1, uint32_t val)
1327
{
1328
    float32 v1 = env->fregs[f1].l.upper;
1329
    CPU_FloatU v2;
1330
    v2.l = val;
1331
    HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __FUNCTION__,
1332
               v1, f1, v2.f);
1333
    env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
1334
}
1335

    
1336
/* 32-bit FP compare RR */
1337
uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2)
1338
{
1339
    float32 v1 = env->fregs[f1].l.upper;
1340
    float32 v2 = env->fregs[f2].l.upper;
1341
    HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __FUNCTION__,
1342
               v1, f1, v2);
1343
    return set_cc_f32(v1, v2);
1344
}
1345

    
1346
/* 64-bit FP compare RR */
1347
uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2)
1348
{
1349
    float64 v1 = env->fregs[f1].d;
1350
    float64 v2 = env->fregs[f2].d;
1351
    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __FUNCTION__,
1352
               v1, f1, v2);
1353
    return set_cc_f64(v1, v2);
1354
}
1355

    
1356
/* 128-bit FP compare RR */
1357
uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2)
1358
{
1359
    CPU_QuadU v1;
1360
    v1.ll.upper = env->fregs[f1].ll;
1361
    v1.ll.lower = env->fregs[f1 + 2].ll;
1362
    CPU_QuadU v2;
1363
    v2.ll.upper = env->fregs[f2].ll;
1364
    v2.ll.lower = env->fregs[f2 + 2].ll;
1365

    
1366
    return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q,
1367
                            &env->fpu_status));
1368
}
1369

    
1370
/* 64-bit FP compare RM */
1371
uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2)
1372
{
1373
    float64 v1 = env->fregs[f1].d;
1374
    CPU_DoubleU v2;
1375
    v2.ll = ldq(a2);
1376
    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __FUNCTION__, v1,
1377
               f1, v2.d);
1378
    return set_cc_f64(v1, v2.d);
1379
}
1380

    
1381
/* 64-bit FP addition RM */
1382
uint32_t HELPER(adb)(uint32_t f1, uint64_t a2)
1383
{
1384
    float64 v1 = env->fregs[f1].d;
1385
    CPU_DoubleU v2;
1386
    v2.ll = ldq(a2);
1387
    HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __FUNCTION__,
1388
               v1, f1, v2.d);
1389
    env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
1390
    return set_cc_nz_f64(v1);
1391
}
1392

    
1393
/* 32-bit FP subtraction RM */
1394
void HELPER(seb)(uint32_t f1, uint32_t val)
1395
{
1396
    float32 v1 = env->fregs[f1].l.upper;
1397
    CPU_FloatU v2;
1398
    v2.l = val;
1399
    env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status);
1400
}
1401

    
1402
/* 64-bit FP subtraction RM */
1403
uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2)
1404
{
1405
    float64 v1 = env->fregs[f1].d;
1406
    CPU_DoubleU v2;
1407
    v2.ll = ldq(a2);
1408
    env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
1409
    return set_cc_nz_f64(v1);
1410
}
1411

    
1412
/* 64-bit FP multiplication RM */
1413
void HELPER(mdb)(uint32_t f1, uint64_t a2)
1414
{
1415
    float64 v1 = env->fregs[f1].d;
1416
    CPU_DoubleU v2;
1417
    v2.ll = ldq(a2);
1418
    HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __FUNCTION__,
1419
               v1, f1, v2.d);
1420
    env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
1421
}
1422

    
1423
/* 64-bit FP division RM */
1424
void HELPER(ddb)(uint32_t f1, uint64_t a2)
1425
{
1426
    float64 v1 = env->fregs[f1].d;
1427
    CPU_DoubleU v2;
1428
    v2.ll = ldq(a2);
1429
    HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __FUNCTION__,
1430
               v1, f1, v2.d);
1431
    env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
1432
}
1433

    
1434
static void set_round_mode(int m3)
1435
{
1436
    switch (m3) {
1437
    case 0:
1438
        /* current mode */
1439
        break;
1440
    case 1:
1441
        /* biased round no nearest */
1442
    case 4:
1443
        /* round to nearest */
1444
        set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
1445
        break;
1446
    case 5:
1447
        /* round to zero */
1448
        set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
1449
        break;
1450
    case 6:
1451
        /* round to +inf */
1452
        set_float_rounding_mode(float_round_up, &env->fpu_status);
1453
        break;
1454
    case 7:
1455
        /* round to -inf */
1456
        set_float_rounding_mode(float_round_down, &env->fpu_status);
1457
        break;
1458
    }
1459
}
1460

    
1461
/* convert 32-bit float to 64-bit int */
1462
uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3)
1463
{
1464
    float32 v2 = env->fregs[f2].l.upper;
1465
    set_round_mode(m3);
1466
    env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
1467
    return set_cc_nz_f32(v2);
1468
}
1469

    
1470
/* convert 64-bit float to 64-bit int */
1471
uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1472
{
1473
    float64 v2 = env->fregs[f2].d;
1474
    set_round_mode(m3);
1475
    env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
1476
    return set_cc_nz_f64(v2);
1477
}
1478

    
1479
/* convert 128-bit float to 64-bit int */
1480
uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1481
{
1482
    CPU_QuadU v2;
1483
    v2.ll.upper = env->fregs[f2].ll;
1484
    v2.ll.lower = env->fregs[f2 + 2].ll;
1485
    set_round_mode(m3);
1486
    env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
1487
    if (float128_is_any_nan(v2.q)) {
1488
        return 3;
1489
    } else if (float128_is_zero(v2.q)) {
1490
        return 0;
1491
    } else if (float128_is_neg(v2.q)) {
1492
        return 1;
1493
    } else {
1494
        return 2;
1495
    }
1496
}
1497

    
1498
/* convert 32-bit float to 32-bit int */
1499
uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3)
1500
{
1501
    float32 v2 = env->fregs[f2].l.upper;
1502
    set_round_mode(m3);
1503
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
1504
                     float32_to_int32(v2, &env->fpu_status);
1505
    return set_cc_nz_f32(v2);
1506
}
1507

    
1508
/* convert 64-bit float to 32-bit int */
1509
uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1510
{
1511
    float64 v2 = env->fregs[f2].d;
1512
    set_round_mode(m3);
1513
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
1514
                     float64_to_int32(v2, &env->fpu_status);
1515
    return set_cc_nz_f64(v2);
1516
}
1517

    
1518
/* convert 128-bit float to 32-bit int */
1519
uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1520
{
1521
    CPU_QuadU v2;
1522
    v2.ll.upper = env->fregs[f2].ll;
1523
    v2.ll.lower = env->fregs[f2 + 2].ll;
1524
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
1525
                     float128_to_int32(v2.q, &env->fpu_status);
1526
    return set_cc_nz_f128(v2.q);
1527
}
1528

    
1529
/* load 32-bit FP zero */
1530
void HELPER(lzer)(uint32_t f1)
1531
{
1532
    env->fregs[f1].l.upper = float32_zero;
1533
}
1534

    
1535
/* load 64-bit FP zero */
1536
void HELPER(lzdr)(uint32_t f1)
1537
{
1538
    env->fregs[f1].d = float64_zero;
1539
}
1540

    
1541
/* load 128-bit FP zero */
1542
void HELPER(lzxr)(uint32_t f1)
1543
{
1544
    CPU_QuadU x;
1545
    x.q = float64_to_float128(float64_zero, &env->fpu_status);
1546
    env->fregs[f1].ll = x.ll.upper;
1547
    env->fregs[f1 + 1].ll = x.ll.lower;
1548
}
1549

    
1550
/* 128-bit FP subtraction RR */
1551
uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2)
1552
{
1553
    CPU_QuadU v1;
1554
    v1.ll.upper = env->fregs[f1].ll;
1555
    v1.ll.lower = env->fregs[f1 + 2].ll;
1556
    CPU_QuadU v2;
1557
    v2.ll.upper = env->fregs[f2].ll;
1558
    v2.ll.lower = env->fregs[f2 + 2].ll;
1559
    CPU_QuadU res;
1560
    res.q = float128_sub(v1.q, v2.q, &env->fpu_status);
1561
    env->fregs[f1].ll = res.ll.upper;
1562
    env->fregs[f1 + 2].ll = res.ll.lower;
1563
    return set_cc_nz_f128(res.q);
1564
}
1565

    
1566
/* 128-bit FP addition RR */
1567
uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2)
1568
{
1569
    CPU_QuadU v1;
1570
    v1.ll.upper = env->fregs[f1].ll;
1571
    v1.ll.lower = env->fregs[f1 + 2].ll;
1572
    CPU_QuadU v2;
1573
    v2.ll.upper = env->fregs[f2].ll;
1574
    v2.ll.lower = env->fregs[f2 + 2].ll;
1575
    CPU_QuadU res;
1576
    res.q = float128_add(v1.q, v2.q, &env->fpu_status);
1577
    env->fregs[f1].ll = res.ll.upper;
1578
    env->fregs[f1 + 2].ll = res.ll.lower;
1579
    return set_cc_nz_f128(res.q);
1580
}
1581

    
1582
/* 32-bit FP multiplication RR */
1583
void HELPER(meebr)(uint32_t f1, uint32_t f2)
1584
{
1585
    env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper,
1586
                                         env->fregs[f2].l.upper,
1587
                                         &env->fpu_status);
1588
}
1589

    
1590
/* 64-bit FP division RR */
1591
void HELPER(ddbr)(uint32_t f1, uint32_t f2)
1592
{
1593
    env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d,
1594
                                   &env->fpu_status);
1595
}
1596

    
1597
/* 64-bit FP multiply and add RM */
1598
void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3)
1599
{
1600
    HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __FUNCTION__, f1, a2, f3);
1601
    CPU_DoubleU v2;
1602
    v2.ll = ldq(a2);
1603
    env->fregs[f1].d = float64_add(env->fregs[f1].d,
1604
                                   float64_mul(v2.d, env->fregs[f3].d,
1605
                                               &env->fpu_status),
1606
                                   &env->fpu_status);
1607
}
1608

    
1609
/* 64-bit FP multiply and add RR */
1610
void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2)
1611
{
1612
    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3);
1613
    env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d,
1614
                                               env->fregs[f3].d,
1615
                                               &env->fpu_status),
1616
                                   env->fregs[f1].d, &env->fpu_status);
1617
}
1618

    
1619
/* 64-bit FP multiply and subtract RR */
1620
void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2)
1621
{
1622
    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3);
1623
    env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d,
1624
                                               env->fregs[f3].d,
1625
                                               &env->fpu_status),
1626
                                   env->fregs[f1].d, &env->fpu_status);
1627
}
1628

    
1629
/* 32-bit FP multiply and add RR */
1630
void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
1631
{
1632
    env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
1633
                                         float32_mul(env->fregs[f2].l.upper,
1634
                                                     env->fregs[f3].l.upper,
1635
                                                     &env->fpu_status),
1636
                                         &env->fpu_status);
1637
}
1638

    
1639
/* convert 32-bit float to 64-bit float */
1640
void HELPER(ldeb)(uint32_t f1, uint64_t a2)
1641
{
1642
    uint32_t v2;
1643
    v2 = ldl(a2);
1644
    env->fregs[f1].d = float32_to_float64(v2,
1645
                                          &env->fpu_status);
1646
}
1647

    
1648
/* convert 64-bit float to 128-bit float */
1649
void HELPER(lxdb)(uint32_t f1, uint64_t a2)
1650
{
1651
    CPU_DoubleU v2;
1652
    v2.ll = ldq(a2);
1653
    CPU_QuadU v1;
1654
    v1.q = float64_to_float128(v2.d, &env->fpu_status);
1655
    env->fregs[f1].ll = v1.ll.upper;
1656
    env->fregs[f1 + 2].ll = v1.ll.lower;
1657
}
1658

    
1659
/* test data class 32-bit */
1660
uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2)
1661
{
1662
    float32 v1 = env->fregs[f1].l.upper;
1663
    int neg = float32_is_neg(v1);
1664
    uint32_t cc = 0;
1665

    
1666
    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, (long)v1, m2, neg);
1667
    if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
1668
        (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
1669
        (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
1670
        (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
1671
        cc = 1;
1672
    } else if (m2 & (1 << (9-neg))) {
1673
        /* assume normalized number */
1674
        cc = 1;
1675
    }
1676

    
1677
    /* FIXME: denormalized? */
1678
    return cc;
1679
}
1680

    
1681
/* test data class 64-bit */
1682
uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2)
1683
{
1684
    float64 v1 = env->fregs[f1].d;
1685
    int neg = float64_is_neg(v1);
1686
    uint32_t cc = 0;
1687

    
1688
    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, v1, m2, neg);
1689
    if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
1690
        (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
1691
        (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
1692
        (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
1693
        cc = 1;
1694
    } else if (m2 & (1 << (9-neg))) {
1695
        /* assume normalized number */
1696
        cc = 1;
1697
    }
1698
    /* FIXME: denormalized? */
1699
    return cc;
1700
}
1701

    
1702
/* test data class 128-bit */
1703
uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2)
1704
{
1705
    CPU_QuadU v1;
1706
    uint32_t cc = 0;
1707
    v1.ll.upper = env->fregs[f1].ll;
1708
    v1.ll.lower = env->fregs[f1 + 2].ll;
1709

    
1710
    int neg = float128_is_neg(v1.q);
1711
    if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
1712
        (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
1713
        (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
1714
        (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) {
1715
        cc = 1;
1716
    } else if (m2 & (1 << (9-neg))) {
1717
        /* assume normalized number */
1718
        cc = 1;
1719
    }
1720
    /* FIXME: denormalized? */
1721
    return cc;
1722
}
1723

    
1724
/* find leftmost one */
1725
uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
1726
{
1727
    uint64_t res = 0;
1728
    uint64_t ov2 = v2;
1729

    
1730
    while (!(v2 & 0x8000000000000000ULL) && v2) {
1731
        v2 <<= 1;
1732
        res++;
1733
    }
1734

    
1735
    if (!v2) {
1736
        env->regs[r1] = 64;
1737
        env->regs[r1 + 1] = 0;
1738
        return 0;
1739
    } else {
1740
        env->regs[r1] = res;
1741
        env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res);
1742
        return 2;
1743
    }
1744
}
1745

    
1746
/* square root 64-bit RR */
1747
void HELPER(sqdbr)(uint32_t f1, uint32_t f2)
1748
{
1749
    env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
1750
}
1751

    
1752
/* checksum */
1753
void HELPER(cksm)(uint32_t r1, uint32_t r2)
1754
{
1755
    uint64_t src = get_address_31fix(r2);
1756
    uint64_t src_len = env->regs[(r2 + 1) & 15];
1757
    uint64_t cksm = (uint32_t)env->regs[r1];
1758

    
1759
    while (src_len >= 4) {
1760
        cksm += ldl(src);
1761

    
1762
        /* move to next word */
1763
        src_len -= 4;
1764
        src += 4;
1765
    }
1766

    
1767
    switch (src_len) {
1768
    case 0:
1769
        break;
1770
    case 1:
1771
        cksm += ldub(src) << 24;
1772
        break;
1773
    case 2:
1774
        cksm += lduw(src) << 16;
1775
        break;
1776
    case 3:
1777
        cksm += lduw(src) << 16;
1778
        cksm += ldub(src + 2) << 8;
1779
        break;
1780
    }
1781

    
1782
    /* indicate we've processed everything */
1783
    env->regs[r2] = src + src_len;
1784
    env->regs[(r2 + 1) & 15] = 0;
1785

    
1786
    /* store result */
1787
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
1788
                    ((uint32_t)cksm + (cksm >> 32));
1789
}
1790

    
1791
static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
1792
                                       int32_t dst)
1793
{
1794
    if (src == dst) {
1795
        return 0;
1796
    } else if (src < dst) {
1797
        return 1;
1798
    } else {
1799
        return 2;
1800
    }
1801
}
1802

    
1803
static inline uint32_t cc_calc_ltgt0_32(CPUS390XState *env, int32_t dst)
1804
{
1805
    return cc_calc_ltgt_32(env, dst, 0);
1806
}
1807

    
1808
static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src,
1809
                                       int64_t dst)
1810
{
1811
    if (src == dst) {
1812
        return 0;
1813
    } else if (src < dst) {
1814
        return 1;
1815
    } else {
1816
        return 2;
1817
    }
1818
}
1819

    
1820
static inline uint32_t cc_calc_ltgt0_64(CPUS390XState *env, int64_t dst)
1821
{
1822
    return cc_calc_ltgt_64(env, dst, 0);
1823
}
1824

    
1825
static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src,
1826
                                         uint32_t dst)
1827
{
1828
    if (src == dst) {
1829
        return 0;
1830
    } else if (src < dst) {
1831
        return 1;
1832
    } else {
1833
        return 2;
1834
    }
1835
}
1836

    
1837
static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
1838
                                         uint64_t dst)
1839
{
1840
    if (src == dst) {
1841
        return 0;
1842
    } else if (src < dst) {
1843
        return 1;
1844
    } else {
1845
        return 2;
1846
    }
1847
}
1848

    
1849
static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask)
1850
{
1851
    HELPER_LOG("%s: val 0x%x mask 0x%x\n", __FUNCTION__, val, mask);
1852
    uint16_t r = val & mask;
1853
    if (r == 0 || mask == 0) {
1854
        return 0;
1855
    } else if (r == mask) {
1856
        return 3;
1857
    } else {
1858
        return 1;
1859
    }
1860
}
1861

    
1862
/* set condition code for test under mask */
1863
static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint32_t mask)
1864
{
1865
    uint16_t r = val & mask;
1866
    HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __FUNCTION__, val, mask, r);
1867
    if (r == 0 || mask == 0) {
1868
        return 0;
1869
    } else if (r == mask) {
1870
        return 3;
1871
    } else {
1872
        while (!(mask & 0x8000)) {
1873
            mask <<= 1;
1874
            val <<= 1;
1875
        }
1876
        if (val & 0x8000) {
1877
            return 2;
1878
        } else {
1879
            return 1;
1880
        }
1881
    }
1882
}
1883

    
1884
static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst)
1885
{
1886
    return !!dst;
1887
}
1888

    
1889
static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1, int64_t a2,
1890
                                      int64_t ar)
1891
{
1892
    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
1893
        return 3; /* overflow */
1894
    } else {
1895
        if (ar < 0) {
1896
            return 1;
1897
        } else if (ar > 0) {
1898
            return 2;
1899
        } else {
1900
            return 0;
1901
        }
1902
    }
1903
}
1904

    
1905
static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1, uint64_t a2,
1906
                                       uint64_t ar)
1907
{
1908
    if (ar == 0) {
1909
        if (a1) {
1910
            return 2;
1911
        } else {
1912
            return 0;
1913
        }
1914
    } else {
1915
        if (ar < a1 || ar < a2) {
1916
          return 3;
1917
        } else {
1918
          return 1;
1919
        }
1920
    }
1921
}
1922

    
1923
static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1, int64_t a2,
1924
                                      int64_t ar)
1925
{
1926
    if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
1927
        return 3; /* overflow */
1928
    } else {
1929
        if (ar < 0) {
1930
            return 1;
1931
        } else if (ar > 0) {
1932
            return 2;
1933
        } else {
1934
            return 0;
1935
        }
1936
    }
1937
}
1938

    
1939
static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1, uint64_t a2,
1940
                                       uint64_t ar)
1941
{
1942
    if (ar == 0) {
1943
        return 2;
1944
    } else {
1945
        if (a2 > a1) {
1946
            return 1;
1947
        } else {
1948
            return 3;
1949
        }
1950
    }
1951
}
1952

    
1953
static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
1954
{
1955
    if ((uint64_t)dst == 0x8000000000000000ULL) {
1956
        return 3;
1957
    } else if (dst) {
1958
        return 1;
1959
    } else {
1960
        return 0;
1961
    }
1962
}
1963

    
1964
static inline uint32_t cc_calc_nabs_64(CPUS390XState *env, int64_t dst)
1965
{
1966
    return !!dst;
1967
}
1968

    
1969
static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
1970
{
1971
    if ((uint64_t)dst == 0x8000000000000000ULL) {
1972
        return 3;
1973
    } else if (dst < 0) {
1974
        return 1;
1975
    } else if (dst > 0) {
1976
        return 2;
1977
    } else {
1978
        return 0;
1979
    }
1980
}
1981

    
1982

    
1983
static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1, int32_t a2,
1984
                                      int32_t ar)
1985
{
1986
    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
1987
        return 3; /* overflow */
1988
    } else {
1989
        if (ar < 0) {
1990
            return 1;
1991
        } else if (ar > 0) {
1992
            return 2;
1993
        } else {
1994
            return 0;
1995
        }
1996
    }
1997
}
1998

    
1999
static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1, uint32_t a2,
2000
                                       uint32_t ar)
2001
{
2002
    if (ar == 0) {
2003
        if (a1) {
2004
          return 2;
2005
        } else {
2006
          return 0;
2007
        }
2008
    } else {
2009
        if (ar < a1 || ar < a2) {
2010
          return 3;
2011
        } else {
2012
          return 1;
2013
        }
2014
    }
2015
}
2016

    
2017
static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1, int32_t a2,
2018
                                      int32_t ar)
2019
{
2020
    if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
2021
        return 3; /* overflow */
2022
    } else {
2023
        if (ar < 0) {
2024
            return 1;
2025
        } else if (ar > 0) {
2026
            return 2;
2027
        } else {
2028
            return 0;
2029
        }
2030
    }
2031
}
2032

    
2033
static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1, uint32_t a2,
2034
                                       uint32_t ar)
2035
{
2036
    if (ar == 0) {
2037
        return 2;
2038
    } else {
2039
        if (a2 > a1) {
2040
            return 1;
2041
        } else {
2042
            return 3;
2043
        }
2044
    }
2045
}
2046

    
2047
static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
2048
{
2049
    if ((uint32_t)dst == 0x80000000UL) {
2050
        return 3;
2051
    } else if (dst) {
2052
        return 1;
2053
    } else {
2054
        return 0;
2055
    }
2056
}
2057

    
2058
static inline uint32_t cc_calc_nabs_32(CPUS390XState *env, int32_t dst)
2059
{
2060
    return !!dst;
2061
}
2062

    
2063
static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
2064
{
2065
    if ((uint32_t)dst == 0x80000000UL) {
2066
        return 3;
2067
    } else if (dst < 0) {
2068
        return 1;
2069
    } else if (dst > 0) {
2070
        return 2;
2071
    } else {
2072
        return 0;
2073
    }
2074
}
2075

    
2076
/* calculate condition code for insert character under mask insn */
2077
static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask, uint32_t val)
2078
{
2079
    HELPER_LOG("%s: mask 0x%x val %d\n", __FUNCTION__, mask, val);
2080
    uint32_t cc;
2081

    
2082
    if (mask == 0xf) {
2083
        if (!val) {
2084
            return 0;
2085
        } else if (val & 0x80000000) {
2086
            return 1;
2087
        } else {
2088
            return 2;
2089
        }
2090
    }
2091

    
2092
    if (!val || !mask) {
2093
        cc = 0;
2094
    } else {
2095
        while (mask != 1) {
2096
            mask >>= 1;
2097
            val >>= 8;
2098
        }
2099
        if (val & 0x80) {
2100
            cc = 1;
2101
        } else {
2102
            cc = 2;
2103
        }
2104
    }
2105
    return cc;
2106
}
2107

    
2108
static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src, uint64_t shift)
2109
{
2110
    uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
2111
    uint64_t match, r;
2112

    
2113
    /* check if the sign bit stays the same */
2114
    if (src & (1ULL << 63)) {
2115
        match = mask;
2116
    } else {
2117
        match = 0;
2118
    }
2119

    
2120
    if ((src & mask) != match) {
2121
        /* overflow */
2122
        return 3;
2123
    }
2124

    
2125
    r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63));
2126

    
2127
    if ((int64_t)r == 0) {
2128
        return 0;
2129
    } else if ((int64_t)r < 0) {
2130
        return 1;
2131
    }
2132

    
2133
    return 2;
2134
}
2135

    
2136

    
2137
static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src,
2138
                                  uint64_t dst, uint64_t vr)
2139
{
2140
    uint32_t r = 0;
2141

    
2142
    switch (cc_op) {
2143
    case CC_OP_CONST0:
2144
    case CC_OP_CONST1:
2145
    case CC_OP_CONST2:
2146
    case CC_OP_CONST3:
2147
        /* cc_op value _is_ cc */
2148
        r = cc_op;
2149
        break;
2150
    case CC_OP_LTGT0_32:
2151
        r = cc_calc_ltgt0_32(env, dst);
2152
        break;
2153
    case CC_OP_LTGT0_64:
2154
        r =  cc_calc_ltgt0_64(env, dst);
2155
        break;
2156
    case CC_OP_LTGT_32:
2157
        r =  cc_calc_ltgt_32(env, src, dst);
2158
        break;
2159
    case CC_OP_LTGT_64:
2160
        r =  cc_calc_ltgt_64(env, src, dst);
2161
        break;
2162
    case CC_OP_LTUGTU_32:
2163
        r =  cc_calc_ltugtu_32(env, src, dst);
2164
        break;
2165
    case CC_OP_LTUGTU_64:
2166
        r =  cc_calc_ltugtu_64(env, src, dst);
2167
        break;
2168
    case CC_OP_TM_32:
2169
        r =  cc_calc_tm_32(env, src, dst);
2170
        break;
2171
    case CC_OP_TM_64:
2172
        r =  cc_calc_tm_64(env, src, dst);
2173
        break;
2174
    case CC_OP_NZ:
2175
        r =  cc_calc_nz(env, dst);
2176
        break;
2177
    case CC_OP_ADD_64:
2178
        r =  cc_calc_add_64(env, src, dst, vr);
2179
        break;
2180
    case CC_OP_ADDU_64:
2181
        r =  cc_calc_addu_64(env, src, dst, vr);
2182
        break;
2183
    case CC_OP_SUB_64:
2184
        r =  cc_calc_sub_64(env, src, dst, vr);
2185
        break;
2186
    case CC_OP_SUBU_64:
2187
        r =  cc_calc_subu_64(env, src, dst, vr);
2188
        break;
2189
    case CC_OP_ABS_64:
2190
        r =  cc_calc_abs_64(env, dst);
2191
        break;
2192
    case CC_OP_NABS_64:
2193
        r =  cc_calc_nabs_64(env, dst);
2194
        break;
2195
    case CC_OP_COMP_64:
2196
        r =  cc_calc_comp_64(env, dst);
2197
        break;
2198

    
2199
    case CC_OP_ADD_32:
2200
        r =  cc_calc_add_32(env, src, dst, vr);
2201
        break;
2202
    case CC_OP_ADDU_32:
2203
        r =  cc_calc_addu_32(env, src, dst, vr);
2204
        break;
2205
    case CC_OP_SUB_32:
2206
        r =  cc_calc_sub_32(env, src, dst, vr);
2207
        break;
2208
    case CC_OP_SUBU_32:
2209
        r =  cc_calc_subu_32(env, src, dst, vr);
2210
        break;
2211
    case CC_OP_ABS_32:
2212
        r =  cc_calc_abs_64(env, dst);
2213
        break;
2214
    case CC_OP_NABS_32:
2215
        r =  cc_calc_nabs_64(env, dst);
2216
        break;
2217
    case CC_OP_COMP_32:
2218
        r =  cc_calc_comp_32(env, dst);
2219
        break;
2220

    
2221
    case CC_OP_ICM:
2222
        r =  cc_calc_icm_32(env, src, dst);
2223
        break;
2224
    case CC_OP_SLAG:
2225
        r =  cc_calc_slag(env, src, dst);
2226
        break;
2227

    
2228
    case CC_OP_LTGT_F32:
2229
        r = set_cc_f32(src, dst);
2230
        break;
2231
    case CC_OP_LTGT_F64:
2232
        r = set_cc_f64(src, dst);
2233
        break;
2234
    case CC_OP_NZ_F32:
2235
        r = set_cc_nz_f32(dst);
2236
        break;
2237
    case CC_OP_NZ_F64:
2238
        r = set_cc_nz_f64(dst);
2239
        break;
2240

    
2241
    default:
2242
        cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op));
2243
    }
2244

    
2245
    HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __FUNCTION__,
2246
               cc_name(cc_op), src, dst, vr, r);
2247
    return r;
2248
}
2249

    
2250
uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
2251
                 uint64_t vr)
2252
{
2253
    return do_calc_cc(env, cc_op, src, dst, vr);
2254
}
2255

    
2256
uint32_t HELPER(calc_cc)(uint32_t cc_op, uint64_t src, uint64_t dst,
2257
                         uint64_t vr)
2258
{
2259
    return do_calc_cc(env, cc_op, src, dst, vr);
2260
}
2261

    
2262
uint64_t HELPER(cvd)(int32_t bin)
2263
{
2264
    /* positive 0 */
2265
    uint64_t dec = 0x0c;
2266
    int shift = 4;
2267

    
2268
    if (bin < 0) {
2269
        bin = -bin;
2270
        dec = 0x0d;
2271
    }
2272

    
2273
    for (shift = 4; (shift < 64) && bin; shift += 4) {
2274
        int current_number = bin % 10;
2275

    
2276
        dec |= (current_number) << shift;
2277
        bin /= 10;
2278
    }
2279

    
2280
    return dec;
2281
}
2282

    
2283
void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
2284
{
2285
    int len_dest = len >> 4;
2286
    int len_src = len & 0xf;
2287
    uint8_t b;
2288
    int second_nibble = 0;
2289

    
2290
    dest += len_dest;
2291
    src += len_src;
2292

    
2293
    /* last byte is special, it only flips the nibbles */
2294
    b = ldub(src);
2295
    stb(dest, (b << 4) | (b >> 4));
2296
    src--;
2297
    len_src--;
2298

    
2299
    /* now pad every nibble with 0xf0 */
2300

    
2301
    while (len_dest > 0) {
2302
        uint8_t cur_byte = 0;
2303

    
2304
        if (len_src > 0) {
2305
            cur_byte = ldub(src);
2306
        }
2307

    
2308
        len_dest--;
2309
        dest--;
2310

    
2311
        /* only advance one nibble at a time */
2312
        if (second_nibble) {
2313
            cur_byte >>= 4;
2314
            len_src--;
2315
            src--;
2316
        }
2317
        second_nibble = !second_nibble;
2318

    
2319
        /* digit */
2320
        cur_byte = (cur_byte & 0xf);
2321
        /* zone bits */
2322
        cur_byte |= 0xf0;
2323

    
2324
        stb(dest, cur_byte);
2325
    }
2326
}
2327

    
2328
void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans)
2329
{
2330
    int i;
2331

    
2332
    for (i = 0; i <= len; i++) {
2333
        uint8_t byte = ldub(array + i);
2334
        uint8_t new_byte = ldub(trans + byte);
2335
        stb(array + i, new_byte);
2336
    }
2337
}
2338

    
2339
#ifndef CONFIG_USER_ONLY
2340

    
2341
void HELPER(load_psw)(uint64_t mask, uint64_t addr)
2342
{
2343
    load_psw(env, mask, addr);
2344
    cpu_loop_exit(env);
2345
}
2346

    
2347
static void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
2348
{
2349
    qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
2350

    
2351
    if (kvm_enabled()) {
2352
#ifdef CONFIG_KVM
2353
        kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
2354
#endif
2355
    } else {
2356
        env->int_pgm_code = code;
2357
        env->int_pgm_ilc = ilc;
2358
        env->exception_index = EXCP_PGM;
2359
        cpu_loop_exit(env);
2360
    }
2361
}
2362

    
2363
static void ext_interrupt(CPUS390XState *env, int type, uint32_t param,
2364
                          uint64_t param64)
2365
{
2366
    cpu_inject_ext(env, type, param, param64);
2367
}
2368

    
2369
int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
2370
{
2371
    int r = 0;
2372
    int shift = 0;
2373

    
2374
#ifdef DEBUG_HELPER
2375
    printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code);
2376
#endif
2377

    
2378
    if (sccb & ~0x7ffffff8ul) {
2379
        fprintf(stderr, "KVM: invalid sccb address 0x%x\n", sccb);
2380
        r = -1;
2381
        goto out;
2382
    }
2383

    
2384
    switch(code) {
2385
        case SCLP_CMDW_READ_SCP_INFO:
2386
        case SCLP_CMDW_READ_SCP_INFO_FORCED:
2387
            while ((ram_size >> (20 + shift)) > 65535) {
2388
                shift++;
2389
            }
2390
            stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift));
2391
            stb_phys(sccb + SCP_INCREMENT, 1 << shift);
2392
            stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
2393

    
2394
            if (kvm_enabled()) {
2395
#ifdef CONFIG_KVM
2396
                kvm_s390_interrupt_internal(env, KVM_S390_INT_SERVICE,
2397
                                            sccb & ~3, 0, 1);
2398
#endif
2399
            } else {
2400
                env->psw.addr += 4;
2401
                ext_interrupt(env, EXT_SERVICE, sccb & ~3, 0);
2402
            }
2403
            break;
2404
        default:
2405
#ifdef DEBUG_HELPER
2406
            printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
2407
#endif
2408
            r = -1;
2409
            break;
2410
    }
2411

    
2412
out:
2413
    return r;
2414
}
2415

    
2416
/* SCLP service call */
2417
uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
2418
{
2419
    if (sclp_service_call(env, r1, r2)) {
2420
        return 3;
2421
    }
2422

    
2423
    return 0;
2424
}
2425

    
2426
/* DIAG */
2427
uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
2428
{
2429
    uint64_t r;
2430

    
2431
    switch (num) {
2432
    case 0x500:
2433
        /* KVM hypercall */
2434
        r = s390_virtio_hypercall(env, mem, code);
2435
        break;
2436
    case 0x44:
2437
        /* yield */
2438
        r = 0;
2439
        break;
2440
    case 0x308:
2441
        /* ipl */
2442
        r = 0;
2443
        break;
2444
    default:
2445
        r = -1;
2446
        break;
2447
    }
2448

    
2449
    if (r) {
2450
        program_interrupt(env, PGM_OPERATION, ILC_LATER_INC);
2451
    }
2452

    
2453
    return r;
2454
}
2455

    
2456
/* Store CPU ID */
2457
void HELPER(stidp)(uint64_t a1)
2458
{
2459
    stq(a1, env->cpu_num);
2460
}
2461

    
2462
/* Set Prefix */
2463
void HELPER(spx)(uint64_t a1)
2464
{
2465
    uint32_t prefix;
2466

    
2467
    prefix = ldl(a1);
2468
    env->psa = prefix & 0xfffff000;
2469
    qemu_log("prefix: %#x\n", prefix);
2470
    tlb_flush_page(env, 0);
2471
    tlb_flush_page(env, TARGET_PAGE_SIZE);
2472
}
2473

    
2474
/* Set Clock */
2475
uint32_t HELPER(sck)(uint64_t a1)
2476
{
2477
    /* XXX not implemented - is it necessary? */
2478

    
2479
    return 0;
2480
}
2481

    
2482
static inline uint64_t clock_value(CPUS390XState *env)
2483
{
2484
    uint64_t time;
2485

    
2486
    time = env->tod_offset +
2487
           time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
2488

    
2489
    return time;
2490
}
2491

    
2492
/* Store Clock */
2493
uint32_t HELPER(stck)(uint64_t a1)
2494
{
2495
    stq(a1, clock_value(env));
2496

    
2497
    return 0;
2498
}
2499

    
2500
/* Store Clock Extended */
2501
uint32_t HELPER(stcke)(uint64_t a1)
2502
{
2503
    stb(a1, 0);
2504
    /* basically the same value as stck */
2505
    stq(a1 + 1, clock_value(env) | env->cpu_num);
2506
    /* more fine grained than stck */
2507
    stq(a1 + 9, 0);
2508
    /* XXX programmable fields */
2509
    stw(a1 + 17, 0);
2510

    
2511

    
2512
    return 0;
2513
}
2514

    
2515
/* Set Clock Comparator */
2516
void HELPER(sckc)(uint64_t a1)
2517
{
2518
    uint64_t time = ldq(a1);
2519

    
2520
    if (time == -1ULL) {
2521
        return;
2522
    }
2523

    
2524
    /* difference between now and then */
2525
    time -= clock_value(env);
2526
    /* nanoseconds */
2527
    time = (time * 125) >> 9;
2528

    
2529
    qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
2530
}
2531

    
2532
/* Store Clock Comparator */
2533
void HELPER(stckc)(uint64_t a1)
2534
{
2535
    /* XXX implement */
2536
    stq(a1, 0);
2537
}
2538

    
2539
/* Set CPU Timer */
2540
void HELPER(spt)(uint64_t a1)
2541
{
2542
    uint64_t time = ldq(a1);
2543

    
2544
    if (time == -1ULL) {
2545
        return;
2546
    }
2547

    
2548
    /* nanoseconds */
2549
    time = (time * 125) >> 9;
2550

    
2551
    qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
2552
}
2553

    
2554
/* Store CPU Timer */
2555
void HELPER(stpt)(uint64_t a1)
2556
{
2557
    /* XXX implement */
2558
    stq(a1, 0);
2559
}
2560

    
2561
/* Store System Information */
2562
uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
2563
{
2564
    int cc = 0;
2565
    int sel1, sel2;
2566

    
2567
    if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
2568
        ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
2569
        /* valid function code, invalid reserved bits */
2570
        program_interrupt(env, PGM_SPECIFICATION, 2);
2571
    }
2572

    
2573
    sel1 = r0 & STSI_R0_SEL1_MASK;
2574
    sel2 = r1 & STSI_R1_SEL2_MASK;
2575

    
2576
    /* XXX: spec exception if sysib is not 4k-aligned */
2577

    
2578
    switch (r0 & STSI_LEVEL_MASK) {
2579
    case STSI_LEVEL_1:
2580
        if ((sel1 == 1) && (sel2 == 1)) {
2581
            /* Basic Machine Configuration */
2582
            struct sysib_111 sysib;
2583

    
2584
            memset(&sysib, 0, sizeof(sysib));
2585
            ebcdic_put(sysib.manuf, "QEMU            ", 16);
2586
            /* same as machine type number in STORE CPU ID */
2587
            ebcdic_put(sysib.type, "QEMU", 4);
2588
            /* same as model number in STORE CPU ID */
2589
            ebcdic_put(sysib.model, "QEMU            ", 16);
2590
            ebcdic_put(sysib.sequence, "QEMU            ", 16);
2591
            ebcdic_put(sysib.plant, "QEMU", 4);
2592
            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2593
        } else if ((sel1 == 2) && (sel2 == 1)) {
2594
            /* Basic Machine CPU */
2595
            struct sysib_121 sysib;
2596

    
2597
            memset(&sysib, 0, sizeof(sysib));
2598
            /* XXX make different for different CPUs? */
2599
            ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
2600
            ebcdic_put(sysib.plant, "QEMU", 4);
2601
            stw_p(&sysib.cpu_addr, env->cpu_num);
2602
            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2603
        } else if ((sel1 == 2) && (sel2 == 2)) {
2604
            /* Basic Machine CPUs */
2605
            struct sysib_122 sysib;
2606

    
2607
            memset(&sysib, 0, sizeof(sysib));
2608
            stl_p(&sysib.capability, 0x443afc29);
2609
            /* XXX change when SMP comes */
2610
            stw_p(&sysib.total_cpus, 1);
2611
            stw_p(&sysib.active_cpus, 1);
2612
            stw_p(&sysib.standby_cpus, 0);
2613
            stw_p(&sysib.reserved_cpus, 0);
2614
            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2615
        } else {
2616
            cc = 3;
2617
        }
2618
        break;
2619
    case STSI_LEVEL_2:
2620
    {
2621
        if ((sel1 == 2) && (sel2 == 1)) {
2622
            /* LPAR CPU */
2623
            struct sysib_221 sysib;
2624

    
2625
            memset(&sysib, 0, sizeof(sysib));
2626
            /* XXX make different for different CPUs? */
2627
            ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
2628
            ebcdic_put(sysib.plant, "QEMU", 4);
2629
            stw_p(&sysib.cpu_addr, env->cpu_num);
2630
            stw_p(&sysib.cpu_id, 0);
2631
            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2632
        } else if ((sel1 == 2) && (sel2 == 2)) {
2633
            /* LPAR CPUs */
2634
            struct sysib_222 sysib;
2635

    
2636
            memset(&sysib, 0, sizeof(sysib));
2637
            stw_p(&sysib.lpar_num, 0);
2638
            sysib.lcpuc = 0;
2639
            /* XXX change when SMP comes */
2640
            stw_p(&sysib.total_cpus, 1);
2641
            stw_p(&sysib.conf_cpus, 1);
2642
            stw_p(&sysib.standby_cpus, 0);
2643
            stw_p(&sysib.reserved_cpus, 0);
2644
            ebcdic_put(sysib.name, "QEMU    ", 8);
2645
            stl_p(&sysib.caf, 1000);
2646
            stw_p(&sysib.dedicated_cpus, 0);
2647
            stw_p(&sysib.shared_cpus, 0);
2648
            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2649
        } else {
2650
            cc = 3;
2651
        }
2652
        break;
2653
    }
2654
    case STSI_LEVEL_3:
2655
    {
2656
        if ((sel1 == 2) && (sel2 == 2)) {
2657
            /* VM CPUs */
2658
            struct sysib_322 sysib;
2659

    
2660
            memset(&sysib, 0, sizeof(sysib));
2661
            sysib.count = 1;
2662
            /* XXX change when SMP comes */
2663
            stw_p(&sysib.vm[0].total_cpus, 1);
2664
            stw_p(&sysib.vm[0].conf_cpus, 1);
2665
            stw_p(&sysib.vm[0].standby_cpus, 0);
2666
            stw_p(&sysib.vm[0].reserved_cpus, 0);
2667
            ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
2668
            stl_p(&sysib.vm[0].caf, 1000);
2669
            ebcdic_put(sysib.vm[0].cpi, "KVM/Linux       ", 16);
2670
            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
2671
        } else {
2672
            cc = 3;
2673
        }
2674
        break;
2675
    }
2676
    case STSI_LEVEL_CURRENT:
2677
        env->regs[0] = STSI_LEVEL_3;
2678
        break;
2679
    default:
2680
        cc = 3;
2681
        break;
2682
    }
2683

    
2684
    return cc;
2685
}
2686

    
2687
void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3)
2688
{
2689
    int i;
2690
    uint64_t src = a2;
2691

    
2692
    for (i = r1;; i = (i + 1) % 16) {
2693
        env->cregs[i] = ldq(src);
2694
        HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
2695
                   i, src, env->cregs[i]);
2696
        src += sizeof(uint64_t);
2697

    
2698
        if (i == r3) {
2699
            break;
2700
        }
2701
    }
2702

    
2703
    tlb_flush(env, 1);
2704
}
2705

    
2706
void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3)
2707
{
2708
    int i;
2709
    uint64_t src = a2;
2710

    
2711
    for (i = r1;; i = (i + 1) % 16) {
2712
        env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | ldl(src);
2713
        src += sizeof(uint32_t);
2714

    
2715
        if (i == r3) {
2716
            break;
2717
        }
2718
    }
2719

    
2720
    tlb_flush(env, 1);
2721
}
2722

    
2723
void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3)
2724
{
2725
    int i;
2726
    uint64_t dest = a2;
2727

    
2728
    for (i = r1;; i = (i + 1) % 16) {
2729
        stq(dest, env->cregs[i]);
2730
        dest += sizeof(uint64_t);
2731

    
2732
        if (i == r3) {
2733
            break;
2734
        }
2735
    }
2736
}
2737

    
2738
void HELPER(stctl)(uint32_t r1, uint64_t a2, uint32_t r3)
2739
{
2740
    int i;
2741
    uint64_t dest = a2;
2742

    
2743
    for (i = r1;; i = (i + 1) % 16) {
2744
        stl(dest, env->cregs[i]);
2745
        dest += sizeof(uint32_t);
2746

    
2747
        if (i == r3) {
2748
            break;
2749
        }
2750
    }
2751
}
2752

    
2753
uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
2754
{
2755
    /* XXX implement */
2756

    
2757
    return 0;
2758
}
2759

    
2760
/* insert storage key extended */
2761
uint64_t HELPER(iske)(uint64_t r2)
2762
{
2763
    uint64_t addr = get_address(0, 0, r2);
2764

    
2765
    if (addr > ram_size) {
2766
        return 0;
2767
    }
2768

    
2769
    return env->storage_keys[addr / TARGET_PAGE_SIZE];
2770
}
2771

    
2772
/* set storage key extended */
2773
void HELPER(sske)(uint32_t r1, uint64_t r2)
2774
{
2775
    uint64_t addr = get_address(0, 0, r2);
2776

    
2777
    if (addr > ram_size) {
2778
        return;
2779
    }
2780

    
2781
    env->storage_keys[addr / TARGET_PAGE_SIZE] = r1;
2782
}
2783

    
2784
/* reset reference bit extended */
2785
uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
2786
{
2787
    uint8_t re;
2788
    uint8_t key;
2789
    if (r2 > ram_size) {
2790
        return 0;
2791
    }
2792

    
2793
    key = env->storage_keys[r2 / TARGET_PAGE_SIZE];
2794
    re = key & (SK_R | SK_C);
2795
    env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R);
2796

    
2797
    /*
2798
     * cc
2799
     *
2800
     * 0  Reference bit zero; change bit zero
2801
     * 1  Reference bit zero; change bit one
2802
     * 2  Reference bit one; change bit zero
2803
     * 3  Reference bit one; change bit one
2804
     */
2805

    
2806
    return re >> 1;
2807
}
2808

    
2809
/* compare and swap and purge */
2810
uint32_t HELPER(csp)(uint32_t r1, uint32_t r2)
2811
{
2812
    uint32_t cc;
2813
    uint32_t o1 = env->regs[r1];
2814
    uint64_t a2 = get_address_31fix(r2) & ~3ULL;
2815
    uint32_t o2 = ldl(a2);
2816

    
2817
    if (o1 == o2) {
2818
        stl(a2, env->regs[(r1 + 1) & 15]);
2819
        if (env->regs[r2] & 0x3) {
2820
            /* flush TLB / ALB */
2821
            tlb_flush(env, 1);
2822
        }
2823
        cc = 0;
2824
    } else {
2825
        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | o2;
2826
        cc = 1;
2827
    }
2828

    
2829
    return cc;
2830
}
2831

    
2832
static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
2833
                        uint64_t mode2)
2834
{
2835
    target_ulong src, dest;
2836
    int flags, cc = 0, i;
2837

    
2838
    if (!l) {
2839
        return 0;
2840
    } else if (l > 256) {
2841
        /* max 256 */
2842
        l = 256;
2843
        cc = 3;
2844
    }
2845

    
2846
    if (mmu_translate(env, a1 & TARGET_PAGE_MASK, 1, mode1, &dest, &flags)) {
2847
        cpu_loop_exit(env);
2848
    }
2849
    dest |= a1 & ~TARGET_PAGE_MASK;
2850

    
2851
    if (mmu_translate(env, a2 & TARGET_PAGE_MASK, 0, mode2, &src, &flags)) {
2852
        cpu_loop_exit(env);
2853
    }
2854
    src |= a2 & ~TARGET_PAGE_MASK;
2855

    
2856
    /* XXX replace w/ memcpy */
2857
    for (i = 0; i < l; i++) {
2858
        /* XXX be more clever */
2859
        if ((((dest + i) & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) ||
2860
            (((src + i) & TARGET_PAGE_MASK) != (src & TARGET_PAGE_MASK))) {
2861
            mvc_asc(l - i, a1 + i, mode1, a2 + i, mode2);
2862
            break;
2863
        }
2864
        stb_phys(dest + i, ldub_phys(src + i));
2865
    }
2866

    
2867
    return cc;
2868
}
2869

    
2870
uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2)
2871
{
2872
    HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
2873
               __FUNCTION__, l, a1, a2);
2874

    
2875
    return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
2876
}
2877

    
2878
uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2)
2879
{
2880
    HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
2881
               __FUNCTION__, l, a1, a2);
2882

    
2883
    return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY);
2884
}
2885

    
2886
uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
2887
{
2888
    int cc = 0;
2889

    
2890
    HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
2891
               __FUNCTION__, order_code, r1, cpu_addr);
2892

    
2893
    /* Remember: Use "R1 or R1+1, whichever is the odd-numbered register"
2894
       as parameter (input). Status (output) is always R1. */
2895

    
2896
    switch (order_code) {
2897
    case SIGP_SET_ARCH:
2898
        /* switch arch */
2899
        break;
2900
    case SIGP_SENSE:
2901
        /* enumerate CPU status */
2902
        if (cpu_addr) {
2903
            /* XXX implement when SMP comes */
2904
            return 3;
2905
        }
2906
        env->regs[r1] &= 0xffffffff00000000ULL;
2907
        cc = 1;
2908
        break;
2909
#if !defined (CONFIG_USER_ONLY)
2910
    case SIGP_RESTART:
2911
        qemu_system_reset_request();
2912
        cpu_loop_exit(env);
2913
        break;
2914
    case SIGP_STOP:
2915
        qemu_system_shutdown_request();
2916
        cpu_loop_exit(env);
2917
        break;
2918
#endif
2919
    default:
2920
        /* unknown sigp */
2921
        fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
2922
        cc = 3;
2923
    }
2924

    
2925
    return cc;
2926
}
2927

    
2928
void HELPER(sacf)(uint64_t a1)
2929
{
2930
    HELPER_LOG("%s: %16" PRIx64 "\n", __FUNCTION__, a1);
2931

    
2932
    switch (a1 & 0xf00) {
2933
    case 0x000:
2934
        env->psw.mask &= ~PSW_MASK_ASC;
2935
        env->psw.mask |= PSW_ASC_PRIMARY;
2936
        break;
2937
    case 0x100:
2938
        env->psw.mask &= ~PSW_MASK_ASC;
2939
        env->psw.mask |= PSW_ASC_SECONDARY;
2940
        break;
2941
    case 0x300:
2942
        env->psw.mask &= ~PSW_MASK_ASC;
2943
        env->psw.mask |= PSW_ASC_HOME;
2944
        break;
2945
    default:
2946
        qemu_log("unknown sacf mode: %" PRIx64 "\n", a1);
2947
        program_interrupt(env, PGM_SPECIFICATION, 2);
2948
        break;
2949
    }
2950
}
2951

    
2952
/* invalidate pte */
2953
void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
2954
{
2955
    uint64_t page = vaddr & TARGET_PAGE_MASK;
2956
    uint64_t pte = 0;
2957

    
2958
    /* XXX broadcast to other CPUs */
2959

    
2960
    /* XXX Linux is nice enough to give us the exact pte address.
2961
           According to spec we'd have to find it out ourselves */
2962
    /* XXX Linux is fine with overwriting the pte, the spec requires
2963
           us to only set the invalid bit */
2964
    stq_phys(pte_addr, pte | _PAGE_INVALID);
2965

    
2966
    /* XXX we exploit the fact that Linux passes the exact virtual
2967
           address here - it's not obliged to! */
2968
    tlb_flush_page(env, page);
2969

    
2970
    /* XXX 31-bit hack */
2971
    if (page & 0x80000000) {
2972
        tlb_flush_page(env, page & ~0x80000000);
2973
    } else {
2974
        tlb_flush_page(env, page | 0x80000000);
2975
    }
2976
}
2977

    
2978
/* flush local tlb */
2979
void HELPER(ptlb)(void)
2980
{
2981
    tlb_flush(env, 1);
2982
}
2983

    
2984
/* store using real address */
2985
void HELPER(stura)(uint64_t addr, uint32_t v1)
2986
{
2987
    stw_phys(get_address(0, 0, addr), v1);
2988
}
2989

    
2990
/* load real address */
2991
uint32_t HELPER(lra)(uint64_t addr, uint32_t r1)
2992
{
2993
    uint32_t cc = 0;
2994
    int old_exc = env->exception_index;
2995
    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
2996
    uint64_t ret;
2997
    int flags;
2998

    
2999
    /* XXX incomplete - has more corner cases */
3000
    if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) {
3001
        program_interrupt(env, PGM_SPECIAL_OP, 2);
3002
    }
3003

    
3004
    env->exception_index = old_exc;
3005
    if (mmu_translate(env, addr, 0, asc, &ret, &flags)) {
3006
        cc = 3;
3007
    }
3008
    if (env->exception_index == EXCP_PGM) {
3009
        ret = env->int_pgm_code | 0x80000000;
3010
    } else {
3011
        ret |= addr & ~TARGET_PAGE_MASK;
3012
    }
3013
    env->exception_index = old_exc;
3014

    
3015
    if (!(env->psw.mask & PSW_MASK_64)) {
3016
        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (ret & 0xffffffffULL);
3017
    } else {
3018
        env->regs[r1] = ret;
3019
    }
3020

    
3021
    return cc;
3022
}
3023

    
3024
#endif