Revision defb0e31 target-s390x/op_helper.c

b/target-s390x/op_helper.c
1 1
/*
2 2
 *  S/390 helper routines
3 3
 *
4
 *  Copyright (c) 2009 Ulrich Hecht
4 5
 *  Copyright (c) 2009 Alexander Graf
5 6
 *
6 7
 * This library is free software; you can redistribute it and/or
......
18 19
 */
19 20

  
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"
21 27

  
22 28
/*****************************************************************************/
23 29
/* Softmmu support */
......
64 70
                cpu_restore_state(tb, env, pc);
65 71
            }
66 72
        }
67
        /* XXX */
68
        /* helper_raise_exception_err(env->exception_index, env->error_code); */
73
        cpu_loop_exit();
69 74
    }
70 75
    env = saved_env;
71 76
}
72 77

  
73 78
#endif
74 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
}
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff