Statistics
| Branch: | Revision:

root / target-s390x / cc_helper.c @ 834574ea

History | View | Annotate | Download (12.7 kB)

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

    
21
#include "cpu.h"
22
#include "helper.h"
23
#include "qemu/host-utils.h"
24

    
25
/* #define DEBUG_HELPER */
26
#ifdef DEBUG_HELPER
27
#define HELPER_LOG(x...) qemu_log(x)
28
#else
29
#define HELPER_LOG(x...)
30
#endif
31

    
32
static uint32_t cc_calc_ltgt_32(int32_t src, int32_t dst)
33
{
34
    if (src == dst) {
35
        return 0;
36
    } else if (src < dst) {
37
        return 1;
38
    } else {
39
        return 2;
40
    }
41
}
42

    
43
static uint32_t cc_calc_ltgt0_32(int32_t dst)
44
{
45
    return cc_calc_ltgt_32(dst, 0);
46
}
47

    
48
static uint32_t cc_calc_ltgt_64(int64_t src, int64_t dst)
49
{
50
    if (src == dst) {
51
        return 0;
52
    } else if (src < dst) {
53
        return 1;
54
    } else {
55
        return 2;
56
    }
57
}
58

    
59
static uint32_t cc_calc_ltgt0_64(int64_t dst)
60
{
61
    return cc_calc_ltgt_64(dst, 0);
62
}
63

    
64
static uint32_t cc_calc_ltugtu_32(uint32_t src, uint32_t dst)
65
{
66
    if (src == dst) {
67
        return 0;
68
    } else if (src < dst) {
69
        return 1;
70
    } else {
71
        return 2;
72
    }
73
}
74

    
75
static uint32_t cc_calc_ltugtu_64(uint64_t src, uint64_t dst)
76
{
77
    if (src == dst) {
78
        return 0;
79
    } else if (src < dst) {
80
        return 1;
81
    } else {
82
        return 2;
83
    }
84
}
85

    
86
static uint32_t cc_calc_tm_32(uint32_t val, uint32_t mask)
87
{
88
    uint32_t r = val & mask;
89

    
90
    if (r == 0) {
91
        return 0;
92
    } else if (r == mask) {
93
        return 3;
94
    } else {
95
        return 1;
96
    }
97
}
98

    
99
static uint32_t cc_calc_tm_64(uint64_t val, uint64_t mask)
100
{
101
    uint64_t r = val & mask;
102

    
103
    if (r == 0) {
104
        return 0;
105
    } else if (r == mask) {
106
        return 3;
107
    } else {
108
        int top = clz64(mask);
109
        if ((int64_t)(val << top) < 0) {
110
            return 2;
111
        } else {
112
            return 1;
113
        }
114
    }
115
}
116

    
117
static uint32_t cc_calc_nz(uint64_t dst)
118
{
119
    return !!dst;
120
}
121

    
122
static uint32_t cc_calc_add_64(int64_t a1, int64_t a2, int64_t ar)
123
{
124
    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
125
        return 3; /* overflow */
126
    } else {
127
        if (ar < 0) {
128
            return 1;
129
        } else if (ar > 0) {
130
            return 2;
131
        } else {
132
            return 0;
133
        }
134
    }
135
}
136

    
137
static uint32_t cc_calc_addu_64(uint64_t a1, uint64_t a2, uint64_t ar)
138
{
139
    return (ar != 0) + 2 * (ar < a1);
140
}
141

    
142
static uint32_t cc_calc_addc_64(uint64_t a1, uint64_t a2, uint64_t ar)
143
{
144
    /* Recover a2 + carry_in.  */
145
    uint64_t a2c = ar - a1;
146
    /* Check for a2+carry_in overflow, then a1+a2c overflow.  */
147
    int carry_out = (a2c < a2) || (ar < a1);
148

    
149
    return (ar != 0) + 2 * carry_out;
150
}
151

    
152
static uint32_t cc_calc_sub_64(int64_t a1, int64_t a2, int64_t ar)
153
{
154
    if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
155
        return 3; /* overflow */
156
    } else {
157
        if (ar < 0) {
158
            return 1;
159
        } else if (ar > 0) {
160
            return 2;
161
        } else {
162
            return 0;
163
        }
164
    }
