cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

cc_helper.c (11809B)


      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.1 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 "qemu/osdep.h"
     22#include "cpu.h"
     23#include "s390x-internal.h"
     24#include "tcg_s390x.h"
     25#include "exec/exec-all.h"
     26#include "exec/helper-proto.h"
     27#include "qemu/host-utils.h"
     28
     29/* #define DEBUG_HELPER */
     30#ifdef DEBUG_HELPER
     31#define HELPER_LOG(x...) qemu_log(x)
     32#else
     33#define HELPER_LOG(x...)
     34#endif
     35
     36static uint32_t cc_calc_ltgt_32(int32_t src, int32_t dst)
     37{
     38    if (src == dst) {
     39        return 0;
     40    } else if (src < dst) {
     41        return 1;
     42    } else {
     43        return 2;
     44    }
     45}
     46
     47static uint32_t cc_calc_ltgt0_32(int32_t dst)
     48{
     49    return cc_calc_ltgt_32(dst, 0);
     50}
     51
     52static uint32_t cc_calc_ltgt_64(int64_t src, int64_t dst)
     53{
     54    if (src == dst) {
     55        return 0;
     56    } else if (src < dst) {
     57        return 1;
     58    } else {
     59        return 2;
     60    }
     61}
     62
     63static uint32_t cc_calc_ltgt0_64(int64_t dst)
     64{
     65    return cc_calc_ltgt_64(dst, 0);
     66}
     67
     68static uint32_t cc_calc_ltugtu_32(uint32_t src, uint32_t dst)
     69{
     70    if (src == dst) {
     71        return 0;
     72    } else if (src < dst) {
     73        return 1;
     74    } else {
     75        return 2;
     76    }
     77}
     78
     79static uint32_t cc_calc_ltugtu_64(uint64_t src, uint64_t dst)
     80{
     81    if (src == dst) {
     82        return 0;
     83    } else if (src < dst) {
     84        return 1;
     85    } else {
     86        return 2;
     87    }
     88}
     89
     90static uint32_t cc_calc_tm_32(uint32_t val, uint32_t mask)
     91{
     92    uint32_t r = val & mask;
     93
     94    if (r == 0) {
     95        return 0;
     96    } else if (r == mask) {
     97        return 3;
     98    } else {
     99        return 1;
    100    }
    101}
    102
    103static uint32_t cc_calc_tm_64(uint64_t val, uint64_t mask)
    104{
    105    uint64_t r = val & mask;
    106
    107    if (r == 0) {
    108        return 0;
    109    } else if (r == mask) {
    110        return 3;
    111    } else {
    112        int top = clz64(mask);
    113        if ((int64_t)(val << top) < 0) {
    114            return 2;
    115        } else {
    116            return 1;
    117        }
    118    }
    119}
    120
    121static uint32_t cc_calc_nz(uint64_t dst)
    122{
    123    return !!dst;
    124}
    125
    126static uint32_t cc_calc_addu(uint64_t carry_out, uint64_t result)
    127{
    128    g_assert(carry_out <= 1);
    129    return (result != 0) + 2 * carry_out;
    130}
    131
    132static uint32_t cc_calc_subu(uint64_t borrow_out, uint64_t result)
    133{
    134    return cc_calc_addu(borrow_out + 1, result);
    135}
    136
    137static uint32_t cc_calc_add_64(int64_t a1, int64_t a2, int64_t ar)
    138{
    139    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
    140        return 3; /* overflow */
    141    } else {
    142        if (ar < 0) {
    143            return 1;
    144        } else if (ar > 0) {
    145            return 2;
    146        } else {
    147            return 0;
    148        }
    149    }
    150}
    151
    152static 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
    167static uint32_t cc_calc_abs_64(int64_t dst)
    168{
    169    if ((uint64_t)dst == 0x8000000000000000ULL) {
    170        return 3;
    171    } else if (dst) {
    172        return 2;
    173    } else {
    174        return 0;
    175    }
    176}
    177
    178static uint32_t cc_calc_nabs_64(int64_t dst)
    179{
    180    return !!dst;
    181}
    182
    183static uint32_t cc_calc_comp_64(int64_t dst)
    184{
    185    if ((uint64_t)dst == 0x8000000000000000ULL) {
    186        return 3;
    187    } else if (dst < 0) {
    188        return 1;
    189    } else if (dst > 0) {
    190        return 2;
    191    } else {
    192        return 0;
    193    }
    194}
    195
    196
    197static uint32_t cc_calc_add_32(int32_t a1, int32_t a2, int32_t ar)
    198{
    199    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
    200        return 3; /* overflow */
    201    } else {
    202        if (ar < 0) {
    203            return 1;
    204        } else if (ar > 0) {
    205            return 2;
    206        } else {
    207            return 0;
    208        }
    209    }
    210}
    211
    212static uint32_t cc_calc_sub_32(int32_t a1, int32_t a2, int32_t ar)
    213{
    214    if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
    215        return 3; /* overflow */
    216    } else {
    217        if (ar < 0) {
    218            return 1;
    219        } else if (ar > 0) {
    220            return 2;
    221        } else {
    222            return 0;
    223        }
    224    }
    225}
    226
    227static uint32_t cc_calc_abs_32(int32_t dst)
    228{
    229    if ((uint32_t)dst == 0x80000000UL) {
    230        return 3;
    231    } else if (dst) {
    232        return 2;
    233    } else {
    234        return 0;
    235    }
    236}
    237
    238static uint32_t cc_calc_nabs_32(int32_t dst)
    239{
    240    return !!dst;
    241}
    242
    243static uint32_t cc_calc_comp_32(int32_t dst)
    244{
    245    if ((uint32_t)dst == 0x80000000UL) {
    246        return 3;
    247    } else if (dst < 0) {
    248        return 1;
    249    } else if (dst > 0) {
    250        return 2;
    251    } else {
    252        return 0;
    253    }
    254}
    255
    256/* calculate condition code for insert character under mask insn */
    257static uint32_t cc_calc_icm(uint64_t mask, uint64_t val)
    258{
    259    if ((val & mask) == 0) {
    260        return 0;
    261    } else {
    262        int top = clz64(mask);
    263        if ((int64_t)(val << top) < 0) {
    264            return 1;
    265        } else {
    266            return 2;
    267        }
    268    }
    269}
    270
    271static uint32_t cc_calc_sla_32(uint32_t src, int shift)
    272{
    273    uint32_t mask = ((1U << shift) - 1U) << (32 - shift);
    274    uint32_t sign = 1U << 31;
    275    uint32_t match;
    276    int32_t r;
    277
    278    /* Check if the sign bit stays the same.  */
    279    if (src & sign) {
    280        match = mask;
    281    } else {
    282        match = 0;
    283    }
    284    if ((src & mask) != match) {
    285        /* Overflow.  */
    286        return 3;
    287    }
    288
    289    r = ((src << shift) & ~sign) | (src & sign);
    290    if (r == 0) {
    291        return 0;
    292    } else if (r < 0) {
    293        return 1;
    294    }
    295    return 2;
    296}
    297
    298static uint32_t cc_calc_sla_64(uint64_t src, int shift)
    299{
    300    uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
    301    uint64_t sign = 1ULL << 63;
    302    uint64_t match;
    303    int64_t r;
    304
    305    /* Check if the sign bit stays the same.  */
    306    if (src & sign) {
    307        match = mask;
    308    } else {
    309        match = 0;
    310    }
    311    if ((src & mask) != match) {
    312        /* Overflow.  */
    313        return 3;
    314    }
    315
    316    r = ((src << shift) & ~sign) | (src & sign);
    317    if (r == 0) {
    318        return 0;
    319    } else if (r < 0) {
    320        return 1;
    321    }
    322    return 2;
    323}
    324
    325static uint32_t cc_calc_flogr(uint64_t dst)
    326{
    327    return dst ? 2 : 0;
    328}
    329
    330static uint32_t cc_calc_lcbb(uint64_t dst)
    331{
    332    return dst == 16 ? 0 : 3;
    333}
    334
    335static uint32_t cc_calc_vc(uint64_t low, uint64_t high)
    336{
    337    if (high == -1ull && low == -1ull) {
    338        /* all elements match */
    339        return 0;
    340    } else if (high == 0 && low == 0) {
    341        /* no elements match */
    342        return 3;
    343    } else {
    344        /* some elements but not all match */
    345        return 1;
    346    }
    347}
    348
    349static uint32_t cc_calc_muls_32(int64_t res)
    350{
    351    const int64_t tmp = res >> 31;
    352
    353    if (!res) {
    354        return 0;
    355    } else if (tmp && tmp != -1) {
    356        return 3;
    357    } else if (res < 0) {
    358        return 1;
    359    }
    360    return 2;
    361}
    362
    363static uint64_t cc_calc_muls_64(int64_t res_high, uint64_t res_low)
    364{
    365    if (!res_high && !res_low) {
    366        return 0;
    367    } else if (res_high + (res_low >> 63) != 0) {
    368        return 3;
    369    } else if (res_high < 0) {
    370        return 1;
    371    }
    372    return 2;
    373}
    374
    375static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
    376                                  uint64_t src, uint64_t dst, uint64_t vr)
    377{
    378    uint32_t r = 0;
    379
    380    switch (cc_op) {
    381    case CC_OP_CONST0:
    382    case CC_OP_CONST1:
    383    case CC_OP_CONST2:
    384    case CC_OP_CONST3:
    385        /* cc_op value _is_ cc */
    386        r = cc_op;
    387        break;
    388    case CC_OP_LTGT0_32:
    389        r = cc_calc_ltgt0_32(dst);
    390        break;
    391    case CC_OP_LTGT0_64:
    392        r =  cc_calc_ltgt0_64(dst);
    393        break;
    394    case CC_OP_LTGT_32:
    395        r =  cc_calc_ltgt_32(src, dst);
    396        break;
    397    case CC_OP_LTGT_64:
    398        r =  cc_calc_ltgt_64(src, dst);
    399        break;
    400    case CC_OP_LTUGTU_32:
    401        r =  cc_calc_ltugtu_32(src, dst);
    402        break;
    403    case CC_OP_LTUGTU_64:
    404        r =  cc_calc_ltugtu_64(src, dst);
    405        break;
    406    case CC_OP_TM_32:
    407        r =  cc_calc_tm_32(src, dst);
    408        break;
    409    case CC_OP_TM_64:
    410        r =  cc_calc_tm_64(src, dst);
    411        break;
    412    case CC_OP_NZ:
    413        r =  cc_calc_nz(dst);
    414        break;
    415    case CC_OP_ADDU:
    416        r = cc_calc_addu(src, dst);
    417        break;
    418    case CC_OP_SUBU:
    419        r = cc_calc_subu(src, dst);
    420        break;
    421    case CC_OP_ADD_64:
    422        r =  cc_calc_add_64(src, dst, vr);
    423        break;
    424    case CC_OP_SUB_64:
    425        r =  cc_calc_sub_64(src, dst, vr);
    426        break;
    427    case CC_OP_ABS_64:
    428        r =  cc_calc_abs_64(dst);
    429        break;
    430    case CC_OP_NABS_64:
    431        r =  cc_calc_nabs_64(dst);
    432        break;
    433    case CC_OP_COMP_64:
    434        r =  cc_calc_comp_64(dst);
    435        break;
    436    case CC_OP_MULS_64:
    437        r = cc_calc_muls_64(src, dst);
    438        break;
    439
    440    case CC_OP_ADD_32:
    441        r =  cc_calc_add_32(src, dst, vr);
    442        break;
    443    case CC_OP_SUB_32:
    444        r =  cc_calc_sub_32(src, dst, vr);
    445        break;
    446    case CC_OP_ABS_32:
    447        r =  cc_calc_abs_32(dst);
    448        break;
    449    case CC_OP_NABS_32:
    450        r =  cc_calc_nabs_32(dst);
    451        break;
    452    case CC_OP_COMP_32:
    453        r =  cc_calc_comp_32(dst);
    454        break;
    455    case CC_OP_MULS_32:
    456        r = cc_calc_muls_32(dst);
    457        break;
    458
    459    case CC_OP_ICM:
    460        r =  cc_calc_icm(src, dst);
    461        break;
    462    case CC_OP_SLA_32:
    463        r =  cc_calc_sla_32(src, dst);
    464        break;
    465    case CC_OP_SLA_64:
    466        r =  cc_calc_sla_64(src, dst);
    467        break;
    468    case CC_OP_FLOGR:
    469        r = cc_calc_flogr(dst);
    470        break;
    471    case CC_OP_LCBB:
    472        r = cc_calc_lcbb(dst);
    473        break;
    474    case CC_OP_VC:
    475        r = cc_calc_vc(src, dst);
    476        break;
    477
    478    case CC_OP_NZ_F32:
    479        r = set_cc_nz_f32(dst);
    480        break;
    481    case CC_OP_NZ_F64:
    482        r = set_cc_nz_f64(dst);
    483        break;
    484    case CC_OP_NZ_F128:
    485        r = set_cc_nz_f128(make_float128(src, dst));
    486        break;
    487
    488    default:
    489        cpu_abort(env_cpu(env), "Unknown CC operation: %s\n", cc_name(cc_op));
    490    }
    491
    492    HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __func__,
    493               cc_name(cc_op), src, dst, vr, r);
    494    return r;
    495}
    496
    497uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
    498                 uint64_t vr)
    499{
    500    return do_calc_cc(env, cc_op, src, dst, vr);
    501}
    502
    503uint32_t HELPER(calc_cc)(CPUS390XState *env, uint32_t cc_op, uint64_t src,
    504                         uint64_t dst, uint64_t vr)
    505{
    506    return do_calc_cc(env, cc_op, src, dst, vr);
    507}
    508
    509#ifndef CONFIG_USER_ONLY
    510void HELPER(load_psw)(CPUS390XState *env, uint64_t mask, uint64_t addr)
    511{
    512    s390_cpu_set_psw(env, mask, addr);
    513    cpu_loop_exit(env_cpu(env));
    514}
    515
    516void HELPER(sacf)(CPUS390XState *env, uint64_t a1)
    517{
    518    HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1);
    519
    520    switch (a1 & 0xf00) {
    521    case 0x000:
    522        env->psw.mask &= ~PSW_MASK_ASC;
    523        env->psw.mask |= PSW_ASC_PRIMARY;
    524        break;
    525    case 0x100:
    526        env->psw.mask &= ~PSW_MASK_ASC;
    527        env->psw.mask |= PSW_ASC_SECONDARY;
    528        break;
    529    case 0x300:
    530        env->psw.mask &= ~PSW_MASK_ASC;
    531        env->psw.mask |= PSW_ASC_HOME;
    532        break;
    533    default:
    534        HELPER_LOG("unknown sacf mode: %" PRIx64 "\n", a1);
    535        tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
    536    }
    537}
    538#endif