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

op_helper.c (12944B)


      1/*
      2 *  SH4 emulation
      3 *
      4 *  Copyright (c) 2005 Samuel Tardieu
      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#include "qemu/osdep.h"
     20#include "cpu.h"
     21#include "exec/helper-proto.h"
     22#include "exec/exec-all.h"
     23#include "exec/cpu_ldst.h"
     24#include "fpu/softfloat.h"
     25
     26#ifndef CONFIG_USER_ONLY
     27
     28void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
     29                                    MMUAccessType access_type,
     30                                    int mmu_idx, uintptr_t retaddr)
     31{
     32    switch (access_type) {
     33    case MMU_INST_FETCH:
     34    case MMU_DATA_LOAD:
     35        cs->exception_index = 0x0e0;
     36        break;
     37    case MMU_DATA_STORE:
     38        cs->exception_index = 0x100;
     39        break;
     40    }
     41    cpu_loop_exit_restore(cs, retaddr);
     42}
     43
     44#endif
     45
     46void helper_ldtlb(CPUSH4State *env)
     47{
     48#ifdef CONFIG_USER_ONLY
     49    cpu_abort(env_cpu(env), "Unhandled ldtlb");
     50#else
     51    cpu_load_tlb(env);
     52#endif
     53}
     54
     55static inline void QEMU_NORETURN raise_exception(CPUSH4State *env, int index,
     56                                                 uintptr_t retaddr)
     57{
     58    CPUState *cs = env_cpu(env);
     59
     60    cs->exception_index = index;
     61    cpu_loop_exit_restore(cs, retaddr);
     62}
     63
     64void helper_raise_illegal_instruction(CPUSH4State *env)
     65{
     66    raise_exception(env, 0x180, 0);
     67}
     68
     69void helper_raise_slot_illegal_instruction(CPUSH4State *env)
     70{
     71    raise_exception(env, 0x1a0, 0);
     72}
     73
     74void helper_raise_fpu_disable(CPUSH4State *env)
     75{
     76    raise_exception(env, 0x800, 0);
     77}
     78
     79void helper_raise_slot_fpu_disable(CPUSH4State *env)
     80{
     81    raise_exception(env, 0x820, 0);
     82}
     83
     84void helper_debug(CPUSH4State *env)
     85{
     86    raise_exception(env, EXCP_DEBUG, 0);
     87}
     88
     89void helper_sleep(CPUSH4State *env)
     90{
     91    CPUState *cs = env_cpu(env);
     92
     93    cs->halted = 1;
     94    env->in_sleep = 1;
     95    raise_exception(env, EXCP_HLT, 0);
     96}
     97
     98void helper_trapa(CPUSH4State *env, uint32_t tra)
     99{
    100    env->tra = tra << 2;
    101    raise_exception(env, 0x160, 0);
    102}
    103
    104void helper_exclusive(CPUSH4State *env)
    105{
    106    /* We do not want cpu_restore_state to run.  */
    107    cpu_loop_exit_atomic(env_cpu(env), 0);
    108}
    109
    110void helper_movcal(CPUSH4State *env, uint32_t address, uint32_t value)
    111{
    112    if (cpu_sh4_is_cached (env, address))
    113    {
    114        memory_content *r = g_new(memory_content, 1);
    115
    116	r->address = address;
    117	r->value = value;
    118	r->next = NULL;
    119
    120	*(env->movcal_backup_tail) = r;
    121	env->movcal_backup_tail = &(r->next);
    122    }
    123}
    124
    125void helper_discard_movcal_backup(CPUSH4State *env)
    126{
    127    memory_content *current = env->movcal_backup;
    128
    129    while(current)
    130    {
    131	memory_content *next = current->next;
    132        g_free(current);
    133	env->movcal_backup = current = next;
    134	if (current == NULL)
    135	    env->movcal_backup_tail = &(env->movcal_backup);
    136    } 
    137}
    138
    139void helper_ocbi(CPUSH4State *env, uint32_t address)
    140{
    141    memory_content **current = &(env->movcal_backup);
    142    while (*current)
    143    {
    144	uint32_t a = (*current)->address;
    145	if ((a & ~0x1F) == (address & ~0x1F))
    146	{
    147	    memory_content *next = (*current)->next;
    148            cpu_stl_data(env, a, (*current)->value);
    149	    
    150	    if (next == NULL)
    151	    {
    152		env->movcal_backup_tail = current;
    153	    }
    154
    155            g_free(*current);
    156	    *current = next;
    157	    break;
    158	}
    159    }
    160}
    161
    162void helper_macl(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
    163{
    164    int64_t res;
    165
    166    res = ((uint64_t) env->mach << 32) | env->macl;
    167    res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
    168    env->mach = (res >> 32) & 0xffffffff;
    169    env->macl = res & 0xffffffff;
    170    if (env->sr & (1u << SR_S)) {
    171	if (res < 0)
    172	    env->mach |= 0xffff0000;
    173	else
    174	    env->mach &= 0x00007fff;
    175    }
    176}
    177
    178void helper_macw(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
    179{
    180    int64_t res;
    181
    182    res = ((uint64_t) env->mach << 32) | env->macl;
    183    res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
    184    env->mach = (res >> 32) & 0xffffffff;
    185    env->macl = res & 0xffffffff;
    186    if (env->sr & (1u << SR_S)) {
    187	if (res < -0x80000000) {
    188	    env->mach = 1;
    189	    env->macl = 0x80000000;
    190	} else if (res > 0x000000007fffffff) {
    191	    env->mach = 1;
    192	    env->macl = 0x7fffffff;
    193	}
    194    }
    195}
    196
    197void helper_ld_fpscr(CPUSH4State *env, uint32_t val)
    198{
    199    env->fpscr = val & FPSCR_MASK;
    200    if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) {
    201	set_float_rounding_mode(float_round_to_zero, &env->fp_status);
    202    } else {
    203	set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
    204    }
    205    set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
    206}
    207
    208static void update_fpscr(CPUSH4State *env, uintptr_t retaddr)
    209{
    210    int xcpt, cause, enable;
    211
    212    xcpt = get_float_exception_flags(&env->fp_status);
    213
    214    /* Clear the cause entries */
    215    env->fpscr &= ~FPSCR_CAUSE_MASK;
    216
    217    if (unlikely(xcpt)) {
    218        if (xcpt & float_flag_invalid) {
    219            env->fpscr |= FPSCR_CAUSE_V;
    220        }
    221        if (xcpt & float_flag_divbyzero) {
    222            env->fpscr |= FPSCR_CAUSE_Z;
    223        }
    224        if (xcpt & float_flag_overflow) {
    225            env->fpscr |= FPSCR_CAUSE_O;
    226        }
    227        if (xcpt & float_flag_underflow) {
    228            env->fpscr |= FPSCR_CAUSE_U;
    229        }
    230        if (xcpt & float_flag_inexact) {
    231            env->fpscr |= FPSCR_CAUSE_I;
    232        }
    233
    234        /* Accumulate in flag entries */
    235        env->fpscr |= (env->fpscr & FPSCR_CAUSE_MASK)
    236                      >> (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT);
    237
    238        /* Generate an exception if enabled */
    239        cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
    240        enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT;
    241        if (cause & enable) {
    242            raise_exception(env, 0x120, retaddr);
    243        }
    244    }
    245}
    246
    247float32 helper_fadd_FT(CPUSH4State *env, float32 t0, float32 t1)
    248{
    249    set_float_exception_flags(0, &env->fp_status);
    250    t0 = float32_add(t0, t1, &env->fp_status);
    251    update_fpscr(env, GETPC());
    252    return t0;
    253}
    254
    255float64 helper_fadd_DT(CPUSH4State *env, float64 t0, float64 t1)
    256{
    257    set_float_exception_flags(0, &env->fp_status);
    258    t0 = float64_add(t0, t1, &env->fp_status);
    259    update_fpscr(env, GETPC());
    260    return t0;
    261}
    262
    263uint32_t helper_fcmp_eq_FT(CPUSH4State *env, float32 t0, float32 t1)
    264{
    265    int relation;
    266
    267    set_float_exception_flags(0, &env->fp_status);
    268    relation = float32_compare(t0, t1, &env->fp_status);
    269    update_fpscr(env, GETPC());
    270    return relation == float_relation_equal;
    271}
    272
    273uint32_t helper_fcmp_eq_DT(CPUSH4State *env, float64 t0, float64 t1)
    274{
    275    int relation;
    276
    277    set_float_exception_flags(0, &env->fp_status);
    278    relation = float64_compare(t0, t1, &env->fp_status);
    279    update_fpscr(env, GETPC());
    280    return relation == float_relation_equal;
    281}
    282
    283uint32_t helper_fcmp_gt_FT(CPUSH4State *env, float32 t0, float32 t1)
    284{
    285    int relation;
    286
    287    set_float_exception_flags(0, &env->fp_status);
    288    relation = float32_compare(t0, t1, &env->fp_status);
    289    update_fpscr(env, GETPC());
    290    return relation == float_relation_greater;
    291}
    292
    293uint32_t helper_fcmp_gt_DT(CPUSH4State *env, float64 t0, float64 t1)
    294{
    295    int relation;
    296
    297    set_float_exception_flags(0, &env->fp_status);
    298    relation = float64_compare(t0, t1, &env->fp_status);
    299    update_fpscr(env, GETPC());
    300    return relation == float_relation_greater;
    301}
    302
    303float64 helper_fcnvsd_FT_DT(CPUSH4State *env, float32 t0)
    304{
    305    float64 ret;
    306    set_float_exception_flags(0, &env->fp_status);
    307    ret = float32_to_float64(t0, &env->fp_status);
    308    update_fpscr(env, GETPC());
    309    return ret;
    310}
    311
    312float32 helper_fcnvds_DT_FT(CPUSH4State *env, float64 t0)
    313{
    314    float32 ret;
    315    set_float_exception_flags(0, &env->fp_status);
    316    ret = float64_to_float32(t0, &env->fp_status);
    317    update_fpscr(env, GETPC());
    318    return ret;
    319}
    320
    321float32 helper_fdiv_FT(CPUSH4State *env, float32 t0, float32 t1)
    322{
    323    set_float_exception_flags(0, &env->fp_status);
    324    t0 = float32_div(t0, t1, &env->fp_status);
    325    update_fpscr(env, GETPC());
    326    return t0;
    327}
    328
    329float64 helper_fdiv_DT(CPUSH4State *env, float64 t0, float64 t1)
    330{
    331    set_float_exception_flags(0, &env->fp_status);
    332    t0 = float64_div(t0, t1, &env->fp_status);
    333    update_fpscr(env, GETPC());
    334    return t0;
    335}
    336
    337float32 helper_float_FT(CPUSH4State *env, uint32_t t0)
    338{
    339    float32 ret;
    340    set_float_exception_flags(0, &env->fp_status);
    341    ret = int32_to_float32(t0, &env->fp_status);
    342    update_fpscr(env, GETPC());
    343    return ret;
    344}
    345
    346float64 helper_float_DT(CPUSH4State *env, uint32_t t0)
    347{
    348    float64 ret;
    349    set_float_exception_flags(0, &env->fp_status);
    350    ret = int32_to_float64(t0, &env->fp_status);
    351    update_fpscr(env, GETPC());
    352    return ret;
    353}
    354
    355float32 helper_fmac_FT(CPUSH4State *env, float32 t0, float32 t1, float32 t2)
    356{
    357    set_float_exception_flags(0, &env->fp_status);
    358    t0 = float32_muladd(t0, t1, t2, 0, &env->fp_status);
    359    update_fpscr(env, GETPC());
    360    return t0;
    361}
    362
    363float32 helper_fmul_FT(CPUSH4State *env, float32 t0, float32 t1)
    364{
    365    set_float_exception_flags(0, &env->fp_status);
    366    t0 = float32_mul(t0, t1, &env->fp_status);
    367    update_fpscr(env, GETPC());
    368    return t0;
    369}
    370
    371float64 helper_fmul_DT(CPUSH4State *env, float64 t0, float64 t1)
    372{
    373    set_float_exception_flags(0, &env->fp_status);
    374    t0 = float64_mul(t0, t1, &env->fp_status);
    375    update_fpscr(env, GETPC());
    376    return t0;
    377}
    378
    379float32 helper_fsqrt_FT(CPUSH4State *env, float32 t0)
    380{
    381    set_float_exception_flags(0, &env->fp_status);
    382    t0 = float32_sqrt(t0, &env->fp_status);
    383    update_fpscr(env, GETPC());
    384    return t0;
    385}
    386
    387float64 helper_fsqrt_DT(CPUSH4State *env, float64 t0)
    388{
    389    set_float_exception_flags(0, &env->fp_status);
    390    t0 = float64_sqrt(t0, &env->fp_status);
    391    update_fpscr(env, GETPC());
    392    return t0;
    393}
    394
    395float32 helper_fsrra_FT(CPUSH4State *env, float32 t0)
    396{
    397    set_float_exception_flags(0, &env->fp_status);
    398    /* "Approximate" 1/sqrt(x) via actual computation.  */
    399    t0 = float32_sqrt(t0, &env->fp_status);
    400    t0 = float32_div(float32_one, t0, &env->fp_status);
    401    /*
    402     * Since this is supposed to be an approximation, an imprecision
    403     * exception is required.  One supposes this also follows the usual
    404     * IEEE rule that other exceptions take precedence.
    405     */
    406    if (get_float_exception_flags(&env->fp_status) == 0) {
    407        set_float_exception_flags(float_flag_inexact, &env->fp_status);
    408    }
    409    update_fpscr(env, GETPC());
    410    return t0;
    411}
    412
    413float32 helper_fsub_FT(CPUSH4State *env, float32 t0, float32 t1)
    414{
    415    set_float_exception_flags(0, &env->fp_status);
    416    t0 = float32_sub(t0, t1, &env->fp_status);
    417    update_fpscr(env, GETPC());
    418    return t0;
    419}
    420
    421float64 helper_fsub_DT(CPUSH4State *env, float64 t0, float64 t1)
    422{
    423    set_float_exception_flags(0, &env->fp_status);
    424    t0 = float64_sub(t0, t1, &env->fp_status);
    425    update_fpscr(env, GETPC());
    426    return t0;
    427}
    428
    429uint32_t helper_ftrc_FT(CPUSH4State *env, float32 t0)
    430{
    431    uint32_t ret;
    432    set_float_exception_flags(0, &env->fp_status);
    433    ret = float32_to_int32_round_to_zero(t0, &env->fp_status);
    434    update_fpscr(env, GETPC());
    435    return ret;
    436}
    437
    438uint32_t helper_ftrc_DT(CPUSH4State *env, float64 t0)
    439{
    440    uint32_t ret;
    441    set_float_exception_flags(0, &env->fp_status);
    442    ret = float64_to_int32_round_to_zero(t0, &env->fp_status);
    443    update_fpscr(env, GETPC());
    444    return ret;
    445}
    446
    447void helper_fipr(CPUSH4State *env, uint32_t m, uint32_t n)
    448{
    449    int bank, i;
    450    float32 r, p;
    451
    452    bank = (env->sr & FPSCR_FR) ? 16 : 0;
    453    r = float32_zero;
    454    set_float_exception_flags(0, &env->fp_status);
    455
    456    for (i = 0 ; i < 4 ; i++) {
    457        p = float32_mul(env->fregs[bank + m + i],
    458                        env->fregs[bank + n + i],
    459                        &env->fp_status);
    460        r = float32_add(r, p, &env->fp_status);
    461    }
    462    update_fpscr(env, GETPC());
    463
    464    env->fregs[bank + n + 3] = r;
    465}
    466
    467void helper_ftrv(CPUSH4State *env, uint32_t n)
    468{
    469    int bank_matrix, bank_vector;
    470    int i, j;
    471    float32 r[4];
    472    float32 p;
    473
    474    bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16;
    475    bank_vector = (env->sr & FPSCR_FR) ? 16 : 0;
    476    set_float_exception_flags(0, &env->fp_status);
    477    for (i = 0 ; i < 4 ; i++) {
    478        r[i] = float32_zero;
    479        for (j = 0 ; j < 4 ; j++) {
    480            p = float32_mul(env->fregs[bank_matrix + 4 * j + i],
    481                            env->fregs[bank_vector + j],
    482                            &env->fp_status);
    483            r[i] = float32_add(r[i], p, &env->fp_status);
    484        }
    485    }
    486    update_fpscr(env, GETPC());
    487
    488    for (i = 0 ; i < 4 ; i++) {
    489        env->fregs[bank_vector + i] = r[i];
    490    }
    491}