165
}
166

    
167
static uint32_t cc_calc_subu_64(uint64_t a1, uint64_t a2, uint64_t ar)
168
{
169
    if (ar == 0) {
170
        return 2;
171
    } else {
172
        if (a2 > a1) {
173
            return 1;
174
        } else {
175
            return 3;
176
        }
177
    }
178
}
179

    
180
static uint32_t cc_calc_subb_64(uint64_t a1, uint64_t a2, uint64_t ar)
181
{
182
    /* We had borrow-in if normal subtraction isn't equal.  */
183
    int borrow_in = ar - (a1 - a2);
184
    int borrow_out;
185

    
186
    /* If a2 was ULONG_MAX, and borrow_in, then a2 is logically 65 bits,
187
       and we must have had borrow out.  */
188
    if (borrow_in && a2 == (uint64_t)-1) {
189
        borrow_out = 1;
190
    } else {
191
        a2 += borrow_in;
192
        borrow_out = (a2 > a1);
193
    }
194

    
195
    return (ar != 0) + 2 * !borrow_out;
196
}
197

    
198
static uint32_t cc_calc_abs_64(int64_t dst)
199
{
200
    if ((uint64_t)dst == 0x8000000000000000ULL) {
201
        return 3;
202
    } else if (dst) {
203
        return 1;
204
    } else {
205
        return 0;
206
    }
207
}
208

    
209
static uint32_t cc_calc_nabs_64(int64_t dst)
210
{
211
    return !!dst;
212
}
213

    
214
static uint32_t cc_calc_comp_64(int64_t dst)
215
{
216
    if ((uint64_t)dst == 0x8000000000000000ULL) {
217
        return 3;
218
    } else if (dst < 0) {
219
        return 1;
220
    } else if (dst > 0) {
221
        return 2;
222
    } else {
223
        return 0;
224
    }
225
}
226

    
227

    
228
static uint32_t cc_calc_add_32(int32_t a1, int32_t a2, int32_t ar)
229
{
230
    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
231
        return 3; /* overflow */
232
    } else {
233
        if (ar < 0) {
234
            return 1;
235
        } else if (ar > 0) {
236
            return 2;
237
        } else {
238
            return 0;
239
        }
240
    }
241
}
242

    
243
static uint32_t cc_calc_addu_32(uint32_t a1, uint32_t a2, uint32_t ar)
244
{
245
    return (ar != 0) + 2 * (ar < a1);
246
}
247

    
248
static uint32_t cc_calc_addc_32(uint32_t a1, uint32_t a2, uint32_t ar)
249
{
250
    /* Recover a2 + carry_in.  */
251
    uint32_t a2c = ar - a1;
252
    /* Check for a2+carry_in overflow, then a1+a2c overflow.  */
253
    int carry_out = (a2c < a2) || (ar < a1);
254

    
255
    return (ar != 0) + 2 * carry_out;
256
}
257

    
258
static uint32_t cc_calc_sub_32(int32_t a1, int32_t a2, int32_t ar)
259
{
260
    if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
261
        return 3; /* overflow */
262
    } else {
263
        if (ar < 0) {
264
            return 1;
265
        } else if (ar > 0) {
266
            return 2;
267
        } else {
268
            return 0;
269
        }
270
    }
