Skip to content
Snippets Groups Projects
Select Git revision
  • v1.1-rc0
  • master default
  • sp/trace-zero-ranges
  • stable-2.5
  • stable-2.4
  • stable-2.3
  • stable-2.2
  • stable-2.1
  • stable-2.0
  • stable-1.7
  • stable-1.6
  • stable-1.5
  • stable-1.4
  • stable-1.3
  • stable-1.2
  • stable-1.1
  • stable-1.0
  • stable-0.15
  • stable-0.14
  • stable-0.13
  • stable-0.12
  • v2.7.0-rc1
  • v2.7.0-rc0
  • v2.6.0
  • v2.5.1.1
  • v2.6.0-rc5
  • v2.6.0-rc4
  • v2.6.0-rc3
  • v2.6.0-rc2
  • v2.6.0-rc1
  • v2.6.0-rc0
  • v2.5.1
  • v2.5.0
  • v2.5.0-rc4
  • v2.5.0-rc3
  • v2.5.0-rc2
  • v2.5.0-rc1
  • v2.5.0-rc0
  • v2.4.1
  • v2.4.0.1
  • v2.3.1
41 results

op_helper.c

  • user avatar
    Andreas Färber authored
    Adopt the license text suggested by Guan Xue-tao (with a minor
    simplification) for all target-unicore/ files except helper.c.
    
    To helper.c Anthony Liguori contributed a qemu_malloc() -> g_malloc()
    conversion, still pending IBM relicensing approval, so that remains
    GPLv2 for now.
    
    By relicensing all possible parts now, we avoid having to formally
    relicense new, e.g., QOM code.
    
    Signed-off-by: default avatarAndreas Färber <afaerber@suse.de>
    Signed-off-by: default avatarGuan Xuetao <gxt@mprc.pku.edu.cn>
    Signed-off-by: default avatarStefan Weil <sw@weilnetz.de>
    Signed-off-by: default avatarBlue Swirl <blauwirbel@gmail.com>
    Signed-off-by: default avatarDor Laor <dlaor@redhat.com>
    2b3bc6c0
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    op_helper.c 5.35 KiB
    /*
     *  UniCore32 helper routines
     *
     * Copyright (C) 2010-2011 GUAN Xue-tao
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation, or (at your option) any
     * later version. See the COPYING file in the top-level directory.
     */
    #include "cpu.h"
    #include "dyngen-exec.h"
    #include "helper.h"
    
    #define SIGNBIT (uint32_t)0x80000000
    #define SIGNBIT64 ((uint64_t)1 << 63)
    
    void HELPER(exception)(uint32_t excp)
    {
        env->exception_index = excp;
        cpu_loop_exit(env);
    }
    
    static target_ulong asr_read(void)
    {
        int ZF;
        ZF = (env->ZF == 0);
        return env->uncached_asr | (env->NF & 0x80000000) | (ZF << 30) |
            (env->CF << 29) | ((env->VF & 0x80000000) >> 3);
    }
    
    target_ulong cpu_asr_read(CPUUniCore32State *env1)
    {
        CPUUniCore32State *saved_env;
        target_ulong ret;
    
        saved_env = env;
        env = env1;
        ret = asr_read();
        env = saved_env;
        return ret;
    }
    
    target_ulong HELPER(asr_read)(void)
    {
        return asr_read();
    }
    
    static void asr_write(target_ulong val, target_ulong mask)
    {
        if (mask & ASR_NZCV) {
            env->ZF = (~val) & ASR_Z;
            env->NF = val;
            env->CF = (val >> 29) & 1;
            env->VF = (val << 3) & 0x80000000;
        }
    
        if ((env->uncached_asr ^ val) & mask & ASR_M) {
            switch_mode(env, val & ASR_M);
        }
        mask &= ~ASR_NZCV;
        env->uncached_asr = (env->uncached_asr & ~mask) | (val & mask);
    }
    
    void cpu_asr_write(CPUUniCore32State *env1, target_ulong val, target_ulong mask)
    {
        CPUUniCore32State *saved_env;
    
        saved_env = env;
        env = env1;
        asr_write(val, mask);
        env = saved_env;
    }
    
    void HELPER(asr_write)(target_ulong val, target_ulong mask)
    {
        asr_write(val, mask);
    }
    
    /* Access to user mode registers from privileged modes.  */
    uint32_t HELPER(get_user_reg)(uint32_t regno)
    {
        uint32_t val;
    
        if (regno == 29) {
            val = env->banked_r29[0];
        } else if (regno == 30) {
            val = env->banked_r30[0];
        } else {
            val = env->regs[regno];
        }
        return val;
    }
    
    void HELPER(set_user_reg)(uint32_t regno, uint32_t val)
    {
        if (regno == 29) {
            env->banked_r29[0] = val;
        } else if (regno == 30) {
            env->banked_r30[0] = val;
        } else {
            env->regs[regno] = val;
        }
    }
    
    /* ??? Flag setting arithmetic is awkward because we need to do comparisons.
       The only way to do that in TCG is a conditional branch, which clobbers
       all our temporaries.  For now implement these as helper functions.  */
    
    uint32_t HELPER(add_cc)(uint32_t a, uint32_t b)
    {
        uint32_t result;
        result = a + b;
        env->NF = env->ZF = result;
        env->CF = result < a;
        env->VF = (a ^ b ^ -1) & (a ^ result);
        return result;
    }
    
    uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
    {
        uint32_t result;
        if (!env->CF) {
            result = a + b;
            env->CF = result < a;
        } else {
            result = a + b + 1;
            env->CF = result <= a;
        }
        env->VF = (a ^ b ^ -1) & (a ^ result);
        env->NF = env->ZF = result;
        return result;
    }
    
    uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
    {
        uint32_t result;
        result = a - b;
        env->NF = env->ZF = result;
        env->CF = a >= b;
        env->VF = (a ^ b) & (a ^ result);
        return result;
    }
    
    uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
    {
        uint32_t result;
        if (!env->CF) {
            result = a - b - 1;
            env->CF = a > b;
        } else {
            result = a - b;
            env->CF = a >= b;
        }
        env->VF = (a ^ b) & (a ^ result);
        env->NF = env->ZF = result;
        return result;
    }
    
    /* Similarly for variable shift instructions.  */
    
    uint32_t HELPER(shl)(uint32_t x, uint32_t i)
    {
        int shift = i & 0xff;
        if (shift >= 32) {
            return 0;
        }
        return x << shift;
    }
    
    uint32_t HELPER(shr)(uint32_t x, uint32_t i)
    {
        int shift = i & 0xff;
        if (shift >= 32) {
            return 0;
        }
        return (uint32_t)x >> shift;
    }
    
    uint32_t HELPER(sar)(uint32_t x, uint32_t i)
    {
        int shift = i & 0xff;
        if (shift >= 32) {
            shift = 31;
        }
        return (int32_t)x >> shift;
    }
    
    uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
    {
        int shift = i & 0xff;
        if (shift >= 32) {
            if (shift == 32) {
                env->CF = x & 1;
            } else {
                env->CF = 0;
            }
            return 0;
        } else if (shift != 0) {
            env->CF = (x >> (32 - shift)) & 1;
            return x << shift;
        }
        return x;
    }
    
    uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i)
    {
        int shift = i & 0xff;
        if (shift >= 32) {
            if (shift == 32) {
                env->CF = (x >> 31) & 1;
            } else {
                env->CF = 0;
            }
            return 0;
        } else if (shift != 0) {
            env->CF = (x >> (shift - 1)) & 1;
            return x >> shift;
        }
        return x;
    }
    
    uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i)
    {
        int shift = i & 0xff;
        if (shift >= 32) {
            env->CF = (x >> 31) & 1;
            return (int32_t)x >> 31;
        } else if (shift != 0) {
            env->CF = (x >> (shift - 1)) & 1;
            return (int32_t)x >> shift;
        }
        return x;
    }
    
    uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
    {
        int shift1, shift;
        shift1 = i & 0xff;
        shift = shift1 & 0x1f;
        if (shift == 0) {
            if (shift1 != 0) {
                env->CF = (x >> 31) & 1;
            }
            return x;
        } else {
            env->CF = (x >> (shift - 1)) & 1;
            return ((uint32_t)x >> shift) | (x << (32 - shift));
        }
    }