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