Statistics
| Branch: | Revision:

root / target-s390x / op_helper.c @ 000a1a38

History | View | Annotate | Download (74.4 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 "memory.h"
23
#include "cputlb.h"
24
#include "dyngen-exec.h"
25
#include "host-utils.h"
26
#include "helper.h"
27
#include <string.h>
28
#include "kvm.h"
29
#include "qemu-timer.h"
30
#ifdef CONFIG_KVM
31
#include <linux/kvm.h>
32
#endif
33

    
34
#if !defined (CONFIG_USER_ONLY)
35
#include "sysemu.h"
36
#endif
37

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

    
43
#define MMUSUFFIX _mmu
44

    
45
#define SHIFT 0
46
#include "softmmu_template.h"
47

    
48
#define SHIFT 1
49
#include "softmmu_template.h"
50

    
51
#define SHIFT 2
52
#include "softmmu_template.h"
53

    
54
#define SHIFT 3
55
#include "softmmu_template.h"
56

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

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

    
86
#endif
87

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

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

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

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

    
119
    dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
120

    
121
    memset(dest_p, byte, len);
122

    
123
    cpu_physical_memory_unmap(dest_p, 1, len, len);
124
}
125

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

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

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

    
149
    dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
150
    src_p = cpu_physical_memory_map(src_phys, &len, 0);
151

    
152
    memmove(dest_p, src_p, len);
153

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
411
    return r;
412
}
413

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

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

    
423
    return r;
424
}
425

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

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

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

    
445
    return cc;
446
}
447

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

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

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

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

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

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

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

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

    
559
    return cc;
560
}
561

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

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

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

    
606
    return cc;
607
}
608

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

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

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

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

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

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

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

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

    
721
    return res;
722
}
723

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

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

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

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

    
768
    return cc;
769
}
770

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

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

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

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

    
792
        if (i == r3) {
793
            break;
794
        }
795
    }
796
}
797

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

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

    
807
        if (i == r3) {
808
            break;
809
        }
810
    }
811
}
812

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

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

    
832
    if (srclen > destlen) {
833
        srclen = destlen;
834
    }
835

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

    
841
    for (; destlen; dest++, destlen--) {
842
        stb(dest, pad);
843
    }
844

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

    
851
    return cc;
852
}
853

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

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

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

    
880
    if (srclen > destlen) {
881
        srclen = destlen;
882
    }
883

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

    
889
    for (; destlen; dest++, destlen--) {
890
        stb(dest, pad);
891
    }
892

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

    
900
    return cc;
901
}
902

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

    
914
    if (!(destlen || srclen)) {
915
        return cc;
916
    }
917

    
918
    if (srclen > destlen) {
919
        srclen = destlen;
920
    }
921

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

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

    
937
    return cc;
938
}
939

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1679
    /* FIXME: denormalized? */
1680
    return cc;
1681
}
1682

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

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

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

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

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

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

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

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

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

    
1761
    while (src_len >= 4) {
1762
        cksm += ldl(src);
1763

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1984

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2127
    r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63));
2128

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

    
2135
    return 2;
2136
}
2137

    
2138

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

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

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

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

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

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

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

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

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

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

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

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

    
2278
        dec |= (current_number) << shift;
2279
        bin /= 10;
2280
    }
2281

    
2282
    return dec;
2283
}
2284

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

    
2292
    dest += len_dest;
2293
    src += len_src;
2294

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

    
2301
    /* now pad every nibble with 0xf0 */
2302

    
2303
    while (len_dest > 0) {
2304
        uint8_t cur_byte = 0;
2305

    
2306
        if (len_src > 0) {
2307
            cur_byte = ldub(src);
2308
        }
2309

    
2310
        len_dest--;
2311
        dest--;
2312

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

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

    
2326
        stb(dest, cur_byte);
2327
    }
2328
}
2329

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

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

    
2341
#ifndef CONFIG_USER_ONLY
2342

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

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

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

    
2365
/*
2366
 * ret < 0 indicates program check, ret = 0,1,2,3 -> cc
2367
 */
