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 (10935B)


      1/*
      2 * Helpers for lazy condition code handling
      3 *
      4 *  Copyright (c) 2003-2005 Fabrice Bellard
      5 *
      6 * This library is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU Lesser General Public
      8 * License as published by the Free Software Foundation; either
      9 * version 2.1 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     18 */
     19
     20#include "qemu/osdep.h"
     21#include "cpu.h"
     22#include "exec/helper-proto.h"
     23
     24static uint32_t compute_all_flags(CPUSPARCState *env)
     25{
     26    return env->psr & PSR_ICC;
     27}
     28
     29static uint32_t compute_C_flags(CPUSPARCState *env)
     30{
     31    return env->psr & PSR_CARRY;
     32}
     33
     34static inline uint32_t get_NZ_icc(int32_t dst)
     35{
     36    uint32_t ret = 0;
     37
     38    if (dst == 0) {
     39        ret = PSR_ZERO;
     40    } else if (dst < 0) {
     41        ret = PSR_NEG;
     42    }
     43    return ret;
     44}
     45
     46#ifdef TARGET_SPARC64
     47static uint32_t compute_all_flags_xcc(CPUSPARCState *env)
     48{
     49    return env->xcc & PSR_ICC;
     50}
     51
     52static uint32_t compute_C_flags_xcc(CPUSPARCState *env)
     53{
     54    return env->xcc & PSR_CARRY;
     55}
     56
     57static inline uint32_t get_NZ_xcc(target_long dst)
     58{
     59    uint32_t ret = 0;
     60
     61    if (!dst) {
     62        ret = PSR_ZERO;
     63    } else if (dst < 0) {
     64        ret = PSR_NEG;
     65    }
     66    return ret;
     67}
     68#endif
     69
     70static inline uint32_t get_V_div_icc(target_ulong src2)
     71{
     72    uint32_t ret = 0;
     73
     74    if (src2 != 0) {
     75        ret = PSR_OVF;
     76    }
     77    return ret;
     78}
     79
     80static uint32_t compute_all_div(CPUSPARCState *env)
     81{
     82    uint32_t ret;
     83
     84    ret = get_NZ_icc(CC_DST);
     85    ret |= get_V_div_icc(CC_SRC2);
     86    return ret;
     87}
     88
     89static uint32_t compute_C_div(CPUSPARCState *env)
     90{
     91    return 0;
     92}
     93
     94static inline uint32_t get_C_add_icc(uint32_t dst, uint32_t src1)
     95{
     96    uint32_t ret = 0;
     97
     98    if (dst < src1) {
     99        ret = PSR_CARRY;
    100    }
    101    return ret;
    102}
    103
    104static inline uint32_t get_C_addx_icc(uint32_t dst, uint32_t src1,
    105                                      uint32_t src2)
    106{
    107    uint32_t ret = 0;
    108
    109    if (((src1 & src2) | (~dst & (src1 | src2))) & (1U << 31)) {
    110        ret = PSR_CARRY;
    111    }
    112    return ret;
    113}
    114
    115static inline uint32_t get_V_add_icc(uint32_t dst, uint32_t src1,
    116                                     uint32_t src2)
    117{
    118    uint32_t ret = 0;
    119
    120    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1U << 31)) {
    121        ret = PSR_OVF;
    122    }
    123    return ret;
    124}
    125
    126#ifdef TARGET_SPARC64
    127static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
    128{
    129    uint32_t ret = 0;
    130
    131    if (dst < src1) {
    132        ret = PSR_CARRY;
    133    }
    134    return ret;
    135}
    136
    137static inline uint32_t get_C_addx_xcc(target_ulong dst, target_ulong src1,
    138                                      target_ulong src2)
    139{
    140    uint32_t ret = 0;
    141
    142    if (((src1 & src2) | (~dst & (src1 | src2))) & (1ULL << 63)) {
    143        ret = PSR_CARRY;
    144    }
    145    return ret;
    146}
    147
    148static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
    149                                     target_ulong src2)
    150{
    151    uint32_t ret = 0;
    152
    153    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63)) {
    154        ret = PSR_OVF;
    155    }
    156    return ret;
    157}
    158
    159static uint32_t compute_all_add_xcc(CPUSPARCState *env)
    160{
    161    uint32_t ret;
    162
    163    ret = get_NZ_xcc(CC_DST);
    164    ret |= get_C_add_xcc(CC_DST, CC_SRC);
    165    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
    166    return ret;
    167}
    168
    169static uint32_t compute_C_add_xcc(CPUSPARCState *env)
    170{
    171    return get_C_add_xcc(CC_DST, CC_SRC);
    172}
    173#endif
    174
    175static uint32_t compute_all_add(CPUSPARCState *env)
    176{
    177    uint32_t ret;
    178
    179    ret = get_NZ_icc(CC_DST);
    180    ret |= get_C_add_icc(CC_DST, CC_SRC);
    181    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
    182    return ret;
    183}
    184
    185static uint32_t compute_C_add(CPUSPARCState *env)
    186{
    187    return get_C_add_icc(CC_DST, CC_SRC);
    188}
    189
    190#ifdef TARGET_SPARC64
    191static uint32_t compute_all_addx_xcc(CPUSPARCState *env)
    192{
    193    uint32_t ret;
    194
    195    ret = get_NZ_xcc(CC_DST);
    196    ret |= get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
    197    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
    198    return ret;
    199}
    200
    201static uint32_t compute_C_addx_xcc(CPUSPARCState *env)
    202{
    203    return get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
    204}
    205#endif
    206
    207static uint32_t compute_all_addx(CPUSPARCState *env)
    208{
    209    uint32_t ret;
    210
    211    ret = get_NZ_icc(CC_DST);
    212    ret |= get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
    213    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
    214    return ret;
    215}
    216
    217static uint32_t compute_C_addx(CPUSPARCState *env)
    218{
    219    return get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
    220}
    221
    222static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
    223{
    224    uint32_t ret = 0;
    225
    226    if ((src1 | src2) & 0x3) {
    227        ret = PSR_OVF;
    228    }
    229    return ret;
    230}
    231
    232static uint32_t compute_all_tadd(CPUSPARCState *env)
    233{
    234    uint32_t ret;
    235
    236    ret = get_NZ_icc(CC_DST);
    237    ret |= get_C_add_icc(CC_DST, CC_SRC);
    238    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
    239    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
    240    return ret;
    241}
    242
    243static uint32_t compute_all_taddtv(CPUSPARCState *env)
    244{
    245    uint32_t ret;
    246
    247    ret = get_NZ_icc(CC_DST);
    248    ret |= get_C_add_icc(CC_DST, CC_SRC);
    249    return ret;
    250}
    251
    252static inline uint32_t get_C_sub_icc(uint32_t src1, uint32_t src2)
    253{
    254    uint32_t ret = 0;
    255
    256    if (src1 < src2) {
    257        ret = PSR_CARRY;
    258    }
    259    return ret;
    260}
    261
    262static inline uint32_t get_C_subx_icc(uint32_t dst, uint32_t src1,
    263                                      uint32_t src2)
    264{
    265    uint32_t ret = 0;
    266
    267    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1U << 31)) {
    268        ret = PSR_CARRY;
    269    }
    270    return ret;
    271}
    272
    273static inline uint32_t get_V_sub_icc(uint32_t dst, uint32_t src1,
    274                                     uint32_t src2)
    275{
    276    uint32_t ret = 0;
    277
    278    if (((src1 ^ src2) & (src1 ^ dst)) & (1U << 31)) {
    279        ret = PSR_OVF;
    280    }
    281    return ret;
    282}
    283
    284
    285#ifdef TARGET_SPARC64
    286static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
    287{
    288    uint32_t ret = 0;
    289
    290    if (src1 < src2) {
    291        ret = PSR_CARRY;
    292    }
    293    return ret;
    294}
    295
    296static inline uint32_t get_C_subx_xcc(target_ulong dst, target_ulong src1,
    297                                      target_ulong src2)
    298{
    299    uint32_t ret = 0;
    300
    301    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1ULL << 63)) {
    302        ret = PSR_CARRY;
    303    }
    304    return ret;
    305}
    306
    307static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
    308                                     target_ulong src2)
    309{
    310    uint32_t ret = 0;
    311
    312    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63)) {
    313        ret = PSR_OVF;
    314    }
    315    return ret;
    316}
    317
    318static uint32_t compute_all_sub_xcc(CPUSPARCState *env)
    319{
    320    uint32_t ret;
    321
    322    ret = get_NZ_xcc(CC_DST);
    323    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
    324    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
    325    return ret;
    326}
    327
    328static uint32_t compute_C_sub_xcc(CPUSPARCState *env)
    329{
    330    return get_C_sub_xcc(CC_SRC, CC_SRC2);
    331}
    332#endif
    333
    334static uint32_t compute_all_sub(CPUSPARCState *env)
    335{
    336    uint32_t ret;
    337
    338    ret = get_NZ_icc(CC_DST);
    339    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
    340    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
    341    return ret;
    342}
    343
    344static uint32_t compute_C_sub(CPUSPARCState *env)
    345{
    346    return get_C_sub_icc(CC_SRC, CC_SRC2);
    347}
    348
    349#ifdef TARGET_SPARC64
    350static uint32_t compute_all_subx_xcc(CPUSPARCState *env)
    351{
    352    uint32_t ret;
    353
    354    ret = get_NZ_xcc(CC_DST);
    355    ret |= get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
    356    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
    357    return ret;
    358}
    359
    360static uint32_t compute_C_subx_xcc(CPUSPARCState *env)
    361{
    362    return get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
    363}
    364#endif
    365
    366static uint32_t compute_all_subx(CPUSPARCState *env)
    367{
    368    uint32_t ret;
    369
    370    ret = get_NZ_icc(CC_DST);
    371    ret |= get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
    372    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
    373    return ret;
    374}
    375
    376static uint32_t compute_C_subx(CPUSPARCState *env)
    377{
    378    return get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
    379}
    380
    381static uint32_t compute_all_tsub(CPUSPARCState *env)
    382{
    383    uint32_t ret;
    384
    385    ret = get_NZ_icc(CC_DST);
    386    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
    387    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
    388    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
    389    return ret;
    390}
    391
    392static uint32_t compute_all_tsubtv(CPUSPARCState *env)
    393{
    394    uint32_t ret;
    395
    396    ret = get_NZ_icc(CC_DST);
    397    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
    398    return ret;
    399}
    400
    401static uint32_t compute_all_logic(CPUSPARCState *env)
    402{
    403    return get_NZ_icc(CC_DST);
    404}
    405
    406static uint32_t compute_C_logic(CPUSPARCState *env)
    407{
    408    return 0;
    409}
    410
    411#ifdef TARGET_SPARC64
    412static uint32_t compute_all_logic_xcc(CPUSPARCState *env)
    413{
    414    return get_NZ_xcc(CC_DST);
    415}
    416#endif
    417
    418typedef struct CCTable {
    419    uint32_t (*compute_all)(CPUSPARCState *env); /* return all the flags */
    420    uint32_t (*compute_c)(CPUSPARCState *env);  /* return the C flag */
    421} CCTable;
    422
    423static const CCTable icc_table[CC_OP_NB] = {
    424    /* CC_OP_DYNAMIC should never happen */
    425    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
    426    [CC_OP_DIV] = { compute_all_div, compute_C_div },
    427    [CC_OP_ADD] = { compute_all_add, compute_C_add },
    428    [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
    429    [CC_OP_TADD] = { compute_all_tadd, compute_C_add },
    430    [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
    431    [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
    432    [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
    433    [CC_OP_TSUB] = { compute_all_tsub, compute_C_sub },
    434    [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_sub },
    435    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
    436};
    437
    438#ifdef TARGET_SPARC64
    439static const CCTable xcc_table[CC_OP_NB] = {
    440    /* CC_OP_DYNAMIC should never happen */
    441    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
    442    [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
    443    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
    444    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
    445    [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
    446    [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
    447    [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
    448    [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
    449    [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
    450    [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
    451    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
    452};
    453#endif
    454
    455void helper_compute_psr(CPUSPARCState *env)
    456{
    457    uint32_t new_psr;
    458
    459    new_psr = icc_table[CC_OP].compute_all(env);
    460    env->psr = new_psr;
    461#ifdef TARGET_SPARC64
    462    new_psr = xcc_table[CC_OP].compute_all(env);
    463    env->xcc = new_psr;
    464#endif
    465    CC_OP = CC_OP_FLAGS;
    466}
    467
    468uint32_t helper_compute_C_icc(CPUSPARCState *env)
    469{
    470    return icc_table[CC_OP].compute_c(env) >> PSR_CARRY_SHIFT;
    471}