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

trans_rvm.c.inc (6971B)


      1/*
      2 * RISC-V translation routines for the RV64M Standard Extension.
      3 *
      4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
      5 * Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
      6 *                    Bastian Koppelmann, kbastian@mail.uni-paderborn.de
      7 *
      8 * This program is free software; you can redistribute it and/or modify it
      9 * under the terms and conditions of the GNU General Public License,
     10 * version 2 or later, as published by the Free Software Foundation.
     11 *
     12 * This program is distributed in the hope it will be useful, but WITHOUT
     13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     15 * more details.
     16 *
     17 * You should have received a copy of the GNU General Public License along with
     18 * this program.  If not, see <http://www.gnu.org/licenses/>.
     19 */
     20
     21
     22static bool trans_mul(DisasContext *ctx, arg_mul *a)
     23{
     24    REQUIRE_EXT(ctx, RVM);
     25    return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl);
     26}
     27
     28static void gen_mulh(TCGv ret, TCGv s1, TCGv s2)
     29{
     30    TCGv discard = tcg_temp_new();
     31
     32    tcg_gen_muls2_tl(discard, ret, s1, s2);
     33    tcg_temp_free(discard);
     34}
     35
     36static bool trans_mulh(DisasContext *ctx, arg_mulh *a)
     37{
     38    REQUIRE_EXT(ctx, RVM);
     39    return gen_arith(ctx, a, EXT_NONE, gen_mulh);
     40}
     41
     42static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2)
     43{
     44    TCGv rl = tcg_temp_new();
     45    TCGv rh = tcg_temp_new();
     46
     47    tcg_gen_mulu2_tl(rl, rh, arg1, arg2);
     48    /* fix up for one negative */
     49    tcg_gen_sari_tl(rl, arg1, TARGET_LONG_BITS - 1);
     50    tcg_gen_and_tl(rl, rl, arg2);
     51    tcg_gen_sub_tl(ret, rh, rl);
     52
     53    tcg_temp_free(rl);
     54    tcg_temp_free(rh);
     55}
     56
     57static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a)
     58{
     59    REQUIRE_EXT(ctx, RVM);
     60    return gen_arith(ctx, a, EXT_NONE, gen_mulhsu);
     61}
     62
     63static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2)
     64{
     65    TCGv discard = tcg_temp_new();
     66
     67    tcg_gen_mulu2_tl(discard, ret, s1, s2);
     68    tcg_temp_free(discard);
     69}
     70
     71static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a)
     72{
     73    REQUIRE_EXT(ctx, RVM);
     74    return gen_arith(ctx, a, EXT_NONE, gen_mulhu);
     75}
     76
     77static void gen_div(TCGv ret, TCGv source1, TCGv source2)
     78{
     79    TCGv temp1, temp2, zero, one, mone, min;
     80
     81    temp1 = tcg_temp_new();
     82    temp2 = tcg_temp_new();
     83    zero = tcg_constant_tl(0);
     84    one = tcg_constant_tl(1);
     85    mone = tcg_constant_tl(-1);
     86    min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1));
     87
     88    /*
     89     * If overflow, set temp2 to 1, else source2.
     90     * This produces the required result of min.
     91     */
     92    tcg_gen_setcond_tl(TCG_COND_EQ, temp1, source1, min);
     93    tcg_gen_setcond_tl(TCG_COND_EQ, temp2, source2, mone);
     94    tcg_gen_and_tl(temp1, temp1, temp2);
     95    tcg_gen_movcond_tl(TCG_COND_NE, temp2, temp1, zero, one, source2);
     96
     97    /*
     98     * If div by zero, set temp1 to -1 and temp2 to 1 to
     99     * produce the required result of -1.
    100     */
    101    tcg_gen_movcond_tl(TCG_COND_EQ, temp1, source2, zero, mone, source1);
    102    tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, temp2);
    103
    104    tcg_gen_div_tl(ret, temp1, temp2);
    105
    106    tcg_temp_free(temp1);
    107    tcg_temp_free(temp2);
    108}
    109
    110static bool trans_div(DisasContext *ctx, arg_div *a)
    111{
    112    REQUIRE_EXT(ctx, RVM);
    113    return gen_arith(ctx, a, EXT_SIGN, gen_div);
    114}
    115
    116static void gen_divu(TCGv ret, TCGv source1, TCGv source2)
    117{
    118    TCGv temp1, temp2, zero, one, max;
    119
    120    temp1 = tcg_temp_new();
    121    temp2 = tcg_temp_new();
    122    zero = tcg_constant_tl(0);
    123    one = tcg_constant_tl(1);
    124    max = tcg_constant_tl(~0);
    125
    126    /*
    127     * If div by zero, set temp1 to max and temp2 to 1 to
    128     * produce the required result of max.
    129     */
    130    tcg_gen_movcond_tl(TCG_COND_EQ, temp1, source2, zero, max, source1);
    131    tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, source2);
    132    tcg_gen_divu_tl(ret, temp1, temp2);
    133
    134    tcg_temp_free(temp1);
    135    tcg_temp_free(temp2);
    136}
    137
    138static bool trans_divu(DisasContext *ctx, arg_divu *a)
    139{
    140    REQUIRE_EXT(ctx, RVM);
    141    return gen_arith(ctx, a, EXT_ZERO, gen_divu);
    142}
    143
    144static void gen_rem(TCGv ret, TCGv source1, TCGv source2)
    145{
    146    TCGv temp1, temp2, zero, one, mone, min;
    147
    148    temp1 = tcg_temp_new();
    149    temp2 = tcg_temp_new();
    150    zero = tcg_constant_tl(0);
    151    one = tcg_constant_tl(1);
    152    mone = tcg_constant_tl(-1);
    153    min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1));
    154
    155    /*
    156     * If overflow, set temp1 to 0, else source1.
    157     * This avoids a possible host trap, and produces the required result of 0.
    158     */
    159    tcg_gen_setcond_tl(TCG_COND_EQ, temp1, source1, min);
    160    tcg_gen_setcond_tl(TCG_COND_EQ, temp2, source2, mone);
    161    tcg_gen_and_tl(temp1, temp1, temp2);
    162    tcg_gen_movcond_tl(TCG_COND_NE, temp1, temp1, zero, zero, source1);
    163
    164    /*
    165     * If div by zero, set temp2 to 1, else source2.
    166     * This avoids a possible host trap, but produces an incorrect result.
    167     */
    168    tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, source2);
    169
    170    tcg_gen_rem_tl(temp1, temp1, temp2);
    171
    172    /* If div by zero, the required result is the original dividend. */
    173    tcg_gen_movcond_tl(TCG_COND_EQ, ret, source2, zero, source1, temp1);
    174
    175    tcg_temp_free(temp1);
    176    tcg_temp_free(temp2);
    177}
    178
    179static bool trans_rem(DisasContext *ctx, arg_rem *a)
    180{
    181    REQUIRE_EXT(ctx, RVM);
    182    return gen_arith(ctx, a, EXT_SIGN, gen_rem);
    183}
    184
    185static void gen_remu(TCGv ret, TCGv source1, TCGv source2)
    186{
    187    TCGv temp, zero, one;
    188
    189    temp = tcg_temp_new();
    190    zero = tcg_constant_tl(0);
    191    one = tcg_constant_tl(1);
    192
    193    /*
    194     * If div by zero, set temp to 1, else source2.
    195     * This avoids a possible host trap, but produces an incorrect result.
    196     */
    197    tcg_gen_movcond_tl(TCG_COND_EQ, temp, source2, zero, one, source2);
    198
    199    tcg_gen_remu_tl(temp, source1, temp);
    200
    201    /* If div by zero, the required result is the original dividend. */
    202    tcg_gen_movcond_tl(TCG_COND_EQ, ret, source2, zero, source1, temp);
    203
    204    tcg_temp_free(temp);
    205}
    206
    207static bool trans_remu(DisasContext *ctx, arg_remu *a)
    208{
    209    REQUIRE_EXT(ctx, RVM);
    210    return gen_arith(ctx, a, EXT_ZERO, gen_remu);
    211}
    212
    213static bool trans_mulw(DisasContext *ctx, arg_mulw *a)
    214{
    215    REQUIRE_64BIT(ctx);
    216    REQUIRE_EXT(ctx, RVM);
    217    ctx->w = true;
    218    return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl);
    219}
    220
    221static bool trans_divw(DisasContext *ctx, arg_divw *a)
    222{
    223    REQUIRE_64BIT(ctx);
    224    REQUIRE_EXT(ctx, RVM);
    225    ctx->w = true;
    226    return gen_arith(ctx, a, EXT_SIGN, gen_div);
    227}
    228
    229static bool trans_divuw(DisasContext *ctx, arg_divuw *a)
    230{
    231    REQUIRE_64BIT(ctx);
    232    REQUIRE_EXT(ctx, RVM);
    233    ctx->w = true;
    234    return gen_arith(ctx, a, EXT_ZERO, gen_divu);
    235}
    236
    237static bool trans_remw(DisasContext *ctx, arg_remw *a)
    238{
    239    REQUIRE_64BIT(ctx);
    240    REQUIRE_EXT(ctx, RVM);
    241    ctx->w = true;
    242    return gen_arith(ctx, a, EXT_SIGN, gen_rem);
    243}
    244
    245static bool trans_remuw(DisasContext *ctx, arg_remuw *a)
    246{
    247    REQUIRE_64BIT(ctx);
    248    REQUIRE_EXT(ctx, RVM);
    249    ctx->w = true;
    250    return gen_arith(ctx, a, EXT_ZERO, gen_remu);
    251}