Statistics
| Branch: | Revision:

root / target-s390x / op_helper.c @ a825aefb

History | View | Annotate | Download (73.8 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 "exec.h"
22
#include "host-utils.h"
23
#include "helpers.h"
24
#include <string.h>
25
#include "kvm.h"
26
#include "qemu-timer.h"
27

    
28
/*****************************************************************************/
29
/* Softmmu support */
30
#if !defined (CONFIG_USER_ONLY)
31

    
32
#define MMUSUFFIX _mmu
33

    
34
#define SHIFT 0
35
#include "softmmu_template.h"
36

    
37
#define SHIFT 1
38
#include "softmmu_template.h"
39

    
40
#define SHIFT 2
41
#include "softmmu_template.h"
42

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

    
46
/* try to fill the TLB and return an exception if error. If retaddr is
47
   NULL, it means that the function was called in C code (i.e. not
48
   from generated code or from helper.c) */
49
/* XXX: fix it to restore all registers */
50
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
51
{
52
    TranslationBlock *tb;
53
    CPUState *saved_env;
54
    unsigned long pc;
55
    int ret;
56

    
57
    /* XXX: hack to restore env in all cases, even if not called from
58
       generated code */
59
    saved_env = env;
60
    env = cpu_single_env;
61
    ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
62
    if (unlikely(ret != 0)) {
63
        if (likely(retaddr)) {
64
            /* now we have a real cpu fault */
65
            pc = (unsigned long)retaddr;
66
            tb = tb_find_pc(pc);
67
            if (likely(tb)) {
68
                /* the PC is inside the translated code. It means that we have
69
                   a virtual CPU fault */
70
                cpu_restore_state(tb, env, pc);
71
            }
72
        }
73
        cpu_loop_exit();
74
    }
75
    env = saved_env;
76
}
77

    
78
#endif
79

    
80
/* #define DEBUG_HELPER */
81
#ifdef DEBUG_HELPER
82
#define HELPER_LOG(x...) qemu_log(x)
83
#else
84
#define HELPER_LOG(x...)
85
#endif
86

    
87
/* raise an exception */
88
void HELPER(exception)(uint32_t excp)
89
{
90
    HELPER_LOG("%s: exception %d\n", __FUNCTION__, excp);
91
    env->exception_index = excp;
92
    cpu_loop_exit();
93
}
94

    
95
#ifndef CONFIG_USER_ONLY
96
static void mvc_fast_memset(CPUState *env, uint32_t l, uint64_t dest,
97
                            uint8_t byte)
98
{
99
    target_phys_addr_t dest_phys;
100
    target_phys_addr_t len = l;
101
    void *dest_p;
102
    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
103
    int flags;
104

    
105
    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
106
        stb(dest, byte);
107
        cpu_abort(env, "should never reach here");
108
    }
109
    dest_phys |= dest & ~TARGET_PAGE_MASK;
110

    
111
    dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
112

    
113
    memset(dest_p, byte, len);
114

    
115
    cpu_physical_memory_unmap(dest_p, 1, len, len);
116
}
117

    
118
static void mvc_fast_memmove(CPUState *env, uint32_t l, uint64_t dest,
119
                             uint64_t src)
120
{
121
    target_phys_addr_t dest_phys;
122
    target_phys_addr_t src_phys;
123
    target_phys_addr_t len = l;
124
    void *dest_p;
125
    void *src_p;
126
    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
127
    int flags;
128

    
129
    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
130
        stb(dest, 0);
131
        cpu_abort(env, "should never reach here");
132
    }
133
    dest_phys |= dest & ~TARGET_PAGE_MASK;
134

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

    
141
    dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
142
    src_p = cpu_physical_memory_map(src_phys, &len, 0);
143

    
144
    memmove(dest_p, src_p, len);
145

    
146
    cpu_physical_memory_unmap(dest_p, 1, len, len);
147
    cpu_physical_memory_unmap(src_p, 0, len, len);
148
}
149
#endif
150

    
151
/* and on array */
152
uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src)
153
{
154
    int i;
155
    unsigned char x;
156
    uint32_t cc = 0;
157

    
158
    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
159
               __FUNCTION__, l, dest, src);
160
    for (i = 0; i <= l; i++) {
161
        x = ldub(dest + i) & ldub(src + i);
162
        if (x) {
163
            cc = 1;
164
        }
165
        stb(dest + i, x);
166
    }
167
    return cc;
168
}
169

    
170
/* xor on array */
171
uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src)
172
{
173
    int i;
174
    unsigned char x;
175
    uint32_t cc = 0;
176

    
177
    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
178
               __FUNCTION__, l, dest, src);
179

    
180
#ifndef CONFIG_USER_ONLY
181
    /* xor with itself is the same as memset(0) */
182
    if ((l > 32) && (src == dest) &&
183
        (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK)) {
184
        mvc_fast_memset(env, l + 1, dest, 0);
185
        return 0;
186
    }
187
#else
188
    if (src == dest) {
189
        memset(g2h(dest), 0, l + 1);
190
        return 0;
191
    }
192
#endif
193

    
194
    for (i = 0; i <= l; i++) {
195
        x = ldub(dest + i) ^ ldub(src + i);
196
        if (x) {
197
            cc = 1;
198
        }
199
        stb(dest + i, x);
200
    }
201
    return cc;
202
}
203

    
204
/* or on array */
205
uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src)
206
{
207
    int i;
208
    unsigned char x;
209
    uint32_t cc = 0;
210

    
211
    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
212
               __FUNCTION__, l, dest, src);
213
    for (i = 0; i <= l; i++) {
214
        x = ldub(dest + i) | ldub(src + i);
215
        if (x) {
216
            cc = 1;
217
        }
218
        stb(dest + i, x);
219
    }
220
    return cc;
221
}
222

    
223
/* memmove */
224
void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
225
{
226
    int i = 0;
227
    int x = 0;
228
    uint32_t l_64 = (l + 1) / 8;
229

    
230
    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
231
               __FUNCTION__, l, dest, src);
232

    
233
#ifndef CONFIG_USER_ONLY
234
    if ((l > 32) &&
235
        (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) &&
236
        (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) {
237
        if (dest == (src + 1)) {
238
            mvc_fast_memset(env, l + 1, dest, ldub(src));
239
            return;
240
        } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
241
            mvc_fast_memmove(env, l + 1, dest, src);
242
            return;
243
        }
244
    }
245
#else
246
    if (dest == (src + 1)) {
247
        memset(g2h(dest), ldub(src), l + 1);
248
        return;
249
    } else {
250
        memmove(g2h(dest), g2h(src), l + 1);
251
        return;
252
    }
253
#endif
254

    
255
    /* handle the parts that fit into 8-byte loads/stores */
256
    if (dest != (src + 1)) {
257
        for (i = 0; i < l_64; i++) {
258
            stq(dest + x, ldq(src + x));
259
            x += 8;
260
        }
261
    }
262

    
263
    /* slow version crossing pages with byte accesses */
264
    for (i = x; i <= l; i++) {
265
        stb(dest + i, ldub(src + i));
266
    }
267
}
268

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

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

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

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

    
358
/* 128 -> 64/64 unsigned division */
359
void HELPER(dlg)(uint32_t r1, uint64_t v2)
360
{
361
    uint64_t divisor = v2;
362

    
363
    if (!env->regs[r1]) {
364
        /* 64 -> 64/64 case */
365
        env->regs[r1] = env->regs[r1+1] % divisor;
366
        env->regs[r1+1] = env->regs[r1+1] / divisor;
367
        return;
368
    } else {
369

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

    
386
static inline uint64_t get_address(int x2, int b2, int d2)
387
{
388
    uint64_t r = d2;
389

    
390
    if (x2) {
391
        r += env->regs[x2];
392
    }
393

    
394
    if (b2) {
395
        r += env->regs[b2];
396
    }
397

    
398
    /* 31-Bit mode */
399
    if (!(env->psw.mask & PSW_MASK_64)) {
400
        r &= 0x7fffffff;
401
    }
402

    
403
    return r;
404
}
405

    
406
static inline uint64_t get_address_31fix(int reg)
407
{
408
    uint64_t r = env->regs[reg];
409

    
410
    /* 31-Bit mode */
411
    if (!(env->psw.mask & PSW_MASK_64)) {
412
        r &= 0x7fffffff;
413
    }
414

    
415
    return r;
416
}
417

    
418
/* search string (c is byte to search, r2 is string, r1 end of string) */
419
uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2)
420
{
421
    uint64_t i;
422
    uint32_t cc = 2;
423
    uint64_t str = get_address_31fix(r2);
424
    uint64_t end = get_address_31fix(r1);
425

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

    
429
    for (i = str; i != end; i++) {
430
        if (ldub(i) == c) {
431
            env->regs[r1] = i;
432
            cc = 1;
433
            break;
434
        }
435
    }
436

    
437
    return cc;
438
}
439

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

    
464
    if (v1 == v2) {
465
        cc = 0;
466
    } else {
467
        cc = (v1 < v2) ? 1 : 2;
468
        /* FIXME: 31-bit mode! */
469
        env->regs[r1] = s1;
470
        env->regs[r2] = s2;
471
    }
472
    return cc;
473
}
474

    
475
/* move page */
476
void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2)
477
{
478
    /* XXX missing r0 handling */
479
#ifdef CONFIG_USER_ONLY
480
    int i;
481

    
482
    for (i = 0; i < TARGET_PAGE_SIZE; i++) {
483
        stb(r1 + i, ldub(r2 + i));
484
    }
485
#else
486
    mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2);
