mirror of
https://git.h3cjp.net/H3cJP/citra.git
synced 2024-11-25 09:52:55 +00:00
dyncom: Remove unused/unnecessary VFP cruft
This commit is contained in:
parent
3ee9f6c5d8
commit
d66a12c6f6
|
@ -6,7 +6,6 @@ set(SRCS
|
|||
arm/dyncom/arm_dyncom_interpreter.cpp
|
||||
arm/dyncom/arm_dyncom_run.cpp
|
||||
arm/dyncom/arm_dyncom_thumb.cpp
|
||||
arm/interpreter/armcopro.cpp
|
||||
arm/interpreter/arminit.cpp
|
||||
arm/interpreter/armsupp.cpp
|
||||
arm/skyeye_common/vfp/vfp.cpp
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
/* armcopro.c -- co-processor interface: ARM6 Instruction Emulator.
|
||||
Copyright (C) 1994, 2000 Advanced RISC Machines Ltd.
|
||||
|
||||
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. */
|
||||
|
||||
#include "core/arm/skyeye_common/armdefs.h"
|
||||
#include "core/arm/skyeye_common/armemu.h"
|
||||
#include "core/arm/skyeye_common/vfp/vfp.h"
|
||||
|
||||
// Dummy Co-processors.
|
||||
|
||||
static unsigned int NoCoPro3R(ARMul_State* state, unsigned int a, ARMword b)
|
||||
{
|
||||
return ARMul_CANT;
|
||||
}
|
||||
|
||||
static unsigned int NoCoPro4R(ARMul_State* state, unsigned int a, ARMword b, ARMword c)
|
||||
{
|
||||
return ARMul_CANT;
|
||||
}
|
||||
|
||||
static unsigned int NoCoPro4W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c)
|
||||
{
|
||||
return ARMul_CANT;
|
||||
}
|
||||
|
||||
static unsigned int NoCoPro5R(ARMul_State* state, unsigned int a, ARMword b, ARMword c, ARMword d)
|
||||
{
|
||||
return ARMul_CANT;
|
||||
}
|
||||
|
||||
static unsigned int NoCoPro5W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c, ARMword* d)
|
||||
{
|
||||
return ARMul_CANT;
|
||||
}
|
||||
|
||||
// Install co-processor instruction handlers in this routine.
|
||||
void ARMul_CoProInit(ARMul_State* state)
|
||||
{
|
||||
// Initialise tham all first.
|
||||
for (unsigned int i = 0; i < 16; i++)
|
||||
ARMul_CoProDetach(state, i);
|
||||
|
||||
// Install CoPro Instruction handlers here.
|
||||
// The format is:
|
||||
// ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
|
||||
// LDC routine, STC routine, MRC routine, MCR routine,
|
||||
// CDP routine, Read Reg routine, Write Reg routine).
|
||||
if (state->is_v6) {
|
||||
ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
|
||||
VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
|
||||
ARMul_CoProAttach(state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
|
||||
VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
|
||||
|
||||
/*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
|
||||
MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/
|
||||
}
|
||||
|
||||
// No handlers below here.
|
||||
|
||||
// Call all the initialisation routines.
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
if (state->CPInit[i])
|
||||
(state->CPInit[i]) (state);
|
||||
}
|
||||
}
|
||||
|
||||
// Install co-processor finalisation routines in this routine.
|
||||
void ARMul_CoProExit(ARMul_State * state)
|
||||
{
|
||||
for (unsigned int i = 0; i < 16; i++)
|
||||
if (state->CPExit[i])
|
||||
(state->CPExit[i]) (state);
|
||||
|
||||
// Detach all handlers.
|
||||
for (unsigned int i = 0; i < 16; i++)
|
||||
ARMul_CoProDetach(state, i);
|
||||
}
|
||||
|
||||
// Routines to hook Co-processors into ARMulator.
|
||||
|
||||
void
|
||||
ARMul_CoProAttach(ARMul_State* state,
|
||||
unsigned number,
|
||||
ARMul_CPInits* init,
|
||||
ARMul_CPExits* exit,
|
||||
ARMul_LDCs* ldc,
|
||||
ARMul_STCs* stc,
|
||||
ARMul_MRCs* mrc,
|
||||
ARMul_MCRs* mcr,
|
||||
ARMul_MRRCs* mrrc,
|
||||
ARMul_MCRRs* mcrr,
|
||||
ARMul_CDPs* cdp,
|
||||
ARMul_CPReads* read, ARMul_CPWrites* write)
|
||||
{
|
||||
if (init != NULL)
|
||||
state->CPInit[number] = init;
|
||||
if (exit != NULL)
|
||||
state->CPExit[number] = exit;
|
||||
if (ldc != NULL)
|
||||
state->LDC[number] = ldc;
|
||||
if (stc != NULL)
|
||||
state->STC[number] = stc;
|
||||
if (mrc != NULL)
|
||||
state->MRC[number] = mrc;
|
||||
if (mcr != NULL)
|
||||
state->MCR[number] = mcr;
|
||||
if (mrrc != NULL)
|
||||
state->MRRC[number] = mrrc;
|
||||
if (mcrr != NULL)
|
||||
state->MCRR[number] = mcrr;
|
||||
if (cdp != NULL)
|
||||
state->CDP[number] = cdp;
|
||||
if (read != NULL)
|
||||
state->CPRead[number] = read;
|
||||
if (write != NULL)
|
||||
state->CPWrite[number] = write;
|
||||
}
|
||||
|
||||
void ARMul_CoProDetach(ARMul_State* state, unsigned number)
|
||||
{
|
||||
ARMul_CoProAttach(state, number, NULL, NULL,
|
||||
NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
|
||||
NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL);
|
||||
|
||||
state->CPInit[number] = NULL;
|
||||
state->CPExit[number] = NULL;
|
||||
state->CPRead[number] = NULL;
|
||||
state->CPWrite[number] = NULL;
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
#include "core/mem_map.h"
|
||||
#include "core/arm/skyeye_common/armdefs.h"
|
||||
#include "core/arm/skyeye_common/armemu.h"
|
||||
#include "core/arm/skyeye_common/vfp/vfp.h"
|
||||
|
||||
/***************************************************************************\
|
||||
* Returns a new instantiation of the ARMulator's state *
|
||||
|
@ -56,15 +57,11 @@ ARMul_State* ARMul_NewState(ARMul_State* state)
|
|||
|
||||
void ARMul_SelectProcessor(ARMul_State* state, unsigned properties)
|
||||
{
|
||||
state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0;
|
||||
state->is_v5 = (properties & ARM_v5_Prop) != 0;
|
||||
state->is_v5e = (properties & ARM_v5e_Prop) != 0;
|
||||
state->is_v6 = (properties & ARM_v6_Prop) != 0;
|
||||
state->is_v7 = (properties & ARM_v7_Prop) != 0;
|
||||
|
||||
// Only initialse the coprocessor support once we
|
||||
// know what kind of chip we are dealing with.
|
||||
ARMul_CoProInit(state);
|
||||
state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0;
|
||||
state->is_v5 = (properties & ARM_v5_Prop) != 0;
|
||||
state->is_v5e = (properties & ARM_v5e_Prop) != 0;
|
||||
state->is_v6 = (properties & ARM_v6_Prop) != 0;
|
||||
state->is_v7 = (properties & ARM_v7_Prop) != 0;
|
||||
}
|
||||
|
||||
// Resets certain MPCore CP15 values to their ARM-defined reset values.
|
||||
|
@ -130,6 +127,8 @@ static void ResetMPCoreCP15Registers(ARMul_State* cpu)
|
|||
\***************************************************************************/
|
||||
void ARMul_Reset(ARMul_State* state)
|
||||
{
|
||||
VFPInit(state);
|
||||
|
||||
state->NextInstr = 0;
|
||||
|
||||
state->Reg[15] = 0;
|
||||
|
|
|
@ -55,18 +55,6 @@ typedef u16 ARMhword; // must be 16 bits wide
|
|||
typedef u8 ARMbyte; // must be 8 bits wide
|
||||
typedef struct ARMul_State ARMul_State;
|
||||
|
||||
typedef unsigned ARMul_CPInits(ARMul_State* state);
|
||||
typedef unsigned ARMul_CPExits(ARMul_State* state);
|
||||
typedef unsigned ARMul_LDCs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
|
||||
typedef unsigned ARMul_STCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
|
||||
typedef unsigned ARMul_MRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
|
||||
typedef unsigned ARMul_MCRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
|
||||
typedef unsigned ARMul_MRRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value1, ARMword* value2);
|
||||
typedef unsigned ARMul_MCRRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value1, ARMword value2);
|
||||
typedef unsigned ARMul_CDPs(ARMul_State* state, unsigned type, ARMword instr);
|
||||
typedef unsigned ARMul_CPReads(ARMul_State* state, unsigned reg, ARMword* value);
|
||||
typedef unsigned ARMul_CPWrites(ARMul_State* state, unsigned reg, ARMword value);
|
||||
|
||||
#define VFP_REG_NUM 64
|
||||
struct ARMul_State
|
||||
{
|
||||
|
@ -117,20 +105,6 @@ struct ARMul_State
|
|||
unsigned NextInstr;
|
||||
unsigned VectorCatch; // Caught exception mask
|
||||
|
||||
ARMul_CPInits* CPInit[16]; // Coprocessor initialisers
|
||||
ARMul_CPExits* CPExit[16]; // Coprocessor finalisers
|
||||
ARMul_LDCs* LDC[16]; // LDC instruction
|
||||
ARMul_STCs* STC[16]; // STC instruction
|
||||
ARMul_MRCs* MRC[16]; // MRC instruction
|
||||
ARMul_MCRs* MCR[16]; // MCR instruction
|
||||
ARMul_MRRCs* MRRC[16]; // MRRC instruction
|
||||
ARMul_MCRRs* MCRR[16]; // MCRR instruction
|
||||
ARMul_CDPs* CDP[16]; // CDP instruction
|
||||
ARMul_CPReads* CPRead[16]; // Read CP register
|
||||
ARMul_CPWrites* CPWrite[16]; // Write CP register
|
||||
unsigned char* CPData[16]; // Coprocessor data
|
||||
unsigned char const* CPRegWords[16]; // Map of coprocessor register sizes
|
||||
|
||||
unsigned NresetSig; // Reset the processor
|
||||
unsigned NfiqSig;
|
||||
unsigned NirqSig;
|
||||
|
|
|
@ -57,12 +57,3 @@ enum {
|
|||
};
|
||||
|
||||
#define FLUSHPIPE state->NextInstr |= PRIMEPIPE
|
||||
|
||||
// Coprocessor support functions.
|
||||
extern void ARMul_CoProInit(ARMul_State*);
|
||||
extern void ARMul_CoProExit(ARMul_State*);
|
||||
extern void ARMul_CoProAttach(ARMul_State*, unsigned, ARMul_CPInits*,
|
||||
ARMul_CPExits*, ARMul_LDCs*, ARMul_STCs*,
|
||||
ARMul_MRCs*, ARMul_MCRs*, ARMul_MRRCs*, ARMul_MCRRs*,
|
||||
ARMul_CDPs*, ARMul_CPReads*, ARMul_CPWrites*);
|
||||
extern void ARMul_CoProDetach(ARMul_State*, unsigned);
|
||||
|
|
|
@ -37,296 +37,18 @@ unsigned VFPInit(ARMul_State* state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value)
|
||||
void VMSR(ARMul_State* state, ARMword reg, ARMword Rt)
|
||||
{
|
||||
/* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
|
||||
int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
|
||||
int OPC_1 = BITS(instr, 21, 23);
|
||||
int Rt = BITS(instr, 12, 15);
|
||||
int CRn = BITS(instr, 16, 19);
|
||||
int CRm = BITS(instr, 0, 3);
|
||||
int OPC_2 = BITS(instr, 5, 7);
|
||||
|
||||
/* TODO check access permission */
|
||||
|
||||
/* CRn/opc1 CRm/opc2 */
|
||||
|
||||
if (CoProc == 10 || CoProc == 11)
|
||||
if (reg == 1)
|
||||
{
|
||||
if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
|
||||
{
|
||||
/* VMOV r to s */
|
||||
/* Transfering Rt is not mandatory, as the value of interest is pointed by value */
|
||||
VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, value);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
|
||||
if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
|
||||
{
|
||||
VMRS(state, CRn, Rt, value);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
state->VFP[VFP_FPSCR] = state->Reg[Rt];
|
||||
}
|
||||
LOG_WARNING(Core_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, u32 instr, u32 value)
|
||||
{
|
||||
/* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
|
||||
int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
|
||||
int OPC_1 = BITS(instr, 21, 23);
|
||||
int Rt = BITS(instr, 12, 15);
|
||||
int CRn = BITS(instr, 16, 19);
|
||||
int CRm = BITS(instr, 0, 3);
|
||||
int OPC_2 = BITS(instr, 5, 7);
|
||||
|
||||
/* TODO check access permission */
|
||||
|
||||
/* CRn/opc1 CRm/opc2 */
|
||||
if (CoProc == 10 || CoProc == 11)
|
||||
else if (reg == 8)
|
||||
{
|
||||
if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
|
||||
{
|
||||
/* VMOV s to r */
|
||||
/* Transfering Rt is not mandatory, as the value of interest is pointed by value */
|
||||
VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, &value);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
|
||||
if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
|
||||
{
|
||||
VMSR(state, CRn, Rt);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
|
||||
if ((OPC_1 & 0x4) == 0 && CoProc == 11 && CRm == 0)
|
||||
{
|
||||
VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
|
||||
if (CoProc == 11 && CRm == 0)
|
||||
{
|
||||
VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
state->VFP[VFP_FPEXC] = state->Reg[Rt];
|
||||
}
|
||||
LOG_WARNING(Core_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, u32 instr, u32* value1, u32* value2)
|
||||
{
|
||||
/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
|
||||
int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
|
||||
int OPC_1 = BITS(instr, 4, 7);
|
||||
int Rt = BITS(instr, 12, 15);
|
||||
int Rt2 = BITS(instr, 16, 19);
|
||||
int CRm = BITS(instr, 0, 3);
|
||||
|
||||
if (CoProc == 10 || CoProc == 11)
|
||||
{
|
||||
if (CoProc == 10 && (OPC_1 & 0xD) == 1)
|
||||
{
|
||||
VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
|
||||
if (CoProc == 11 && (OPC_1 & 0xD) == 1)
|
||||
{
|
||||
/* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
|
||||
VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
}
|
||||
LOG_WARNING(Core_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, u32 instr, u32 value1, u32 value2)
|
||||
{
|
||||
/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
|
||||
int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
|
||||
int OPC_1 = BITS(instr, 4, 7);
|
||||
int Rt = BITS(instr, 12, 15);
|
||||
int Rt2 = BITS(instr, 16, 19);
|
||||
int CRm = BITS(instr, 0, 3);
|
||||
|
||||
/* TODO check access permission */
|
||||
|
||||
/* CRn/opc1 CRm/opc2 */
|
||||
|
||||
if (CoProc == 11 || CoProc == 10)
|
||||
{
|
||||
if (CoProc == 10 && (OPC_1 & 0xD) == 1)
|
||||
{
|
||||
VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
|
||||
if (CoProc == 11 && (OPC_1 & 0xD) == 1)
|
||||
{
|
||||
/* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
|
||||
VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
}
|
||||
LOG_WARNING(Core_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, u32 instr, u32 * value)
|
||||
{
|
||||
/* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */
|
||||
int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
|
||||
int CRd = BITS(instr, 12, 15);
|
||||
int Rn = BITS(instr, 16, 19);
|
||||
int imm8 = BITS(instr, 0, 7);
|
||||
int P = BIT(instr, 24);
|
||||
int U = BIT(instr, 23);
|
||||
int D = BIT(instr, 22);
|
||||
int W = BIT(instr, 21);
|
||||
|
||||
/* TODO check access permission */
|
||||
|
||||
/* VSTM */
|
||||
if ( (P|U|D|W) == 0 ) {
|
||||
LOG_ERROR(Core_ARM11, "In %s, UNDEFINED\n", __FUNCTION__);
|
||||
exit(-1);
|
||||
}
|
||||
if (CoProc == 10 || CoProc == 11) {
|
||||
#if 1
|
||||
if (P == 0 && U == 0 && W == 0) {
|
||||
LOG_ERROR(Core_ARM11, "VSTM Related encodings\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (P == U && W == 1) {
|
||||
LOG_ERROR(Core_ARM11, "UNDEFINED\n");
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (P == 1 && W == 0)
|
||||
{
|
||||
return VSTR(state, type, instr, value);
|
||||
}
|
||||
|
||||
if (P == 1 && U == 0 && W == 1 && Rn == 0xD)
|
||||
{
|
||||
return VPUSH(state, type, instr, value);
|
||||
}
|
||||
|
||||
return VSTM(state, type, instr, value);
|
||||
}
|
||||
LOG_WARNING(Core_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, u32 instr, u32 value)
|
||||
{
|
||||
/* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */
|
||||
int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
|
||||
int CRd = BITS(instr, 12, 15);
|
||||
int Rn = BITS(instr, 16, 19);
|
||||
int imm8 = BITS(instr, 0, 7);
|
||||
int P = BIT(instr, 24);
|
||||
int U = BIT(instr, 23);
|
||||
int D = BIT(instr, 22);
|
||||
int W = BIT(instr, 21);
|
||||
|
||||
/* TODO check access permission */
|
||||
|
||||
if ( (P|U|D|W) == 0 ) {
|
||||
LOG_ERROR(Core_ARM11, "In %s, UNDEFINED\n", __FUNCTION__);
|
||||
exit(-1);
|
||||
}
|
||||
if (CoProc == 10 || CoProc == 11)
|
||||
{
|
||||
if (P == 1 && W == 0)
|
||||
{
|
||||
return VLDR(state, type, instr, value);
|
||||
}
|
||||
|
||||
if (P == 0 && U == 1 && W == 1 && Rn == 0xD)
|
||||
{
|
||||
return VPOP(state, type, instr, value);
|
||||
}
|
||||
|
||||
return VLDM(state, type, instr, value);
|
||||
}
|
||||
LOG_WARNING(Core_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, u32 instr)
|
||||
{
|
||||
/* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */
|
||||
int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
|
||||
int OPC_1 = BITS(instr, 20, 23);
|
||||
int CRd = BITS(instr, 12, 15);
|
||||
int CRn = BITS(instr, 16, 19);
|
||||
int CRm = BITS(instr, 0, 3);
|
||||
int OPC_2 = BITS(instr, 5, 7);
|
||||
|
||||
/* TODO check access permission */
|
||||
|
||||
/* CRn/opc1 CRm/opc2 */
|
||||
|
||||
if (CoProc == 10 || CoProc == 11)
|
||||
{
|
||||
if ((OPC_1 & 0xB) == 0xB && BITS(instr, 4, 7) == 0)
|
||||
{
|
||||
unsigned int single = BIT(instr, 8) == 0;
|
||||
unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
|
||||
unsigned int imm;
|
||||
instr = BITS(instr, 16, 19) << 4 | BITS(instr, 0, 3); // FIXME dirty workaround to get a correct imm
|
||||
|
||||
if (single)
|
||||
imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0x1f : 0)<<25 | BITS(instr, 0, 5)<<19;
|
||||
else
|
||||
imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0xff : 0)<<22 | BITS(instr, 0, 5)<<16;
|
||||
|
||||
VMOVI(state, single, d, imm);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
|
||||
if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x6) == 0x2)
|
||||
{
|
||||
unsigned int single = BIT(instr, 8) == 0;
|
||||
unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
|
||||
unsigned int m = (single ? BITS(instr, 0, 3)<<1 | BIT(instr, 5) : BITS(instr, 0, 3) | BIT(instr, 5)<<4);
|
||||
VMOVR(state, single, d, m);
|
||||
return ARMul_DONE;
|
||||
}
|
||||
|
||||
int exceptions = 0;
|
||||
if (CoProc == 10)
|
||||
exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_FPSCR]);
|
||||
else
|
||||
exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_FPSCR]);
|
||||
|
||||
vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_FPSCR]);
|
||||
|
||||
return ARMul_DONE;
|
||||
}
|
||||
LOG_WARNING(Core_ARM11, "Can't identify %x\n", instr);
|
||||
return ARMul_CANT;
|
||||
}
|
||||
|
||||
/* ----------- MRC ------------ */
|
||||
void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value)
|
||||
{
|
||||
if (to_arm)
|
||||
|
@ -338,43 +60,7 @@ void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword*
|
|||
state->ExtReg[n] = *value;
|
||||
}
|
||||
}
|
||||
void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value)
|
||||
{
|
||||
if (reg == 1)
|
||||
{
|
||||
if (Rt != 15)
|
||||
{
|
||||
*value = state->VFP[VFP_FPSCR];
|
||||
}
|
||||
else
|
||||
{
|
||||
*value = state->VFP[VFP_FPSCR] ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
case 0:
|
||||
*value = state->VFP[VFP_FPSID];
|
||||
break;
|
||||
case 6:
|
||||
/* MVFR1, VFPv3 only ? */
|
||||
LOG_TRACE(Core_ARM11, "\tr%d <= MVFR1 unimplemented\n", Rt);
|
||||
break;
|
||||
case 7:
|
||||
/* MVFR0, VFPv3 only? */
|
||||
LOG_TRACE(Core_ARM11, "\tr%d <= MVFR0 unimplemented\n", Rt);
|
||||
break;
|
||||
case 8:
|
||||
*value = state->VFP[VFP_FPEXC];
|
||||
break;
|
||||
default:
|
||||
LOG_TRACE(Core_ARM11, "\tSUBARCHITECTURE DEFINED\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2)
|
||||
{
|
||||
if (to_arm)
|
||||
|
@ -402,301 +88,6 @@ void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMwor
|
|||
}
|
||||
}
|
||||
|
||||
/* ----------- MCR ------------ */
|
||||
void VMSR(ARMul_State* state, ARMword reg, ARMword Rt)
|
||||
{
|
||||
if (reg == 1)
|
||||
{
|
||||
state->VFP[VFP_FPSCR] = state->Reg[Rt];
|
||||
}
|
||||
else if (reg == 8)
|
||||
{
|
||||
state->VFP[VFP_FPEXC] = state->Reg[Rt];
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 ------------ */
|
||||
int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value)
|
||||
{
|
||||
static int i = 0;
|
||||
static int single_reg, add, d, n, imm32, regs;
|
||||
if (type == ARMul_FIRST)
|
||||
{
|
||||
single_reg = BIT(instr, 8) == 0; // Double precision
|
||||
add = BIT(instr, 23);
|
||||
imm32 = BITS(instr, 0,7)<<2; // may not be used
|
||||
d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); /* Base register */
|
||||
n = BITS(instr, 16, 19); // destination register
|
||||
|
||||
i = 0;
|
||||
regs = 1;
|
||||
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else if (type == ARMul_DATA)
|
||||
{
|
||||
if (single_reg)
|
||||
{
|
||||
*value = state->ExtReg[d+i];
|
||||
i++;
|
||||
if (i < regs)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME Careful of endianness, may need to rework this */
|
||||
*value = state->ExtReg[d*2+i];
|
||||
i++;
|
||||
if (i < regs*2)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value)
|
||||
{
|
||||
static int i = 0;
|
||||
static int single_regs, d, imm32, regs;
|
||||
if (type == ARMul_FIRST)
|
||||
{
|
||||
single_regs = BIT(instr, 8) == 0; // Single precision
|
||||
d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
|
||||
imm32 = BITS(instr, 0,7)<<2; // may not be used
|
||||
regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FSTMX if regs is odd
|
||||
|
||||
state->Reg[R13] = state->Reg[R13] - imm32;
|
||||
|
||||
i = 0;
|
||||
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else if (type == ARMul_DATA)
|
||||
{
|
||||
if (single_regs)
|
||||
{
|
||||
*value = state->ExtReg[d + i];
|
||||
i++;
|
||||
if (i < regs)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME Careful of endianness, may need to rework this */
|
||||
*value = state->ExtReg[d*2 + i];
|
||||
i++;
|
||||
if (i < regs*2)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value)
|
||||
{
|
||||
static int i = 0;
|
||||
static int single_regs, add, wback, d, n, imm32, regs;
|
||||
if (type == ARMul_FIRST)
|
||||
{
|
||||
single_regs = BIT(instr, 8) == 0; // Single precision
|
||||
add = BIT(instr, 23);
|
||||
wback = BIT(instr, 21); // write-back
|
||||
d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
|
||||
n = BITS(instr, 16, 19); // destination register
|
||||
imm32 = BITS(instr, 0,7) * 4; // may not be used
|
||||
regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FSTMX if regs is odd
|
||||
|
||||
if (wback) {
|
||||
state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else if (type == ARMul_DATA)
|
||||
{
|
||||
if (single_regs)
|
||||
{
|
||||
*value = state->ExtReg[d + i];
|
||||
i++;
|
||||
if (i < regs)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME Careful of endianness, may need to rework this */
|
||||
*value = state->ExtReg[d*2 + i];
|
||||
i++;
|
||||
if (i < regs*2)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ----------- LDC ------------ */
|
||||
int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value)
|
||||
{
|
||||
static int i = 0;
|
||||
static int single_regs, d, imm32, regs;
|
||||
if (type == ARMul_FIRST)
|
||||
{
|
||||
single_regs = BIT(instr, 8) == 0; // Single precision
|
||||
d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
|
||||
imm32 = BITS(instr, 0, 7)<<2; // may not be used
|
||||
regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FLDMX if regs is odd
|
||||
|
||||
state->Reg[R13] = state->Reg[R13] + imm32;
|
||||
|
||||
i = 0;
|
||||
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else if (type == ARMul_TRANSFER)
|
||||
{
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else if (type == ARMul_DATA)
|
||||
{
|
||||
if (single_regs)
|
||||
{
|
||||
state->ExtReg[d + i] = value;
|
||||
i++;
|
||||
if (i < regs)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME Careful of endianness, may need to rework this */
|
||||
state->ExtReg[d*2 + i] = value;
|
||||
i++;
|
||||
if (i < regs*2)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value)
|
||||
{
|
||||
static int i = 0;
|
||||
static int single_reg, add, d, n, imm32, regs;
|
||||
if (type == ARMul_FIRST)
|
||||
{
|
||||
single_reg = BIT(instr, 8) == 0; // Double precision
|
||||
add = BIT(instr, 23);
|
||||
imm32 = BITS(instr, 0, 7)<<2; // may not be used
|
||||
d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
|
||||
n = BITS(instr, 16, 19); // destination register
|
||||
|
||||
i = 0;
|
||||
regs = 1;
|
||||
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else if (type == ARMul_TRANSFER)
|
||||
{
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else if (type == ARMul_DATA)
|
||||
{
|
||||
if (single_reg)
|
||||
{
|
||||
state->ExtReg[d+i] = value;
|
||||
i++;
|
||||
if (i < regs)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME Careful of endianness, may need to rework this */
|
||||
state->ExtReg[d*2+i] = value;
|
||||
i++;
|
||||
if (i < regs*2)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value)
|
||||
{
|
||||
static int i = 0;
|
||||
static int single_regs, add, wback, d, n, imm32, regs;
|
||||
if (type == ARMul_FIRST)
|
||||
{
|
||||
single_regs = BIT(instr, 8) == 0; // Single precision
|
||||
add = BIT(instr, 23);
|
||||
wback = BIT(instr, 21); // write-back
|
||||
d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
|
||||
n = BITS(instr, 16, 19); // destination register
|
||||
imm32 = BITS(instr, 0, 7) * 4; // may not be used
|
||||
regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FLDMX if regs is odd
|
||||
|
||||
if (wback) {
|
||||
state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else if (type == ARMul_DATA)
|
||||
{
|
||||
if (single_regs)
|
||||
{
|
||||
state->ExtReg[d + i] = value;
|
||||
i++;
|
||||
if (i < regs)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME Careful of endianness, may need to rework this */
|
||||
state->ExtReg[d*2 + i] = value;
|
||||
i++;
|
||||
if (i < regs*2)
|
||||
return ARMul_INC;
|
||||
else
|
||||
return ARMul_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ----------- CDP ------------ */
|
||||
void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm)
|
||||
{
|
||||
if (single)
|
||||
|
|
|
@ -28,13 +28,6 @@
|
|||
#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
|
||||
|
||||
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);
|
||||
|
||||
s32 vfp_get_float(ARMul_State* state, u32 reg);
|
||||
void vfp_put_float(ARMul_State* state, s32 val, u32 reg);
|
||||
|
@ -44,23 +37,10 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc
|
|||
u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
|
||||
u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
|
||||
|
||||
// MRC
|
||||
void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value);
|
||||
void VMSR(ARMul_State* state, ARMword reg, ARMword Rt);
|
||||
void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value);
|
||||
void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2);
|
||||
void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2);
|
||||
void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
|
||||
void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
|
||||
|
||||
// MCR
|
||||
void VMSR(ARMul_State* state, ARMword reg, ARMword Rt);
|
||||
|
||||
// STC
|
||||
int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value);
|
||||
int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value);
|
||||
int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value);
|
||||
|
||||
// LDC
|
||||
int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value);
|
||||
int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value);
|
||||
int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value);
|
||||
|
|
Loading…
Reference in a new issue