summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/arm/interpreter/armcopro.cpp142
-rw-r--r--src/core/arm/interpreter/arminit.cpp17
-rw-r--r--src/core/arm/skyeye_common/armdefs.h26
-rw-r--r--src/core/arm/skyeye_common/armemu.h9
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp621
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h22
7 files changed, 15 insertions, 823 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 0528175ba..42733b95e 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -6,7 +6,6 @@ set(SRCS
6 arm/dyncom/arm_dyncom_interpreter.cpp 6 arm/dyncom/arm_dyncom_interpreter.cpp
7 arm/dyncom/arm_dyncom_run.cpp 7 arm/dyncom/arm_dyncom_run.cpp
8 arm/dyncom/arm_dyncom_thumb.cpp 8 arm/dyncom/arm_dyncom_thumb.cpp
9 arm/interpreter/armcopro.cpp
10 arm/interpreter/arminit.cpp 9 arm/interpreter/arminit.cpp
11 arm/interpreter/armsupp.cpp 10 arm/interpreter/armsupp.cpp
12 arm/skyeye_common/vfp/vfp.cpp 11 arm/skyeye_common/vfp/vfp.cpp
diff --git a/src/core/arm/interpreter/armcopro.cpp b/src/core/arm/interpreter/armcopro.cpp
deleted file mode 100644
index 4ae0c52e4..000000000
--- a/src/core/arm/interpreter/armcopro.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
1/* armcopro.c -- co-processor interface: ARM6 Instruction Emulator.
2 Copyright (C) 1994, 2000 Advanced RISC Machines Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18#include "core/arm/skyeye_common/armdefs.h"
19#include "core/arm/skyeye_common/armemu.h"
20#include "core/arm/skyeye_common/vfp/vfp.h"
21
22// Dummy Co-processors.
23
24static unsigned int NoCoPro3R(ARMul_State* state, unsigned int a, ARMword b)
25{
26 return ARMul_CANT;
27}
28
29static unsigned int NoCoPro4R(ARMul_State* state, unsigned int a, ARMword b, ARMword c)
30{
31 return ARMul_CANT;
32}
33
34static unsigned int NoCoPro4W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c)
35{
36 return ARMul_CANT;
37}
38
39static unsigned int NoCoPro5R(ARMul_State* state, unsigned int a, ARMword b, ARMword c, ARMword d)
40{
41 return ARMul_CANT;
42}
43
44static unsigned int NoCoPro5W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c, ARMword* d)
45{
46 return ARMul_CANT;
47}
48
49// Install co-processor instruction handlers in this routine.
50void ARMul_CoProInit(ARMul_State* state)
51{
52 // Initialise tham all first.
53 for (unsigned int i = 0; i < 16; i++)
54 ARMul_CoProDetach(state, i);
55
56 // Install CoPro Instruction handlers here.
57 // The format is:
58 // ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
59 // LDC routine, STC routine, MRC routine, MCR routine,
60 // CDP routine, Read Reg routine, Write Reg routine).
61 if (state->is_v6) {
62 ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
63 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
64 ARMul_CoProAttach(state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
65 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
66
67 /*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
68 MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/
69 }
70
71 // No handlers below here.
72
73 // Call all the initialisation routines.
74 for (unsigned int i = 0; i < 16; i++) {
75 if (state->CPInit[i])
76 (state->CPInit[i]) (state);
77 }
78}
79
80// Install co-processor finalisation routines in this routine.
81void ARMul_CoProExit(ARMul_State * state)
82{
83 for (unsigned int i = 0; i < 16; i++)
84 if (state->CPExit[i])
85 (state->CPExit[i]) (state);
86
87 // Detach all handlers.
88 for (unsigned int i = 0; i < 16; i++)
89 ARMul_CoProDetach(state, i);
90}
91
92// Routines to hook Co-processors into ARMulator.
93
94void
95ARMul_CoProAttach(ARMul_State* state,
96unsigned number,
97ARMul_CPInits* init,
98ARMul_CPExits* exit,
99ARMul_LDCs* ldc,
100ARMul_STCs* stc,
101ARMul_MRCs* mrc,
102ARMul_MCRs* mcr,
103ARMul_MRRCs* mrrc,
104ARMul_MCRRs* mcrr,
105ARMul_CDPs* cdp,
106ARMul_CPReads* read, ARMul_CPWrites* write)
107{
108 if (init != NULL)
109 state->CPInit[number] = init;
110 if (exit != NULL)
111 state->CPExit[number] = exit;
112 if (ldc != NULL)
113 state->LDC[number] = ldc;
114 if (stc != NULL)
115 state->STC[number] = stc;
116 if (mrc != NULL)
117 state->MRC[number] = mrc;
118 if (mcr != NULL)
119 state->MCR[number] = mcr;
120 if (mrrc != NULL)
121 state->MRRC[number] = mrrc;
122 if (mcrr != NULL)
123 state->MCRR[number] = mcrr;
124 if (cdp != NULL)
125 state->CDP[number] = cdp;
126 if (read != NULL)
127 state->CPRead[number] = read;
128 if (write != NULL)
129 state->CPWrite[number] = write;
130}
131
132void ARMul_CoProDetach(ARMul_State* state, unsigned number)
133{
134 ARMul_CoProAttach(state, number, NULL, NULL,
135 NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
136 NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL);
137
138 state->CPInit[number] = NULL;
139 state->CPExit[number] = NULL;
140 state->CPRead[number] = NULL;
141 state->CPWrite[number] = NULL;
142}
diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp
index 1d732fe84..6fa028f49 100644
--- a/src/core/arm/interpreter/arminit.cpp
+++ b/src/core/arm/interpreter/arminit.cpp
@@ -19,6 +19,7 @@
19#include "core/mem_map.h" 19#include "core/mem_map.h"
20#include "core/arm/skyeye_common/armdefs.h" 20#include "core/arm/skyeye_common/armdefs.h"
21#include "core/arm/skyeye_common/armemu.h" 21#include "core/arm/skyeye_common/armemu.h"
22#include "core/arm/skyeye_common/vfp/vfp.h"
22 23
23/***************************************************************************\ 24/***************************************************************************\
24* Returns a new instantiation of the ARMulator's state * 25* Returns a new instantiation of the ARMulator's state *
@@ -56,15 +57,11 @@ ARMul_State* ARMul_NewState(ARMul_State* state)
56 57
57void ARMul_SelectProcessor(ARMul_State* state, unsigned properties) 58void ARMul_SelectProcessor(ARMul_State* state, unsigned properties)
58{ 59{
59 state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0; 60 state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0;
60 state->is_v5 = (properties & ARM_v5_Prop) != 0; 61 state->is_v5 = (properties & ARM_v5_Prop) != 0;
61 state->is_v5e = (properties & ARM_v5e_Prop) != 0; 62 state->is_v5e = (properties & ARM_v5e_Prop) != 0;
62 state->is_v6 = (properties & ARM_v6_Prop) != 0; 63 state->is_v6 = (properties & ARM_v6_Prop) != 0;
63 state->is_v7 = (properties & ARM_v7_Prop) != 0; 64 state->is_v7 = (properties & ARM_v7_Prop) != 0;
64
65 // Only initialse the coprocessor support once we
66 // know what kind of chip we are dealing with.
67 ARMul_CoProInit(state);
68} 65}
69 66
70// Resets certain MPCore CP15 values to their ARM-defined reset values. 67// Resets certain MPCore CP15 values to their ARM-defined reset values.
@@ -130,6 +127,8 @@ static void ResetMPCoreCP15Registers(ARMul_State* cpu)
130\***************************************************************************/ 127\***************************************************************************/
131void ARMul_Reset(ARMul_State* state) 128void ARMul_Reset(ARMul_State* state)
132{ 129{
130 VFPInit(state);
131
133 state->NextInstr = 0; 132 state->NextInstr = 0;
134 133
135 state->Reg[15] = 0; 134 state->Reg[15] = 0;
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index 743e935f0..64ca523e8 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -55,18 +55,6 @@ typedef u16 ARMhword; // must be 16 bits wide
55typedef u8 ARMbyte; // must be 8 bits wide 55typedef u8 ARMbyte; // must be 8 bits wide
56typedef struct ARMul_State ARMul_State; 56typedef struct ARMul_State ARMul_State;
57 57
58typedef unsigned ARMul_CPInits(ARMul_State* state);
59typedef unsigned ARMul_CPExits(ARMul_State* state);
60typedef unsigned ARMul_LDCs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
61typedef unsigned ARMul_STCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
62typedef unsigned ARMul_MRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
63typedef unsigned ARMul_MCRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
64typedef unsigned ARMul_MRRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value1, ARMword* value2);
65typedef unsigned ARMul_MCRRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value1, ARMword value2);
66typedef unsigned ARMul_CDPs(ARMul_State* state, unsigned type, ARMword instr);
67typedef unsigned ARMul_CPReads(ARMul_State* state, unsigned reg, ARMword* value);
68typedef unsigned ARMul_CPWrites(ARMul_State* state, unsigned reg, ARMword value);
69
70#define VFP_REG_NUM 64 58#define VFP_REG_NUM 64
71struct ARMul_State 59struct ARMul_State
72{ 60{
@@ -117,20 +105,6 @@ struct ARMul_State
117 unsigned NextInstr; 105 unsigned NextInstr;
118 unsigned VectorCatch; // Caught exception mask 106 unsigned VectorCatch; // Caught exception mask
119 107
120 ARMul_CPInits* CPInit[16]; // Coprocessor initialisers
121 ARMul_CPExits* CPExit[16]; // Coprocessor finalisers
122 ARMul_LDCs* LDC[16]; // LDC instruction
123 ARMul_STCs* STC[16]; // STC instruction
124 ARMul_MRCs* MRC[16]; // MRC instruction
125 ARMul_MCRs* MCR[16]; // MCR instruction
126 ARMul_MRRCs* MRRC[16]; // MRRC instruction
127 ARMul_MCRRs* MCRR[16]; // MCRR instruction
128 ARMul_CDPs* CDP[16]; // CDP instruction
129 ARMul_CPReads* CPRead[16]; // Read CP register
130 ARMul_CPWrites* CPWrite[16]; // Write CP register
131 unsigned char* CPData[16]; // Coprocessor data
132 unsigned char const* CPRegWords[16]; // Map of coprocessor register sizes
133
134 unsigned NresetSig; // Reset the processor 108 unsigned NresetSig; // Reset the processor
135 unsigned NfiqSig; 109 unsigned NfiqSig;
136 unsigned NirqSig; 110 unsigned NirqSig;
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
index 2a1c50779..b8113dfc1 100644
--- a/src/core/arm/skyeye_common/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -57,12 +57,3 @@ enum {
57}; 57};
58 58
59#define FLUSHPIPE state->NextInstr |= PRIMEPIPE 59#define FLUSHPIPE state->NextInstr |= PRIMEPIPE
60
61// Coprocessor support functions.
62extern void ARMul_CoProInit(ARMul_State*);
63extern void ARMul_CoProExit(ARMul_State*);
64extern void ARMul_CoProAttach(ARMul_State*, unsigned, ARMul_CPInits*,
65 ARMul_CPExits*, ARMul_LDCs*, ARMul_STCs*,
66 ARMul_MRCs*, ARMul_MCRs*, ARMul_MRRCs*, ARMul_MCRRs*,
67 ARMul_CDPs*, ARMul_CPReads*, ARMul_CPWrites*);
68extern void ARMul_CoProDetach(ARMul_State*, unsigned);
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index d793261fd..d0fa157a2 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -37,296 +37,18 @@ unsigned VFPInit(ARMul_State* state)
37 return 0; 37 return 0;
38} 38}
39 39
40unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value) 40void VMSR(ARMul_State* state, ARMword reg, ARMword Rt)
41{
42 /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
43 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
44 int OPC_1 = BITS(instr, 21, 23);
45 int Rt = BITS(instr, 12, 15);
46 int CRn = BITS(instr, 16, 19);
47 int CRm = BITS(instr, 0, 3);
48 int OPC_2 = BITS(instr, 5, 7);
49
50 /* TODO check access permission */
51
52 /* CRn/opc1 CRm/opc2 */
53
54 if (CoProc == 10 || CoProc == 11)
55 {
56 if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
57 {
58 /* VMOV r to s */
59 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
60 VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, value);
61 return ARMul_DONE;
62 }
63
64 if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
65 {
66 VMRS(state, CRn, Rt, value);
67 return ARMul_DONE;
68 }
69 }
70 LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
71 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
72
73 return ARMul_CANT;
74}
75
76unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value)
77{
78 /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
79 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
80 int OPC_1 = BITS(instr, 21, 23);
81 int Rt = BITS(instr, 12, 15);
82 int CRn = BITS(instr, 16, 19);
83 int CRm = BITS(instr, 0, 3);
84 int OPC_2 = BITS(instr, 5, 7);
85
86 /* TODO check access permission */
87
88 /* CRn/opc1 CRm/opc2 */
89 if (CoProc == 10 || CoProc == 11)
90 {
91 if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
92 {
93 /* VMOV s to r */
94 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
95 VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, &value);
96 return ARMul_DONE;
97 }
98
99 if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
100 {
101 VMSR(state, CRn, Rt);
102 return ARMul_DONE;
103 }
104
105 if ((OPC_1 & 0x4) == 0 && CoProc == 11 && CRm == 0)
106 {
107 VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
108 return ARMul_DONE;
109 }
110
111 if (CoProc == 11 && CRm == 0)
112 {
113 VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
114 return ARMul_DONE;
115 }
116 }
117 LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
118 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
119
120 return ARMul_CANT;
121}
122
123unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32* value2)
124{
125 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
126 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
127 int OPC_1 = BITS(instr, 4, 7);
128 int Rt = BITS(instr, 12, 15);
129 int Rt2 = BITS(instr, 16, 19);
130 int CRm = BITS(instr, 0, 3);
131
132 if (CoProc == 10 || CoProc == 11)
133 {
134 if (CoProc == 10 && (OPC_1 & 0xD) == 1)
135 {
136 VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
137 return ARMul_DONE;
138 }
139
140 if (CoProc == 11 && (OPC_1 & 0xD) == 1)
141 {
142 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
143 VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
144 return ARMul_DONE;
145 }
146 }
147 LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
148 instr, CoProc, OPC_1, Rt, Rt2, CRm);
149
150 return ARMul_CANT;
151}
152
153unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 value2)
154{
155 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
156 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
157 int OPC_1 = BITS(instr, 4, 7);
158 int Rt = BITS(instr, 12, 15);
159 int Rt2 = BITS(instr, 16, 19);
160 int CRm = BITS(instr, 0, 3);
161
162 /* TODO check access permission */
163
164 /* CRn/opc1 CRm/opc2 */
165
166 if (CoProc == 11 || CoProc == 10)
167 {
168 if (CoProc == 10 && (OPC_1 & 0xD) == 1)
169 {
170 VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
171 return ARMul_DONE;
172 }
173
174 if (CoProc == 11 && (OPC_1 & 0xD) == 1)
175 {
176 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
177 VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
178 return ARMul_DONE;
179 }
180 }
181 LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
182 instr, CoProc, OPC_1, Rt, Rt2, CRm);
183
184 return ARMul_CANT;
185}
186
187unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value)
188{
189 /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */
190 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
191 int CRd = BITS(instr, 12, 15);
192 int Rn = BITS(instr, 16, 19);
193 int imm8 = BITS(instr, 0, 7);
194 int P = BIT(instr, 24);
195 int U = BIT(instr, 23);
196 int D = BIT(instr, 22);
197 int W = BIT(instr, 21);
198
199 /* TODO check access permission */
200
201 /* VSTM */
202 if ( (P|U|D|W) == 0 ) {
203 LOG_ERROR(Core_ARM11, "In %s, UNDEFINED\n", __FUNCTION__);
204 exit(-1);
205 }
206 if (CoProc == 10 || CoProc == 11) {
207#if 1
208 if (P == 0 && U == 0 && W == 0) {
209 LOG_ERROR(Core_ARM11, "VSTM Related encodings\n");
210 exit(-1);
211 }
212 if (P == U && W == 1) {
213 LOG_ERROR(Core_ARM11, "UNDEFINED\n");
214 exit(-1);
215 }
216#endif
217
218 if (P == 1 && W == 0)
219 {
220 return VSTR(state, type, instr, value);
221 }
222
223 if (P == 1 && U == 0 && W == 1 && Rn == 0xD)
224 {
225 return VPUSH(state, type, instr, value);
226 }
227
228 return VSTM(state, type, instr, value);
229 }
230 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",
231 instr, CoProc, CRd, Rn, imm8, P, U, D, W);
232
233 return ARMul_CANT;
234}
235
236unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value)
237{ 41{
238 /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */ 42 if (reg == 1)
239 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
240 int CRd = BITS(instr, 12, 15);
241 int Rn = BITS(instr, 16, 19);
242 int imm8 = BITS(instr, 0, 7);
243 int P = BIT(instr, 24);
244 int U = BIT(instr, 23);
245 int D = BIT(instr, 22);
246 int W = BIT(instr, 21);
247
248 /* TODO check access permission */
249
250 if ( (P|U|D|W) == 0 ) {
251 LOG_ERROR(Core_ARM11, "In %s, UNDEFINED\n", __FUNCTION__);
252 exit(-1);
253 }
254 if (CoProc == 10 || CoProc == 11)
255 { 43 {
256 if (P == 1 && W == 0) 44 state->VFP[VFP_FPSCR] = state->Reg[Rt];
257 {
258 return VLDR(state, type, instr, value);
259 }
260
261 if (P == 0 && U == 1 && W == 1 && Rn == 0xD)
262 {
263 return VPOP(state, type, instr, value);
264 }
265
266 return VLDM(state, type, instr, value);
267 } 45 }
268 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", 46 else if (reg == 8)
269 instr, CoProc, CRd, Rn, imm8, P, U, D, W);
270
271 return ARMul_CANT;
272}
273
274unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr)
275{
276 /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */
277 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
278 int OPC_1 = BITS(instr, 20, 23);
279 int CRd = BITS(instr, 12, 15);
280 int CRn = BITS(instr, 16, 19);
281 int CRm = BITS(instr, 0, 3);
282 int OPC_2 = BITS(instr, 5, 7);
283
284 /* TODO check access permission */
285
286 /* CRn/opc1 CRm/opc2 */
287
288 if (CoProc == 10 || CoProc == 11)
289 { 47 {
290 if ((OPC_1 & 0xB) == 0xB && BITS(instr, 4, 7) == 0) 48 state->VFP[VFP_FPEXC] = state->Reg[Rt];
291 {
292 unsigned int single = BIT(instr, 8) == 0;
293 unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
294 unsigned int imm;
295 instr = BITS(instr, 16, 19) << 4 | BITS(instr, 0, 3); // FIXME dirty workaround to get a correct imm
296
297 if (single)
298 imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0x1f : 0)<<25 | BITS(instr, 0, 5)<<19;
299 else
300 imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0xff : 0)<<22 | BITS(instr, 0, 5)<<16;
301
302 VMOVI(state, single, d, imm);
303 return ARMul_DONE;
304 }
305
306 if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x6) == 0x2)
307 {
308 unsigned int single = BIT(instr, 8) == 0;
309 unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
310 unsigned int m = (single ? BITS(instr, 0, 3)<<1 | BIT(instr, 5) : BITS(instr, 0, 3) | BIT(instr, 5)<<4);
311 VMOVR(state, single, d, m);
312 return ARMul_DONE;
313 }
314
315 int exceptions = 0;
316 if (CoProc == 10)
317 exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_FPSCR]);
318 else
319 exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_FPSCR]);
320
321 vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_FPSCR]);
322
323 return ARMul_DONE;
324 } 49 }
325 LOG_WARNING(Core_ARM11, "Can't identify %x\n", instr);
326 return ARMul_CANT;
327} 50}
328 51
329/* ----------- MRC ------------ */
330void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value) 52void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value)
331{ 53{
332 if (to_arm) 54 if (to_arm)
@@ -338,43 +60,7 @@ void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword*
338 state->ExtReg[n] = *value; 60 state->ExtReg[n] = *value;
339 } 61 }
340} 62}
341void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value) 63
342{
343 if (reg == 1)
344 {
345 if (Rt != 15)
346 {
347 *value = state->VFP[VFP_FPSCR];
348 }
349 else
350 {
351 *value = state->VFP[VFP_FPSCR] ;
352 }
353 }
354 else
355 {
356 switch (reg)
357 {
358 case 0:
359 *value = state->VFP[VFP_FPSID];
360 break;
361 case 6:
362 /* MVFR1, VFPv3 only ? */
363 LOG_TRACE(Core_ARM11, "\tr%d <= MVFR1 unimplemented\n", Rt);
364 break;
365 case 7:
366 /* MVFR0, VFPv3 only? */
367 LOG_TRACE(Core_ARM11, "\tr%d <= MVFR0 unimplemented\n", Rt);
368 break;
369 case 8:
370 *value = state->VFP[VFP_FPEXC];
371 break;
372 default:
373 LOG_TRACE(Core_ARM11, "\tSUBARCHITECTURE DEFINED\n");
374 break;
375 }
376 }
377}
378void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) 64void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2)
379{ 65{
380 if (to_arm) 66 if (to_arm)
@@ -402,301 +88,6 @@ void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMwor
402 } 88 }
403} 89}
404 90
405/* ----------- MCR ------------ */
406void VMSR(ARMul_State* state, ARMword reg, ARMword Rt)
407{
408 if (reg == 1)
409 {
410 state->VFP[VFP_FPSCR] = state->Reg[Rt];
411 }
412 else if (reg == 8)
413 {
414 state->VFP[VFP_FPEXC] = state->Reg[Rt];
415 }
416}
417
418/* Memory operation are not inlined, as old Interpreter and Fast interpreter
419 don't have the same memory operation interface.
420 Old interpreter framework does one access to coprocessor per data, and
421 handles already data write, as well as address computation,
422 which is not the case for Fast interpreter. Therefore, implementation
423 of vfp instructions in old interpreter and fast interpreter are separate. */
424
425/* ----------- STC ------------ */
426int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value)
427{
428 static int i = 0;
429 static int single_reg, add, d, n, imm32, regs;
430 if (type == ARMul_FIRST)
431 {
432 single_reg = BIT(instr, 8) == 0; // Double precision
433 add = BIT(instr, 23);
434 imm32 = BITS(instr, 0,7)<<2; // may not be used
435 d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); /* Base register */
436 n = BITS(instr, 16, 19); // destination register
437
438 i = 0;
439 regs = 1;
440
441 return ARMul_DONE;
442 }
443 else if (type == ARMul_DATA)
444 {
445 if (single_reg)
446 {
447 *value = state->ExtReg[d+i];
448 i++;
449 if (i < regs)
450 return ARMul_INC;
451 else
452 return ARMul_DONE;
453 }
454 else
455 {
456 /* FIXME Careful of endianness, may need to rework this */
457 *value = state->ExtReg[d*2+i];
458 i++;
459 if (i < regs*2)
460 return ARMul_INC;
461 else
462 return ARMul_DONE;
463 }
464 }
465
466 return -1;
467}
468int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value)
469{
470 static int i = 0;
471 static int single_regs, d, imm32, regs;
472 if (type == ARMul_FIRST)
473 {
474 single_regs = BIT(instr, 8) == 0; // Single precision
475 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
476 imm32 = BITS(instr, 0,7)<<2; // may not be used
477 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FSTMX if regs is odd
478
479 state->Reg[R13] = state->Reg[R13] - imm32;
480
481 i = 0;
482
483 return ARMul_DONE;
484 }
485 else if (type == ARMul_DATA)
486 {
487 if (single_regs)
488 {
489 *value = state->ExtReg[d + i];
490 i++;
491 if (i < regs)
492 return ARMul_INC;
493 else
494 return ARMul_DONE;
495 }
496 else
497 {
498 /* FIXME Careful of endianness, may need to rework this */
499 *value = state->ExtReg[d*2 + i];
500 i++;
501 if (i < regs*2)
502 return ARMul_INC;
503 else
504 return ARMul_DONE;
505 }
506 }
507
508 return -1;
509}
510int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value)
511{
512 static int i = 0;
513 static int single_regs, add, wback, d, n, imm32, regs;
514 if (type == ARMul_FIRST)
515 {
516 single_regs = BIT(instr, 8) == 0; // Single precision
517 add = BIT(instr, 23);
518 wback = BIT(instr, 21); // write-back
519 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
520 n = BITS(instr, 16, 19); // destination register
521 imm32 = BITS(instr, 0,7) * 4; // may not be used
522 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FSTMX if regs is odd
523
524 if (wback) {
525 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
526 }
527
528 i = 0;
529
530 return ARMul_DONE;
531 }
532 else if (type == ARMul_DATA)
533 {
534 if (single_regs)
535 {
536 *value = state->ExtReg[d + i];
537 i++;
538 if (i < regs)
539 return ARMul_INC;
540 else
541 return ARMul_DONE;
542 }
543 else
544 {
545 /* FIXME Careful of endianness, may need to rework this */
546 *value = state->ExtReg[d*2 + i];
547 i++;
548 if (i < regs*2)
549 return ARMul_INC;
550 else
551 return ARMul_DONE;
552 }
553 }
554
555 return -1;
556}
557
558/* ----------- LDC ------------ */
559int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value)
560{
561 static int i = 0;
562 static int single_regs, d, imm32, regs;
563 if (type == ARMul_FIRST)
564 {
565 single_regs = BIT(instr, 8) == 0; // Single precision
566 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
567 imm32 = BITS(instr, 0, 7)<<2; // may not be used
568 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FLDMX if regs is odd
569
570 state->Reg[R13] = state->Reg[R13] + imm32;
571
572 i = 0;
573
574 return ARMul_DONE;
575 }
576 else if (type == ARMul_TRANSFER)
577 {
578 return ARMul_DONE;
579 }
580 else if (type == ARMul_DATA)
581 {
582 if (single_regs)
583 {
584 state->ExtReg[d + i] = value;
585 i++;
586 if (i < regs)
587 return ARMul_INC;
588 else
589 return ARMul_DONE;
590 }
591 else
592 {
593 /* FIXME Careful of endianness, may need to rework this */
594 state->ExtReg[d*2 + i] = value;
595 i++;
596 if (i < regs*2)
597 return ARMul_INC;
598 else
599 return ARMul_DONE;
600 }
601 }
602
603 return -1;
604}
605int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value)
606{
607 static int i = 0;
608 static int single_reg, add, d, n, imm32, regs;
609 if (type == ARMul_FIRST)
610 {
611 single_reg = BIT(instr, 8) == 0; // Double precision
612 add = BIT(instr, 23);
613 imm32 = BITS(instr, 0, 7)<<2; // may not be used
614 d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
615 n = BITS(instr, 16, 19); // destination register
616
617 i = 0;
618 regs = 1;
619
620 return ARMul_DONE;
621 }
622 else if (type == ARMul_TRANSFER)
623 {
624 return ARMul_DONE;
625 }
626 else if (type == ARMul_DATA)
627 {
628 if (single_reg)
629 {
630 state->ExtReg[d+i] = value;
631 i++;
632 if (i < regs)
633 return ARMul_INC;
634 else
635 return ARMul_DONE;
636 }
637 else
638 {
639 /* FIXME Careful of endianness, may need to rework this */
640 state->ExtReg[d*2+i] = value;
641 i++;
642 if (i < regs*2)
643 return ARMul_INC;
644 else
645 return ARMul_DONE;
646 }
647 }
648
649 return -1;
650}
651int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value)
652{
653 static int i = 0;
654 static int single_regs, add, wback, d, n, imm32, regs;
655 if (type == ARMul_FIRST)
656 {
657 single_regs = BIT(instr, 8) == 0; // Single precision
658 add = BIT(instr, 23);
659 wback = BIT(instr, 21); // write-back
660 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
661 n = BITS(instr, 16, 19); // destination register
662 imm32 = BITS(instr, 0, 7) * 4; // may not be used
663 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FLDMX if regs is odd
664
665 if (wback) {
666 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
667 }
668
669 i = 0;
670
671 return ARMul_DONE;
672 }
673 else if (type == ARMul_DATA)
674 {
675 if (single_regs)
676 {
677 state->ExtReg[d + i] = value;
678 i++;
679 if (i < regs)
680 return ARMul_INC;
681 else
682 return ARMul_DONE;
683 }
684 else
685 {
686 /* FIXME Careful of endianness, may need to rework this */
687 state->ExtReg[d*2 + i] = value;
688 i++;
689 if (i < regs*2)
690 return ARMul_INC;
691 else
692 return ARMul_DONE;
693 }
694 }
695
696 return -1;
697}
698
699/* ----------- CDP ------------ */
700void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm) 91void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm)
701{ 92{
702 if (single) 93 if (single)
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index 1b72383e7..727350f14 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -28,13 +28,6 @@
28#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]); 28#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
29 29
30unsigned VFPInit(ARMul_State* state); 30unsigned VFPInit(ARMul_State* state);
31unsigned VFPMRC(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
32unsigned VFPMCR(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
33unsigned VFPMRRC(ARMul_State* state, unsigned type, ARMword instr, ARMword* value1, ARMword* value2);
34unsigned VFPMCRR(ARMul_State* state, unsigned type, ARMword instr, ARMword value1, ARMword value2);
35unsigned VFPSTC(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
36unsigned VFPLDC(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
37unsigned VFPCDP(ARMul_State* state, unsigned type, ARMword instr);
38 31
39s32 vfp_get_float(ARMul_State* state, u32 reg); 32s32 vfp_get_float(ARMul_State* state, u32 reg);
40void vfp_put_float(ARMul_State* state, s32 val, u32 reg); 33void 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
44u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); 37u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
45u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); 38u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
46 39
47// MRC 40void VMSR(ARMul_State* state, ARMword reg, ARMword Rt);
48void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value);
49void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value); 41void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value);
50void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); 42void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2);
51void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); 43void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2);
52void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm); 44void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
53void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm); 45void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
54 46
55// MCR
56void VMSR(ARMul_State* state, ARMword reg, ARMword Rt);
57
58// STC
59int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value);
60int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value);
61int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value);
62
63// LDC
64int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value);
65int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value);
66int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value);