271
}
272

    
273
static uint32_t cc_calc_subu_32(uint32_t a1, uint32_t a2, uint32_t ar)
274
{
275
    if (ar == 0) {
276
        return 2;
277
    } else {
278
        if (a2 > a1) {
279
            return 1;
280
        } else {
281
            return 3;
282
        }
283
    }
284
}
285

    
286
static uint32_t cc_calc_subb_32(uint32_t a1, uint32_t a2, uint32_t ar)
287
{
288
    /* We had borrow-in if normal subtraction isn't equal.  */
289
    int borrow_in = ar - (a1 - a2);
290
    int borrow_out;
291

    
292
    /* If a2 was UINT_MAX, and borrow_in, then a2 is logically 65 bits,
293
       and we must have had borrow out.  */
294
    if (borrow_in && a2 == (uint32_t)-1) {
295
        borrow_out = 1;
296
    } else {
297
        a2 += borrow_in;
298
        borrow_out = (a2 > a1);
299
    }
300

    
301
    return (ar != 0) + 2 * !borrow_out;
302
}
303

    
304
static uint32_t cc_calc_abs_32(int32_t dst)
305
{
306
    if ((uint32_t)dst == 0x80000000UL) {
307
        return 3;
308
    } else if (dst) {
309
        return 1;
310
    } else {
311
        return 0;
312
    }
313
}
314

    
315
static uint32_t cc_calc_nabs_32(int32_t dst)
316
{
317
    return !!dst;
318
}
319

    
320
static uint32_t cc_calc_comp_32(int32_t dst)
321
{
322
    if ((uint32_t)dst == 0x80000000UL) {
323
        return 3;
324
    } else if (dst < 0) {
325
        return 1;
326
    } else if (dst > 0) {
327
        return 2;
328
    } else {
329
        return 0;
330
    }
331
}
332

    
333
/* calculate condition code for insert character under mask insn */
334
static uint32_t cc_calc_icm(uint64_t mask, uint64_t val)
335
{
336
    if ((val & mask) == 0) {
337
        return 0;
338
    } else {
339
        int top = clz64(mask);
340
        if ((int64_t)(val << top) < 0) {
341
            return 1;
342
        } else {
343
            return 2;
344
        }
345
    }
346
}
347

    
348
static uint32_t cc_calc_sla_32(uint32_t src, int shift)
349
{
350
    uint32_t mask = ((1U << shift) - 1U) << (32 - shift);
351
    uint32_t sign = 1U << 31;
352
    uint32_t match;
353
    int32_t r;
354

    
355
    /* Check if the sign bit stays the same.  */
356
    if (src & sign) {
357
        match = mask;
358
    } else {
359
        match = 0;
360
    }
361
    if ((src & mask) != match) {
362
        /* Overflow.  */
363
        return 3;
364
    }
365

    
366
    r = ((src << shift) & ~sign) | (src & sign);
367
    if (r == 0) {
368
        return 0;
369
    } else if (r < 0) {
370
        return 1;
371
    }
372
    return 2;
373
}
374

    
375
static uint32_t cc_calc_sla_64(uint64_t src, int shift)
376
{
377
    uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
378
    uint64_t sign = 1ULL << 63;
379
    uint64_t match;
380
    int64_t r;
381

    
382
    /* Check if the sign bit stays the same.  */
383
    if (src & sign) {
384
        match = mask;
385
    } else {
386
        match = 0;
387
    }
388
    if ((src & mask) != match) {
389
        /* Overflow.  */
390
        return 3;
391
    }
392

    
393
    r = ((src << shift) & ~sign) | (src & sign);
394
    if (r == 0) {
395
        return 0;
396
    } else if (r < 0) {
397
        return 1;
398
    }
399
    return 2;
400
}
401

    
402
static uint32_t cc_calc_flogr(uint64_t dst)
403
{
404
    return dst ? 2 : 0;
405
}
406

    
407
static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
408
                                  uint64_t src, uint64_t dst, uint64_t vr)
