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

gen_tcg.h (28622B)


      1/*
      2 *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
      3 *
      4 *  This program is free software; you can redistribute it and/or modify
      5 *  it under the terms of the GNU General Public License as published by
      6 *  the Free Software Foundation; either version 2 of the License, or
      7 *  (at your option) any later version.
      8 *
      9 *  This program is distributed in the hope that it will be useful,
     10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 *  GNU General Public License for more details.
     13 *
     14 *  You should have received a copy of the GNU General Public License
     15 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#ifndef HEXAGON_GEN_TCG_H
     19#define HEXAGON_GEN_TCG_H
     20
     21/*
     22 * Here is a primer to understand the tag names for load/store instructions
     23 *
     24 * Data types
     25 *      b        signed byte                       r0 = memb(r2+#0)
     26 *     ub        unsigned byte                     r0 = memub(r2+#0)
     27 *      h        signed half word (16 bits)        r0 = memh(r2+#0)
     28 *     uh        unsigned half word                r0 = memuh(r2+#0)
     29 *      i        integer (32 bits)                 r0 = memw(r2+#0)
     30 *      d        double word (64 bits)             r1:0 = memd(r2+#0)
     31 *
     32 * Addressing modes
     33 *     _io       indirect with offset              r0 = memw(r1+#4)
     34 *     _ur       absolute with register offset     r0 = memw(r1<<#4+##variable)
     35 *     _rr       indirect with register offset     r0 = memw(r1+r4<<#2)
     36 *     gp        global pointer relative           r0 = memw(gp+#200)
     37 *     _sp       stack pointer relative            r0 = memw(r29+#12)
     38 *     _ap       absolute set                      r0 = memw(r1=##variable)
     39 *     _pr       post increment register           r0 = memw(r1++m1)
     40 *     _pbr      post increment bit reverse        r0 = memw(r1++m1:brev)
     41 *     _pi       post increment immediate          r0 = memb(r1++#1)
     42 *     _pci      post increment circular immediate r0 = memw(r1++#4:circ(m0))
     43 *     _pcr      post increment circular register  r0 = memw(r1++I:circ(m0))
     44 */
     45
     46/* Macros for complex addressing modes */
     47#define GET_EA_ap \
     48    do { \
     49        fEA_IMM(UiV); \
     50        tcg_gen_movi_tl(ReV, UiV); \
     51    } while (0)
     52#define GET_EA_pr \
     53    do { \
     54        fEA_REG(RxV); \
     55        fPM_M(RxV, MuV); \
     56    } while (0)
     57#define GET_EA_pbr \
     58    do { \
     59        gen_helper_fbrev(EA, RxV); \
     60        tcg_gen_add_tl(RxV, RxV, MuV); \
     61    } while (0)
     62#define GET_EA_pi \
     63    do { \
     64        fEA_REG(RxV); \
     65        fPM_I(RxV, siV); \
     66    } while (0)
     67#define GET_EA_pci \
     68    do { \
     69        TCGv tcgv_siV = tcg_const_tl(siV); \
     70        tcg_gen_mov_tl(EA, RxV); \
     71        gen_helper_fcircadd(RxV, RxV, tcgv_siV, MuV, \
     72                            hex_gpr[HEX_REG_CS0 + MuN]); \
     73        tcg_temp_free(tcgv_siV); \
     74    } while (0)
     75#define GET_EA_pcr(SHIFT) \
     76    do { \
     77        TCGv ireg = tcg_temp_new(); \
     78        tcg_gen_mov_tl(EA, RxV); \
     79        gen_read_ireg(ireg, MuV, (SHIFT)); \
     80        gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
     81        tcg_temp_free(ireg); \
     82    } while (0)
     83
     84/* Instructions with multiple definitions */
     85#define fGEN_TCG_LOAD_AP(RES, SIZE, SIGN) \
     86    do { \
     87        fMUST_IMMEXT(UiV); \
     88        fEA_IMM(UiV); \
     89        fLOAD(1, SIZE, SIGN, EA, RES); \
     90        tcg_gen_movi_tl(ReV, UiV); \
     91    } while (0)
     92
     93#define fGEN_TCG_L4_loadrub_ap(SHORTCODE) \
     94    fGEN_TCG_LOAD_AP(RdV, 1, u)
     95#define fGEN_TCG_L4_loadrb_ap(SHORTCODE) \
     96    fGEN_TCG_LOAD_AP(RdV, 1, s)
     97#define fGEN_TCG_L4_loadruh_ap(SHORTCODE) \
     98    fGEN_TCG_LOAD_AP(RdV, 2, u)
     99#define fGEN_TCG_L4_loadrh_ap(SHORTCODE) \
    100    fGEN_TCG_LOAD_AP(RdV, 2, s)
    101#define fGEN_TCG_L4_loadri_ap(SHORTCODE) \
    102    fGEN_TCG_LOAD_AP(RdV, 4, u)
    103#define fGEN_TCG_L4_loadrd_ap(SHORTCODE) \
    104    fGEN_TCG_LOAD_AP(RddV, 8, u)
    105
    106#define fGEN_TCG_L2_loadrub_pci(SHORTCODE)    SHORTCODE
    107#define fGEN_TCG_L2_loadrb_pci(SHORTCODE)     SHORTCODE
    108#define fGEN_TCG_L2_loadruh_pci(SHORTCODE)    SHORTCODE
    109#define fGEN_TCG_L2_loadrh_pci(SHORTCODE)     SHORTCODE
    110#define fGEN_TCG_L2_loadri_pci(SHORTCODE)     SHORTCODE
    111#define fGEN_TCG_L2_loadrd_pci(SHORTCODE)     SHORTCODE
    112
    113#define fGEN_TCG_LOAD_pcr(SHIFT, LOAD) \
    114    do { \
    115        TCGv ireg = tcg_temp_new(); \
    116        tcg_gen_mov_tl(EA, RxV); \
    117        gen_read_ireg(ireg, MuV, SHIFT); \
    118        gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
    119        LOAD; \
    120        tcg_temp_free(ireg); \
    121    } while (0)
    122
    123#define fGEN_TCG_L2_loadrub_pcr(SHORTCODE) \
    124      fGEN_TCG_LOAD_pcr(0, fLOAD(1, 1, u, EA, RdV))
    125#define fGEN_TCG_L2_loadrb_pcr(SHORTCODE) \
    126      fGEN_TCG_LOAD_pcr(0, fLOAD(1, 1, s, EA, RdV))
    127#define fGEN_TCG_L2_loadruh_pcr(SHORTCODE) \
    128      fGEN_TCG_LOAD_pcr(1, fLOAD(1, 2, u, EA, RdV))
    129#define fGEN_TCG_L2_loadrh_pcr(SHORTCODE) \
    130      fGEN_TCG_LOAD_pcr(1, fLOAD(1, 2, s, EA, RdV))
    131#define fGEN_TCG_L2_loadri_pcr(SHORTCODE) \
    132      fGEN_TCG_LOAD_pcr(2, fLOAD(1, 4, u, EA, RdV))
    133#define fGEN_TCG_L2_loadrd_pcr(SHORTCODE) \
    134      fGEN_TCG_LOAD_pcr(3, fLOAD(1, 8, u, EA, RddV))
    135
    136#define fGEN_TCG_L2_loadrub_pr(SHORTCODE)      SHORTCODE
    137#define fGEN_TCG_L2_loadrub_pbr(SHORTCODE)     SHORTCODE
    138#define fGEN_TCG_L2_loadrub_pi(SHORTCODE)      SHORTCODE
    139#define fGEN_TCG_L2_loadrb_pr(SHORTCODE)       SHORTCODE
    140#define fGEN_TCG_L2_loadrb_pbr(SHORTCODE)      SHORTCODE
    141#define fGEN_TCG_L2_loadrb_pi(SHORTCODE)       SHORTCODE
    142#define fGEN_TCG_L2_loadruh_pr(SHORTCODE)      SHORTCODE
    143#define fGEN_TCG_L2_loadruh_pbr(SHORTCODE)     SHORTCODE
    144#define fGEN_TCG_L2_loadruh_pi(SHORTCODE)      SHORTCODE
    145#define fGEN_TCG_L2_loadrh_pr(SHORTCODE)       SHORTCODE
    146#define fGEN_TCG_L2_loadrh_pbr(SHORTCODE)      SHORTCODE
    147#define fGEN_TCG_L2_loadrh_pi(SHORTCODE)       SHORTCODE
    148#define fGEN_TCG_L2_loadri_pr(SHORTCODE)       SHORTCODE
    149#define fGEN_TCG_L2_loadri_pbr(SHORTCODE)      SHORTCODE
    150#define fGEN_TCG_L2_loadri_pi(SHORTCODE)       SHORTCODE
    151#define fGEN_TCG_L2_loadrd_pr(SHORTCODE)       SHORTCODE
    152#define fGEN_TCG_L2_loadrd_pbr(SHORTCODE)      SHORTCODE
    153#define fGEN_TCG_L2_loadrd_pi(SHORTCODE)       SHORTCODE
    154
    155/*
    156 * These instructions load 2 bytes and places them in
    157 * two halves of the destination register.
    158 * The GET_EA macro determines the addressing mode.
    159 * The SIGN argument determines whether to zero-extend or
    160 * sign-extend.
    161 */
    162#define fGEN_TCG_loadbXw2(GET_EA, SIGN) \
    163    do { \
    164        TCGv tmp = tcg_temp_new(); \
    165        TCGv byte = tcg_temp_new(); \
    166        GET_EA; \
    167        fLOAD(1, 2, u, EA, tmp); \
    168        tcg_gen_movi_tl(RdV, 0); \
    169        for (int i = 0; i < 2; i++) { \
    170            gen_set_half(i, RdV, gen_get_byte(byte, i, tmp, (SIGN))); \
    171        } \
    172        tcg_temp_free(tmp); \
    173        tcg_temp_free(byte); \
    174    } while (0)
    175
    176#define fGEN_TCG_L2_loadbzw2_io(SHORTCODE) \
    177    fGEN_TCG_loadbXw2(fEA_RI(RsV, siV), false)
    178#define fGEN_TCG_L4_loadbzw2_ur(SHORTCODE) \
    179    fGEN_TCG_loadbXw2(fEA_IRs(UiV, RtV, uiV), false)
    180#define fGEN_TCG_L2_loadbsw2_io(SHORTCODE) \
    181    fGEN_TCG_loadbXw2(fEA_RI(RsV, siV), true)
    182#define fGEN_TCG_L4_loadbsw2_ur(SHORTCODE) \
    183    fGEN_TCG_loadbXw2(fEA_IRs(UiV, RtV, uiV), true)
    184#define fGEN_TCG_L4_loadbzw2_ap(SHORTCODE) \
    185    fGEN_TCG_loadbXw2(GET_EA_ap, false)
    186#define fGEN_TCG_L2_loadbzw2_pr(SHORTCODE) \
    187    fGEN_TCG_loadbXw2(GET_EA_pr, false)
    188#define fGEN_TCG_L2_loadbzw2_pbr(SHORTCODE) \
    189    fGEN_TCG_loadbXw2(GET_EA_pbr, false)
    190#define fGEN_TCG_L2_loadbzw2_pi(SHORTCODE) \
    191    fGEN_TCG_loadbXw2(GET_EA_pi, false)
    192#define fGEN_TCG_L4_loadbsw2_ap(SHORTCODE) \
    193    fGEN_TCG_loadbXw2(GET_EA_ap, true)
    194#define fGEN_TCG_L2_loadbsw2_pr(SHORTCODE) \
    195    fGEN_TCG_loadbXw2(GET_EA_pr, true)
    196#define fGEN_TCG_L2_loadbsw2_pbr(SHORTCODE) \
    197    fGEN_TCG_loadbXw2(GET_EA_pbr, true)
    198#define fGEN_TCG_L2_loadbsw2_pi(SHORTCODE) \
    199    fGEN_TCG_loadbXw2(GET_EA_pi, true)
    200#define fGEN_TCG_L2_loadbzw2_pci(SHORTCODE) \
    201    fGEN_TCG_loadbXw2(GET_EA_pci, false)
    202#define fGEN_TCG_L2_loadbsw2_pci(SHORTCODE) \
    203    fGEN_TCG_loadbXw2(GET_EA_pci, true)
    204#define fGEN_TCG_L2_loadbzw2_pcr(SHORTCODE) \
    205    fGEN_TCG_loadbXw2(GET_EA_pcr(1), false)
    206#define fGEN_TCG_L2_loadbsw2_pcr(SHORTCODE) \
    207    fGEN_TCG_loadbXw2(GET_EA_pcr(1), true)
    208
    209/*
    210 * These instructions load 4 bytes and places them in
    211 * four halves of the destination register pair.
    212 * The GET_EA macro determines the addressing mode.
    213 * The SIGN argument determines whether to zero-extend or
    214 * sign-extend.
    215 */
    216#define fGEN_TCG_loadbXw4(GET_EA, SIGN) \
    217    do { \
    218        TCGv tmp = tcg_temp_new(); \
    219        TCGv byte = tcg_temp_new(); \
    220        GET_EA; \
    221        fLOAD(1, 4, u, EA, tmp);  \
    222        tcg_gen_movi_i64(RddV, 0); \
    223        for (int i = 0; i < 4; i++) { \
    224            gen_set_half_i64(i, RddV, gen_get_byte(byte, i, tmp, (SIGN)));  \
    225        }  \
    226        tcg_temp_free(tmp); \
    227        tcg_temp_free(byte); \
    228    } while (0)
    229
    230#define fGEN_TCG_L2_loadbzw4_io(SHORTCODE) \
    231    fGEN_TCG_loadbXw4(fEA_RI(RsV, siV), false)
    232#define fGEN_TCG_L4_loadbzw4_ur(SHORTCODE) \
    233    fGEN_TCG_loadbXw4(fEA_IRs(UiV, RtV, uiV), false)
    234#define fGEN_TCG_L2_loadbsw4_io(SHORTCODE) \
    235    fGEN_TCG_loadbXw4(fEA_RI(RsV, siV), true)
    236#define fGEN_TCG_L4_loadbsw4_ur(SHORTCODE) \
    237    fGEN_TCG_loadbXw4(fEA_IRs(UiV, RtV, uiV), true)
    238#define fGEN_TCG_L2_loadbzw4_pci(SHORTCODE) \
    239    fGEN_TCG_loadbXw4(GET_EA_pci, false)
    240#define fGEN_TCG_L2_loadbsw4_pci(SHORTCODE) \
    241    fGEN_TCG_loadbXw4(GET_EA_pci, true)
    242#define fGEN_TCG_L2_loadbzw4_pcr(SHORTCODE) \
    243    fGEN_TCG_loadbXw4(GET_EA_pcr(2), false)
    244#define fGEN_TCG_L2_loadbsw4_pcr(SHORTCODE) \
    245    fGEN_TCG_loadbXw4(GET_EA_pcr(2), true)
    246#define fGEN_TCG_L4_loadbzw4_ap(SHORTCODE) \
    247    fGEN_TCG_loadbXw4(GET_EA_ap, false)
    248#define fGEN_TCG_L2_loadbzw4_pr(SHORTCODE) \
    249    fGEN_TCG_loadbXw4(GET_EA_pr, false)
    250#define fGEN_TCG_L2_loadbzw4_pbr(SHORTCODE) \
    251    fGEN_TCG_loadbXw4(GET_EA_pbr, false)
    252#define fGEN_TCG_L2_loadbzw4_pi(SHORTCODE) \
    253    fGEN_TCG_loadbXw4(GET_EA_pi, false)
    254#define fGEN_TCG_L4_loadbsw4_ap(SHORTCODE) \
    255    fGEN_TCG_loadbXw4(GET_EA_ap, true)
    256#define fGEN_TCG_L2_loadbsw4_pr(SHORTCODE) \
    257    fGEN_TCG_loadbXw4(GET_EA_pr, true)
    258#define fGEN_TCG_L2_loadbsw4_pbr(SHORTCODE) \
    259    fGEN_TCG_loadbXw4(GET_EA_pbr, true)
    260#define fGEN_TCG_L2_loadbsw4_pi(SHORTCODE) \
    261    fGEN_TCG_loadbXw4(GET_EA_pi, true)
    262
    263/*
    264 * These instructions load a half word, shift the destination right by 16 bits
    265 * and place the loaded value in the high half word of the destination pair.
    266 * The GET_EA macro determines the addressing mode.
    267 */
    268#define fGEN_TCG_loadalignh(GET_EA) \
    269    do { \
    270        TCGv tmp = tcg_temp_new(); \
    271        TCGv_i64 tmp_i64 = tcg_temp_new_i64(); \
    272        GET_EA;  \
    273        fLOAD(1, 2, u, EA, tmp);  \
    274        tcg_gen_extu_i32_i64(tmp_i64, tmp); \
    275        tcg_gen_shri_i64(RyyV, RyyV, 16); \
    276        tcg_gen_deposit_i64(RyyV, RyyV, tmp_i64, 48, 16); \
    277        tcg_temp_free(tmp); \
    278        tcg_temp_free_i64(tmp_i64); \
    279    } while (0)
    280
    281#define fGEN_TCG_L4_loadalignh_ur(SHORTCODE) \
    282    fGEN_TCG_loadalignh(fEA_IRs(UiV, RtV, uiV))
    283#define fGEN_TCG_L2_loadalignh_io(SHORTCODE) \
    284    fGEN_TCG_loadalignh(fEA_RI(RsV, siV))
    285#define fGEN_TCG_L2_loadalignh_pci(SHORTCODE) \
    286    fGEN_TCG_loadalignh(GET_EA_pci)
    287#define fGEN_TCG_L2_loadalignh_pcr(SHORTCODE) \
    288    fGEN_TCG_loadalignh(GET_EA_pcr(1))
    289#define fGEN_TCG_L4_loadalignh_ap(SHORTCODE) \
    290    fGEN_TCG_loadalignh(GET_EA_ap)
    291#define fGEN_TCG_L2_loadalignh_pr(SHORTCODE) \
    292    fGEN_TCG_loadalignh(GET_EA_pr)
    293#define fGEN_TCG_L2_loadalignh_pbr(SHORTCODE) \
    294    fGEN_TCG_loadalignh(GET_EA_pbr)
    295#define fGEN_TCG_L2_loadalignh_pi(SHORTCODE) \
    296    fGEN_TCG_loadalignh(GET_EA_pi)
    297
    298/* Same as above, but loads a byte instead of half word */
    299#define fGEN_TCG_loadalignb(GET_EA) \
    300    do { \
    301        TCGv tmp = tcg_temp_new(); \
    302        TCGv_i64 tmp_i64 = tcg_temp_new_i64(); \
    303        GET_EA;  \
    304        fLOAD(1, 1, u, EA, tmp);  \
    305        tcg_gen_extu_i32_i64(tmp_i64, tmp); \
    306        tcg_gen_shri_i64(RyyV, RyyV, 8); \
    307        tcg_gen_deposit_i64(RyyV, RyyV, tmp_i64, 56, 8); \
    308        tcg_temp_free(tmp); \
    309        tcg_temp_free_i64(tmp_i64); \
    310    } while (0)
    311
    312#define fGEN_TCG_L2_loadalignb_io(SHORTCODE) \
    313    fGEN_TCG_loadalignb(fEA_RI(RsV, siV))
    314#define fGEN_TCG_L4_loadalignb_ur(SHORTCODE) \
    315    fGEN_TCG_loadalignb(fEA_IRs(UiV, RtV, uiV))
    316#define fGEN_TCG_L2_loadalignb_pci(SHORTCODE) \
    317    fGEN_TCG_loadalignb(GET_EA_pci)
    318#define fGEN_TCG_L2_loadalignb_pcr(SHORTCODE) \
    319    fGEN_TCG_loadalignb(GET_EA_pcr(0))
    320#define fGEN_TCG_L4_loadalignb_ap(SHORTCODE) \
    321    fGEN_TCG_loadalignb(GET_EA_ap)
    322#define fGEN_TCG_L2_loadalignb_pr(SHORTCODE) \
    323    fGEN_TCG_loadalignb(GET_EA_pr)
    324#define fGEN_TCG_L2_loadalignb_pbr(SHORTCODE) \
    325    fGEN_TCG_loadalignb(GET_EA_pbr)
    326#define fGEN_TCG_L2_loadalignb_pi(SHORTCODE) \
    327    fGEN_TCG_loadalignb(GET_EA_pi)
    328
    329/*
    330 * Predicated loads
    331 * Here is a primer to understand the tag names
    332 *
    333 * Predicate used
    334 *      t        true "old" value                  if (p0) r0 = memb(r2+#0)
    335 *      f        false "old" value                 if (!p0) r0 = memb(r2+#0)
    336 *      tnew     true "new" value                  if (p0.new) r0 = memb(r2+#0)
    337 *      fnew     false "new" value                 if (!p0.new) r0 = memb(r2+#0)
    338 */
    339#define fGEN_TCG_PRED_LOAD(GET_EA, PRED, SIZE, SIGN) \
    340    do { \
    341        TCGv LSB = tcg_temp_local_new(); \
    342        TCGLabel *label = gen_new_label(); \
    343        GET_EA; \
    344        PRED;  \
    345        PRED_LOAD_CANCEL(LSB, EA); \
    346        tcg_gen_movi_tl(RdV, 0); \
    347        tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
    348            fLOAD(1, SIZE, SIGN, EA, RdV); \
    349        gen_set_label(label); \
    350        tcg_temp_free(LSB); \
    351    } while (0)
    352
    353#define fGEN_TCG_L2_ploadrubt_pi(SHORTCODE) \
    354    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 1, u)
    355#define fGEN_TCG_L2_ploadrubf_pi(SHORTCODE) \
    356    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 1, u)
    357#define fGEN_TCG_L2_ploadrubtnew_pi(SHORTCODE) \
    358    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 1, u)
    359#define fGEN_TCG_L2_ploadrubfnew_pi(SHORTCODE) \
    360    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 1, u)
    361#define fGEN_TCG_L2_ploadrbt_pi(SHORTCODE) \
    362    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 1, s)
    363#define fGEN_TCG_L2_ploadrbf_pi(SHORTCODE) \
    364    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 1, s)
    365#define fGEN_TCG_L2_ploadrbtnew_pi(SHORTCODE) \
    366    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 1, s)
    367#define fGEN_TCG_L2_ploadrbfnew_pi(SHORTCODE) \
    368    fGEN_TCG_PRED_LOAD({ fEA_REG(RxV); fPM_I(RxV, siV); }, \
    369                       fLSBNEWNOT(PtN), 1, s)
    370
    371#define fGEN_TCG_L2_ploadruht_pi(SHORTCODE) \
    372    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 2, u)
    373#define fGEN_TCG_L2_ploadruhf_pi(SHORTCODE) \
    374    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 2, u)
    375#define fGEN_TCG_L2_ploadruhtnew_pi(SHORTCODE) \
    376    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 2, u)
    377#define fGEN_TCG_L2_ploadruhfnew_pi(SHORTCODE) \
    378    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 2, u)
    379#define fGEN_TCG_L2_ploadrht_pi(SHORTCODE) \
    380    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 2, s)
    381#define fGEN_TCG_L2_ploadrhf_pi(SHORTCODE) \
    382    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 2, s)
    383#define fGEN_TCG_L2_ploadrhtnew_pi(SHORTCODE) \
    384    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 2, s)
    385#define fGEN_TCG_L2_ploadrhfnew_pi(SHORTCODE) \
    386    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 2, s)
    387
    388#define fGEN_TCG_L2_ploadrit_pi(SHORTCODE) \
    389    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 4, u)
    390#define fGEN_TCG_L2_ploadrif_pi(SHORTCODE) \
    391    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 4, u)
    392#define fGEN_TCG_L2_ploadritnew_pi(SHORTCODE) \
    393    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 4, u)
    394#define fGEN_TCG_L2_ploadrifnew_pi(SHORTCODE) \
    395    fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 4, u)
    396
    397/* Predicated loads into a register pair */
    398#define fGEN_TCG_PRED_LOAD_PAIR(GET_EA, PRED) \
    399    do { \
    400        TCGv LSB = tcg_temp_local_new(); \
    401        TCGLabel *label = gen_new_label(); \
    402        GET_EA; \
    403        PRED;  \
    404        PRED_LOAD_CANCEL(LSB, EA); \
    405        tcg_gen_movi_i64(RddV, 0); \
    406        tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
    407            fLOAD(1, 8, u, EA, RddV); \
    408        gen_set_label(label); \
    409        tcg_temp_free(LSB); \
    410    } while (0)
    411
    412#define fGEN_TCG_L2_ploadrdt_pi(SHORTCODE) \
    413    fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBOLD(PtV))
    414#define fGEN_TCG_L2_ploadrdf_pi(SHORTCODE) \
    415    fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBOLDNOT(PtV))
    416#define fGEN_TCG_L2_ploadrdtnew_pi(SHORTCODE) \
    417    fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBNEW(PtN))
    418#define fGEN_TCG_L2_ploadrdfnew_pi(SHORTCODE) \
    419    fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBNEWNOT(PtN))
    420
    421/* load-locked and store-locked */
    422#define fGEN_TCG_L2_loadw_locked(SHORTCODE) \
    423    SHORTCODE
    424#define fGEN_TCG_L4_loadd_locked(SHORTCODE) \
    425    SHORTCODE
    426#define fGEN_TCG_S2_storew_locked(SHORTCODE) \
    427    SHORTCODE
    428#define fGEN_TCG_S4_stored_locked(SHORTCODE) \
    429    SHORTCODE
    430
    431#define fGEN_TCG_STORE(SHORTCODE) \
    432    do { \
    433        TCGv HALF = tcg_temp_new(); \
    434        TCGv BYTE = tcg_temp_new(); \
    435        SHORTCODE; \
    436        tcg_temp_free(HALF); \
    437        tcg_temp_free(BYTE); \
    438    } while (0)
    439
    440#define fGEN_TCG_STORE_pcr(SHIFT, STORE) \
    441    do { \
    442        TCGv ireg = tcg_temp_new(); \
    443        TCGv HALF = tcg_temp_new(); \
    444        TCGv BYTE = tcg_temp_new(); \
    445        tcg_gen_mov_tl(EA, RxV); \
    446        gen_read_ireg(ireg, MuV, SHIFT); \
    447        gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
    448        STORE; \
    449        tcg_temp_free(ireg); \
    450        tcg_temp_free(HALF); \
    451        tcg_temp_free(BYTE); \
    452    } while (0)
    453
    454#define fGEN_TCG_S2_storerb_pbr(SHORTCODE) \
    455    fGEN_TCG_STORE(SHORTCODE)
    456#define fGEN_TCG_S2_storerb_pci(SHORTCODE) \
    457    fGEN_TCG_STORE(SHORTCODE)
    458#define fGEN_TCG_S2_storerb_pcr(SHORTCODE) \
    459    fGEN_TCG_STORE_pcr(0, fSTORE(1, 1, EA, fGETBYTE(0, RtV)))
    460
    461#define fGEN_TCG_S2_storerh_pbr(SHORTCODE) \
    462    fGEN_TCG_STORE(SHORTCODE)
    463#define fGEN_TCG_S2_storerh_pci(SHORTCODE) \
    464    fGEN_TCG_STORE(SHORTCODE)
    465#define fGEN_TCG_S2_storerh_pcr(SHORTCODE) \
    466    fGEN_TCG_STORE_pcr(1, fSTORE(1, 2, EA, fGETHALF(0, RtV)))
    467
    468#define fGEN_TCG_S2_storerf_pbr(SHORTCODE) \
    469    fGEN_TCG_STORE(SHORTCODE)
    470#define fGEN_TCG_S2_storerf_pci(SHORTCODE) \
    471    fGEN_TCG_STORE(SHORTCODE)
    472#define fGEN_TCG_S2_storerf_pcr(SHORTCODE) \
    473    fGEN_TCG_STORE_pcr(1, fSTORE(1, 2, EA, fGETHALF(1, RtV)))
    474
    475#define fGEN_TCG_S2_storeri_pbr(SHORTCODE) \
    476    fGEN_TCG_STORE(SHORTCODE)
    477#define fGEN_TCG_S2_storeri_pci(SHORTCODE) \
    478    fGEN_TCG_STORE(SHORTCODE)
    479#define fGEN_TCG_S2_storeri_pcr(SHORTCODE) \
    480    fGEN_TCG_STORE_pcr(2, fSTORE(1, 4, EA, RtV))
    481
    482#define fGEN_TCG_S2_storerd_pbr(SHORTCODE) \
    483    fGEN_TCG_STORE(SHORTCODE)
    484#define fGEN_TCG_S2_storerd_pci(SHORTCODE) \
    485    fGEN_TCG_STORE(SHORTCODE)
    486#define fGEN_TCG_S2_storerd_pcr(SHORTCODE) \
    487    fGEN_TCG_STORE_pcr(3, fSTORE(1, 8, EA, RttV))
    488
    489#define fGEN_TCG_S2_storerbnew_pbr(SHORTCODE) \
    490    fGEN_TCG_STORE(SHORTCODE)
    491#define fGEN_TCG_S2_storerbnew_pci(SHORTCODE) \
    492    fGEN_TCG_STORE(SHORTCODE)
    493#define fGEN_TCG_S2_storerbnew_pcr(SHORTCODE) \
    494    fGEN_TCG_STORE_pcr(0, fSTORE(1, 1, EA, fGETBYTE(0, NtN)))
    495
    496#define fGEN_TCG_S2_storerhnew_pbr(SHORTCODE) \
    497    fGEN_TCG_STORE(SHORTCODE)
    498#define fGEN_TCG_S2_storerhnew_pci(SHORTCODE) \
    499    fGEN_TCG_STORE(SHORTCODE)
    500#define fGEN_TCG_S2_storerhnew_pcr(SHORTCODE) \
    501    fGEN_TCG_STORE_pcr(1, fSTORE(1, 2, EA, fGETHALF(0, NtN)))
    502
    503#define fGEN_TCG_S2_storerinew_pbr(SHORTCODE) \
    504    fGEN_TCG_STORE(SHORTCODE)
    505#define fGEN_TCG_S2_storerinew_pci(SHORTCODE) \
    506    fGEN_TCG_STORE(SHORTCODE)
    507#define fGEN_TCG_S2_storerinew_pcr(SHORTCODE) \
    508    fGEN_TCG_STORE_pcr(2, fSTORE(1, 4, EA, NtN))
    509
    510/*
    511 * Mathematical operations with more than one definition require
    512 * special handling
    513 */
    514#define fGEN_TCG_A5_ACS(SHORTCODE) \
    515    do { \
    516        gen_helper_vacsh_pred(PeV, cpu_env, RxxV, RssV, RttV); \
    517        gen_helper_vacsh_val(RxxV, cpu_env, RxxV, RssV, RttV); \
    518    } while (0)
    519
    520/*
    521 * Approximate reciprocal
    522 * r3,p1 = sfrecipa(r0, r1)
    523 *
    524 * The helper packs the 2 32-bit results into a 64-bit value,
    525 * so unpack them into the proper results.
    526 */
    527#define fGEN_TCG_F2_sfrecipa(SHORTCODE) \
    528    do { \
    529        TCGv_i64 tmp = tcg_temp_new_i64(); \
    530        gen_helper_sfrecipa(tmp, cpu_env, RsV, RtV);  \
    531        tcg_gen_extrh_i64_i32(RdV, tmp); \
    532        tcg_gen_extrl_i64_i32(PeV, tmp); \
    533        tcg_temp_free_i64(tmp); \
    534    } while (0)
    535
    536/*
    537 * Approximation of the reciprocal square root
    538 * r1,p0 = sfinvsqrta(r0)
    539 *
    540 * The helper packs the 2 32-bit results into a 64-bit value,
    541 * so unpack them into the proper results.
    542 */
    543#define fGEN_TCG_F2_sfinvsqrta(SHORTCODE) \
    544    do { \
    545        TCGv_i64 tmp = tcg_temp_new_i64(); \
    546        gen_helper_sfinvsqrta(tmp, cpu_env, RsV); \
    547        tcg_gen_extrh_i64_i32(RdV, tmp); \
    548        tcg_gen_extrl_i64_i32(PeV, tmp); \
    549        tcg_temp_free_i64(tmp); \
    550    } while (0)
    551
    552/*
    553 * Add or subtract with carry.
    554 * Predicate register is used as an extra input and output.
    555 * r5:4 = add(r1:0, r3:2, p1):carry
    556 */
    557#define fGEN_TCG_A4_addp_c(SHORTCODE) \
    558    do { \
    559        TCGv_i64 carry = tcg_temp_new_i64(); \
    560        TCGv_i64 zero = tcg_const_i64(0); \
    561        tcg_gen_extu_i32_i64(carry, PxV); \
    562        tcg_gen_andi_i64(carry, carry, 1); \
    563        tcg_gen_add2_i64(RddV, carry, RssV, zero, carry, zero); \
    564        tcg_gen_add2_i64(RddV, carry, RddV, carry, RttV, zero); \
    565        tcg_gen_extrl_i64_i32(PxV, carry); \
    566        gen_8bitsof(PxV, PxV); \
    567        tcg_temp_free_i64(carry); \
    568        tcg_temp_free_i64(zero); \
    569    } while (0)
    570
    571/* r5:4 = sub(r1:0, r3:2, p1):carry */
    572#define fGEN_TCG_A4_subp_c(SHORTCODE) \
    573    do { \
    574        TCGv_i64 carry = tcg_temp_new_i64(); \
    575        TCGv_i64 zero = tcg_const_i64(0); \
    576        TCGv_i64 not_RttV = tcg_temp_new_i64(); \
    577        tcg_gen_extu_i32_i64(carry, PxV); \
    578        tcg_gen_andi_i64(carry, carry, 1); \
    579        tcg_gen_not_i64(not_RttV, RttV); \
    580        tcg_gen_add2_i64(RddV, carry, RssV, zero, carry, zero); \
    581        tcg_gen_add2_i64(RddV, carry, RddV, carry, not_RttV, zero); \
    582        tcg_gen_extrl_i64_i32(PxV, carry); \
    583        gen_8bitsof(PxV, PxV); \
    584        tcg_temp_free_i64(carry); \
    585        tcg_temp_free_i64(zero); \
    586        tcg_temp_free_i64(not_RttV); \
    587    } while (0)
    588
    589/*
    590 * Compare each of the 8 unsigned bytes
    591 * The minimum is placed in each byte of the destination.
    592 * Each bit of the predicate is set true if the bit from the first operand
    593 * is greater than the bit from the second operand.
    594 * r5:4,p1 = vminub(r1:0, r3:2)
    595 */
    596#define fGEN_TCG_A6_vminub_RdP(SHORTCODE) \
    597    do { \
    598        TCGv left = tcg_temp_new(); \
    599        TCGv right = tcg_temp_new(); \
    600        TCGv tmp = tcg_temp_new(); \
    601        tcg_gen_movi_tl(PeV, 0); \
    602        tcg_gen_movi_i64(RddV, 0); \
    603        for (int i = 0; i < 8; i++) { \
    604            gen_get_byte_i64(left, i, RttV, false); \
    605            gen_get_byte_i64(right, i, RssV, false); \
    606            tcg_gen_setcond_tl(TCG_COND_GT, tmp, left, right); \
    607            tcg_gen_deposit_tl(PeV, PeV, tmp, i, 1); \
    608            tcg_gen_umin_tl(tmp, left, right); \
    609            gen_set_byte_i64(i, RddV, tmp); \
    610        } \
    611        tcg_temp_free(left); \
    612        tcg_temp_free(right); \
    613        tcg_temp_free(tmp); \
    614    } while (0)
    615
    616/* Floating point */
    617#define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
    618    gen_helper_conv_sf2df(RddV, cpu_env, RsV)
    619#define fGEN_TCG_F2_conv_df2sf(SHORTCODE) \
    620    gen_helper_conv_df2sf(RdV, cpu_env, RssV)
    621#define fGEN_TCG_F2_conv_uw2sf(SHORTCODE) \
    622    gen_helper_conv_uw2sf(RdV, cpu_env, RsV)
    623#define fGEN_TCG_F2_conv_uw2df(SHORTCODE) \
    624    gen_helper_conv_uw2df(RddV, cpu_env, RsV)
    625#define fGEN_TCG_F2_conv_w2sf(SHORTCODE) \
    626    gen_helper_conv_w2sf(RdV, cpu_env, RsV)
    627#define fGEN_TCG_F2_conv_w2df(SHORTCODE) \
    628    gen_helper_conv_w2df(RddV, cpu_env, RsV)
    629#define fGEN_TCG_F2_conv_ud2sf(SHORTCODE) \
    630    gen_helper_conv_ud2sf(RdV, cpu_env, RssV)
    631#define fGEN_TCG_F2_conv_ud2df(SHORTCODE) \
    632    gen_helper_conv_ud2df(RddV, cpu_env, RssV)
    633#define fGEN_TCG_F2_conv_d2sf(SHORTCODE) \
    634    gen_helper_conv_d2sf(RdV, cpu_env, RssV)
    635#define fGEN_TCG_F2_conv_d2df(SHORTCODE) \
    636    gen_helper_conv_d2df(RddV, cpu_env, RssV)
    637#define fGEN_TCG_F2_conv_sf2uw(SHORTCODE) \
    638    gen_helper_conv_sf2uw(RdV, cpu_env, RsV)
    639#define fGEN_TCG_F2_conv_sf2w(SHORTCODE) \
    640    gen_helper_conv_sf2w(RdV, cpu_env, RsV)
    641#define fGEN_TCG_F2_conv_sf2ud(SHORTCODE) \
    642    gen_helper_conv_sf2ud(RddV, cpu_env, RsV)
    643#define fGEN_TCG_F2_conv_sf2d(SHORTCODE) \
    644    gen_helper_conv_sf2d(RddV, cpu_env, RsV)
    645#define fGEN_TCG_F2_conv_df2uw(SHORTCODE) \
    646    gen_helper_conv_df2uw(RdV, cpu_env, RssV)
    647#define fGEN_TCG_F2_conv_df2w(SHORTCODE) \
    648    gen_helper_conv_df2w(RdV, cpu_env, RssV)
    649#define fGEN_TCG_F2_conv_df2ud(SHORTCODE) \
    650    gen_helper_conv_df2ud(RddV, cpu_env, RssV)
    651#define fGEN_TCG_F2_conv_df2d(SHORTCODE) \
    652    gen_helper_conv_df2d(RddV, cpu_env, RssV)
    653#define fGEN_TCG_F2_conv_sf2uw_chop(SHORTCODE) \
    654    gen_helper_conv_sf2uw_chop(RdV, cpu_env, RsV)
    655#define fGEN_TCG_F2_conv_sf2w_chop(SHORTCODE) \
    656    gen_helper_conv_sf2w_chop(RdV, cpu_env, RsV)
    657#define fGEN_TCG_F2_conv_sf2ud_chop(SHORTCODE) \
    658    gen_helper_conv_sf2ud_chop(RddV, cpu_env, RsV)
    659#define fGEN_TCG_F2_conv_sf2d_chop(SHORTCODE) \
    660    gen_helper_conv_sf2d_chop(RddV, cpu_env, RsV)
    661#define fGEN_TCG_F2_conv_df2uw_chop(SHORTCODE) \
    662    gen_helper_conv_df2uw_chop(RdV, cpu_env, RssV)
    663#define fGEN_TCG_F2_conv_df2w_chop(SHORTCODE) \
    664    gen_helper_conv_df2w_chop(RdV, cpu_env, RssV)
    665#define fGEN_TCG_F2_conv_df2ud_chop(SHORTCODE) \
    666    gen_helper_conv_df2ud_chop(RddV, cpu_env, RssV)
    667#define fGEN_TCG_F2_conv_df2d_chop(SHORTCODE) \
    668    gen_helper_conv_df2d_chop(RddV, cpu_env, RssV)
    669#define fGEN_TCG_F2_sfadd(SHORTCODE) \
    670    gen_helper_sfadd(RdV, cpu_env, RsV, RtV)
    671#define fGEN_TCG_F2_sfsub(SHORTCODE) \
    672    gen_helper_sfsub(RdV, cpu_env, RsV, RtV)
    673#define fGEN_TCG_F2_sfcmpeq(SHORTCODE) \
    674    gen_helper_sfcmpeq(PdV, cpu_env, RsV, RtV)
    675#define fGEN_TCG_F2_sfcmpgt(SHORTCODE) \
    676    gen_helper_sfcmpgt(PdV, cpu_env, RsV, RtV)
    677#define fGEN_TCG_F2_sfcmpge(SHORTCODE) \
    678    gen_helper_sfcmpge(PdV, cpu_env, RsV, RtV)
    679#define fGEN_TCG_F2_sfcmpuo(SHORTCODE) \
    680    gen_helper_sfcmpuo(PdV, cpu_env, RsV, RtV)
    681#define fGEN_TCG_F2_sfmax(SHORTCODE) \
    682    gen_helper_sfmax(RdV, cpu_env, RsV, RtV)
    683#define fGEN_TCG_F2_sfmin(SHORTCODE) \
    684    gen_helper_sfmin(RdV, cpu_env, RsV, RtV)
    685#define fGEN_TCG_F2_sfclass(SHORTCODE) \
    686    do { \
    687        TCGv imm = tcg_constant_tl(uiV); \
    688        gen_helper_sfclass(PdV, cpu_env, RsV, imm); \
    689    } while (0)
    690#define fGEN_TCG_F2_sffixupn(SHORTCODE) \
    691    gen_helper_sffixupn(RdV, cpu_env, RsV, RtV)
    692#define fGEN_TCG_F2_sffixupd(SHORTCODE) \
    693    gen_helper_sffixupd(RdV, cpu_env, RsV, RtV)
    694#define fGEN_TCG_F2_sffixupr(SHORTCODE) \
    695    gen_helper_sffixupr(RdV, cpu_env, RsV)
    696#define fGEN_TCG_F2_dfadd(SHORTCODE) \
    697    gen_helper_dfadd(RddV, cpu_env, RssV, RttV)
    698#define fGEN_TCG_F2_dfsub(SHORTCODE) \
    699    gen_helper_dfsub(RddV, cpu_env, RssV, RttV)
    700#define fGEN_TCG_F2_dfmax(SHORTCODE) \
    701    gen_helper_dfmax(RddV, cpu_env, RssV, RttV)
    702#define fGEN_TCG_F2_dfmin(SHORTCODE) \
    703    gen_helper_dfmin(RddV, cpu_env, RssV, RttV)
    704#define fGEN_TCG_F2_dfcmpeq(SHORTCODE) \
    705    gen_helper_dfcmpeq(PdV, cpu_env, RssV, RttV)
    706#define fGEN_TCG_F2_dfcmpgt(SHORTCODE) \
    707    gen_helper_dfcmpgt(PdV, cpu_env, RssV, RttV)
    708#define fGEN_TCG_F2_dfcmpge(SHORTCODE) \
    709    gen_helper_dfcmpge(PdV, cpu_env, RssV, RttV)
    710#define fGEN_TCG_F2_dfcmpuo(SHORTCODE) \
    711    gen_helper_dfcmpuo(PdV, cpu_env, RssV, RttV)
    712#define fGEN_TCG_F2_dfclass(SHORTCODE) \
    713    do { \
    714        TCGv imm = tcg_constant_tl(uiV); \
    715        gen_helper_dfclass(PdV, cpu_env, RssV, imm); \
    716    } while (0)
    717#define fGEN_TCG_F2_sfmpy(SHORTCODE) \
    718    gen_helper_sfmpy(RdV, cpu_env, RsV, RtV)
    719#define fGEN_TCG_F2_sffma(SHORTCODE) \
    720    gen_helper_sffma(RxV, cpu_env, RxV, RsV, RtV)
    721#define fGEN_TCG_F2_sffma_sc(SHORTCODE) \
    722    gen_helper_sffma_sc(RxV, cpu_env, RxV, RsV, RtV, PuV)
    723#define fGEN_TCG_F2_sffms(SHORTCODE) \
    724    gen_helper_sffms(RxV, cpu_env, RxV, RsV, RtV)
    725#define fGEN_TCG_F2_sffma_lib(SHORTCODE) \
    726    gen_helper_sffma_lib(RxV, cpu_env, RxV, RsV, RtV)
    727#define fGEN_TCG_F2_sffms_lib(SHORTCODE) \
    728    gen_helper_sffms_lib(RxV, cpu_env, RxV, RsV, RtV)
    729
    730#define fGEN_TCG_F2_dfmpyfix(SHORTCODE) \
    731    gen_helper_dfmpyfix(RddV, cpu_env, RssV, RttV)
    732#define fGEN_TCG_F2_dfmpyhh(SHORTCODE) \
    733    gen_helper_dfmpyhh(RxxV, cpu_env, RxxV, RssV, RttV)
    734
    735/* Nothing to do for these in qemu, need to suppress compiler warnings */
    736#define fGEN_TCG_Y4_l2fetch(SHORTCODE) \
    737    do { \
    738        RsV = RsV; \
    739        RtV = RtV; \
    740    } while (0)
    741#define fGEN_TCG_Y5_l2fetch(SHORTCODE) \
    742    do { \
    743        RsV = RsV; \
    744    } while (0)
    745
    746#endif