2368
int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
2369
{
2370
    int r = 0;
2371
    int shift = 0;
2372

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

    
2377
    /* basic checks */
2378
    if (!memory_region_is_ram(phys_page_find(sccb >> TARGET_PAGE_BITS)->mr)) {
2379
        return -PGM_ADDRESSING;
2380
    }
2381
    if (sccb & ~0x7ffffff8ul) {
2382
        return -PGM_SPECIFICATION;
2383
    }
2384

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

    
2395
            s390_sclp_extint(sccb & ~3);
2396
            break;
2397
        default:
2398
#ifdef DEBUG_HELPER
2399
            printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
2400
#endif
2401
            r = 3;
2402
            break;
2403
    }
2404

    
2405
    return r;
2406
}
2407

    
2408
/* SCLP service call */
2409
uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
2410
{
2411
    int r;
2412

    
2413
    r = sclp_service_call(env, r1, r2);
2414
    if (r < 0) {
2415
        program_interrupt(env, -r, 4);
2416
        return 0;
2417
    }
2418
    return r;
2419
}
2420

    
2421
/* DIAG */
2422
uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
2423
{
2424
    uint64_t r;
2425

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

    
2444
    if (r) {
2445
        program_interrupt(env, PGM_OPERATION, ILC_LATER_INC);
2446
    }
2447

    
2448
    return r;
2449
}
2450

    
2451
/* Store CPU ID */
2452
void HELPER(stidp)(uint64_t a1)
2453
{
2454
    stq(a1, env->cpu_num);
2455
}
2456

    
2457
/* Set Prefix */
2458
void HELPER(spx)(uint64_t a1)
2459
{
2460
    uint32_t prefix;
2461

    
2462
    prefix = ldl(a1);
2463
    env->psa = prefix & 0xfffff000;
2464
    qemu_log("prefix: %#x\n", prefix);
2465
    tlb_flush_page(env, 0);
2466
    tlb_flush_page(env, TARGET_PAGE_SIZE);
2467
}
2468

    
2469
/* Set Clock */
2470
uint32_t HELPER(sck)(uint64_t a1)
2471
{
2472
    /* XXX not implemented - is it necessary? */
2473

    
2474
    return 0;
2475
}
2476

    
2477
static inline uint64_t clock_value(CPUS390XState *env)
2478
{
2479
    uint64_t time;
2480

    
2481
    time = env->tod_offset +
2482
           time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
2483

    
2484
    return time;
2485
}
2486

    
2487
/* Store Clock */
2488
uint32_t HELPER(stck)(uint64_t a1)
2489
{
2490
    stq(a1, clock_value(env));
2491

    
2492
    return 0;
2493
}
2494

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

    
2506

    
2507
    return 0;
2508
}
2509

    
2510
/* Set Clock Comparator */
2511
void HELPER(sckc)(uint64_t a1)
2512
{
2513
    uint64_t time = ldq(a1);
2514

    
2515
    if (time == -1ULL) {
2516
        return;
2517
    }
2518

    
2519
    /* difference between now and then */
2520
    time -= clock_value(env);
2521
    /* nanoseconds */
2522
    time = (time * 125) >> 9;
2523

    
2524
    qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
2525
}
2526

    
2527
/* Store Clock Comparator */
2528
void HELPER(stckc)(uint64_t a1)
2529
{
2530
    /* XXX implement */
2531
    stq(a1, 0);
2532
}
2533

    
2534
/* Set CPU Timer */
2535
void HELPER(spt)(uint64_t a1)
2536
{
2537
    uint64_t time = ldq(a1);
2538

    
2539
    if (time == -1ULL) {
2540
        return;
2541
    }
2542

    
2543
    /* nanoseconds */
2544
    time = (time * 125) >> 9;
2545

    
2546
    qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
2547
}
2548

    
2549
/* Store CPU Timer */
2550
void HELPER(stpt)(uint64_t a1)
2551
{
2552
    /* XXX implement */
2553
    stq(a1, 0);
2554
}
2555

    
2556
/* Store System Information */
2557
uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
2558
{
2559
    int cc = 0;
2560
    int sel1, sel2;
2561

    
2562
    if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
2563
        ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
2564
        /* valid function code, invalid reserved bits */
2565
        program_interrupt(env, PGM_SPECIFICATION, 2);
2566
    }
2567

    
2568
    sel1 = r0 & STSI_R0_SEL1_MASK;
2569
    sel2 = r1 & STSI_R1_SEL2_MASK;
2570

    
2571
    /* XXX: spec exception if sysib is not 4k-aligned */
2572

    
2573
    switch (r0 & STSI_LEVEL_MASK) {
2574
    case STSI_LEVEL_1:
2575
        if ((sel1 == 1) && (sel2 == 1)) {
2576
            /* Basic Machine Configuration */
2577
            struct sysib_111 sysib;
2578

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

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

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

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

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

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

    
2679
    return cc;
2680
}
2681

    
2682
void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3)
2683
{
2684
    int i;
2685
    uint64_t src = a2;
2686

    
2687
    for (i = r1;; i = (i + 1) % 16) {
2688
        env->cregs[i] = ldq(src);
2689
        HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
2690
                   i, src, env->cregs[i]);
2691
        src += sizeof(uint64_t);
2692

    
2693
        if (i == r3) {
2694
            break;
2695
        }
2696
    }
2697

    
2698
    tlb_flush(env, 1);
2699
}
2700

    
2701
void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3)
2702
{
2703
    int i;
2704
    uint64_t src = a2;
2705

    
2706
    for (i = r1;; i = (i + 1) % 16) {
2707
        env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | ldl(src);
2708
        src += sizeof(uint32_t);
2709

    
2710
        if (i == r3) {
2711
            break;
2712
        }
2713
    }
2714

    
2715
    tlb_flush(env, 1);
2716
}
2717

    
2718
void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3)
2719
{
2720
    int i;
2721
    uint64_t dest = a2;
2722

    
2723
    for (i = r1;; i = (i + 1) % 16) {
2724
        stq(dest, env->cregs[i]);
2725
        dest += sizeof(uint64_t);
2726

    
2727
        if (i == r3) {
2728
            break;
2729
        }
2730
    }
2731
}
2732

    
2733
void HELPER(stctl)(uint32_t r1, uint64_t a2, uint32_t r3)
2734
{
2735
    int i;
2736
    uint64_t dest = a2;
2737

    
2738
    for (i = r1;; i = (i + 1) % 16) {
2739
        stl(dest, env->cregs[i]);
2740
        dest += sizeof(uint32_t);
2741

    
2742
        if (i == r3) {
2743
            break;
2744
        }
2745
    }
2746
}
2747

    
2748
uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
2749
{
2750
    /* XXX implement */
2751

    
2752
    return 0;
2753
}
2754

    
2755
/* insert storage key extended */
2756
uint64_t HELPER(iske)(uint64_t r2)
2757
{
2758
    uint64_t addr = get_address(0, 0, r2);
2759

    
2760
    if (addr > ram_size) {
2761
        return 0;
2762
    }
2763

    
2764
    return env->storage_keys[addr / TARGET_PAGE_SIZE];
2765
}
2766

    
2767
/* set storage key extended */
2768
void HELPER(sske)(uint32_t r1, uint64_t r2)
2769
{
2770
    uint64_t addr = get_address(0, 0, r2);
2771

    
2772
    if (addr > ram_size) {
2773
        return;
2774
    }
2775

    
2776
    env->storage_keys[addr / TARGET_PAGE_SIZE] = r1;
2777
}
2778

    
2779
/* reset reference bit extended */
2780
uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
2781
{
2782
    uint8_t re;
2783
    uint8_t key;
2784
    if (r2 > ram_size) {
2785
        return 0;
2786
    }
2787

    
2788
    key = env->storage_keys[r2 / TARGET_PAGE_SIZE];
2789
    re = key & (SK_R | SK_C);
2790
    env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R);
2791

    
2792
    /*
2793
     * cc
2794
     *
2795
     * 0  Reference bit zero; change bit zero
2796
     * 1  Reference bit zero; change bit one
2797
     * 2  Reference bit one; change bit zero
2798
     * 3  Reference bit one; change bit one
2799
     */
2800

    
2801
    return re >> 1;
