target/sparc: Explicitly compute condition codes
-----BEGIN PGP SIGNATURE----- iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmVH9oodHHJpY2hhcmQu aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV/M8QgAgPTp/wFLVnSRFLaN fBoelVhM4WTWMQ+SUwZMtCvqcMHaBxIMu+hyk5MI11hFOUi9N+vWvRb+NZ6JbK+1 sqWcx0NdYfNdOeoi1dgzGgcCkFA8u9zW/K7Ih0W8WuU20uiJ4Zw/qmnEELIl/mZR 5Ft1mhLMhQSYsH0KSypugLWBxR9SFNH1cV3C1SG2q+6snm/mhKk9NN18zJGFdmmY 4CQThx159P/DaPUONZbSAMN94opu6K8FSymELPDUZBYwJRq7fyGKYuDUGRvN1kxx I8p/MF1V5Vcth9lvGyBYulFWjo9BDMpkIdmWzXZLOWfzZVAed8PcglxoQqgMbU5u eyY/Cw== =Tv1h -----END PGP SIGNATURE----- Merge tag 'pull-sp-20231105' of https://gitlab.com/rth7680/qemu into staging target/sparc: Explicitly compute condition codes # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmVH9oodHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV/M8QgAgPTp/wFLVnSRFLaN # fBoelVhM4WTWMQ+SUwZMtCvqcMHaBxIMu+hyk5MI11hFOUi9N+vWvRb+NZ6JbK+1 # sqWcx0NdYfNdOeoi1dgzGgcCkFA8u9zW/K7Ih0W8WuU20uiJ4Zw/qmnEELIl/mZR # 5Ft1mhLMhQSYsH0KSypugLWBxR9SFNH1cV3C1SG2q+6snm/mhKk9NN18zJGFdmmY # 4CQThx159P/DaPUONZbSAMN94opu6K8FSymELPDUZBYwJRq7fyGKYuDUGRvN1kxx # I8p/MF1V5Vcth9lvGyBYulFWjo9BDMpkIdmWzXZLOWfzZVAed8PcglxoQqgMbU5u # eyY/Cw== # =Tv1h # -----END PGP SIGNATURE----- # gpg: Signature made Mon 06 Nov 2023 04:09:46 HKT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * tag 'pull-sp-20231105' of https://gitlab.com/rth7680/qemu: (21 commits) target/sparc: Check for invalid cond in gen_compare_reg target/sparc: Implement UDIV inline target/sparc: Implement UDIVX and SDIVX inline target/sparc: Discard cpu_cond at the end of each insn target/sparc: Record entire jump condition in DisasContext target/sparc: Merge gen_op_next_insn into only caller target/sparc: Pass displacement to advance_jump_cond target/sparc: Merge advance_jump_uncond_{never,always} into advance_jump_cond target/sparc: Merge gen_branch2 into advance_pc target/sparc: Do flush_cond in advance_jump_cond target/sparc: Always copy conditions into a new temporary target/sparc: Change DisasCompare.c2 to int target/sparc: Remove DisasCompare.is_bool target/sparc: Remove CC_OP leftovers target/sparc: Remove CC_OP_TADDTV, CC_OP_TSUBTV target/sparc: Remove CC_OP_SUB, CC_OP_SUBX, CC_OP_TSUB target/sparc: Remove CC_OP_ADD, CC_OP_ADDX, CC_OP_TADD target/sparc: Remove CC_OP_DIV target/sparc: Remove CC_OP_LOGIC target/sparc: Split psr and xcc into components ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
3e01f1147a
@ -197,10 +197,8 @@ static uint32_t do_getpsr(CPUSPARCState *env)
|
||||
/* Avoid ifdefs below for the abi32 and abi64 paths. */
|
||||
#ifdef TARGET_ABI32
|
||||
#define TARGET_TT_SYSCALL (TT_TRAP + 0x10) /* t_linux */
|
||||
#define syscall_cc psr
|
||||
#else
|
||||
#define TARGET_TT_SYSCALL (TT_TRAP + 0x6d) /* tl0_linux64 */
|
||||
#define syscall_cc xcc
|
||||
#endif
|
||||
|
||||
/* Avoid ifdefs below for the v9 and pre-v9 hw traps. */
|
||||
@ -224,11 +222,6 @@ void cpu_loop (CPUSPARCState *env)
|
||||
cpu_exec_end(cs);
|
||||
process_queued_cpu_work(cs);
|
||||
|
||||
/* Compute PSR before exposing state. */
|
||||
if (env->cc_op != CC_OP_FLAGS) {
|
||||
cpu_get_psr(env);
|
||||
}
|
||||
|
||||
switch (trapnr) {
|
||||
case TARGET_TT_SYSCALL:
|
||||
ret = do_syscall (env, env->gregs[1],
|
||||
@ -240,10 +233,10 @@ void cpu_loop (CPUSPARCState *env)
|
||||
break;
|
||||
}
|
||||
if ((abi_ulong)ret >= (abi_ulong)(-515)) {
|
||||
env->syscall_cc |= PSR_CARRY;
|
||||
set_syscall_C(env, 1);
|
||||
ret = -ret;
|
||||
} else {
|
||||
env->syscall_cc &= ~PSR_CARRY;
|
||||
set_syscall_C(env, 0);
|
||||
}
|
||||
env->regwptr[0] = ret;
|
||||
/* next instruction */
|
||||
|
@ -164,7 +164,7 @@ static void restore_pt_regs(struct target_pt_regs *regs, CPUSPARCState *env)
|
||||
*/
|
||||
uint32_t psr;
|
||||
__get_user(psr, ®s->psr);
|
||||
env->psr = (psr & PSR_ICC) | (env->psr & ~PSR_ICC);
|
||||
cpu_put_psr_icc(env, psr);
|
||||
#endif
|
||||
|
||||
/* Note that pc and npc are handled in the caller. */
|
||||
|
@ -26,6 +26,17 @@
|
||||
# define TARGET_STACK_BIAS 0
|
||||
#endif
|
||||
|
||||
static void set_syscall_C(CPUSPARCState *env, bool val)
|
||||
{
|
||||
#ifndef TARGET_SPARC64
|
||||
env->icc_C = val;
|
||||
#elif defined(TARGET_ABI32)
|
||||
env->icc_C = (uint64_t)val << 32;
|
||||
#else
|
||||
env->xcc_C = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void cpu_clone_regs_child(CPUSPARCState *env, target_ulong newsp,
|
||||
unsigned flags)
|
||||
{
|
||||
@ -58,11 +69,7 @@ static inline void cpu_clone_regs_child(CPUSPARCState *env, target_ulong newsp,
|
||||
* do the pc advance twice.
|
||||
*/
|
||||
env->regwptr[WREG_O0] = 0;
|
||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
||||
env->xcc &= ~PSR_CARRY;
|
||||
#else
|
||||
env->psr &= ~PSR_CARRY;
|
||||
#endif
|
||||
set_syscall_C(env, 0);
|
||||
env->pc = env->npc;
|
||||
env->npc = env->npc + 4;
|
||||
}
|
||||
|
@ -1,471 +0,0 @@
|
||||
/*
|
||||
* Helpers for lazy condition code handling
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
static uint32_t compute_all_flags(CPUSPARCState *env)
|
||||
{
|
||||
return env->psr & PSR_ICC;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_flags(CPUSPARCState *env)
|
||||
{
|
||||
return env->psr & PSR_CARRY;
|
||||
}
|
||||
|
||||
static inline uint32_t get_NZ_icc(int32_t dst)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (dst == 0) {
|
||||
ret = PSR_ZERO;
|
||||
} else if (dst < 0) {
|
||||
ret = PSR_NEG;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static uint32_t compute_all_flags_xcc(CPUSPARCState *env)
|
||||
{
|
||||
return env->xcc & PSR_ICC;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_flags_xcc(CPUSPARCState *env)
|
||||
{
|
||||
return env->xcc & PSR_CARRY;
|
||||
}
|
||||
|
||||
static inline uint32_t get_NZ_xcc(target_long dst)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (!dst) {
|
||||
ret = PSR_ZERO;
|
||||
} else if (dst < 0) {
|
||||
ret = PSR_NEG;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline uint32_t get_V_div_icc(target_ulong src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (src2 != 0) {
|
||||
ret = PSR_OVF;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_all_div(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_icc(CC_DST);
|
||||
ret |= get_V_div_icc(CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_div(CPUSPARCState *env)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t get_C_add_icc(uint32_t dst, uint32_t src1)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (dst < src1) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_C_addx_icc(uint32_t dst, uint32_t src1,
|
||||
uint32_t src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (((src1 & src2) | (~dst & (src1 | src2))) & (1U << 31)) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_V_add_icc(uint32_t dst, uint32_t src1,
|
||||
uint32_t src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1U << 31)) {
|
||||
ret = PSR_OVF;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (dst < src1) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_C_addx_xcc(target_ulong dst, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (((src1 & src2) | (~dst & (src1 | src2))) & (1ULL << 63)) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63)) {
|
||||
ret = PSR_OVF;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_all_add_xcc(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_xcc(CC_DST);
|
||||
ret |= get_C_add_xcc(CC_DST, CC_SRC);
|
||||
ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_add_xcc(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_add_xcc(CC_DST, CC_SRC);
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t compute_all_add(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_icc(CC_DST);
|
||||
ret |= get_C_add_icc(CC_DST, CC_SRC);
|
||||
ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_add(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_add_icc(CC_DST, CC_SRC);
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static uint32_t compute_all_addx_xcc(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_xcc(CC_DST);
|
||||
ret |= get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
|
||||
ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_addx_xcc(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t compute_all_addx(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_icc(CC_DST);
|
||||
ret |= get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
|
||||
ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_addx(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
|
||||
}
|
||||
|
||||
static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if ((src1 | src2) & 0x3) {
|
||||
ret = PSR_OVF;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_all_tadd(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_icc(CC_DST);
|
||||
ret |= get_C_add_icc(CC_DST, CC_SRC);
|
||||
ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
|
||||
ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_all_taddtv(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_icc(CC_DST);
|
||||
ret |= get_C_add_icc(CC_DST, CC_SRC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_C_sub_icc(uint32_t src1, uint32_t src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (src1 < src2) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_C_subx_icc(uint32_t dst, uint32_t src1,
|
||||
uint32_t src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (((~src1 & src2) | (dst & (~src1 | src2))) & (1U << 31)) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_V_sub_icc(uint32_t dst, uint32_t src1,
|
||||
uint32_t src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (((src1 ^ src2) & (src1 ^ dst)) & (1U << 31)) {
|
||||
ret = PSR_OVF;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (src1 < src2) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_C_subx_xcc(target_ulong dst, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (((~src1 & src2) | (dst & (~src1 | src2))) & (1ULL << 63)) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63)) {
|
||||
ret = PSR_OVF;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_all_sub_xcc(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_xcc(CC_DST);
|
||||
ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
|
||||
ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_sub_xcc(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_sub_xcc(CC_SRC, CC_SRC2);
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t compute_all_sub(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_icc(CC_DST);
|
||||
ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
|
||||
ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_sub(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_sub_icc(CC_SRC, CC_SRC2);
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static uint32_t compute_all_subx_xcc(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_xcc(CC_DST);
|
||||
ret |= get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
|
||||
ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_subx_xcc(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t compute_all_subx(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_icc(CC_DST);
|
||||
ret |= get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
|
||||
ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_subx(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
|
||||
}
|
||||
|
||||
static uint32_t compute_all_tsub(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_icc(CC_DST);
|
||||
ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
|
||||
ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
|
||||
ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_all_tsubtv(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_icc(CC_DST);
|
||||
ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_all_logic(CPUSPARCState *env)
|
||||
{
|
||||
return get_NZ_icc(CC_DST);
|
||||
}
|
||||
|
||||
static uint32_t compute_C_logic(CPUSPARCState *env)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static uint32_t compute_all_logic_xcc(CPUSPARCState *env)
|
||||
{
|
||||
return get_NZ_xcc(CC_DST);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct CCTable {
|
||||
uint32_t (*compute_all)(CPUSPARCState *env); /* return all the flags */
|
||||
uint32_t (*compute_c)(CPUSPARCState *env); /* return the C flag */
|
||||
} CCTable;
|
||||
|
||||
static const CCTable icc_table[CC_OP_NB] = {
|
||||
/* CC_OP_DYNAMIC should never happen */
|
||||
[CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
|
||||
[CC_OP_DIV] = { compute_all_div, compute_C_div },
|
||||
[CC_OP_ADD] = { compute_all_add, compute_C_add },
|
||||
[CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
|
||||
[CC_OP_TADD] = { compute_all_tadd, compute_C_add },
|
||||
[CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
|
||||
[CC_OP_SUB] = { compute_all_sub, compute_C_sub },
|
||||
[CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
|
||||
[CC_OP_TSUB] = { compute_all_tsub, compute_C_sub },
|
||||
[CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_sub },
|
||||
[CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
|
||||
};
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static const CCTable xcc_table[CC_OP_NB] = {
|
||||
/* CC_OP_DYNAMIC should never happen */
|
||||
[CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
|
||||
[CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
|
||||
[CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
|
||||
[CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
|
||||
[CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
|
||||
[CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
|
||||
[CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
|
||||
[CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
|
||||
[CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
|
||||
[CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
|
||||
[CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
|
||||
};
|
||||
#endif
|
||||
|
||||
void helper_compute_psr(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t new_psr;
|
||||
|
||||
new_psr = icc_table[CC_OP].compute_all(env);
|
||||
env->psr = new_psr;
|
||||
#ifdef TARGET_SPARC64
|
||||
new_psr = xcc_table[CC_OP].compute_all(env);
|
||||
env->xcc = new_psr;
|
||||
#endif
|
||||
CC_OP = CC_OP_FLAGS;
|
||||
}
|
||||
|
||||
uint32_t helper_compute_C_icc(CPUSPARCState *env)
|
||||
{
|
||||
return icc_table[CC_OP].compute_c(env) >> PSR_CARRY_SHIFT;
|
||||
}
|
@ -46,7 +46,6 @@ static void sparc_cpu_reset_hold(Object *obj)
|
||||
env->wim = 1;
|
||||
#endif
|
||||
env->regwptr = env->regbase + (env->cwp * 16);
|
||||
CC_OP = CC_OP_FLAGS;
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
#ifdef TARGET_SPARC64
|
||||
env->cleanwin = env->nwindows - 2;
|
||||
|
@ -137,32 +137,6 @@ enum {
|
||||
#define PSR_CWP 0x1f
|
||||
#endif
|
||||
|
||||
#define CC_SRC (env->cc_src)
|
||||
#define CC_SRC2 (env->cc_src2)
|
||||
#define CC_DST (env->cc_dst)
|
||||
#define CC_OP (env->cc_op)
|
||||
|
||||
/* Even though lazy evaluation of CPU condition codes tends to be less
|
||||
* important on RISC systems where condition codes are only updated
|
||||
* when explicitly requested, SPARC uses it to update 32-bit and 64-bit
|
||||
* condition codes.
|
||||
*/
|
||||
enum {
|
||||
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
|
||||
CC_OP_FLAGS, /* all cc are back in status register */
|
||||
CC_OP_DIV, /* modify N, Z and V, C = 0*/
|
||||
CC_OP_ADD, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_ADDX, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_TADD, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_TADDTV, /* modify all flags except V, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_SUB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_SUBX, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_TSUB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_TSUBTV, /* modify all flags except V, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_LOGIC, /* modify N and Z, C = V = 0, CC_DST = res */
|
||||
CC_OP_NB,
|
||||
};
|
||||
|
||||
/* Trap base register */
|
||||
#define TBR_BASE_MASK 0xfffff000
|
||||
|
||||
@ -458,15 +432,35 @@ struct CPUArchState {
|
||||
target_ulong npc; /* next program counter */
|
||||
target_ulong y; /* multiply/divide register */
|
||||
|
||||
/* emulator internal flags handling */
|
||||
target_ulong cc_src, cc_src2;
|
||||
target_ulong cc_dst;
|
||||
uint32_t cc_op;
|
||||
/*
|
||||
* Bit 31 is for icc, bit 63 for xcc.
|
||||
* Other bits are garbage.
|
||||
*/
|
||||
target_long cc_N;
|
||||
target_long cc_V;
|
||||
|
||||
/*
|
||||
* Z is represented as == 0; any non-zero value is !Z.
|
||||
* For sparc64, the high 32-bits of icc.Z are garbage.
|
||||
*/
|
||||
target_ulong icc_Z;
|
||||
#ifdef TARGET_SPARC64
|
||||
target_ulong xcc_Z;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For sparc32, icc.C is boolean.
|
||||
* For sparc64, xcc.C is boolean;
|
||||
* icc.C is bit 32 with other bits garbage.
|
||||
*/
|
||||
target_ulong icc_C;
|
||||
#ifdef TARGET_SPARC64
|
||||
target_ulong xcc_C;
|
||||
#endif
|
||||
|
||||
target_ulong cond; /* conditional branch result (XXX: save it in a
|
||||
temporary register when possible) */
|
||||
|
||||
uint32_t psr; /* processor state register */
|
||||
target_ulong fsr; /* FPU state register */
|
||||
CPU_DoubleU fpr[TARGET_DPREGS]; /* floating point registers */
|
||||
uint32_t cwp; /* index of current register window (extracted
|
||||
@ -522,7 +516,6 @@ struct CPUArchState {
|
||||
#define MAXTL_MAX 8
|
||||
#define MAXTL_MASK (MAXTL_MAX - 1)
|
||||
trap_state ts[MAXTL_MAX];
|
||||
uint32_t xcc; /* Extended integer condition codes */
|
||||
uint32_t asi;
|
||||
uint32_t pstate;
|
||||
uint32_t tl;
|
||||
@ -619,6 +612,7 @@ void sparc_restore_state_to_opc(CPUState *cs,
|
||||
/* win_helper.c */
|
||||
target_ulong cpu_get_psr(CPUSPARCState *env1);
|
||||
void cpu_put_psr(CPUSPARCState *env1, target_ulong val);
|
||||
void cpu_put_psr_icc(CPUSPARCState *env1, target_ulong val);
|
||||
void cpu_put_psr_raw(CPUSPARCState *env1, target_ulong val);
|
||||
#ifdef TARGET_SPARC64
|
||||
void cpu_change_pstate(CPUSPARCState *env1, uint32_t new_pstate);
|
||||
|
@ -81,109 +81,58 @@ void helper_tick_set_limit(void *opaque, uint64_t limit)
|
||||
}
|
||||
#endif
|
||||
|
||||
static target_ulong do_udiv(CPUSPARCState *env, target_ulong a,
|
||||
target_ulong b, int cc, uintptr_t ra)
|
||||
uint64_t helper_udiv(CPUSPARCState *env, target_ulong a, target_ulong b)
|
||||
{
|
||||
int overflow = 0;
|
||||
uint64_t x0;
|
||||
uint32_t x1;
|
||||
uint64_t a64 = (uint32_t)a | ((uint64_t)env->y << 32);
|
||||
uint32_t b32 = b;
|
||||
uint32_t r;
|
||||
|
||||
x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
|
||||
x1 = (b & 0xffffffff);
|
||||
|
||||
if (x1 == 0) {
|
||||
cpu_raise_exception_ra(env, TT_DIV_ZERO, ra);
|
||||
}
|
||||
|
||||
x0 = x0 / x1;
|
||||
if (x0 > UINT32_MAX) {
|
||||
x0 = UINT32_MAX;
|
||||
overflow = 1;
|
||||
}
|
||||
|
||||
if (cc) {
|
||||
env->cc_src2 = overflow;
|
||||
}
|
||||
return x0;
|
||||
}
|
||||
|
||||
target_ulong helper_udiv(CPUSPARCState *env, target_ulong a, target_ulong b)
|
||||
{
|
||||
return do_udiv(env, a, b, 0, GETPC());
|
||||
}
|
||||
|
||||
target_ulong helper_udiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b)
|
||||
{
|
||||
return do_udiv(env, a, b, 1, GETPC());
|
||||
}
|
||||
|
||||
static target_ulong do_sdiv(CPUSPARCState *env, target_ulong a,
|
||||
target_ulong b, int cc, uintptr_t ra)
|
||||
{
|
||||
int overflow = 0;
|
||||
int64_t x0;
|
||||
int32_t x1;
|
||||
|
||||
x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
|
||||
x1 = (b & 0xffffffff);
|
||||
|
||||
if (x1 == 0) {
|
||||
cpu_raise_exception_ra(env, TT_DIV_ZERO, ra);
|
||||
} else if (x1 == -1 && x0 == INT64_MIN) {
|
||||
x0 = INT32_MAX;
|
||||
overflow = 1;
|
||||
} else {
|
||||
x0 = x0 / x1;
|
||||
if ((int32_t) x0 != x0) {
|
||||
x0 = x0 < 0 ? INT32_MIN : INT32_MAX;
|
||||
overflow = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cc) {
|
||||
env->cc_src2 = overflow;
|
||||
}
|
||||
return x0;
|
||||
}
|
||||
|
||||
target_ulong helper_sdiv(CPUSPARCState *env, target_ulong a, target_ulong b)
|
||||
{
|
||||
return do_sdiv(env, a, b, 0, GETPC());
|
||||
}
|
||||
|
||||
target_ulong helper_sdiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b)
|
||||
{
|
||||
return do_sdiv(env, a, b, 1, GETPC());
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
int64_t helper_sdivx(CPUSPARCState *env, int64_t a, int64_t b)
|
||||
{
|
||||
if (b == 0) {
|
||||
/* Raise divide by zero trap. */
|
||||
cpu_raise_exception_ra(env, TT_DIV_ZERO, GETPC());
|
||||
} else if (b == -1) {
|
||||
/* Avoid overflow trap with i386 divide insn. */
|
||||
return -a;
|
||||
} else {
|
||||
return a / b;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b)
|
||||
{
|
||||
if (b == 0) {
|
||||
/* Raise divide by zero trap. */
|
||||
if (b32 == 0) {
|
||||
cpu_raise_exception_ra(env, TT_DIV_ZERO, GETPC());
|
||||
}
|
||||
return a / b;
|
||||
|
||||
a64 /= b32;
|
||||
r = a64;
|
||||
if (unlikely(a64 > UINT32_MAX)) {
|
||||
return -1; /* r = UINT32_MAX, v = 1 */
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t helper_sdiv(CPUSPARCState *env, target_ulong a, target_ulong b)
|
||||
{
|
||||
int64_t a64 = (uint32_t)a | ((uint64_t)env->y << 32);
|
||||
int32_t b32 = b;
|
||||
int32_t r;
|
||||
|
||||
if (b32 == 0) {
|
||||
cpu_raise_exception_ra(env, TT_DIV_ZERO, GETPC());
|
||||
}
|
||||
|
||||
if (unlikely(a64 == INT64_MIN)) {
|
||||
/*
|
||||
* Special case INT64_MIN / -1 is required to avoid trap on x86 host.
|
||||
* However, with a dividend of INT64_MIN, there is no 32-bit divisor
|
||||
* which can yield a 32-bit result:
|
||||
* INT64_MIN / INT32_MIN = 0x1_0000_0000
|
||||
* INT64_MIN / INT32_MAX = -0x1_0000_0002
|
||||
* Therefore we know we must overflow and saturate.
|
||||
*/
|
||||
return (uint32_t)(b32 < 0 ? INT32_MAX : INT32_MIN) | (-1ull << 32);
|
||||
}
|
||||
|
||||
a64 /= b;
|
||||
r = a64;
|
||||
if (unlikely(r != a64)) {
|
||||
return (uint32_t)(a64 < 0 ? INT32_MIN : INT32_MAX) | (-1ull << 32);
|
||||
}
|
||||
return (uint32_t)r;
|
||||
}
|
||||
#endif
|
||||
|
||||
target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
target_ulong dst;
|
||||
target_ulong dst, v;
|
||||
|
||||
/* Tag overflow occurs if either input has bits 0 or 1 set. */
|
||||
if ((src1 | src2) & 3) {
|
||||
@ -193,13 +142,23 @@ target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1,
|
||||
dst = src1 + src2;
|
||||
|
||||
/* Tag overflow occurs if the addition overflows. */
|
||||
if (~(src1 ^ src2) & (src1 ^ dst) & (1u << 31)) {
|
||||
v = ~(src1 ^ src2) & (src1 ^ dst);
|
||||
if (v & (1u << 31)) {
|
||||
goto tag_overflow;
|
||||
}
|
||||
|
||||
/* Only modify the CC after any exceptions have been generated. */
|
||||
env->cc_src = src1;
|
||||
env->cc_src2 = src2;
|
||||
env->cc_V = v;
|
||||
env->cc_N = dst;
|
||||
env->icc_Z = dst;
|
||||
#ifdef TARGET_SPARC64
|
||||
env->xcc_Z = dst;
|
||||
env->icc_C = dst ^ src1 ^ src2;
|
||||
env->xcc_C = dst < src1;
|
||||
#else
|
||||
env->icc_C = dst < src1;
|
||||
#endif
|
||||
|
||||
return dst;
|
||||
|
||||
tag_overflow:
|
||||
@ -209,7 +168,7 @@ target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1,
|
||||
target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
target_ulong dst;
|
||||
target_ulong dst, v;
|
||||
|
||||
/* Tag overflow occurs if either input has bits 0 or 1 set. */
|
||||
if ((src1 | src2) & 3) {
|
||||
@ -219,13 +178,23 @@ target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1,
|
||||
dst = src1 - src2;
|
||||
|
||||
/* Tag overflow occurs if the subtraction overflows. */
|
||||
if ((src1 ^ src2) & (src1 ^ dst) & (1u << 31)) {
|
||||
v = (src1 ^ src2) & (src1 ^ dst);
|
||||
if (v & (1u << 31)) {
|
||||
goto tag_overflow;
|
||||
}
|
||||
|
||||
/* Only modify the CC after any exceptions have been generated. */
|
||||
env->cc_src = src1;
|
||||
env->cc_src2 = src2;
|
||||
env->cc_V = v;
|
||||
env->cc_N = dst;
|
||||
env->icc_Z = dst;
|
||||
#ifdef TARGET_SPARC64
|
||||
env->xcc_Z = dst;
|
||||
env->icc_C = dst ^ src1 ^ src2;
|
||||
env->xcc_C = src1 < src2;
|
||||
#else
|
||||
env->icc_C = src1 < src2;
|
||||
#endif
|
||||
|
||||
return dst;
|
||||
|
||||
tag_overflow:
|
||||
|
@ -27,16 +27,10 @@ DEF_HELPER_FLAGS_2(tick_set_limit, TCG_CALL_NO_RWG, void, ptr, i64)
|
||||
DEF_HELPER_1(debug, void, env)
|
||||
DEF_HELPER_1(save, void, env)
|
||||
DEF_HELPER_1(restore, void, env)
|
||||
DEF_HELPER_3(udiv, tl, env, tl, tl)
|
||||
DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
|
||||
DEF_HELPER_3(sdiv, tl, env, tl, tl)
|
||||
DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(udiv, TCG_CALL_NO_WG, i64, env, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(sdiv, TCG_CALL_NO_WG, i64, env, tl, tl)
|
||||
DEF_HELPER_3(taddcctv, tl, env, tl, tl)
|
||||
DEF_HELPER_3(tsubcctv, tl, env, tl, tl)
|
||||
#ifdef TARGET_SPARC64
|
||||
DEF_HELPER_FLAGS_3(sdivx, TCG_CALL_NO_WG, s64, env, s64, s64)
|
||||
DEF_HELPER_FLAGS_3(udivx, TCG_CALL_NO_WG, i64, env, i64, i64)
|
||||
#endif
|
||||
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
|
||||
DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32)
|
||||
DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
|
||||
@ -150,5 +144,3 @@ VIS_CMPHELPER(cmpne)
|
||||
#undef F_HELPER_0_1
|
||||
#undef VIS_HELPER
|
||||
#undef VIS_CMPHELPER
|
||||
DEF_HELPER_1(compute_psr, void, env)
|
||||
DEF_HELPER_FLAGS_1(compute_C_icc, TCG_CALL_NO_WG_SE, i32, env)
|
||||
|
@ -182,9 +182,10 @@ UMUL 10 ..... 0.1010 ..... . ............. @r_r_ri_cc
|
||||
SMUL 10 ..... 0.1011 ..... . ............. @r_r_ri_cc
|
||||
MULScc 10 ..... 100100 ..... . ............. @r_r_ri_cc1
|
||||
|
||||
UDIVX 10 ..... 001101 ..... . ............. @r_r_ri_cc0
|
||||
SDIVX 10 ..... 101101 ..... . ............. @r_r_ri_cc0
|
||||
UDIV 10 ..... 0.1110 ..... . ............. @r_r_ri_cc
|
||||
UDIVX 10 ..... 001101 ..... . ............. @r_r_ri
|
||||
SDIVX 10 ..... 101101 ..... . ............. @r_r_ri
|
||||
UDIV 10 ..... 001110 ..... . ............. @r_r_ri
|
||||
UDIVcc 10 ..... 011110 ..... . ............. @r_r_ri_cc1
|
||||
SDIV 10 ..... 0.1111 ..... . ............. @r_r_ri_cc
|
||||
|
||||
TADDcc 10 ..... 100000 ..... . ............. @r_r_ri_cc1
|
||||
|
@ -103,11 +103,6 @@ void sparc_cpu_do_interrupt(CPUState *cs)
|
||||
CPUSPARCState *env = &cpu->env;
|
||||
int cwp, intno = cs->exception_index;
|
||||
|
||||
/* Compute PSR before exposing state. */
|
||||
if (env->cc_op != CC_OP_FLAGS) {
|
||||
cpu_get_psr(env);
|
||||
}
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_INT)) {
|
||||
static int count;
|
||||
const char *name;
|
||||
|
@ -135,11 +135,6 @@ void sparc_cpu_do_interrupt(CPUState *cs)
|
||||
int intno = cs->exception_index;
|
||||
trap_state *tsptr;
|
||||
|
||||
/* Compute PSR before exposing state. */
|
||||
if (env->cc_op != CC_OP_FLAGS) {
|
||||
cpu_get_psr(env);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PCALL
|
||||
if (qemu_loglevel_mask(CPU_LOG_INT)) {
|
||||
static int count;
|
||||
|
@ -83,6 +83,42 @@ static const VMStateInfo vmstate_psr = {
|
||||
.put = put_psr,
|
||||
};
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static int get_xcc(QEMUFile *f, void *opaque, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
SPARCCPU *cpu = opaque;
|
||||
CPUSPARCState *env = &cpu->env;
|
||||
uint32_t val = qemu_get_be32(f);
|
||||
|
||||
/* Do not clobber icc.[NV] */
|
||||
env->cc_N = deposit64(env->cc_N, 32, 32, -(val & PSR_NEG));
|
||||
env->cc_V = deposit64(env->cc_V, 32, 32, -(val & PSR_OVF));
|
||||
env->xcc_Z = ~val & PSR_ZERO;
|
||||
env->xcc_C = (val >> PSR_CARRY_SHIFT) & 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_xcc(QEMUFile *f, void *opaque, size_t size,
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
SPARCCPU *cpu = opaque;
|
||||
CPUSPARCState *env = &cpu->env;
|
||||
uint32_t val = cpu_get_ccr(env);
|
||||
|
||||
/* Extract just xcc out of ccr and shift into legacy position. */
|
||||
qemu_put_be32(f, (val & 0xf0) << (20 - 4));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateInfo vmstate_xcc = {
|
||||
.name = "xcc",
|
||||
.get = get_xcc,
|
||||
.put = put_xcc,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int cpu_pre_save(void *opaque)
|
||||
{
|
||||
SPARCCPU *cpu = opaque;
|
||||
@ -155,7 +191,14 @@ const VMStateDescription vmstate_sparc_cpu = {
|
||||
VMSTATE_UINT32(env.mmu_version, SPARCCPU),
|
||||
VMSTATE_STRUCT_ARRAY(env.ts, SPARCCPU, MAXTL_MAX, 0,
|
||||
vmstate_trap_state, trap_state),
|
||||
VMSTATE_UINT32(env.xcc, SPARCCPU),
|
||||
{
|
||||
.name = "xcc",
|
||||
.version_id = 0,
|
||||
.size = sizeof(uint32_t),
|
||||
.info = &vmstate_xcc,
|
||||
.flags = VMS_SINGLE,
|
||||
.offset = 0,
|
||||
},
|
||||
VMSTATE_UINT32(env.asi, SPARCCPU),
|
||||
VMSTATE_UINT32(env.pstate, SPARCCPU),
|
||||
VMSTATE_UINT32(env.tl, SPARCCPU),
|
||||
|
@ -3,7 +3,6 @@ gen = decodetree.process('insns.decode')
|
||||
sparc_ss = ss.source_set()
|
||||
sparc_ss.add(gen)
|
||||
sparc_ss.add(files(
|
||||
'cc_helper.c',
|
||||
'cpu.c',
|
||||
'fop_helper.c',
|
||||
'gdbstub.c',
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -53,23 +53,47 @@ void cpu_set_cwp(CPUSPARCState *env, int new_cwp)
|
||||
|
||||
target_ulong cpu_get_psr(CPUSPARCState *env)
|
||||
{
|
||||
helper_compute_psr(env);
|
||||
target_ulong icc = 0;
|
||||
|
||||
icc |= ((int32_t)env->cc_N < 0) << PSR_NEG_SHIFT;
|
||||
icc |= ((int32_t)env->cc_V < 0) << PSR_OVF_SHIFT;
|
||||
icc |= ((int32_t)env->icc_Z == 0) << PSR_ZERO_SHIFT;
|
||||
if (TARGET_LONG_BITS == 64) {
|
||||
icc |= extract64(env->icc_C, 32, 1) << PSR_CARRY_SHIFT;
|
||||
} else {
|
||||
icc |= env->icc_C << PSR_CARRY_SHIFT;
|
||||
}
|
||||
|
||||
#if !defined(TARGET_SPARC64)
|
||||
return env->version | (env->psr & PSR_ICC) |
|
||||
return env->version | icc |
|
||||
(env->psref ? PSR_EF : 0) |
|
||||
(env->psrpil << 8) |
|
||||
(env->psrs ? PSR_S : 0) |
|
||||
(env->psrps ? PSR_PS : 0) |
|
||||
(env->psret ? PSR_ET : 0) | env->cwp;
|
||||
#else
|
||||
return env->psr & PSR_ICC;
|
||||
return icc;
|
||||
#endif
|
||||
}
|
||||
|
||||
void cpu_put_psr_icc(CPUSPARCState *env, target_ulong val)
|
||||
{
|
||||
if (TARGET_LONG_BITS == 64) {
|
||||
/* Do not clobber xcc.[NV] */
|
||||
env->cc_N = deposit64(env->cc_N, 0, 32, -(val & PSR_NEG));
|
||||
env->cc_V = deposit64(env->cc_V, 0, 32, -(val & PSR_OVF));
|
||||
env->icc_C = -(val & PSR_CARRY);
|
||||
} else {
|
||||
env->cc_N = -(val & PSR_NEG);
|
||||
env->cc_V = -(val & PSR_OVF);
|
||||
env->icc_C = (val >> PSR_CARRY_SHIFT) & 1;
|
||||
}
|
||||
env->icc_Z = ~val & PSR_ZERO;
|
||||
}
|
||||
|
||||
void cpu_put_psr_raw(CPUSPARCState *env, target_ulong val)
|
||||
{
|
||||
env->psr = val & PSR_ICC;
|
||||
cpu_put_psr_icc(env, val);
|
||||
#if !defined(TARGET_SPARC64)
|
||||
env->psref = (val & PSR_EF) ? 1 : 0;
|
||||
env->psrpil = (val & PSR_PIL) >> 8;
|
||||
@ -77,7 +101,6 @@ void cpu_put_psr_raw(CPUSPARCState *env, target_ulong val)
|
||||
env->psrps = (val & PSR_PS) ? 1 : 0;
|
||||
env->psret = (val & PSR_ET) ? 1 : 0;
|
||||
#endif
|
||||
env->cc_op = CC_OP_FLAGS;
|
||||
#if !defined(TARGET_SPARC64)
|
||||
cpu_set_cwp(env, val & PSR_CWP);
|
||||
#endif
|
||||
@ -244,18 +267,29 @@ void helper_restored(CPUSPARCState *env)
|
||||
|
||||
target_ulong cpu_get_ccr(CPUSPARCState *env)
|
||||
{
|
||||
target_ulong psr;
|
||||
target_ulong ccr = 0;
|
||||
|
||||
psr = cpu_get_psr(env);
|
||||
ccr |= (env->icc_C >> 32) & 1;
|
||||
ccr |= ((int32_t)env->cc_V < 0) << 1;
|
||||
ccr |= ((int32_t)env->icc_Z == 0) << 2;
|
||||
ccr |= ((int32_t)env->cc_N < 0) << 3;
|
||||
|
||||
return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20);
|
||||
ccr |= env->xcc_C << 4;
|
||||
ccr |= (env->cc_V < 0) << 5;
|
||||
ccr |= (env->xcc_Z == 0) << 6;
|
||||
ccr |= (env->cc_N < 0) << 7;
|
||||
|
||||
return ccr;
|
||||
}
|
||||
|
||||
void cpu_put_ccr(CPUSPARCState *env, target_ulong val)
|
||||
{
|
||||
env->xcc = (val >> 4) << 20;
|
||||
env->psr = (val & 0xf) << 20;
|
||||
CC_OP = CC_OP_FLAGS;
|
||||
env->cc_N = deposit64(-(val & 0x08), 32, 32, -(val & 0x80));
|
||||
env->cc_V = deposit64(-(val & 0x02), 32, 32, -(val & 0x20));
|
||||
env->icc_C = (uint64_t)val << 32;
|
||||
env->xcc_C = (val >> 4) & 1;
|
||||
env->icc_Z = ~val & 0x04;
|
||||
env->xcc_Z = ~val & 0x40;
|
||||
}
|
||||
|
||||
target_ulong cpu_get_cwp64(CPUSPARCState *env)
|
||||
|
Loading…
Reference in New Issue
Block a user