Browse Source
- moved mmu to arm/interpreter folder
- moved mmu to arm/interpreter folder
- added initial VFP code from skyeyepull/15/merge
16 changed files with 8791 additions and 1 deletions
-
6src/core/CMakeLists.txt
-
0src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
-
0src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h
-
0src/core/arm/interpreter/mmu/cache.h
-
0src/core/arm/interpreter/mmu/rb.h
-
0src/core/arm/interpreter/mmu/tlb.h
-
0src/core/arm/interpreter/mmu/wb.h
-
84src/core/arm/interpreter/vfp/asm_vfp.h
-
357src/core/arm/interpreter/vfp/vfp.cpp
-
111src/core/arm/interpreter/vfp/vfp.h
-
541src/core/arm/interpreter/vfp/vfp_helper.h
-
1262src/core/arm/interpreter/vfp/vfpdouble.cpp
-
5123src/core/arm/interpreter/vfp/vfpinstr.cpp
-
1277src/core/arm/interpreter/vfp/vfpsingle.cpp
-
7src/core/core.vcxproj
-
24src/core/core.vcxproj.filters
@ -0,0 +1,84 @@ |
|||
/* |
|||
* arch/arm/include/asm/vfp.h |
|||
* |
|||
* VFP register definitions. |
|||
* First, the standard VFP set. |
|||
*/ |
|||
|
|||
#define FPSID cr0 |
|||
#define FPSCR cr1 |
|||
#define MVFR1 cr6 |
|||
#define MVFR0 cr7 |
|||
#define FPEXC cr8 |
|||
#define FPINST cr9 |
|||
#define FPINST2 cr10 |
|||
|
|||
/* FPSID bits */ |
|||
#define FPSID_IMPLEMENTER_BIT (24) |
|||
#define FPSID_IMPLEMENTER_MASK (0xff << FPSID_IMPLEMENTER_BIT) |
|||
#define FPSID_SOFTWARE (1<<23) |
|||
#define FPSID_FORMAT_BIT (21) |
|||
#define FPSID_FORMAT_MASK (0x3 << FPSID_FORMAT_BIT) |
|||
#define FPSID_NODOUBLE (1<<20) |
|||
#define FPSID_ARCH_BIT (16) |
|||
#define FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) |
|||
#define FPSID_PART_BIT (8) |
|||
#define FPSID_PART_MASK (0xFF << FPSID_PART_BIT) |
|||
#define FPSID_VARIANT_BIT (4) |
|||
#define FPSID_VARIANT_MASK (0xF << FPSID_VARIANT_BIT) |
|||
#define FPSID_REV_BIT (0) |
|||
#define FPSID_REV_MASK (0xF << FPSID_REV_BIT) |
|||
|
|||
/* FPEXC bits */ |
|||
#define FPEXC_EX (1 << 31) |
|||
#define FPEXC_EN (1 << 30) |
|||
#define FPEXC_DEX (1 << 29) |
|||
#define FPEXC_FP2V (1 << 28) |
|||
#define FPEXC_VV (1 << 27) |
|||
#define FPEXC_TFV (1 << 26) |
|||
#define FPEXC_LENGTH_BIT (8) |
|||
#define FPEXC_LENGTH_MASK (7 << FPEXC_LENGTH_BIT) |
|||
#define FPEXC_IDF (1 << 7) |
|||
#define FPEXC_IXF (1 << 4) |
|||
#define FPEXC_UFF (1 << 3) |
|||
#define FPEXC_OFF (1 << 2) |
|||
#define FPEXC_DZF (1 << 1) |
|||
#define FPEXC_IOF (1 << 0) |
|||
#define FPEXC_TRAP_MASK (FPEXC_IDF|FPEXC_IXF|FPEXC_UFF|FPEXC_OFF|FPEXC_DZF|FPEXC_IOF) |
|||
|
|||
/* FPSCR bits */ |
|||
#define FPSCR_DEFAULT_NAN (1<<25) |
|||
#define FPSCR_FLUSHTOZERO (1<<24) |
|||
#define FPSCR_ROUND_NEAREST (0<<22) |
|||
#define FPSCR_ROUND_PLUSINF (1<<22) |
|||
#define FPSCR_ROUND_MINUSINF (2<<22) |
|||
#define FPSCR_ROUND_TOZERO (3<<22) |
|||
#define FPSCR_RMODE_BIT (22) |
|||
#define FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT) |
|||
#define FPSCR_STRIDE_BIT (20) |
|||
#define FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT) |
|||
#define FPSCR_LENGTH_BIT (16) |
|||
#define FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT) |
|||
#define FPSCR_IOE (1<<8) |
|||
#define FPSCR_DZE (1<<9) |
|||
#define FPSCR_OFE (1<<10) |
|||
#define FPSCR_UFE (1<<11) |
|||
#define FPSCR_IXE (1<<12) |
|||
#define FPSCR_IDE (1<<15) |
|||
#define FPSCR_IOC (1<<0) |
|||
#define FPSCR_DZC (1<<1) |
|||
#define FPSCR_OFC (1<<2) |
|||
#define FPSCR_UFC (1<<3) |
|||
#define FPSCR_IXC (1<<4) |
|||
#define FPSCR_IDC (1<<7) |
|||
|
|||
/* MVFR0 bits */ |
|||
#define MVFR0_A_SIMD_BIT (0) |
|||
#define MVFR0_A_SIMD_MASK (0xf << MVFR0_A_SIMD_BIT) |
|||
|
|||
/* Bit patterns for decoding the packaged operation descriptors */ |
|||
#define VFPOPDESC_LENGTH_BIT (9) |
|||
#define VFPOPDESC_LENGTH_MASK (0x07 << VFPOPDESC_LENGTH_BIT) |
|||
#define VFPOPDESC_UNUSED_BIT (24) |
|||
#define VFPOPDESC_UNUSED_MASK (0xFF << VFPOPDESC_UNUSED_BIT) |
|||
#define VFPOPDESC_OPDESC_MASK (~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK)) |
|||
@ -0,0 +1,357 @@ |
|||
/*
|
|||
armvfp.c - ARM VFPv3 emulation unit |
|||
Copyright (C) 2003 Skyeye Develop Group |
|||
for help please send mail to <skyeye-developer@lists.gro.clinux.org> |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program 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 General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
*/ |
|||
|
|||
/* Note: this file handles interface with arm core and vfp registers */ |
|||
|
|||
/* Opens debug for classic interpreter only */ |
|||
//#define DEBUG
|
|||
|
|||
#include "common/common.h"
|
|||
|
|||
#include "core/arm/interpreter/armdefs.h"
|
|||
#include "core/arm/interpreter/vfp/vfp.h"
|
|||
|
|||
//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */
|
|||
|
|||
unsigned |
|||
VFPInit (ARMul_State *state) |
|||
{ |
|||
state->VFP[VFP_OFFSET(VFP_FPSID)] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 | |
|||
VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION; |
|||
state->VFP[VFP_OFFSET(VFP_FPEXC)] = 0; |
|||
state->VFP[VFP_OFFSET(VFP_FPSCR)] = 0; |
|||
|
|||
//persistent_state = state;
|
|||
/* Reset only specify VFP_FPEXC_EN = '0' */ |
|||
|
|||
return No_exp; |
|||
} |
|||
|
|||
unsigned |
|||
VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value) |
|||
{ |
|||
/* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ |
|||
int CoProc = BITS (8, 11); /* 10 or 11 */ |
|||
int OPC_1 = BITS (21, 23); |
|||
int Rt = BITS (12, 15); |
|||
int CRn = BITS (16, 19); |
|||
int CRm = BITS (0, 3); |
|||
int OPC_2 = BITS (5, 7); |
|||
|
|||
/* TODO check access permission */ |
|||
|
|||
/* CRn/opc1 CRm/opc2 */ |
|||
|
|||
if (CoProc == 10 || CoProc == 11) |
|||
{ |
|||
#define VFP_MRC_TRANS
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_MRC_TRANS
|
|||
} |
|||
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", |
|||
instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); |
|||
|
|||
return ARMul_CANT; |
|||
} |
|||
|
|||
unsigned |
|||
VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value) |
|||
{ |
|||
/* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ |
|||
int CoProc = BITS (8, 11); /* 10 or 11 */ |
|||
int OPC_1 = BITS (21, 23); |
|||
int Rt = BITS (12, 15); |
|||
int CRn = BITS (16, 19); |
|||
int CRm = BITS (0, 3); |
|||
int OPC_2 = BITS (5, 7); |
|||
|
|||
/* TODO check access permission */ |
|||
|
|||
/* CRn/opc1 CRm/opc2 */ |
|||
if (CoProc == 10 || CoProc == 11) |
|||
{ |
|||
#define VFP_MCR_TRANS
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_MCR_TRANS
|
|||
} |
|||
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", |
|||
instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); |
|||
|
|||
return ARMul_CANT; |
|||
} |
|||
|
|||
unsigned |
|||
VFPMRRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value1, ARMword * value2) |
|||
{ |
|||
/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ |
|||
int CoProc = BITS (8, 11); /* 10 or 11 */ |
|||
int OPC_1 = BITS (4, 7); |
|||
int Rt = BITS (12, 15); |
|||
int Rt2 = BITS (16, 19); |
|||
int CRm = BITS (0, 3); |
|||
|
|||
if (CoProc == 10 || CoProc == 11) |
|||
{ |
|||
#define VFP_MRRC_TRANS
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_MRRC_TRANS
|
|||
} |
|||
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", |
|||
instr, CoProc, OPC_1, Rt, Rt2, CRm); |
|||
|
|||
return ARMul_CANT; |
|||
} |
|||
|
|||
unsigned |
|||
VFPMCRR (ARMul_State * state, unsigned type, ARMword instr, ARMword value1, ARMword value2) |
|||
{ |
|||
/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ |
|||
int CoProc = BITS (8, 11); /* 10 or 11 */ |
|||
int OPC_1 = BITS (4, 7); |
|||
int Rt = BITS (12, 15); |
|||
int Rt2 = BITS (16, 19); |
|||
int CRm = BITS (0, 3); |
|||
|
|||
/* TODO check access permission */ |
|||
|
|||
/* CRn/opc1 CRm/opc2 */ |
|||
|
|||
if (CoProc == 11 || CoProc == 10) |
|||
{ |
|||
#define VFP_MCRR_TRANS
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_MCRR_TRANS
|
|||
} |
|||
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", |
|||
instr, CoProc, OPC_1, Rt, Rt2, CRm); |
|||
|
|||
return ARMul_CANT; |
|||
} |
|||
|
|||
unsigned |
|||
VFPSTC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value) |
|||
{ |
|||
/* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */ |
|||
int CoProc = BITS (8, 11); /* 10 or 11 */ |
|||
int CRd = BITS (12, 15); |
|||
int Rn = BITS (16, 19); |
|||
int imm8 = BITS (0, 7); |
|||
int P = BIT(24); |
|||
int U = BIT(23); |
|||
int D = BIT(22); |
|||
int W = BIT(21); |
|||
|
|||
/* TODO check access permission */ |
|||
|
|||
/* VSTM */ |
|||
if ( (P|U|D|W) == 0 ) |
|||
{ |
|||
DEBUG_LOG(ARM11, "In %s, UNDEFINED\n", __FUNCTION__); exit(-1); |
|||
} |
|||
if (CoProc == 10 || CoProc == 11) |
|||
{ |
|||
#if 1
|
|||
if (P == 0 && U == 0 && W == 0) |
|||
{ |
|||
DEBUG_LOG(ARM11, "VSTM Related encodings\n"); exit(-1); |
|||
} |
|||
if (P == U && W == 1) |
|||
{ |
|||
DEBUG_LOG(ARM11, "UNDEFINED\n"); exit(-1); |
|||
} |
|||
#endif
|
|||
|
|||
#define VFP_STC_TRANS
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_STC_TRANS
|
|||
} |
|||
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", |
|||
instr, CoProc, CRd, Rn, imm8, P, U, D, W); |
|||
|
|||
return ARMul_CANT; |
|||
} |
|||
|
|||
unsigned |
|||
VFPLDC (ARMul_State * state, unsigned type, ARMword instr, ARMword value) |
|||
{ |
|||
/* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */ |
|||
int CoProc = BITS (8, 11); /* 10 or 11 */ |
|||
int CRd = BITS (12, 15); |
|||
int Rn = BITS (16, 19); |
|||
int imm8 = BITS (0, 7); |
|||
int P = BIT(24); |
|||
int U = BIT(23); |
|||
int D = BIT(22); |
|||
int W = BIT(21); |
|||
|
|||
/* TODO check access permission */ |
|||
|
|||
if ( (P|U|D|W) == 0 ) |
|||
{ |
|||
DEBUG_LOG(ARM11, "In %s, UNDEFINED\n", __FUNCTION__); exit(-1); |
|||
} |
|||
if (CoProc == 10 || CoProc == 11) |
|||
{ |
|||
#define VFP_LDC_TRANS
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_LDC_TRANS
|
|||
} |
|||
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", |
|||
instr, CoProc, CRd, Rn, imm8, P, U, D, W); |
|||
|
|||
return ARMul_CANT; |
|||
} |
|||
|
|||
unsigned |
|||
VFPCDP (ARMul_State * state, unsigned type, ARMword instr) |
|||
{ |
|||
/* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */ |
|||
int CoProc = BITS (8, 11); /* 10 or 11 */ |
|||
int OPC_1 = BITS (20, 23); |
|||
int CRd = BITS (12, 15); |
|||
int CRn = BITS (16, 19); |
|||
int CRm = BITS (0, 3); |
|||
int OPC_2 = BITS (5, 7); |
|||
|
|||
/* TODO check access permission */ |
|||
|
|||
/* CRn/opc1 CRm/opc2 */ |
|||
|
|||
if (CoProc == 10 || CoProc == 11) |
|||
{ |
|||
#define VFP_CDP_TRANS
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_CDP_TRANS
|
|||
|
|||
int exceptions = 0; |
|||
if (CoProc == 10) |
|||
exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); |
|||
else |
|||
exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); |
|||
|
|||
vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); |
|||
|
|||
return ARMul_DONE; |
|||
} |
|||
DEBUG_LOG(ARM11, "Can't identify %x\n", instr); |
|||
return ARMul_CANT; |
|||
} |
|||
|
|||
|
|||
/* ----------- MRC ------------ */ |
|||
#define VFP_MRC_IMPL
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_MRC_IMPL
|
|||
|
|||
#define VFP_MRRC_IMPL
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_MRRC_IMPL
|
|||
|
|||
|
|||
/* ----------- MCR ------------ */ |
|||
#define VFP_MCR_IMPL
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_MCR_IMPL
|
|||
|
|||
#define VFP_MCRR_IMPL
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_MCRR_IMPL
|
|||
|
|||
/* Memory operation are not inlined, as old Interpreter and Fast interpreter
|
|||
don't have the same memory operation interface. |
|||
Old interpreter framework does one access to coprocessor per data, and |
|||
handles already data write, as well as address computation, |
|||
which is not the case for Fast interpreter. Therefore, implementation |
|||
of vfp instructions in old interpreter and fast interpreter are separate. */ |
|||
|
|||
/* ----------- STC ------------ */ |
|||
#define VFP_STC_IMPL
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_STC_IMPL
|
|||
|
|||
|
|||
/* ----------- LDC ------------ */ |
|||
#define VFP_LDC_IMPL
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_LDC_IMPL
|
|||
|
|||
|
|||
/* ----------- CDP ------------ */ |
|||
#define VFP_CDP_IMPL
|
|||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
|||
#undef VFP_CDP_IMPL
|
|||
|
|||
/* Miscellaneous functions */ |
|||
int32_t vfp_get_float(arm_core_t* state, unsigned int reg) |
|||
{ |
|||
DBG("VFP get float: s%d=[%08x]\n", reg, state->ExtReg[reg]); |
|||
return state->ExtReg[reg]; |
|||
} |
|||
|
|||
void vfp_put_float(arm_core_t* state, int32_t val, unsigned int reg) |
|||
{ |
|||
DBG("VFP put float: s%d <= [%08x]\n", reg, val); |
|||
state->ExtReg[reg] = val; |
|||
} |
|||
|
|||
uint64_t vfp_get_double(arm_core_t* state, unsigned int reg) |
|||
{ |
|||
uint64_t result; |
|||
result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2]; |
|||
DBG("VFP get double: s[%d-%d]=[%016llx]\n", reg*2+1, reg*2, result); |
|||
return result; |
|||
} |
|||
|
|||
void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg) |
|||
{ |
|||
DBG("VFP put double: s[%d-%d] <= [%08x-%08x]\n", reg*2+1, reg*2, (uint32_t) (val>>32), (uint32_t) (val & 0xffffffff)); |
|||
state->ExtReg[reg*2] = (uint32_t) (val & 0xffffffff); |
|||
state->ExtReg[reg*2+1] = (uint32_t) (val>>32); |
|||
} |
|||
|
|||
|
|||
|
|||
/*
|
|||
* Process bitmask of exception conditions. (from vfpmodule.c) |
|||
*/ |
|||
void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) |
|||
{ |
|||
int si_code = 0; |
|||
|
|||
vfpdebug("VFP: raising exceptions %08x\n", exceptions); |
|||
|
|||
if (exceptions == VFP_EXCEPTION_ERROR) { |
|||
DEBUG_LOG(ARM11, "unhandled bounce %x\n", inst); |
|||
exit(-1); |
|||
return; |
|||
} |
|||
|
|||
/*
|
|||
* If any of the status flags are set, update the FPSCR. |
|||
* Comparison instructions always return at least one of |
|||
* these flags set. |
|||
*/ |
|||
if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) |
|||
fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V); |
|||
|
|||
fpscr |= exceptions; |
|||
|
|||
state->VFP[VFP_OFFSET(VFP_FPSCR)] = fpscr; |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
/* |
|||
vfp/vfp.h - ARM VFPv3 emulation unit - vfp interface |
|||
Copyright (C) 2003 Skyeye Develop Group |
|||
for help please send mail to <skyeye-developer@lists.gro.clinux.org> |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program 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 General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
*/ |
|||
|
|||
#ifndef __VFP_H__ |
|||
#define __VFP_H__ |
|||
|
|||
#define DBG(msg) DEBUG_LOG(ARM11, msg) |
|||
|
|||
#define vfpdebug //printf |
|||
|
|||
#include "core/arm/interpreter/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */ |
|||
|
|||
unsigned VFPInit (ARMul_State *state); |
|||
unsigned VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value); |
|||
unsigned VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value); |
|||
unsigned VFPMRRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value1, ARMword * value2); |
|||
unsigned VFPMCRR (ARMul_State * state, unsigned type, ARMword instr, ARMword value1, ARMword value2); |
|||
unsigned VFPSTC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value); |
|||
unsigned VFPLDC (ARMul_State * state, unsigned type, ARMword instr, ARMword value); |
|||
unsigned VFPCDP (ARMul_State * state, unsigned type, ARMword instr); |
|||
|
|||
/* FPSID Information */ |
|||
#define VFP_FPSID_IMPLMEN 0 /* should be the same as cp15 0 c0 0*/ |
|||
#define VFP_FPSID_SW 0 |
|||
#define VFP_FPSID_SUBARCH 0x2 /* VFP version. Current is v3 (not strict) */ |
|||
#define VFP_FPSID_PARTNUM 0x1 |
|||
#define VFP_FPSID_VARIANT 0x1 |
|||
#define VFP_FPSID_REVISION 0x1 |
|||
|
|||
/* FPEXC Flags */ |
|||
#define VFP_FPEXC_EX 1<<31 |
|||
#define VFP_FPEXC_EN 1<<30 |
|||
|
|||
/* FPSCR Flags */ |
|||
#define VFP_FPSCR_NFLAG 1<<31 |
|||
#define VFP_FPSCR_ZFLAG 1<<30 |
|||
#define VFP_FPSCR_CFLAG 1<<29 |
|||
#define VFP_FPSCR_VFLAG 1<<28 |
|||
|
|||
#define VFP_FPSCR_AHP 1<<26 /* Alternative Half Precision */ |
|||
#define VFP_FPSCR_DN 1<<25 /* Default NaN */ |
|||
#define VFP_FPSCR_FZ 1<<24 /* Flush-to-zero */ |
|||
#define VFP_FPSCR_RMODE 3<<22 /* Rounding Mode */ |
|||
#define VFP_FPSCR_STRIDE 3<<20 /* Stride (vector) */ |
|||
#define VFP_FPSCR_LEN 7<<16 /* Stride (vector) */ |
|||
|
|||
#define VFP_FPSCR_IDE 1<<15 /* Input Denormal exc */ |
|||
#define VFP_FPSCR_IXE 1<<12 /* Inexact exc */ |
|||
#define VFP_FPSCR_UFE 1<<11 /* Undeflow exc */ |
|||
#define VFP_FPSCR_OFE 1<<10 /* Overflow exc */ |
|||
#define VFP_FPSCR_DZE 1<<9 /* Division by Zero exc */ |
|||
#define VFP_FPSCR_IOE 1<<8 /* Invalid Operation exc */ |
|||
|
|||
#define VFP_FPSCR_IDC 1<<7 /* Input Denormal cum exc */ |
|||
#define VFP_FPSCR_IXC 1<<4 /* Inexact cum exc */ |
|||
#define VFP_FPSCR_UFC 1<<3 /* Undeflow cum exc */ |
|||
#define VFP_FPSCR_OFC 1<<2 /* Overflow cum exc */ |
|||
#define VFP_FPSCR_DZC 1<<1 /* Division by Zero cum exc */ |
|||
#define VFP_FPSCR_IOC 1<<0 /* Invalid Operation cum exc */ |
|||
|
|||
/* Inline instructions. Note: Used in a cpp file as well */ |
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
int32_t vfp_get_float(ARMul_State * state, unsigned int reg); |
|||
void vfp_put_float(ARMul_State * state, int32_t val, unsigned int reg); |
|||
uint64_t vfp_get_double(ARMul_State * state, unsigned int reg); |
|||
void vfp_put_double(ARMul_State * state, uint64_t val, unsigned int reg); |
|||
void vfp_raise_exceptions(ARMul_State * state, uint32_t exceptions, uint32_t inst, uint32_t fpscr); |
|||
extern uint32_t vfp_single_cpdo(ARMul_State * state, uint32_t inst, uint32_t fpscr); |
|||
extern uint32_t vfp_double_cpdo(ARMul_State * state, uint32_t inst, uint32_t fpscr); |
|||
|
|||
/* MRC */ |
|||
inline void VMRS(ARMul_State * state, ARMword reg, ARMword Rt, ARMword *value); |
|||
inline void VMOVBRS(ARMul_State * state, ARMword to_arm, ARMword t, ARMword n, ARMword *value); |
|||
inline void VMOVBRRD(ARMul_State * state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword *value1, ARMword *value2); |
|||
inline void VMOVI(ARMul_State * state, ARMword single, ARMword d, ARMword imm); |
|||
inline void VMOVR(ARMul_State * state, ARMword single, ARMword d, ARMword imm); |
|||
/* MCR */ |
|||
inline void VMSR(ARMul_State * state, ARMword reg, ARMword Rt); |
|||
/* STC */ |
|||
inline int VSTM(ARMul_State * state, int type, ARMword instr, ARMword* value); |
|||
inline int VPUSH(ARMul_State * state, int type, ARMword instr, ARMword* value); |
|||
inline int VSTR(ARMul_State * state, int type, ARMword instr, ARMword* value); |
|||
/* LDC */ |
|||
inline int VLDM(ARMul_State * state, int type, ARMword instr, ARMword value); |
|||
inline int VPOP(ARMul_State * state, int type, ARMword instr, ARMword value); |
|||
inline int VLDR(ARMul_State * state, int type, ARMword instr, ARMword value); |
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif |
|||
@ -0,0 +1,541 @@ |
|||
/* |
|||
vfp/vfp.h - ARM VFPv3 emulation unit - SoftFloat lib helper |
|||
Copyright (C) 2003 Skyeye Develop Group |
|||
for help please send mail to <skyeye-developer@lists.gro.clinux.org> |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program 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 General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
*/ |
|||
|
|||
/* |
|||
* The following code is derivative from Linux Android kernel vfp |
|||
* floating point support. |
|||
* |
|||
* Copyright (C) 2004 ARM Limited. |
|||
* Written by Deep Blue Solutions Limited. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
#ifndef __VFP_HELPER_H__ |
|||
#define __VFP_HELPER_H__ |
|||
|
|||
/* Custom edit */ |
|||
|
|||
#include <stdint.h> |
|||
#include <stdio.h> |
|||
|
|||
#include "core/arm/interpreter/armdefs.h" |
|||
|
|||
#define u16 uint16_t |
|||
#define u32 uint32_t |
|||
#define u64 uint64_t |
|||
#define s16 int16_t |
|||
#define s32 int32_t |
|||
#define s64 int64_t |
|||
|
|||
#define pr_info //printf |
|||
#define pr_debug //printf |
|||
|
|||
static u32 fls(int x); |
|||
#define do_div(n, base) {n/=base;} |
|||
|
|||
/* From vfpinstr.h */ |
|||
|
|||
#define INST_CPRTDO(inst) (((inst) & 0x0f000000) == 0x0e000000) |
|||
#define INST_CPRT(inst) ((inst) & (1 << 4)) |
|||
#define INST_CPRT_L(inst) ((inst) & (1 << 20)) |
|||
#define INST_CPRT_Rd(inst) (((inst) & (15 << 12)) >> 12) |
|||
#define INST_CPRT_OP(inst) (((inst) >> 21) & 7) |
|||
#define INST_CPNUM(inst) ((inst) & 0xf00) |
|||
#define CPNUM(cp) ((cp) << 8) |
|||
|
|||
#define FOP_MASK (0x00b00040) |
|||
#define FOP_FMAC (0x00000000) |
|||
#define FOP_FNMAC (0x00000040) |
|||
#define FOP_FMSC (0x00100000) |
|||
#define FOP_FNMSC (0x00100040) |
|||
#define FOP_FMUL (0x00200000) |
|||
#define FOP_FNMUL (0x00200040) |
|||
#define FOP_FADD (0x00300000) |
|||
#define FOP_FSUB (0x00300040) |
|||
#define FOP_FDIV (0x00800000) |
|||
#define FOP_EXT (0x00b00040) |
|||
|
|||
#define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4) |
|||
|
|||
#define FEXT_MASK (0x000f0080) |
|||
#define FEXT_FCPY (0x00000000) |
|||
#define FEXT_FABS (0x00000080) |
|||
#define FEXT_FNEG (0x00010000) |
|||
#define FEXT_FSQRT (0x00010080) |
|||
#define FEXT_FCMP (0x00040000) |
|||
#define FEXT_FCMPE (0x00040080) |
|||
#define FEXT_FCMPZ (0x00050000) |
|||
#define FEXT_FCMPEZ (0x00050080) |
|||
#define FEXT_FCVT (0x00070080) |
|||
#define FEXT_FUITO (0x00080000) |
|||
#define FEXT_FSITO (0x00080080) |
|||
#define FEXT_FTOUI (0x000c0000) |
|||
#define FEXT_FTOUIZ (0x000c0080) |
|||
#define FEXT_FTOSI (0x000d0000) |
|||
#define FEXT_FTOSIZ (0x000d0080) |
|||
|
|||
#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) |
|||
|
|||
#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22) |
|||
#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18) |
|||
#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5) |
|||
#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1) |
|||
#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) |
|||
#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3) |
|||
|
|||
#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00) |
|||
|
|||
#define FPSCR_N (1 << 31) |
|||
#define FPSCR_Z (1 << 30) |
|||
#define FPSCR_C (1 << 29) |
|||
#define FPSCR_V (1 << 28) |
|||
|
|||
/* -------------- */ |
|||
|
|||
/* From asm/include/vfp.h */ |
|||
|
|||
/* FPSCR bits */ |
|||
#define FPSCR_DEFAULT_NAN (1<<25) |
|||
#define FPSCR_FLUSHTOZERO (1<<24) |
|||
#define FPSCR_ROUND_NEAREST (0<<22) |
|||
#define FPSCR_ROUND_PLUSINF (1<<22) |
|||
#define FPSCR_ROUND_MINUSINF (2<<22) |
|||
#define FPSCR_ROUND_TOZERO (3<<22) |
|||
#define FPSCR_RMODE_BIT (22) |
|||
#define FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT) |
|||
#define FPSCR_STRIDE_BIT (20) |
|||
#define FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT) |
|||
#define FPSCR_LENGTH_BIT (16) |
|||
#define FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT) |
|||
#define FPSCR_IOE (1<<8) |
|||
#define FPSCR_DZE (1<<9) |
|||
#define FPSCR_OFE (1<<10) |
|||
#define FPSCR_UFE (1<<11) |
|||
#define FPSCR_IXE (1<<12) |
|||
#define FPSCR_IDE (1<<15) |
|||
#define FPSCR_IOC (1<<0) |
|||
#define FPSCR_DZC (1<<1) |
|||
#define FPSCR_OFC (1<<2) |
|||
#define FPSCR_UFC (1<<3) |
|||
#define FPSCR_IXC (1<<4) |
|||
#define FPSCR_IDC (1<<7) |
|||
|
|||
/* ---------------- */ |
|||
|
|||
static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) |
|||
{ |
|||
if (shift) { |
|||
if (shift < 32) |
|||
val = val >> shift | ((val << (32 - shift)) != 0); |
|||
else |
|||
val = val != 0; |
|||
} |
|||
return val; |
|||
} |
|||
|
|||
static inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) |
|||
{ |
|||
if (shift) { |
|||
if (shift < 64) |
|||
val = val >> shift | ((val << (64 - shift)) != 0); |
|||
else |
|||
val = val != 0; |
|||
} |
|||
return val; |
|||
} |
|||
|
|||
static inline u32 vfp_hi64to32jamming(u64 val) |
|||
{ |
|||
u32 v; |
|||
u32 highval = val >> 32; |
|||
u32 lowval = val & 0xffffffff; |
|||
|
|||
if (lowval >= 1) |
|||
v = highval | 1; |
|||
else |
|||
v = highval; |
|||
|
|||
return v; |
|||
} |
|||
|
|||
static inline void add128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml) |
|||
{ |
|||
*resl = nl + ml; |
|||
*resh = nh + mh; |
|||
if (*resl < nl) |
|||
*resh += 1; |
|||
} |
|||
|
|||
static inline void sub128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml) |
|||
{ |
|||
*resl = nl - ml; |
|||
*resh = nh - mh; |
|||
if (*resl > nl) |
|||
*resh -= 1; |
|||
} |
|||
|
|||
static inline void mul64to128(u64 *resh, u64 *resl, u64 n, u64 m) |
|||
{ |
|||
u32 nh, nl, mh, ml; |
|||
u64 rh, rma, rmb, rl; |
|||
|
|||
nl = n; |
|||
ml = m; |
|||
rl = (u64)nl * ml; |
|||
|
|||
nh = n >> 32; |
|||
rma = (u64)nh * ml; |
|||
|
|||
mh = m >> 32; |
|||
rmb = (u64)nl * mh; |
|||
rma += rmb; |
|||
|
|||
rh = (u64)nh * mh; |
|||
rh += ((u64)(rma < rmb) << 32) + (rma >> 32); |
|||
|
|||
rma <<= 32; |
|||
rl += rma; |
|||
rh += (rl < rma); |
|||
|
|||
*resl = rl; |
|||
*resh = rh; |
|||
} |
|||
|
|||
static inline void shift64left(u64 *resh, u64 *resl, u64 n) |
|||
{ |
|||
*resh = n >> 63; |
|||
*resl = n << 1; |
|||
} |
|||
|
|||
static inline u64 vfp_hi64multiply64(u64 n, u64 m) |
|||
{ |
|||
u64 rh, rl; |
|||
mul64to128(&rh, &rl, n, m); |
|||
return rh | (rl != 0); |
|||
} |
|||
|
|||
static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) |
|||
{ |
|||
u64 mh, ml, remh, reml, termh, terml, z; |
|||
|
|||
if (nh >= m) |
|||
return ~0ULL; |
|||
mh = m >> 32; |
|||
if (mh << 32 <= nh) { |
|||
z = 0xffffffff00000000ULL; |
|||
} else { |
|||
z = nh; |
|||
do_div(z, mh); |
|||
z <<= 32; |
|||
} |
|||
mul64to128(&termh, &terml, m, z); |
|||
sub128(&remh, &reml, nh, nl, termh, terml); |
|||
ml = m << 32; |
|||
while ((s64)remh < 0) { |
|||
z -= 0x100000000ULL; |
|||
add128(&remh, &reml, remh, reml, mh, ml); |
|||
} |
|||
remh = (remh << 32) | (reml >> 32); |
|||
if (mh << 32 <= remh) { |
|||
z |= 0xffffffff; |
|||
} else { |
|||
do_div(remh, mh); |
|||
z |= remh; |
|||
} |
|||
return z; |
|||
} |
|||
|
|||
/* |
|||
* Operations on unpacked elements |
|||
*/ |
|||
#define vfp_sign_negate(sign) (sign ^ 0x8000) |
|||
|
|||
/* |
|||
* Single-precision |
|||
*/ |
|||
struct vfp_single { |
|||
s16 exponent; |
|||
u16 sign; |
|||
u32 significand; |
|||
}; |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
extern s32 vfp_get_float(ARMul_State * state, unsigned int reg); |
|||
extern void vfp_put_float(ARMul_State * state, s32 val, unsigned int reg); |
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
/* |
|||
* VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa |
|||
* VFP_SINGLE_EXPONENT_BITS - number of bits in the exponent |
|||
* VFP_SINGLE_LOW_BITS - number of low bits in the unpacked significand |
|||
* which are not propagated to the float upon packing. |
|||
*/ |
|||
#define VFP_SINGLE_MANTISSA_BITS (23) |
|||
#define VFP_SINGLE_EXPONENT_BITS (8) |
|||
#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2) |
|||
#define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1) |
|||
|
|||
/* |
|||
* The bit in an unpacked float which indicates that it is a quiet NaN |
|||
*/ |
|||
#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS)) |
|||
|
|||
/* |
|||
* Operations on packed single-precision numbers |
|||
*/ |
|||
#define vfp_single_packed_sign(v) ((v) & 0x80000000) |
|||
#define vfp_single_packed_negate(v) ((v) ^ 0x80000000) |
|||
#define vfp_single_packed_abs(v) ((v) & ~0x80000000) |
|||
#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1)) |
|||
#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1)) |
|||
|
|||
/* |
|||
* Unpack a single-precision float. Note that this returns the magnitude |
|||
* of the single-precision float mantissa with the 1. if necessary, |
|||
* aligned to bit 30. |
|||
*/ |
|||
static inline void vfp_single_unpack(struct vfp_single *s, s32 val) |
|||
{ |
|||
u32 significand; |
|||
|
|||
s->sign = vfp_single_packed_sign(val) >> 16, |
|||
s->exponent = vfp_single_packed_exponent(val); |
|||
|
|||
significand = (u32) val; |
|||
significand = (significand << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2; |
|||
if (s->exponent && s->exponent != 255) |
|||
significand |= 0x40000000; |
|||
s->significand = significand; |
|||
} |
|||
|
|||
/* |
|||
* Re-pack a single-precision float. This assumes that the float is |
|||
* already normalised such that the MSB is bit 30, _not_ bit 31. |
|||
*/ |
|||
static inline s32 vfp_single_pack(struct vfp_single *s) |
|||
{ |
|||
u32 val; |
|||
val = (s->sign << 16) + |
|||
(s->exponent << VFP_SINGLE_MANTISSA_BITS) + |
|||
(s->significand >> VFP_SINGLE_LOW_BITS); |
|||
return (s32)val; |
|||
} |
|||
|
|||
#define VFP_NUMBER (1<<0) |
|||
#define VFP_ZERO (1<<1) |
|||
#define VFP_DENORMAL (1<<2) |
|||
#define VFP_INFINITY (1<<3) |
|||
#define VFP_NAN (1<<4) |
|||
#define VFP_NAN_SIGNAL (1<<5) |
|||
|
|||
#define VFP_QNAN (VFP_NAN) |
|||
#define VFP_SNAN (VFP_NAN|VFP_NAN_SIGNAL) |
|||
|
|||
static inline int vfp_single_type(struct vfp_single *s) |
|||
{ |
|||
int type = VFP_NUMBER; |
|||
if (s->exponent == 255) { |
|||
if (s->significand == 0) |
|||
type = VFP_INFINITY; |
|||
else if (s->significand & VFP_SINGLE_SIGNIFICAND_QNAN) |
|||
type = VFP_QNAN; |
|||
else |
|||
type = VFP_SNAN; |
|||
} else if (s->exponent == 0) { |
|||
if (s->significand == 0) |
|||
type |= VFP_ZERO; |
|||
else |
|||
type |= VFP_DENORMAL; |
|||
} |
|||
return type; |
|||
} |
|||
|
|||
|
|||
u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func); |
|||
|
|||
/* |
|||
* Double-precision |
|||
*/ |
|||
struct vfp_double { |
|||
s16 exponent; |
|||
u16 sign; |
|||
u64 significand; |
|||
}; |
|||
|
|||
/* |
|||
* VFP_REG_ZERO is a special register number for vfp_get_double |
|||
* which returns (double)0.0. This is useful for the compare with |
|||
* zero instructions. |
|||
*/ |
|||
#ifdef CONFIG_VFPv3 |
|||
#define VFP_REG_ZERO 32 |
|||
#else |
|||
#define VFP_REG_ZERO 16 |
|||
#endif |
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
extern u64 vfp_get_double(ARMul_State * state, unsigned int reg); |
|||
extern void vfp_put_double(ARMul_State * state, u64 val, unsigned int reg); |
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
#define VFP_DOUBLE_MANTISSA_BITS (52) |
|||
#define VFP_DOUBLE_EXPONENT_BITS (11) |
|||
#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2) |
|||
#define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1) |
|||
|
|||
/* |
|||
* The bit in an unpacked double which indicates that it is a quiet NaN |
|||
*/ |
|||
#define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS)) |
|||
|
|||
/* |
|||
* Operations on packed single-precision numbers |
|||
*/ |
|||
#define vfp_double_packed_sign(v) ((v) & (1ULL << 63)) |
|||
#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63)) |
|||
#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63)) |
|||
#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1)) |
|||
#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1)) |
|||
|
|||
/* |
|||
* Unpack a double-precision float. Note that this returns the magnitude |
|||
* of the double-precision float mantissa with the 1. if necessary, |
|||
* aligned to bit 62. |
|||
*/ |
|||
static inline void vfp_double_unpack(struct vfp_double *s, s64 val) |
|||
{ |
|||
u64 significand; |
|||
|
|||
s->sign = vfp_double_packed_sign(val) >> 48; |
|||
s->exponent = vfp_double_packed_exponent(val); |
|||
|
|||
significand = (u64) val; |
|||
significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2; |
|||
if (s->exponent && s->exponent != 2047) |
|||
significand |= (1ULL << 62); |
|||
s->significand = significand; |
|||
} |
|||
|
|||
/* |
|||
* Re-pack a double-precision float. This assumes that the float is |
|||
* already normalised such that the MSB is bit 30, _not_ bit 31. |
|||
*/ |
|||
static inline s64 vfp_double_pack(struct vfp_double *s) |
|||
{ |
|||
u64 val; |
|||
val = ((u64)s->sign << 48) + |
|||
((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) + |
|||
(s->significand >> VFP_DOUBLE_LOW_BITS); |
|||
return (s64)val; |
|||
} |
|||
|
|||
static inline int vfp_double_type(struct vfp_double *s) |
|||
{ |
|||
int type = VFP_NUMBER; |
|||
if (s->exponent == 2047) { |
|||
if (s->significand == 0) |
|||
type = VFP_INFINITY; |
|||
else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN) |
|||
type = VFP_QNAN; |
|||
else |
|||
type = VFP_SNAN; |
|||
} else if (s->exponent == 0) { |
|||
if (s->significand == 0) |
|||
type |= VFP_ZERO; |
|||
else |
|||
type |= VFP_DENORMAL; |
|||
} |
|||
return type; |
|||
} |
|||
|
|||
u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func); |
|||
|
|||
u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand); |
|||
|
|||
/* |
|||
* A special flag to tell the normalisation code not to normalise. |
|||
*/ |
|||
#define VFP_NAN_FLAG 0x100 |
|||
|
|||
/* |
|||
* A bit pattern used to indicate the initial (unset) value of the |
|||
* exception mask, in case nothing handles an instruction. This |
|||
* doesn't include the NAN flag, which get masked out before |
|||
* we check for an error. |
|||
*/ |
|||
#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG) |
|||
|
|||
/* |
|||
* A flag to tell vfp instruction type. |
|||
* OP_SCALAR - this operation always operates in scalar mode |
|||
* OP_SD - the instruction exceptionally writes to a single precision result. |
|||
* OP_DD - the instruction exceptionally writes to a double precision result. |
|||
* OP_SM - the instruction exceptionally reads from a single precision operand. |
|||
*/ |
|||
#define OP_SCALAR (1 << 0) |
|||
#define OP_SD (1 << 1) |
|||
#define OP_DD (1 << 1) |
|||
#define OP_SM (1 << 2) |
|||
|
|||
struct op { |
|||
u32 (* const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr); |
|||
u32 flags; |
|||
}; |
|||
|
|||
static inline u32 fls(int x) |
|||
{ |
|||
int r = 32; |
|||
|
|||
if (!x) |
|||
return 0; |
|||
if (!(x & 0xffff0000u)) { |
|||
x <<= 16; |
|||
r -= 16; |
|||
} |
|||
if (!(x & 0xff000000u)) { |
|||
x <<= 8; |
|||
r -= 8; |
|||
} |
|||
if (!(x & 0xf0000000u)) { |
|||
x <<= 4; |
|||
r -= 4; |
|||
} |
|||
if (!(x & 0xc0000000u)) { |
|||
x <<= 2; |
|||
r -= 2; |
|||
} |
|||
if (!(x & 0x80000000u)) { |
|||
x <<= 1; |
|||
r -= 1; |
|||
} |
|||
return r; |
|||
|
|||
} |
|||
|
|||
#endif |
|||
1262
src/core/arm/interpreter/vfp/vfpdouble.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
5123
src/core/arm/interpreter/vfp/vfpinstr.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1277
src/core/arm/interpreter/vfp/vfpsingle.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue