summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2014-05-15 22:54:17 -0400
committerGravatar bunnei2014-05-15 22:54:17 -0400
commit3e1eafa244dc2ea6a1d8de6e841370c83c362dda (patch)
treef4fb8778ccb4d71cc73c10a7ad4d0be62acc4533 /src
parentMerge pull request #15 from bunnei/hle-services (diff)
downloadyuzu-3e1eafa244dc2ea6a1d8de6e841370c83c362dda.tar.gz
yuzu-3e1eafa244dc2ea6a1d8de6e841370c83c362dda.tar.xz
yuzu-3e1eafa244dc2ea6a1d8de6e841370c83c362dda.zip
- moved mmu to arm/interpreter folder
- added initial VFP code from skyeye
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt6
-rw-r--r--src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp (renamed from src/core/arm/mmu/arm1176jzf_s_mmu.cpp)0
-rw-r--r--src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h (renamed from src/core/arm/mmu/arm1176jzf_s_mmu.h)0
-rw-r--r--src/core/arm/interpreter/mmu/cache.h (renamed from src/core/arm/mmu/cache.h)0
-rw-r--r--src/core/arm/interpreter/mmu/rb.h (renamed from src/core/arm/mmu/rb.h)0
-rw-r--r--src/core/arm/interpreter/mmu/tlb.h (renamed from src/core/arm/mmu/tlb.h)0
-rw-r--r--src/core/arm/interpreter/mmu/wb.h (renamed from src/core/arm/mmu/wb.h)0
-rw-r--r--src/core/arm/interpreter/vfp/asm_vfp.h84
-rw-r--r--src/core/arm/interpreter/vfp/vfp.cpp357
-rw-r--r--src/core/arm/interpreter/vfp/vfp.h111
-rw-r--r--src/core/arm/interpreter/vfp/vfp_helper.h541
-rw-r--r--src/core/arm/interpreter/vfp/vfpdouble.cpp1262
-rw-r--r--src/core/arm/interpreter/vfp/vfpinstr.cpp5123
-rw-r--r--src/core/arm/interpreter/vfp/vfpsingle.cpp1277
-rw-r--r--src/core/core.vcxproj7
-rw-r--r--src/core/core.vcxproj.filters24
16 files changed, 8791 insertions, 1 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index eb4fef381..0d4a0ca7a 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -14,7 +14,11 @@ set(SRCS core.cpp
14 arm/interpreter/armsupp.cpp 14 arm/interpreter/armsupp.cpp
15 arm/interpreter/armvirt.cpp 15 arm/interpreter/armvirt.cpp
16 arm/interpreter/thumbemu.cpp 16 arm/interpreter/thumbemu.cpp
17 arm/mmu/arm1176jzf_s_mmu.cpp 17 arm/interpreter/vfp/vfp.cpp
18 arm/interpreter/vfp/vfpdouble.cpp
19 arm/interpreter/vfp/vfpinsr.cpp
20 arm/interpreter/vfp/vfpsingle.cpp
21 arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
18 elf/elf_reader.cpp 22 elf/elf_reader.cpp
19 file_sys/directory_file_system.cpp 23 file_sys/directory_file_system.cpp
20 file_sys/meta_file_system.cpp 24 file_sys/meta_file_system.cpp
diff --git a/src/core/arm/mmu/arm1176jzf_s_mmu.cpp b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
index a32f076b9..a32f076b9 100644
--- a/src/core/arm/mmu/arm1176jzf_s_mmu.cpp
+++ b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
diff --git a/src/core/arm/mmu/arm1176jzf_s_mmu.h b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h
index 299c6b46b..299c6b46b 100644
--- a/src/core/arm/mmu/arm1176jzf_s_mmu.h
+++ b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h
diff --git a/src/core/arm/mmu/cache.h b/src/core/arm/interpreter/mmu/cache.h
index d308d9b87..d308d9b87 100644
--- a/src/core/arm/mmu/cache.h
+++ b/src/core/arm/interpreter/mmu/cache.h
diff --git a/src/core/arm/mmu/rb.h b/src/core/arm/interpreter/mmu/rb.h
index 7bf0ebb26..7bf0ebb26 100644
--- a/src/core/arm/mmu/rb.h
+++ b/src/core/arm/interpreter/mmu/rb.h
diff --git a/src/core/arm/mmu/tlb.h b/src/core/arm/interpreter/mmu/tlb.h
index 938c01786..938c01786 100644
--- a/src/core/arm/mmu/tlb.h
+++ b/src/core/arm/interpreter/mmu/tlb.h
diff --git a/src/core/arm/mmu/wb.h b/src/core/arm/interpreter/mmu/wb.h
index 8fb7de946..8fb7de946 100644
--- a/src/core/arm/mmu/wb.h
+++ b/src/core/arm/interpreter/mmu/wb.h
diff --git a/src/core/arm/interpreter/vfp/asm_vfp.h b/src/core/arm/interpreter/vfp/asm_vfp.h
new file mode 100644
index 000000000..f4ab34fd4
--- /dev/null
+++ b/src/core/arm/interpreter/vfp/asm_vfp.h
@@ -0,0 +1,84 @@
1/*
2 * arch/arm/include/asm/vfp.h
3 *
4 * VFP register definitions.
5 * First, the standard VFP set.
6 */
7
8#define FPSID cr0
9#define FPSCR cr1
10#define MVFR1 cr6
11#define MVFR0 cr7
12#define FPEXC cr8
13#define FPINST cr9
14#define FPINST2 cr10
15
16/* FPSID bits */
17#define FPSID_IMPLEMENTER_BIT (24)
18#define FPSID_IMPLEMENTER_MASK (0xff << FPSID_IMPLEMENTER_BIT)
19#define FPSID_SOFTWARE (1<<23)
20#define FPSID_FORMAT_BIT (21)
21#define FPSID_FORMAT_MASK (0x3 << FPSID_FORMAT_BIT)
22#define FPSID_NODOUBLE (1<<20)
23#define FPSID_ARCH_BIT (16)
24#define FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT)
25#define FPSID_PART_BIT (8)
26#define FPSID_PART_MASK (0xFF << FPSID_PART_BIT)
27#define FPSID_VARIANT_BIT (4)
28#define FPSID_VARIANT_MASK (0xF << FPSID_VARIANT_BIT)
29#define FPSID_REV_BIT (0)
30#define FPSID_REV_MASK (0xF << FPSID_REV_BIT)
31
32/* FPEXC bits */
33#define FPEXC_EX (1 << 31)
34#define FPEXC_EN (1 << 30)
35#define FPEXC_DEX (1 << 29)
36#define FPEXC_FP2V (1 << 28)
37#define FPEXC_VV (1 << 27)
38#define FPEXC_TFV (1 << 26)
39#define FPEXC_LENGTH_BIT (8)
40#define FPEXC_LENGTH_MASK (7 << FPEXC_LENGTH_BIT)
41#define FPEXC_IDF (1 << 7)
42#define FPEXC_IXF (1 << 4)
43#define FPEXC_UFF (1 << 3)
44#define FPEXC_OFF (1 << 2)
45#define FPEXC_DZF (1 << 1)
46#define FPEXC_IOF (1 << 0)
47#define FPEXC_TRAP_MASK (FPEXC_IDF|FPEXC_IXF|FPEXC_UFF|FPEXC_OFF|FPEXC_DZF|FPEXC_IOF)
48
49/* FPSCR bits */
50#define FPSCR_DEFAULT_NAN (1<<25)
51#define FPSCR_FLUSHTOZERO (1<<24)
52#define FPSCR_ROUND_NEAREST (0<<22)
53#define FPSCR_ROUND_PLUSINF (1<<22)
54#define FPSCR_ROUND_MINUSINF (2<<22)
55#define FPSCR_ROUND_TOZERO (3<<22)
56#define FPSCR_RMODE_BIT (22)
57#define FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT)
58#define FPSCR_STRIDE_BIT (20)
59#define FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT)
60#define FPSCR_LENGTH_BIT (16)
61#define FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT)
62#define FPSCR_IOE (1<<8)
63#define FPSCR_DZE (1<<9)
64#define FPSCR_OFE (1<<10)
65#define FPSCR_UFE (1<<11)
66#define FPSCR_IXE (1<<12)
67#define FPSCR_IDE (1<<15)
68#define FPSCR_IOC (1<<0)
69#define FPSCR_DZC (1<<1)
70#define FPSCR_OFC (1<<2)
71#define FPSCR_UFC (1<<3)
72#define FPSCR_IXC (1<<4)
73#define FPSCR_IDC (1<<7)
74
75/* MVFR0 bits */
76#define MVFR0_A_SIMD_BIT (0)
77#define MVFR0_A_SIMD_MASK (0xf << MVFR0_A_SIMD_BIT)
78
79/* Bit patterns for decoding the packaged operation descriptors */
80#define VFPOPDESC_LENGTH_BIT (9)
81#define VFPOPDESC_LENGTH_MASK (0x07 << VFPOPDESC_LENGTH_BIT)
82#define VFPOPDESC_UNUSED_BIT (24)
83#define VFPOPDESC_UNUSED_MASK (0xFF << VFPOPDESC_UNUSED_BIT)
84#define VFPOPDESC_OPDESC_MASK (~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK))
diff --git a/src/core/arm/interpreter/vfp/vfp.cpp b/src/core/arm/interpreter/vfp/vfp.cpp
new file mode 100644
index 000000000..eea5e24a9
--- /dev/null
+++ b/src/core/arm/interpreter/vfp/vfp.cpp
@@ -0,0 +1,357 @@
1/*
2 armvfp.c - ARM VFPv3 emulation unit
3 Copyright (C) 2003 Skyeye Develop Group
4 for help please send mail to <skyeye-developer@lists.gro.clinux.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21/* Note: this file handles interface with arm core and vfp registers */
22
23/* Opens debug for classic interpreter only */
24//#define DEBUG
25
26#include "common/common.h"
27
28#include "core/arm/interpreter/armdefs.h"
29#include "core/arm/interpreter/vfp/vfp.h"
30
31//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */
32
33unsigned
34VFPInit (ARMul_State *state)
35{
36 state->VFP[VFP_OFFSET(VFP_FPSID)] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 |
37 VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION;
38 state->VFP[VFP_OFFSET(VFP_FPEXC)] = 0;
39 state->VFP[VFP_OFFSET(VFP_FPSCR)] = 0;
40
41 //persistent_state = state;
42 /* Reset only specify VFP_FPEXC_EN = '0' */
43
44 return No_exp;
45}
46
47unsigned
48VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value)
49{
50 /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
51 int CoProc = BITS (8, 11); /* 10 or 11 */
52 int OPC_1 = BITS (21, 23);
53 int Rt = BITS (12, 15);
54 int CRn = BITS (16, 19);
55 int CRm = BITS (0, 3);
56 int OPC_2 = BITS (5, 7);
57
58 /* TODO check access permission */
59
60 /* CRn/opc1 CRm/opc2 */
61
62 if (CoProc == 10 || CoProc == 11)
63 {
64 #define VFP_MRC_TRANS
65 #include "core/arm/interpreter/vfp/vfpinstr.cpp"
66 #undef VFP_MRC_TRANS
67 }
68 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
69 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
70
71 return ARMul_CANT;
72}
73
74unsigned
75VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
76{
77 /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
78 int CoProc = BITS (8, 11); /* 10 or 11 */
79 int OPC_1 = BITS (21, 23);
80 int Rt = BITS (12, 15);
81 int CRn = BITS (16, 19);
82 int CRm = BITS (0, 3);
83 int OPC_2 = BITS (5, 7);
84
85 /* TODO check access permission */
86
87 /* CRn/opc1 CRm/opc2 */
88 if (CoProc == 10 || CoProc == 11)
89 {
90 #define VFP_MCR_TRANS
91 #include "core/arm/interpreter/vfp/vfpinstr.cpp"
92 #undef VFP_MCR_TRANS
93 }
94 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
95 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
96
97 return ARMul_CANT;
98}
99
100unsigned
101VFPMRRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value1, ARMword * value2)
102{
103 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
104 int CoProc = BITS (8, 11); /* 10 or 11 */
105 int OPC_1 = BITS (4, 7);
106 int Rt = BITS (12, 15);
107 int Rt2 = BITS (16, 19);
108 int CRm = BITS (0, 3);
109
110 if (CoProc == 10 || CoProc == 11)
111 {
112 #define VFP_MRRC_TRANS
113 #include "core/arm/interpreter/vfp/vfpinstr.cpp"
114 #undef VFP_MRRC_TRANS
115 }
116 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
117 instr, CoProc, OPC_1, Rt, Rt2, CRm);
118
119 return ARMul_CANT;
120}
121
122unsigned
123VFPMCRR (ARMul_State * state, unsigned type, ARMword instr, ARMword value1, ARMword value2)
124{
125 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
126 int CoProc = BITS (8, 11); /* 10 or 11 */
127 int OPC_1 = BITS (4, 7);
128 int Rt = BITS (12, 15);
129 int Rt2 = BITS (16, 19);
130 int CRm = BITS (0, 3);
131
132 /* TODO check access permission */
133
134 /* CRn/opc1 CRm/opc2 */
135
136 if (CoProc == 11 || CoProc == 10)
137 {
138 #define VFP_MCRR_TRANS
139 #include "core/arm/interpreter/vfp/vfpinstr.cpp"
140 #undef VFP_MCRR_TRANS
141 }
142 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
143 instr, CoProc, OPC_1, Rt, Rt2, CRm);
144
145 return ARMul_CANT;
146}
147
148unsigned
149VFPSTC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value)
150{
151 /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */
152 int CoProc = BITS (8, 11); /* 10 or 11 */
153 int CRd = BITS (12, 15);
154 int Rn = BITS (16, 19);
155 int imm8 = BITS (0, 7);
156 int P = BIT(24);
157 int U = BIT(23);
158 int D = BIT(22);
159 int W = BIT(21);
160
161 /* TODO check access permission */
162
163 /* VSTM */
164 if ( (P|U|D|W) == 0 )
165 {
166 DEBUG_LOG(ARM11, "In %s, UNDEFINED\n", __FUNCTION__); exit(-1);
167 }
168 if (CoProc == 10 || CoProc == 11)
169 {
170 #if 1
171 if (P == 0 && U == 0 && W == 0)
172 {
173 DEBUG_LOG(ARM11, "VSTM Related encodings\n"); exit(-1);
174 }
175 if (P == U && W == 1)
176 {
177 DEBUG_LOG(ARM11, "UNDEFINED\n"); exit(-1);
178 }
179 #endif
180
181 #define VFP_STC_TRANS
182 #include "core/arm/interpreter/vfp/vfpinstr.cpp"
183 #undef VFP_STC_TRANS
184 }
185 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
186 instr, CoProc, CRd, Rn, imm8, P, U, D, W);
187
188 return ARMul_CANT;
189}
190
191unsigned
192VFPLDC (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
193{
194 /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */
195 int CoProc = BITS (8, 11); /* 10 or 11 */
196 int CRd = BITS (12, 15);
197 int Rn = BITS (16, 19);
198 int imm8 = BITS (0, 7);
199 int P = BIT(24);
200 int U = BIT(23);
201 int D = BIT(22);
202 int W = BIT(21);
203
204 /* TODO check access permission */
205
206 if ( (P|U|D|W) == 0 )
207 {
208 DEBUG_LOG(ARM11, "In %s, UNDEFINED\n", __FUNCTION__); exit(-1);
209 }
210 if (CoProc == 10 || CoProc == 11)
211 {
212 #define VFP_LDC_TRANS
213 #include "core/arm/interpreter/vfp/vfpinstr.cpp"
214 #undef VFP_LDC_TRANS
215 }
216 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
217 instr, CoProc, CRd, Rn, imm8, P, U, D, W);
218
219 return ARMul_CANT;
220}
221
222unsigned
223VFPCDP (ARMul_State * state, unsigned type, ARMword instr)
224{
225 /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */
226 int CoProc = BITS (8, 11); /* 10 or 11 */
227 int OPC_1 = BITS (20, 23);
228 int CRd = BITS (12, 15);
229 int CRn = BITS (16, 19);
230 int CRm = BITS (0, 3);
231 int OPC_2 = BITS (5, 7);
232
233 /* TODO check access permission */
234
235 /* CRn/opc1 CRm/opc2 */
236
237 if (CoProc == 10 || CoProc == 11)
238 {
239 #define VFP_CDP_TRANS
240 #include "core/arm/interpreter/vfp/vfpinstr.cpp"
241 #undef VFP_CDP_TRANS
242
243 int exceptions = 0;
244 if (CoProc == 10)
245 exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
246 else
247 exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
248
249 vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
250
251 return ARMul_DONE;
252 }
253 DEBUG_LOG(ARM11, "Can't identify %x\n", instr);
254 return ARMul_CANT;
255}
256
257
258/* ----------- MRC ------------ */
259#define VFP_MRC_IMPL
260#include "core/arm/interpreter/vfp/vfpinstr.cpp"
261#undef VFP_MRC_IMPL
262
263#define VFP_MRRC_IMPL
264#include "core/arm/interpreter/vfp/vfpinstr.cpp"
265#undef VFP_MRRC_IMPL
266
267
268/* ----------- MCR ------------ */
269#define VFP_MCR_IMPL
270#include "core/arm/interpreter/vfp/vfpinstr.cpp"
271#undef VFP_MCR_IMPL
272
273#define VFP_MCRR_IMPL
274#include "core/arm/interpreter/vfp/vfpinstr.cpp"
275#undef VFP_MCRR_IMPL
276
277/* Memory operation are not inlined, as old Interpreter and Fast interpreter
278 don't have the same memory operation interface.
279 Old interpreter framework does one access to coprocessor per data, and
280 handles already data write, as well as address computation,
281 which is not the case for Fast interpreter. Therefore, implementation
282 of vfp instructions in old interpreter and fast interpreter are separate. */
283
284/* ----------- STC ------------ */
285#define VFP_STC_IMPL
286#include "core/arm/interpreter/vfp/vfpinstr.cpp"
287#undef VFP_STC_IMPL
288
289
290/* ----------- LDC ------------ */
291#define VFP_LDC_IMPL
292#include "core/arm/interpreter/vfp/vfpinstr.cpp"
293#undef VFP_LDC_IMPL
294
295
296/* ----------- CDP ------------ */
297#define VFP_CDP_IMPL
298#include "core/arm/interpreter/vfp/vfpinstr.cpp"
299#undef VFP_CDP_IMPL
300
301/* Miscellaneous functions */
302int32_t vfp_get_float(arm_core_t* state, unsigned int reg)
303{
304 DBG("VFP get float: s%d=[%08x]\n", reg, state->ExtReg[reg]);
305 return state->ExtReg[reg];
306}
307
308void vfp_put_float(arm_core_t* state, int32_t val, unsigned int reg)
309{
310 DBG("VFP put float: s%d <= [%08x]\n", reg, val);
311 state->ExtReg[reg] = val;
312}
313
314uint64_t vfp_get_double(arm_core_t* state, unsigned int reg)
315{
316 uint64_t result;
317 result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2];
318 DBG("VFP get double: s[%d-%d]=[%016llx]\n", reg*2+1, reg*2, result);
319 return result;
320}
321
322void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg)
323{
324 DBG("VFP put double: s[%d-%d] <= [%08x-%08x]\n", reg*2+1, reg*2, (uint32_t) (val>>32), (uint32_t) (val & 0xffffffff));
325 state->ExtReg[reg*2] = (uint32_t) (val & 0xffffffff);
326 state->ExtReg[reg*2+1] = (uint32_t) (val>>32);
327}
328
329
330
331/*
332 * Process bitmask of exception conditions. (from vfpmodule.c)
333 */
334void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr)
335{
336 int si_code = 0;
337
338 vfpdebug("VFP: raising exceptions %08x\n", exceptions);
339
340 if (exceptions == VFP_EXCEPTION_ERROR) {
341 DEBUG_LOG(ARM11, "unhandled bounce %x\n", inst);
342 exit(-1);
343 return;
344 }
345
346 /*
347 * If any of the status flags are set, update the FPSCR.
348 * Comparison instructions always return at least one of
349 * these flags set.
350 */
351 if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V))
352 fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V);
353
354 fpscr |= exceptions;
355
356 state->VFP[VFP_OFFSET(VFP_FPSCR)] = fpscr;
357}
diff --git a/src/core/arm/interpreter/vfp/vfp.h b/src/core/arm/interpreter/vfp/vfp.h
new file mode 100644
index 000000000..e16076310
--- /dev/null
+++ b/src/core/arm/interpreter/vfp/vfp.h
@@ -0,0 +1,111 @@
1/*
2 vfp/vfp.h - ARM VFPv3 emulation unit - vfp interface
3 Copyright (C) 2003 Skyeye Develop Group
4 for help please send mail to <skyeye-developer@lists.gro.clinux.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21#ifndef __VFP_H__
22#define __VFP_H__
23
24#define DBG(msg) DEBUG_LOG(ARM11, msg)
25
26#define vfpdebug //printf
27
28#include "core/arm/interpreter/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */
29
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
39/* FPSID Information */
40#define VFP_FPSID_IMPLMEN 0 /* should be the same as cp15 0 c0 0*/
41#define VFP_FPSID_SW 0
42#define VFP_FPSID_SUBARCH 0x2 /* VFP version. Current is v3 (not strict) */
43#define VFP_FPSID_PARTNUM 0x1
44#define VFP_FPSID_VARIANT 0x1
45#define VFP_FPSID_REVISION 0x1
46
47/* FPEXC Flags */
48#define VFP_FPEXC_EX 1<<31
49#define VFP_FPEXC_EN 1<<30
50
51/* FPSCR Flags */
52#define VFP_FPSCR_NFLAG 1<<31
53#define VFP_FPSCR_ZFLAG 1<<30
54#define VFP_FPSCR_CFLAG 1<<29
55#define VFP_FPSCR_VFLAG 1<<28
56
57#define VFP_FPSCR_AHP 1<<26 /* Alternative Half Precision */
58#define VFP_FPSCR_DN 1<<25 /* Default NaN */
59#define VFP_FPSCR_FZ 1<<24 /* Flush-to-zero */
60#define VFP_FPSCR_RMODE 3<<22 /* Rounding Mode */
61#define VFP_FPSCR_STRIDE 3<<20 /* Stride (vector) */
62#define VFP_FPSCR_LEN 7<<16 /* Stride (vector) */
63
64#define VFP_FPSCR_IDE 1<<15 /* Input Denormal exc */
65#define VFP_FPSCR_IXE 1<<12 /* Inexact exc */
66#define VFP_FPSCR_UFE 1<<11 /* Undeflow exc */
67#define VFP_FPSCR_OFE 1<<10 /* Overflow exc */
68#define VFP_FPSCR_DZE 1<<9 /* Division by Zero exc */
69#define VFP_FPSCR_IOE 1<<8 /* Invalid Operation exc */
70
71#define VFP_FPSCR_IDC 1<<7 /* Input Denormal cum exc */
72#define VFP_FPSCR_IXC 1<<4 /* Inexact cum exc */
73#define VFP_FPSCR_UFC 1<<3 /* Undeflow cum exc */
74#define VFP_FPSCR_OFC 1<<2 /* Overflow cum exc */
75#define VFP_FPSCR_DZC 1<<1 /* Division by Zero cum exc */
76#define VFP_FPSCR_IOC 1<<0 /* Invalid Operation cum exc */
77
78/* Inline instructions. Note: Used in a cpp file as well */
79#ifdef __cplusplus
80 extern "C" {
81#endif
82int32_t vfp_get_float(ARMul_State * state, unsigned int reg);
83void vfp_put_float(ARMul_State * state, int32_t val, unsigned int reg);
84uint64_t vfp_get_double(ARMul_State * state, unsigned int reg);
85void vfp_put_double(ARMul_State * state, uint64_t val, unsigned int reg);
86void vfp_raise_exceptions(ARMul_State * state, uint32_t exceptions, uint32_t inst, uint32_t fpscr);
87extern uint32_t vfp_single_cpdo(ARMul_State * state, uint32_t inst, uint32_t fpscr);
88extern uint32_t vfp_double_cpdo(ARMul_State * state, uint32_t inst, uint32_t fpscr);
89
90/* MRC */
91inline void VMRS(ARMul_State * state, ARMword reg, ARMword Rt, ARMword *value);
92inline void VMOVBRS(ARMul_State * state, ARMword to_arm, ARMword t, ARMword n, ARMword *value);
93inline void VMOVBRRD(ARMul_State * state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword *value1, ARMword *value2);
94inline void VMOVI(ARMul_State * state, ARMword single, ARMword d, ARMword imm);
95inline void VMOVR(ARMul_State * state, ARMword single, ARMword d, ARMword imm);
96/* MCR */
97inline void VMSR(ARMul_State * state, ARMword reg, ARMword Rt);
98/* STC */
99inline int VSTM(ARMul_State * state, int type, ARMword instr, ARMword* value);
100inline int VPUSH(ARMul_State * state, int type, ARMword instr, ARMword* value);
101inline int VSTR(ARMul_State * state, int type, ARMword instr, ARMword* value);
102/* LDC */
103inline int VLDM(ARMul_State * state, int type, ARMword instr, ARMword value);
104inline int VPOP(ARMul_State * state, int type, ARMword instr, ARMword value);
105inline int VLDR(ARMul_State * state, int type, ARMword instr, ARMword value);
106
107#ifdef __cplusplus
108 }
109#endif
110
111#endif
diff --git a/src/core/arm/interpreter/vfp/vfp_helper.h b/src/core/arm/interpreter/vfp/vfp_helper.h
new file mode 100644
index 000000000..80f9a93f4
--- /dev/null
+++ b/src/core/arm/interpreter/vfp/vfp_helper.h
@@ -0,0 +1,541 @@
1/*
2 vfp/vfp.h - ARM VFPv3 emulation unit - SoftFloat lib helper
3 Copyright (C) 2003 Skyeye Develop Group
4 for help please send mail to <skyeye-developer@lists.gro.clinux.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21/*
22 * The following code is derivative from Linux Android kernel vfp
23 * floating point support.
24 *
25 * Copyright (C) 2004 ARM Limited.
26 * Written by Deep Blue Solutions Limited.
27 *
28 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License version 2 as
30 * published by the Free Software Foundation.
31 */
32
33#ifndef __VFP_HELPER_H__
34#define __VFP_HELPER_H__
35
36/* Custom edit */
37
38#include <stdint.h>
39#include <stdio.h>
40
41#include "core/arm/interpreter/armdefs.h"
42
43#define u16 uint16_t
44#define u32 uint32_t
45#define u64 uint64_t
46#define s16 int16_t
47#define s32 int32_t
48#define s64 int64_t
49
50#define pr_info //printf
51#define pr_debug //printf
52
53static u32 fls(int x);
54#define do_div(n, base) {n/=base;}
55
56/* From vfpinstr.h */
57
58#define INST_CPRTDO(inst) (((inst) & 0x0f000000) == 0x0e000000)
59#define INST_CPRT(inst) ((inst) & (1 << 4))
60#define INST_CPRT_L(inst) ((inst) & (1 << 20))
61#define INST_CPRT_Rd(inst) (((inst) & (15 << 12)) >> 12)
62#define INST_CPRT_OP(inst) (((inst) >> 21) & 7)
63#define INST_CPNUM(inst) ((inst) & 0xf00)
64#define CPNUM(cp) ((cp) << 8)
65
66#define FOP_MASK (0x00b00040)
67#define FOP_FMAC (0x00000000)
68#define FOP_FNMAC (0x00000040)
69#define FOP_FMSC (0x00100000)
70#define FOP_FNMSC (0x00100040)
71#define FOP_FMUL (0x00200000)
72#define FOP_FNMUL (0x00200040)
73#define FOP_FADD (0x00300000)
74#define FOP_FSUB (0x00300040)
75#define FOP_FDIV (0x00800000)
76#define FOP_EXT (0x00b00040)
77
78#define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4)
79
80#define FEXT_MASK (0x000f0080)
81#define FEXT_FCPY (0x00000000)
82#define FEXT_FABS (0x00000080)
83#define FEXT_FNEG (0x00010000)
84#define FEXT_FSQRT (0x00010080)
85#define FEXT_FCMP (0x00040000)
86#define FEXT_FCMPE (0x00040080)
87#define FEXT_FCMPZ (0x00050000)
88#define FEXT_FCMPEZ (0x00050080)
89#define FEXT_FCVT (0x00070080)
90#define FEXT_FUITO (0x00080000)
91#define FEXT_FSITO (0x00080080)
92#define FEXT_FTOUI (0x000c0000)
93#define FEXT_FTOUIZ (0x000c0080)
94#define FEXT_FTOSI (0x000d0000)
95#define FEXT_FTOSIZ (0x000d0080)
96
97#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
98
99#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22)
100#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18)
101#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5)
102#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1)
103#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
104#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3)
105
106#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00)
107
108#define FPSCR_N (1 << 31)
109#define FPSCR_Z (1 << 30)
110#define FPSCR_C (1 << 29)
111#define FPSCR_V (1 << 28)
112
113/* -------------- */
114
115/* From asm/include/vfp.h */
116
117/* FPSCR bits */
118#define FPSCR_DEFAULT_NAN (1<<25)
119#define FPSCR_FLUSHTOZERO (1<<24)
120#define FPSCR_ROUND_NEAREST (0<<22)
121#define FPSCR_ROUND_PLUSINF (1<<22)
122#define FPSCR_ROUND_MINUSINF (2<<22)
123#define FPSCR_ROUND_TOZERO (3<<22)
124#define FPSCR_RMODE_BIT (22)
125#define FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT)
126#define FPSCR_STRIDE_BIT (20)
127#define FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT)
128#define FPSCR_LENGTH_BIT (16)
129#define FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT)
130#define FPSCR_IOE (1<<8)
131#define FPSCR_DZE (1<<9)
132#define FPSCR_OFE (1<<10)
133#define FPSCR_UFE (1<<11)
134#define FPSCR_IXE (1<<12)
135#define FPSCR_IDE (1<<15)
136#define FPSCR_IOC (1<<0)
137#define FPSCR_DZC (1<<1)
138#define FPSCR_OFC (1<<2)
139#define FPSCR_UFC (1<<3)
140#define FPSCR_IXC (1<<4)
141#define FPSCR_IDC (1<<7)
142
143/* ---------------- */
144
145static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
146{
147 if (shift) {
148 if (shift < 32)
149 val = val >> shift | ((val << (32 - shift)) != 0);
150 else
151 val = val != 0;
152 }
153 return val;
154}
155
156static inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
157{
158 if (shift) {
159 if (shift < 64)
160 val = val >> shift | ((val << (64 - shift)) != 0);
161 else
162 val = val != 0;
163 }
164 return val;
165}
166
167static inline u32 vfp_hi64to32jamming(u64 val)
168{
169 u32 v;
170 u32 highval = val >> 32;
171 u32 lowval = val & 0xffffffff;
172
173 if (lowval >= 1)
174 v = highval | 1;
175 else
176 v = highval;
177
178 return v;
179}
180
181static inline void add128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml)
182{
183 *resl = nl + ml;
184 *resh = nh + mh;
185 if (*resl < nl)
186 *resh += 1;
187}
188
189static inline void sub128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml)
190{
191 *resl = nl - ml;
192 *resh = nh - mh;
193 if (*resl > nl)
194 *resh -= 1;
195}
196
197static inline void mul64to128(u64 *resh, u64 *resl, u64 n, u64 m)
198{
199 u32 nh, nl, mh, ml;
200 u64 rh, rma, rmb, rl;
201
202 nl = n;
203 ml = m;
204 rl = (u64)nl * ml;
205
206 nh = n >> 32;
207 rma = (u64)nh * ml;
208
209 mh = m >> 32;
210 rmb = (u64)nl * mh;
211 rma += rmb;
212
213 rh = (u64)nh * mh;
214 rh += ((u64)(rma < rmb) << 32) + (rma >> 32);
215
216 rma <<= 32;
217 rl += rma;
218 rh += (rl < rma);
219
220 *resl = rl;
221 *resh = rh;
222}
223
224static inline void shift64left(u64 *resh, u64 *resl, u64 n)
225{
226 *resh = n >> 63;
227 *resl = n << 1;
228}
229
230static inline u64 vfp_hi64multiply64(u64 n, u64 m)
231{
232 u64 rh, rl;
233 mul64to128(&rh, &rl, n, m);
234 return rh | (rl != 0);
235}
236
237static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
238{
239 u64 mh, ml, remh, reml, termh, terml, z;
240
241 if (nh >= m)
242 return ~0ULL;
243 mh = m >> 32;
244 if (mh << 32 <= nh) {
245 z = 0xffffffff00000000ULL;
246 } else {
247 z = nh;
248 do_div(z, mh);
249 z <<= 32;
250 }
251 mul64to128(&termh, &terml, m, z);
252 sub128(&remh, &reml, nh, nl, termh, terml);
253 ml = m << 32;
254 while ((s64)remh < 0) {
255 z -= 0x100000000ULL;
256 add128(&remh, &reml, remh, reml, mh, ml);
257 }
258 remh = (remh << 32) | (reml >> 32);
259 if (mh << 32 <= remh) {
260 z |= 0xffffffff;
261 } else {
262 do_div(remh, mh);
263 z |= remh;
264 }
265 return z;
266}
267
268/*
269 * Operations on unpacked elements
270 */
271#define vfp_sign_negate(sign) (sign ^ 0x8000)
272
273/*
274 * Single-precision
275 */
276struct vfp_single {
277 s16 exponent;
278 u16 sign;
279 u32 significand;
280};
281
282#ifdef __cplusplus
283 extern "C" {
284#endif
285extern s32 vfp_get_float(ARMul_State * state, unsigned int reg);
286extern void vfp_put_float(ARMul_State * state, s32 val, unsigned int reg);
287#ifdef __cplusplus
288 }
289#endif
290
291/*
292 * VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa
293 * VFP_SINGLE_EXPONENT_BITS - number of bits in the exponent
294 * VFP_SINGLE_LOW_BITS - number of low bits in the unpacked significand
295 * which are not propagated to the float upon packing.
296 */
297#define VFP_SINGLE_MANTISSA_BITS (23)
298#define VFP_SINGLE_EXPONENT_BITS (8)
299#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2)
300#define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1)
301
302/*
303 * The bit in an unpacked float which indicates that it is a quiet NaN
304 */
305#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS))
306
307/*
308 * Operations on packed single-precision numbers
309 */
310#define vfp_single_packed_sign(v) ((v) & 0x80000000)
311#define vfp_single_packed_negate(v) ((v) ^ 0x80000000)
312#define vfp_single_packed_abs(v) ((v) & ~0x80000000)
313#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1))
314#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1))
315
316/*
317 * Unpack a single-precision float. Note that this returns the magnitude
318 * of the single-precision float mantissa with the 1. if necessary,
319 * aligned to bit 30.
320 */
321static inline void vfp_single_unpack(struct vfp_single *s, s32 val)
322{
323 u32 significand;
324
325 s->sign = vfp_single_packed_sign(val) >> 16,
326 s->exponent = vfp_single_packed_exponent(val);
327
328 significand = (u32) val;
329 significand = (significand << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2;
330 if (s->exponent && s->exponent != 255)
331 significand |= 0x40000000;
332 s->significand = significand;
333}
334
335/*
336 * Re-pack a single-precision float. This assumes that the float is
337 * already normalised such that the MSB is bit 30, _not_ bit 31.
338 */
339static inline s32 vfp_single_pack(struct vfp_single *s)
340{
341 u32 val;
342 val = (s->sign << 16) +
343 (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
344 (s->significand >> VFP_SINGLE_LOW_BITS);
345 return (s32)val;
346}
347
348#define VFP_NUMBER (1<<0)
349#define VFP_ZERO (1<<1)
350#define VFP_DENORMAL (1<<2)
351#define VFP_INFINITY (1<<3)
352#define VFP_NAN (1<<4)
353#define VFP_NAN_SIGNAL (1<<5)
354
355#define VFP_QNAN (VFP_NAN)
356#define VFP_SNAN (VFP_NAN|VFP_NAN_SIGNAL)
357
358static inline int vfp_single_type(struct vfp_single *s)
359{
360 int type = VFP_NUMBER;
361 if (s->exponent == 255) {
362 if (s->significand == 0)
363 type = VFP_INFINITY;
364 else if (s->significand & VFP_SINGLE_SIGNIFICAND_QNAN)
365 type = VFP_QNAN;
366 else
367 type = VFP_SNAN;
368 } else if (s->exponent == 0) {
369 if (s->significand == 0)
370 type |= VFP_ZERO;
371 else
372 type |= VFP_DENORMAL;
373 }
374 return type;
375}
376
377
378u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func);
379
380/*
381 * Double-precision
382 */
383struct vfp_double {
384 s16 exponent;
385 u16 sign;
386 u64 significand;
387};
388
389/*
390 * VFP_REG_ZERO is a special register number for vfp_get_double
391 * which returns (double)0.0. This is useful for the compare with
392 * zero instructions.
393 */
394#ifdef CONFIG_VFPv3
395#define VFP_REG_ZERO 32
396#else
397#define VFP_REG_ZERO 16
398#endif
399#ifdef __cplusplus
400 extern "C" {
401#endif
402extern u64 vfp_get_double(ARMul_State * state, unsigned int reg);
403extern void vfp_put_double(ARMul_State * state, u64 val, unsigned int reg);
404#ifdef __cplusplus
405 }
406#endif
407#define VFP_DOUBLE_MANTISSA_BITS (52)
408#define VFP_DOUBLE_EXPONENT_BITS (11)
409#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2)
410#define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1)
411
412/*
413 * The bit in an unpacked double which indicates that it is a quiet NaN
414 */
415#define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS))
416
417/*
418 * Operations on packed single-precision numbers
419 */
420#define vfp_double_packed_sign(v) ((v) & (1ULL << 63))
421#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63))
422#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63))
423#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
424#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1))
425
426/*
427 * Unpack a double-precision float. Note that this returns the magnitude
428 * of the double-precision float mantissa with the 1. if necessary,
429 * aligned to bit 62.
430 */
431static inline void vfp_double_unpack(struct vfp_double *s, s64 val)
432{
433 u64 significand;
434
435 s->sign = vfp_double_packed_sign(val) >> 48;
436 s->exponent = vfp_double_packed_exponent(val);
437
438 significand = (u64) val;
439 significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2;
440 if (s->exponent && s->exponent != 2047)
441 significand |= (1ULL << 62);
442 s->significand = significand;
443}
444
445/*
446 * Re-pack a double-precision float. This assumes that the float is
447 * already normalised such that the MSB is bit 30, _not_ bit 31.
448 */
449static inline s64 vfp_double_pack(struct vfp_double *s)
450{
451 u64 val;
452 val = ((u64)s->sign << 48) +
453 ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
454 (s->significand >> VFP_DOUBLE_LOW_BITS);
455 return (s64)val;
456}
457
458static inline int vfp_double_type(struct vfp_double *s)
459{
460 int type = VFP_NUMBER;
461 if (s->exponent == 2047) {
462 if (s->significand == 0)
463 type = VFP_INFINITY;
464 else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN)
465 type = VFP_QNAN;
466 else
467 type = VFP_SNAN;
468 } else if (s->exponent == 0) {
469 if (s->significand == 0)
470 type |= VFP_ZERO;
471 else
472 type |= VFP_DENORMAL;
473 }
474 return type;
475}
476
477u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func);
478
479u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
480
481/*
482 * A special flag to tell the normalisation code not to normalise.
483 */
484#define VFP_NAN_FLAG 0x100
485
486/*
487 * A bit pattern used to indicate the initial (unset) value of the
488 * exception mask, in case nothing handles an instruction. This
489 * doesn't include the NAN flag, which get masked out before
490 * we check for an error.
491 */
492#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG)
493
494/*
495 * A flag to tell vfp instruction type.
496 * OP_SCALAR - this operation always operates in scalar mode
497 * OP_SD - the instruction exceptionally writes to a single precision result.
498 * OP_DD - the instruction exceptionally writes to a double precision result.
499 * OP_SM - the instruction exceptionally reads from a single precision operand.
500 */
501#define OP_SCALAR (1 << 0)
502#define OP_SD (1 << 1)
503#define OP_DD (1 << 1)
504#define OP_SM (1 << 2)
505
506struct op {
507 u32 (* const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr);
508 u32 flags;
509};
510
511static inline u32 fls(int x)
512{
513 int r = 32;
514
515 if (!x)
516 return 0;
517 if (!(x & 0xffff0000u)) {
518 x <<= 16;
519 r -= 16;
520 }
521 if (!(x & 0xff000000u)) {
522 x <<= 8;
523 r -= 8;
524 }
525 if (!(x & 0xf0000000u)) {
526 x <<= 4;
527 r -= 4;
528 }
529 if (!(x & 0xc0000000u)) {
530 x <<= 2;
531 r -= 2;
532 }
533 if (!(x & 0x80000000u)) {
534 x <<= 1;
535 r -= 1;
536 }
537 return r;
538
539}
540
541#endif
diff --git a/src/core/arm/interpreter/vfp/vfpdouble.cpp b/src/core/arm/interpreter/vfp/vfpdouble.cpp
new file mode 100644
index 000000000..37fd28829
--- /dev/null
+++ b/src/core/arm/interpreter/vfp/vfpdouble.cpp
@@ -0,0 +1,1262 @@
1/*
2 vfp/vfpdouble.c - ARM VFPv3 emulation unit - SoftFloat double instruction
3 Copyright (C) 2003 Skyeye Develop Group
4 for help please send mail to <skyeye-developer@lists.gro.clinux.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21/*
22 * This code is derived in part from :
23 * - Android kernel
24 * - John R. Housers softfloat library, which
25 * carries the following notice:
26 *
27 * ===========================================================================
28 * This C source file is part of the SoftFloat IEC/IEEE Floating-point
29 * Arithmetic Package, Release 2.
30 *
31 * Written by John R. Hauser. This work was made possible in part by the
32 * International Computer Science Institute, located at Suite 600, 1947 Center
33 * Street, Berkeley, California 94704. Funding was partially provided by the
34 * National Science Foundation under grant MIP-9311980. The original version
35 * of this code was written as part of a project to build a fixed-point vector
36 * processor in collaboration with the University of California at Berkeley,
37 * overseen by Profs. Nelson Morgan and John Wawrzynek. More information
38 * is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
39 * arithmetic/softfloat.html'.
40 *
41 * THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
42 * has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
43 * TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
44 * PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
45 * AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
46 *
47 * Derivative works are acceptable, even for commercial purposes, so long as
48 * (1) they include prominent notice that the work is derivative, and (2) they
49 * include prominent notice akin to these three paragraphs for those parts of
50 * this code that are retained.
51 * ===========================================================================
52 */
53
54#include "vfp_helper.h"
55#include "asm_vfp.h"
56
57static struct vfp_double vfp_double_default_qnan = {
58 //.exponent = 2047,
59 //.sign = 0,
60 //.significand = VFP_DOUBLE_SIGNIFICAND_QNAN,
61};
62
63static void vfp_double_dump(const char *str, struct vfp_double *d)
64{
65 pr_debug("VFP: %s: sign=%d exponent=%d significand=%016llx\n",
66 str, d->sign != 0, d->exponent, d->significand);
67}
68
69static void vfp_double_normalise_denormal(struct vfp_double *vd)
70{
71 int bits = 31 - fls(vd->significand >> 32);
72 if (bits == 31)
73 bits = 63 - fls(vd->significand);
74
75 vfp_double_dump("normalise_denormal: in", vd);
76
77 if (bits) {
78 vd->exponent -= bits - 1;
79 vd->significand <<= bits;
80 }
81
82 vfp_double_dump("normalise_denormal: out", vd);
83}
84
85u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func)
86{
87 u64 significand, incr;
88 int exponent, shift, underflow;
89 u32 rmode;
90
91 vfp_double_dump("pack: in", vd);
92
93 /*
94 * Infinities and NaNs are a special case.
95 */
96 if (vd->exponent == 2047 && (vd->significand == 0 || exceptions))
97 goto pack;
98
99 /*
100 * Special-case zero.
101 */
102 if (vd->significand == 0) {
103 vd->exponent = 0;
104 goto pack;
105 }
106
107 exponent = vd->exponent;
108 significand = vd->significand;
109
110 shift = 32 - fls(significand >> 32);
111 if (shift == 32)
112 shift = 64 - fls(significand);
113 if (shift) {
114 exponent -= shift;
115 significand <<= shift;
116 }
117
118#if 1
119 vd->exponent = exponent;
120 vd->significand = significand;
121 vfp_double_dump("pack: normalised", vd);
122#endif
123
124 /*
125 * Tiny number?
126 */
127 underflow = exponent < 0;
128 if (underflow) {
129 significand = vfp_shiftright64jamming(significand, -exponent);
130 exponent = 0;
131#if 1
132 vd->exponent = exponent;
133 vd->significand = significand;
134 vfp_double_dump("pack: tiny number", vd);
135#endif
136 if (!(significand & ((1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1)))
137 underflow = 0;
138 }
139
140 /*
141 * Select rounding increment.
142 */
143 incr = 0;
144 rmode = fpscr & FPSCR_RMODE_MASK;
145
146 if (rmode == FPSCR_ROUND_NEAREST) {
147 incr = 1ULL << VFP_DOUBLE_LOW_BITS;
148 if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0)
149 incr -= 1;
150 } else if (rmode == FPSCR_ROUND_TOZERO) {
151 incr = 0;
152 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0))
153 incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1;
154
155 pr_debug("VFP: rounding increment = 0x%08llx\n", incr);
156
157 /*
158 * Is our rounding going to overflow?
159 */
160 if ((significand + incr) < significand) {
161 exponent += 1;
162 significand = (significand >> 1) | (significand & 1);
163 incr >>= 1;
164#if 1
165 vd->exponent = exponent;
166 vd->significand = significand;
167 vfp_double_dump("pack: overflow", vd);
168#endif
169 }
170
171 /*
172 * If any of the low bits (which will be shifted out of the
173 * number) are non-zero, the result is inexact.
174 */
175 if (significand & ((1 << (VFP_DOUBLE_LOW_BITS + 1)) - 1))
176 exceptions |= FPSCR_IXC;
177
178 /*
179 * Do our rounding.
180 */
181 significand += incr;
182
183 /*
184 * Infinity?
185 */
186 if (exponent >= 2046) {
187 exceptions |= FPSCR_OFC | FPSCR_IXC;
188 if (incr == 0) {
189 vd->exponent = 2045;
190 vd->significand = 0x7fffffffffffffffULL;
191 } else {
192 vd->exponent = 2047; /* infinity */
193 vd->significand = 0;
194 }
195 } else {
196 if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0)
197 exponent = 0;
198 if (exponent || significand > 0x8000000000000000ULL)
199 underflow = 0;
200 if (underflow)
201 exceptions |= FPSCR_UFC;
202 vd->exponent = exponent;
203 vd->significand = significand >> 1;
204 }
205
206 pack:
207 vfp_double_dump("pack: final", vd);
208 {
209 s64 d = vfp_double_pack(vd);
210 pr_debug("VFP: %s: d(d%d)=%016llx exceptions=%08x\n", func,
211 dd, d, exceptions);
212 vfp_put_double(state, d, dd);
213 }
214 return exceptions;
215}
216
217/*
218 * Propagate the NaN, setting exceptions if it is signalling.
219 * 'n' is always a NaN. 'm' may be a number, NaN or infinity.
220 */
221static u32
222vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn,
223 struct vfp_double *vdm, u32 fpscr)
224{
225 struct vfp_double *nan;
226 int tn, tm = 0;
227
228 tn = vfp_double_type(vdn);
229
230 if (vdm)
231 tm = vfp_double_type(vdm);
232
233 if (fpscr & FPSCR_DEFAULT_NAN)
234 /*
235 * Default NaN mode - always returns a quiet NaN
236 */
237 nan = &vfp_double_default_qnan;
238 else {
239 /*
240 * Contemporary mode - select the first signalling
241 * NAN, or if neither are signalling, the first
242 * quiet NAN.
243 */
244 if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN))
245 nan = vdn;
246 else
247 nan = vdm;
248 /*
249 * Make the NaN quiet.
250 */
251 nan->significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
252 }
253
254 *vdd = *nan;
255
256 /*
257 * If one was a signalling NAN, raise invalid operation.
258 */
259 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG;
260}
261
262/*
263 * Extended operations
264 */
265static u32 vfp_double_fabs(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
266{
267 pr_debug("In %s\n", __FUNCTION__);
268 vfp_put_double(state, vfp_double_packed_abs(vfp_get_double(state, dm)), dd);
269 return 0;
270}
271
272static u32 vfp_double_fcpy(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
273{
274 pr_debug("In %s\n", __FUNCTION__);
275 vfp_put_double(state, vfp_get_double(state, dm), dd);
276 return 0;
277}
278
279static u32 vfp_double_fneg(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
280{
281 pr_debug("In %s\n", __FUNCTION__);
282 vfp_put_double(state, vfp_double_packed_negate(vfp_get_double(state, dm)), dd);
283 return 0;
284}
285
286static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
287{
288 pr_debug("In %s\n", __FUNCTION__);
289 struct vfp_double vdm, vdd;
290 int ret, tm;
291
292 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
293 tm = vfp_double_type(&vdm);
294 if (tm & (VFP_NAN|VFP_INFINITY)) {
295 struct vfp_double *vdp = &vdd;
296
297 if (tm & VFP_NAN)
298 ret = vfp_propagate_nan(vdp, &vdm, NULL, fpscr);
299 else if (vdm.sign == 0) {
300 sqrt_copy:
301 vdp = &vdm;
302 ret = 0;
303 } else {
304 sqrt_invalid:
305 vdp = &vfp_double_default_qnan;
306 ret = FPSCR_IOC;
307 }
308 vfp_put_double(state, vfp_double_pack(vdp), dd);
309 return ret;
310 }
311
312 /*
313 * sqrt(+/- 0) == +/- 0
314 */
315 if (tm & VFP_ZERO)
316 goto sqrt_copy;
317
318 /*
319 * Normalise a denormalised number
320 */
321 if (tm & VFP_DENORMAL)
322 vfp_double_normalise_denormal(&vdm);
323
324 /*
325 * sqrt(<0) = invalid
326 */
327 if (vdm.sign)
328 goto sqrt_invalid;
329
330 vfp_double_dump("sqrt", &vdm);
331
332 /*
333 * Estimate the square root.
334 */
335 vdd.sign = 0;
336 vdd.exponent = ((vdm.exponent - 1023) >> 1) + 1023;
337 vdd.significand = (u64)vfp_estimate_sqrt_significand(vdm.exponent, vdm.significand >> 32) << 31;
338
339 vfp_double_dump("sqrt estimate1", &vdd);
340
341 vdm.significand >>= 1 + (vdm.exponent & 1);
342 vdd.significand += 2 + vfp_estimate_div128to64(vdm.significand, 0, vdd.significand);
343
344 vfp_double_dump("sqrt estimate2", &vdd);
345
346 /*
347 * And now adjust.
348 */
349 if ((vdd.significand & VFP_DOUBLE_LOW_BITS_MASK) <= 5) {
350 if (vdd.significand < 2) {
351 vdd.significand = ~0ULL;
352 } else {
353 u64 termh, terml, remh, reml;
354 vdm.significand <<= 2;
355 mul64to128(&termh, &terml, vdd.significand, vdd.significand);
356 sub128(&remh, &reml, vdm.significand, 0, termh, terml);
357 while ((s64)remh < 0) {
358 vdd.significand -= 1;
359 shift64left(&termh, &terml, vdd.significand);
360 terml |= 1;
361 add128(&remh, &reml, remh, reml, termh, terml);
362 }
363 vdd.significand |= (remh | reml) != 0;
364 }
365 }
366 vdd.significand = vfp_shiftright64jamming(vdd.significand, 1);
367
368 return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fsqrt");
369}
370
371/*
372 * Equal := ZC
373 * Less than := N
374 * Greater than := C
375 * Unordered := CV
376 */
377static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u32 fpscr)
378{
379 s64 d, m;
380 u32 ret = 0;
381
382 pr_debug("In %s, state=0x%x, fpscr=0x%x\n", __FUNCTION__, state, fpscr);
383 m = vfp_get_double(state, dm);
384 if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) {
385 ret |= FPSCR_C | FPSCR_V;
386 if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
387 /*
388 * Signalling NaN, or signalling on quiet NaN
389 */
390 ret |= FPSCR_IOC;
391 }
392
393 d = vfp_get_double(state, dd);
394 if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) {
395 ret |= FPSCR_C | FPSCR_V;
396 if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
397 /*
398 * Signalling NaN, or signalling on quiet NaN
399 */
400 ret |= FPSCR_IOC;
401 }
402
403 if (ret == 0) {
404 //printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m);
405 if (d == m || vfp_double_packed_abs(d | m) == 0) {
406 /*
407 * equal
408 */
409 ret |= FPSCR_Z | FPSCR_C;
410 //printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret);
411 } else if (vfp_double_packed_sign(d ^ m)) {
412 /*
413 * different signs
414 */
415 if (vfp_double_packed_sign(d))
416 /*
417 * d is negative, so d < m
418 */
419 ret |= FPSCR_N;
420 else
421 /*
422 * d is positive, so d > m
423 */
424 ret |= FPSCR_C;
425 } else if ((vfp_double_packed_sign(d) != 0) ^ (d < m)) {
426 /*
427 * d < m
428 */
429 ret |= FPSCR_N;
430 } else if ((vfp_double_packed_sign(d) != 0) ^ (d > m)) {
431 /*
432 * d > m
433 */
434 ret |= FPSCR_C;
435 }
436 }
437 pr_debug("In %s, state=0x%x, ret=0x%x\n", __FUNCTION__, state, ret);
438
439 return ret;
440}
441
442static u32 vfp_double_fcmp(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
443{
444 pr_debug("In %s\n", __FUNCTION__);
445 return vfp_compare(state, dd, 0, dm, fpscr);
446}
447
448static u32 vfp_double_fcmpe(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
449{
450 pr_debug("In %s\n", __FUNCTION__);
451 return vfp_compare(state, dd, 1, dm, fpscr);
452}
453
454static u32 vfp_double_fcmpz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
455{
456 pr_debug("In %s\n", __FUNCTION__);
457 return vfp_compare(state, dd, 0, VFP_REG_ZERO, fpscr);
458}
459
460static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
461{
462 pr_debug("In %s\n", __FUNCTION__);
463 return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr);
464}
465
466static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
467{
468 struct vfp_double vdm;
469 struct vfp_single vsd;
470 int tm;
471 u32 exceptions = 0;
472
473 pr_debug("In %s\n", __FUNCTION__);
474 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
475
476 tm = vfp_double_type(&vdm);
477
478 /*
479 * If we have a signalling NaN, signal invalid operation.
480 */
481 if (tm == VFP_SNAN)
482 exceptions = FPSCR_IOC;
483
484 if (tm & VFP_DENORMAL)
485 vfp_double_normalise_denormal(&vdm);
486
487 vsd.sign = vdm.sign;
488 vsd.significand = vfp_hi64to32jamming(vdm.significand);
489
490 /*
491 * If we have an infinity or a NaN, the exponent must be 255
492 */
493 if (tm & (VFP_INFINITY|VFP_NAN)) {
494 vsd.exponent = 255;
495 if (tm == VFP_QNAN)
496 vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
497 goto pack_nan;
498 } else if (tm & VFP_ZERO)
499 vsd.exponent = 0;
500 else
501 vsd.exponent = vdm.exponent - (1023 - 127);
502
503 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fcvts");
504
505 pack_nan:
506 vfp_put_float(state, vfp_single_pack(&vsd), sd);
507 return exceptions;
508}
509
510static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
511{
512 struct vfp_double vdm;
513 u32 m = vfp_get_float(state, dm);
514
515 pr_debug("In %s\n", __FUNCTION__);
516 vdm.sign = 0;
517 vdm.exponent = 1023 + 63 - 1;
518 vdm.significand = (u64)m;
519
520 return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fuito");
521}
522
523static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
524{
525 struct vfp_double vdm;
526 u32 m = vfp_get_float(state, dm);
527
528 pr_debug("In %s\n", __FUNCTION__);
529 vdm.sign = (m & 0x80000000) >> 16;
530 vdm.exponent = 1023 + 63 - 1;
531 vdm.significand = vdm.sign ? -m : m;
532
533 return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fsito");
534}
535
536static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
537{
538 struct vfp_double vdm;
539 u32 d, exceptions = 0;
540 int rmode = fpscr & FPSCR_RMODE_MASK;
541 int tm;
542
543 pr_debug("In %s\n", __FUNCTION__);
544 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
545
546 /*
547 * Do we have a denormalised number?
548 */
549 tm = vfp_double_type(&vdm);
550 if (tm & VFP_DENORMAL)
551 exceptions |= FPSCR_IDC;
552
553 if (tm & VFP_NAN)
554 vdm.sign = 0;
555
556 if (vdm.exponent >= 1023 + 32) {
557 d = vdm.sign ? 0 : 0xffffffff;
558 exceptions = FPSCR_IOC;
559 } else if (vdm.exponent >= 1023 - 1) {
560 int shift = 1023 + 63 - vdm.exponent;
561 u64 rem, incr = 0;
562
563 /*
564 * 2^0 <= m < 2^32-2^8
565 */
566 d = (vdm.significand << 1) >> shift;
567 rem = vdm.significand << (65 - shift);
568
569 if (rmode == FPSCR_ROUND_NEAREST) {
570 incr = 0x8000000000000000ULL;
571 if ((d & 1) == 0)
572 incr -= 1;
573 } else if (rmode == FPSCR_ROUND_TOZERO) {
574 incr = 0;
575 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) {
576 incr = ~0ULL;
577 }
578
579 if ((rem + incr) < rem) {
580 if (d < 0xffffffff)
581 d += 1;
582 else
583 exceptions |= FPSCR_IOC;
584 }
585
586 if (d && vdm.sign) {
587 d = 0;
588 exceptions |= FPSCR_IOC;
589 } else if (rem)
590 exceptions |= FPSCR_IXC;
591 } else {
592 d = 0;
593 if (vdm.exponent | vdm.significand) {
594 exceptions |= FPSCR_IXC;
595 if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0)
596 d = 1;
597 else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) {
598 d = 0;
599 exceptions |= FPSCR_IOC;
600 }
601 }
602 }
603
604 pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
605
606 vfp_put_float(state, d, sd);
607
608 return exceptions;
609}
610
611static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
612{
613 pr_debug("In %s\n", __FUNCTION__);
614 return vfp_double_ftoui(state, sd, unused, dm, FPSCR_ROUND_TOZERO);
615}
616
617static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
618{
619 struct vfp_double vdm;
620 u32 d, exceptions = 0;
621 int rmode = fpscr & FPSCR_RMODE_MASK;
622 int tm;
623
624 pr_debug("In %s\n", __FUNCTION__);
625 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
626 vfp_double_dump("VDM", &vdm);
627
628 /*
629 * Do we have denormalised number?
630 */
631 tm = vfp_double_type(&vdm);
632 if (tm & VFP_DENORMAL)
633 exceptions |= FPSCR_IDC;
634
635 if (tm & VFP_NAN) {
636 d = 0;
637 exceptions |= FPSCR_IOC;
638 } else if (vdm.exponent >= 1023 + 32) {
639 d = 0x7fffffff;
640 if (vdm.sign)
641 d = ~d;
642 exceptions |= FPSCR_IOC;
643 } else if (vdm.exponent >= 1023 - 1) {
644 int shift = 1023 + 63 - vdm.exponent; /* 58 */
645 u64 rem, incr = 0;
646
647 d = (vdm.significand << 1) >> shift;
648 rem = vdm.significand << (65 - shift);
649
650 if (rmode == FPSCR_ROUND_NEAREST) {
651 incr = 0x8000000000000000ULL;
652 if ((d & 1) == 0)
653 incr -= 1;
654 } else if (rmode == FPSCR_ROUND_TOZERO) {
655 incr = 0;
656 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) {
657 incr = ~0ULL;
658 }
659
660 if ((rem + incr) < rem && d < 0xffffffff)
661 d += 1;
662 if (d > 0x7fffffff + (vdm.sign != 0)) {
663 d = 0x7fffffff + (vdm.sign != 0);
664 exceptions |= FPSCR_IOC;
665 } else if (rem)
666 exceptions |= FPSCR_IXC;
667
668 if (vdm.sign)
669 d = -d;
670 } else {
671 d = 0;
672 if (vdm.exponent | vdm.significand) {
673 exceptions |= FPSCR_IXC;
674 if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0)
675 d = 1;
676 else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign)
677 d = -1;
678 }
679 }
680
681 pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
682
683 vfp_put_float(state, (s32)d, sd);
684
685 return exceptions;
686}
687
688static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
689{
690 pr_debug("In %s\n", __FUNCTION__);
691 return vfp_double_ftosi(state, dd, unused, dm, FPSCR_ROUND_TOZERO);
692}
693
694static struct op fops_ext[] = {
695 { vfp_double_fcpy, 0 }, //0x00000000 - FEXT_FCPY
696 { vfp_double_fabs, 0 }, //0x00000001 - FEXT_FABS
697 { vfp_double_fneg, 0 }, //0x00000002 - FEXT_FNEG
698 { vfp_double_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT
699 { NULL, 0 },
700 { NULL, 0 },
701 { NULL, 0 },
702 { NULL, 0 },
703 { vfp_double_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP
704 { vfp_double_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE
705 { vfp_double_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ
706 { vfp_double_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ
707 { NULL, 0 },
708 { NULL, 0 },
709 { NULL, 0 },
710 { vfp_double_fcvts, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT
711 { vfp_double_fuito, OP_SCALAR }, //0x00000010 - FEXT_FUITO
712 { vfp_double_fsito, OP_SCALAR }, //0x00000011 - FEXT_FSITO
713 { NULL, 0 },
714 { NULL, 0 },
715 { NULL, 0 },
716 { NULL, 0 },
717 { NULL, 0 },
718 { NULL, 0 },
719 { vfp_double_ftoui, OP_SCALAR }, //0x00000018 - FEXT_FTOUI
720 { vfp_double_ftouiz, OP_SCALAR }, //0x00000019 - FEXT_FTOUIZ
721 { vfp_double_ftosi, OP_SCALAR }, //0x0000001A - FEXT_FTOSI
722 { vfp_double_ftosiz, OP_SCALAR }, //0x0000001B - FEXT_FTOSIZ
723};
724
725
726
727
728static u32
729vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn,
730 struct vfp_double *vdm, u32 fpscr)
731{
732 struct vfp_double *vdp;
733 u32 exceptions = 0;
734 int tn, tm;
735
736 tn = vfp_double_type(vdn);
737 tm = vfp_double_type(vdm);
738
739 if (tn & tm & VFP_INFINITY) {
740 /*
741 * Two infinities. Are they different signs?
742 */
743 if (vdn->sign ^ vdm->sign) {
744 /*
745 * different signs -> invalid
746 */
747 exceptions = FPSCR_IOC;
748 vdp = &vfp_double_default_qnan;
749 } else {
750 /*
751 * same signs -> valid
752 */
753 vdp = vdn;
754 }
755 } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) {
756 /*
757 * One infinity and one number -> infinity
758 */
759 vdp = vdn;
760 } else {
761 /*
762 * 'n' is a NaN of some type
763 */
764 return vfp_propagate_nan(vdd, vdn, vdm, fpscr);
765 }
766 *vdd = *vdp;
767 return exceptions;
768}
769
770static u32
771vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,
772 struct vfp_double *vdm, u32 fpscr)
773{
774 u32 exp_diff;
775 u64 m_sig;
776
777 if (vdn->significand & (1ULL << 63) ||
778 vdm->significand & (1ULL << 63)) {
779 pr_info("VFP: bad FP values\n");
780 vfp_double_dump("VDN", vdn);
781 vfp_double_dump("VDM", vdm);
782 }
783
784 /*
785 * Ensure that 'n' is the largest magnitude number. Note that
786 * if 'n' and 'm' have equal exponents, we do not swap them.
787 * This ensures that NaN propagation works correctly.
788 */
789 if (vdn->exponent < vdm->exponent) {
790 struct vfp_double *t = vdn;
791 vdn = vdm;
792 vdm = t;
793 }
794
795 /*
796 * Is 'n' an infinity or a NaN? Note that 'm' may be a number,
797 * infinity or a NaN here.
798 */
799 if (vdn->exponent == 2047)
800 return vfp_double_fadd_nonnumber(vdd, vdn, vdm, fpscr);
801
802 /*
803 * We have two proper numbers, where 'vdn' is the larger magnitude.
804 *
805 * Copy 'n' to 'd' before doing the arithmetic.
806 */
807 *vdd = *vdn;
808
809 /*
810 * Align 'm' with the result.
811 */
812 exp_diff = vdn->exponent - vdm->exponent;
813 m_sig = vfp_shiftright64jamming(vdm->significand, exp_diff);
814
815 /*
816 * If the signs are different, we are really subtracting.
817 */
818 if (vdn->sign ^ vdm->sign) {
819 m_sig = vdn->significand - m_sig;
820 if ((s64)m_sig < 0) {
821 vdd->sign = vfp_sign_negate(vdd->sign);
822 m_sig = -m_sig;
823 } else if (m_sig == 0) {
824 vdd->sign = (fpscr & FPSCR_RMODE_MASK) ==
825 FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
826 }
827 } else {
828 m_sig += vdn->significand;
829 }
830 vdd->significand = m_sig;
831
832 return 0;
833}
834
835static u32
836vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn,
837 struct vfp_double *vdm, u32 fpscr)
838{
839 vfp_double_dump("VDN", vdn);
840 vfp_double_dump("VDM", vdm);
841
842 /*
843 * Ensure that 'n' is the largest magnitude number. Note that
844 * if 'n' and 'm' have equal exponents, we do not swap them.
845 * This ensures that NaN propagation works correctly.
846 */
847 if (vdn->exponent < vdm->exponent) {
848 struct vfp_double *t = vdn;
849 vdn = vdm;
850 vdm = t;
851 pr_debug("VFP: swapping M <-> N\n");
852 }
853
854 vdd->sign = vdn->sign ^ vdm->sign;
855
856 /*
857 * If 'n' is an infinity or NaN, handle it. 'm' may be anything.
858 */
859 if (vdn->exponent == 2047) {
860 if (vdn->significand || (vdm->exponent == 2047 && vdm->significand))
861 return vfp_propagate_nan(vdd, vdn, vdm, fpscr);
862 if ((vdm->exponent | vdm->significand) == 0) {
863 *vdd = vfp_double_default_qnan;
864 return FPSCR_IOC;
865 }
866 vdd->exponent = vdn->exponent;
867 vdd->significand = 0;
868 return 0;
869 }
870
871 /*
872 * If 'm' is zero, the result is always zero. In this case,
873 * 'n' may be zero or a number, but it doesn't matter which.
874 */
875 if ((vdm->exponent | vdm->significand) == 0) {
876 vdd->exponent = 0;
877 vdd->significand = 0;
878 return 0;
879 }
880
881 /*
882 * We add 2 to the destination exponent for the same reason
883 * as the addition case - though this time we have +1 from
884 * each input operand.
885 */
886 vdd->exponent = vdn->exponent + vdm->exponent - 1023 + 2;
887 vdd->significand = vfp_hi64multiply64(vdn->significand, vdm->significand);
888
889 vfp_double_dump("VDD", vdd);
890 return 0;
891}
892
893#define NEG_MULTIPLY (1 << 0)
894#define NEG_SUBTRACT (1 << 1)
895
896static u32
897vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr, u32 negate, char *func)
898{
899 struct vfp_double vdd, vdp, vdn, vdm;
900 u32 exceptions;
901
902 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
903 if (vdn.exponent == 0 && vdn.significand)
904 vfp_double_normalise_denormal(&vdn);
905
906 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
907 if (vdm.exponent == 0 && vdm.significand)
908 vfp_double_normalise_denormal(&vdm);
909
910 exceptions = vfp_double_multiply(&vdp, &vdn, &vdm, fpscr);
911 if (negate & NEG_MULTIPLY)
912 vdp.sign = vfp_sign_negate(vdp.sign);
913
914 vfp_double_unpack(&vdn, vfp_get_double(state, dd));
915 if (negate & NEG_SUBTRACT)
916 vdn.sign = vfp_sign_negate(vdn.sign);
917
918 exceptions |= vfp_double_add(&vdd, &vdn, &vdp, fpscr);
919
920 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, func);
921}
922
923/*
924 * Standard operations
925 */
926
927/*
928 * sd = sd + (sn * sm)
929 */
930static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
931{
932 pr_debug("In %s\n", __FUNCTION__);
933 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, 0, "fmac");
934}
935
936/*
937 * sd = sd - (sn * sm)
938 */
939static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
940{
941 pr_debug("In %s\n", __FUNCTION__);
942 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac");
943}
944
945/*
946 * sd = -sd + (sn * sm)
947 */
948static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
949{
950 pr_debug("In %s\n", __FUNCTION__);
951 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc");
952}
953
954/*
955 * sd = -sd - (sn * sm)
956 */
957static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
958{
959 pr_debug("In %s\n", __FUNCTION__);
960 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
961}
962
963/*
964 * sd = sn * sm
965 */
966static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
967{
968 struct vfp_double vdd, vdn, vdm;
969 u32 exceptions;
970
971 pr_debug("In %s\n", __FUNCTION__);
972 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
973 if (vdn.exponent == 0 && vdn.significand)
974 vfp_double_normalise_denormal(&vdn);
975
976 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
977 if (vdm.exponent == 0 && vdm.significand)
978 vfp_double_normalise_denormal(&vdm);
979
980 exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr);
981 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fmul");
982}
983
984/*
985 * sd = -(sn * sm)
986 */
987static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
988{
989 struct vfp_double vdd, vdn, vdm;
990 u32 exceptions;
991
992 pr_debug("In %s\n", __FUNCTION__);
993 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
994 if (vdn.exponent == 0 && vdn.significand)
995 vfp_double_normalise_denormal(&vdn);
996
997 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
998 if (vdm.exponent == 0 && vdm.significand)
999 vfp_double_normalise_denormal(&vdm);
1000
1001 exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr);
1002 vdd.sign = vfp_sign_negate(vdd.sign);
1003
1004 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fnmul");
1005}
1006
1007/*
1008 * sd = sn + sm
1009 */
1010static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
1011{
1012 struct vfp_double vdd, vdn, vdm;
1013 u32 exceptions;
1014
1015 pr_debug("In %s\n", __FUNCTION__);
1016 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
1017 if (vdn.exponent == 0 && vdn.significand)
1018 vfp_double_normalise_denormal(&vdn);
1019
1020 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
1021 if (vdm.exponent == 0 && vdm.significand)
1022 vfp_double_normalise_denormal(&vdm);
1023
1024 exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr);
1025
1026 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fadd");
1027}
1028
1029/*
1030 * sd = sn - sm
1031 */
1032static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
1033{
1034 struct vfp_double vdd, vdn, vdm;
1035 u32 exceptions;
1036
1037 pr_debug("In %s\n", __FUNCTION__);
1038 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
1039 if (vdn.exponent == 0 && vdn.significand)
1040 vfp_double_normalise_denormal(&vdn);
1041
1042 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
1043 if (vdm.exponent == 0 && vdm.significand)
1044 vfp_double_normalise_denormal(&vdm);
1045
1046 /*
1047 * Subtraction is like addition, but with a negated operand.
1048 */
1049 vdm.sign = vfp_sign_negate(vdm.sign);
1050
1051 exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr);
1052
1053 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fsub");
1054}
1055
1056/*
1057 * sd = sn / sm
1058 */
1059static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
1060{
1061 struct vfp_double vdd, vdn, vdm;
1062 u32 exceptions = 0;
1063 int tm, tn;
1064
1065 pr_debug("In %s\n", __FUNCTION__);
1066 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
1067 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
1068
1069 vdd.sign = vdn.sign ^ vdm.sign;
1070
1071 tn = vfp_double_type(&vdn);
1072 tm = vfp_double_type(&vdm);
1073
1074 /*
1075 * Is n a NAN?
1076 */
1077 if (tn & VFP_NAN)
1078 goto vdn_nan;
1079
1080 /*
1081 * Is m a NAN?
1082 */
1083 if (tm & VFP_NAN)
1084 goto vdm_nan;
1085
1086 /*
1087 * If n and m are infinity, the result is invalid
1088 * If n and m are zero, the result is invalid
1089 */
1090 if (tm & tn & (VFP_INFINITY|VFP_ZERO))
1091 goto invalid;
1092
1093 /*
1094 * If n is infinity, the result is infinity
1095 */
1096 if (tn & VFP_INFINITY)
1097 goto infinity;
1098
1099 /*
1100 * If m is zero, raise div0 exceptions
1101 */
1102 if (tm & VFP_ZERO)
1103 goto divzero;
1104
1105 /*
1106 * If m is infinity, or n is zero, the result is zero
1107 */
1108 if (tm & VFP_INFINITY || tn & VFP_ZERO)
1109 goto zero;
1110
1111 if (tn & VFP_DENORMAL)
1112 vfp_double_normalise_denormal(&vdn);
1113 if (tm & VFP_DENORMAL)
1114 vfp_double_normalise_denormal(&vdm);
1115
1116 /*
1117 * Ok, we have two numbers, we can perform division.
1118 */
1119 vdd.exponent = vdn.exponent - vdm.exponent + 1023 - 1;
1120 vdm.significand <<= 1;
1121 if (vdm.significand <= (2 * vdn.significand)) {
1122 vdn.significand >>= 1;
1123 vdd.exponent++;
1124 }
1125 vdd.significand = vfp_estimate_div128to64(vdn.significand, 0, vdm.significand);
1126 if ((vdd.significand & 0x1ff) <= 2) {
1127 u64 termh, terml, remh, reml;
1128 mul64to128(&termh, &terml, vdm.significand, vdd.significand);
1129 sub128(&remh, &reml, vdn.significand, 0, termh, terml);
1130 while ((s64)remh < 0) {
1131 vdd.significand -= 1;
1132 add128(&remh, &reml, remh, reml, 0, vdm.significand);
1133 }
1134 vdd.significand |= (reml != 0);
1135 }
1136 return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fdiv");
1137
1138 vdn_nan:
1139 exceptions = vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr);
1140 pack:
1141 vfp_put_double(state, vfp_double_pack(&vdd), dd);
1142 return exceptions;
1143
1144 vdm_nan:
1145 exceptions = vfp_propagate_nan(&vdd, &vdm, &vdn, fpscr);
1146 goto pack;
1147
1148 zero:
1149 vdd.exponent = 0;
1150 vdd.significand = 0;
1151 goto pack;
1152
1153 divzero:
1154 exceptions = FPSCR_DZC;
1155 infinity:
1156 vdd.exponent = 2047;
1157 vdd.significand = 0;
1158 goto pack;
1159
1160 invalid:
1161 vfp_put_double(state, vfp_double_pack(&vfp_double_default_qnan), dd);
1162 return FPSCR_IOC;
1163}
1164
1165static struct op fops[] = {
1166 { vfp_double_fmac, 0 },
1167 { vfp_double_fmsc, 0 },
1168 { vfp_double_fmul, 0 },
1169 { vfp_double_fadd, 0 },
1170 { vfp_double_fnmac, 0 },
1171 { vfp_double_fnmsc, 0 },
1172 { vfp_double_fnmul, 0 },
1173 { vfp_double_fsub, 0 },
1174 { vfp_double_fdiv, 0 },
1175};
1176
1177#define FREG_BANK(x) ((x) & 0x0c)
1178#define FREG_IDX(x) ((x) & 3)
1179
1180u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1181{
1182 u32 op = inst & FOP_MASK;
1183 u32 exceptions = 0;
1184 unsigned int dest;
1185 unsigned int dn = vfp_get_dn(inst);
1186 unsigned int dm;
1187 unsigned int vecitr, veclen, vecstride;
1188 struct op *fop;
1189
1190 pr_debug("In %s\n", __FUNCTION__);
1191 vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK));
1192
1193 fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
1194
1195 /*
1196 * fcvtds takes an sN register number as destination, not dN.
1197 * It also always operates on scalars.
1198 */
1199 if (fop->flags & OP_SD)
1200 dest = vfp_get_sd(inst);
1201 else
1202 dest = vfp_get_dd(inst);
1203
1204 /*
1205 * f[us]ito takes a sN operand, not a dN operand.
1206 */
1207 if (fop->flags & OP_SM)
1208 dm = vfp_get_sm(inst);
1209 else
1210 dm = vfp_get_dm(inst);
1211
1212 /*
1213 * If destination bank is zero, vector length is always '1'.
1214 * ARM DDI0100F C5.1.3, C5.3.2.
1215 */
1216 if ((fop->flags & OP_SCALAR) || (FREG_BANK(dest) == 0))
1217 veclen = 0;
1218 else
1219 veclen = fpscr & FPSCR_LENGTH_MASK;
1220
1221 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
1222 (veclen >> FPSCR_LENGTH_BIT) + 1);
1223
1224 if (!fop->fn) {
1225 printf("VFP: could not find double op %d\n", FEXT_TO_IDX(inst));
1226 goto invalid;
1227 }
1228
1229 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
1230 u32 except;
1231 char type;
1232
1233 type = fop->flags & OP_SD ? 's' : 'd';
1234 if (op == FOP_EXT)
1235 pr_debug("VFP: itr%d (%c%u) = op[%u] (d%u)\n",
1236 vecitr >> FPSCR_LENGTH_BIT,
1237 type, dest, dn, dm);
1238 else
1239 pr_debug("VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)\n",
1240 vecitr >> FPSCR_LENGTH_BIT,
1241 type, dest, dn, FOP_TO_IDX(op), dm);
1242
1243 except = fop->fn(state, dest, dn, dm, fpscr);
1244 pr_debug("VFP: itr%d: exceptions=%08x\n",
1245 vecitr >> FPSCR_LENGTH_BIT, except);
1246
1247 exceptions |= except;
1248
1249 /*
1250 * CHECK: It appears to be undefined whether we stop when
1251 * we encounter an exception. We continue.
1252 */
1253 dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 3);
1254 dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 3);
1255 if (FREG_BANK(dm) != 0)
1256 dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 3);
1257 }
1258 return exceptions;
1259
1260 invalid:
1261 return ~0;
1262}
diff --git a/src/core/arm/interpreter/vfp/vfpinstr.cpp b/src/core/arm/interpreter/vfp/vfpinstr.cpp
new file mode 100644
index 000000000..a57047911
--- /dev/null
+++ b/src/core/arm/interpreter/vfp/vfpinstr.cpp
@@ -0,0 +1,5123 @@
1/*
2 vfp/vfpinstr.c - ARM VFPv3 emulation unit - Individual instructions data
3 Copyright (C) 2003 Skyeye Develop Group
4 for help please send mail to <skyeye-developer@lists.gro.clinux.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21/* Notice: this file should not be compiled as is, and is meant to be
22 included in other files only. */
23
24/* ----------------------------------------------------------------------- */
25/* CDP instructions */
26/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */
27
28/* ----------------------------------------------------------------------- */
29/* VMLA */
30/* cond 1110 0D00 Vn-- Vd-- 101X N0M0 Vm-- */
31#define vfpinstr vmla
32#define vfpinstr_inst vmla_inst
33#define VFPLABEL_INST VMLA_INST
34#ifdef VFP_DECODE
35{"vmla", 4, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0},
36#endif
37#ifdef VFP_DECODE_EXCLUSION
38{"vmla", 0, ARMVFP2, 0},
39#endif
40#ifdef VFP_INTERPRETER_TABLE
41INTERPRETER_TRANSLATE(vfpinstr),
42#endif
43#ifdef VFP_INTERPRETER_LABEL
44&&VFPLABEL_INST,
45#endif
46#ifdef VFP_INTERPRETER_STRUCT
47typedef struct _vmla_inst {
48 unsigned int instr;
49 unsigned int dp_operation;
50} vfpinstr_inst;
51#endif
52#ifdef VFP_INTERPRETER_TRANS
53ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
54{
55 VFP_DEBUG_TRANSLATE;
56
57 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
58 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
59
60 inst_base->cond = BITS(inst, 28, 31);
61 inst_base->idx = index;
62 inst_base->br = NON_BRANCH;
63 inst_base->load_r15 = 0;
64
65 inst_cream->dp_operation = BIT(inst, 8);
66 inst_cream->instr = inst;
67
68 return inst_base;
69}
70#endif
71#ifdef VFP_INTERPRETER_IMPL
72VFPLABEL_INST:
73{
74 INC_ICOUNTER;
75 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
76 CHECK_VFP_ENABLED;
77
78 DBG("VMLA :\n");
79
80 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
81
82 int ret;
83
84 if (inst_cream->dp_operation)
85 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
86 else
87 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
88
89 CHECK_VFP_CDP_RET;
90 }
91 cpu->Reg[15] += GET_INST_SIZE(cpu);
92 INC_PC(sizeof(vfpinstr_inst));
93 FETCH_INST;
94 GOTO_NEXT_INST;
95}
96#endif
97#ifdef VFP_CDP_TRANS
98if ((OPC_1 & 0xB) == 0 && (OPC_2 & 0x2) == 0)
99{
100 DBG("VMLA :\n");
101}
102#endif
103#ifdef VFP_DYNCOM_TABLE
104DYNCOM_FILL_ACTION(vfpinstr),
105#endif
106#ifdef VFP_DYNCOM_TAG
107int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
108{
109 int instr_size = INSTR_SIZE;
110 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
111 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
112 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
113 return instr_size;
114}
115#endif
116#ifdef VFP_DYNCOM_TRANS
117int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
118 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
119 //arch_arm_undef(cpu, bb, instr);
120 int m;
121 int n;
122 int d ;
123 int add = (BIT(6) == 0);
124 int s = BIT(8) == 0;
125 Value *mm;
126 Value *nn;
127 Value *tmp;
128 if(s){
129 m = BIT(5) | BITS(0,3) << 1;
130 n = BIT(7) | BITS(16,19) << 1;
131 d = BIT(22) | BITS(12,15) << 1;
132 mm = FR32(m);
133 nn = FR32(n);
134 tmp = FPMUL(nn,mm);
135 if(!add)
136 tmp = FPNEG32(tmp);
137 mm = FR32(d);
138 tmp = FPADD(mm,tmp);
139 //LETS(d,tmp);
140 LETFPS(d,tmp);
141 }else {
142 m = BITS(0,3) | BIT(5) << 4;
143 n = BITS(16,19) | BIT(7) << 4;
144 d = BIT(22) << 4 | BITS(12,15);
145 //mm = SITOFP(32,RSPR(m));
146 //LETS(d,tmp);
147 mm = ZEXT64(IBITCAST32(FR32(2 * m)));
148 nn = ZEXT64(IBITCAST32(FR32(2 * m + 1)));
149 tmp = OR(SHL(nn,CONST64(32)),mm);
150 mm = FPBITCAST64(tmp);
151 tmp = ZEXT64(IBITCAST32(FR32(2 * n)));
152 nn = ZEXT64(IBITCAST32(FR32(2 * n + 1)));
153 nn = OR(SHL(nn,CONST64(32)),tmp);
154 nn = FPBITCAST64(nn);
155 tmp = FPMUL(nn,mm);
156 if(!add)
157 tmp = FPNEG64(tmp);
158 mm = ZEXT64(IBITCAST32(FR32(2 * d)));
159 nn = ZEXT64(IBITCAST32(FR32(2 * d + 1)));
160 mm = OR(SHL(nn,CONST64(32)),mm);
161 mm = FPBITCAST64(mm);
162 tmp = FPADD(mm,tmp);
163 mm = TRUNC32(LSHR(IBITCAST64(tmp),CONST64(32)));
164 nn = TRUNC32(AND(IBITCAST64(tmp),CONST64(0xffffffff)));
165 LETFPS(2*d ,FPBITCAST32(nn));
166 LETFPS(d*2 + 1 , FPBITCAST32(mm));
167 }
168 return No_exp;
169}
170#endif
171#undef vfpinstr
172#undef vfpinstr_inst
173#undef VFPLABEL_INST
174
175/* ----------------------------------------------------------------------- */
176/* VNMLS */
177/* cond 1110 0D00 Vn-- Vd-- 101X N1M0 Vm-- */
178#define vfpinstr vmls
179#define vfpinstr_inst vmls_inst
180#define VFPLABEL_INST VMLS_INST
181#ifdef VFP_DECODE
182{"vmls", 7, ARMVFP2, 28 , 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0},
183#endif
184#ifdef VFP_DECODE_EXCLUSION
185{"vmls", 0, ARMVFP2, 0},
186#endif
187#ifdef VFP_INTERPRETER_TABLE
188INTERPRETER_TRANSLATE(vfpinstr),
189#endif
190#ifdef VFP_INTERPRETER_LABEL
191&&VFPLABEL_INST,
192#endif
193#ifdef VFP_INTERPRETER_STRUCT
194typedef struct _vmls_inst {
195 unsigned int instr;
196 unsigned int dp_operation;
197} vfpinstr_inst;
198#endif
199#ifdef VFP_INTERPRETER_TRANS
200ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
201{
202 VFP_DEBUG_TRANSLATE;
203
204 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
205 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
206
207 inst_base->cond = BITS(inst, 28, 31);
208 inst_base->idx = index;
209 inst_base->br = NON_BRANCH;
210 inst_base->load_r15 = 0;
211
212 inst_cream->dp_operation = BIT(inst, 8);
213 inst_cream->instr = inst;
214
215 return inst_base;
216}
217#endif
218#ifdef VFP_INTERPRETER_IMPL
219VFPLABEL_INST:
220{
221 INC_ICOUNTER;
222 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
223 CHECK_VFP_ENABLED;
224
225 DBG("VMLS :\n");
226
227 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
228
229 int ret;
230
231 if (inst_cream->dp_operation)
232 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
233 else
234 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
235
236 CHECK_VFP_CDP_RET;
237 }
238 cpu->Reg[15] += GET_INST_SIZE(cpu);
239 INC_PC(sizeof(vfpinstr_inst));
240 FETCH_INST;
241 GOTO_NEXT_INST;
242}
243#endif
244#ifdef VFP_CDP_TRANS
245if ((OPC_1 & 0xB) == 0 && (OPC_2 & 0x2) == 2)
246{
247 DBG("VMLS :\n");
248}
249#endif
250#ifdef VFP_DYNCOM_TABLE
251DYNCOM_FILL_ACTION(vfpinstr),
252#endif
253#ifdef VFP_DYNCOM_TAG
254int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
255{
256 int instr_size = INSTR_SIZE;
257 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
258 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
259 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
260 return instr_size;
261}
262#endif
263#ifdef VFP_DYNCOM_TRANS
264int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
265 DBG("\t\tin %s VMLS instruction is executed out of here.\n", __FUNCTION__);
266 //arch_arm_undef(cpu, bb, instr);
267 int m;
268 int n;
269 int d ;
270 int add = (BIT(6) == 0);
271 int s = BIT(8) == 0;
272 Value *mm;
273 Value *nn;
274 Value *tmp;
275 if(s){
276 m = BIT(5) | BITS(0,3) << 1;
277 n = BIT(7) | BITS(16,19) << 1;
278 d = BIT(22) | BITS(12,15) << 1;
279 mm = FR32(m);
280 nn = FR32(n);
281 tmp = FPMUL(nn,mm);
282 if(!add)
283 tmp = FPNEG32(tmp);
284 mm = FR32(d);
285 tmp = FPADD(mm,tmp);
286 //LETS(d,tmp);
287 LETFPS(d,tmp);
288 }else {
289 m = BITS(0,3) | BIT(5) << 4;
290 n = BITS(16,19) | BIT(7) << 4;
291 d = BIT(22) << 4 | BITS(12,15);
292 //mm = SITOFP(32,RSPR(m));
293 //LETS(d,tmp);
294 mm = ZEXT64(IBITCAST32(FR32(2 * m)));
295 nn = ZEXT64(IBITCAST32(FR32(2 * m + 1)));
296 tmp = OR(SHL(nn,CONST64(32)),mm);
297 mm = FPBITCAST64(tmp);
298 tmp = ZEXT64(IBITCAST32(FR32(2 * n)));
299 nn = ZEXT64(IBITCAST32(FR32(2 * n + 1)));
300 nn = OR(SHL(nn,CONST64(32)),tmp);
301 nn = FPBITCAST64(nn);
302 tmp = FPMUL(nn,mm);
303 if(!add)
304 tmp = FPNEG64(tmp);
305 mm = ZEXT64(IBITCAST32(FR32(2 * d)));
306 nn = ZEXT64(IBITCAST32(FR32(2 * d + 1)));
307 mm = OR(SHL(nn,CONST64(32)),mm);
308 mm = FPBITCAST64(mm);
309 tmp = FPADD(mm,tmp);
310 mm = TRUNC32(LSHR(IBITCAST64(tmp),CONST64(32)));
311 nn = TRUNC32(AND(IBITCAST64(tmp),CONST64(0xffffffff)));
312 LETFPS(2*d ,FPBITCAST32(nn));
313 LETFPS(d*2 + 1 , FPBITCAST32(mm));
314 }
315 return No_exp;
316}
317#endif
318#undef vfpinstr
319#undef vfpinstr_inst
320#undef VFPLABEL_INST
321
322/* ----------------------------------------------------------------------- */
323/* VNMLA */
324/* cond 1110 0D01 Vn-- Vd-- 101X N1M0 Vm-- */
325#define vfpinstr vnmla
326#define vfpinstr_inst vnmla_inst
327#define VFPLABEL_INST VNMLA_INST
328#ifdef VFP_DECODE
329//{"vnmla", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
330{"vnmla", 4, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0},
331{"vnmla", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
332//{"vnmla", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
333#endif
334#ifdef VFP_DECODE_EXCLUSION
335{"vnmla", 0, ARMVFP2, 0},
336{"vnmla", 0, ARMVFP2, 0},
337#endif
338#ifdef VFP_INTERPRETER_TABLE
339INTERPRETER_TRANSLATE(vfpinstr),
340INTERPRETER_TRANSLATE(vfpinstr),
341#endif
342#ifdef VFP_INTERPRETER_LABEL
343&&VFPLABEL_INST,
344&&VFPLABEL_INST,
345#endif
346#ifdef VFP_INTERPRETER_STRUCT
347typedef struct _vnmla_inst {
348 unsigned int instr;
349 unsigned int dp_operation;
350} vfpinstr_inst;
351#endif
352#ifdef VFP_INTERPRETER_TRANS
353ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
354{
355 VFP_DEBUG_TRANSLATE;
356
357 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
358 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
359
360 inst_base->cond = BITS(inst, 28, 31);
361 inst_base->idx = index;
362 inst_base->br = NON_BRANCH;
363 inst_base->load_r15 = 0;
364
365 inst_cream->dp_operation = BIT(inst, 8);
366 inst_cream->instr = inst;
367
368 return inst_base;
369}
370#endif
371#ifdef VFP_INTERPRETER_IMPL
372VFPLABEL_INST:
373{
374 INC_ICOUNTER;
375 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
376 CHECK_VFP_ENABLED;
377
378 DBG("VNMLA :\n");
379
380 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
381
382 int ret;
383
384 if (inst_cream->dp_operation)
385 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
386 else
387 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
388
389 CHECK_VFP_CDP_RET;
390 }
391 cpu->Reg[15] += GET_INST_SIZE(cpu);
392 INC_PC(sizeof(vfpinstr_inst));
393 FETCH_INST;
394 GOTO_NEXT_INST;
395}
396#endif
397#ifdef VFP_CDP_TRANS
398if ((OPC_1 & 0xB) == 1 && (OPC_2 & 0x2) == 2)
399{
400 DBG("VNMLA :\n");
401}
402#endif
403#ifdef VFP_DYNCOM_TABLE
404DYNCOM_FILL_ACTION(vfpinstr),
405DYNCOM_FILL_ACTION(vfpinstr),
406#endif
407#ifdef VFP_DYNCOM_TAG
408int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
409{
410 int instr_size = INSTR_SIZE;
411 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
412 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
413 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
414 return instr_size;
415}
416#endif
417#ifdef VFP_DYNCOM_TRANS
418int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
419 DBG("\t\tin %s VNMLA instruction is executed out of here.\n", __FUNCTION__);
420 //arch_arm_undef(cpu, bb, instr);
421 int m;
422 int n;
423 int d ;
424 int add = (BIT(6) == 0);
425 int s = BIT(8) == 0;
426 Value *mm;
427 Value *nn;
428 Value *tmp;
429 if(s){
430 m = BIT(5) | BITS(0,3) << 1;
431 n = BIT(7) | BITS(16,19) << 1;
432 d = BIT(22) | BITS(12,15) << 1;
433 mm = FR32(m);
434 nn = FR32(n);
435 tmp = FPMUL(nn,mm);
436 if(!add)
437 tmp = FPNEG32(tmp);
438 mm = FR32(d);
439 tmp = FPADD(FPNEG32(mm),tmp);
440 //LETS(d,tmp);
441 LETFPS(d,tmp);
442 }else {
443 m = BITS(0,3) | BIT(5) << 4;
444 n = BITS(16,19) | BIT(7) << 4;
445 d = BIT(22) << 4 | BITS(12,15);
446 //mm = SITOFP(32,RSPR(m));
447 //LETS(d,tmp);
448 mm = ZEXT64(IBITCAST32(FR32(2 * m)));
449 nn = ZEXT64(IBITCAST32(FR32(2 * m + 1)));
450 tmp = OR(SHL(nn,CONST64(32)),mm);
451 mm = FPBITCAST64(tmp);
452 tmp = ZEXT64(IBITCAST32(FR32(2 * n)));
453 nn = ZEXT64(IBITCAST32(FR32(2 * n + 1)));
454 nn = OR(SHL(nn,CONST64(32)),tmp);
455 nn = FPBITCAST64(nn);
456 tmp = FPMUL(nn,mm);
457 if(!add)
458 tmp = FPNEG64(tmp);
459 mm = ZEXT64(IBITCAST32(FR32(2 * d)));
460 nn = ZEXT64(IBITCAST32(FR32(2 * d + 1)));
461 mm = OR(SHL(nn,CONST64(32)),mm);
462 mm = FPBITCAST64(mm);
463 tmp = FPADD(FPNEG64(mm),tmp);
464 mm = TRUNC32(LSHR(IBITCAST64(tmp),CONST64(32)));
465 nn = TRUNC32(AND(IBITCAST64(tmp),CONST64(0xffffffff)));
466 LETFPS(2*d ,FPBITCAST32(nn));
467 LETFPS(d*2 + 1 , FPBITCAST32(mm));
468 }
469 return No_exp;
470}
471#endif
472#undef vfpinstr
473#undef vfpinstr_inst
474#undef VFPLABEL_INST
475
476/* ----------------------------------------------------------------------- */
477/* VNMLS */
478/* cond 1110 0D01 Vn-- Vd-- 101X N0M0 Vm-- */
479#define vfpinstr vnmls
480#define vfpinstr_inst vnmls_inst
481#define VFPLABEL_INST VNMLS_INST
482#ifdef VFP_DECODE
483{"vnmls", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
484#endif
485#ifdef VFP_DECODE_EXCLUSION
486{"vnmls", 0, ARMVFP2, 0},
487#endif
488#ifdef VFP_INTERPRETER_TABLE
489INTERPRETER_TRANSLATE(vfpinstr),
490#endif
491#ifdef VFP_INTERPRETER_LABEL
492&&VFPLABEL_INST,
493#endif
494#ifdef VFP_INTERPRETER_STRUCT
495typedef struct _vnmls_inst {
496 unsigned int instr;
497 unsigned int dp_operation;
498} vfpinstr_inst;
499#endif
500#ifdef VFP_INTERPRETER_TRANS
501ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
502{
503 VFP_DEBUG_TRANSLATE;
504
505 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
506 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
507
508 inst_base->cond = BITS(inst, 28, 31);
509 inst_base->idx = index;
510 inst_base->br = NON_BRANCH;
511 inst_base->load_r15 = 0;
512
513 inst_cream->dp_operation = BIT(inst, 8);
514 inst_cream->instr = inst;
515
516 return inst_base;
517}
518#endif
519#ifdef VFP_INTERPRETER_IMPL
520VFPLABEL_INST:
521{
522 INC_ICOUNTER;
523 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
524 CHECK_VFP_ENABLED;
525
526 DBG("VNMLS :\n");
527
528 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
529
530 int ret;
531
532 if (inst_cream->dp_operation)
533 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
534 else
535 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
536
537 CHECK_VFP_CDP_RET;
538 }
539 cpu->Reg[15] += GET_INST_SIZE(cpu);
540 INC_PC(sizeof(vfpinstr_inst));
541 FETCH_INST;
542 GOTO_NEXT_INST;
543}
544#endif
545#ifdef VFP_CDP_TRANS
546if ((OPC_1 & 0xB) == 1 && (OPC_2 & 0x2) == 0)
547{
548 DBG("VNMLS :\n");
549}
550#endif
551#ifdef VFP_DYNCOM_TABLE
552DYNCOM_FILL_ACTION(vfpinstr),
553#endif
554#ifdef VFP_DYNCOM_TAG
555int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
556{
557 int instr_size = INSTR_SIZE;
558 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
559 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
560 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
561 return instr_size;
562}
563#endif
564#ifdef VFP_DYNCOM_TRANS
565int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
566 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
567 //arch_arm_undef(cpu, bb, instr);
568 int m;
569 int n;
570 int d ;
571 int add = (BIT(6) == 0);
572 int s = BIT(8) == 0;
573 Value *mm;
574 Value *nn;
575 Value *tmp;
576 if(s){
577 m = BIT(5) | BITS(0,3) << 1;
578 n = BIT(7) | BITS(16,19) << 1;
579 d = BIT(22) | BITS(12,15) << 1;
580 mm = FR32(m);
581 nn = FR32(n);
582 tmp = FPMUL(nn,mm);
583 if(!add)
584 tmp = FPNEG32(tmp);
585 mm = FR32(d);
586 tmp = FPADD(FPNEG32(mm),tmp);
587 //LETS(d,tmp);
588 LETFPS(d,tmp);
589 }else {
590 m = BITS(0,3) | BIT(5) << 4;
591 n = BITS(16,19) | BIT(7) << 4;
592 d = BIT(22) << 4 | BITS(12,15);
593 //mm = SITOFP(32,RSPR(m));
594 //LETS(d,tmp);
595 mm = ZEXT64(IBITCAST32(FR32(2 * m)));
596 nn = ZEXT64(IBITCAST32(FR32(2 * m + 1)));
597 tmp = OR(SHL(nn,CONST64(32)),mm);
598 mm = FPBITCAST64(tmp);
599 tmp = ZEXT64(IBITCAST32(FR32(2 * n)));
600 nn = ZEXT64(IBITCAST32(FR32(2 * n + 1)));
601 nn = OR(SHL(nn,CONST64(32)),tmp);
602 nn = FPBITCAST64(nn);
603 tmp = FPMUL(nn,mm);
604 if(!add)
605 tmp = FPNEG64(tmp);
606 mm = ZEXT64(IBITCAST32(FR32(2 * d)));
607 nn = ZEXT64(IBITCAST32(FR32(2 * d + 1)));
608 mm = OR(SHL(nn,CONST64(32)),mm);
609 mm = FPBITCAST64(mm);
610 tmp = FPADD(FPNEG64(mm),tmp);
611 mm = TRUNC32(LSHR(IBITCAST64(tmp),CONST64(32)));
612 nn = TRUNC32(AND(IBITCAST64(tmp),CONST64(0xffffffff)));
613 LETFPS(2*d ,FPBITCAST32(nn));
614 LETFPS(d*2 + 1 , FPBITCAST32(mm));
615 }
616 return No_exp;
617}
618#endif
619#undef vfpinstr
620#undef vfpinstr_inst
621#undef VFPLABEL_INST
622
623/* ----------------------------------------------------------------------- */
624/* VNMUL */
625/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */
626#define vfpinstr vnmul
627#define vfpinstr_inst vnmul_inst
628#define VFPLABEL_INST VNMUL_INST
629#ifdef VFP_DECODE
630{"vnmul", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
631#endif
632#ifdef VFP_DECODE_EXCLUSION
633{"vnmul", 0, ARMVFP2, 0},
634#endif
635#ifdef VFP_INTERPRETER_TABLE
636INTERPRETER_TRANSLATE(vfpinstr),
637#endif
638#ifdef VFP_INTERPRETER_LABEL
639&&VFPLABEL_INST,
640#endif
641#ifdef VFP_INTERPRETER_STRUCT
642typedef struct _vnmul_inst {
643 unsigned int instr;
644 unsigned int dp_operation;
645} vfpinstr_inst;
646#endif
647#ifdef VFP_INTERPRETER_TRANS
648ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
649{
650 VFP_DEBUG_TRANSLATE;
651
652 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
653 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
654
655 inst_base->cond = BITS(inst, 28, 31);
656 inst_base->idx = index;
657 inst_base->br = NON_BRANCH;
658 inst_base->load_r15 = 0;
659
660 inst_cream->dp_operation = BIT(inst, 8);
661 inst_cream->instr = inst;
662
663 return inst_base;
664}
665#endif
666#ifdef VFP_INTERPRETER_IMPL
667VFPLABEL_INST:
668{
669 INC_ICOUNTER;
670 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
671 CHECK_VFP_ENABLED;
672
673 DBG("VNMUL :\n");
674
675 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
676
677 int ret;
678
679 if (inst_cream->dp_operation)
680 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
681 else
682 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
683
684 CHECK_VFP_CDP_RET;
685 }
686 cpu->Reg[15] += GET_INST_SIZE(cpu);
687 INC_PC(sizeof(vfpinstr_inst));
688 FETCH_INST;
689 GOTO_NEXT_INST;
690}
691#endif
692#ifdef VFP_CDP_TRANS
693if ((OPC_1 & 0xB) == 2 && (OPC_2 & 0x2) == 2)
694{
695 DBG("VNMUL :\n");
696}
697#endif
698#ifdef VFP_DYNCOM_TABLE
699DYNCOM_FILL_ACTION(vfpinstr),
700#endif
701#ifdef VFP_DYNCOM_TAG
702int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
703{
704 int instr_size = INSTR_SIZE;
705 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
706 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
707 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
708 return instr_size;
709}
710#endif
711#ifdef VFP_DYNCOM_TRANS
712int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
713 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
714 //arch_arm_undef(cpu, bb, instr);
715 int m;
716 int n;
717 int d ;
718 int add = (BIT(6) == 0);
719 int s = BIT(8) == 0;
720 Value *mm;
721 Value *nn;
722 Value *tmp;
723 if(s){
724 m = BIT(5) | BITS(0,3) << 1;
725 n = BIT(7) | BITS(16,19) << 1;
726 d = BIT(22) | BITS(12,15) << 1;
727 mm = FR32(m);
728 nn = FR32(n);
729 tmp = FPMUL(nn,mm);
730 //LETS(d,tmp);
731 LETFPS(d,FPNEG32(tmp));
732 }else {
733 m = BITS(0,3) | BIT(5) << 4;
734 n = BITS(16,19) | BIT(7) << 4;
735 d = BIT(22) << 4 | BITS(12,15);
736 //mm = SITOFP(32,RSPR(m));
737 //LETS(d,tmp);
738 mm = ZEXT64(IBITCAST32(FR32(2 * m)));
739 nn = ZEXT64(IBITCAST32(FR32(2 * m + 1)));
740 tmp = OR(SHL(nn,CONST64(32)),mm);
741 mm = FPBITCAST64(tmp);
742 tmp = ZEXT64(IBITCAST32(FR32(2 * n)));
743 nn = ZEXT64(IBITCAST32(FR32(2 * n + 1)));
744 nn = OR(SHL(nn,CONST64(32)),tmp);
745 nn = FPBITCAST64(nn);
746 tmp = FPMUL(nn,mm);
747 tmp = FPNEG64(tmp);
748 mm = TRUNC32(LSHR(IBITCAST64(tmp),CONST64(32)));
749 nn = TRUNC32(AND(IBITCAST64(tmp),CONST64(0xffffffff)));
750 LETFPS(2*d ,FPBITCAST32(nn));
751 LETFPS(d*2 + 1 , FPBITCAST32(mm));
752 }
753 return No_exp;
754}
755#endif
756#undef vfpinstr
757#undef vfpinstr_inst
758#undef VFPLABEL_INST
759
760/* ----------------------------------------------------------------------- */
761/* VMUL */
762/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */
763#define vfpinstr vmul
764#define vfpinstr_inst vmul_inst
765#define VFPLABEL_INST VMUL_INST
766#ifdef VFP_DECODE
767{"vmul", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
768#endif
769#ifdef VFP_DECODE_EXCLUSION
770{"vmul", 0, ARMVFP2, 0},
771#endif
772#ifdef VFP_INTERPRETER_TABLE
773INTERPRETER_TRANSLATE(vfpinstr),
774#endif
775#ifdef VFP_INTERPRETER_LABEL
776&&VFPLABEL_INST,
777#endif
778#ifdef VFP_INTERPRETER_STRUCT
779typedef struct _vmul_inst {
780 unsigned int instr;
781 unsigned int dp_operation;
782} vfpinstr_inst;
783#endif
784#ifdef VFP_INTERPRETER_TRANS
785ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
786{
787 VFP_DEBUG_TRANSLATE;
788
789 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
790 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
791
792 inst_base->cond = BITS(inst, 28, 31);
793 inst_base->idx = index;
794 inst_base->br = NON_BRANCH;
795 inst_base->load_r15 = 0;
796
797 inst_cream->dp_operation = BIT(inst, 8);
798 inst_cream->instr = inst;
799
800 return inst_base;
801}
802#endif
803#ifdef VFP_INTERPRETER_IMPL
804VFPLABEL_INST:
805{
806 INC_ICOUNTER;
807 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
808 CHECK_VFP_ENABLED;
809
810 DBG("VMUL :\n");
811
812 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
813
814 int ret;
815
816 if (inst_cream->dp_operation)
817 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
818 else
819 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
820
821 CHECK_VFP_CDP_RET;
822 }
823 cpu->Reg[15] += GET_INST_SIZE(cpu);
824 INC_PC(sizeof(vfpinstr_inst));
825 FETCH_INST;
826 GOTO_NEXT_INST;
827}
828#endif
829#ifdef VFP_CDP_TRANS
830if ((OPC_1 & 0xB) == 2 && (OPC_2 & 0x2) == 0)
831{
832 DBG("VMUL :\n");
833}
834#endif
835#ifdef VFP_DYNCOM_TABLE
836DYNCOM_FILL_ACTION(vfpinstr),
837#endif
838#ifdef VFP_DYNCOM_TAG
839int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
840{
841 int instr_size = INSTR_SIZE;
842 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
843 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
844 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
845 return instr_size;
846}
847#endif
848#ifdef VFP_DYNCOM_TRANS
849int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
850 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
851 //printf("\n\n\t\tin %s instruction is executed out.\n\n", __FUNCTION__);
852 //arch_arm_undef(cpu, bb, instr);
853 int m;
854 int n;
855 int d ;
856 int s = BIT(8) == 0;
857 Value *mm;
858 Value *nn;
859 Value *tmp;
860 if(s){
861 m = BIT(5) | BITS(0,3) << 1;
862 n = BIT(7) | BITS(16,19) << 1;
863 d = BIT(22) | BITS(12,15) << 1;
864 //mm = SITOFP(32,FR(m));
865 //nn = SITOFP(32,FRn));
866 mm = FR32(m);
867 nn = FR32(n);
868 tmp = FPMUL(nn,mm);
869 //LETS(d,tmp);
870 LETFPS(d,tmp);
871 }else {
872 m = BITS(0,3) | BIT(5) << 4;
873 n = BITS(16,19) | BIT(7) << 4;
874 d = BIT(22) << 4 | BITS(12,15);
875 //mm = SITOFP(32,RSPR(m));
876 //LETS(d,tmp);
877 Value *lo = FR32(2 * m);
878 Value *hi = FR32(2 * m + 1);
879 hi = IBITCAST32(hi);
880 lo = IBITCAST32(lo);
881 Value *hi64 = ZEXT64(hi);
882 Value* lo64 = ZEXT64(lo);
883 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
884 Value* m0 = FPBITCAST64(v64);
885 lo = FR32(2 * n);
886 hi = FR32(2 * n + 1);
887 hi = IBITCAST32(hi);
888 lo = IBITCAST32(lo);
889 hi64 = ZEXT64(hi);
890 lo64 = ZEXT64(lo);
891 v64 = OR(SHL(hi64,CONST64(32)),lo64);
892 Value *n0 = FPBITCAST64(v64);
893 tmp = FPMUL(n0,m0);
894 Value *val64 = IBITCAST64(tmp);
895 hi = LSHR(val64,CONST64(32));
896 lo = AND(val64,CONST64(0xffffffff));
897 hi = TRUNC32(hi);
898 lo = TRUNC32(lo);
899 hi = FPBITCAST32(hi);
900 lo = FPBITCAST32(lo);
901 LETFPS(2*d ,lo);
902 LETFPS(d*2 + 1 , hi);
903 }
904 return No_exp;
905}
906#endif
907#undef vfpinstr
908#undef vfpinstr_inst
909#undef VFPLABEL_INST
910
911/* ----------------------------------------------------------------------- */
912/* VADD */
913/* cond 1110 0D11 Vn-- Vd-- 101X N0M0 Vm-- */
914#define vfpinstr vadd
915#define vfpinstr_inst vadd_inst
916#define VFPLABEL_INST VADD_INST
917#ifdef VFP_DECODE
918{"vadd", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
919#endif
920#ifdef VFP_DECODE_EXCLUSION
921{"vadd", 0, ARMVFP2, 0},
922#endif
923#ifdef VFP_INTERPRETER_TABLE
924INTERPRETER_TRANSLATE(vfpinstr),
925#endif
926#ifdef VFP_INTERPRETER_LABEL
927&&VFPLABEL_INST,
928#endif
929#ifdef VFP_INTERPRETER_STRUCT
930typedef struct _vadd_inst {
931 unsigned int instr;
932 unsigned int dp_operation;
933} vfpinstr_inst;
934#endif
935#ifdef VFP_INTERPRETER_TRANS
936ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
937{
938 VFP_DEBUG_TRANSLATE;
939
940 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
941 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
942
943 inst_base->cond = BITS(inst, 28, 31);
944 inst_base->idx = index;
945 inst_base->br = NON_BRANCH;
946 inst_base->load_r15 = 0;
947
948 inst_cream->dp_operation = BIT(inst, 8);
949 inst_cream->instr = inst;
950
951 return inst_base;
952}
953#endif
954#ifdef VFP_INTERPRETER_IMPL
955VFPLABEL_INST:
956{
957 INC_ICOUNTER;
958 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
959 CHECK_VFP_ENABLED;
960
961 DBG("VADD :\n");
962
963 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
964
965 int ret;
966
967 if (inst_cream->dp_operation)
968 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
969 else
970 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
971
972 CHECK_VFP_CDP_RET;
973 }
974 cpu->Reg[15] += GET_INST_SIZE(cpu);
975 INC_PC(sizeof(vfpinstr_inst));
976 FETCH_INST;
977 GOTO_NEXT_INST;
978}
979#endif
980#ifdef VFP_CDP_TRANS
981if ((OPC_1 & 0xB) == 3 && (OPC_2 & 0x2) == 0)
982{
983 DBG("VADD :\n");
984}
985#endif
986#ifdef VFP_DYNCOM_TABLE
987DYNCOM_FILL_ACTION(vfpinstr),
988#endif
989#ifdef VFP_DYNCOM_TAG
990int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
991{
992 int instr_size = INSTR_SIZE;
993 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
994 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
995 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
996 return instr_size;
997}
998#endif
999#ifdef VFP_DYNCOM_TRANS
1000int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1001 DBG("\t\tin %s instruction will implement out of JIT.\n", __FUNCTION__);
1002 //arch_arm_undef(cpu, bb, instr);
1003 int m;
1004 int n;
1005 int d ;
1006 int s = BIT(8) == 0;
1007 Value *mm;
1008 Value *nn;
1009 Value *tmp;
1010 if(s){
1011 m = BIT(5) | BITS(0,3) << 1;
1012 n = BIT(7) | BITS(16,19) << 1;
1013 d = BIT(22) | BITS(12,15) << 1;
1014 mm = FR32(m);
1015 nn = FR32(n);
1016 tmp = FPADD(nn,mm);
1017 LETFPS(d,tmp);
1018 }else {
1019 m = BITS(0,3) | BIT(5) << 4;
1020 n = BITS(16,19) | BIT(7) << 4;
1021 d = BIT(22) << 4 | BITS(12,15);
1022 Value *lo = FR32(2 * m);
1023 Value *hi = FR32(2 * m + 1);
1024 hi = IBITCAST32(hi);
1025 lo = IBITCAST32(lo);
1026 Value *hi64 = ZEXT64(hi);
1027 Value* lo64 = ZEXT64(lo);
1028 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
1029 Value* m0 = FPBITCAST64(v64);
1030 lo = FR32(2 * n);
1031 hi = FR32(2 * n + 1);
1032 hi = IBITCAST32(hi);
1033 lo = IBITCAST32(lo);
1034 hi64 = ZEXT64(hi);
1035 lo64 = ZEXT64(lo);
1036 v64 = OR(SHL(hi64,CONST64(32)),lo64);
1037 Value *n0 = FPBITCAST64(v64);
1038 tmp = FPADD(n0,m0);
1039 Value *val64 = IBITCAST64(tmp);
1040 hi = LSHR(val64,CONST64(32));
1041 lo = AND(val64,CONST64(0xffffffff));
1042 hi = TRUNC32(hi);
1043 lo = TRUNC32(lo);
1044 hi = FPBITCAST32(hi);
1045 lo = FPBITCAST32(lo);
1046 LETFPS(2*d ,lo);
1047 LETFPS(d*2 + 1 , hi);
1048 }
1049 return No_exp;
1050}
1051#endif
1052#undef vfpinstr
1053#undef vfpinstr_inst
1054#undef VFPLABEL_INST
1055
1056/* ----------------------------------------------------------------------- */
1057/* VSUB */
1058/* cond 1110 0D11 Vn-- Vd-- 101X N1M0 Vm-- */
1059#define vfpinstr vsub
1060#define vfpinstr_inst vsub_inst
1061#define VFPLABEL_INST VSUB_INST
1062#ifdef VFP_DECODE
1063{"vsub", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
1064#endif
1065#ifdef VFP_DECODE_EXCLUSION
1066{"vsub", 0, ARMVFP2, 0},
1067#endif
1068#ifdef VFP_INTERPRETER_TABLE
1069INTERPRETER_TRANSLATE(vfpinstr),
1070#endif
1071#ifdef VFP_INTERPRETER_LABEL
1072&&VFPLABEL_INST,
1073#endif
1074#ifdef VFP_INTERPRETER_STRUCT
1075typedef struct _vsub_inst {
1076 unsigned int instr;
1077 unsigned int dp_operation;
1078} vfpinstr_inst;
1079#endif
1080#ifdef VFP_INTERPRETER_TRANS
1081ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1082{
1083 VFP_DEBUG_TRANSLATE;
1084
1085 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
1086 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1087
1088 inst_base->cond = BITS(inst, 28, 31);
1089 inst_base->idx = index;
1090 inst_base->br = NON_BRANCH;
1091 inst_base->load_r15 = 0;
1092
1093 inst_cream->dp_operation = BIT(inst, 8);
1094 inst_cream->instr = inst;
1095
1096 return inst_base;
1097}
1098#endif
1099#ifdef VFP_INTERPRETER_IMPL
1100VFPLABEL_INST:
1101{
1102 INC_ICOUNTER;
1103 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1104 CHECK_VFP_ENABLED;
1105
1106 DBG("VSUB :\n");
1107
1108 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1109
1110 int ret;
1111
1112 if (inst_cream->dp_operation)
1113 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
1114 else
1115 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
1116
1117 CHECK_VFP_CDP_RET;
1118 }
1119 cpu->Reg[15] += GET_INST_SIZE(cpu);
1120 INC_PC(sizeof(vfpinstr_inst));
1121 FETCH_INST;
1122 GOTO_NEXT_INST;
1123}
1124#endif
1125#ifdef VFP_CDP_TRANS
1126if ((OPC_1 & 0xB) == 3 && (OPC_2 & 0x2) == 2)
1127{
1128 DBG("VSUB :\n");
1129}
1130#endif
1131#ifdef VFP_DYNCOM_TABLE
1132DYNCOM_FILL_ACTION(vfpinstr),
1133#endif
1134#ifdef VFP_DYNCOM_TAG
1135int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1136{
1137 int instr_size = INSTR_SIZE;
1138 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1139 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1140 return instr_size;
1141}
1142#endif
1143#ifdef VFP_DYNCOM_TRANS
1144int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1145 DBG("\t\tin %s instr=0x%x, instruction is executed out of JIT.\n", __FUNCTION__, instr);
1146 //arch_arm_undef(cpu, bb, instr);
1147 int m;
1148 int n;
1149 int d ;
1150 int s = BIT(8) == 0;
1151 Value *mm;
1152 Value *nn;
1153 Value *tmp;
1154 if(s){
1155 m = BIT(5) | BITS(0,3) << 1;
1156 n = BIT(7) | BITS(16,19) << 1;
1157 d = BIT(22) | BITS(12,15) << 1;
1158 mm = FR32(m);
1159 nn = FR32(n);
1160 tmp = FPSUB(nn,mm);
1161 LETFPS(d,tmp);
1162 }else {
1163 m = BITS(0,3) | BIT(5) << 4;
1164 n = BITS(16,19) | BIT(7) << 4;
1165 d = BIT(22) << 4 | BITS(12,15);
1166 Value *lo = FR32(2 * m);
1167 Value *hi = FR32(2 * m + 1);
1168 hi = IBITCAST32(hi);
1169 lo = IBITCAST32(lo);
1170 Value *hi64 = ZEXT64(hi);
1171 Value* lo64 = ZEXT64(lo);
1172 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
1173 Value* m0 = FPBITCAST64(v64);
1174 lo = FR32(2 * n);
1175 hi = FR32(2 * n + 1);
1176 hi = IBITCAST32(hi);
1177 lo = IBITCAST32(lo);
1178 hi64 = ZEXT64(hi);
1179 lo64 = ZEXT64(lo);
1180 v64 = OR(SHL(hi64,CONST64(32)),lo64);
1181 Value *n0 = FPBITCAST64(v64);
1182 tmp = FPSUB(n0,m0);
1183 Value *val64 = IBITCAST64(tmp);
1184 hi = LSHR(val64,CONST64(32));
1185 lo = AND(val64,CONST64(0xffffffff));
1186 hi = TRUNC32(hi);
1187 lo = TRUNC32(lo);
1188 hi = FPBITCAST32(hi);
1189 lo = FPBITCAST32(lo);
1190 LETFPS(2*d ,lo);
1191 LETFPS(d*2 + 1 , hi);
1192 }
1193 return No_exp;
1194}
1195#endif
1196#undef vfpinstr
1197#undef vfpinstr_inst
1198#undef VFPLABEL_INST
1199
1200/* ----------------------------------------------------------------------- */
1201/* VDIV */
1202/* cond 1110 1D00 Vn-- Vd-- 101X N0M0 Vm-- */
1203#define vfpinstr vdiv
1204#define vfpinstr_inst vdiv_inst
1205#define VFPLABEL_INST VDIV_INST
1206#ifdef VFP_DECODE
1207{"vdiv", 5, ARMVFP2, 23, 27, 0x1d, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
1208#endif
1209#ifdef VFP_DECODE_EXCLUSION
1210{"vdiv", 0, ARMVFP2, 0},
1211#endif
1212#ifdef VFP_INTERPRETER_TABLE
1213INTERPRETER_TRANSLATE(vfpinstr),
1214#endif
1215#ifdef VFP_INTERPRETER_LABEL
1216&&VFPLABEL_INST,
1217#endif
1218#ifdef VFP_INTERPRETER_STRUCT
1219typedef struct _vdiv_inst {
1220 unsigned int instr;
1221 unsigned int dp_operation;
1222} vfpinstr_inst;
1223#endif
1224#ifdef VFP_INTERPRETER_TRANS
1225ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1226{
1227 VFP_DEBUG_TRANSLATE;
1228
1229 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
1230 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1231
1232 inst_base->cond = BITS(inst, 28, 31);
1233 inst_base->idx = index;
1234 inst_base->br = NON_BRANCH;
1235 inst_base->load_r15 = 0;
1236
1237 inst_cream->dp_operation = BIT(inst, 8);
1238 inst_cream->instr = inst;
1239
1240 return inst_base;
1241}
1242#endif
1243#ifdef VFP_INTERPRETER_IMPL
1244VFPLABEL_INST:
1245{
1246 INC_ICOUNTER;
1247 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1248 CHECK_VFP_ENABLED;
1249
1250 DBG("VDIV :\n");
1251
1252 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1253
1254 int ret;
1255
1256 if (inst_cream->dp_operation)
1257 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
1258 else
1259 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
1260
1261 CHECK_VFP_CDP_RET;
1262 }
1263 cpu->Reg[15] += GET_INST_SIZE(cpu);
1264 INC_PC(sizeof(vfpinstr_inst));
1265 FETCH_INST;
1266 GOTO_NEXT_INST;
1267}
1268#endif
1269#ifdef VFP_CDP_TRANS
1270if ((OPC_1 & 0xB) == 0xA && (OPC_2 & 0x2) == 0)
1271{
1272 DBG("VDIV :\n");
1273}
1274#endif
1275#ifdef VFP_DYNCOM_TABLE
1276DYNCOM_FILL_ACTION(vfpinstr),
1277#endif
1278#ifdef VFP_DYNCOM_TAG
1279int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1280{
1281 int instr_size = INSTR_SIZE;
1282 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1283 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1284 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1285 return instr_size;
1286}
1287#endif
1288#ifdef VFP_DYNCOM_TRANS
1289int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1290 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1291 //arch_arm_undef(cpu, bb, instr);
1292 int m;
1293 int n;
1294 int d ;
1295 int s = BIT(8) == 0;
1296 Value *mm;
1297 Value *nn;
1298 Value *tmp;
1299 if(s){
1300 m = BIT(5) | BITS(0,3) << 1;
1301 n = BIT(7) | BITS(16,19) << 1;
1302 d = BIT(22) | BITS(12,15) << 1;
1303 mm = FR32(m);
1304 nn = FR32(n);
1305 tmp = FPDIV(nn,mm);
1306 LETFPS(d,tmp);
1307 }else {
1308 m = BITS(0,3) | BIT(5) << 4;
1309 n = BITS(16,19) | BIT(7) << 4;
1310 d = BIT(22) << 4 | BITS(12,15);
1311 Value *lo = FR32(2 * m);
1312 Value *hi = FR32(2 * m + 1);
1313 hi = IBITCAST32(hi);
1314 lo = IBITCAST32(lo);
1315 Value *hi64 = ZEXT64(hi);
1316 Value* lo64 = ZEXT64(lo);
1317 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
1318 Value* m0 = FPBITCAST64(v64);
1319 lo = FR32(2 * n);
1320 hi = FR32(2 * n + 1);
1321 hi = IBITCAST32(hi);
1322 lo = IBITCAST32(lo);
1323 hi64 = ZEXT64(hi);
1324 lo64 = ZEXT64(lo);
1325 v64 = OR(SHL(hi64,CONST64(32)),lo64);
1326 Value *n0 = FPBITCAST64(v64);
1327 tmp = FPDIV(n0,m0);
1328 Value *val64 = IBITCAST64(tmp);
1329 hi = LSHR(val64,CONST64(32));
1330 lo = AND(val64,CONST64(0xffffffff));
1331 hi = TRUNC32(hi);
1332 lo = TRUNC32(lo);
1333 hi = FPBITCAST32(hi);
1334 lo = FPBITCAST32(lo);
1335 LETFPS(2*d ,lo);
1336 LETFPS(d*2 + 1 , hi);
1337 }
1338 return No_exp;
1339}
1340#endif
1341#undef vfpinstr
1342#undef vfpinstr_inst
1343#undef VFPLABEL_INST
1344
1345/* ----------------------------------------------------------------------- */
1346/* VMOVI move immediate */
1347/* cond 1110 1D11 im4H Vd-- 101X 0000 im4L */
1348/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */
1349#define vfpinstr vmovi
1350#define vfpinstr_inst vmovi_inst
1351#define VFPLABEL_INST VMOVI_INST
1352#ifdef VFP_DECODE
1353{"vmov(i)", 4, ARMVFP3, 23, 27, 0x1d, 20, 21, 0x3, 9, 11, 0x5, 4, 7, 0},
1354#endif
1355#ifdef VFP_DECODE_EXCLUSION
1356{"vmov(i)", 0, ARMVFP3, 0},
1357#endif
1358#ifdef VFP_INTERPRETER_TABLE
1359INTERPRETER_TRANSLATE(vfpinstr),
1360#endif
1361#ifdef VFP_INTERPRETER_LABEL
1362&&VFPLABEL_INST,
1363#endif
1364#ifdef VFP_INTERPRETER_STRUCT
1365typedef struct _vmovi_inst {
1366 unsigned int single;
1367 unsigned int d;
1368 unsigned int imm;
1369} vfpinstr_inst;
1370#endif
1371#ifdef VFP_INTERPRETER_TRANS
1372ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1373{
1374 VFP_DEBUG_TRANSLATE;
1375
1376 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
1377 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1378
1379 inst_base->cond = BITS(inst, 28, 31);
1380 inst_base->idx = index;
1381 inst_base->br = NON_BRANCH;
1382 inst_base->load_r15 = 0;
1383
1384 inst_cream->single = BIT(inst, 8) == 0;
1385 inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4);
1386 unsigned int imm8 = BITS(inst, 16, 19) << 4 | BITS(inst, 0, 3);
1387 if (inst_cream->single)
1388 inst_cream->imm = BIT(imm8, 7)<<31 | (BIT(imm8, 6)==0)<<30 | (BIT(imm8, 6) ? 0x1f : 0)<<25 | BITS(imm8, 0, 5)<<19;
1389 else
1390 inst_cream->imm = BIT(imm8, 7)<<31 | (BIT(imm8, 6)==0)<<30 | (BIT(imm8, 6) ? 0xff : 0)<<22 | BITS(imm8, 0, 5)<<16;
1391 return inst_base;
1392}
1393#endif
1394#ifdef VFP_INTERPRETER_IMPL
1395VFPLABEL_INST:
1396{
1397 INC_ICOUNTER;
1398 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1399 CHECK_VFP_ENABLED;
1400
1401 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1402
1403 VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm);
1404 }
1405 cpu->Reg[15] += GET_INST_SIZE(cpu);
1406 INC_PC(sizeof(vfpinstr_inst));
1407 FETCH_INST;
1408 GOTO_NEXT_INST;
1409}
1410#endif
1411#ifdef VFP_CDP_TRANS
1412if ( (OPC_1 & 0xb) == 0xb && BITS(4, 7) == 0)
1413{
1414 unsigned int single = BIT(8) == 0;
1415 unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4);
1416 unsigned int imm;
1417 instr = BITS(16, 19) << 4 | BITS(0, 3); /* FIXME dirty workaround to get a correct imm */
1418 if (single) {
1419 imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0x1f : 0)<<25 | BITS(0, 5)<<19;
1420 } else {
1421 imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0xff : 0)<<22 | BITS(0, 5)<<16;
1422 }
1423 VMOVI(state, single, d, imm);
1424 return ARMul_DONE;
1425}
1426#endif
1427#ifdef VFP_CDP_IMPL
1428void VMOVI(ARMul_State * state, ARMword single, ARMword d, ARMword imm)
1429{
1430 DBG("VMOV(I) :\n");
1431
1432 if (single)
1433 {
1434 DBG("\ts%d <= [%x]\n", d, imm);
1435 state->ExtReg[d] = imm;
1436 }
1437 else
1438 {
1439 /* Check endian please */
1440 DBG("\ts[%d-%d] <= [%x-%x]\n", d*2+1, d*2, imm, 0);
1441 state->ExtReg[d*2+1] = imm;
1442 state->ExtReg[d*2] = 0;
1443 }
1444}
1445#endif
1446#ifdef VFP_DYNCOM_TABLE
1447DYNCOM_FILL_ACTION(vfpinstr),
1448#endif
1449#ifdef VFP_DYNCOM_TAG
1450int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1451{
1452 int instr_size = INSTR_SIZE;
1453 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1454 arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1455 return instr_size;
1456}
1457#endif
1458#ifdef VFP_DYNCOM_TRANS
1459int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1460 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1461 //arch_arm_undef(cpu, bb, instr);
1462 int single = (BIT(8) == 0);
1463 int d;
1464 int imm32;
1465 Value *v;
1466 Value *tmp;
1467 v = CONST32(BITS(0,3) | BITS(16,19) << 4);
1468 //v = CONST64(0x3ff0000000000000);
1469 if(single){
1470 d = BIT(22) | BITS(12,15) << 1;
1471 }else {
1472 d = BITS(12,15) | BIT(22) << 4;
1473 }
1474 if(single){
1475 LETFPS(d,FPBITCAST32(v));
1476 }else {
1477 //v = UITOFP(64,v);
1478 //tmp = IBITCAST64(v);
1479 LETFPS(d*2 ,FPBITCAST32(TRUNC32(AND(v,CONST64(0xffffffff)))));
1480 LETFPS(d * 2 + 1,FPBITCAST32(TRUNC32(LSHR(v,CONST64(32)))));
1481 }
1482 return No_exp;
1483}
1484#endif
1485#undef vfpinstr
1486#undef vfpinstr_inst
1487#undef VFPLABEL_INST
1488
1489/* ----------------------------------------------------------------------- */
1490/* VMOVR move register */
1491/* cond 1110 1D11 0000 Vd-- 101X 01M0 Vm-- */
1492/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */
1493#define vfpinstr vmovr
1494#define vfpinstr_inst vmovr_inst
1495#define VFPLABEL_INST VMOVR_INST
1496#ifdef VFP_DECODE
1497{"vmov(r)", 5, ARMVFP3, 23, 27, 0x1d, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 1, 4, 4, 0},
1498#endif
1499#ifdef VFP_DECODE_EXCLUSION
1500{"vmov(r)", 0, ARMVFP3, 0},
1501#endif
1502#ifdef VFP_INTERPRETER_TABLE
1503INTERPRETER_TRANSLATE(vfpinstr),
1504#endif
1505#ifdef VFP_INTERPRETER_LABEL
1506&&VFPLABEL_INST,
1507#endif
1508#ifdef VFP_INTERPRETER_STRUCT
1509typedef struct _vmovr_inst {
1510 unsigned int single;
1511 unsigned int d;
1512 unsigned int m;
1513} vfpinstr_inst;
1514#endif
1515#ifdef VFP_INTERPRETER_TRANS
1516ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1517{
1518 VFP_DEBUG_TRANSLATE;
1519 VFP_DEBUG_UNTESTED(VMOVR);
1520
1521 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
1522 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1523
1524 inst_base->cond = BITS(inst, 28, 31);
1525 inst_base->idx = index;
1526 inst_base->br = NON_BRANCH;
1527 inst_base->load_r15 = 0;
1528
1529 inst_cream->single = BIT(inst, 8) == 0;
1530 inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4);
1531 inst_cream->m = (inst_cream->single ? BITS(inst, 0, 3)<<1 | BIT(inst, 5) : BITS(inst, 0, 3) | BIT(inst, 5)<<4);
1532 return inst_base;
1533}
1534#endif
1535#ifdef VFP_INTERPRETER_IMPL
1536VFPLABEL_INST:
1537{
1538 INC_ICOUNTER;
1539 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1540 CHECK_VFP_ENABLED;
1541
1542 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1543
1544 VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m);
1545 }
1546 cpu->Reg[15] += GET_INST_SIZE(cpu);
1547 INC_PC(sizeof(vfpinstr_inst));
1548 FETCH_INST;
1549 GOTO_NEXT_INST;
1550}
1551#endif
1552#ifdef VFP_CDP_TRANS
1553if ( (OPC_1 & 0xb) == 0xb && CRn == 0 && (OPC_2 & 0x6) == 0x2 )
1554{
1555 unsigned int single = BIT(8) == 0;
1556 unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4);
1557 unsigned int m = (single ? BITS( 0, 3)<<1 | BIT( 5) : BITS( 0, 3) | BIT( 5)<<4);;
1558 VMOVR(state, single, d, m);
1559 return ARMul_DONE;
1560}
1561#endif
1562#ifdef VFP_CDP_IMPL
1563void VMOVR(ARMul_State * state, ARMword single, ARMword d, ARMword m)
1564{
1565 DBG("VMOV(R) :\n");
1566
1567 if (single)
1568 {
1569 DBG("\ts%d <= s%d[%x]\n", d, m, state->ExtReg[m]);
1570 state->ExtReg[d] = state->ExtReg[m];
1571 }
1572 else
1573 {
1574 /* Check endian please */
1575 DBG("\ts[%d-%d] <= s[%d-%d][%x-%x]\n", d*2+1, d*2, m*2+1, m*2, state->ExtReg[m*2+1], state->ExtReg[m*2]);
1576 state->ExtReg[d*2+1] = state->ExtReg[m*2+1];
1577 state->ExtReg[d*2] = state->ExtReg[m*2];
1578 }
1579}
1580#endif
1581#ifdef VFP_DYNCOM_TABLE
1582DYNCOM_FILL_ACTION(vfpinstr),
1583#endif
1584#ifdef VFP_DYNCOM_TAG
1585int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1586{
1587 int instr_size = INSTR_SIZE;
1588 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1589 DBG("In %s, pc=0x%x, next_pc=0x%x\n", __FUNCTION__, pc, *next_pc);
1590 if(instr >> 28 != 0xe)
1591 *tag |= TAG_CONDITIONAL;
1592
1593 return instr_size;
1594}
1595#endif
1596#ifdef VFP_DYNCOM_TRANS
1597int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1598 DBG("\t\tin %s VMOV \n", __FUNCTION__);
1599 int single = BIT(8) == 0;
1600 int d = (single ? BITS(12,15)<<1 | BIT(22) : BIT(22) << 4 | BITS(12,15));
1601 int m = (single ? BITS(0, 3)<<1 | BIT(5) : BITS(0, 3) | BIT(5)<<4);
1602
1603 if (single)
1604 {
1605 LETFPS(d, FR32(m));
1606 }
1607 else
1608 {
1609 /* Check endian please */
1610 LETFPS((d*2 + 1), FR32(m*2 + 1));
1611 LETFPS((d * 2), FR32(m * 2));
1612 }
1613 return No_exp;
1614}
1615#endif
1616#undef vfpinstr
1617#undef vfpinstr_inst
1618#undef VFPLABEL_INST
1619
1620/* ----------------------------------------------------------------------- */
1621/* VABS */
1622/* cond 1110 1D11 0000 Vd-- 101X 11M0 Vm-- */
1623#define vfpinstr vabs
1624#define vfpinstr_inst vabs_inst
1625#define VFPLABEL_INST VABS_INST
1626#ifdef VFP_DECODE
1627{"vabs", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
1628#endif
1629#ifdef VFP_DECODE_EXCLUSION
1630{"vabs", 0, ARMVFP2, 0},
1631#endif
1632#ifdef VFP_INTERPRETER_TABLE
1633INTERPRETER_TRANSLATE(vfpinstr),
1634#endif
1635#ifdef VFP_INTERPRETER_LABEL
1636&&VFPLABEL_INST,
1637#endif
1638#ifdef VFP_INTERPRETER_STRUCT
1639typedef struct _vabs_inst {
1640 unsigned int instr;
1641 unsigned int dp_operation;
1642} vfpinstr_inst;
1643#endif
1644#ifdef VFP_INTERPRETER_TRANS
1645ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1646{
1647 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VABS);
1648
1649 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
1650 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1651
1652 inst_base->cond = BITS(inst, 28, 31);
1653 inst_base->idx = index;
1654 inst_base->br = NON_BRANCH;
1655 inst_base->load_r15 = 0;
1656
1657 inst_cream->dp_operation = BIT(inst, 8);
1658 inst_cream->instr = inst;
1659
1660 return inst_base;
1661}
1662#endif
1663#ifdef VFP_INTERPRETER_IMPL
1664VFPLABEL_INST:
1665{
1666 INC_ICOUNTER;
1667 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1668 CHECK_VFP_ENABLED;
1669
1670 DBG("VABS :\n");
1671
1672 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1673
1674 int ret;
1675
1676 if (inst_cream->dp_operation)
1677 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
1678 else
1679 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
1680
1681 CHECK_VFP_CDP_RET;
1682 }
1683 cpu->Reg[15] += GET_INST_SIZE(cpu);
1684 INC_PC(sizeof(vfpinstr_inst));
1685 FETCH_INST;
1686 GOTO_NEXT_INST;
1687}
1688#endif
1689#ifdef VFP_CDP_TRANS
1690if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x7) == 6)
1691{
1692 DBG("VABS :\n");
1693}
1694#endif
1695#ifdef VFP_DYNCOM_TABLE
1696DYNCOM_FILL_ACTION(vfpinstr),
1697#endif
1698#ifdef VFP_DYNCOM_TAG
1699int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1700{
1701 int instr_size = INSTR_SIZE;
1702 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1703 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1704 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1705 return instr_size;
1706}
1707#endif
1708#ifdef VFP_DYNCOM_TRANS
1709int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1710 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1711 //arch_arm_undef(cpu, bb, instr);
1712 int single = BIT(8) == 0;
1713 int d = (single ? BITS(12,15)<<1 | BIT(22) : BIT(22) << 4 | BITS(12,15));
1714 int m = (single ? BITS(0, 3)<<1 | BIT(5) : BITS(0, 3) | BIT(5)<<4);
1715 Value* m0;
1716 if (single)
1717 {
1718 m0 = FR32(m);
1719 m0 = SELECT(FPCMP_OLT(m0,FPCONST32(0.0)),FPNEG32(m0),m0);
1720 LETFPS(d,m0);
1721 }
1722 else
1723 {
1724 /* Check endian please */
1725 Value *lo = FR32(2 * m);
1726 Value *hi = FR32(2 * m + 1);
1727 hi = IBITCAST32(hi);
1728 lo = IBITCAST32(lo);
1729 Value *hi64 = ZEXT64(hi);
1730 Value* lo64 = ZEXT64(lo);
1731 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
1732 m0 = FPBITCAST64(v64);
1733 m0 = SELECT(FPCMP_OLT(m0,FPCONST64(0.0)),FPNEG64(m0),m0);
1734 Value *val64 = IBITCAST64(m0);
1735 hi = LSHR(val64,CONST64(32));
1736 lo = AND(val64,CONST64(0xffffffff));
1737 hi = TRUNC32(hi);
1738 lo = TRUNC32(lo);
1739 hi = FPBITCAST32(hi);
1740 lo = FPBITCAST32(lo);
1741 LETFPS(2*d ,lo);
1742 LETFPS(d*2 + 1 , hi);
1743 }
1744 return No_exp;
1745}
1746#endif
1747#undef vfpinstr
1748#undef vfpinstr_inst
1749#undef VFPLABEL_INST
1750
1751/* ----------------------------------------------------------------------- */
1752/* VNEG */
1753/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */
1754#define vfpinstr vneg
1755#define vfpinstr_inst vneg_inst
1756#define VFPLABEL_INST VNEG_INST
1757#ifdef VFP_DECODE
1758//{"vneg", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 1, 4, 4, 0},
1759{"vneg", 5, ARMVFP2, 23, 27, 0x1d, 17, 21, 0x18, 9, 11, 0x5, 6, 7, 1, 4, 4, 0},
1760#endif
1761#ifdef VFP_DECODE_EXCLUSION
1762{"vneg", 0, ARMVFP2, 0},
1763#endif
1764#ifdef VFP_INTERPRETER_TABLE
1765INTERPRETER_TRANSLATE(vfpinstr),
1766#endif
1767#ifdef VFP_INTERPRETER_LABEL
1768&&VFPLABEL_INST,
1769#endif
1770#ifdef VFP_INTERPRETER_STRUCT
1771typedef struct _vneg_inst {
1772 unsigned int instr;
1773 unsigned int dp_operation;
1774} vfpinstr_inst;
1775#endif
1776#ifdef VFP_INTERPRETER_TRANS
1777ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1778{
1779 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VNEG);
1780
1781 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
1782 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1783
1784 inst_base->cond = BITS(inst, 28, 31);
1785 inst_base->idx = index;
1786 inst_base->br = NON_BRANCH;
1787 inst_base->load_r15 = 0;
1788
1789 inst_cream->dp_operation = BIT(inst, 8);
1790 inst_cream->instr = inst;
1791
1792 return inst_base;
1793}
1794#endif
1795#ifdef VFP_INTERPRETER_IMPL
1796VFPLABEL_INST:
1797{
1798 INC_ICOUNTER;
1799 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1800 CHECK_VFP_ENABLED;
1801
1802 DBG("VNEG :\n");
1803
1804 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1805
1806 int ret;
1807
1808 if (inst_cream->dp_operation)
1809 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
1810 else
1811 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
1812
1813 CHECK_VFP_CDP_RET;
1814 }
1815 cpu->Reg[15] += GET_INST_SIZE(cpu);
1816 INC_PC(sizeof(vfpinstr_inst));
1817 FETCH_INST;
1818 GOTO_NEXT_INST;
1819}
1820#endif
1821#ifdef VFP_CDP_TRANS
1822if ((OPC_1 & 0xB) == 0xB && CRn == 1 && (OPC_2 & 0x7) == 2)
1823{
1824 DBG("VNEG :\n");
1825}
1826#endif
1827#ifdef VFP_DYNCOM_TABLE
1828DYNCOM_FILL_ACTION(vfpinstr),
1829#endif
1830#ifdef VFP_DYNCOM_TAG
1831int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1832{
1833 int instr_size = INSTR_SIZE;
1834 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1835 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1836 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1837 return instr_size;
1838}
1839#endif
1840#ifdef VFP_DYNCOM_TRANS
1841int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1842 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1843 //arch_arm_undef(cpu, bb, instr);
1844 int single = BIT(8) == 0;
1845 int d = (single ? BITS(12,15)<<1 | BIT(22) : BIT(22) << 4 | BITS(12,15));
1846 int m = (single ? BITS(0, 3)<<1 | BIT(5) : BITS(0, 3) | BIT(5)<<4);
1847 Value* m0;
1848 if (single)
1849 {
1850 m0 = FR32(m);
1851 m0 = FPNEG32(m0);
1852 LETFPS(d,m0);
1853 }
1854 else
1855 {
1856 /* Check endian please */
1857 Value *lo = FR32(2 * m);
1858 Value *hi = FR32(2 * m + 1);
1859 hi = IBITCAST32(hi);
1860 lo = IBITCAST32(lo);
1861 Value *hi64 = ZEXT64(hi);
1862 Value* lo64 = ZEXT64(lo);
1863 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
1864 m0 = FPBITCAST64(v64);
1865 m0 = FPNEG64(m0);
1866 Value *val64 = IBITCAST64(m0);
1867 hi = LSHR(val64,CONST64(32));
1868 lo = AND(val64,CONST64(0xffffffff));
1869 hi = TRUNC32(hi);
1870 lo = TRUNC32(lo);
1871 hi = FPBITCAST32(hi);
1872 lo = FPBITCAST32(lo);
1873 LETFPS(2*d ,lo);
1874 LETFPS(d*2 + 1 , hi);
1875 }
1876 return No_exp;
1877}
1878#endif
1879#undef vfpinstr
1880#undef vfpinstr_inst
1881#undef VFPLABEL_INST
1882
1883/* ----------------------------------------------------------------------- */
1884/* VSQRT */
1885/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */
1886#define vfpinstr vsqrt
1887#define vfpinstr_inst vsqrt_inst
1888#define VFPLABEL_INST VSQRT_INST
1889#ifdef VFP_DECODE
1890{"vsqrt", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x31, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
1891#endif
1892#ifdef VFP_DECODE_EXCLUSION
1893{"vsqrt", 0, ARMVFP2, 0},
1894#endif
1895#ifdef VFP_INTERPRETER_TABLE
1896INTERPRETER_TRANSLATE(vfpinstr),
1897#endif
1898#ifdef VFP_INTERPRETER_LABEL
1899&&VFPLABEL_INST,
1900#endif
1901#ifdef VFP_INTERPRETER_STRUCT
1902typedef struct _vsqrt_inst {
1903 unsigned int instr;
1904 unsigned int dp_operation;
1905} vfpinstr_inst;
1906#endif
1907#ifdef VFP_INTERPRETER_TRANS
1908ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1909{
1910 VFP_DEBUG_TRANSLATE;
1911
1912 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
1913 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1914
1915 inst_base->cond = BITS(inst, 28, 31);
1916 inst_base->idx = index;
1917 inst_base->br = NON_BRANCH;
1918 inst_base->load_r15 = 0;
1919
1920 inst_cream->dp_operation = BIT(inst, 8);
1921 inst_cream->instr = inst;
1922
1923 return inst_base;
1924}
1925#endif
1926#ifdef VFP_INTERPRETER_IMPL
1927VFPLABEL_INST:
1928{
1929 INC_ICOUNTER;
1930 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1931 CHECK_VFP_ENABLED;
1932
1933 DBG("VSQRT :\n");
1934
1935 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
1936
1937 int ret;
1938
1939 if (inst_cream->dp_operation)
1940 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
1941 else
1942 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
1943
1944 CHECK_VFP_CDP_RET;
1945 }
1946 cpu->Reg[15] += GET_INST_SIZE(cpu);
1947 INC_PC(sizeof(vfpinstr_inst));
1948 FETCH_INST;
1949 GOTO_NEXT_INST;
1950}
1951#endif
1952#ifdef VFP_CDP_TRANS
1953if ((OPC_1 & 0xB) == 0xB && CRn == 1 && (OPC_2 & 0x7) == 6)
1954{
1955 DBG("VSQRT :\n");
1956}
1957#endif
1958#ifdef VFP_DYNCOM_TABLE
1959DYNCOM_FILL_ACTION(vfpinstr),
1960#endif
1961#ifdef VFP_DYNCOM_TAG
1962int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1963{
1964 int instr_size = INSTR_SIZE;
1965 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1966 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1967 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1968 return instr_size;
1969}
1970#endif
1971#ifdef VFP_DYNCOM_TRANS
1972int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1973 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1974 //arch_arm_undef(cpu, bb, instr);
1975 int dp_op = (BIT(8) == 1);
1976 int d = dp_op ? BITS(12,15) | BIT(22) << 4 : BIT(22) | BITS(12,15) << 1;
1977 int m = dp_op ? BITS(0,3) | BIT(5) << 4 : BIT(5) | BITS(0,3) << 1;
1978 Value* v;
1979 Value* tmp;
1980 if(dp_op){
1981 v = SHL(ZEXT64(IBITCAST32(FR32(2 * m + 1))),CONST64(32));
1982 tmp = ZEXT64(IBITCAST32(FR32(2 * m)));
1983 v = OR(v,tmp);
1984 v = FPSQRT(FPBITCAST64(v));
1985 tmp = TRUNC32(LSHR(IBITCAST64(v),CONST64(32)));
1986 v = TRUNC32(AND(IBITCAST64(v),CONST64( 0xffffffff)));
1987 LETFPS(2 * d , FPBITCAST32(v));
1988 LETFPS(2 * d + 1, FPBITCAST32(tmp));
1989 }else {
1990 v = FR32(m);
1991 v = FPSQRT(FPEXT(64,v));
1992 v = FPTRUNC(32,v);
1993 LETFPS(d,v);
1994 }
1995 return No_exp;
1996}
1997#endif
1998#undef vfpinstr
1999#undef vfpinstr_inst
2000#undef VFPLABEL_INST
2001
2002/* ----------------------------------------------------------------------- */
2003/* VCMP VCMPE */
2004/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 1 */
2005#define vfpinstr vcmp
2006#define vfpinstr_inst vcmp_inst
2007#define VFPLABEL_INST VCMP_INST
2008#ifdef VFP_DECODE
2009{"vcmp", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x34, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
2010#endif
2011#ifdef VFP_DECODE_EXCLUSION
2012{"vcmp", 0, ARMVFP2, 0},
2013#endif
2014#ifdef VFP_INTERPRETER_TABLE
2015INTERPRETER_TRANSLATE(vfpinstr),
2016#endif
2017#ifdef VFP_INTERPRETER_LABEL
2018&&VFPLABEL_INST,
2019#endif
2020#ifdef VFP_INTERPRETER_STRUCT
2021typedef struct _vcmp_inst {
2022 unsigned int instr;
2023 unsigned int dp_operation;
2024} vfpinstr_inst;
2025#endif
2026#ifdef VFP_INTERPRETER_TRANS
2027ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2028{
2029 VFP_DEBUG_TRANSLATE;
2030
2031 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
2032 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2033
2034 inst_base->cond = BITS(inst, 28, 31);
2035 inst_base->idx = index;
2036 inst_base->br = NON_BRANCH;
2037 inst_base->load_r15 = 0;
2038
2039 inst_cream->dp_operation = BIT(inst, 8);
2040 inst_cream->instr = inst;
2041
2042 return inst_base;
2043}
2044#endif
2045#ifdef VFP_INTERPRETER_IMPL
2046VFPLABEL_INST:
2047{
2048 INC_ICOUNTER;
2049 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2050 CHECK_VFP_ENABLED;
2051
2052 DBG("VCMP(1) :\n");
2053
2054 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2055
2056 int ret;
2057
2058 if (inst_cream->dp_operation)
2059 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2060 else
2061 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2062
2063 CHECK_VFP_CDP_RET;
2064 }
2065 cpu->Reg[15] += GET_INST_SIZE(cpu);
2066 INC_PC(sizeof(vfpinstr_inst));
2067 FETCH_INST;
2068 GOTO_NEXT_INST;
2069}
2070#endif
2071#ifdef VFP_CDP_TRANS
2072if ((OPC_1 & 0xB) == 0xB && CRn == 4 && (OPC_2 & 0x2) == 2)
2073{
2074 DBG("VCMP(1) :\n");
2075}
2076#endif
2077#ifdef VFP_DYNCOM_TABLE
2078DYNCOM_FILL_ACTION(vfpinstr),
2079#endif
2080#ifdef VFP_DYNCOM_TAG
2081int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2082{
2083 int instr_size = INSTR_SIZE;
2084 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
2085 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2086 return instr_size;
2087}
2088#endif
2089#ifdef VFP_DYNCOM_TRANS
2090int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2091 DBG("\t\tin %s instruction is executed out of JIT.\n", __FUNCTION__);
2092 //arch_arm_undef(cpu, bb, instr);
2093 int dp_op = (BIT(8) == 1);
2094 int d = dp_op ? BITS(12,15) | BIT(22) << 4 : BIT(22) | BITS(12,15) << 1;
2095 int m = dp_op ? BITS(0,3) | BIT(5) << 4 : BIT(5) | BITS(0,3) << 1;
2096 Value* v;
2097 Value* tmp;
2098 Value* n;
2099 Value* z;
2100 Value* c;
2101 Value* vt;
2102 Value* v1;
2103 Value* nzcv;
2104 if(dp_op){
2105 v = SHL(ZEXT64(IBITCAST32(FR32(2 * m + 1))),CONST64(32));
2106 tmp = ZEXT64(IBITCAST32(FR32(2 * m)));
2107 v1 = OR(v,tmp);
2108 v = SHL(ZEXT64(IBITCAST32(FR32(2 * d + 1))),CONST64(32));
2109 tmp = ZEXT64(IBITCAST32(FR32(2 * d)));
2110 v = OR(v,tmp);
2111 z = FPCMP_OEQ(FPBITCAST64(v),FPBITCAST64(v1));
2112 n = FPCMP_OLT(FPBITCAST64(v),FPBITCAST64(v1));
2113 c = FPCMP_OGE(FPBITCAST64(v),FPBITCAST64(v1));
2114 tmp = FPCMP_UNO(FPBITCAST64(v),FPBITCAST64(v1));
2115 v1 = tmp;
2116 c = OR(c,tmp);
2117 n = SHL(ZEXT32(n),CONST32(31));
2118 z = SHL(ZEXT32(z),CONST32(30));
2119 c = SHL(ZEXT32(c),CONST32(29));
2120 v1 = SHL(ZEXT32(v1),CONST(28));
2121 nzcv = OR(OR(OR(n,z),c),v1);
2122 v = R(VFP_FPSCR);
2123 tmp = OR(nzcv,AND(v,CONST32(0x0fffffff)));
2124 LET(VFP_FPSCR,tmp);
2125 }else {
2126 z = FPCMP_OEQ(FR32(d),FR32(m));
2127 n = FPCMP_OLT(FR32(d),FR32(m));
2128 c = FPCMP_OGE(FR32(d),FR32(m));
2129 tmp = FPCMP_UNO(FR32(d),FR32(m));
2130 c = OR(c,tmp);
2131 v1 = tmp;
2132 n = SHL(ZEXT32(n),CONST32(31));
2133 z = SHL(ZEXT32(z),CONST32(30));
2134 c = SHL(ZEXT32(c),CONST32(29));
2135 v1 = SHL(ZEXT32(v1),CONST(28));
2136 nzcv = OR(OR(OR(n,z),c),v1);
2137 v = R(VFP_FPSCR);
2138 tmp = OR(nzcv,AND(v,CONST32(0x0fffffff)));
2139 LET(VFP_FPSCR,tmp);
2140 }
2141 return No_exp;
2142}
2143#endif
2144#undef vfpinstr
2145#undef vfpinstr_inst
2146#undef VFPLABEL_INST
2147
2148/* ----------------------------------------------------------------------- */
2149/* VCMP VCMPE */
2150/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 2 */
2151#define vfpinstr vcmp2
2152#define vfpinstr_inst vcmp2_inst
2153#define VFPLABEL_INST VCMP2_INST
2154#ifdef VFP_DECODE
2155{"vcmp2", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x35, 9, 11, 0x5, 0, 6, 0x40},
2156#endif
2157#ifdef VFP_DECODE_EXCLUSION
2158{"vcmp2", 0, ARMVFP2, 0},
2159#endif
2160#ifdef VFP_INTERPRETER_TABLE
2161INTERPRETER_TRANSLATE(vfpinstr),
2162#endif
2163#ifdef VFP_INTERPRETER_LABEL
2164&&VFPLABEL_INST,
2165#endif
2166#ifdef VFP_INTERPRETER_STRUCT
2167typedef struct _vcmp2_inst {
2168 unsigned int instr;
2169 unsigned int dp_operation;
2170} vfpinstr_inst;
2171#endif
2172#ifdef VFP_INTERPRETER_TRANS
2173ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2174{
2175 VFP_DEBUG_TRANSLATE;
2176
2177 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
2178 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2179
2180 inst_base->cond = BITS(inst, 28, 31);
2181 inst_base->idx = index;
2182 inst_base->br = NON_BRANCH;
2183 inst_base->load_r15 = 0;
2184
2185 inst_cream->dp_operation = BIT(inst, 8);
2186 inst_cream->instr = inst;
2187
2188 return inst_base;
2189}
2190#endif
2191#ifdef VFP_INTERPRETER_IMPL
2192VFPLABEL_INST:
2193{
2194 INC_ICOUNTER;
2195 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2196 CHECK_VFP_ENABLED;
2197
2198 DBG("VCMP(2) :\n");
2199
2200 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2201
2202 int ret;
2203
2204 if (inst_cream->dp_operation)
2205 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2206 else
2207 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2208
2209 CHECK_VFP_CDP_RET;
2210 }
2211 cpu->Reg[15] += GET_INST_SIZE(cpu);
2212 INC_PC(sizeof(vfpinstr_inst));
2213 FETCH_INST;
2214 GOTO_NEXT_INST;
2215}
2216#endif
2217#ifdef VFP_CDP_TRANS
2218if ((OPC_1 & 0xB) == 0xB && CRn == 5 && (OPC_2 & 0x2) == 2 && CRm == 0)
2219{
2220 DBG("VCMP(2) :\n");
2221}
2222#endif
2223#ifdef VFP_DYNCOM_TABLE
2224DYNCOM_FILL_ACTION(vfpinstr),
2225#endif
2226#ifdef VFP_DYNCOM_TAG
2227int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2228{
2229 int instr_size = INSTR_SIZE;
2230 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
2231 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2232 return instr_size;
2233}
2234#endif
2235#ifdef VFP_DYNCOM_TRANS
2236int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2237 DBG("\t\tin %s instruction will executed out of JIT.\n", __FUNCTION__);
2238 //arch_arm_undef(cpu, bb, instr);
2239 int dp_op = (BIT(8) == 1);
2240 int d = dp_op ? BITS(12,15) | BIT(22) << 4 : BIT(22) | BITS(12,15) << 1;
2241 //int m = dp_op ? BITS(0,3) | BIT(5) << 4 : BIT(5) | BITS(0,3) << 1;
2242 Value* v;
2243 Value* tmp;
2244 Value* n;
2245 Value* z;
2246 Value* c;
2247 Value* vt;
2248 Value* v1;
2249 Value* nzcv;
2250 if(dp_op){
2251 v1 = CONST64(0);
2252 v = SHL(ZEXT64(IBITCAST32(FR32(2 * d + 1))),CONST64(32));
2253 tmp = ZEXT64(IBITCAST32(FR32(2 * d)));
2254 v = OR(v,tmp);
2255 z = FPCMP_OEQ(FPBITCAST64(v),FPBITCAST64(v1));
2256 n = FPCMP_OLT(FPBITCAST64(v),FPBITCAST64(v1));
2257 c = FPCMP_OGE(FPBITCAST64(v),FPBITCAST64(v1));
2258 tmp = FPCMP_UNO(FPBITCAST64(v),FPBITCAST64(v1));
2259 v1 = tmp;
2260 c = OR(c,tmp);
2261 n = SHL(ZEXT32(n),CONST32(31));
2262 z = SHL(ZEXT32(z),CONST32(30));
2263 c = SHL(ZEXT32(c),CONST32(29));
2264 v1 = SHL(ZEXT32(v1),CONST(28));
2265 nzcv = OR(OR(OR(n,z),c),v1);
2266 v = R(VFP_FPSCR);
2267 tmp = OR(nzcv,AND(v,CONST32(0x0fffffff)));
2268 LET(VFP_FPSCR,tmp);
2269 }else {
2270 v1 = CONST(0);
2271 v1 = FPBITCAST32(v1);
2272 z = FPCMP_OEQ(FR32(d),v1);
2273 n = FPCMP_OLT(FR32(d),v1);
2274 c = FPCMP_OGE(FR32(d),v1);
2275 tmp = FPCMP_UNO(FR32(d),v1);
2276 c = OR(c,tmp);
2277 v1 = tmp;
2278 n = SHL(ZEXT32(n),CONST32(31));
2279 z = SHL(ZEXT32(z),CONST32(30));
2280 c = SHL(ZEXT32(c),CONST32(29));
2281 v1 = SHL(ZEXT32(v1),CONST(28));
2282 nzcv = OR(OR(OR(n,z),c),v1);
2283 v = R(VFP_FPSCR);
2284 tmp = OR(nzcv,AND(v,CONST32(0x0fffffff)));
2285 LET(VFP_FPSCR,tmp);
2286 }
2287 return No_exp;
2288}
2289#endif
2290#undef vfpinstr
2291#undef vfpinstr_inst
2292#undef VFPLABEL_INST
2293
2294/* ----------------------------------------------------------------------- */
2295/* VCVTBDS between double and single */
2296/* cond 1110 1D11 0111 Vd-- 101X 11M0 Vm-- */
2297#define vfpinstr vcvtbds
2298#define vfpinstr_inst vcvtbds_inst
2299#define VFPLABEL_INST VCVTBDS_INST
2300#ifdef VFP_DECODE
2301{"vcvt(bds)", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x37, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
2302#endif
2303#ifdef VFP_DECODE_EXCLUSION
2304{"vcvt(bds)", 0, ARMVFP2, 0},
2305#endif
2306#ifdef VFP_INTERPRETER_TABLE
2307INTERPRETER_TRANSLATE(vfpinstr),
2308#endif
2309#ifdef VFP_INTERPRETER_LABEL
2310&&VFPLABEL_INST,
2311#endif
2312#ifdef VFP_INTERPRETER_STRUCT
2313typedef struct _vcvtbds_inst {
2314 unsigned int instr;
2315 unsigned int dp_operation;
2316} vfpinstr_inst;
2317#endif
2318#ifdef VFP_INTERPRETER_TRANS
2319ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2320{
2321 VFP_DEBUG_TRANSLATE;
2322
2323 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
2324 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2325
2326 inst_base->cond = BITS(inst, 28, 31);
2327 inst_base->idx = index;
2328 inst_base->br = NON_BRANCH;
2329 inst_base->load_r15 = 0;
2330
2331 inst_cream->dp_operation = BIT(inst, 8);
2332 inst_cream->instr = inst;
2333
2334 return inst_base;
2335}
2336#endif
2337#ifdef VFP_INTERPRETER_IMPL
2338VFPLABEL_INST:
2339{
2340 INC_ICOUNTER;
2341 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2342 CHECK_VFP_ENABLED;
2343
2344 DBG("VCVT(BDS) :\n");
2345
2346 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2347
2348 int ret;
2349
2350 if (inst_cream->dp_operation)
2351 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2352 else
2353 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2354
2355 CHECK_VFP_CDP_RET;
2356 }
2357 cpu->Reg[15] += GET_INST_SIZE(cpu);
2358 INC_PC(sizeof(vfpinstr_inst));
2359 FETCH_INST;
2360 GOTO_NEXT_INST;
2361}
2362#endif
2363#ifdef VFP_CDP_TRANS
2364if ((OPC_1 & 0xB) == 0xB && CRn == 7 && (OPC_2 & 0x6) == 6)
2365{
2366 DBG("VCVT(BDS) :\n");
2367}
2368#endif
2369#ifdef VFP_DYNCOM_TABLE
2370DYNCOM_FILL_ACTION(vfpinstr),
2371#endif
2372#ifdef VFP_DYNCOM_TAG
2373int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2374{
2375 int instr_size = INSTR_SIZE;
2376 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
2377 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2378 return instr_size;
2379}
2380#endif
2381#ifdef VFP_DYNCOM_TRANS
2382int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2383 DBG("\t\tin %s instruction is executed out.\n", __FUNCTION__);
2384 //arch_arm_undef(cpu, bb, instr);
2385 int dp_op = (BIT(8) == 1);
2386 int d = dp_op ? BITS(12,15) << 1 | BIT(22) : BIT(22) << 4 | BITS(12,15);
2387 int m = dp_op ? BITS(0,3) | BIT(5) << 4 : BIT(5) | BITS(0,3) << 1;
2388 int d2s = dp_op;
2389 Value* v;
2390 Value* tmp;
2391 Value* v1;
2392 if(d2s){
2393 v = SHL(ZEXT64(IBITCAST32(FR32(2 * m + 1))),CONST64(32));
2394 tmp = ZEXT64(IBITCAST32(FR32(2 * m)));
2395 v1 = OR(v,tmp);
2396 tmp = FPTRUNC(32,FPBITCAST64(v1));
2397 LETFPS(d,tmp);
2398 }else {
2399 v = FR32(m);
2400 tmp = FPEXT(64,v);
2401 v = IBITCAST64(tmp);
2402 tmp = TRUNC32(AND(v,CONST64(0xffffffff)));
2403 v1 = TRUNC32(LSHR(v,CONST64(32)));
2404 LETFPS(2 * d, FPBITCAST32(tmp) );
2405 LETFPS(2 * d + 1, FPBITCAST32(v1));
2406 }
2407 return No_exp;
2408}
2409#endif
2410#undef vfpinstr
2411#undef vfpinstr_inst
2412#undef VFPLABEL_INST
2413
2414/* ----------------------------------------------------------------------- */
2415/* VCVTBFF between floating point and fixed point */
2416/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */
2417#define vfpinstr vcvtbff
2418#define vfpinstr_inst vcvtbff_inst
2419#define VFPLABEL_INST VCVTBFF_INST
2420#ifdef VFP_DECODE
2421{"vcvt(bff)", 6, ARMVFP3, 23, 27, 0x1d, 19, 21, 0x7, 17, 17, 0x1, 9, 11, 0x5, 6, 6, 1},
2422#endif
2423#ifdef VFP_DECODE_EXCLUSION
2424{"vcvt(bff)", 0, ARMVFP3, 4, 4, 1},
2425#endif
2426#ifdef VFP_INTERPRETER_TABLE
2427INTERPRETER_TRANSLATE(vfpinstr),
2428#endif
2429#ifdef VFP_INTERPRETER_LABEL
2430&&VFPLABEL_INST,
2431#endif
2432#ifdef VFP_INTERPRETER_STRUCT
2433typedef struct _vcvtbff_inst {
2434 unsigned int instr;
2435 unsigned int dp_operation;
2436} vfpinstr_inst;
2437#endif
2438#ifdef VFP_INTERPRETER_TRANS
2439ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2440{
2441 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VCVTBFF);
2442
2443 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
2444 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2445
2446 inst_base->cond = BITS(inst, 28, 31);
2447 inst_base->idx = index;
2448 inst_base->br = NON_BRANCH;
2449 inst_base->load_r15 = 0;
2450
2451 inst_cream->dp_operation = BIT(inst, 8);
2452 inst_cream->instr = inst;
2453
2454 return inst_base;
2455}
2456#endif
2457#ifdef VFP_INTERPRETER_IMPL
2458VFPLABEL_INST:
2459{
2460 INC_ICOUNTER;
2461 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2462 CHECK_VFP_ENABLED;
2463
2464 DBG("VCVT(BFF) :\n");
2465
2466 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2467
2468 int ret;
2469
2470 if (inst_cream->dp_operation)
2471 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2472 else
2473 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2474
2475 CHECK_VFP_CDP_RET;
2476 }
2477 cpu->Reg[15] += GET_INST_SIZE(cpu);
2478 INC_PC(sizeof(vfpinstr_inst));
2479 FETCH_INST;
2480 GOTO_NEXT_INST;
2481}
2482#endif
2483#ifdef VFP_CDP_TRANS
2484if ((OPC_1 & 0xB) == 0xB && CRn >= 0xA && (OPC_2 & 0x2) == 2)
2485{
2486 DBG("VCVT(BFF) :\n");
2487}
2488#endif
2489#ifdef VFP_DYNCOM_TABLE
2490DYNCOM_FILL_ACTION(vfpinstr),
2491#endif
2492#ifdef VFP_DYNCOM_TAG
2493int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2494{
2495 int instr_size = INSTR_SIZE;
2496 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2497 arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
2498 return instr_size;
2499}
2500#endif
2501#ifdef VFP_DYNCOM_TRANS
2502int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2503 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2504 arch_arm_undef(cpu, bb, instr);
2505 return No_exp;
2506}
2507#endif
2508#undef vfpinstr
2509#undef vfpinstr_inst
2510#undef VFPLABEL_INST
2511
2512/* ----------------------------------------------------------------------- */
2513/* VCVTBFI between floating point and integer */
2514/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */
2515#define vfpinstr vcvtbfi
2516#define vfpinstr_inst vcvtbfi_inst
2517#define VFPLABEL_INST VCVTBFI_INST
2518#ifdef VFP_DECODE
2519{"vcvt(bfi)", 5, ARMVFP2, 23, 27, 0x1d, 19, 21, 0x7, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
2520#endif
2521#ifdef VFP_DECODE_EXCLUSION
2522{"vcvt(bfi)", 0, ARMVFP2, 0},
2523#endif
2524#ifdef VFP_INTERPRETER_TABLE
2525INTERPRETER_TRANSLATE(vfpinstr),
2526#endif
2527#ifdef VFP_INTERPRETER_LABEL
2528&&VFPLABEL_INST,
2529#endif
2530#ifdef VFP_INTERPRETER_STRUCT
2531typedef struct _vcvtbfi_inst {
2532 unsigned int instr;
2533 unsigned int dp_operation;
2534} vfpinstr_inst;
2535#endif
2536#ifdef VFP_INTERPRETER_TRANS
2537ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2538{
2539 VFP_DEBUG_TRANSLATE;
2540
2541 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
2542 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2543
2544 inst_base->cond = BITS(inst, 28, 31);
2545 inst_base->idx = index;
2546 inst_base->br = NON_BRANCH;
2547 inst_base->load_r15 = 0;
2548
2549 inst_cream->dp_operation = BIT(inst, 8);
2550 inst_cream->instr = inst;
2551
2552
2553 return inst_base;
2554}
2555#endif
2556#ifdef VFP_INTERPRETER_IMPL
2557VFPLABEL_INST:
2558{
2559 INC_ICOUNTER;
2560 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2561 CHECK_VFP_ENABLED;
2562
2563 DBG("VCVT(BFI) :\n");
2564
2565 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2566
2567 int ret;
2568
2569 if (inst_cream->dp_operation)
2570 ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2571 else
2572 ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2573
2574 CHECK_VFP_CDP_RET;
2575 }
2576 cpu->Reg[15] += GET_INST_SIZE(cpu);
2577 INC_PC(sizeof(vfpinstr_inst));
2578 FETCH_INST;
2579 GOTO_NEXT_INST;
2580}
2581#endif
2582#ifdef VFP_CDP_TRANS
2583if ((OPC_1 & 0xB) == 0xB && CRn > 7 && (OPC_2 & 0x2) == 2)
2584{
2585 DBG("VCVT(BFI) :\n");
2586}
2587#endif
2588#ifdef VFP_DYNCOM_TABLE
2589DYNCOM_FILL_ACTION(vfpinstr),
2590#endif
2591#ifdef VFP_DYNCOM_TAG
2592int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2593{
2594 int instr_size = INSTR_SIZE;
2595 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2596 DBG("\t\tin %s, instruction will be executed out of JIT.\n", __FUNCTION__);
2597 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
2598 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2599 return instr_size;
2600}
2601#endif
2602#ifdef VFP_DYNCOM_TRANS
2603int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2604 DBG("\t\tin %s, instruction will be executed out of JIT.\n", __FUNCTION__);
2605 //arch_arm_undef(cpu, bb, instr);
2606 unsigned int opc2 = BITS(16,18);
2607 int to_integer = ((opc2 >> 2) == 1);
2608 int dp_op = (BIT(8) == 1);
2609 unsigned int op = BIT(7);
2610 int m,d;
2611 Value* v;
2612 Value* hi;
2613 Value* lo;
2614 Value* v64;
2615 if(to_integer){
2616 d = BIT(22) | (BITS(12,15) << 1);
2617 if(dp_op)
2618 m = BITS(0,3) | BIT(5) << 4;
2619 else
2620 m = BIT(5) | BITS(0,3) << 1;
2621 }else {
2622 m = BIT(5) | BITS(0,3) << 1;
2623 if(dp_op)
2624 d = BITS(12,15) | BIT(22) << 4;
2625 else
2626 d = BIT(22) | BITS(12,15) << 1;
2627 }
2628 if(to_integer){
2629 if(dp_op){
2630 lo = FR32(m * 2);
2631 hi = FR32(m * 2 + 1);
2632 hi = ZEXT64(IBITCAST32(hi));
2633 lo = ZEXT64(IBITCAST32(lo));
2634 v64 = OR(SHL(hi,CONST64(32)),lo);
2635 if(BIT(16)){
2636 v = FPTOSI(32,FPBITCAST64(v64));
2637 }
2638 else
2639 v = FPTOUI(32,FPBITCAST64(v64));
2640
2641 v = FPBITCAST32(v);
2642 LETFPS(d,v);
2643 }else {
2644 v = FR32(m);
2645 if(BIT(16)){
2646
2647 v = FPTOSI(32,v);
2648 }
2649 else
2650 v = FPTOUI(32,v);
2651 LETFPS(d,FPBITCAST32(v));
2652 }
2653 }else {
2654 if(dp_op){
2655 v = IBITCAST32(FR32(m));
2656 if(BIT(7))
2657 v64 = SITOFP(64,v);
2658 else
2659 v64 = UITOFP(64,v);
2660 v = IBITCAST64(v64);
2661 hi = FPBITCAST32(TRUNC32(LSHR(v,CONST64(32))));
2662 lo = FPBITCAST32(TRUNC32(AND(v,CONST64(0xffffffff))));
2663 LETFPS(2 * d , lo);
2664 LETFPS(2 * d + 1, hi);
2665 }else {
2666 v = IBITCAST32(FR32(m));
2667 if(BIT(7))
2668 v = SITOFP(32,v);
2669 else
2670 v = UITOFP(32,v);
2671 LETFPS(d,v);
2672 }
2673 }
2674 return No_exp;
2675}
2676
2677/**
2678* @brief The implementation of c language for vcvtbfi instruction of dyncom
2679*
2680* @param cpu
2681* @param instr
2682*
2683* @return
2684*/
2685int vcvtbfi_instr_impl(arm_core_t* cpu, uint32 instr){
2686 int dp_operation = BIT(8);
2687 int ret;
2688 if (dp_operation)
2689 ret = vfp_double_cpdo(cpu, instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2690 else
2691 ret = vfp_single_cpdo(cpu, instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2692
2693 vfp_raise_exceptions(cpu, ret, instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2694 return 0;
2695}
2696#endif
2697#undef vfpinstr
2698#undef vfpinstr_inst
2699#undef VFPLABEL_INST
2700
2701/* ----------------------------------------------------------------------- */
2702/* MRC / MCR instructions */
2703/* cond 1110 AAAL XXXX XXXX 101C XBB1 XXXX */
2704/* cond 1110 op11 CRn- Rt-- copr op21 CRm- */
2705
2706/* ----------------------------------------------------------------------- */
2707/* VMOVBRS between register and single precision */
2708/* cond 1110 000o Vn-- Rt-- 1010 N001 0000 */
2709/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */
2710#define vfpinstr vmovbrs
2711#define vfpinstr_inst vmovbrs_inst
2712#define VFPLABEL_INST VMOVBRS_INST
2713#ifdef VFP_DECODE
2714{"vmovbrs", 3, ARMVFP2, 21, 27, 0x70, 8, 11, 0xA, 0, 6, 0x10},
2715#endif
2716#ifdef VFP_DECODE_EXCLUSION
2717{"vmovbrs", 0, ARMVFP2, 0},
2718#endif
2719#ifdef VFP_INTERPRETER_TABLE
2720INTERPRETER_TRANSLATE(vfpinstr),
2721#endif
2722#ifdef VFP_INTERPRETER_LABEL
2723&&VFPLABEL_INST,
2724#endif
2725#ifdef VFP_INTERPRETER_STRUCT
2726typedef struct _vmovbrs_inst {
2727 unsigned int to_arm;
2728 unsigned int t;
2729 unsigned int n;
2730} vfpinstr_inst;
2731#endif
2732#ifdef VFP_INTERPRETER_TRANS
2733ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2734{
2735 VFP_DEBUG_TRANSLATE;
2736
2737 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
2738 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2739
2740 inst_base->cond = BITS(inst, 28, 31);
2741 inst_base->idx = index;
2742 inst_base->br = NON_BRANCH;
2743 inst_base->load_r15 = 0;
2744
2745 inst_cream->to_arm = BIT(inst, 20) == 1;
2746 inst_cream->t = BITS(inst, 12, 15);
2747 inst_cream->n = BIT(inst, 7) | BITS(inst, 16, 19)<<1;
2748
2749 return inst_base;
2750}
2751#endif
2752#ifdef VFP_INTERPRETER_IMPL
2753VFPLABEL_INST:
2754{
2755 INC_ICOUNTER;
2756 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2757 CHECK_VFP_ENABLED;
2758
2759 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2760
2761 VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t]));
2762 }
2763 cpu->Reg[15] += GET_INST_SIZE(cpu);
2764 INC_PC(sizeof(vfpinstr_inst));
2765 FETCH_INST;
2766 GOTO_NEXT_INST;
2767}
2768#endif
2769#ifdef VFP_MRC_TRANS
2770if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
2771{
2772 /* VMOV r to s */
2773 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
2774 VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, value);
2775 return ARMul_DONE;
2776}
2777#endif
2778#ifdef VFP_MCR_TRANS
2779if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
2780{
2781 /* VMOV s to r */
2782 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
2783 VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, &value);
2784 return ARMul_DONE;
2785}
2786#endif
2787#ifdef VFP_MRC_IMPL
2788void VMOVBRS(ARMul_State * state, ARMword to_arm, ARMword t, ARMword n, ARMword *value)
2789{
2790 DBG("VMOV(BRS) :\n");
2791 if (to_arm)
2792 {
2793 DBG("\tr%d <= s%d=[%x]\n", t, n, state->ExtReg[n]);
2794 *value = state->ExtReg[n];
2795 }
2796 else
2797 {
2798 DBG("\ts%d <= r%d=[%x]\n", n, t, *value);
2799 state->ExtReg[n] = *value;
2800 }
2801}
2802#endif
2803#ifdef VFP_DYNCOM_TABLE
2804DYNCOM_FILL_ACTION(vfpinstr),
2805#endif
2806#ifdef VFP_DYNCOM_TAG
2807int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2808{
2809 int instr_size = INSTR_SIZE;
2810 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2811 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2812 return instr_size;
2813}
2814#endif
2815#ifdef VFP_DYNCOM_TRANS
2816int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2817 DBG("VMOV(BRS) :\n");
2818 int to_arm = BIT(20) == 1;
2819 int t = BITS(12, 15);
2820 int n = BIT(7) | BITS(16, 19)<<1;
2821
2822 if (to_arm)
2823 {
2824 DBG("\tr%d <= s%d\n", t, n);
2825 LET(t, IBITCAST32(FR32(n)));
2826 }
2827 else
2828 {
2829 DBG("\ts%d <= r%d\n", n, t);
2830 LETFPS(n, FPBITCAST32(R(t)));
2831 }
2832 return No_exp;
2833}
2834#endif
2835#undef vfpinstr
2836#undef vfpinstr_inst
2837#undef VFPLABEL_INST
2838
2839/* ----------------------------------------------------------------------- */
2840/* VMSR */
2841/* cond 1110 1110 reg- Rt-- 1010 0001 0000 */
2842/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */
2843#define vfpinstr vmsr
2844#define vfpinstr_inst vmsr_inst
2845#define VFPLABEL_INST VMSR_INST
2846#ifdef VFP_DECODE
2847{"vmsr", 2, ARMVFP2, 20, 27, 0xEE, 0, 11, 0xA10},
2848#endif
2849#ifdef VFP_DECODE_EXCLUSION
2850{"vmsr", 0, ARMVFP2, 0},
2851#endif
2852#ifdef VFP_INTERPRETER_TABLE
2853INTERPRETER_TRANSLATE(vfpinstr),
2854#endif
2855#ifdef VFP_INTERPRETER_LABEL
2856&&VFPLABEL_INST,
2857#endif
2858#ifdef VFP_INTERPRETER_STRUCT
2859typedef struct _vmsr_inst {
2860 unsigned int reg;
2861 unsigned int Rd;
2862} vfpinstr_inst;
2863#endif
2864#ifdef VFP_INTERPRETER_TRANS
2865ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2866{
2867 VFP_DEBUG_TRANSLATE;
2868
2869 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
2870 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2871
2872 inst_base->cond = BITS(inst, 28, 31);
2873 inst_base->idx = index;
2874 inst_base->br = NON_BRANCH;
2875 inst_base->load_r15 = 0;
2876
2877 inst_cream->reg = BITS(inst, 16, 19);
2878 inst_cream->Rd = BITS(inst, 12, 15);
2879
2880 return inst_base;
2881}
2882#endif
2883#ifdef VFP_INTERPRETER_IMPL
2884VFPLABEL_INST:
2885{
2886 INC_ICOUNTER;
2887 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2888 /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled ,
2889 and in privilegied mode */
2890 /* Exceptions must be checked, according to v7 ref manual */
2891 CHECK_VFP_ENABLED;
2892
2893 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
2894
2895 VMSR(cpu, inst_cream->reg, inst_cream->Rd);
2896 }
2897 cpu->Reg[15] += GET_INST_SIZE(cpu);
2898 INC_PC(sizeof(vfpinstr_inst));
2899 FETCH_INST;
2900 GOTO_NEXT_INST;
2901}
2902#endif
2903#ifdef VFP_MCR_TRANS
2904if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
2905{
2906 VMSR(state, CRn, Rt);
2907 return ARMul_DONE;
2908}
2909#endif
2910#ifdef VFP_MCR_IMPL
2911void VMSR(ARMul_State * state, ARMword reg, ARMword Rt)
2912{
2913 if (reg == 1)
2914 {
2915 DBG("VMSR :\tfpscr <= r%d=[%x]\n", Rt, state->Reg[Rt]);
2916 state->VFP[VFP_OFFSET(VFP_FPSCR)] = state->Reg[Rt];
2917 }
2918 else if (reg == 8)
2919 {
2920 DBG("VMSR :\tfpexc <= r%d=[%x]\n", Rt, state->Reg[Rt]);
2921 state->VFP[VFP_OFFSET(VFP_FPEXC)] = state->Reg[Rt];
2922 }
2923}
2924#endif
2925#ifdef VFP_DYNCOM_TABLE
2926DYNCOM_FILL_ACTION(vfpinstr),
2927#endif
2928#ifdef VFP_DYNCOM_TAG
2929int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2930{
2931 int instr_size = INSTR_SIZE;
2932 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2933 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
2934 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2935 return instr_size;
2936}
2937#endif
2938#ifdef VFP_DYNCOM_TRANS
2939int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2940 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2941 //arch_arm_undef(cpu, bb, instr);
2942 DBG("VMSR :");
2943 if(RD == 15) {
2944 printf("in %s is not implementation.\n", __FUNCTION__);
2945 exit(-1);
2946 }
2947
2948 Value *data = NULL;
2949 int reg = RN;
2950 int Rt = RD;
2951 if (reg == 1)
2952 {
2953 LET(VFP_FPSCR, R(Rt));
2954 DBG("\tflags <= fpscr\n");
2955 }
2956 else
2957 {
2958 switch (reg)
2959 {
2960 case 8:
2961 LET(VFP_FPEXC, R(Rt));
2962 DBG("\tfpexc <= r%d \n", Rt);
2963 break;
2964 default:
2965 DBG("\tSUBARCHITECTURE DEFINED\n");
2966 break;
2967 }
2968 }
2969 return No_exp;
2970}
2971#endif
2972#undef vfpinstr
2973#undef vfpinstr_inst
2974#undef VFPLABEL_INST
2975
2976/* ----------------------------------------------------------------------- */
2977/* VMOVBRC register to scalar */
2978/* cond 1110 0XX0 Vd-- Rt-- 1011 DXX1 0000 */
2979/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */
2980#define vfpinstr vmovbrc
2981#define vfpinstr_inst vmovbrc_inst
2982#define VFPLABEL_INST VMOVBRC_INST
2983#ifdef VFP_DECODE
2984{"vmovbrc", 4, ARMVFP2, 23, 27, 0x1C, 20, 20, 0x0, 8,11,0xB, 0,4,0x10},
2985#endif
2986#ifdef VFP_DECODE_EXCLUSION
2987{"vmovbrc", 0, ARMVFP2, 0},
2988#endif
2989#ifdef VFP_INTERPRETER_TABLE
2990INTERPRETER_TRANSLATE(vfpinstr),
2991#endif
2992#ifdef VFP_INTERPRETER_LABEL
2993&&VFPLABEL_INST,
2994#endif
2995#ifdef VFP_INTERPRETER_STRUCT
2996typedef struct _vmovbrc_inst {
2997 unsigned int esize;
2998 unsigned int index;
2999 unsigned int d;
3000 unsigned int t;
3001} vfpinstr_inst;
3002#endif
3003#ifdef VFP_INTERPRETER_TRANS
3004ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3005{
3006 VFP_DEBUG_TRANSLATE;
3007
3008 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
3009 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3010
3011 inst_base->cond = BITS(inst, 28, 31);
3012 inst_base->idx = index;
3013 inst_base->br = NON_BRANCH;
3014 inst_base->load_r15 = 0;
3015
3016 inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4;
3017 inst_cream->t = BITS(inst, 12, 15);
3018 /* VFP variant of instruction */
3019 inst_cream->esize = 32;
3020 inst_cream->index = BIT(inst, 21);
3021
3022 return inst_base;
3023}
3024#endif
3025#ifdef VFP_INTERPRETER_IMPL
3026VFPLABEL_INST:
3027{
3028 INC_ICOUNTER;
3029 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3030 CHECK_VFP_ENABLED;
3031
3032 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3033
3034 VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
3035 }
3036 cpu->Reg[15] += GET_INST_SIZE(cpu);
3037 INC_PC(sizeof(vfpinstr_inst));
3038 FETCH_INST;
3039 GOTO_NEXT_INST;
3040}
3041#endif
3042#ifdef VFP_MCR_TRANS
3043if ((OPC_1 & 0x4) == 0 && CoProc == 11 && CRm == 0)
3044{
3045 VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
3046 return ARMul_DONE;
3047}
3048#endif
3049#ifdef VFP_DYNCOM_TABLE
3050DYNCOM_FILL_ACTION(vfpinstr),
3051#endif
3052#ifdef VFP_DYNCOM_TAG
3053int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3054{
3055 int instr_size = INSTR_SIZE;
3056 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3057 arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
3058 return instr_size;
3059}
3060#endif
3061#ifdef VFP_DYNCOM_TRANS
3062int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3063 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3064 arch_arm_undef(cpu, bb, instr);
3065 return No_exp;
3066}
3067#endif
3068#undef vfpinstr
3069#undef vfpinstr_inst
3070#undef VFPLABEL_INST
3071
3072/* ----------------------------------------------------------------------- */
3073/* VMRS */
3074/* cond 1110 1111 CRn- Rt-- 1010 0001 0000 */
3075/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */
3076#define vfpinstr vmrs
3077#define vfpinstr_inst vmrs_inst
3078#define VFPLABEL_INST VMRS_INST
3079#ifdef VFP_DECODE
3080{"vmrs", 2, ARMVFP2, 20, 27, 0xEF, 0, 11, 0xa10},
3081#endif
3082#ifdef VFP_DECODE_EXCLUSION
3083{"vmrs", 0, ARMVFP2, 0},
3084#endif
3085#ifdef VFP_INTERPRETER_TABLE
3086INTERPRETER_TRANSLATE(vfpinstr),
3087#endif
3088#ifdef VFP_INTERPRETER_LABEL
3089&&VFPLABEL_INST,
3090#endif
3091#ifdef VFP_INTERPRETER_STRUCT
3092typedef struct _vmrs_inst {
3093 unsigned int reg;
3094 unsigned int Rt;
3095} vfpinstr_inst;
3096#endif
3097#ifdef VFP_INTERPRETER_TRANS
3098ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3099{
3100 VFP_DEBUG_TRANSLATE;
3101
3102 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
3103 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3104
3105 inst_base->cond = BITS(inst, 28, 31);
3106 inst_base->idx = index;
3107 inst_base->br = NON_BRANCH;
3108 inst_base->load_r15 = 0;
3109
3110 inst_cream->reg = BITS(inst, 16, 19);
3111 inst_cream->Rt = BITS(inst, 12, 15);
3112
3113 return inst_base;
3114}
3115#endif
3116#ifdef VFP_INTERPRETER_IMPL
3117VFPLABEL_INST:
3118{
3119 INC_ICOUNTER;
3120 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3121 /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled,
3122 and in privilegied mode */
3123 /* Exceptions must be checked, according to v7 ref manual */
3124 CHECK_VFP_ENABLED;
3125
3126 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3127
3128 DBG("VMRS :");
3129
3130 if (inst_cream->reg == 1) /* FPSCR */
3131 {
3132 if (inst_cream->Rt != 15)
3133 {
3134 cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_OFFSET(VFP_FPSCR)];
3135 DBG("\tr%d <= fpscr[%08x]\n", inst_cream->Rt, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
3136 }
3137 else
3138 {
3139 cpu->NFlag = (cpu->VFP[VFP_OFFSET(VFP_FPSCR)] >> 31) & 1;
3140 cpu->ZFlag = (cpu->VFP[VFP_OFFSET(VFP_FPSCR)] >> 30) & 1;
3141 cpu->CFlag = (cpu->VFP[VFP_OFFSET(VFP_FPSCR)] >> 29) & 1;
3142 cpu->VFlag = (cpu->VFP[VFP_OFFSET(VFP_FPSCR)] >> 28) & 1;
3143 DBG("\tflags <= fpscr[%1xxxxxxxx]\n", cpu->VFP[VFP_OFFSET(VFP_FPSCR)]>>28);
3144 }
3145 }
3146 else
3147 {
3148 switch (inst_cream->reg)
3149 {
3150 case 0:
3151 cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_OFFSET(VFP_FPSID)];
3152 DBG("\tr%d <= fpsid[%08x]\n", inst_cream->Rt, cpu->VFP[VFP_OFFSET(VFP_FPSID)]);
3153 break;
3154 case 6:
3155 /* MVFR1, VFPv3 only ? */
3156 DBG("\tr%d <= MVFR1 unimplemented\n", inst_cream->Rt);
3157 break;
3158 case 7:
3159 /* MVFR0, VFPv3 only? */
3160 DBG("\tr%d <= MVFR0 unimplemented\n", inst_cream->Rt);
3161 break;
3162 case 8:
3163 cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_OFFSET(VFP_FPEXC)];
3164 DBG("\tr%d <= fpexc[%08x]\n", inst_cream->Rt, cpu->VFP[VFP_OFFSET(VFP_FPEXC)]);
3165 break;
3166 default:
3167 DBG("\tSUBARCHITECTURE DEFINED\n");
3168 break;
3169 }
3170 }
3171 }
3172 cpu->Reg[15] += GET_INST_SIZE(cpu);
3173 INC_PC(sizeof(vfpinstr_inst));
3174 FETCH_INST;
3175 GOTO_NEXT_INST;
3176}
3177#endif
3178#ifdef VFP_MRC_TRANS
3179if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
3180{
3181 VMRS(state, CRn, Rt, value);
3182 return ARMul_DONE;
3183}
3184#endif
3185#ifdef VFP_MRC_IMPL
3186void VMRS(ARMul_State * state, ARMword reg, ARMword Rt, ARMword * value)
3187{
3188 DBG("VMRS :");
3189 if (reg == 1)
3190 {
3191 if (Rt != 15)
3192 {
3193 *value = state->VFP[VFP_OFFSET(VFP_FPSCR)];
3194 DBG("\tr%d <= fpscr[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
3195 }
3196 else
3197 {
3198 *value = state->VFP[VFP_OFFSET(VFP_FPSCR)] ;
3199 DBG("\tflags <= fpscr[%1xxxxxxxx]\n", state->VFP[VFP_OFFSET(VFP_FPSCR)]>>28);
3200 }
3201 }
3202 else
3203 {
3204 switch (reg)
3205 {
3206 case 0:
3207 *value = state->VFP[VFP_OFFSET(VFP_FPSID)];
3208 DBG("\tr%d <= fpsid[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPSID)]);
3209 break;
3210 case 6:
3211 /* MVFR1, VFPv3 only ? */
3212 DBG("\tr%d <= MVFR1 unimplemented\n", Rt);
3213 break;
3214 case 7:
3215 /* MVFR0, VFPv3 only? */
3216 DBG("\tr%d <= MVFR0 unimplemented\n", Rt);
3217 break;
3218 case 8:
3219 *value = state->VFP[VFP_OFFSET(VFP_FPEXC)];
3220 DBG("\tr%d <= fpexc[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPEXC)]);
3221 break;
3222 default:
3223 DBG("\tSUBARCHITECTURE DEFINED\n");
3224 break;
3225 }
3226 }
3227}
3228#endif
3229#ifdef VFP_DYNCOM_TABLE
3230DYNCOM_FILL_ACTION(vfpinstr),
3231#endif
3232#ifdef VFP_DYNCOM_TAG
3233int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3234{
3235 int instr_size = INSTR_SIZE;
3236 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3237 DBG("\t\tin %s .\n", __FUNCTION__);
3238 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
3239 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
3240 return instr_size;
3241}
3242#endif
3243#ifdef VFP_DYNCOM_TRANS
3244int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3245 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3246 //arch_arm_undef(cpu, bb, instr);
3247
3248 Value *data = NULL;
3249 int reg = BITS(16, 19);;
3250 int Rt = BITS(12, 15);
3251 DBG("VMRS : reg=%d, Rt=%d\n", reg, Rt);
3252 if (reg == 1)
3253 {
3254 if (Rt != 15)
3255 {
3256 LET(Rt, R(VFP_FPSCR));
3257 DBG("\tr%d <= fpscr\n", Rt);
3258 }
3259 else
3260 {
3261 //LET(Rt, R(VFP_FPSCR));
3262 update_cond_from_fpscr(cpu, instr, bb, pc);
3263 DBG("In %s, \tflags <= fpscr\n", __FUNCTION__);
3264 }
3265 }
3266 else
3267 {
3268 switch (reg)
3269 {
3270 case 0:
3271 LET(Rt, R(VFP_FPSID));
3272 DBG("\tr%d <= fpsid\n", Rt);
3273 break;
3274 case 6:
3275 /* MVFR1, VFPv3 only ? */
3276 DBG("\tr%d <= MVFR1 unimplemented\n", Rt);
3277 break;
3278 case 7:
3279 /* MVFR0, VFPv3 only? */
3280 DBG("\tr%d <= MVFR0 unimplemented\n", Rt);
3281 break;
3282 case 8:
3283 LET(Rt, R(VFP_FPEXC));
3284 DBG("\tr%d <= fpexc\n", Rt);
3285 break;
3286 default:
3287 DBG("\tSUBARCHITECTURE DEFINED\n");
3288 break;
3289 }
3290 }
3291
3292 return No_exp;
3293}
3294#endif
3295#undef vfpinstr
3296#undef vfpinstr_inst
3297#undef VFPLABEL_INST
3298
3299/* ----------------------------------------------------------------------- */
3300/* VMOVBCR scalar to register */
3301/* cond 1110 XXX1 Vd-- Rt-- 1011 NXX1 0000 */
3302/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MCR */
3303#define vfpinstr vmovbcr
3304#define vfpinstr_inst vmovbcr_inst
3305#define VFPLABEL_INST VMOVBCR_INST
3306#ifdef VFP_DECODE
3307{"vmovbcr", 4, ARMVFP2, 24, 27, 0xE, 20, 20, 1, 8, 11,0xB, 0,4, 0x10},
3308#endif
3309#ifdef VFP_DECODE_EXCLUSION
3310{"vmovbcr", 0, ARMVFP2, 0},
3311#endif
3312#ifdef VFP_INTERPRETER_TABLE
3313INTERPRETER_TRANSLATE(vfpinstr),
3314#endif
3315#ifdef VFP_INTERPRETER_LABEL
3316&&VFPLABEL_INST,
3317#endif
3318#ifdef VFP_INTERPRETER_STRUCT
3319typedef struct _vmovbcr_inst {
3320 unsigned int esize;
3321 unsigned int index;
3322 unsigned int d;
3323 unsigned int t;
3324} vfpinstr_inst;
3325#endif
3326#ifdef VFP_INTERPRETER_TRANS
3327ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3328{
3329 VFP_DEBUG_TRANSLATE;
3330
3331 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
3332 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3333
3334 inst_base->cond = BITS(inst, 28, 31);
3335 inst_base->idx = index;
3336 inst_base->br = NON_BRANCH;
3337 inst_base->load_r15 = 0;
3338
3339 inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4;
3340 inst_cream->t = BITS(inst, 12, 15);
3341 /* VFP variant of instruction */
3342 inst_cream->esize = 32;
3343 inst_cream->index = BIT(inst, 21);
3344
3345 return inst_base;
3346}
3347#endif
3348#ifdef VFP_INTERPRETER_IMPL
3349VFPLABEL_INST:
3350{
3351 INC_ICOUNTER;
3352 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3353 CHECK_VFP_ENABLED;
3354
3355 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3356
3357 VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
3358 }
3359 cpu->Reg[15] += GET_INST_SIZE(cpu);
3360 INC_PC(sizeof(vfpinstr_inst));
3361 FETCH_INST;
3362 GOTO_NEXT_INST;
3363}
3364#endif
3365#ifdef VFP_MCR_TRANS
3366if (CoProc == 11 && CRm == 0)
3367{
3368 VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
3369 return ARMul_DONE;
3370}
3371#endif
3372#ifdef VFP_DYNCOM_TABLE
3373DYNCOM_FILL_ACTION(vfpinstr),
3374#endif
3375#ifdef VFP_DYNCOM_TAG
3376int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3377{
3378 int instr_size = INSTR_SIZE;
3379 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3380 arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
3381 return instr_size;
3382}
3383#endif
3384#ifdef VFP_DYNCOM_TRANS
3385int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3386 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3387 arch_arm_undef(cpu, bb, instr);
3388 return No_exp;
3389}
3390#endif
3391#undef vfpinstr
3392#undef vfpinstr_inst
3393#undef VFPLABEL_INST
3394
3395/* ----------------------------------------------------------------------- */
3396/* MRRC / MCRR instructions */
3397/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */
3398/* cond 1100 0100 Rt2- Rt-- copr opc1 CRm- MCRR */
3399
3400/* ----------------------------------------------------------------------- */
3401/* VMOVBRRSS between 2 registers to 2 singles */
3402/* cond 1100 010X Rt2- Rt-- 1010 00X1 Vm-- */
3403/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */
3404#define vfpinstr vmovbrrss
3405#define vfpinstr_inst vmovbrrss_inst
3406#define VFPLABEL_INST VMOVBRRSS_INST
3407#ifdef VFP_DECODE
3408{"vmovbrrss", 3, ARMVFP2, 21, 27, 0x62, 8, 11, 0xA, 4, 4, 1},
3409#endif
3410#ifdef VFP_DECODE_EXCLUSION
3411{"vmovbrrss", 0, ARMVFP2, 0},
3412#endif
3413#ifdef VFP_INTERPRETER_TABLE
3414INTERPRETER_TRANSLATE(vfpinstr),
3415#endif
3416#ifdef VFP_INTERPRETER_LABEL
3417&&VFPLABEL_INST,
3418#endif
3419#ifdef VFP_INTERPRETER_STRUCT
3420typedef struct _vmovbrrss_inst {
3421 unsigned int to_arm;
3422 unsigned int t;
3423 unsigned int t2;
3424 unsigned int m;
3425} vfpinstr_inst;
3426#endif
3427#ifdef VFP_INTERPRETER_TRANS
3428ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3429{
3430 VFP_DEBUG_TRANSLATE;
3431
3432 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
3433 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3434
3435 inst_base->cond = BITS(inst, 28, 31);
3436 inst_base->idx = index;
3437 inst_base->br = NON_BRANCH;
3438 inst_base->load_r15 = 0;
3439
3440 inst_cream->to_arm = BIT(inst, 20) == 1;
3441 inst_cream->t = BITS(inst, 12, 15);
3442 inst_cream->t2 = BITS(inst, 16, 19);
3443 inst_cream->m = BITS(inst, 0, 3)<<1|BIT(inst, 5);
3444
3445 return inst_base;
3446}
3447#endif
3448#ifdef VFP_INTERPRETER_IMPL
3449VFPLABEL_INST:
3450{
3451 INC_ICOUNTER;
3452 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3453 CHECK_VFP_ENABLED;
3454
3455 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3456
3457 VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS);
3458 }
3459 cpu->Reg[15] += GET_INST_SIZE(cpu);
3460 INC_PC(sizeof(vfpinstr_inst));
3461 FETCH_INST;
3462 GOTO_NEXT_INST;
3463}
3464#endif
3465#ifdef VFP_MCRR_TRANS
3466if (CoProc == 10 && (OPC_1 & 0xD) == 1)
3467{
3468 VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS);
3469 return ARMul_DONE;
3470}
3471#endif
3472#ifdef VFP_MRRC_TRANS
3473if (CoProc == 10 && (OPC_1 & 0xD) == 1)
3474{
3475 VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS);
3476 return ARMul_DONE;
3477}
3478#endif
3479#ifdef VFP_DYNCOM_TABLE
3480DYNCOM_FILL_ACTION(vfpinstr),
3481#endif
3482#ifdef VFP_DYNCOM_TAG
3483int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3484{
3485 int instr_size = INSTR_SIZE;
3486 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3487 arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
3488 return instr_size;
3489}
3490#endif
3491#ifdef VFP_DYNCOM_TRANS
3492int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3493 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3494 arch_arm_undef(cpu, bb, instr);
3495 return No_exp;
3496}
3497#endif
3498#undef vfpinstr
3499#undef vfpinstr_inst
3500#undef VFPLABEL_INST
3501
3502/* ----------------------------------------------------------------------- */
3503/* VMOVBRRD between 2 registers and 1 double */
3504/* cond 1100 010X Rt2- Rt-- 1011 00X1 Vm-- */
3505/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */
3506#define vfpinstr vmovbrrd
3507#define vfpinstr_inst vmovbrrd_inst
3508#define VFPLABEL_INST VMOVBRRD_INST
3509#ifdef VFP_DECODE
3510{"vmovbrrd", 3, ARMVFP2, 21, 27, 0x62, 6, 11, 0x2c, 4, 4, 1},
3511#endif
3512#ifdef VFP_DECODE_EXCLUSION
3513{"vmovbrrd", 0, ARMVFP2, 0},
3514#endif
3515#ifdef VFP_INTERPRETER_TABLE
3516INTERPRETER_TRANSLATE(vfpinstr),
3517#endif
3518#ifdef VFP_INTERPRETER_LABEL
3519&&VFPLABEL_INST,
3520#endif
3521#ifdef VFP_INTERPRETER_STRUCT
3522typedef struct _vmovbrrd_inst {
3523 unsigned int to_arm;
3524 unsigned int t;
3525 unsigned int t2;
3526 unsigned int m;
3527} vfpinstr_inst;
3528#endif
3529#ifdef VFP_INTERPRETER_TRANS
3530ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3531{
3532 VFP_DEBUG_TRANSLATE;
3533
3534 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
3535 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3536
3537 inst_base->cond = BITS(inst, 28, 31);
3538 inst_base->idx = index;
3539 inst_base->br = NON_BRANCH;
3540 inst_base->load_r15 = 0;
3541
3542 inst_cream->to_arm = BIT(inst, 20) == 1;
3543 inst_cream->t = BITS(inst, 12, 15);
3544 inst_cream->t2 = BITS(inst, 16, 19);
3545 inst_cream->m = BIT(inst, 5)<<4 | BITS(inst, 0, 3);
3546
3547 return inst_base;
3548}
3549#endif
3550#ifdef VFP_INTERPRETER_IMPL
3551VFPLABEL_INST:
3552{
3553 INC_ICOUNTER;
3554 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3555 CHECK_VFP_ENABLED;
3556
3557 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3558
3559 VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m,
3560 &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2]));
3561 }
3562 cpu->Reg[15] += GET_INST_SIZE(cpu);
3563 INC_PC(sizeof(vfpinstr_inst));
3564 FETCH_INST;
3565 GOTO_NEXT_INST;
3566}
3567#endif
3568#ifdef VFP_MCRR_TRANS
3569if (CoProc == 11 && (OPC_1 & 0xD) == 1)
3570{
3571 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
3572 VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, &value1, &value2);
3573 return ARMul_DONE;
3574}
3575#endif
3576#ifdef VFP_MRRC_TRANS
3577if (CoProc == 11 && (OPC_1 & 0xD) == 1)
3578{
3579 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
3580 VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, value1, value2);
3581 return ARMul_DONE;
3582}
3583#endif
3584#ifdef VFP_MRRC_IMPL
3585void VMOVBRRD(ARMul_State * state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword *value1, ARMword *value2)
3586{
3587 DBG("VMOV(BRRD) :\n");
3588 if (to_arm)
3589 {
3590 DBG("\tr[%d-%d] <= s[%d-%d]=[%x-%x]\n", t2, t, n*2+1, n*2, state->ExtReg[n*2+1], state->ExtReg[n*2]);
3591 *value2 = state->ExtReg[n*2+1];
3592 *value1 = state->ExtReg[n*2];
3593 }
3594 else
3595 {
3596 DBG("\ts[%d-%d] <= r[%d-%d]=[%x-%x]\n", n*2+1, n*2, t2, t, *value2, *value1);
3597 state->ExtReg[n*2+1] = *value2;
3598 state->ExtReg[n*2] = *value1;
3599 }
3600}
3601
3602#endif
3603#ifdef VFP_DYNCOM_TABLE
3604DYNCOM_FILL_ACTION(vfpinstr),
3605#endif
3606#ifdef VFP_DYNCOM_TAG
3607int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3608{
3609 int instr_size = INSTR_SIZE;
3610 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3611 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
3612 if(instr >> 28 != 0xe)
3613 *tag |= TAG_CONDITIONAL;
3614 return instr_size;
3615}
3616#endif
3617#ifdef VFP_DYNCOM_TRANS
3618int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3619 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3620 //arch_arm_undef(cpu, bb, instr);
3621 int to_arm = BIT(20) == 1;
3622 int t = BITS(12, 15);
3623 int t2 = BITS(16, 19);
3624 int n = BIT(5)<<4 | BITS(0, 3);
3625 if(to_arm){
3626 LET(t, IBITCAST32(FR32(n * 2)));
3627 LET(t2, IBITCAST32(FR32(n * 2 + 1)));
3628 }
3629 else{
3630 LETFPS(n * 2, FPBITCAST32(R(t)));
3631 LETFPS(n * 2 + 1, FPBITCAST32(R(t2)));
3632 }
3633 return No_exp;
3634}
3635#endif
3636#undef vfpinstr
3637#undef vfpinstr_inst
3638#undef VFPLABEL_INST
3639
3640/* ----------------------------------------------------------------------- */
3641/* LDC/STC between 2 registers and 1 double */
3642/* cond 110X XXX1 Rn-- CRd- copr imm- imm- LDC */
3643/* cond 110X XXX0 Rn-- CRd- copr imm8 imm8 STC */
3644
3645/* ----------------------------------------------------------------------- */
3646/* VSTR */
3647/* cond 1101 UD00 Rn-- Vd-- 101X imm8 imm8 */
3648#define vfpinstr vstr
3649#define vfpinstr_inst vstr_inst
3650#define VFPLABEL_INST VSTR_INST
3651#ifdef VFP_DECODE
3652{"vstr", 3, ARMVFP2, 24, 27, 0xd, 20, 21, 0, 9, 11, 0x5},
3653#endif
3654#ifdef VFP_DECODE_EXCLUSION
3655{"vstr", 0, ARMVFP2, 0},
3656#endif
3657#ifdef VFP_INTERPRETER_TABLE
3658INTERPRETER_TRANSLATE(vfpinstr),
3659#endif
3660#ifdef VFP_INTERPRETER_LABEL
3661&&VFPLABEL_INST,
3662#endif
3663#ifdef VFP_INTERPRETER_STRUCT
3664typedef struct _vstr_inst {
3665 unsigned int single;
3666 unsigned int n;
3667 unsigned int d;
3668 unsigned int imm32;
3669 unsigned int add;
3670} vfpinstr_inst;
3671#endif
3672#ifdef VFP_INTERPRETER_TRANS
3673ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3674{
3675 VFP_DEBUG_TRANSLATE;
3676
3677 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
3678 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3679
3680 inst_base->cond = BITS(inst, 28, 31);
3681 inst_base->idx = index;
3682 inst_base->br = NON_BRANCH;
3683 inst_base->load_r15 = 0;
3684
3685 inst_cream->single = BIT(inst, 8) == 0;
3686 inst_cream->add = BIT(inst, 23);
3687 inst_cream->imm32 = BITS(inst, 0,7) << 2;
3688 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4);
3689 inst_cream->n = BITS(inst, 16, 19);
3690
3691 return inst_base;
3692}
3693#endif
3694#ifdef VFP_INTERPRETER_IMPL
3695VFPLABEL_INST:
3696{
3697 INC_ICOUNTER;
3698 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3699 CHECK_VFP_ENABLED;
3700
3701 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3702
3703 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]);
3704 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32);
3705 DBG("VSTR :\n");
3706
3707
3708 if (inst_cream->single)
3709 {
3710 fault = check_address_validity(cpu, addr, &phys_addr, 0);
3711 if (fault) goto MMU_EXCEPTION;
3712 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d], 32);
3713 if (fault) goto MMU_EXCEPTION;
3714 DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d, cpu->ExtReg[inst_cream->d]);
3715 }
3716 else
3717 {
3718 fault = check_address_validity(cpu, addr, &phys_addr, 0);
3719 if (fault) goto MMU_EXCEPTION;
3720
3721 /* Check endianness */
3722 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d*2], 32);
3723 if (fault) goto MMU_EXCEPTION;
3724
3725 fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
3726 if (fault) goto MMU_EXCEPTION;
3727
3728 fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[inst_cream->d*2+1], 32);
3729 if (fault) goto MMU_EXCEPTION;
3730 DBG("\taddr[%x-%x] <= s[%d-%d]=[%x-%x]\n", addr+4, addr, inst_cream->d*2+1, inst_cream->d*2, cpu->ExtReg[inst_cream->d*2+1], cpu->ExtReg[inst_cream->d*2]);
3731 }
3732 }
3733 cpu->Reg[15] += GET_INST_SIZE(cpu);
3734 INC_PC(sizeof(vstr_inst));
3735 FETCH_INST;
3736 GOTO_NEXT_INST;
3737}
3738#endif
3739#ifdef VFP_STC_TRANS
3740if (P == 1 && W == 0)
3741{
3742 return VSTR(state, type, instr, value);
3743}
3744#endif
3745#ifdef VFP_STC_IMPL
3746int VSTR(ARMul_State * state, int type, ARMword instr, ARMword * value)
3747{
3748 static int i = 0;
3749 static int single_reg, add, d, n, imm32, regs;
3750 if (type == ARMul_FIRST)
3751 {
3752 single_reg = BIT(8) == 0; /* Double precision */
3753 add = BIT(23); /* */
3754 imm32 = BITS(0,7)<<2; /* may not be used */
3755 d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
3756 n = BITS(16, 19); /* destination register */
3757
3758 DBG("VSTR :\n");
3759
3760 i = 0;
3761 regs = 1;
3762
3763 return ARMul_DONE;
3764 }
3765 else if (type == ARMul_DATA)
3766 {
3767 if (single_reg)
3768 {
3769 *value = state->ExtReg[d+i];
3770 DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d+i]);
3771 i++;
3772 if (i < regs)
3773 return ARMul_INC;
3774 else
3775 return ARMul_DONE;
3776 }
3777 else
3778 {
3779 /* FIXME Careful of endianness, may need to rework this */
3780 *value = state->ExtReg[d*2+i];
3781 DBG("\taddr[?] <= s[%d]=[%x]\n", d*2+i, state->ExtReg[d*2+i]);
3782 i++;
3783 if (i < regs*2)
3784 return ARMul_INC;
3785 else
3786 return ARMul_DONE;
3787 }
3788 }
3789
3790 return -1;
3791}
3792#endif
3793#ifdef VFP_DYNCOM_TABLE
3794DYNCOM_FILL_ACTION(vfpinstr),
3795#endif
3796#ifdef VFP_DYNCOM_TAG
3797int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3798{
3799 int instr_size = INSTR_SIZE;
3800 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
3801 DBG("In %s, pc=0x%x, next_pc=0x%x\n", __FUNCTION__, pc, *next_pc);
3802 *tag |= TAG_NEW_BB;
3803 if(instr >> 28 != 0xe)
3804 *tag |= TAG_CONDITIONAL;
3805
3806 return instr_size;
3807}
3808#endif
3809#ifdef VFP_DYNCOM_TRANS
3810int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3811 int single = BIT(8) == 0;
3812 int add = BIT(23);
3813 int imm32 = BITS(0,7) << 2;
3814 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4));
3815 int n = BITS(16, 19);
3816
3817 Value* base = (n == 15) ? ADD(AND(R(n), CONST(0xFFFFFFFC)), CONST(8)): R(n);
3818 Value* Addr = add ? ADD(base, CONST(imm32)) : SUB(base, CONST(imm32));
3819 DBG("VSTR :\n");
3820 //if(single)
3821 // bb = arch_check_mm(cpu, bb, Addr, 4, 0, cpu->dyncom_engine->bb_trap);
3822 //else
3823 // bb = arch_check_mm(cpu, bb, Addr, 8, 0, cpu->dyncom_engine->bb_trap);
3824 //Value* phys_addr;
3825 if(single){
3826 #if 0
3827 phys_addr = get_phys_addr(cpu, bb, Addr, 0);
3828 bb = cpu->dyncom_engine->bb;
3829 arch_write_memory(cpu, bb, phys_addr, RSPR(d), 32);
3830 #endif
3831 //memory_write(cpu, bb, Addr, RSPR(d), 32);
3832 memory_write(cpu, bb, Addr, IBITCAST32(FR32(d)), 32);
3833 bb = cpu->dyncom_engine->bb;
3834 }
3835 else{
3836 #if 0
3837 phys_addr = get_phys_addr(cpu, bb, Addr, 0);
3838 bb = cpu->dyncom_engine->bb;
3839 arch_write_memory(cpu, bb, phys_addr, RSPR(d * 2), 32);
3840 #endif
3841 //memory_write(cpu, bb, Addr, RSPR(d * 2), 32);
3842 memory_write(cpu, bb, Addr, IBITCAST32(FR32(d * 2)), 32);
3843 bb = cpu->dyncom_engine->bb;
3844 #if 0
3845 phys_addr = get_phys_addr(cpu, bb, ADD(Addr, CONST(4)), 0);
3846 bb = cpu->dyncom_engine->bb;
3847 arch_write_memory(cpu, bb, phys_addr, RSPR(d * 2 + 1), 32);
3848 #endif
3849 //memory_write(cpu, bb, ADD(Addr, CONST(4)), RSPR(d * 2 + 1), 32);
3850 memory_write(cpu, bb, ADD(Addr, CONST(4)), IBITCAST32(FR32(d * 2 + 1)), 32);
3851 bb = cpu->dyncom_engine->bb;
3852 }
3853 return No_exp;
3854}
3855#endif
3856#undef vfpinstr
3857#undef vfpinstr_inst
3858#undef VFPLABEL_INST
3859
3860/* ----------------------------------------------------------------------- */
3861/* VPUSH */
3862/* cond 1101 0D10 1101 Vd-- 101X imm8 imm8 */
3863#define vfpinstr vpush
3864#define vfpinstr_inst vpush_inst
3865#define VFPLABEL_INST VPUSH_INST
3866#ifdef VFP_DECODE
3867{"vpush", 3, ARMVFP2, 23, 27, 0x1a, 16, 21, 0x2d, 9, 11, 0x5},
3868#endif
3869#ifdef VFP_DECODE_EXCLUSION
3870{"vpush", 0, ARMVFP2, 0},
3871#endif
3872#ifdef VFP_INTERPRETER_TABLE
3873INTERPRETER_TRANSLATE(vfpinstr),
3874#endif
3875#ifdef VFP_INTERPRETER_LABEL
3876&&VFPLABEL_INST,
3877#endif
3878#ifdef VFP_INTERPRETER_STRUCT
3879typedef struct _vpush_inst {
3880 unsigned int single;
3881 unsigned int d;
3882 unsigned int imm32;
3883 unsigned int regs;
3884} vfpinstr_inst;
3885#endif
3886#ifdef VFP_INTERPRETER_TRANS
3887ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3888{
3889 VFP_DEBUG_TRANSLATE;
3890
3891 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
3892 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3893
3894 inst_base->cond = BITS(inst, 28, 31);
3895 inst_base->idx = index;
3896 inst_base->br = NON_BRANCH;
3897 inst_base->load_r15 = 0;
3898
3899 inst_cream->single = BIT(inst, 8) == 0;
3900 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4);
3901 inst_cream->imm32 = BITS(inst, 0, 7)<<2;
3902 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
3903
3904 return inst_base;
3905}
3906#endif
3907#ifdef VFP_INTERPRETER_IMPL
3908VFPLABEL_INST:
3909{
3910 INC_ICOUNTER;
3911 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3912 CHECK_VFP_ENABLED;
3913
3914 int i;
3915
3916 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
3917
3918 DBG("VPUSH :\n");
3919
3920 addr = cpu->Reg[R13] - inst_cream->imm32;
3921
3922
3923 for (i = 0; i < inst_cream->regs; i++)
3924 {
3925 if (inst_cream->single)
3926 {
3927 fault = check_address_validity(cpu, addr, &phys_addr, 0);
3928 if (fault) goto MMU_EXCEPTION;
3929 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
3930 if (fault) goto MMU_EXCEPTION;
3931 DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
3932 addr += 4;
3933 }
3934 else
3935 {
3936 /* Careful of endianness, little by default */
3937 fault = check_address_validity(cpu, addr, &phys_addr, 0);
3938 if (fault) goto MMU_EXCEPTION;
3939 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
3940 if (fault) goto MMU_EXCEPTION;
3941
3942 fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
3943 if (fault) goto MMU_EXCEPTION;
3944 fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
3945 if (fault) goto MMU_EXCEPTION;
3946 DBG("\taddr[%x-%x] <= s[%d-%d]=[%x-%x]\n", addr+4, addr, (inst_cream->d+i)*2+1, (inst_cream->d+i)*2, cpu->ExtReg[(inst_cream->d+i)*2+1], cpu->ExtReg[(inst_cream->d+i)*2]);
3947 addr += 8;
3948 }
3949 }
3950 DBG("\tsp[%x]", cpu->Reg[R13]);
3951 cpu->Reg[R13] = cpu->Reg[R13] - inst_cream->imm32;
3952 DBG("=>[%x]\n", cpu->Reg[R13]);
3953
3954 }
3955 cpu->Reg[15] += GET_INST_SIZE(cpu);
3956 INC_PC(sizeof(vpush_inst));
3957 FETCH_INST;
3958 GOTO_NEXT_INST;
3959}
3960#endif
3961#ifdef VFP_STC_TRANS
3962if (P == 1 && U == 0 && W == 1 && Rn == 0xD)
3963{
3964 return VPUSH(state, type, instr, value);
3965}
3966#endif
3967#ifdef VFP_STC_IMPL
3968int VPUSH(ARMul_State * state, int type, ARMword instr, ARMword * value)
3969{
3970 static int i = 0;
3971 static int single_regs, add, wback, d, n, imm32, regs;
3972 if (type == ARMul_FIRST)
3973 {
3974 single_regs = BIT(8) == 0; /* Single precision */
3975 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
3976 imm32 = BITS(0,7)<<2; /* may not be used */
3977 regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FSTMX if regs is odd */
3978
3979 DBG("VPUSH :\n");
3980 DBG("\tsp[%x]", state->Reg[R13]);
3981 state->Reg[R13] = state->Reg[R13] - imm32;
3982 DBG("=>[%x]\n", state->Reg[R13]);
3983
3984 i = 0;
3985
3986 return ARMul_DONE;
3987 }
3988 else if (type == ARMul_DATA)
3989 {
3990 if (single_regs)
3991 {
3992 *value = state->ExtReg[d + i];
3993 DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d + i]);
3994 i++;
3995 if (i < regs)
3996 return ARMul_INC;
3997 else
3998 return ARMul_DONE;
3999 }
4000 else
4001 {
4002 /* FIXME Careful of endianness, may need to rework this */
4003 *value = state->ExtReg[d*2 + i];
4004 DBG("\taddr[?] <= s[%d]=[%x]\n", d*2 + i, state->ExtReg[d*2 + i]);
4005 i++;
4006 if (i < regs*2)
4007 return ARMul_INC;
4008 else
4009 return ARMul_DONE;
4010 }
4011 }
4012
4013 return -1;
4014}
4015#endif
4016#ifdef VFP_DYNCOM_TABLE
4017DYNCOM_FILL_ACTION(vfpinstr),
4018#endif
4019#ifdef VFP_DYNCOM_TAG
4020int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4021{
4022 int instr_size = INSTR_SIZE;
4023 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
4024 DBG("In %s, pc=0x%x, next_pc=0x%x\n", __FUNCTION__, pc, *next_pc);
4025 *tag |= TAG_NEW_BB;
4026 if(instr >> 28 != 0xe)
4027 *tag |= TAG_CONDITIONAL;
4028
4029 return instr_size;
4030}
4031#endif
4032#ifdef VFP_DYNCOM_TRANS
4033int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4034 int single = BIT(8) == 0;
4035 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4));
4036 int imm32 = BITS(0, 7)<<2;
4037 int regs = (single ? BITS(0, 7) : BITS(1, 7));
4038
4039 DBG("\t\tin %s \n", __FUNCTION__);
4040 Value* Addr = SUB(R(13), CONST(imm32));
4041 //if(single)
4042 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 0, cpu->dyncom_engine->bb_trap);
4043 //else
4044 // bb = arch_check_mm(cpu, bb, Addr, regs * 8, 0, cpu->dyncom_engine->bb_trap);
4045 //Value* phys_addr;
4046 int i;
4047 for (i = 0; i < regs; i++)
4048 {
4049 if (single)
4050 {
4051 //fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
4052 #if 0
4053 phys_addr = get_phys_addr(cpu, bb, Addr, 0);
4054 bb = cpu->dyncom_engine->bb;
4055 arch_write_memory(cpu, bb, phys_addr, RSPR(d + i), 32);
4056 #endif
4057 //memory_write(cpu, bb, Addr, RSPR(d + i), 32);
4058 memory_write(cpu, bb, Addr, IBITCAST32(FR32(d + i)), 32);
4059 bb = cpu->dyncom_engine->bb;
4060 Addr = ADD(Addr, CONST(4));
4061 }
4062 else
4063 {
4064 /* Careful of endianness, little by default */
4065 #if 0
4066 phys_addr = get_phys_addr(cpu, bb, Addr, 0);
4067 bb = cpu->dyncom_engine->bb;
4068 arch_write_memory(cpu, bb, phys_addr, RSPR((d + i) * 2), 32);
4069 #endif
4070 //memory_write(cpu, bb, Addr, RSPR((d + i) * 2), 32);
4071 memory_write(cpu, bb, Addr, IBITCAST32(FR32((d + i) * 2)), 32);
4072 bb = cpu->dyncom_engine->bb;
4073 #if 0
4074 phys_addr = get_phys_addr(cpu, bb, ADD(Addr, CONST(4)), 0);
4075 bb = cpu->dyncom_engine->bb;
4076 arch_write_memory(cpu, bb, phys_addr, RSPR((d + i) * 2 + 1), 32);
4077 #endif
4078 //memory_write(cpu, bb, ADD(Addr, CONST(4)), RSPR((d + i) * 2 + 1), 32);
4079 memory_write(cpu, bb, ADD(Addr, CONST(4)), IBITCAST32(FR32((d + i) * 2 + 1)), 32);
4080 bb = cpu->dyncom_engine->bb;
4081
4082 Addr = ADD(Addr, CONST(8));
4083 }
4084 }
4085 LET(13, SUB(R(13), CONST(imm32)));
4086
4087 return No_exp;
4088}
4089#endif
4090#undef vfpinstr
4091#undef vfpinstr_inst
4092#undef VFPLABEL_INST
4093
4094/* ----------------------------------------------------------------------- */
4095/* VSTM */
4096/* cond 110P UDW0 Rn-- Vd-- 101X imm8 imm8 */
4097#define vfpinstr vstm
4098#define vfpinstr_inst vstm_inst
4099#define VFPLABEL_INST VSTM_INST
4100#ifdef VFP_DECODE
4101{"vstm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 0, 9, 11, 0x5},
4102#endif
4103#ifdef VFP_DECODE_EXCLUSION
4104{"vstm", 0, ARMVFP2, 0},
4105#endif
4106#ifdef VFP_INTERPRETER_TABLE
4107INTERPRETER_TRANSLATE(vfpinstr),
4108#endif
4109#ifdef VFP_INTERPRETER_LABEL
4110&&VFPLABEL_INST,
4111#endif
4112#ifdef VFP_INTERPRETER_STRUCT
4113typedef struct _vstm_inst {
4114 unsigned int single;
4115 unsigned int add;
4116 unsigned int wback;
4117 unsigned int d;
4118 unsigned int n;
4119 unsigned int imm32;
4120 unsigned int regs;
4121} vfpinstr_inst;
4122#endif
4123#ifdef VFP_INTERPRETER_TRANS
4124ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4125{
4126 VFP_DEBUG_TRANSLATE;
4127
4128 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
4129 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
4130
4131 inst_base->cond = BITS(inst, 28, 31);
4132 inst_base->idx = index;
4133 inst_base->br = NON_BRANCH;
4134 inst_base->load_r15 = 0;
4135
4136 inst_cream->single = BIT(inst, 8) == 0;
4137 inst_cream->add = BIT(inst, 23);
4138 inst_cream->wback = BIT(inst, 21);
4139 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4);
4140 inst_cream->n = BITS(inst, 16, 19);
4141 inst_cream->imm32 = BITS(inst, 0, 7)<<2;
4142 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
4143
4144 return inst_base;
4145}
4146#endif
4147#ifdef VFP_INTERPRETER_IMPL
4148VFPLABEL_INST: /* encoding 1 */
4149{
4150 INC_ICOUNTER;
4151 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4152 CHECK_VFP_ENABLED;
4153
4154 int i;
4155
4156 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
4157
4158 addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32);
4159 DBG("VSTM : addr[%x]\n", addr);
4160
4161
4162 for (i = 0; i < inst_cream->regs; i++)
4163 {
4164 if (inst_cream->single)
4165 {
4166 fault = check_address_validity(cpu, addr, &phys_addr, 0);
4167 if (fault) goto MMU_EXCEPTION;
4168
4169 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
4170 if (fault) goto MMU_EXCEPTION;
4171 DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
4172 addr += 4;
4173 }
4174 else
4175 {
4176 /* Careful of endianness, little by default */
4177 fault = check_address_validity(cpu, addr, &phys_addr, 0);
4178 if (fault) goto MMU_EXCEPTION;
4179
4180 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
4181 if (fault) goto MMU_EXCEPTION;
4182
4183 fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
4184 if (fault) goto MMU_EXCEPTION;
4185
4186 fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
4187 if (fault) goto MMU_EXCEPTION;
4188 DBG("\taddr[%x-%x] <= s[%d-%d]=[%x-%x]\n", addr+4, addr, (inst_cream->d+i)*2+1, (inst_cream->d+i)*2, cpu->ExtReg[(inst_cream->d+i)*2+1], cpu->ExtReg[(inst_cream->d+i)*2]);
4189 addr += 8;
4190 }
4191 }
4192 if (inst_cream->wback){
4193 cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 :
4194 cpu->Reg[inst_cream->n] - inst_cream->imm32);
4195 DBG("\twback r%d[%x]\n", inst_cream->n, cpu->Reg[inst_cream->n]);
4196 }
4197
4198 }
4199 cpu->Reg[15] += 4;
4200 INC_PC(sizeof(vstm_inst));
4201
4202 FETCH_INST;
4203 GOTO_NEXT_INST;
4204}
4205#endif
4206#ifdef VFP_STC_TRANS
4207/* Should be the last operation of STC */
4208return VSTM(state, type, instr, value);
4209#endif
4210#ifdef VFP_STC_IMPL
4211int VSTM(ARMul_State * state, int type, ARMword instr, ARMword * value)
4212{
4213 static int i = 0;
4214 static int single_regs, add, wback, d, n, imm32, regs;
4215 if (type == ARMul_FIRST)
4216 {
4217 single_regs = BIT(8) == 0; /* Single precision */
4218 add = BIT(23); /* */
4219 wback = BIT(21); /* write-back */
4220 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
4221 n = BITS(16, 19); /* destination register */
4222 imm32 = BITS(0,7) * 4; /* may not be used */
4223 regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FSTMX if regs is odd */
4224
4225 DBG("VSTM :\n");
4226
4227 if (wback) {
4228 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
4229 DBG("\twback r%d[%x]\n", n, state->Reg[n]);
4230 }
4231
4232 i = 0;
4233
4234 return ARMul_DONE;
4235 }
4236 else if (type == ARMul_DATA)
4237 {
4238 if (single_regs)
4239 {
4240 *value = state->ExtReg[d + i];
4241 DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d + i]);
4242 i++;
4243 if (i < regs)
4244 return ARMul_INC;
4245 else
4246 return ARMul_DONE;
4247 }
4248 else
4249 {
4250 /* FIXME Careful of endianness, may need to rework this */
4251 *value = state->ExtReg[d*2 + i];
4252 DBG("\taddr[?] <= s[%d]=[%x]\n", d*2 + i, state->ExtReg[d*2 + i]);
4253 i++;
4254 if (i < regs*2)
4255 return ARMul_INC;
4256 else
4257 return ARMul_DONE;
4258 }
4259 }
4260
4261 return -1;
4262}
4263#endif
4264#ifdef VFP_DYNCOM_TABLE
4265DYNCOM_FILL_ACTION(vfpinstr),
4266#endif
4267#ifdef VFP_DYNCOM_TAG
4268int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4269{
4270 int instr_size = INSTR_SIZE;
4271 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
4272 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
4273 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
4274 DBG("In %s, pc=0x%x, next_pc=0x%x\n", __FUNCTION__, pc, *next_pc);
4275 *tag |= TAG_NEW_BB;
4276 if(instr >> 28 != 0xe)
4277 *tag |= TAG_CONDITIONAL;
4278
4279 return instr_size;
4280}
4281#endif
4282#ifdef VFP_DYNCOM_TRANS
4283int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4284 //arch_arm_undef(cpu, bb, instr);
4285 int single = BIT(8) == 0;
4286 int add = BIT(23);
4287 int wback = BIT(21);
4288 int d = single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4);
4289 int n = BITS(16, 19);
4290 int imm32 = BITS(0, 7)<<2;
4291 int regs = single ? BITS(0, 7) : BITS(1, 7);
4292
4293 Value* Addr = SELECT(CONST1(add), R(n), SUB(R(n), CONST(imm32)));
4294 DBG("VSTM \n");
4295 //if(single)
4296 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 0, cpu->dyncom_engine->bb_trap);
4297 //else
4298 // bb = arch_check_mm(cpu, bb, Addr, regs * 8, 0, cpu->dyncom_engine->bb_trap);
4299
4300 int i;
4301 Value* phys_addr;
4302 for (i = 0; i < regs; i++)
4303 {
4304 if (single)
4305 {
4306
4307 //fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
4308 /* if R(i) is R15? */
4309 #if 0
4310 phys_addr = get_phys_addr(cpu, bb, Addr, 0);
4311 bb = cpu->dyncom_engine->bb;
4312 arch_write_memory(cpu, bb, phys_addr, RSPR(d + i), 32);
4313 #endif
4314 //memory_write(cpu, bb, Addr, RSPR(d + i), 32);
4315 memory_write(cpu, bb, Addr, IBITCAST32(FR32(d + i)),32);
4316 bb = cpu->dyncom_engine->bb;
4317 //if (fault) goto MMU_EXCEPTION;
4318 //DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
4319 Addr = ADD(Addr, CONST(4));
4320 }
4321 else
4322 {
4323
4324 //fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
4325 #if 0
4326 phys_addr = get_phys_addr(cpu, bb, Addr, 0);
4327 bb = cpu->dyncom_engine->bb;
4328 arch_write_memory(cpu, bb, phys_addr, RSPR((d + i) * 2), 32);
4329 #endif
4330 //memory_write(cpu, bb, Addr, RSPR((d + i) * 2), 32);
4331 memory_write(cpu, bb, Addr, IBITCAST32(FR32((d + i) * 2)),32);
4332 bb = cpu->dyncom_engine->bb;
4333 //if (fault) goto MMU_EXCEPTION;
4334
4335 //fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
4336 #if 0
4337 phys_addr = get_phys_addr(cpu, bb, ADD(Addr, CONST(4)), 0);
4338 bb = cpu->dyncom_engine->bb;
4339 arch_write_memory(cpu, bb, phys_addr, RSPR((d + i) * 2 + 1), 32);
4340 #endif
4341 //memory_write(cpu, bb, ADD(Addr, CONST(4)), RSPR((d + i) * 2 + 1), 32);
4342 memory_write(cpu, bb, ADD(Addr, CONST(4)), IBITCAST32(FR32((d + i) * 2 + 1)), 32);
4343 bb = cpu->dyncom_engine->bb;
4344 //if (fault) goto MMU_EXCEPTION;
4345 //DBG("\taddr[%x-%x] <= s[%d-%d]=[%x-%x]\n", addr+4, addr, (inst_cream->d+i)*2+1, (inst_cream->d+i)*2, cpu->ExtReg[(inst_cream->d+i)*2+1], cpu->ExtReg[(inst_cream->d+i)*2]);
4346 //addr += 8;
4347 Addr = ADD(Addr, CONST(8));
4348 }
4349 }
4350 if (wback){
4351 //cpu->Reg[n] = (add ? cpu->Reg[n] + imm32 :
4352 // cpu->Reg[n] - imm32);
4353 LET(n, SELECT(CONST1(add), ADD(R(n), CONST(imm32)), SUB(R(n), CONST(imm32))));
4354 DBG("\twback r%d, add=%d, imm32=%d\n", n, add, imm32);
4355 }
4356 return No_exp;
4357}
4358#endif
4359#undef vfpinstr
4360#undef vfpinstr_inst
4361#undef VFPLABEL_INST
4362
4363/* ----------------------------------------------------------------------- */
4364/* VPOP */
4365/* cond 1100 1D11 1101 Vd-- 101X imm8 imm8 */
4366#define vfpinstr vpop
4367#define vfpinstr_inst vpop_inst
4368#define VFPLABEL_INST VPOP_INST
4369#ifdef VFP_DECODE
4370{"vpop", 3, ARMVFP2, 23, 27, 0x19, 16, 21, 0x3d, 9, 11, 0x5},
4371#endif
4372#ifdef VFP_DECODE_EXCLUSION
4373{"vpop", 0, ARMVFP2, 0},
4374#endif
4375#ifdef VFP_INTERPRETER_TABLE
4376INTERPRETER_TRANSLATE(vfpinstr),
4377#endif
4378#ifdef VFP_INTERPRETER_LABEL
4379&&VFPLABEL_INST,
4380#endif
4381#ifdef VFP_INTERPRETER_STRUCT
4382typedef struct _vpop_inst {
4383 unsigned int single;
4384 unsigned int d;
4385 unsigned int imm32;
4386 unsigned int regs;
4387} vfpinstr_inst;
4388#endif
4389#ifdef VFP_INTERPRETER_TRANS
4390ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4391{
4392 VFP_DEBUG_TRANSLATE;
4393
4394 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
4395 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
4396
4397 inst_base->cond = BITS(inst, 28, 31);
4398 inst_base->idx = index;
4399 inst_base->br = NON_BRANCH;
4400 inst_base->load_r15 = 0;
4401
4402 inst_cream->single = BIT(inst, 8) == 0;
4403 inst_cream->d = (inst_cream->single ? (BITS(inst, 12, 15)<<1)|BIT(inst, 22) : BITS(inst, 12, 15)|(BIT(inst, 22)<<4));
4404 inst_cream->imm32 = BITS(inst, 0, 7)<<2;
4405 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
4406
4407 return inst_base;
4408}
4409#endif
4410#ifdef VFP_INTERPRETER_IMPL
4411VFPLABEL_INST:
4412{
4413 INC_ICOUNTER;
4414 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4415 CHECK_VFP_ENABLED;
4416
4417 int i;
4418 unsigned int value1, value2;
4419
4420 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
4421
4422 DBG("VPOP :\n");
4423
4424 addr = cpu->Reg[R13];
4425
4426
4427 for (i = 0; i < inst_cream->regs; i++)
4428 {
4429 if (inst_cream->single)
4430 {
4431 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4432 if (fault) goto MMU_EXCEPTION;
4433
4434 fault = interpreter_read_memory(core, addr, phys_addr, value1, 32);
4435 if (fault) goto MMU_EXCEPTION;
4436 DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d+i, value1, addr);
4437 cpu->ExtReg[inst_cream->d+i] = value1;
4438 addr += 4;
4439 }
4440 else
4441 {
4442 /* Careful of endianness, little by default */
4443 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4444 if (fault) goto MMU_EXCEPTION;
4445
4446 fault = interpreter_read_memory(core, addr, phys_addr, value1, 32);
4447 if (fault) goto MMU_EXCEPTION;
4448
4449 fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
4450 if (fault) goto MMU_EXCEPTION;
4451
4452 fault = interpreter_read_memory(core, addr + 4, phys_addr, value2, 32);
4453 if (fault) goto MMU_EXCEPTION;
4454 DBG("\ts[%d-%d] <= [%x-%x] addr[%x-%x]\n", (inst_cream->d+i)*2+1, (inst_cream->d+i)*2, value2, value1, addr+4, addr);
4455 cpu->ExtReg[(inst_cream->d+i)*2] = value1;
4456 cpu->ExtReg[(inst_cream->d+i)*2 + 1] = value2;
4457 addr += 8;
4458 }
4459 }
4460 DBG("\tsp[%x]", cpu->Reg[R13]);
4461 cpu->Reg[R13] = cpu->Reg[R13] + inst_cream->imm32;
4462 DBG("=>[%x]\n", cpu->Reg[R13]);
4463
4464 }
4465 cpu->Reg[15] += GET_INST_SIZE(cpu);
4466 INC_PC(sizeof(vpop_inst));
4467 FETCH_INST;
4468 GOTO_NEXT_INST;
4469}
4470#endif
4471#ifdef VFP_LDC_TRANS
4472if (P == 0 && U == 1 && W == 1 && Rn == 0xD)
4473{
4474 return VPOP(state, type, instr, value);
4475}
4476#endif
4477#ifdef VFP_LDC_IMPL
4478int VPOP(ARMul_State * state, int type, ARMword instr, ARMword value)
4479{
4480 static int i = 0;
4481 static int single_regs, add, wback, d, n, imm32, regs;
4482 if (type == ARMul_FIRST)
4483 {
4484 single_regs = BIT(8) == 0; /* Single precision */
4485 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
4486 imm32 = BITS(0,7)<<2; /* may not be used */
4487 regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FLDMX if regs is odd */
4488
4489 DBG("VPOP :\n");
4490 DBG("\tsp[%x]", state->Reg[R13]);
4491 state->Reg[R13] = state->Reg[R13] + imm32;
4492 DBG("=>[%x]\n", state->Reg[R13]);
4493
4494 i = 0;
4495
4496 return ARMul_DONE;
4497 }
4498 else if (type == ARMul_TRANSFER)
4499 {
4500 return ARMul_DONE;
4501 }
4502 else if (type == ARMul_DATA)
4503 {
4504 if (single_regs)
4505 {
4506 state->ExtReg[d + i] = value;
4507 DBG("\ts%d <= [%x]\n", d + i, value);
4508 i++;
4509 if (i < regs)
4510 return ARMul_INC;
4511 else
4512 return ARMul_DONE;
4513 }
4514 else
4515 {
4516 /* FIXME Careful of endianness, may need to rework this */
4517 state->ExtReg[d*2 + i] = value;
4518 DBG("\ts%d <= [%x]\n", d*2 + i, value);
4519 i++;
4520 if (i < regs*2)
4521 return ARMul_INC;
4522 else
4523 return ARMul_DONE;
4524 }
4525 }
4526
4527 return -1;
4528}
4529#endif
4530#ifdef VFP_DYNCOM_TABLE
4531DYNCOM_FILL_ACTION(vfpinstr),
4532#endif
4533#ifdef VFP_DYNCOM_TAG
4534int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4535{
4536 int instr_size = INSTR_SIZE;
4537 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
4538 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
4539 /* Should check if PC is destination register */
4540 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
4541 DBG("In %s, pc=0x%x, next_pc=0x%x\n", __FUNCTION__, pc, *next_pc);
4542 *tag |= TAG_NEW_BB;
4543 if(instr >> 28 != 0xe)
4544 *tag |= TAG_CONDITIONAL;
4545
4546 return instr_size;
4547}
4548#endif
4549#ifdef VFP_DYNCOM_TRANS
4550int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4551 DBG("\t\tin %s instruction .\n", __FUNCTION__);
4552 //arch_arm_undef(cpu, bb, instr);
4553 int single = BIT(8) == 0;
4554 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4));
4555 int imm32 = BITS(0, 7)<<2;
4556 int regs = (single ? BITS(0, 7) : BITS(1, 7));
4557
4558 int i;
4559 unsigned int value1, value2;
4560
4561 DBG("VPOP :\n");
4562
4563 Value* Addr = R(13);
4564 Value* val;
4565 //if(single)
4566 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 1, cpu->dyncom_engine->bb_trap);
4567 //else
4568 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 1, cpu->dyncom_engine->bb_trap);
4569 //Value* phys_addr;
4570 for (i = 0; i < regs; i++)
4571 {
4572 if (single)
4573 {
4574 #if 0
4575 phys_addr = get_phys_addr(cpu, bb, Addr, 1);
4576 bb = cpu->dyncom_engine->bb;
4577 val = arch_read_memory(cpu,bb,phys_addr,0,32);
4578 #endif
4579 memory_read(cpu, bb, Addr, 0, 32);
4580 bb = cpu->dyncom_engine->bb;
4581 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
4582 LETFPS(d + i, FPBITCAST32(val));
4583 Addr = ADD(Addr, CONST(4));
4584 }
4585 else
4586 {
4587 /* Careful of endianness, little by default */
4588 #if 0
4589 phys_addr = get_phys_addr(cpu, bb, Addr, 1);
4590 bb = cpu->dyncom_engine->bb;
4591 val = arch_read_memory(cpu,bb,phys_addr,0,32);
4592 #endif
4593 memory_read(cpu, bb, Addr, 0, 32);
4594 bb = cpu->dyncom_engine->bb;
4595 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
4596 LETFPS((d + i) * 2, FPBITCAST32(val));
4597 #if 0
4598 phys_addr = get_phys_addr(cpu, bb, ADD(Addr, CONST(4)), 1);
4599 bb = cpu->dyncom_engine->bb;
4600 val = arch_read_memory(cpu,bb,phys_addr,0,32);
4601 #endif
4602 memory_read(cpu, bb, ADD(Addr, CONST(4)), 0, 32);
4603 bb = cpu->dyncom_engine->bb;
4604 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
4605 LETFPS((d + i) * 2 + 1, FPBITCAST32(val));
4606
4607 Addr = ADD(Addr, CONST(8));
4608 }
4609 }
4610 LET(13, ADD(R(13), CONST(imm32)));
4611 return No_exp;
4612}
4613#endif
4614#undef vfpinstr
4615#undef vfpinstr_inst
4616#undef VFPLABEL_INST
4617
4618/* ----------------------------------------------------------------------- */
4619/* VLDR */
4620/* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */
4621#define vfpinstr vldr
4622#define vfpinstr_inst vldr_inst
4623#define VFPLABEL_INST VLDR_INST
4624#ifdef VFP_DECODE
4625{"vldr", 3, ARMVFP2, 24, 27, 0xd, 20, 21, 0x1, 9, 11, 0x5},
4626#endif
4627#ifdef VFP_DECODE_EXCLUSION
4628{"vldr", 0, ARMVFP2, 0},
4629#endif
4630#ifdef VFP_INTERPRETER_TABLE
4631INTERPRETER_TRANSLATE(vfpinstr),
4632#endif
4633#ifdef VFP_INTERPRETER_LABEL
4634&&VFPLABEL_INST,
4635#endif
4636#ifdef VFP_INTERPRETER_STRUCT
4637typedef struct _vldr_inst {
4638 unsigned int single;
4639 unsigned int n;
4640 unsigned int d;
4641 unsigned int imm32;
4642 unsigned int add;
4643} vfpinstr_inst;
4644#endif
4645#ifdef VFP_INTERPRETER_TRANS
4646ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4647{
4648 VFP_DEBUG_TRANSLATE;
4649
4650 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
4651 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
4652
4653 inst_base->cond = BITS(inst, 28, 31);
4654 inst_base->idx = index;
4655 inst_base->br = NON_BRANCH;
4656 inst_base->load_r15 = 0;
4657
4658 inst_cream->single = BIT(inst, 8) == 0;
4659 inst_cream->add = BIT(inst, 23);
4660 inst_cream->imm32 = BITS(inst, 0,7) << 2;
4661 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4);
4662 inst_cream->n = BITS(inst, 16, 19);
4663
4664 return inst_base;
4665}
4666#endif
4667#ifdef VFP_INTERPRETER_IMPL
4668VFPLABEL_INST:
4669{
4670 INC_ICOUNTER;
4671 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4672 CHECK_VFP_ENABLED;
4673
4674 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
4675
4676 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]);
4677 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32);
4678 DBG("VLDR :\n", addr);
4679
4680
4681 if (inst_cream->single)
4682 {
4683 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4684 if (fault) goto MMU_EXCEPTION;
4685 fault = interpreter_read_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d], 32);
4686 if (fault) goto MMU_EXCEPTION;
4687 DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d, cpu->ExtReg[inst_cream->d], addr);
4688 }
4689 else
4690 {
4691 unsigned int word1, word2;
4692 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4693 if (fault) goto MMU_EXCEPTION;
4694 fault = interpreter_read_memory(core, addr, phys_addr, word1, 32);
4695 if (fault) goto MMU_EXCEPTION;
4696
4697 fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
4698 if (fault) goto MMU_EXCEPTION;
4699 fault = interpreter_read_memory(core, addr + 4, phys_addr, word2, 32);
4700 if (fault) goto MMU_EXCEPTION;
4701 /* Check endianness */
4702 cpu->ExtReg[inst_cream->d*2] = word1;
4703 cpu->ExtReg[inst_cream->d*2+1] = word2;
4704 DBG("\ts[%d-%d] <= [%x-%x] addr[%x-%x]\n", inst_cream->d*2+1, inst_cream->d*2, word2, word1, addr+4, addr);
4705 }
4706 }
4707 cpu->Reg[15] += GET_INST_SIZE(cpu);
4708 INC_PC(sizeof(vldr_inst));
4709 FETCH_INST;
4710 GOTO_NEXT_INST;
4711}
4712#endif
4713#ifdef VFP_LDC_TRANS
4714if (P == 1 && W == 0)
4715{
4716 return VLDR(state, type, instr, value);
4717}
4718#endif
4719#ifdef VFP_LDC_IMPL
4720int VLDR(ARMul_State * state, int type, ARMword instr, ARMword value)
4721{
4722 static int i = 0;
4723 static int single_reg, add, d, n, imm32, regs;
4724 if (type == ARMul_FIRST)
4725 {
4726 single_reg = BIT(8) == 0; /* Double precision */
4727 add = BIT(23); /* */
4728 imm32 = BITS(0,7)<<2; /* may not be used */
4729 d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
4730 n = BITS(16, 19); /* destination register */
4731
4732 DBG("VLDR :\n");
4733
4734 i = 0;
4735 regs = 1;
4736
4737 return ARMul_DONE;
4738 }
4739 else if (type == ARMul_TRANSFER)
4740 {
4741 return ARMul_DONE;
4742 }
4743 else if (type == ARMul_DATA)
4744 {
4745 if (single_reg)
4746 {
4747 state->ExtReg[d+i] = value;
4748 DBG("\ts%d <= [%x]\n", d+i, value);
4749 i++;
4750 if (i < regs)
4751 return ARMul_INC;
4752 else
4753 return ARMul_DONE;
4754 }
4755 else
4756 {
4757 /* FIXME Careful of endianness, may need to rework this */
4758 state->ExtReg[d*2+i] = value;
4759 DBG("\ts[%d] <= [%x]\n", d*2+i, value);
4760 i++;
4761 if (i < regs*2)
4762 return ARMul_INC;
4763 else
4764 return ARMul_DONE;
4765 }
4766 }
4767
4768 return -1;
4769}
4770#endif
4771#ifdef VFP_DYNCOM_TABLE
4772DYNCOM_FILL_ACTION(vfpinstr),
4773#endif
4774#ifdef VFP_DYNCOM_TAG
4775int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4776{
4777 int instr_size = INSTR_SIZE;
4778 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
4779 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
4780 /* Should check if PC is destination register */
4781 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
4782 DBG("In %s, pc=0x%x, next_pc=0x%x\n", __FUNCTION__, pc, *next_pc);
4783 *tag |= TAG_NEW_BB;
4784 if(instr >> 28 != 0xe)
4785 *tag |= TAG_CONDITIONAL;
4786
4787 return instr_size;
4788}
4789#endif
4790#ifdef VFP_DYNCOM_TRANS
4791int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4792 int single = BIT(8) == 0;
4793 int add = BIT(23);
4794 int wback = BIT(21);
4795 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4));
4796 int n = BITS(16, 19);
4797 int imm32 = BITS(0, 7)<<2;
4798 int regs = (single ? BITS(0, 7) : BITS(1, 7));
4799 Value* base = R(n);
4800 DBG("\t\tin %s .\n", __FUNCTION__);
4801 if(n == 15){
4802 base = ADD(AND(base, CONST(0xFFFFFFFC)), CONST(8));
4803 }
4804 Value* Addr = add ? (ADD(base, CONST(imm32))) : (SUB(base, CONST(imm32)));
4805 //if(single)
4806 // bb = arch_check_mm(cpu, bb, Addr, 4, 1, cpu->dyncom_engine->bb_trap);
4807 //else
4808 // bb = arch_check_mm(cpu, bb, Addr, 8, 1, cpu->dyncom_engine->bb_trap);
4809 //Value* phys_addr;
4810 Value* val;
4811 if(single){
4812 #if 0
4813 phys_addr = get_phys_addr(cpu, bb, Addr, 1);
4814 bb = cpu->dyncom_engine->bb;
4815 val = arch_read_memory(cpu,bb,phys_addr,0,32);
4816 #endif
4817 memory_read(cpu, bb, Addr, 0, 32);
4818 bb = cpu->dyncom_engine->bb;
4819 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
4820 //LETS(d, val);
4821 LETFPS(d,FPBITCAST32(val));
4822 }
4823 else{
4824 #if 0
4825 phys_addr = get_phys_addr(cpu, bb, Addr, 1);
4826 bb = cpu->dyncom_engine->bb;
4827 val = arch_read_memory(cpu,bb,phys_addr,0,32);
4828 #endif
4829 memory_read(cpu, bb, Addr, 0, 32);
4830 bb = cpu->dyncom_engine->bb;
4831 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
4832 //LETS(d * 2, val);
4833 LETFPS(d * 2,FPBITCAST32(val));
4834 #if 0
4835 phys_addr = get_phys_addr(cpu, bb, ADD(Addr, CONST(4)), 1);
4836 bb = cpu->dyncom_engine->bb;
4837 val = arch_read_memory(cpu,bb,phys_addr,0,32);
4838 #endif
4839 memory_read(cpu, bb, ADD(Addr, CONST(4)), 0,32);
4840 bb = cpu->dyncom_engine->bb;
4841 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
4842 //LETS(d * 2 + 1, val);
4843 LETFPS( d * 2 + 1,FPBITCAST32(val));
4844 }
4845
4846 return No_exp;
4847}
4848#endif
4849#undef vfpinstr
4850#undef vfpinstr_inst
4851#undef VFPLABEL_INST
4852
4853/* ----------------------------------------------------------------------- */
4854/* VLDM */
4855/* cond 110P UDW1 Rn-- Vd-- 101X imm8 imm8 */
4856#define vfpinstr vldm
4857#define vfpinstr_inst vldm_inst
4858#define VFPLABEL_INST VLDM_INST
4859#ifdef VFP_DECODE
4860{"vldm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 1, 9, 11, 0x5},
4861#endif
4862#ifdef VFP_DECODE_EXCLUSION
4863{"vldm", 0, ARMVFP2, 0},
4864#endif
4865#ifdef VFP_INTERPRETER_TABLE
4866INTERPRETER_TRANSLATE(vfpinstr),
4867#endif
4868#ifdef VFP_INTERPRETER_LABEL
4869&&VFPLABEL_INST,
4870#endif
4871#ifdef VFP_INTERPRETER_STRUCT
4872typedef struct _vldm_inst {
4873 unsigned int single;
4874 unsigned int add;
4875 unsigned int wback;
4876 unsigned int d;
4877 unsigned int n;
4878 unsigned int imm32;
4879 unsigned int regs;
4880} vfpinstr_inst;
4881#endif
4882#ifdef VFP_INTERPRETER_TRANS
4883ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4884{
4885 VFP_DEBUG_TRANSLATE;
4886
4887 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst));
4888 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
4889
4890 inst_base->cond = BITS(inst, 28, 31);
4891 inst_base->idx = index;
4892 inst_base->br = NON_BRANCH;
4893 inst_base->load_r15 = 0;
4894
4895 inst_cream->single = BIT(inst, 8) == 0;
4896 inst_cream->add = BIT(inst, 23);
4897 inst_cream->wback = BIT(inst, 21);
4898 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4);
4899 inst_cream->n = BITS(inst, 16, 19);
4900 inst_cream->imm32 = BITS(inst, 0, 7)<<2;
4901 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
4902
4903 return inst_base;
4904}
4905#endif
4906#ifdef VFP_INTERPRETER_IMPL
4907VFPLABEL_INST:
4908{
4909 INC_ICOUNTER;
4910 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4911 CHECK_VFP_ENABLED;
4912
4913 int i;
4914
4915 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component;
4916
4917 addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32);
4918 DBG("VLDM : addr[%x]\n", addr);
4919
4920 for (i = 0; i < inst_cream->regs; i++)
4921 {
4922 if (inst_cream->single)
4923 {
4924 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4925 if (fault) goto MMU_EXCEPTION;
4926 fault = interpreter_read_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
4927 if (fault) goto MMU_EXCEPTION;
4928 DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d+i, cpu->ExtReg[inst_cream->d+i], addr);
4929 addr += 4;
4930 }
4931 else
4932 {
4933 /* Careful of endianness, little by default */
4934 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4935 if (fault) goto MMU_EXCEPTION;
4936 fault = interpreter_read_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
4937 if (fault) goto MMU_EXCEPTION;
4938
4939 fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
4940 if (fault) goto MMU_EXCEPTION;
4941 fault = interpreter_read_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
4942 if (fault) goto MMU_EXCEPTION;
4943 DBG("\ts[%d-%d] <= [%x-%x] addr[%x-%x]\n", (inst_cream->d+i)*2+1, (inst_cream->d+i)*2, cpu->ExtReg[(inst_cream->d+i)*2+1], cpu->ExtReg[(inst_cream->d+i)*2], addr+4, addr);
4944 addr += 8;
4945 }
4946 }
4947 if (inst_cream->wback){
4948 cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 :
4949 cpu->Reg[inst_cream->n] - inst_cream->imm32);
4950 DBG("\twback r%d[%x]\n", inst_cream->n, cpu->Reg[inst_cream->n]);
4951 }
4952
4953 }
4954 cpu->Reg[15] += GET_INST_SIZE(cpu);
4955 INC_PC(sizeof(vfpinstr_inst));
4956 FETCH_INST;
4957 GOTO_NEXT_INST;
4958}
4959#endif
4960#ifdef VFP_LDC_TRANS
4961/* Should be the last operation of LDC */
4962return VLDM(state, type, instr, value);
4963#endif
4964#ifdef VFP_LDC_IMPL
4965int VLDM(ARMul_State * state, int type, ARMword instr, ARMword value)
4966{
4967 static int i = 0;
4968 static int single_regs, add, wback, d, n, imm32, regs;
4969 if (type == ARMul_FIRST)
4970 {
4971 single_regs = BIT(8) == 0; /* Single precision */
4972 add = BIT(23); /* */
4973 wback = BIT(21); /* write-back */
4974 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
4975 n = BITS(16, 19); /* destination register */
4976 imm32 = BITS(0,7) * 4; /* may not be used */
4977 regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FLDMX if regs is odd */
4978
4979 DBG("VLDM :\n");
4980
4981 if (wback) {
4982 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
4983 DBG("\twback r%d[%x]\n", n, state->Reg[n]);
4984 }
4985
4986 i = 0;
4987
4988 return ARMul_DONE;
4989 }
4990 else if (type == ARMul_DATA)
4991 {
4992 if (single_regs)
4993 {
4994 state->ExtReg[d + i] = value;
4995 DBG("\ts%d <= [%x] addr[?]\n", d+i, state->ExtReg[d + i]);
4996 i++;
4997 if (i < regs)
4998 return ARMul_INC;
4999 else
5000 return ARMul_DONE;
5001 }
5002 else
5003 {
5004 /* FIXME Careful of endianness, may need to rework this */
5005 state->ExtReg[d*2 + i] = value;
5006 DBG("\ts[%d] <= [%x] addr[?]\n", d*2 + i, state->ExtReg[d*2 + i]);
5007 i++;
5008 if (i < regs*2)
5009 return ARMul_INC;
5010 else
5011 return ARMul_DONE;
5012 }
5013 }
5014
5015 return -1;
5016}
5017#endif
5018#ifdef VFP_DYNCOM_TABLE
5019DYNCOM_FILL_ACTION(vfpinstr),
5020#endif
5021#ifdef VFP_DYNCOM_TAG
5022int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
5023{
5024 int instr_size = INSTR_SIZE;
5025 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
5026 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
5027 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
5028 DBG("In %s, pc=0x%x, next_pc=0x%x\n", __FUNCTION__, pc, *next_pc);
5029 *tag |= TAG_NEW_BB;
5030 if(instr >> 28 != 0xe)
5031 *tag |= TAG_CONDITIONAL;
5032
5033 return instr_size;
5034}
5035#endif
5036#ifdef VFP_DYNCOM_TRANS
5037int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
5038 int single = BIT(8) == 0;
5039 int add = BIT(23);
5040 int wback = BIT(21);
5041 int d = single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|BIT(22)<<4;
5042 int n = BITS(16, 19);
5043 int imm32 = BITS(0, 7)<<2;
5044 int regs = single ? BITS(0, 7) : BITS(1, 7);
5045
5046 Value* Addr = SELECT(CONST1(add), R(n), SUB(R(n), CONST(imm32)));
5047 //if(single)
5048 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 1, cpu->dyncom_engine->bb_trap);
5049 //else
5050 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 1, cpu->dyncom_engine->bb_trap);
5051
5052 DBG("VLDM \n");
5053 int i;
5054 //Value* phys_addr;
5055 Value* val;
5056 for (i = 0; i < regs; i++)
5057 {
5058 if (single)
5059 {
5060
5061 //fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
5062 /* if R(i) is R15? */
5063 #if 0
5064 phys_addr = get_phys_addr(cpu, bb, Addr, 1);
5065 bb = cpu->dyncom_engine->bb;
5066 val = arch_read_memory(cpu,bb,phys_addr,0,32);
5067 #endif
5068 memory_read(cpu, bb, Addr, 0, 32);
5069 bb = cpu->dyncom_engine->bb;
5070 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
5071 //LETS(d + i, val);
5072 LETFPS(d + i, FPBITCAST32(val));
5073 //if (fault) goto MMU_EXCEPTION;
5074 //DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
5075 Addr = ADD(Addr, CONST(4));
5076 }
5077 else
5078 {
5079 #if 0
5080 phys_addr = get_phys_addr(cpu, bb, Addr, 1);
5081 bb = cpu->dyncom_engine->bb;
5082 val = arch_read_memory(cpu,bb,phys_addr,0,32);
5083 #endif
5084 memory_read(cpu, bb, Addr, 0, 32);
5085 bb = cpu->dyncom_engine->bb;
5086 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
5087 LETFPS((d + i) * 2, FPBITCAST32(val));
5088 #if 0
5089 phys_addr = get_phys_addr(cpu, bb, ADD(Addr, CONST(4)), 1);
5090 bb = cpu->dyncom_engine->bb;
5091 val = arch_read_memory(cpu,bb,phys_addr,0,32);
5092 #endif
5093 memory_read(cpu, bb, Addr, 0, 32);
5094 bb = cpu->dyncom_engine->bb;
5095 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
5096 LETFPS((d + i) * 2 + 1, FPBITCAST32(val));
5097
5098 //fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
5099 //DBG("\taddr[%x-%x] <= s[%d-%d]=[%x-%x]\n", addr+4, addr, (inst_cream->d+i)*2+1, (inst_cream->d+i)*2, cpu->ExtReg[(inst_cream->d+i)*2+1], cpu->ExtReg[(inst_cream->d+i)*2]);
5100 //addr += 8;
5101 Addr = ADD(Addr, CONST(8));
5102 }
5103 }
5104 if (wback){
5105 //cpu->Reg[n] = (add ? cpu->Reg[n] + imm32 :
5106 // cpu->Reg[n] - imm32);
5107 LET(n, SELECT(CONST1(add), ADD(R(n), CONST(imm32)), SUB(R(n), CONST(imm32))));
5108 DBG("\twback r%d, add=%d, imm32=%d\n", n, add, imm32);
5109 }
5110 return No_exp;
5111}
5112#endif
5113#undef vfpinstr
5114#undef vfpinstr_inst
5115#undef VFPLABEL_INST
5116
5117#define VFP_DEBUG_TRANSLATE DBG("in func %s, %x\n", __FUNCTION__, inst);
5118#define VFP_DEBUG_UNIMPLEMENTED(x) printf("in func %s, " #x " unimplemented\n", __FUNCTION__); exit(-1);
5119#define VFP_DEBUG_UNTESTED(x) printf("in func %s, " #x " untested\n", __FUNCTION__);
5120
5121#define CHECK_VFP_ENABLED
5122
5123#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]); //if (ret == -1) {printf("VFP CDP FAILURE %x\n", inst_cream->instr); exit(-1);}
diff --git a/src/core/arm/interpreter/vfp/vfpsingle.cpp b/src/core/arm/interpreter/vfp/vfpsingle.cpp
new file mode 100644
index 000000000..24c0ded2b
--- /dev/null
+++ b/src/core/arm/interpreter/vfp/vfpsingle.cpp
@@ -0,0 +1,1277 @@
1/*
2 vfp/vfpsingle.c - ARM VFPv3 emulation unit - SoftFloat single instruction
3 Copyright (C) 2003 Skyeye Develop Group
4 for help please send mail to <skyeye-developer@lists.gro.clinux.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21/*
22 * This code is derived in part from :
23 * - Android kernel
24 * - John R. Housers softfloat library, which
25 * carries the following notice:
26 *
27 * ===========================================================================
28 * This C source file is part of the SoftFloat IEC/IEEE Floating-point
29 * Arithmetic Package, Release 2.
30 *
31 * Written by John R. Hauser. This work was made possible in part by the
32 * International Computer Science Institute, located at Suite 600, 1947 Center
33 * Street, Berkeley, California 94704. Funding was partially provided by the
34 * National Science Foundation under grant MIP-9311980. The original version
35 * of this code was written as part of a project to build a fixed-point vector
36 * processor in collaboration with the University of California at Berkeley,
37 * overseen by Profs. Nelson Morgan and John Wawrzynek. More information
38 * is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
39 * arithmetic/softfloat.html'.
40 *
41 * THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
42 * has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
43 * TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
44 * PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
45 * AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
46 *
47 * Derivative works are acceptable, even for commercial purposes, so long as
48 * (1) they include prominent notice that the work is derivative, and (2) they
49 * include prominent notice akin to these three paragraphs for those parts of
50 * this code that are retained.
51 * ===========================================================================
52 */
53
54#include "vfp_helper.h"
55#include "asm_vfp.h"
56
57static struct vfp_single vfp_single_default_qnan = {
58 //.exponent = 255,
59 //.sign = 0,
60 //.significand = VFP_SINGLE_SIGNIFICAND_QNAN,
61};
62
63static void vfp_single_dump(const char *str, struct vfp_single *s)
64{
65 pr_debug("VFP: %s: sign=%d exponent=%d significand=%08x\n",
66 str, s->sign != 0, s->exponent, s->significand);
67}
68
69static void vfp_single_normalise_denormal(struct vfp_single *vs)
70{
71 int bits = 31 - fls(vs->significand);
72
73 vfp_single_dump("normalise_denormal: in", vs);
74
75 if (bits) {
76 vs->exponent -= bits - 1;
77 vs->significand <<= bits;
78 }
79
80 vfp_single_dump("normalise_denormal: out", vs);
81}
82
83
84u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func)
85{
86 u32 significand, incr, rmode;
87 int exponent, shift, underflow;
88
89 vfp_single_dump("pack: in", vs);
90
91 /*
92 * Infinities and NaNs are a special case.
93 */
94 if (vs->exponent == 255 && (vs->significand == 0 || exceptions))
95 goto pack;
96
97 /*
98 * Special-case zero.
99 */
100 if (vs->significand == 0) {
101 vs->exponent = 0;
102 goto pack;
103 }
104
105 exponent = vs->exponent;
106 significand = vs->significand;
107
108 /*
109 * Normalise first. Note that we shift the significand up to
110 * bit 31, so we have VFP_SINGLE_LOW_BITS + 1 below the least
111 * significant bit.
112 */
113 shift = 32 - fls(significand);
114 if (shift < 32 && shift) {
115 exponent -= shift;
116 significand <<= shift;
117 }
118
119#if 1
120 vs->exponent = exponent;
121 vs->significand = significand;
122 vfp_single_dump("pack: normalised", vs);
123#endif
124
125 /*
126 * Tiny number?
127 */
128 underflow = exponent < 0;
129 if (underflow) {
130 significand = vfp_shiftright32jamming(significand, -exponent);
131 exponent = 0;
132#if 1
133 vs->exponent = exponent;
134 vs->significand = significand;
135 vfp_single_dump("pack: tiny number", vs);
136#endif
137 if (!(significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1)))
138 underflow = 0;
139 }
140
141 /*
142 * Select rounding increment.
143 */
144 incr = 0;
145 rmode = fpscr & FPSCR_RMODE_MASK;
146
147 if (rmode == FPSCR_ROUND_NEAREST) {
148 incr = 1 << VFP_SINGLE_LOW_BITS;
149 if ((significand & (1 << (VFP_SINGLE_LOW_BITS + 1))) == 0)
150 incr -= 1;
151 } else if (rmode == FPSCR_ROUND_TOZERO) {
152 incr = 0;
153 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vs->sign != 0))
154 incr = (1 << (VFP_SINGLE_LOW_BITS + 1)) - 1;
155
156 pr_debug("VFP: rounding increment = 0x%08x\n", incr);
157
158 /*
159 * Is our rounding going to overflow?
160 */
161 if ((significand + incr) < significand) {
162 exponent += 1;
163 significand = (significand >> 1) | (significand & 1);
164 incr >>= 1;
165#if 1
166 vs->exponent = exponent;
167 vs->significand = significand;
168 vfp_single_dump("pack: overflow", vs);
169#endif
170 }
171
172 /*
173 * If any of the low bits (which will be shifted out of the
174 * number) are non-zero, the result is inexact.
175 */
176 if (significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1))
177 exceptions |= FPSCR_IXC;
178
179 /*
180 * Do our rounding.
181 */
182 significand += incr;
183
184 /*
185 * Infinity?
186 */
187 if (exponent >= 254) {
188 exceptions |= FPSCR_OFC | FPSCR_IXC;
189 if (incr == 0) {
190 vs->exponent = 253;
191 vs->significand = 0x7fffffff;
192 } else {
193 vs->exponent = 255; /* infinity */
194 vs->significand = 0;
195 }
196 } else {
197 if (significand >> (VFP_SINGLE_LOW_BITS + 1) == 0)
198 exponent = 0;
199 if (exponent || significand > 0x80000000)
200 underflow = 0;
201 if (underflow)
202 exceptions |= FPSCR_UFC;
203 vs->exponent = exponent;
204 vs->significand = significand >> 1;
205 }
206
207 pack:
208 vfp_single_dump("pack: final", vs);
209 {
210 s32 d = vfp_single_pack(vs);
211#if 1
212 pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func,
213 sd, d, exceptions);
214#endif
215 vfp_put_float(state, d, sd);
216 }
217
218 return exceptions;
219}
220
221/*
222 * Propagate the NaN, setting exceptions if it is signalling.
223 * 'n' is always a NaN. 'm' may be a number, NaN or infinity.
224 */
225static u32
226vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn,
227 struct vfp_single *vsm, u32 fpscr)
228{
229 struct vfp_single *nan;
230 int tn, tm = 0;
231
232 tn = vfp_single_type(vsn);
233
234 if (vsm)
235 tm = vfp_single_type(vsm);
236
237 if (fpscr & FPSCR_DEFAULT_NAN)
238 /*
239 * Default NaN mode - always returns a quiet NaN
240 */
241 nan = &vfp_single_default_qnan;
242 else {
243 /*
244 * Contemporary mode - select the first signalling
245 * NAN, or if neither are signalling, the first
246 * quiet NAN.
247 */
248 if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN))
249 nan = vsn;
250 else
251 nan = vsm;
252 /*
253 * Make the NaN quiet.
254 */
255 nan->significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
256 }
257
258 *vsd = *nan;
259
260 /*
261 * If one was a signalling NAN, raise invalid operation.
262 */
263 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG;
264}
265
266
267/*
268 * Extended operations
269 */
270static u32 vfp_single_fabs(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
271{
272 vfp_put_float(state, vfp_single_packed_abs(m), sd);
273 return 0;
274}
275
276static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
277{
278 vfp_put_float(state, m, sd);
279 return 0;
280}
281
282static u32 vfp_single_fneg(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
283{
284 vfp_put_float(state, vfp_single_packed_negate(m), sd);
285 return 0;
286}
287
288static const u16 sqrt_oddadjust[] = {
289 0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0,
290 0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67
291};
292
293static const u16 sqrt_evenadjust[] = {
294 0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e,
295 0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002
296};
297
298u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand)
299{
300 int index;
301 u32 z, a;
302
303 if ((significand & 0xc0000000) != 0x40000000) {
304 pr_debug("VFP: estimate_sqrt: invalid significand\n");
305 }
306
307 a = significand << 1;
308 index = (a >> 27) & 15;
309 if (exponent & 1) {
310 z = 0x4000 + (a >> 17) - sqrt_oddadjust[index];
311 z = ((a / z) << 14) + (z << 15);
312 a >>= 1;
313 } else {
314 z = 0x8000 + (a >> 17) - sqrt_evenadjust[index];
315 z = a / z + z;
316 z = (z >= 0x20000) ? 0xffff8000 : (z << 15);
317 if (z <= a)
318 return (s32)a >> 1;
319 }
320 {
321 u64 v = (u64)a << 31;
322 do_div(v, z);
323 return v + (z >> 1);
324 }
325}
326
327static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
328{
329 struct vfp_single vsm, vsd;
330 int ret, tm;
331
332 vfp_single_unpack(&vsm, m);
333 tm = vfp_single_type(&vsm);
334 if (tm & (VFP_NAN|VFP_INFINITY)) {
335 struct vfp_single *vsp = &vsd;
336
337 if (tm & VFP_NAN)
338 ret = vfp_propagate_nan(vsp, &vsm, NULL, fpscr);
339 else if (vsm.sign == 0) {
340 sqrt_copy:
341 vsp = &vsm;
342 ret = 0;
343 } else {
344 sqrt_invalid:
345 vsp = &vfp_single_default_qnan;
346 ret = FPSCR_IOC;
347 }
348 vfp_put_float(state, vfp_single_pack(vsp), sd);
349 return ret;
350 }
351
352 /*
353 * sqrt(+/- 0) == +/- 0
354 */
355 if (tm & VFP_ZERO)
356 goto sqrt_copy;
357
358 /*
359 * Normalise a denormalised number
360 */
361 if (tm & VFP_DENORMAL)
362 vfp_single_normalise_denormal(&vsm);
363
364 /*
365 * sqrt(<0) = invalid
366 */
367 if (vsm.sign)
368 goto sqrt_invalid;
369
370 vfp_single_dump("sqrt", &vsm);
371
372 /*
373 * Estimate the square root.
374 */
375 vsd.sign = 0;
376 vsd.exponent = ((vsm.exponent - 127) >> 1) + 127;
377 vsd.significand = vfp_estimate_sqrt_significand(vsm.exponent, vsm.significand) + 2;
378
379 vfp_single_dump("sqrt estimate", &vsd);
380
381 /*
382 * And now adjust.
383 */
384 if ((vsd.significand & VFP_SINGLE_LOW_BITS_MASK) <= 5) {
385 if (vsd.significand < 2) {
386 vsd.significand = 0xffffffff;
387 } else {
388 u64 term;
389 s64 rem;
390 vsm.significand <<= !(vsm.exponent & 1);
391 term = (u64)vsd.significand * vsd.significand;
392 rem = ((u64)vsm.significand << 32) - term;
393
394 pr_debug("VFP: term=%016llx rem=%016llx\n", term, rem);
395
396 while (rem < 0) {
397 vsd.significand -= 1;
398 rem += ((u64)vsd.significand << 1) | 1;
399 }
400 vsd.significand |= rem != 0;
401 }
402 }
403 vsd.significand = vfp_shiftright32jamming(vsd.significand, 1);
404
405 return vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fsqrt");
406}
407
408/*
409 * Equal := ZC
410 * Less than := N
411 * Greater than := C
412 * Unordered := CV
413 */
414static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u32 fpscr)
415{
416 s32 d;
417 u32 ret = 0;
418
419 d = vfp_get_float(state, sd);
420 if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) {
421 ret |= FPSCR_C | FPSCR_V;
422 if (signal_on_qnan || !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
423 /*
424 * Signalling NaN, or signalling on quiet NaN
425 */
426 ret |= FPSCR_IOC;
427 }
428
429 if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) {
430 ret |= FPSCR_C | FPSCR_V;
431 if (signal_on_qnan || !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
432 /*
433 * Signalling NaN, or signalling on quiet NaN
434 */
435 ret |= FPSCR_IOC;
436 }
437
438 if (ret == 0) {
439 if (d == m || vfp_single_packed_abs(d | m) == 0) {
440 /*
441 * equal
442 */
443 ret |= FPSCR_Z | FPSCR_C;
444 } else if (vfp_single_packed_sign(d ^ m)) {
445 /*
446 * different signs
447 */
448 if (vfp_single_packed_sign(d))
449 /*
450 * d is negative, so d < m
451 */
452 ret |= FPSCR_N;
453 else
454 /*
455 * d is positive, so d > m
456 */
457 ret |= FPSCR_C;
458 } else if ((vfp_single_packed_sign(d) != 0) ^ (d < m)) {
459 /*
460 * d < m
461 */
462 ret |= FPSCR_N;
463 } else if ((vfp_single_packed_sign(d) != 0) ^ (d > m)) {
464 /*
465 * d > m
466 */
467 ret |= FPSCR_C;
468 }
469 }
470 return ret;
471}
472
473static u32 vfp_single_fcmp(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
474{
475 return vfp_compare(state, sd, 0, m, fpscr);
476}
477
478static u32 vfp_single_fcmpe(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
479{
480 return vfp_compare(state, sd, 1, m, fpscr);
481}
482
483static u32 vfp_single_fcmpz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
484{
485 return vfp_compare(state, sd, 0, 0, fpscr);
486}
487
488static u32 vfp_single_fcmpez(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
489{
490 return vfp_compare(state, sd, 1, 0, fpscr);
491}
492
493static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr)
494{
495 struct vfp_single vsm;
496 struct vfp_double vdd;
497 int tm;
498 u32 exceptions = 0;
499
500 vfp_single_unpack(&vsm, m);
501
502 tm = vfp_single_type(&vsm);
503
504 /*
505 * If we have a signalling NaN, signal invalid operation.
506 */
507 if (tm == VFP_SNAN)
508 exceptions = FPSCR_IOC;
509
510 if (tm & VFP_DENORMAL)
511 vfp_single_normalise_denormal(&vsm);
512
513 vdd.sign = vsm.sign;
514 vdd.significand = (u64)vsm.significand << 32;
515
516 /*
517 * If we have an infinity or NaN, the exponent must be 2047.
518 */
519 if (tm & (VFP_INFINITY|VFP_NAN)) {
520 vdd.exponent = 2047;
521 if (tm == VFP_QNAN)
522 vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
523 goto pack_nan;
524 } else if (tm & VFP_ZERO)
525 vdd.exponent = 0;
526 else
527 vdd.exponent = vsm.exponent + (1023 - 127);
528
529 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fcvtd");
530
531 pack_nan:
532 vfp_put_double(state, vfp_double_pack(&vdd), dd);
533 return exceptions;
534}
535
536static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
537{
538 struct vfp_single vs;
539
540 vs.sign = 0;
541 vs.exponent = 127 + 31 - 1;
542 vs.significand = (u32)m;
543
544 return vfp_single_normaliseround(state, sd, &vs, fpscr, 0, "fuito");
545}
546
547static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
548{
549 struct vfp_single vs;
550
551 vs.sign = (m & 0x80000000) >> 16;
552 vs.exponent = 127 + 31 - 1;
553 vs.significand = vs.sign ? -m : m;
554
555 return vfp_single_normaliseround(state, sd, &vs, fpscr, 0, "fsito");
556}
557
558static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
559{
560 struct vfp_single vsm;
561 u32 d, exceptions = 0;
562 int rmode = fpscr & FPSCR_RMODE_MASK;
563 int tm;
564
565 vfp_single_unpack(&vsm, m);
566 vfp_single_dump("VSM", &vsm);
567
568 /*
569 * Do we have a denormalised number?
570 */
571 tm = vfp_single_type(&vsm);
572 if (tm & VFP_DENORMAL)
573 exceptions |= FPSCR_IDC;
574
575 if (tm & VFP_NAN)
576 vsm.sign = 0;
577
578 if (vsm.exponent >= 127 + 32) {
579 d = vsm.sign ? 0 : 0xffffffff;
580 exceptions = FPSCR_IOC;
581 } else if (vsm.exponent >= 127 - 1) {
582 int shift = 127 + 31 - vsm.exponent;
583 u32 rem, incr = 0;
584
585 /*
586 * 2^0 <= m < 2^32-2^8
587 */
588 d = (vsm.significand << 1) >> shift;
589 rem = vsm.significand << (33 - shift);
590
591 if (rmode == FPSCR_ROUND_NEAREST) {
592 incr = 0x80000000;
593 if ((d & 1) == 0)
594 incr -= 1;
595 } else if (rmode == FPSCR_ROUND_TOZERO) {
596 incr = 0;
597 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) {
598 incr = ~0;
599 }
600
601 if ((rem + incr) < rem) {
602 if (d < 0xffffffff)
603 d += 1;
604 else
605 exceptions |= FPSCR_IOC;
606 }
607
608 if (d && vsm.sign) {
609 d = 0;
610 exceptions |= FPSCR_IOC;
611 } else if (rem)
612 exceptions |= FPSCR_IXC;
613 } else {
614 d = 0;
615 if (vsm.exponent | vsm.significand) {
616 exceptions |= FPSCR_IXC;
617 if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0)
618 d = 1;
619 else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) {
620 d = 0;
621 exceptions |= FPSCR_IOC;
622 }
623 }
624 }
625
626 pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
627
628 vfp_put_float(state, d, sd);
629
630 return exceptions;
631}
632
633static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
634{
635 return vfp_single_ftoui(state, sd, unused, m, FPSCR_ROUND_TOZERO);
636}
637
638static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
639{
640 struct vfp_single vsm;
641 u32 d, exceptions = 0;
642 int rmode = fpscr & FPSCR_RMODE_MASK;
643 int tm;
644
645 vfp_single_unpack(&vsm, m);
646 vfp_single_dump("VSM", &vsm);
647
648 /*
649 * Do we have a denormalised number?
650 */
651 tm = vfp_single_type(&vsm);
652 if (vfp_single_type(&vsm) & VFP_DENORMAL)
653 exceptions |= FPSCR_IDC;
654
655 if (tm & VFP_NAN) {
656 d = 0;
657 exceptions |= FPSCR_IOC;
658 } else if (vsm.exponent >= 127 + 32) {
659 /*
660 * m >= 2^31-2^7: invalid
661 */
662 d = 0x7fffffff;
663 if (vsm.sign)
664 d = ~d;
665 exceptions |= FPSCR_IOC;
666 } else if (vsm.exponent >= 127 - 1) {
667 int shift = 127 + 31 - vsm.exponent;
668 u32 rem, incr = 0;
669
670 /* 2^0 <= m <= 2^31-2^7 */
671 d = (vsm.significand << 1) >> shift;
672 rem = vsm.significand << (33 - shift);
673
674 if (rmode == FPSCR_ROUND_NEAREST) {
675 incr = 0x80000000;
676 if ((d & 1) == 0)
677 incr -= 1;
678 } else if (rmode == FPSCR_ROUND_TOZERO) {
679 incr = 0;
680 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) {
681 incr = ~0;
682 }
683
684 if ((rem + incr) < rem && d < 0xffffffff)
685 d += 1;
686 if (d > 0x7fffffff + (vsm.sign != 0)) {
687 d = 0x7fffffff + (vsm.sign != 0);
688 exceptions |= FPSCR_IOC;
689 } else if (rem)
690 exceptions |= FPSCR_IXC;
691
692 if (vsm.sign)
693 d = -d;
694 } else {
695 d = 0;
696 if (vsm.exponent | vsm.significand) {
697 exceptions |= FPSCR_IXC;
698 if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0)
699 d = 1;
700 else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign)
701 d = -1;
702 }
703 }
704
705 pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
706
707 vfp_put_float(state, (s32)d, sd);
708
709 return exceptions;
710}
711
712static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
713{
714 return vfp_single_ftosi(state, sd, unused, m, FPSCR_ROUND_TOZERO);
715}
716
717static struct op fops_ext[] = {
718 { vfp_single_fcpy, 0 }, //0x00000000 - FEXT_FCPY
719 { vfp_single_fabs, 0 }, //0x00000001 - FEXT_FABS
720 { vfp_single_fneg, 0 }, //0x00000002 - FEXT_FNEG
721 { vfp_single_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT
722 { NULL, 0 },
723 { NULL, 0 },
724 { NULL, 0 },
725 { NULL, 0 },
726 { vfp_single_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP
727 { vfp_single_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE
728 { vfp_single_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ
729 { vfp_single_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ
730 { NULL, 0 },
731 { NULL, 0 },
732 { NULL, 0 },
733 { vfp_single_fcvtd, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT
734 { vfp_single_fuito, OP_SCALAR }, //0x00000010 - FEXT_FUITO
735 { vfp_single_fsito, OP_SCALAR }, //0x00000011 - FEXT_FSITO
736 { NULL, 0 },
737 { NULL, 0 },
738 { NULL, 0 },
739 { NULL, 0 },
740 { NULL, 0 },
741 { NULL, 0 },
742 { vfp_single_ftoui, OP_SCALAR }, //0x00000018 - FEXT_FTOUI
743 { vfp_single_ftouiz, OP_SCALAR }, //0x00000019 - FEXT_FTOUIZ
744 { vfp_single_ftosi, OP_SCALAR }, //0x0000001A - FEXT_FTOSI
745 { vfp_single_ftosiz, OP_SCALAR }, //0x0000001B - FEXT_FTOSIZ
746};
747
748
749
750
751
752static u32
753vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn,
754 struct vfp_single *vsm, u32 fpscr)
755{
756 struct vfp_single *vsp;
757 u32 exceptions = 0;
758 int tn, tm;
759
760 tn = vfp_single_type(vsn);
761 tm = vfp_single_type(vsm);
762
763 if (tn & tm & VFP_INFINITY) {
764 /*
765 * Two infinities. Are they different signs?
766 */
767 if (vsn->sign ^ vsm->sign) {
768 /*
769 * different signs -> invalid
770 */
771 exceptions = FPSCR_IOC;
772 vsp = &vfp_single_default_qnan;
773 } else {
774 /*
775 * same signs -> valid
776 */
777 vsp = vsn;
778 }
779 } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) {
780 /*
781 * One infinity and one number -> infinity
782 */
783 vsp = vsn;
784 } else {
785 /*
786 * 'n' is a NaN of some type
787 */
788 return vfp_propagate_nan(vsd, vsn, vsm, fpscr);
789 }
790 *vsd = *vsp;
791 return exceptions;
792}
793
794static u32
795vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
796 struct vfp_single *vsm, u32 fpscr)
797{
798 u32 exp_diff, m_sig;
799
800 if (vsn->significand & 0x80000000 ||
801 vsm->significand & 0x80000000) {
802 pr_info("VFP: bad FP values\n");
803 vfp_single_dump("VSN", vsn);
804 vfp_single_dump("VSM", vsm);
805 }
806
807 /*
808 * Ensure that 'n' is the largest magnitude number. Note that
809 * if 'n' and 'm' have equal exponents, we do not swap them.
810 * This ensures that NaN propagation works correctly.
811 */
812 if (vsn->exponent < vsm->exponent) {
813 struct vfp_single *t = vsn;
814 vsn = vsm;
815 vsm = t;
816 }
817
818 /*
819 * Is 'n' an infinity or a NaN? Note that 'm' may be a number,
820 * infinity or a NaN here.
821 */
822 if (vsn->exponent == 255)
823 return vfp_single_fadd_nonnumber(vsd, vsn, vsm, fpscr);
824
825 /*
826 * We have two proper numbers, where 'vsn' is the larger magnitude.
827 *
828 * Copy 'n' to 'd' before doing the arithmetic.
829 */
830 *vsd = *vsn;
831
832 /*
833 * Align both numbers.
834 */
835 exp_diff = vsn->exponent - vsm->exponent;
836 m_sig = vfp_shiftright32jamming(vsm->significand, exp_diff);
837
838 /*
839 * If the signs are different, we are really subtracting.
840 */
841 if (vsn->sign ^ vsm->sign) {
842 m_sig = vsn->significand - m_sig;
843 if ((s32)m_sig < 0) {
844 vsd->sign = vfp_sign_negate(vsd->sign);
845 m_sig = -m_sig;
846 } else if (m_sig == 0) {
847 vsd->sign = (fpscr & FPSCR_RMODE_MASK) ==
848 FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
849 }
850 } else {
851 m_sig = vsn->significand + m_sig;
852 }
853 vsd->significand = m_sig;
854
855 return 0;
856}
857
858static u32
859vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_single *vsm, u32 fpscr)
860{
861 vfp_single_dump("VSN", vsn);
862 vfp_single_dump("VSM", vsm);
863
864 /*
865 * Ensure that 'n' is the largest magnitude number. Note that
866 * if 'n' and 'm' have equal exponents, we do not swap them.
867 * This ensures that NaN propagation works correctly.
868 */
869 if (vsn->exponent < vsm->exponent) {
870 struct vfp_single *t = vsn;
871 vsn = vsm;
872 vsm = t;
873 pr_debug("VFP: swapping M <-> N\n");
874 }
875
876 vsd->sign = vsn->sign ^ vsm->sign;
877
878 /*
879 * If 'n' is an infinity or NaN, handle it. 'm' may be anything.
880 */
881 if (vsn->exponent == 255) {
882 if (vsn->significand || (vsm->exponent == 255 && vsm->significand))
883 return vfp_propagate_nan(vsd, vsn, vsm, fpscr);
884 if ((vsm->exponent | vsm->significand) == 0) {
885 *vsd = vfp_single_default_qnan;
886 return FPSCR_IOC;
887 }
888 vsd->exponent = vsn->exponent;
889 vsd->significand = 0;
890 return 0;
891 }
892
893 /*
894 * If 'm' is zero, the result is always zero. In this case,
895 * 'n' may be zero or a number, but it doesn't matter which.
896 */
897 if ((vsm->exponent | vsm->significand) == 0) {
898 vsd->exponent = 0;
899 vsd->significand = 0;
900 return 0;
901 }
902
903 /*
904 * We add 2 to the destination exponent for the same reason as
905 * the addition case - though this time we have +1 from each
906 * input operand.
907 */
908 vsd->exponent = vsn->exponent + vsm->exponent - 127 + 2;
909 vsd->significand = vfp_hi64to32jamming((u64)vsn->significand * vsm->significand);
910
911 vfp_single_dump("VSD", vsd);
912 return 0;
913}
914
915#define NEG_MULTIPLY (1 << 0)
916#define NEG_SUBTRACT (1 << 1)
917
918static u32
919vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr, u32 negate, char *func)
920{
921 struct vfp_single vsd, vsp, vsn, vsm;
922 u32 exceptions;
923 s32 v;
924
925 v = vfp_get_float(state, sn);
926 pr_debug("VFP: s%u = %08x\n", sn, v);
927 vfp_single_unpack(&vsn, v);
928 if (vsn.exponent == 0 && vsn.significand)
929 vfp_single_normalise_denormal(&vsn);
930
931 vfp_single_unpack(&vsm, m);
932 if (vsm.exponent == 0 && vsm.significand)
933 vfp_single_normalise_denormal(&vsm);
934
935 exceptions = vfp_single_multiply(&vsp, &vsn, &vsm, fpscr);
936 if (negate & NEG_MULTIPLY)
937 vsp.sign = vfp_sign_negate(vsp.sign);
938
939 v = vfp_get_float(state, sd);
940 pr_debug("VFP: s%u = %08x\n", sd, v);
941 vfp_single_unpack(&vsn, v);
942 if (negate & NEG_SUBTRACT)
943 vsn.sign = vfp_sign_negate(vsn.sign);
944
945 exceptions |= vfp_single_add(&vsd, &vsn, &vsp, fpscr);
946
947 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, func);
948}
949
950/*
951 * Standard operations
952 */
953
954/*
955 * sd = sd + (sn * sm)
956 */
957static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
958{
959 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
960 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac");
961}
962
963/*
964 * sd = sd - (sn * sm)
965 */
966static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
967{
968 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sd, sn);
969 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac");
970}
971
972/*
973 * sd = -sd + (sn * sm)
974 */
975static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
976{
977 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
978 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc");
979}
980
981/*
982 * sd = -sd - (sn * sm)
983 */
984static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
985{
986 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
987 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
988}
989
990/*
991 * sd = sn * sm
992 */
993static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
994{
995 struct vfp_single vsd, vsn, vsm;
996 u32 exceptions;
997 s32 n = vfp_get_float(state, sn);
998
999 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, n);
1000
1001 vfp_single_unpack(&vsn, n);
1002 if (vsn.exponent == 0 && vsn.significand)
1003 vfp_single_normalise_denormal(&vsn);
1004
1005 vfp_single_unpack(&vsm, m);
1006 if (vsm.exponent == 0 && vsm.significand)
1007 vfp_single_normalise_denormal(&vsm);
1008
1009 exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr);
1010 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fmul");
1011}
1012
1013/*
1014 * sd = -(sn * sm)
1015 */
1016static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1017{
1018 struct vfp_single vsd, vsn, vsm;
1019 u32 exceptions;
1020 s32 n = vfp_get_float(state, sn);
1021
1022 pr_debug("VFP: s%u = %08x\n", sn, n);
1023
1024 vfp_single_unpack(&vsn, n);
1025 if (vsn.exponent == 0 && vsn.significand)
1026 vfp_single_normalise_denormal(&vsn);
1027
1028 vfp_single_unpack(&vsm, m);
1029 if (vsm.exponent == 0 && vsm.significand)
1030 vfp_single_normalise_denormal(&vsm);
1031
1032 exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr);
1033 vsd.sign = vfp_sign_negate(vsd.sign);
1034 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fnmul");
1035}
1036
1037/*
1038 * sd = sn + sm
1039 */
1040static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1041{
1042 struct vfp_single vsd, vsn, vsm;
1043 u32 exceptions;
1044 s32 n = vfp_get_float(state, sn);
1045
1046 pr_debug("VFP: s%u = %08x\n", sn, n);
1047
1048 /*
1049 * Unpack and normalise denormals.
1050 */
1051 vfp_single_unpack(&vsn, n);
1052 if (vsn.exponent == 0 && vsn.significand)
1053 vfp_single_normalise_denormal(&vsn);
1054
1055 vfp_single_unpack(&vsm, m);
1056 if (vsm.exponent == 0 && vsm.significand)
1057 vfp_single_normalise_denormal(&vsm);
1058
1059 exceptions = vfp_single_add(&vsd, &vsn, &vsm, fpscr);
1060
1061 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fadd");
1062}
1063
1064/*
1065 * sd = sn - sm
1066 */
1067static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1068{
1069 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
1070 /*
1071 * Subtraction is addition with one sign inverted.
1072 */
1073 return vfp_single_fadd(state, sd, sn, vfp_single_packed_negate(m), fpscr);
1074}
1075
1076/*
1077 * sd = sn / sm
1078 */
1079static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1080{
1081 struct vfp_single vsd, vsn, vsm;
1082 u32 exceptions = 0;
1083 s32 n = vfp_get_float(state, sn);
1084 int tm, tn;
1085
1086 pr_debug("VFP: s%u = %08x\n", sn, n);
1087
1088 vfp_single_unpack(&vsn, n);
1089 vfp_single_unpack(&vsm, m);
1090
1091 vsd.sign = vsn.sign ^ vsm.sign;
1092
1093 tn = vfp_single_type(&vsn);
1094 tm = vfp_single_type(&vsm);
1095
1096 /*
1097 * Is n a NAN?
1098 */
1099 if (tn & VFP_NAN)
1100 goto vsn_nan;
1101
1102 /*
1103 * Is m a NAN?
1104 */
1105 if (tm & VFP_NAN)
1106 goto vsm_nan;
1107
1108 /*
1109 * If n and m are infinity, the result is invalid
1110 * If n and m are zero, the result is invalid
1111 */
1112 if (tm & tn & (VFP_INFINITY|VFP_ZERO))
1113 goto invalid;
1114
1115 /*
1116 * If n is infinity, the result is infinity
1117 */
1118 if (tn & VFP_INFINITY)
1119 goto infinity;
1120
1121 /*
1122 * If m is zero, raise div0 exception
1123 */
1124 if (tm & VFP_ZERO)
1125 goto divzero;
1126
1127 /*
1128 * If m is infinity, or n is zero, the result is zero
1129 */
1130 if (tm & VFP_INFINITY || tn & VFP_ZERO)
1131 goto zero;
1132
1133 if (tn & VFP_DENORMAL)
1134 vfp_single_normalise_denormal(&vsn);
1135 if (tm & VFP_DENORMAL)
1136 vfp_single_normalise_denormal(&vsm);
1137
1138 /*
1139 * Ok, we have two numbers, we can perform division.
1140 */
1141 vsd.exponent = vsn.exponent - vsm.exponent + 127 - 1;
1142 vsm.significand <<= 1;
1143 if (vsm.significand <= (2 * vsn.significand)) {
1144 vsn.significand >>= 1;
1145 vsd.exponent++;
1146 }
1147 {
1148 u64 significand = (u64)vsn.significand << 32;
1149 do_div(significand, vsm.significand);
1150 vsd.significand = significand;
1151 }
1152 if ((vsd.significand & 0x3f) == 0)
1153 vsd.significand |= ((u64)vsm.significand * vsd.significand != (u64)vsn.significand << 32);
1154
1155 return vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fdiv");
1156
1157 vsn_nan:
1158 exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr);
1159 pack:
1160 vfp_put_float(state, vfp_single_pack(&vsd), sd);
1161 return exceptions;
1162
1163 vsm_nan:
1164 exceptions = vfp_propagate_nan(&vsd, &vsm, &vsn, fpscr);
1165 goto pack;
1166
1167 zero:
1168 vsd.exponent = 0;
1169 vsd.significand = 0;
1170 goto pack;
1171
1172 divzero:
1173 exceptions = FPSCR_DZC;
1174 infinity:
1175 vsd.exponent = 255;
1176 vsd.significand = 0;
1177 goto pack;
1178
1179 invalid:
1180 vfp_put_float(state, vfp_single_pack(&vfp_single_default_qnan), sd);
1181 return FPSCR_IOC;
1182}
1183
1184static struct op fops[] = {
1185 { vfp_single_fmac, 0 },
1186 { vfp_single_fmsc, 0 },
1187 { vfp_single_fmul, 0 },
1188 { vfp_single_fadd, 0 },
1189 { vfp_single_fnmac, 0 },
1190 { vfp_single_fnmsc, 0 },
1191 { vfp_single_fnmul, 0 },
1192 { vfp_single_fsub, 0 },
1193 { vfp_single_fdiv, 0 },
1194};
1195
1196#define FREG_BANK(x) ((x) & 0x18)
1197#define FREG_IDX(x) ((x) & 7)
1198
1199u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1200{
1201 u32 op = inst & FOP_MASK;
1202 u32 exceptions = 0;
1203 unsigned int dest;
1204 unsigned int sn = vfp_get_sn(inst);
1205 unsigned int sm = vfp_get_sm(inst);
1206 unsigned int vecitr, veclen, vecstride;
1207 struct op *fop;
1208 pr_debug("In %s\n", __FUNCTION__);
1209
1210 vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
1211
1212 fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
1213
1214 /*
1215 * fcvtsd takes a dN register number as destination, not sN.
1216 * Technically, if bit 0 of dd is set, this is an invalid
1217 * instruction. However, we ignore this for efficiency.
1218 * It also only operates on scalars.
1219 */
1220 if (fop->flags & OP_DD)
1221 dest = vfp_get_dd(inst);
1222 else
1223 dest = vfp_get_sd(inst);
1224
1225 /*
1226 * If destination bank is zero, vector length is always '1'.
1227 * ARM DDI0100F C5.1.3, C5.3.2.
1228 */
1229 if ((fop->flags & OP_SCALAR) || FREG_BANK(dest) == 0)
1230 veclen = 0;
1231 else
1232 veclen = fpscr & FPSCR_LENGTH_MASK;
1233
1234 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
1235 (veclen >> FPSCR_LENGTH_BIT) + 1);
1236
1237 if (!fop->fn) {
1238 printf("VFP: could not find single op %d, inst=0x%x@0x%x\n", FEXT_TO_IDX(inst), inst, state->Reg[15]);
1239 exit(-1);
1240 goto invalid;
1241 }
1242
1243 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
1244 s32 m = vfp_get_float(state, sm);
1245 u32 except;
1246 char type;
1247
1248 type = fop->flags & OP_DD ? 'd' : 's';
1249 if (op == FOP_EXT)
1250 pr_debug("VFP: itr%d (%c%u) = op[%u] (s%u=%08x)\n",
1251 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
1252 sm, m);
1253 else
1254 pr_debug("VFP: itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)\n",
1255 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
1256 FOP_TO_IDX(op), sm, m);
1257
1258 except = fop->fn(state, dest, sn, m, fpscr);
1259 pr_debug("VFP: itr%d: exceptions=%08x\n",
1260 vecitr >> FPSCR_LENGTH_BIT, except);
1261
1262 exceptions |= except;
1263
1264 /*
1265 * CHECK: It appears to be undefined whether we stop when
1266 * we encounter an exception. We continue.
1267 */
1268 dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7);
1269 sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7);
1270 if (FREG_BANK(sm) != 0)
1271 sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7);
1272 }
1273 return exceptions;
1274
1275 invalid:
1276 return (u32)-1;
1277}
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index b56661e48..1aaf28eee 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -147,6 +147,10 @@
147 <ClCompile Include="arm\interpreter\armvirt.cpp" /> 147 <ClCompile Include="arm\interpreter\armvirt.cpp" />
148 <ClCompile Include="arm\interpreter\arm_interpreter.cpp" /> 148 <ClCompile Include="arm\interpreter\arm_interpreter.cpp" />
149 <ClCompile Include="arm\interpreter\thumbemu.cpp" /> 149 <ClCompile Include="arm\interpreter\thumbemu.cpp" />
150 <ClCompile Include="arm\interpreter\vfp\vfp.cpp" />
151 <ClCompile Include="arm\interpreter\vfp\vfpdouble.cpp" />
152 <ClCompile Include="arm\interpreter\vfp\vfpinstr.cpp" />
153 <ClCompile Include="arm\interpreter\vfp\vfpsingle.cpp" />
150 <ClCompile Include="arm\mmu\arm1176jzf_s_mmu.cpp" /> 154 <ClCompile Include="arm\mmu\arm1176jzf_s_mmu.cpp" />
151 <ClCompile Include="core.cpp" /> 155 <ClCompile Include="core.cpp" />
152 <ClCompile Include="core_timing.cpp" /> 156 <ClCompile Include="core_timing.cpp" />
@@ -182,6 +186,9 @@
182 <ClInclude Include="arm\interpreter\arm_interpreter.h" /> 186 <ClInclude Include="arm\interpreter\arm_interpreter.h" />
183 <ClInclude Include="arm\interpreter\arm_regformat.h" /> 187 <ClInclude Include="arm\interpreter\arm_regformat.h" />
184 <ClInclude Include="arm\interpreter\skyeye_defs.h" /> 188 <ClInclude Include="arm\interpreter\skyeye_defs.h" />
189 <ClInclude Include="arm\interpreter\vfp\asm_vfp.h" />
190 <ClInclude Include="arm\interpreter\vfp\vfp.h" />
191 <ClInclude Include="arm\interpreter\vfp\vfp_helper.h" />
185 <ClInclude Include="arm\mmu\arm1176jzf_s_mmu.h" /> 192 <ClInclude Include="arm\mmu\arm1176jzf_s_mmu.h" />
186 <ClInclude Include="arm\mmu\cache.h" /> 193 <ClInclude Include="arm\mmu\cache.h" />
187 <ClInclude Include="arm\mmu\rb.h" /> 194 <ClInclude Include="arm\mmu\rb.h" />
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 5c947ec23..7436b9ed0 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -28,6 +28,9 @@
28 <Filter Include="hle\service"> 28 <Filter Include="hle\service">
29 <UniqueIdentifier>{812c5189-ca49-4704-b842-3ffad09092d3}</UniqueIdentifier> 29 <UniqueIdentifier>{812c5189-ca49-4704-b842-3ffad09092d3}</UniqueIdentifier>
30 </Filter> 30 </Filter>
31 <Filter Include="arm\interpreter\vfp">
32 <UniqueIdentifier>{de62238f-a28e-4a33-8495-23fed6784588}</UniqueIdentifier>
33 </Filter>
31 </ItemGroup> 34 </ItemGroup>
32 <ItemGroup> 35 <ItemGroup>
33 <ClCompile Include="arm\disassembler\arm_disasm.cpp"> 36 <ClCompile Include="arm\disassembler\arm_disasm.cpp">
@@ -114,6 +117,18 @@
114 <ClCompile Include="hle\config_mem.cpp"> 117 <ClCompile Include="hle\config_mem.cpp">
115 <Filter>hle</Filter> 118 <Filter>hle</Filter>
116 </ClCompile> 119 </ClCompile>
120 <ClCompile Include="arm\interpreter\vfp\vfp.cpp">
121 <Filter>arm\interpreter\vfp</Filter>
122 </ClCompile>
123 <ClCompile Include="arm\interpreter\vfp\vfpinstr.cpp">
124 <Filter>arm\interpreter\vfp</Filter>
125 </ClCompile>
126 <ClCompile Include="arm\interpreter\vfp\vfpdouble.cpp">
127 <Filter>arm\interpreter\vfp</Filter>
128 </ClCompile>
129 <ClCompile Include="arm\interpreter\vfp\vfpsingle.cpp">
130 <Filter>arm\interpreter\vfp</Filter>
131 </ClCompile>
117 </ItemGroup> 132 </ItemGroup>
118 <ItemGroup> 133 <ItemGroup>
119 <ClInclude Include="arm\disassembler\arm_disasm.h"> 134 <ClInclude Include="arm\disassembler\arm_disasm.h">
@@ -223,6 +238,15 @@
223 <ClInclude Include="hle\config_mem.h"> 238 <ClInclude Include="hle\config_mem.h">
224 <Filter>hle</Filter> 239 <Filter>hle</Filter>
225 </ClInclude> 240 </ClInclude>
241 <ClInclude Include="arm\interpreter\vfp\asm_vfp.h">
242 <Filter>arm\interpreter\vfp</Filter>
243 </ClInclude>
244 <ClInclude Include="arm\interpreter\vfp\vfp.h">
245 <Filter>arm\interpreter\vfp</Filter>
246 </ClInclude>
247 <ClInclude Include="arm\interpreter\vfp\vfp_helper.h">
248 <Filter>arm\interpreter\vfp</Filter>
249 </ClInclude>
226 </ItemGroup> 250 </ItemGroup>
227 <ItemGroup> 251 <ItemGroup>
228 <Text Include="CMakeLists.txt" /> 252 <Text Include="CMakeLists.txt" />