487
#endif
488
}
489

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

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

    
531
/* compare double and swap 64-bit */
532
uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3)
533
{
534
    /* FIXME: locking? */
535
    uint32_t cc;
536
    uint64_t v2_hi = ldq(a2);
537
    uint64_t v2_lo = ldq(a2 + 8);
538
    uint64_t v1_hi = env->regs[r1];
539
    uint64_t v1_lo = env->regs[r1 + 1];
540

    
541
    if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) {
542
        cc = 0;
543
        stq(a2, env->regs[r3]);
544
        stq(a2 + 8, env->regs[r3 + 1]);
545
    } else {
546
        cc = 1;
547
        env->regs[r1] = v2_hi;
548
        env->regs[r1 + 1] = v2_lo;
549
    }
550

    
551
    return cc;
552
}
553

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

    
571
static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask)
572
{
573
    int pos = 24; /* top of the lower half of r1 */
574
    uint64_t rmask = 0xff000000ULL;
575
    uint8_t val = 0;
576
    int ccd = 0;
577
    uint32_t cc = 0;
578

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

    
598
    return cc;
599
}
600

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

    
658
/* absolute value 32-bit */
659
uint32_t HELPER(abs_i32)(int32_t val)
660
{
661
    if (val < 0) {
662
        return -val;
663
    } else {
664
        return val;
665
    }
666
}
667

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

    
678
/* absolute value 64-bit */
679
uint64_t HELPER(abs_i64)(int64_t val)
680
{
681
    HELPER_LOG("%s: val 0x%" PRIx64 "\n", __FUNCTION__, val);
682

    
683
    if (val < 0) {
684
        return -val;
685
    } else {
686
        return val;
687
    }
688
}
689

    
690
/* negative absolute value 64-bit */
691
int64_t HELPER(nabs_i64)(int64_t val)
692
{
693
    if (val < 0) {
694
        return val;
695
    } else {
696
        return -val;
697
    }
698
}
699

    
700
/* add with carry 32-bit unsigned */
701
uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
702
{
703
    uint32_t res;
704

    
705
    res = v1 + v2;
706
    if (cc & 2) {
707
        res++;
708
    }
709

    
710
    return res;
711
}
712

    
713
/* store character under mask high operates on the upper half of r1 */
714
void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask)
715
{
716
    int pos = 56; /* top of the upper half of r1 */
717

    
718
    while (mask) {
719
        if (mask & 8) {
720
            stb(address, (env->regs[r1] >> pos) & 0xff);
721
            address++;
722
        }
723
        mask = (mask << 1) & 0xf;
724
        pos -= 8;
725
    }
726
}
727

    
728
/* insert character under mask high; same as icm, but operates on the
729
   upper half of r1 */
730
uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask)
731
{
732
    int pos = 56; /* top of the upper half of r1 */
733
    uint64_t rmask = 0xff00000000000000ULL;
734
    uint8_t val = 0;
735
    int ccd = 0;
736
    uint32_t cc = 0;
737

    
738
    while (mask) {
739
        if (mask & 8) {
740
            env->regs[r1] &= ~rmask;
741
            val = ldub(address);
742
            if ((val & 0x80) && !ccd) {
743
                cc = 1;
744
            }
745
            ccd = 1;
746
            if (val && cc == 0) {
747
                cc = 2;
748
            }
749
            env->regs[r1] |= (uint64_t)val << pos;
750
            address++;
751
        }
752
        mask = (mask << 1) & 0xf;
753
        pos -= 8;
754
        rmask >>= 8;
755
    }
756

    
757
    return cc;
758
}
759

    
760
/* insert psw mask and condition code into r1 */
761
void HELPER(ipm)(uint32_t cc, uint32_t r1)
762
{
763
    uint64_t r = env->regs[r1];
764

    
765
    r &= 0xffffffff00ffffffULL;
766
    r |= (cc << 28) | ( (env->psw.mask >> 40) & 0xf );
767
    env->regs[r1] = r;
768
    HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __FUNCTION__,
769
               cc, env->psw.mask, r);
770
}
771

    
772
/* load access registers r1 to r3 from memory at a2 */
773
void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3)
774
{
775
    int i;
776

    
777
    for (i = r1;; i = (i + 1) % 16) {
778
        env->aregs[i] = ldl(a2);
779
        a2 += 4;
780

    
781
        if (i == r3) {
782
            break;
783
        }
784
    }
785
}
786

    
787
/* store access registers r1 to r3 in memory at a2 */
788
void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3)
789
{
790
    int i;
791

    
792
    for (i = r1;; i = (i + 1) % 16) {
793
        stl(a2, env->aregs[i]);
794
        a2 += 4;
795

    
796
        if (i == r3) {
797
            break;
798
        }
799
    }
800
}
801

    
802
/* move long */
803
uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2)
804
{
805
    uint64_t destlen = env->regs[r1 + 1] & 0xffffff;
806
    uint64_t dest = get_address_31fix(r1);
807
    uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
808
    uint64_t src = get_address_31fix(r2);
809
    uint8_t pad = src >> 24;
810
    uint8_t v;
811
    uint32_t cc;
812

    
813
    if (destlen == srclen) {
814
        cc = 0;
815
    } else if (destlen < srclen) {
816
        cc = 1;
817
    } else {
818
        cc = 2;
819
    }
820

    
821
    if (srclen > destlen) {
822
        srclen = destlen;
823
    }
824

    
825
    for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
826
        v = ldub(src);
827
        stb(dest, v);
828
    }
829

    
830
    for (; destlen; dest++, destlen--) {
831
        stb(dest, pad);
832
    }
833

    
834
    env->regs[r1 + 1] = destlen;
835
    /* can't use srclen here, we trunc'ed it */
836
    env->regs[r2 + 1] -= src - env->regs[r2];
837
    env->regs[r1] = dest;
838
    env->regs[r2] = src;
839

    
840
    return cc;
841
}
842

    
843
/* move long extended another memcopy insn with more bells and whistles */
844
uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3)
845
{
846
    uint64_t destlen = env->regs[r1 + 1];
847
    uint64_t dest = env->regs[r1];
848
    uint64_t srclen = env->regs[r3 + 1];
849
    uint64_t src = env->regs[r3];
850
    uint8_t pad = a2 & 0xff;
851
    uint8_t v;
852
    uint32_t cc;
853

    
854
    if (!(env->psw.mask & PSW_MASK_64)) {
855
        destlen = (uint32_t)destlen;
856
        srclen = (uint32_t)srclen;
857
        dest &= 0x7fffffff;
858
        src &= 0x7fffffff;
859
    }
860

    
861
    if (destlen == srclen) {
862
        cc = 0;
863
    } else if (destlen < srclen) {
864
        cc = 1;
865
    } else {
866
        cc = 2;
867
    }
868

    
869
    if (srclen > destlen) {
870
        srclen = destlen;
871
    }
872

    
873
    for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
874
        v = ldub(src);
875
        stb(dest, v);
876
    }
877

    
878
    for (; destlen; dest++, destlen--) {
879
        stb(dest, pad);
880
    }
881

    
882
    env->regs[r1 + 1] = destlen;
883
    /* can't use srclen here, we trunc'ed it */
884
    /* FIXME: 31-bit mode! */
885
    env->regs[r3 + 1] -= src - env->regs[r3];
886
    env->regs[r1] = dest;
887
    env->regs[r3] = src;
888

    
889
    return cc;
890
}
891

    
892
/* compare logical long extended memcompare insn with padding */
893
uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
894
{
895
    uint64_t destlen = env->regs[r1 + 1];
896
    uint64_t dest = get_address_31fix(r1);
897
    uint64_t srclen = env->regs[r3 + 1];
898
    uint64_t src = get_address_31fix(r3);
899
    uint8_t pad = a2 & 0xff;
900
    uint8_t v1 = 0,v2 = 0;
901
    uint32_t cc = 0;
902

    
903
    if (!(destlen || srclen)) {
904
        return cc;
905
    }
906

    
907
    if (srclen > destlen) {
908
        srclen = destlen;
909
    }
910

    
911
    for (; destlen || srclen; src++, dest++, destlen--, srclen--) {
912
        v1 = srclen ? ldub(src) : pad;
913
        v2 = destlen ? ldub(dest) : pad;
914
        if (v1 != v2) {
915
            cc = (v1 < v2) ? 1 : 2;
916
            break;
917
        }
918
    }
919

    
920
    env->regs[r1 + 1] = destlen;
921
    /* can't use srclen here, we trunc'ed it */
922
    env->regs[r3 + 1] -= src - env->regs[r3];
923
    env->regs[r1] = dest;
924
    env->regs[r3] = src;
925

    
926
    return cc;
927
}
928

    
929
/* subtract unsigned v2 from v1 with borrow */
930
uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
931
{
932
    uint32_t v1 = env->regs[r1];
933
    uint32_t res = v1 + (~v2) + (cc >> 1);
934

    
935
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res;
936
    if (cc & 2) {
937
        /* borrow */
938
        return v1 ? 1 : 0;
939
    } else {
940
        return v1 ? 3 : 2;
941
    }
942
}
943

    
944
/* subtract unsigned v2 from v1 with borrow */
945
uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
946
{
947
    uint64_t res = v1 + (~v2) + (cc >> 1);
948

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

    
958
static inline int float_comp_to_cc(int float_compare)
959
{
960
    switch (float_compare) {
961
    case float_relation_equal:
962
        return 0;
963
    case float_relation_less:
964
        return 1;
965
    case float_relation_greater:
966
        return 2;
967
    case float_relation_unordered:
968
        return 3;
969
    default:
970
        cpu_abort(env, "unknown return value for float compare\n");
971
    }
972
}
973

    
974
/* condition codes for binary FP ops */
975
static uint32_t set_cc_f32(float32 v1, float32 v2)
976
{
977
    return float_comp_to_cc(float32_compare_quiet(v1, v2, &env->fpu_status));
978
}
979

    
980
static uint32_t set_cc_f64(float64 v1, float64 v2)
981
{
982
    return float_comp_to_cc(float64_compare_quiet(v1, v2, &env->fpu_status));
983
}
984

    
985
/* condition codes for unary FP ops */
986
static uint32_t set_cc_nz_f32(float32 v)
987
{
988
    if (float32_is_any_nan(v)) {
989
        return 3;
990
    } else if (float32_is_zero(v)) {
991
        return 0;
992
    } else if (float32_is_neg(v)) {
993
        return 1;
994
    } else {
995
        return 2;
996
    }
997
}
998

    
999
static uint32_t set_cc_nz_f64(float64 v)
1000
{
1001
    if (float64_is_any_nan(v)) {
1002
        return 3;
1003
    } else if (float64_is_zero(v)) {
1004
        return 0;
1005
    } else if (float64_is_neg(v)) {
1006
        return 1;
1007
    } else {
1008
        return 2;
1009
    }
1010
}
1011

    
1012
static uint32_t set_cc_nz_f128(float128 v)
1013
{
1014
    if (float128_is_any_nan(v)) {
1015
        return 3;
1016
    } else if (float128_is_zero(v)) {
1017
        return 0;
1018
    } else if (float128_is_neg(v)) {
1019
        return 1;
1020
    } else {
1021
        return 2;
1022
    }
1023
}
1024

    
1025
/* convert 32-bit int to 64-bit float */
1026
void HELPER(cdfbr)(uint32_t f1, int32_t v2)
1027
{
1028
    HELPER_LOG("%s: converting %d to f%d\n", __FUNCTION__, v2, f1);
1029
    env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
1030
}
1031

    
1032
/* convert 32-bit int to 128-bit float */
1033
void HELPER(cxfbr)(uint32_t f1, int32_t v2)
1034
{
1035
    CPU_QuadU v1;
1036
    v1.q = int32_to_float128(v2, &env->fpu_status);
1037
    env->fregs[f1].ll = v1.ll.upper;
1038
    env->fregs[f1 + 2].ll = v1.ll.lower;
1039
}
1040

    
1041
/* convert 64-bit int to 32-bit float */
1042
void HELPER(cegbr)(uint32_t f1, int64_t v2)
1043
{
1044
    HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1);
1045
    env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
1046
}
1047

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

    
1055
/* convert 64-bit int to 128-bit float */
1056
void HELPER(cxgbr)(uint32_t f1, int64_t v2)
1057
{
1058
    CPU_QuadU x1;
1059
    x1.q = int64_to_float128(v2, &env->fpu_status);
1060
    HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __FUNCTION__, v2,
1061
               x1.ll.upper, x1.ll.lower);
1062
    env->fregs[f1].ll = x1.ll.upper;
1063
    env->fregs[f1 + 2].ll = x1.ll.lower;
1064
}
1065

    
1066
/* convert 32-bit int to 32-bit float */
1067
void HELPER(cefbr)(uint32_t f1, int32_t v2)
1068
{
1069
    env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
1070
    HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __FUNCTION__, v2,
1071
               env->fregs[f1].l.upper, f1);
1072
}
1073

    
1074
/* 32-bit FP addition RR */
1075
uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2)
1076
{
1077
    env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
1078
                                         env->fregs[f2].l.upper,
1079
                                         &env->fpu_status);
1080
    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__,
1081
               env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
1082

    
1083
    return set_cc_nz_f32(env->fregs[f1].l.upper);
1084
}
1085

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

    
1094
    return set_cc_nz_f64(env->fregs[f1].d);
1095
}
1096

    
1097
/* 32-bit FP subtraction RR */
1098
uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2)
1099
{
1100
    env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
1101
                                         env->fregs[f2].l.upper,
1102
                                         &env->fpu_status);
1103
    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__,
1104
               env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
1105

    
1106
    return set_cc_nz_f32(env->fregs[f1].l.upper);
1107
}
1108

    
1109
/* 64-bit FP subtraction RR */
1110
uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2)
1111
{
1112
    env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
1113
                                   &env->fpu_status);
1114
    HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
1115
               __FUNCTION__, env->fregs[f2].d, env->fregs[f1].d, f1);
1116

    
1117
    return set_cc_nz_f64(env->fregs[f1].d);
1118
}
1119

    
1120
/* 32-bit FP division RR */
1121
void HELPER(debr)(uint32_t f1, uint32_t f2)
1122
{
1123
    env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper,
1124
                                         env->fregs[f2].l.upper,
1125
                                         &env->fpu_status);
1126
}
1127

    
1128
/* 128-bit FP division RR */
1129
void HELPER(dxbr)(uint32_t f1, uint32_t f2)
1130
{
1131
    CPU_QuadU v1;
1132
    v1.ll.upper = env->fregs[f1].ll;
1133
    v1.ll.lower = env->fregs[f1 + 2].ll;
1134
    CPU_QuadU v2;
1135
    v2.ll.upper = env->fregs[f2].ll;
1136
    v2.ll.lower = env->fregs[f2 + 2].ll;
1137
    CPU_QuadU res;
1138
    res.q = float128_div(v1.q, v2.q, &env->fpu_status);
1139
    env->fregs[f1].ll = res.ll.upper;
1140
    env->fregs[f1 + 2].ll = res.ll.lower;
1141
}
1142

    
1143
/* 64-bit FP multiplication RR */
1144
void HELPER(mdbr)(uint32_t f1, uint32_t f2)
1145
{
1146
    env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d,
1147
                                   &env->fpu_status);
1148
}
1149

    
1150
/* 128-bit FP multiplication RR */
1151
void HELPER(mxbr)(uint32_t f1, uint32_t f2)
1152
{
1153
    CPU_QuadU v1;
1154
    v1.ll.upper = env->fregs[f1].ll;
1155
    v1.ll.lower = env->fregs[f1 + 2].ll;
1156
    CPU_QuadU v2;
1157
    v2.ll.upper = env->fregs[f2].ll;
1158
    v2.ll.lower = env->fregs[f2 + 2].ll;
1159
    CPU_QuadU res;
1160
    res.q = float128_mul(v1.q, v2.q, &env->fpu_status);
1161
    env->fregs[f1].ll = res.ll.upper;
1162
    env->fregs[f1 + 2].ll = res.ll.lower;
1163
}
1164

    
1165
/* convert 32-bit float to 64-bit float */
1166
void HELPER(ldebr)(uint32_t r1, uint32_t r2)
1167
{
1168
    env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
1169
                                          &env->fpu_status);
1170
}
1171

    
1172
/* convert 128-bit float to 64-bit float */
1173
void HELPER(ldxbr)(uint32_t f1, uint32_t f2)
1174
{
1175
    CPU_QuadU x2;
1176
    x2.ll.upper = env->fregs[f2].ll;
1177
    x2.ll.lower = env->fregs[f2 + 2].ll;
1178
    env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status);
1179
    HELPER_LOG("%s: to 0x%ld\n", __FUNCTION__, env->fregs[f1].d);
1180
}
1181

    
1182
/* convert 64-bit float to 128-bit float */
1183
void HELPER(lxdbr)(uint32_t f1, uint32_t f2)
1184
{
1185
    CPU_QuadU res;
1186
    res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status);
1187
    env->fregs[f1].ll = res.ll.upper;
1188
    env->fregs[f1 + 2].ll = res.ll.lower;
1189
}
1190

    
1191
/* convert 64-bit float to 32-bit float */
1192
void HELPER(ledbr)(uint32_t f1, uint32_t f2)
1193
{
1194
    float64 d2 = env->fregs[f2].d;
1195
    env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
1196
}
1197

    
1198
/* convert 128-bit float to 32-bit float */
1199
void HELPER(lexbr)(uint32_t f1, uint32_t f2)
1200
{
1201
    CPU_QuadU x2;
1202
    x2.ll.upper = env->fregs[f2].ll;
1203
    x2.ll.lower = env->fregs[f2 + 2].ll;
1204
    env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status);
1205
    HELPER_LOG("%s: to 0x%d\n", __FUNCTION__, env->fregs[f1].l.upper);
1206
}
1207

    
1208
/* absolute value of 32-bit float */
1209
uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2)
1210
{
1211
    float32 v1;
1212
    float32 v2 = env->fregs[f2].d;
1213
    v1 = float32_abs(v2);
1214
    env->fregs[f1].d = v1;
1215
    return set_cc_nz_f32(v1);
1216
}
1217

    
1218
/* absolute value of 64-bit float */
1219
uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2)
1220
{
1221
    float64 v1;
1222
    float64 v2 = env->fregs[f2].d;
1223
    v1 = float64_abs(v2);
1224
    env->fregs[f1].d = v1;
1225
    return set_cc_nz_f64(v1);
1226
}
1227

    
1228
/* absolute value of 128-bit float */
1229
uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2)
1230
{
1231
    CPU_QuadU v1;
1232
    CPU_QuadU v2;
1233
    v2.ll.upper = env->fregs[f2].ll;
1234
    v2.ll.lower = env->fregs[f2 + 2].ll;
1235
    v1.q = float128_abs(v2.q);
1236
    env->fregs[f1].ll = v1.ll.upper;
1237
    env->fregs[f1 + 2].ll = v1.ll.lower;
1238
    return set_cc_nz_f128(v1.q);
1239
}
1240

    
1241
/* load and test 64-bit float */
1242
uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2)
1243
{
1244
    env->fregs[f1].d = env->fregs[f2].d;
1245
    return set_cc_nz_f64(env->fregs[f1].d);
1246
}
1247

    
1248
/* load and test 32-bit float */
1249
uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2)
1250
{
1251
    env->fregs[f1].l.upper = env->fregs[f2].l.upper;
1252
    return set_cc_nz_f32(env->fregs[f1].l.upper);
1253
}
1254

    
1255
/* load and test 128-bit float */
1256
uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2)
1257
{
1258
    CPU_QuadU x;
1259
    x.ll.upper = env->fregs[f2].ll;
1260
    x.ll.lower = env->fregs[f2 + 2].ll;
1261
    env->fregs[f1].ll = x.ll.upper;
1262
    env->fregs[f1 + 2].ll = x.ll.lower;
1263
    return set_cc_nz_f128(x.q);
1264
}
1265

    
1266
/* load complement of 32-bit float */
1267
uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2)
1268
{
1269
    env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
1270

    
1271
    return set_cc_nz_f32(env->fregs[f1].l.upper);
1272
}
1273

    
1274
/* load complement of 64-bit float */
1275
uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2)
1276
{
1277
    env->fregs[f1].d = float64_chs(env->fregs[f2].d);
1278

    
1279
    return set_cc_nz_f64(env->fregs[f1].d);
1280
}
1281

    
1282
/* load complement of 128-bit float */
1283
uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2)
1284
{
1285
    CPU_QuadU x1, x2;
1286
    x2.ll.upper = env->fregs[f2].ll;
1287
    x2.ll.lower = env->fregs[f2 + 2].ll;
1288
    x1.q = float128_chs(x2.q);
1289
    env->fregs[f1].ll = x1.ll.upper;
1290
    env->fregs[f1 + 2].ll = x1.ll.lower;
1291
    return set_cc_nz_f128(x1.q);
1292
}
1293

    
1294
/* 32-bit FP addition RM */
1295
void HELPER(aeb)(uint32_t f1, uint32_t val)
1296
{
1297
    float32 v1 = env->fregs[f1].l.upper;
1298
    CPU_FloatU v2;
1299
    v2.l = val;
1300
    HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __FUNCTION__,
1301
               v1, f1, v2.f);
1302
    env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
1303
}
1304

    
1305
/* 32-bit FP division RM */
1306
void HELPER(deb)(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: dividing 0x%d from f%d by 0x%d\n", __FUNCTION__,
1312
               v1, f1, v2.f);
1313
    env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
1314
}
1315

    
1316
/* 32-bit FP multiplication RM */
1317
void HELPER(meeb)(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: multiplying 0x%d from f%d and 0x%d\n", __FUNCTION__,
1323
               v1, f1, v2.f);
1324
    env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
1325
}
1326

    
1327
/* 32-bit FP compare RR */
1328
uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2)
1329
{
1330
    float32 v1 = env->fregs[f1].l.upper;
1331
    float32 v2 = env->fregs[f2].l.upper;;
1332
    HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __FUNCTION__,
1333
               v1, f1, v2);
1334
    return set_cc_f32(v1, v2);
1335
}
1336

    
1337
/* 64-bit FP compare RR */
1338
uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2)
1339
{
1340
    float64 v1 = env->fregs[f1].d;
1341
    float64 v2 = env->fregs[f2].d;;
1342
    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __FUNCTION__,
1343
               v1, f1, v2);
1344
    return set_cc_f64(v1, v2);
1345
}
1346

    
1347
/* 128-bit FP compare RR */
1348
uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2)
1349
{
1350
    CPU_QuadU v1;
1351
    v1.ll.upper = env->fregs[f1].ll;
1352
    v1.ll.lower = env->fregs[f1 + 2].ll;
1353
    CPU_QuadU v2;
1354
    v2.ll.upper = env->fregs[f2].ll;
1355
    v2.ll.lower = env->fregs[f2 + 2].ll;
1356

    
1357
    return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q,
1358
                            &env->fpu_status));
1359
}
1360

    
1361
/* 64-bit FP compare RM */
1362
uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2)
1363
{
1364
    float64 v1 = env->fregs[f1].d;
1365
    CPU_DoubleU v2;
1366
    v2.ll = ldq(a2);
1367
    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __FUNCTION__, v1,
1368
               f1, v2.d);
1369
    return set_cc_f64(v1, v2.d);
1370
}
1371

    
1372
/* 64-bit FP addition RM */
1373
uint32_t HELPER(adb)(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: adding 0x%lx from f%d and 0x%lx\n", __FUNCTION__,
1379
               v1, f1, v2.d);
1380
    env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
1381
    return set_cc_nz_f64(v1);
1382
}
1383

    
1384
/* 32-bit FP subtraction RM */
1385
void HELPER(seb)(uint32_t f1, uint32_t val)
1386
{
1387
    float32 v1 = env->fregs[f1].l.upper;
1388
    CPU_FloatU v2;
1389
    v2.l = val;
1390
    env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status);
1391
}
1392

    
1393
/* 64-bit FP subtraction RM */
1394
uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2)
1395
{
1396
    float64 v1 = env->fregs[f1].d;
1397
    CPU_DoubleU v2;
1398
    v2.ll = ldq(a2);
1399
    env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
1400
    return set_cc_nz_f64(v1);
1401
}
1402

    
1403
/* 64-bit FP multiplication RM */
1404
void HELPER(mdb)(uint32_t f1, uint64_t a2)
1405
{
1406
    float64 v1 = env->fregs[f1].d;
1407
    CPU_DoubleU v2;
1408
    v2.ll = ldq(a2);
1409
    HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __FUNCTION__,
1410
               v1, f1, v2.d);
1411
    env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
1412
}
1413

    
1414
/* 64-bit FP division RM */
1415
void HELPER(ddb)(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: dividing 0x%lx from f%d by 0x%ld\n", __FUNCTION__,
1421
               v1, f1, v2.d);
1422
    env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
1423
}
1424

    
1425
static void set_round_mode(int m3)
1426
{
1427
    switch (m3) {
1428
    case 0:
1429
        /* current mode */
1430
        break;
1431
    case 1:
1432
        /* biased round no nearest */
1433
    case 4:
1434
        /* round to nearest */
1435
        set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
1436
        break;
1437
    case 5:
1438
        /* round to zero */
1439
        set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
1440
        break;
1441
    case 6:
1442
        /* round to +inf */
1443
        set_float_rounding_mode(float_round_up, &env->fpu_status);
1444
        break;
1445
    case 7:
1446
        /* round to -inf */
1447
        set_float_rounding_mode(float_round_down, &env->fpu_status);
1448
        break;
1449
    }
1450
}
1451

    
1452
/* convert 32-bit float to 64-bit int */
1453
uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3)
1454
{
1455
    float32 v2 = env->fregs[f2].l.upper;
1456
    set_round_mode(m3);
1457
    env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
1458
    return set_cc_nz_f32(v2);
1459
}
1460

    
1461
/* convert 64-bit float to 64-bit int */
1462
uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1463
{
1464
    float64 v2 = env->fregs[f2].d;
1465
    set_round_mode(m3);
1466
    env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
1467
    return set_cc_nz_f64(v2);
1468
}
1469

    
1470
/* convert 128-bit float to 64-bit int */
1471
uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1472
{
1473
    CPU_QuadU v2;
1474
    v2.ll.upper = env->fregs[f2].ll;
1475
    v2.ll.lower = env->fregs[f2 + 2].ll;
1476
    set_round_mode(m3);
1477
    env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
1478
    if (float128_is_any_nan(v2.q)) {
1479
        return 3;
1480
    } else if (float128_is_zero(v2.q)) {
1481
        return 0;
1482
    } else if (float128_is_neg(v2.q)) {
1483
        return 1;
1484
    } else {
1485
        return 2;
1486
    }
1487
}
1488

    
1489
/* convert 32-bit float to 32-bit int */
1490
uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3)
1491
{
1492
    float32 v2 = env->fregs[f2].l.upper;
1493
    set_round_mode(m3);
1494
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
1495
                     float32_to_int32(v2, &env->fpu_status);
1496
    return set_cc_nz_f32(v2);
1497
}
1498

    
1499
/* convert 64-bit float to 32-bit int */
1500
uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1501
{
1502
    float64 v2 = env->fregs[f2].d;
1503
    set_round_mode(m3);
1504
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
1505
                     float64_to_int32(v2, &env->fpu_status);
1506
    return set_cc_nz_f64(v2);
1507
}
1508

    
1509
/* convert 128-bit float to 32-bit int */
1510
uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
1511
{
1512
    CPU_QuadU v2;
1513
    v2.ll.upper = env->fregs[f2].ll;
1514
    v2.ll.lower = env->fregs[f2 + 2].ll;
1515
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
1516
                     float128_to_int32(v2.q, &env->fpu_status);
1517
    return set_cc_nz_f128(v2.q);
1518
}
1519

    
1520
/* load 32-bit FP zero */
1521
void HELPER(lzer)(uint32_t f1)
1522
{
1523
    env->fregs[f1].l.upper = float32_zero;
1524
}
1525

    
1526
/* load 64-bit FP zero */
1527
void HELPER(lzdr)(uint32_t f1)
1528
{
1529
    env->fregs[f1].d = float64_zero;
1530
}
1531

    
1532
/* load 128-bit FP zero */
1533
void HELPER(lzxr)(uint32_t f1)
1534
{
1535
    CPU_QuadU x;
1536
    x.q = float64_to_float128(float64_zero, &env->fpu_status);
1537
    env->fregs[f1].ll = x.ll.upper;
1538
    env->fregs[f1 + 1].ll = x.ll.lower;
1539
}
1540

    
1541
/* 128-bit FP subtraction RR */
1542
uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2)
1543
{
1544
    CPU_QuadU v1;
1545
    v1.ll.upper = env->fregs[f1].ll;
1546
    v1.ll.lower = env->fregs[f1 + 2].ll;
1547
    CPU_QuadU v2;
1548
    v2.ll.upper = env->fregs[f2].ll;
1549
    v2.ll.lower = env->fregs[f2 + 2].ll;
1550
    CPU_QuadU res;
1551
    res.q = float128_sub(v1.q, v2.q, &env->fpu_status);
1552
    env->fregs[f1].ll = res.ll.upper;
1553
    env->fregs[f1 + 2].ll = res.ll.lower;
1554
    return set_cc_nz_f128(res.q);
1555
}
1556

    
1557
/* 128-bit FP addition RR */
1558
uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2)
1559
{
1560
    CPU_QuadU v1;
1561
    v1.ll.upper = env->fregs[f1].ll;
1562
    v1.ll.lower = env->fregs[f1 + 2].ll;
1563
    CPU_QuadU v2;
1564
    v2.ll.upper = env->fregs[f2].ll;
1565
    v2.ll.lower = env->fregs[f2 + 2].ll;
1566
    CPU_QuadU res;
1567
    res.q = float128_add(v1.q, v2.q, &env->fpu_status);
1568
    env->fregs[f1].ll = res.ll.upper;
1569
    env->fregs[f1 + 2].ll = res.ll.lower;
1570
    return set_cc_nz_f128(res.q);
1571
}
1572

    
1573
/* 32-bit FP multiplication RR */
1574
void HELPER(meebr)(uint32_t f1, uint32_t f2)
1575
{
1576
    env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper,
1577
                                         env->fregs[f2].l.upper,
1578
                                         &env->fpu_status);
1579
}
1580

    
1581
/* 64-bit FP division RR */
1582
void HELPER(ddbr)(uint32_t f1, uint32_t f2)
1583
{
1584
    env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d,
1585
                                   &env->fpu_status);
1586
}
1587

    
1588
/* 64-bit FP multiply and add RM */
1589
void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3)
1590
{
1591
    HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __FUNCTION__, f1, a2, f3);
1592
    CPU_DoubleU v2;
1593
    v2.ll = ldq(a2);
1594
    env->fregs[f1].d = float64_add(env->fregs[f1].d,
1595
                                   float64_mul(v2.d, env->fregs[f3].d,
1596
                                               &env->fpu_status),
1597
                                   &env->fpu_status);
1598
}
1599

    
1600
/* 64-bit FP multiply and add RR */
1601
void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2)
1602
{
1603
    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3);
1604
    env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d,
1605
                                               env->fregs[f3].d,
1606
                                               &env->fpu_status),
1607
                                   env->fregs[f1].d, &env->fpu_status);
1608
}
1609

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

    
1620
/* 32-bit FP multiply and add RR */
1621
void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
1622
{
1623
    env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
1624
                                         float32_mul(env->fregs[f2].l.upper,
1625
                                                     env->fregs[f3].l.upper,
1626
                                                     &env->fpu_status),
1627
                                         &env->fpu_status);
1628
}
1629

    
1630
/* convert 64-bit float to 128-bit float */
1631
void HELPER(lxdb)(uint32_t f1, uint64_t a2)
1632
{
1633
    CPU_DoubleU v2;
1634
    v2.ll = ldq(a2);
1635
    CPU_QuadU v1;
1636
    v1.q = float64_to_float128(v2.d, &env->fpu_status);
1637
    env->fregs[f1].ll = v1.ll.upper;
1638
    env->fregs[f1 + 2].ll = v1.ll.lower;
1639
}
1640

    
1641
/* test data class 32-bit */
1642
uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2)
1643
{
1644
    float32 v1 = env->fregs[f1].l.upper;
1645
    int neg = float32_is_neg(v1);
1646
    uint32_t cc = 0;
1647

    
1648
    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, (long)v1, m2, neg);
1649
    if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
1650
        (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
1651
        (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
1652
        (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
1653
        cc = 1;
1654
    } else if (m2 & (1 << (9-neg))) {
1655
        /* assume normalized number */
1656
        cc = 1;
1657
    }
1658

    
1659
    /* FIXME: denormalized? */
1660
    return cc;
1661
}
1662

    
1663
/* test data class 64-bit */
1664
uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2)
1665
{
1666
    float64 v1 = env->fregs[f1].d;
1667
    int neg = float64_is_neg(v1);
1668
    uint32_t cc = 0;
1669

    
1670
    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, v1, m2, neg);
1671
    if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
1672
        (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
1673
        (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
1674
        (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
1675
        cc = 1;
1676
    } else if (m2 & (1 << (9-neg))) {
1677
        /* assume normalized number */
1678
        cc = 1;
1679
    }
1680
    /* FIXME: denormalized? */
1681
    return cc;
1682
}
1683

    
1684
/* test data class 128-bit */
1685
uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2)
1686
{
1687
    CPU_QuadU v1;
1688
    uint32_t cc = 0;
1689
    v1.ll.upper = env->fregs[f1].ll;
1690
    v1.ll.lower = env->fregs[f1 + 2].ll;
1691

    
1692
    int neg = float128_is_neg(v1.q);
1693
    if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
1694
        (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
1695
        (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
1696
        (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) {
1697
        cc = 1;
1698
    } else if (m2 & (1 << (9-neg))) {
1699
        /* assume normalized number */
1700
        cc = 1;
1701
    }
1702
    /* FIXME: denormalized? */
1703
    return cc;
1704
}
1705

    
1706
/* find leftmost one */
1707
uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
1708
{
1709
    uint64_t res = 0;
1710
    uint64_t ov2 = v2;
1711

    
1712
    while (!(v2 & 0x8000000000000000ULL) && v2) {
1713
        v2 <<= 1;
1714
        res++;
1715
    }
1716

    
1717
    if (!v2) {
1718
        env->regs[r1] = 64;
1719
        env->regs[r1 + 1] = 0;
1720
        return 0;
1721
    } else {
1722
        env->regs[r1] = res;
1723
        env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res);
1724
        return 2;
1725
    }
1726
}
1727

    
1728
/* square root 64-bit RR */
1729
void HELPER(sqdbr)(uint32_t f1, uint32_t f2)
1730
{
1731
    env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
1732
}
1733

    
1734
static inline uint64_t cksm_overflow(uint64_t cksm)
1735
{
1736
    if (cksm > 0xffffffffULL) {
1737
        cksm &= 0xffffffffULL;
1738
        cksm++;
1739
    }
1740
    return cksm;
1741
}
1742

    
1743
/* checksum */
1744
void HELPER(cksm)(uint32_t r1, uint32_t r2)
1745
{
1746
    uint64_t src = get_address_31fix(r2);
1747
    uint64_t src_len = env->regs[(r2 + 1) & 15];
1748
    uint64_t cksm = 0;
1749

    
1750
    while (src_len >= 4) {
1751
        cksm += ldl(src);
1752
        cksm = cksm_overflow(cksm);
1753

    
1754
        /* move to next word */
1755
        src_len -= 4;
1756
        src += 4;
1757
    }
1758

    
1759
    switch (src_len) {
1760
    case 0:
1761
        break;
1762
    case 1:
1763
        cksm += ldub(src);
1764
        cksm = cksm_overflow(cksm);
1765
        break;
1766
    case 2:
1767
        cksm += lduw(src);
1768
        cksm = cksm_overflow(cksm);
1769
        break;
1770
    case 3:
1771
        /* XXX check if this really is correct */
1772
        cksm += lduw(src) << 8;
1773
        cksm += ldub(src + 2);
1774
        cksm = cksm_overflow(cksm);
1775
        break;
1776
    }
1777

    
1778
    /* indicate we've processed everything */
1779
    env->regs[(r2 + 1) & 15] = 0;
1780

    
1781
    /* store result */
1782
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (uint32_t)cksm;
1783
}
1784

    
1785
static inline uint32_t cc_calc_ltgt_32(CPUState *env, int32_t src,
1786
                                       int32_t dst)
1787
{
1788
    if (src == dst) {
1789
        return 0;
1790
    } else if (src < dst) {
1791
        return 1;
1792
    } else {
1793
        return 2;
1794
    }
1795
}
1796

    
1797
static inline uint32_t cc_calc_ltgt0_32(CPUState *env, int32_t dst)
1798
{
1799
    return cc_calc_ltgt_32(env, dst, 0);
1800
}
1801

    
1802
static inline uint32_t cc_calc_ltgt_64(CPUState *env, int64_t src,
1803
                                       int64_t dst)
1804
{
1805
    if (src == dst) {
1806
        return 0;
1807
    } else if (src < dst) {
1808
        return 1;
1809
    } else {
1810
        return 2;
1811
    }
1812
}
1813

    
1814
static inline uint32_t cc_calc_ltgt0_64(CPUState *env, int64_t dst)
1815
{
1816
    return cc_calc_ltgt_64(env, dst, 0);
1817
}
1818

    
1819
static inline uint32_t cc_calc_ltugtu_32(CPUState *env, uint32_t src,
1820
                                         uint32_t dst)
1821
{
1822
    if (src == dst) {
1823
        return 0;
1824
    } else if (src < dst) {
1825
        return 1;
1826
    } else {
1827
        return 2;
1828
    }
1829
}
1830

    
1831
static inline uint32_t cc_calc_ltugtu_64(CPUState *env, uint64_t src,
1832
                                         uint64_t dst)
1833
{
1834
    if (src == dst) {
1835
        return 0;
1836
    } else if (src < dst) {
1837
        return 1;
1838
    } else {
1839
        return 2;
1840
    }
1841
}
1842

    
1843
static inline uint32_t cc_calc_tm_32(CPUState *env, uint32_t val, uint32_t mask)
1844
{
1845
    HELPER_LOG("%s: val 0x%x mask 0x%x\n", __FUNCTION__, val, mask);
1846
    uint16_t r = val & mask;
1847
    if (r == 0 || mask == 0) {
1848
        return 0;
1849
    } else if (r == mask) {
1850
        return 3;
1851
    } else {
1852
        return 1;
1853
    }
1854
}
1855

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

    
1878
static inline uint32_t cc_calc_nz(CPUState *env, uint64_t dst)
1879
{
1880
    return !!dst;
1881
}
1882

    
1883
static inline uint32_t cc_calc_add_64(CPUState *env, int64_t a1, int64_t a2,
1884
                                      int64_t ar)
1885
{
1886
    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
1887
        return 3; /* overflow */
1888
    } else {
1889
        if (ar < 0) {
1890
            return 1;
1891
        } else if (ar > 0) {
1892
            return 2;
1893
        } else {
1894
            return 0;
1895
        }
1896
    }
1897
}
1898

    
1899
static inline uint32_t cc_calc_addu_64(CPUState *env, uint64_t a1, uint64_t a2,
1900
                                       uint64_t ar)
1901
{
1902
    if (ar == 0) {
1903
        if (a1) {
1904
            return 2;
1905
        } else {
1906
            return 0;
1907
        }
1908
    } else {
1909
        if (ar < a1 || ar < a2) {
1910
          return 3;
1911
        } else {
1912
          return 1;
1913
        }
1914
    }
1915
}
1916

    
1917
static inline uint32_t cc_calc_sub_64(CPUState *env, int64_t a1, int64_t a2,
1918
                                      int64_t ar)
1919
{
1920
    if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
1921
        return 3; /* overflow */
1922
    } else {
1923
        if (ar < 0) {
1924
            return 1;
1925
        } else if (ar > 0) {
1926
            return 2;
1927
        } else {
1928
            return 0;
1929
        }
1930
    }
1931
}
1932

    
1933
static inline uint32_t cc_calc_subu_64(CPUState *env, uint64_t a1, uint64_t a2,
1934
                                       uint64_t ar)
1935
{
1936
    if (ar == 0) {
1937
        return 2;
1938
    } else {
1939
        if (a2 > a1) {
1940
            return 1;
1941
        } else {
1942
            return 3;
1943
        }
1944
    }
1945
}
1946

    
1947
static inline uint32_t cc_calc_abs_64(CPUState *env, int64_t dst)
1948
{
1949
    if ((uint64_t)dst == 0x8000000000000000ULL) {
1950
        return 3;
1951
    } else if (dst) {
1952
        return 1;
1953
    } else {
1954
        return 0;
1955
    }
1956
}
1957

    
1958
static inline uint32_t cc_calc_nabs_64(CPUState *env, int64_t dst)
1959
{
1960
    return !!dst;
1961
}
1962

    
1963
static inline uint32_t cc_calc_comp_64(CPUState *env, int64_t dst)
1964
{
1965
    if ((uint64_t)dst == 0x8000000000000000ULL) {
1966
        return 3;
1967
    } else if (dst < 0) {
1968
        return 1;
1969
    } else if (dst > 0) {
1970
        return 2;
1971
    } else {
1972
        return 0;
1973
    }
1974
}
1975

    
1976

    
1977
static inline uint32_t cc_calc_add_32(CPUState *env, int32_t a1, int32_t a2,
1978
                                      int32_t ar)
1979
{
1980
    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
1981
        return 3; /* overflow */
1982
    } else {
1983
        if (ar < 0) {
1984
            return 1;
1985
        } else if (ar > 0) {
1986
            return 2;
1987
        } else {
1988
            return 0;
1989
        }
1990
    }
1991
}
1992

    
1993
static inline uint32_t cc_calc_addu_32(CPUState *env, uint32_t a1, uint32_t a2,
1994
                                       uint32_t ar)
1995
{
1996
    if (ar == 0) {
1997
        if (a1) {
1998
          return 2;
1999
        } else {
2000
          return 0;
2001
        }
2002
    } else {
2003
        if (ar < a1 || ar < a2) {
2004
          return 3;
2005
        } else {
2006
          return 1;
2007
        }
2008
    }
2009
}
2010

    
2011
static inline uint32_t cc_calc_sub_32(CPUState *env, int32_t a1, int32_t a2,
2012
                                      int32_t ar)
2013
{
2014
    if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
2015
        return 3; /* overflow */
2016
    } else {
2017
        if (ar < 0) {
2018
            return 1;
2019
        } else if (ar > 0) {
2020
            return 2;
2021
        } else {
2022
            return 0;
2023
        }
2024
    }
2025
}
2026

    
2027
static inline uint32_t cc_calc_subu_32(CPUState *env, uint32_t a1, uint32_t a2,
2028
                                       uint32_t ar)
2029
{
2030
    if (ar == 0) {
2031
        return 2;
2032
    } else {
2033
        if (a2 > a1) {
2034
            return 1;
2035
        } else {
2036
            return 3;
2037
        }
2038
    }
2039
}
2040

    
2041
static inline uint32_t cc_calc_abs_32(CPUState *env, int32_t dst)
2042
{
2043
    if ((uint32_t)dst == 0x80000000UL) {
2044
        return 3;
2045
    } else if (dst) {
2046
        return 1;
2047
    } else {
2048
        return 0;
2049
    }
2050
}
2051

    
2052
static inline uint32_t cc_calc_nabs_32(CPUState *env, int32_t dst)
2053
{
2054
    return !!dst;
2055
}
2056

    
2057
static inline uint32_t cc_calc_comp_32(CPUState *env, int32_t dst)
2058
{
2059
    if ((uint32_t)dst == 0x80000000UL) {
2060
        return 3;
2061
    } else if (dst < 0) {
2062
        return 1;
2063
    } else if (dst > 0) {
2064
        return 2;
2065
    } else {
2066
        return 0;
2067
    }
2068
}
2069

    
2070
/* calculate condition code for insert character under mask insn */
2071
static inline uint32_t cc_calc_icm_32(CPUState *env, uint32_t mask, uint32_t val)
2072
{
2073
    HELPER_LOG("%s: mask 0x%x val %d\n", __FUNCTION__, mask, val);
2074
    uint32_t cc;
2075

    
2076
    if (mask == 0xf) {
2077
        if (!val) {
2078
            return 0;
2079
        } else if (val & 0x80000000) {
2080
            return 1;
2081
        } else {
2082
            return 2;
2083
        }
2084
    }
2085

    
2086
    if (!val || !mask) {
2087
        cc = 0;
2088
    } else {
2089
        while (mask != 1) {
2090
            mask >>= 1;
2091
            val >>= 8;
2092
        }
2093
        if (val & 0x80) {
2094
            cc = 1;
2095
        } else {
2096
            cc = 2;
2097
        }
2098
    }
2099
    return cc;
2100
}
2101

    
2102
static inline uint32_t cc_calc_slag(CPUState *env, uint64_t src, uint64_t shift)
2103
{
2104
    uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
2105
    uint64_t match, r;
2106

    
2107
    /* check if the sign bit stays the same */
2108
    if (src & (1ULL << 63)) {
2109
        match = mask;
2110
    } else {
2111
        match = 0;
2112
    }
2113

    
2114
    if ((src & mask) != match) {
2115
        /* overflow */
2116
        return 3;
2117
    }
2118

    
2119
    r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63));
2120

    
2121
    if ((int64_t)r == 0) {
2122
        return 0;
2123
    } else if ((int64_t)r < 0) {
2124
        return 1;
2125
    }
2126

    
2127
    return 2;
2128
}
2129

    
2130

    
2131
static inline uint32_t do_calc_cc(CPUState *env, uint32_t cc_op, uint64_t src,
2132
                                  uint64_t dst, uint64_t vr)
2133
{
2134
    uint32_t r = 0;
2135

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

    
2193
    case CC_OP_ADD_32:
2194
        r =  cc_calc_add_32(env, src, dst, vr);
2195
        break;
2196
    case CC_OP_ADDU_32:
2197
        r =  cc_calc_addu_32(env, src, dst, vr);
2198
        break;
2199
    case CC_OP_SUB_32:
2200
        r =  cc_calc_sub_32(env, src, dst, vr);
2201
        break;
2202
    case CC_OP_SUBU_32:
2203
        r =  cc_calc_subu_32(env, src, dst, vr);
2204
        break;
2205
    case CC_OP_ABS_32:
2206
        r =  cc_calc_abs_64(env, dst);
2207
        break;
2208
    case CC_OP_NABS_32:
2209
        r =  cc_calc_nabs_64(env, dst);
2210
        break;
2211
    case CC_OP_COMP_32:
2212
        r =  cc_calc_comp_32(env, dst);
2213
        break;
2214

    
2215
    case CC_OP_ICM:
2216
        r =  cc_calc_icm_32(env, src, dst);
2217
        break;
2218
    case CC_OP_SLAG:
2219
        r =  cc_calc_slag(env, src, dst);
2220
        break;
2221

    
2222
    case CC_OP_LTGT_F32:
2223
        r = set_cc_f32(src, dst);
2224
        break;
2225
    case CC_OP_LTGT_F64:
2226
        r = set_cc_f64(src, dst);
2227
        break;
2228
    case CC_OP_NZ_F32:
2229
        r = set_cc_nz_f32(dst);
2230
        break;
2231
    case CC_OP_NZ_F64:
2232
        r = set_cc_nz_f64(dst);
2233
        break;
2234

    
2235
    default:
2236
        cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op));
2237
    }
2238

    
2239
    HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __FUNCTION__,
2240
               cc_name(cc_op), src, dst, vr, r);
2241
    return r;
2242
}
2243

    
2244
uint32_t calc_cc(CPUState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
2245
                 uint64_t vr)
2246
{
2247
    return do_calc_cc(env, cc_op, src, dst, vr);
2248
}
2249

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

    
2256
uint64_t HELPER(cvd)(int32_t bin)
2257
{
2258
    /* positive 0 */
2259
    uint64_t dec = 0x0c;
2260
    int shift = 4;
2261

    
2262
    if (bin < 0) {
2263
        bin = -bin;
2264
        dec = 0x0d;
2265
    }
2266

    
2267
    for (shift = 4; (shift < 64) && bin; shift += 4) {
2268
        int current_number = bin % 10;
2269

    
2270
        dec |= (current_number) << shift;
2271
        bin /= 10;
2272
    }
2273

    
2274
    return dec;
2275
}
2276

    
2277
void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
2278
{
2279
    int len_dest = len >> 4;
2280
    int len_src = len & 0xf;
2281
    uint8_t b;
2282
    int second_nibble = 0;
2283

    
2284
    dest += len_dest;
2285
    src += len_src;
2286

    
2287
    /* last byte is special, it only flips the nibbles */
2288
    b = ldub(src);
2289
    stb(dest, (b << 4) | (b >> 4));
2290
    src--;
2291
    len_src--;
2292

    
2293
    /* now pad every nibble with 0xf0 */
2294

    
2295
    while (len_dest > 0) {
2296
        uint8_t cur_byte = 0;
2297

    
2298
        if (len_src > 0) {
2299
            cur_byte = ldub(src);
2300
        }
2301

    
2302
        len_dest--;
2303
        dest--;
2304

    
2305
        /* only advance one nibble at a time */
2306
        if (second_nibble) {
2307
            cur_byte >>= 4;
2308
            len_src--;
2309
            src--;
2310
        }
2311
        second_nibble = !second_nibble;
2312

    
2313
        /* digit */
2314
        cur_byte = (cur_byte & 0xf);
2315
        /* zone bits */
2316
        cur_byte |= 0xf0;
2317

    
2318
        stb(dest, cur_byte);
2319
    }
2320
}
2321

    
2322
void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans)
2323
{
2324
    int i;
2325

    
2326
    for (i = 0; i <= len; i++) {
2327
        uint8_t byte = ldub(array + i);
2328
        uint8_t new_byte = ldub(trans + byte);
2329
        stb(array + i, new_byte);
2330
    }
2331
}
2332

    
2333
#ifndef CONFIG_USER_ONLY
2334

    
2335
void HELPER(load_psw)(uint64_t mask, uint64_t addr)
2336
{
2337
    load_psw(env, mask, addr);
2338
    cpu_loop_exit();
2339
}
2340

    
2341
static void program_interrupt(CPUState *env, uint32_t code, int ilc)
2342
{
2343
    qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
2344

    
2345
    if (kvm_enabled()) {
2346
        kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
2347
    } else {
2348
        env->int_pgm_code = code;
2349
        env->int_pgm_ilc = ilc;
2350
        env->exception_index = EXCP_PGM;
2351
        cpu_loop_exit();
2352
    }
2353
}
2354

    
2355
static void ext_interrupt(CPUState *env, int type, uint32_t param,
2356
                          uint64_t param64)
2357
{
2358
    cpu_inject_ext(env, type, param, param64);
2359
}
2360

    
2361
int sclp_service_call(CPUState *env, uint32_t sccb, uint64_t code)
2362
{
2363
    int r = 0;
2364
    int shift = 0;
2365

    
2366
#ifdef DEBUG_HELPER
2367
    printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code);
2368
#endif
2369

    
2370
    if (sccb & ~0x7ffffff8ul) {
2371
        fprintf(stderr, "KVM: invalid sccb address 0x%x\n", sccb);
2372
        r = -1;
2373
        goto out;
2374
    }
2375

    
2376
    switch(code) {
2377
        case SCLP_CMDW_READ_SCP_INFO:
2378
        case SCLP_CMDW_READ_SCP_INFO_FORCED:
2379
            while ((ram_size >> (20 + shift)) > 65535) {
2380
                shift++;
2381
            }
2382
            stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift));
2383
            stb_phys(sccb + SCP_INCREMENT, 1 << shift);
2384
            stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
2385

    
2386
            if (kvm_enabled()) {
2387
#ifdef CONFIG_KVM
2388
                kvm_s390_interrupt_internal(env, KVM_S390_INT_SERVICE,
2389
                                            sccb & ~3, 0, 1);
2390
#endif
2391
            } else {
2392
                env->psw.addr += 4;
2393
                ext_interrupt(env, EXT_SERVICE, sccb & ~3, 0);
2394
            }
2395
            break;
2396
        default:
2397
#ifdef DEBUG_HELPER
2398
            printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
2399
#endif
2400
            r = -1;
2401
            break;
2402
    }
2403

    
2404
out:
2405
    return r;
2406
}
2407

    
2408
/* SCLP service call */
2409
uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
2410
{
2411
    if (sclp_service_call(env, r1, r2)) {
2412
        return 3;
2413
    }
2414

    
2415
    return 0;
2416
}
2417

    
2418
/* DIAG */
2419
uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
2420
{
2421
    uint64_t r;
2422

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

    
2441
    if (r) {
2442
        program_interrupt(env, PGM_OPERATION, ILC_LATER_INC);
2443
    }
2444

    
2445
    return r;
2446
}
2447

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

    
2454
/* Set Prefix */
2455
void HELPER(spx)(uint64_t a1)
2456
{
2457
    uint32_t prefix;
2458

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

    
2466
/* Set Clock */
2467
uint32_t HELPER(sck)(uint64_t a1)
2468
{
2469
    /* XXX not implemented - is it necessary? */
2470

    
2471
    return 0;
2472
}
2473

    
2474
static inline uint64_t clock_value(CPUState *env)
2475
{
2476
    uint64_t time;
2477

    
2478
    time = env->tod_offset +
2479
           time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
2480

    
2481
    return time;
2482
}
2483

    
2484
/* Store Clock */
2485
uint32_t HELPER(stck)(uint64_t a1)
2486
{
2487
    stq(a1, clock_value(env));
2488

    
2489
    return 0;
2490
}
2491

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

    
2503

    
2504
    return 0;
2505
}
2506

    
2507
/* Set Clock Comparator */
2508
void HELPER(sckc)(uint64_t a1)
2509
{
2510
    uint64_t time = ldq(a1);
2511

    
2512
    if (time == -1ULL) {
2513
        return;
2514
    }
2515

    
2516
    /* difference between now and then */
2517
    time -= clock_value(env);
2518
    /* nanoseconds */
2519
    time = (time * 125) >> 9;
2520

    
2521
    qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
2522
}
2523

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

    
2531
/* Set CPU Timer */
2532
void HELPER(spt)(uint64_t a1)
2533
{
2534
    uint64_t time = ldq(a1);
2535

    
2536
    if (time == -1ULL) {
2537
        return;
2538
    }
2539

    
2540
    /* nanoseconds */
2541
    time = (time * 125) >> 9;
2542

    
2543
    qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
2544
}
2545

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

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

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

    
2565
    sel1 = r0 & STSI_R0_SEL1_MASK;
2566
    sel2 = r1 & STSI_R1_SEL2_MASK;
2567

    
2568
    /* XXX: spec exception if sysib is not 4k-aligned */
2569

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

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

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

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

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

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

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

    
2676
    return cc;
2677
}
2678

    
2679
void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3)
2680
{
2681
    int i;
2682
    uint64_t src = a2;
2683

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

    
2690
        if (i == r3) {
2691
            break;
2692
        }
2693
    }
2694

    
2695
    tlb_flush(env, 1);
2696
}
2697

    
2698
void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3)
2699
{
2700
    int i;
2701
    uint64_t src = a2;
2702

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

    
2707
        if (i == r3) {
2708
            break;
2709
        }
2710
    }
2711

    
2712
    tlb_flush(env, 1);
2713
}
2714

    
2715
void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3)
2716
{
2717
    int i;
2718
    uint64_t dest = a2;
2719

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

    
2724
        if (i == r3) {
2725
            break;
2726
        }
2727
    }
2728
}
2729

    
2730
void HELPER(stctl)(uint32_t r1, uint64_t a2, uint32_t r3)
2731
{
2732
    int i;
2733
    uint64_t dest = a2;
2734

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

    
2739
        if (i == r3) {
2740
            break;
2741
        }
2742
    }
2743
}
2744

    
2745
uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
2746
{
2747
    /* XXX implement */
2748

    
2749
    return 0;
2750
}
2751

    
2752
/* insert storage key extended */
2753
uint64_t HELPER(iske)(uint64_t r2)
2754
{
2755
    uint64_t addr = get_address(0, 0, r2);
2756

    
2757
    if (addr > ram_size) {
2758
        return 0;
2759
    }
2760

    
2761
    /* XXX maybe use qemu's internal keys? */
2762
    return env->storage_keys[addr / TARGET_PAGE_SIZE];
2763
}
2764

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

    
2770
    if (addr > ram_size) {
2771
        return;
2772
    }
2773

    
2774
    env->storage_keys[addr / TARGET_PAGE_SIZE] = r1;
2775
}
2776

    
2777
/* reset reference bit extended */
2778
uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
2779
{
2780
    if (r2 > ram_size) {
2781
        return 0;
2782
    }
2783

    
2784
    /* XXX implement */
2785
#if 0
2786
    env->storage_keys[r2 / TARGET_PAGE_SIZE] &= ~SK_REFERENCED;
2787
#endif
2788

    
2789
    /*
2790
     * cc
2791
     *
2792
     * 0  Reference bit zero; change bit zero
2793
     * 1  Reference bit zero; change bit one
2794
     * 2  Reference bit one; change bit zero
2795
     * 3  Reference bit one; change bit one
2796
     */
2797
    return 0;
2798
}
2799

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

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

    
2820
    return cc;
2821
}
2822

    
2823
static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
2824
                        uint64_t mode2)
2825
{
2826
    target_ulong src, dest;
2827
    int flags, cc = 0, i;
2828

    
2829
    if (!l) {
2830
        return 0;
2831
    } else if (l > 256) {
2832
        /* max 256 */
2833
        l = 256;
2834
        cc = 3;
2835
    }
2836

    
2837
    if (mmu_translate(env, a1 & TARGET_PAGE_MASK, 1, mode1, &dest, &flags)) {
2838
        cpu_loop_exit();
2839
    }
2840
    dest |= a1 & ~TARGET_PAGE_MASK;
2841

    
2842
    if (mmu_translate(env, a2 & TARGET_PAGE_MASK, 0, mode2, &src, &flags)) {
2843
        cpu_loop_exit();
2844
    }
2845
    src |= a2 & ~TARGET_PAGE_MASK;
2846

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

    
2858
    return cc;
2859
}
2860

    
2861
uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2)
2862
{
2863
    HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
2864
               __FUNCTION__, l, a1, a2);
2865

    
2866
    return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
2867
}
2868

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

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

    
2877
uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
2878
{
2879
    int cc = 0;
2880

    
2881
    HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
2882
               __FUNCTION__, order_code, r1, cpu_addr);
2883

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

    
2887
    switch (order_code) {
2888
    case SIGP_SET_ARCH:
2889
        /* switch arch */
2890
        break;
2891
    case SIGP_SENSE:
2892
        /* enumerate CPU status */
2893
        if (cpu_addr) {
2894
            /* XXX implement when SMP comes */
2895
            return 3;
2896
        }
2897
        env->regs[r1] &= 0xffffffff00000000ULL;
2898
        cc = 1;
2899
        break;
2900
    default:
2901
        /* unknown sigp */
2902
        fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
2903
        cc = 3;
2904
    }
2905

    
2906
    return cc;
2907
}
2908

    
2909
void HELPER(sacf)(uint64_t a1)
2910
{
2911
    HELPER_LOG("%s: %16" PRIx64 "\n", __FUNCTION__, a1);
2912

    
2913
    switch (a1 & 0xf00) {
2914
    case 0x000:
2915
        env->psw.mask &= ~PSW_MASK_ASC;
2916
        env->psw.mask |= PSW_ASC_PRIMARY;
2917
        break;
2918
    case 0x100:
2919
        env->psw.mask &= ~PSW_MASK_ASC;
2920
        env->psw.mask |= PSW_ASC_SECONDARY;
2921
        break;
2922
    case 0x300:
2923
        env->psw.mask &= ~PSW_MASK_ASC;
2924
        env->psw.mask |= PSW_ASC_HOME;
2925
        break;
2926
    default:
2927
        qemu_log("unknown sacf mode: %" PRIx64 "\n", a1);
2928
        program_interrupt(env, PGM_SPECIFICATION, 2);
2929
        break;
2930
    }
2931
}
2932

    
2933
/* invalidate pte */
2934
void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
2935
{
2936
    uint64_t page = vaddr & TARGET_PAGE_MASK;
2937
    uint64_t pte = 0;
2938

    
2939
    /* XXX broadcast to other CPUs */
2940

    
2941
    /* XXX Linux is nice enough to give us the exact pte address.
2942
           According to spec we'd have to find it out ourselves */
2943
    /* XXX Linux is fine with overwriting the pte, the spec requires
2944
           us to only set the invalid bit */
2945
    stq_phys(pte_addr, pte | _PAGE_INVALID);
2946

    
2947
    /* XXX we exploit the fact that Linux passes the exact virtual
2948
           address here - it's not obliged to! */
2949
    tlb_flush_page(env, page);
2950
}
2951

    
2952
/* flush local tlb */
2953
void HELPER(ptlb)(void)
2954
{
2955
    tlb_flush(env, 1);
2956
}
2957

    
2958
/* store using real address */
2959
void HELPER(stura)(uint64_t addr, uint32_t v1)
2960
{
2961
    stw_phys(get_address(0, 0, addr), v1);
2962
}
2963

    
2964
/* load real address */
2965
uint32_t HELPER(lra)(uint64_t addr, uint32_t r1)
2966
{
2967
    uint32_t cc = 0;
2968
    int old_exc = env->exception_index;
2969
    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
2970
    uint64_t ret;
2971
    int flags;
2972

    
2973
    /* XXX incomplete - has more corner cases */
2974
    if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) {
2975
        program_interrupt(env, PGM_SPECIAL_OP, 2);
2976
    }
2977

    
2978
    env->exception_index = old_exc;
2979
    if (mmu_translate(env, addr, 0, asc, &ret, &flags)) {
2980
        cc = 3;
2981
    }
2982
    if (env->exception_index == EXCP_PGM) {
2983
        ret = env->int_pgm_code | 0x80000000;
2984
    } else {
2985
        ret |= addr & ~TARGET_PAGE_MASK;
2986
    }
2987
    env->exception_index = old_exc;
2988

    
2989
    if (!(env->psw.mask & PSW_MASK_64)) {
2990
        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (ret & 0xffffffffULL);
2991
    } else {
2992
        env->regs[r1] = ret;
2993
    }
2994

    
2995
    return cc;
2996
}
2997

    
2998
#endif