2802
}
2803

    
2804
/* compare and swap and purge */
2805
uint32_t HELPER(csp)(uint32_t r1, uint32_t r2)
2806
{
2807
    uint32_t cc;
2808
    uint32_t o1 = env->regs[r1];
2809
    uint64_t a2 = get_address_31fix(r2) & ~3ULL;
2810
    uint32_t o2 = ldl(a2);
2811

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

    
2824
    return cc;
2825
}
2826

    
2827
static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
2828
                        uint64_t mode2)
2829
{
2830
    target_ulong src, dest;
2831
    int flags, cc = 0, i;
2832

    
2833
    if (!l) {
2834
        return 0;
2835
    } else if (l > 256) {
2836
        /* max 256 */
2837
        l = 256;
2838
        cc = 3;
2839
    }
2840

    
2841
    if (mmu_translate(env, a1 & TARGET_PAGE_MASK, 1, mode1, &dest, &flags)) {
2842
        cpu_loop_exit(env);
2843
    }
2844
    dest |= a1 & ~TARGET_PAGE_MASK;
2845

    
2846
    if (mmu_translate(env, a2 & TARGET_PAGE_MASK, 0, mode2, &src, &flags)) {
2847
        cpu_loop_exit(env);
2848
    }
2849
    src |= a2 & ~TARGET_PAGE_MASK;
2850

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

    
2862
    return cc;
2863
}
2864

    
2865
uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2)
2866
{
2867
    HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
2868
               __FUNCTION__, l, a1, a2);
2869

    
2870
    return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
2871
}
2872

    
2873
uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2)
2874
{
2875
    HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
2876
               __FUNCTION__, l, a1, a2);
2877

    
2878
    return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY);
2879
}
2880

    
2881
uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
2882
{
2883
    int cc = 0;
2884

    
2885
    HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
2886
               __FUNCTION__, order_code, r1, cpu_addr);
2887

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

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

    
2920
    return cc;
2921
}
2922

    
2923
void HELPER(sacf)(uint64_t a1)
2924
{
2925
    HELPER_LOG("%s: %16" PRIx64 "\n", __FUNCTION__, a1);
2926

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

    
2947
/* invalidate pte */
2948
void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
2949
{
2950
    uint64_t page = vaddr & TARGET_PAGE_MASK;
2951
    uint64_t pte = 0;
2952

    
2953
    /* XXX broadcast to other CPUs */
2954

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

    
2961
    /* XXX we exploit the fact that Linux passes the exact virtual
2962
           address here - it's not obliged to! */
2963
    tlb_flush_page(env, page);
2964

    
2965
    /* XXX 31-bit hack */
2966
    if (page & 0x80000000) {
2967
        tlb_flush_page(env, page & ~0x80000000);
2968
    } else {
2969
        tlb_flush_page(env, page | 0x80000000);
2970
    }
2971
}
2972

    
2973
/* flush local tlb */
2974
void HELPER(ptlb)(void)
2975
{
2976
    tlb_flush(env, 1);
2977
}
2978

    
2979
/* store using real address */
2980
void HELPER(stura)(uint64_t addr, uint32_t v1)
2981
{
2982
    stw_phys(get_address(0, 0, addr), v1);
2983
}
2984

    
2985
/* load real address */
2986
uint32_t HELPER(lra)(uint64_t addr, uint32_t r1)
2987
{
2988
    uint32_t cc = 0;
2989
    int old_exc = env->exception_index;
2990
    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
2991
    uint64_t ret;
2992
    int flags;
2993

    
2994
    /* XXX incomplete - has more corner cases */
2995
    if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) {
2996
        program_interrupt(env, PGM_SPECIAL_OP, 2);
2997
    }
2998

    
2999
    env->exception_index = old_exc;
3000
    if (mmu_translate(env, addr, 0, asc, &ret, &flags)) {
3001
        cc = 3;
3002
    }
3003
    if (env->exception_index == EXCP_PGM) {
3004
        ret = env->int_pgm_code | 0x80000000;
3005
    } else {
3006
        ret |= addr & ~TARGET_PAGE_MASK;
3007
    }
3008
    env->exception_index = old_exc;
3009

    
3010
    if (!(env->psw.mask & PSW_MASK_64)) {
3011
        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (ret & 0xffffffffULL);
3012
    } else {
3013
        env->regs[r1] = ret;
3014
    }
3015

    
3016
    return cc;
3017
}
3018

    
3019
#endif