409
{
410
    uint32_t r = 0;
411

    
412
    switch (cc_op) {
413
    case CC_OP_CONST0:
414
    case CC_OP_CONST1:
415
    case CC_OP_CONST2:
416
    case CC_OP_CONST3:
417
        /* cc_op value _is_ cc */
418
        r = cc_op;
419
        break;
420
    case CC_OP_LTGT0_32:
421
        r = cc_calc_ltgt0_32(dst);
422
        break;
423
    case CC_OP_LTGT0_64:
424
        r =  cc_calc_ltgt0_64(dst);
425
        break;
426
    case CC_OP_LTGT_32:
427
        r =  cc_calc_ltgt_32(src, dst);
428
        break;
429
    case CC_OP_LTGT_64:
430
        r =  cc_calc_ltgt_64(src, dst);
431
        break;
432
    case CC_OP_LTUGTU_32:
433
        r =  cc_calc_ltugtu_32(src, dst);
434
        break;
435
    case CC_OP_LTUGTU_64:
436
        r =  cc_calc_ltugtu_64(src, dst);
437
        break;
438
    case CC_OP_TM_32:
439
        r =  cc_calc_tm_32(src, dst);
440
        break;
441
    case CC_OP_TM_64:
442
        r =  cc_calc_tm_64(src, dst);
443
        break;
444
    case CC_OP_NZ:
445
        r =  cc_calc_nz(dst);
446
        break;
447
    case CC_OP_ADD_64:
448
        r =  cc_calc_add_64(src, dst, vr);
449
        break;
450
    case CC_OP_ADDU_64:
451
        r =  cc_calc_addu_64(src, dst, vr);
452
        break;
453
    case CC_OP_ADDC_64:
454
        r =  cc_calc_addc_64(src, dst, vr);
455
        break;
456
    case CC_OP_SUB_64:
457
        r =  cc_calc_sub_64(src, dst, vr);
458
        break;
459
    case CC_OP_SUBU_64:
460
        r =  cc_calc_subu_64(src, dst, vr);
461
        break;
462
    case CC_OP_SUBB_64:
463
        r =  cc_calc_subb_64(src, dst, vr);
464
        break;
465
    case CC_OP_ABS_64:
466
        r =  cc_calc_abs_64(dst);
467
        break;
468
    case CC_OP_NABS_64:
469
        r =  cc_calc_nabs_64(dst);
470
        break;
471
    case CC_OP_COMP_64:
472
        r =  cc_calc_comp_64(dst);
473
        break;
474

    
475
    case CC_OP_ADD_32:
476
        r =  cc_calc_add_32(src, dst, vr);
477
        break;
478
    case CC_OP_ADDU_32:
479
        r =  cc_calc_addu_32(src, dst, vr);
480
        break;
481
    case CC_OP_ADDC_32:
482
        r =  cc_calc_addc_32(src, dst, vr);
483
        break;
484
    case CC_OP_SUB_32:
485
        r =  cc_calc_sub_32(src, dst, vr);
486
        break;
487
    case CC_OP_SUBU_32:
488
        r =  cc_calc_subu_32(src, dst, vr);
489
        break;
490
    case CC_OP_SUBB_32:
491
        r =  cc_calc_subb_32(src, dst, vr);
492
        break;
493
    case CC_OP_ABS_32:
494
        r =  cc_calc_abs_32(dst);
495
        break;
496
    case CC_OP_NABS_32:
497
        r =  cc_calc_nabs_32(dst);
498
        break;
499
    case CC_OP_COMP_32:
500
        r =  cc_calc_comp_32(dst);
501
        break;
502

    
503
    case CC_OP_ICM:
504
        r =  cc_calc_icm(src, dst);
505
        break;
506
    case CC_OP_SLA_32:
507
        r =  cc_calc_sla_32(src, dst);
508
        break;
509
    case CC_OP_SLA_64:
510
        r =  cc_calc_sla_64(src, dst);
511
        break;
512
    case CC_OP_FLOGR:
513
        r = cc_calc_flogr(dst);
514
        break;
515

    
516
    case CC_OP_NZ_F32:
517
        r = set_cc_nz_f32(dst);
518
        break;
519
    case CC_OP_NZ_F64:
520
        r = set_cc_nz_f64(dst);
521
        break;
522
    case CC_OP_NZ_F128:
523
        r = set_cc_nz_f128(make_float128(src, dst));
524
        break;
525

    
526
    default:
527
        cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op));
528
    }
529

    
530
    HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __func__,
531
               cc_name(cc_op), src, dst, vr, r);
532
    return r;
533
}
534

    
535
uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
536
                 uint64_t vr)
537
{
538
    return do_calc_cc(env, cc_op, src, dst, vr);
539
}
540

    
541
uint32_t HELPER(calc_cc)(CPUS390XState *env, uint32_t cc_op, uint64_t src,
542
                         uint64_t dst, uint64_t vr)
543
{
544
    return do_calc_cc(env, cc_op, src, dst, vr);
545
}
546

    
547
#ifndef CONFIG_USER_ONLY
548
void HELPER(load_psw)(CPUS390XState *env, uint64_t mask, uint64_t addr)
549
{
550
    load_psw(env, mask, addr);
551
    cpu_loop_exit(env);
552
}
553

    
554
void HELPER(sacf)(CPUS390XState *env, uint64_t a1)
555
{
556
    HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1);
557

    
558
    switch (a1 & 0xf00) {
559
    case 0x000:
560
        env->psw.mask &= ~PSW_MASK_ASC;
561
        env->psw.mask |= PSW_ASC_PRIMARY;
562
        break;
563
    case 0x100:
564
        env->psw.mask &= ~PSW_MASK_ASC;
565
        env->psw.mask |= PSW_ASC_SECONDARY;
566
        break;
567
    case 0x300:
568
        env->psw.mask &= ~PSW_MASK_ASC;
569
        env->psw.mask |= PSW_ASC_HOME;
570
        break;
571
    default:
572
        qemu_log("unknown sacf mode: %" PRIx64 "\n", a1);
573
        program_interrupt(env, PGM_SPECIFICATION, 2);
574
        break;
575
    }
576
}
577
#endif