qemu/target-unicore32/op_helper.c
<<
>>
Prefs
   1/*
   2 *  UniCore32 helper routines
   3 *
   4 * Copyright (C) 2010-2012 Guan Xuetao
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation, or (at your option) any
   9 * later version. See the COPYING file in the top-level directory.
  10 */
  11#include "qemu/osdep.h"
  12#include "cpu.h"
  13#include "exec/helper-proto.h"
  14#include "exec/cpu_ldst.h"
  15
  16#define SIGNBIT (uint32_t)0x80000000
  17#define SIGNBIT64 ((uint64_t)1 << 63)
  18
  19void HELPER(exception)(CPUUniCore32State *env, uint32_t excp)
  20{
  21    CPUState *cs = CPU(uc32_env_get_cpu(env));
  22
  23    cs->exception_index = excp;
  24    cpu_loop_exit(cs);
  25}
  26
  27static target_ulong asr_read(CPUUniCore32State *env)
  28{
  29    int ZF;
  30    ZF = (env->ZF == 0);
  31    return env->uncached_asr | (env->NF & 0x80000000) | (ZF << 30) |
  32        (env->CF << 29) | ((env->VF & 0x80000000) >> 3);
  33}
  34
  35target_ulong cpu_asr_read(CPUUniCore32State *env)
  36{
  37    return asr_read(env);
  38}
  39
  40target_ulong HELPER(asr_read)(CPUUniCore32State *env)
  41{
  42    return asr_read(env);
  43}
  44
  45static void asr_write(CPUUniCore32State *env, target_ulong val,
  46                      target_ulong mask)
  47{
  48    if (mask & ASR_NZCV) {
  49        env->ZF = (~val) & ASR_Z;
  50        env->NF = val;
  51        env->CF = (val >> 29) & 1;
  52        env->VF = (val << 3) & 0x80000000;
  53    }
  54
  55    if ((env->uncached_asr ^ val) & mask & ASR_M) {
  56        switch_mode(env, val & ASR_M);
  57    }
  58    mask &= ~ASR_NZCV;
  59    env->uncached_asr = (env->uncached_asr & ~mask) | (val & mask);
  60}
  61
  62void cpu_asr_write(CPUUniCore32State *env, target_ulong val, target_ulong mask)
  63{
  64    asr_write(env, val, mask);
  65}
  66
  67void HELPER(asr_write)(CPUUniCore32State *env, target_ulong val,
  68                       target_ulong mask)
  69{
  70    asr_write(env, val, mask);
  71}
  72
  73/* Access to user mode registers from privileged modes.  */
  74uint32_t HELPER(get_user_reg)(CPUUniCore32State *env, uint32_t regno)
  75{
  76    uint32_t val;
  77
  78    if (regno == 29) {
  79        val = env->banked_r29[0];
  80    } else if (regno == 30) {
  81        val = env->banked_r30[0];
  82    } else {
  83        val = env->regs[regno];
  84    }
  85    return val;
  86}
  87
  88void HELPER(set_user_reg)(CPUUniCore32State *env, uint32_t regno, uint32_t val)
  89{
  90    if (regno == 29) {
  91        env->banked_r29[0] = val;
  92    } else if (regno == 30) {
  93        env->banked_r30[0] = val;
  94    } else {
  95        env->regs[regno] = val;
  96    }
  97}
  98
  99/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
 100   The only way to do that in TCG is a conditional branch, which clobbers
 101   all our temporaries.  For now implement these as helper functions.  */
 102
 103uint32_t HELPER(add_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
 104{
 105    uint32_t result;
 106    result = a + b;
 107    env->NF = env->ZF = result;
 108    env->CF = result < a;
 109    env->VF = (a ^ b ^ -1) & (a ^ result);
 110    return result;
 111}
 112
 113uint32_t HELPER(adc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
 114{
 115    uint32_t result;
 116    if (!env->CF) {
 117        result = a + b;
 118        env->CF = result < a;
 119    } else {
 120        result = a + b + 1;
 121        env->CF = result <= a;
 122    }
 123    env->VF = (a ^ b ^ -1) & (a ^ result);
 124    env->NF = env->ZF = result;
 125    return result;
 126}
 127
 128uint32_t HELPER(sub_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
 129{
 130    uint32_t result;
 131    result = a - b;
 132    env->NF = env->ZF = result;
 133    env->CF = a >= b;
 134    env->VF = (a ^ b) & (a ^ result);
 135    return result;
 136}
 137
 138uint32_t HELPER(sbc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
 139{
 140    uint32_t result;
 141    if (!env->CF) {
 142        result = a - b - 1;
 143        env->CF = a > b;
 144    } else {
 145        result = a - b;
 146        env->CF = a >= b;
 147    }
 148    env->VF = (a ^ b) & (a ^ result);
 149    env->NF = env->ZF = result;
 150    return result;
 151}
 152
 153/* Similarly for variable shift instructions.  */
 154
 155uint32_t HELPER(shl)(uint32_t x, uint32_t i)
 156{
 157    int shift = i & 0xff;
 158    if (shift >= 32) {
 159        return 0;
 160    }
 161    return x << shift;
 162}
 163
 164uint32_t HELPER(shr)(uint32_t x, uint32_t i)
 165{
 166    int shift = i & 0xff;
 167    if (shift >= 32) {
 168        return 0;
 169    }
 170    return (uint32_t)x >> shift;
 171}
 172
 173uint32_t HELPER(sar)(uint32_t x, uint32_t i)
 174{
 175    int shift = i & 0xff;
 176    if (shift >= 32) {
 177        shift = 31;
 178    }
 179    return (int32_t)x >> shift;
 180}
 181
 182uint32_t HELPER(shl_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
 183{
 184    int shift = i & 0xff;
 185    if (shift >= 32) {
 186        if (shift == 32) {
 187            env->CF = x & 1;
 188        } else {
 189            env->CF = 0;
 190        }
 191        return 0;
 192    } else if (shift != 0) {
 193        env->CF = (x >> (32 - shift)) & 1;
 194        return x << shift;
 195    }
 196    return x;
 197}
 198
 199uint32_t HELPER(shr_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
 200{
 201    int shift = i & 0xff;
 202    if (shift >= 32) {
 203        if (shift == 32) {
 204            env->CF = (x >> 31) & 1;
 205        } else {
 206            env->CF = 0;
 207        }
 208        return 0;
 209    } else if (shift != 0) {
 210        env->CF = (x >> (shift - 1)) & 1;
 211        return x >> shift;
 212    }
 213    return x;
 214}
 215
 216uint32_t HELPER(sar_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
 217{
 218    int shift = i & 0xff;
 219    if (shift >= 32) {
 220        env->CF = (x >> 31) & 1;
 221        return (int32_t)x >> 31;
 222    } else if (shift != 0) {
 223        env->CF = (x >> (shift - 1)) & 1;
 224        return (int32_t)x >> shift;
 225    }
 226    return x;
 227}
 228
 229uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
 230{
 231    int shift1, shift;
 232    shift1 = i & 0xff;
 233    shift = shift1 & 0x1f;
 234    if (shift == 0) {
 235        if (shift1 != 0) {
 236            env->CF = (x >> 31) & 1;
 237        }
 238        return x;
 239    } else {
 240        env->CF = (x >> (shift - 1)) & 1;
 241        return ((uint32_t)x >> shift) | (x << (32 - shift));
 242    }
 243}
 244
 245#ifndef CONFIG_USER_ONLY
 246void tlb_fill(CPUState *cs, target_ulong addr, int is_write,
 247              int mmu_idx, uintptr_t retaddr)
 248{
 249    int ret;
 250
 251    ret = uc32_cpu_handle_mmu_fault(cs, addr, is_write, mmu_idx);
 252    if (unlikely(ret)) {
 253        if (retaddr) {
 254            /* now we have a real cpu fault */
 255            cpu_restore_state(cs, retaddr);
 256        }
 257        cpu_loop_exit(cs);
 258    }
 259}
 260#endif
 261