?? op_helper.c
字號:
/* * PowerPC emulation helpers for qemu. * * Copyright (c) 2003-2007 Jocelyn Mayer * * 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 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "exec.h"#include "host-utils.h"#include "helper_regs.h"#include "op_helper.h"#define MEMSUFFIX _raw#include "op_helper.h"#include "op_helper_mem.h"#if !defined(CONFIG_USER_ONLY)#define MEMSUFFIX _user#include "op_helper.h"#include "op_helper_mem.h"#define MEMSUFFIX _kernel#include "op_helper.h"#include "op_helper_mem.h"#define MEMSUFFIX _hypv#include "op_helper.h"#include "op_helper_mem.h"#endif//#define DEBUG_OP//#define DEBUG_EXCEPTIONS//#define DEBUG_SOFTWARE_TLB/*****************************************************************************//* Exceptions processing helpers */void do_raise_exception_err (uint32_t exception, int error_code){#if 0 printf("Raise exception %3x code : %d\n", exception, error_code);#endif env->exception_index = exception; env->error_code = error_code; cpu_loop_exit();}void do_raise_exception (uint32_t exception){ do_raise_exception_err(exception, 0);}void cpu_dump_EA (target_ulong EA);void do_print_mem_EA (target_ulong EA){ cpu_dump_EA(EA);}/*****************************************************************************//* Registers load and stores */void do_load_cr (void){ T0 = (env->crf[0] << 28) | (env->crf[1] << 24) | (env->crf[2] << 20) | (env->crf[3] << 16) | (env->crf[4] << 12) | (env->crf[5] << 8) | (env->crf[6] << 4) | (env->crf[7] << 0);}void do_store_cr (uint32_t mask){ int i, sh; for (i = 0, sh = 7; i < 8; i++, sh--) { if (mask & (1 << sh)) env->crf[i] = (T0 >> (sh * 4)) & 0xFUL; }}#if defined(TARGET_PPC64)void do_store_pri (int prio){ env->spr[SPR_PPR] &= ~0x001C000000000000ULL; env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50;}#endiftarget_ulong ppc_load_dump_spr (int sprn){ if (loglevel != 0) { fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n", sprn, sprn, env->spr[sprn]); } return env->spr[sprn];}void ppc_store_dump_spr (int sprn, target_ulong val){ if (loglevel != 0) { fprintf(logfile, "Write SPR %d %03x => " ADDRX " <= " ADDRX "\n", sprn, sprn, env->spr[sprn], val); } env->spr[sprn] = val;}/*****************************************************************************//* Fixed point operations helpers */void do_adde (void){ T2 = T0; T0 += T1 + xer_ca; if (likely(!((uint32_t)T0 < (uint32_t)T2 || (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) { xer_ca = 0; } else { xer_ca = 1; }}#if defined(TARGET_PPC64)void do_adde_64 (void){ T2 = T0; T0 += T1 + xer_ca; if (likely(!((uint64_t)T0 < (uint64_t)T2 || (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) { xer_ca = 0; } else { xer_ca = 1; }}#endifvoid do_addmeo (void){ T1 = T0; T0 += xer_ca + (-1); xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31; xer_so |= xer_ov; if (likely(T1 != 0)) xer_ca = 1; else xer_ca = 0;}#if defined(TARGET_PPC64)void do_addmeo_64 (void){ T1 = T0; T0 += xer_ca + (-1); xer_ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63; xer_so |= xer_ov; if (likely(T1 != 0)) xer_ca = 1; else xer_ca = 0;}#endifvoid do_divwo (void){ if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || (int32_t)T1 == 0))) { xer_ov = 0; T0 = (int32_t)T0 / (int32_t)T1; } else { xer_ov = 1; T0 = UINT32_MAX * ((uint32_t)T0 >> 31); } xer_so |= xer_ov;}#if defined(TARGET_PPC64)void do_divdo (void){ if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == (int64_t)-1LL) || (int64_t)T1 == 0))) { xer_ov = 0; T0 = (int64_t)T0 / (int64_t)T1; } else { xer_ov = 1; T0 = UINT64_MAX * ((uint64_t)T0 >> 63); } xer_so |= xer_ov;}#endifvoid do_divwuo (void){ if (likely((uint32_t)T1 != 0)) { xer_ov = 0; T0 = (uint32_t)T0 / (uint32_t)T1; } else { xer_ov = 1; xer_so = 1; T0 = 0; }}#if defined(TARGET_PPC64)void do_divduo (void){ if (likely((uint64_t)T1 != 0)) { xer_ov = 0; T0 = (uint64_t)T0 / (uint64_t)T1; } else { xer_ov = 1; xer_so = 1; T0 = 0; }}#endifvoid do_mullwo (void){ int64_t res = (int64_t)T0 * (int64_t)T1; if (likely((int32_t)res == res)) { xer_ov = 0; } else { xer_ov = 1; xer_so = 1; } T0 = (int32_t)res;}#if defined(TARGET_PPC64)void do_mulldo (void){ int64_t th; uint64_t tl; muls64(&tl, &th, T0, T1); T0 = (int64_t)tl; /* If th != 0 && th != -1, then we had an overflow */ if (likely((uint64_t)(th + 1) <= 1)) { xer_ov = 0; } else { xer_ov = 1; } xer_so |= xer_ov;}#endifvoid do_nego (void){ if (likely((int32_t)T0 != INT32_MIN)) { xer_ov = 0; T0 = -(int32_t)T0; } else { xer_ov = 1; xer_so = 1; }}#if defined(TARGET_PPC64)void do_nego_64 (void){ if (likely((int64_t)T0 != INT64_MIN)) { xer_ov = 0; T0 = -(int64_t)T0; } else { xer_ov = 1; xer_so = 1; }}#endifvoid do_subfe (void){ T0 = T1 + ~T0 + xer_ca; if (likely((uint32_t)T0 >= (uint32_t)T1 && (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) { xer_ca = 0; } else { xer_ca = 1; }}#if defined(TARGET_PPC64)void do_subfe_64 (void){ T0 = T1 + ~T0 + xer_ca; if (likely((uint64_t)T0 >= (uint64_t)T1 && (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) { xer_ca = 0; } else { xer_ca = 1; }}#endifvoid do_subfmeo (void){ T1 = T0; T0 = ~T0 + xer_ca - 1; xer_ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31; xer_so |= xer_ov; if (likely((uint32_t)T1 != UINT32_MAX)) xer_ca = 1; else xer_ca = 0;}#if defined(TARGET_PPC64)void do_subfmeo_64 (void){ T1 = T0; T0 = ~T0 + xer_ca - 1; xer_ov = ((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0)) >> 63; xer_so |= xer_ov; if (likely((uint64_t)T1 != UINT64_MAX)) xer_ca = 1; else xer_ca = 0;}#endifvoid do_subfzeo (void){ T1 = T0; T0 = ~T0 + xer_ca; xer_ov = (((uint32_t)~T1 ^ UINT32_MAX) & ((uint32_t)(~T1) ^ (uint32_t)T0)) >> 31; xer_so |= xer_ov; if (likely((uint32_t)T0 >= (uint32_t)~T1)) { xer_ca = 0; } else { xer_ca = 1; }}#if defined(TARGET_PPC64)void do_subfzeo_64 (void){ T1 = T0; T0 = ~T0 + xer_ca; xer_ov = (((uint64_t)~T1 ^ UINT64_MAX) & ((uint64_t)(~T1) ^ (uint64_t)T0)) >> 63; xer_so |= xer_ov; if (likely((uint64_t)T0 >= (uint64_t)~T1)) { xer_ca = 0; } else { xer_ca = 1; }}#endifvoid do_cntlzw (void){ T0 = clz32(T0);}#if defined(TARGET_PPC64)void do_cntlzd (void){ T0 = clz64(T0);}#endif/* shift right arithmetic helper */void do_sraw (void){ int32_t ret; if (likely(!(T1 & 0x20UL))) { if (likely((uint32_t)T1 != 0)) { ret = (int32_t)T0 >> (T1 & 0x1fUL); if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) { xer_ca = 0; } else { xer_ca = 1; } } else { ret = T0; xer_ca = 0; } } else { ret = UINT32_MAX * ((uint32_t)T0 >> 31); if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) { xer_ca = 0; } else { xer_ca = 1; } } T0 = ret;}#if defined(TARGET_PPC64)void do_srad (void){ int64_t ret; if (likely(!(T1 & 0x40UL))) { if (likely((uint64_t)T1 != 0)) { ret = (int64_t)T0 >> (T1 & 0x3FUL); if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) { xer_ca = 0; } else { xer_ca = 1; } } else { ret = T0; xer_ca = 0; } } else { ret = UINT64_MAX * ((uint64_t)T0 >> 63); if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) { xer_ca = 0; } else { xer_ca = 1; } } T0 = ret;}#endifvoid do_popcntb (void){ uint32_t ret; int i; ret = 0; for (i = 0; i < 32; i += 8) ret |= ctpop8((T0 >> i) & 0xFF) << i; T0 = ret;}#if defined(TARGET_PPC64)void do_popcntb_64 (void){ uint64_t ret; int i; ret = 0; for (i = 0; i < 64; i += 8) ret |= ctpop8((T0 >> i) & 0xFF) << i; T0 = ret;}#endif/*****************************************************************************//* Floating point operations helpers */static always_inline int fpisneg (float64 f){ union { float64 f; uint64_t u; } u; u.f = f; return u.u >> 63 != 0;}static always_inline int isden (float f){ union { float64 f; uint64_t u; } u; u.f = f; return ((u.u >> 52) & 0x7FF) == 0;}static always_inline int iszero (float64 f){ union { float64 f; uint64_t u; } u; u.f = f; return (u.u & ~0x8000000000000000ULL) == 0;}static always_inline int isinfinity (float64 f){ union { float64 f; uint64_t u; } u; u.f = f; return ((u.u >> 52) & 0x7FF) == 0x7FF && (u.u & 0x000FFFFFFFFFFFFFULL) == 0;}void do_compute_fprf (int set_fprf){ int isneg; isneg = fpisneg(FT0); if (unlikely(float64_is_nan(FT0))) { if (float64_is_signaling_nan(FT0)) { /* Signaling NaN: flags are undefined */ T0 = 0x00; } else { /* Quiet NaN */ T0 = 0x11; } } else if (unlikely(isinfinity(FT0))) { /* +/- infinity */ if (isneg) T0 = 0x09; else T0 = 0x05; } else { if (iszero(FT0)) { /* +/- zero */ if (isneg) T0 = 0x12;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -