summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt14
-rw-r--r--src/core/arm/interpreter/arm_interpreter.cpp2
-rw-r--r--src/core/arm/interpreter/armcopro.cpp842
-rw-r--r--src/core/arm/interpreter/armemu.cpp11
-rw-r--r--src/core/arm/interpreter/armemu.h35
-rw-r--r--src/core/arm/interpreter/arminit.cpp8
-rw-r--r--src/core/arm/interpreter/armmmu.h28
-rw-r--r--src/core/arm/interpreter/armsupp.cpp156
-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.cpp370
-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/maverick.cpp1206
-rw-r--r--src/core/arm/interpreter/mmu/rb.cpp126
-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/sa_mmu.cpp864
-rw-r--r--src/core/arm/interpreter/mmu/sa_mmu.h58
-rw-r--r--src/core/arm/interpreter/mmu/tlb.cpp307
-rw-r--r--src/core/arm/interpreter/mmu/tlb.h (renamed from src/core/arm/mmu/tlb.h)9
-rw-r--r--src/core/arm/interpreter/mmu/wb.cpp149
-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/mmu/xscale_copro.cpp1391
-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.cpp1263
-rw-r--r--src/core/arm/interpreter/vfp/vfpinstr.cpp5123
-rw-r--r--src/core/arm/interpreter/vfp/vfpsingle.cpp1278
-rw-r--r--src/core/core.vcxproj28
-rw-r--r--src/core/core.vcxproj.filters93
-rw-r--r--src/core/hle/coprocessor.cpp20
-rw-r--r--src/core/hle/coprocessor.h3
33 files changed, 14292 insertions, 185 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index eb4fef381..fdf68c386 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -7,6 +7,7 @@ set(SRCS core.cpp
7 arm/disassembler/arm_disasm.cpp 7 arm/disassembler/arm_disasm.cpp
8 arm/disassembler/load_symbol_map.cpp 8 arm/disassembler/load_symbol_map.cpp
9 arm/interpreter/arm_interpreter.cpp 9 arm/interpreter/arm_interpreter.cpp
10 arm/interpreter/armcopro.cpp
10 arm/interpreter/armemu.cpp 11 arm/interpreter/armemu.cpp
11 arm/interpreter/arminit.cpp 12 arm/interpreter/arminit.cpp
12 arm/interpreter/armmmu.cpp 13 arm/interpreter/armmmu.cpp
@@ -14,7 +15,18 @@ set(SRCS core.cpp
14 arm/interpreter/armsupp.cpp 15 arm/interpreter/armsupp.cpp
15 arm/interpreter/armvirt.cpp 16 arm/interpreter/armvirt.cpp
16 arm/interpreter/thumbemu.cpp 17 arm/interpreter/thumbemu.cpp
17 arm/mmu/arm1176jzf_s_mmu.cpp 18 arm/interpreter/vfp/vfp.cpp
19 arm/interpreter/vfp/vfpdouble.cpp
20 arm/interpreter/vfp/vfpinstr.cpp
21 arm/interpreter/vfp/vfpsingle.cpp
22 arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
23 arm/interpreter/mmu/cache.cpp
24 arm/interpreter/mmu/maverick.cpp
25 arm/interpreter/mmu/rb.cpp
26 arm/interpreter/mmu/sa_mmu.cpp
27 arm/interpreter/mmu/tlb.cpp
28 arm/interpreter/mmu/wb.cpp
29 arm/interpreter/mmu/xscale_copro.cpp
18 elf/elf_reader.cpp 30 elf/elf_reader.cpp
19 file_sys/directory_file_system.cpp 31 file_sys/directory_file_system.cpp
20 file_sys/meta_file_system.cpp 32 file_sys/meta_file_system.cpp
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp
index 4045779d7..4652803de 100644
--- a/src/core/arm/interpreter/arm_interpreter.cpp
+++ b/src/core/arm/interpreter/arm_interpreter.cpp
@@ -2,7 +2,7 @@
2// Licensed under GPLv2 2// Licensed under GPLv2
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "arm_interpreter.h" 5#include "core/arm/interpreter/arm_interpreter.h"
6 6
7const static cpu_config_t s_arm11_cpu_info = { 7const static cpu_config_t s_arm11_cpu_info = {
8 "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE 8 "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
diff --git a/src/core/arm/interpreter/armcopro.cpp b/src/core/arm/interpreter/armcopro.cpp
new file mode 100644
index 000000000..6a75e6601
--- /dev/null
+++ b/src/core/arm/interpreter/armcopro.cpp
@@ -0,0 +1,842 @@
1/* armcopro.c -- co-processor interface: ARM6 Instruction Emulator.
2 Copyright (C) 1994, 2000 Advanced RISC Machines Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18
19#include "core/arm/interpreter/armdefs.h"
20#include "core/arm/interpreter/armos.h"
21#include "core/arm/interpreter/armemu.h"
22#include "core/arm/interpreter/vfp/vfp.h"
23
24//chy 2005-07-08
25//#include "ansidecl.h"
26//chy -------
27//#include "iwmmxt.h"
28
29
30//chy 2005-09-19 add CP6 MRC support (for get irq number and base)
31extern unsigned xscale_cp6_mrc (ARMul_State * state, unsigned type,
32 ARMword instr, ARMword * data);
33//chy 2005-09-19---------------
34
35extern unsigned xscale_cp13_init (ARMul_State * state);
36extern unsigned xscale_cp13_exit (ARMul_State * state);
37extern unsigned xscale_cp13_ldc (ARMul_State * state, unsigned type,
38 ARMword instr, ARMword data);
39extern unsigned xscale_cp13_stc (ARMul_State * state, unsigned type,
40 ARMword instr, ARMword * data);
41extern unsigned xscale_cp13_mrc (ARMul_State * state, unsigned type,
42 ARMword instr, ARMword * data);
43extern unsigned xscale_cp13_mcr (ARMul_State * state, unsigned type,
44 ARMword instr, ARMword data);
45extern unsigned xscale_cp13_cdp (ARMul_State * state, unsigned type,
46 ARMword instr);
47extern unsigned xscale_cp13_read_reg (ARMul_State * state, unsigned reg,
48 ARMword * data);
49extern unsigned xscale_cp13_write_reg (ARMul_State * state, unsigned reg,
50 ARMword data);
51extern unsigned xscale_cp14_init (ARMul_State * state);
52extern unsigned xscale_cp14_exit (ARMul_State * state);
53extern unsigned xscale_cp14_ldc (ARMul_State * state, unsigned type,
54 ARMword instr, ARMword data);
55extern unsigned xscale_cp14_stc (ARMul_State * state, unsigned type,
56 ARMword instr, ARMword * data);
57extern unsigned xscale_cp14_mrc (ARMul_State * state, unsigned type,
58 ARMword instr, ARMword * data);
59extern unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type,
60 ARMword instr, ARMword data);
61extern unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type,
62 ARMword instr);
63extern unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg,
64 ARMword * data);
65extern unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg,
66 ARMword data);
67extern unsigned xscale_cp15_init (ARMul_State * state);
68extern unsigned xscale_cp15_exit (ARMul_State * state);
69extern unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type,
70 ARMword instr, ARMword data);
71extern unsigned xscale_cp15_stc (ARMul_State * state, unsigned type,
72 ARMword instr, ARMword * data);
73extern unsigned xscale_cp15_mrc (ARMul_State * state, unsigned type,
74 ARMword instr, ARMword * data);
75extern unsigned xscale_cp15_mcr (ARMul_State * state, unsigned type,
76 ARMword instr, ARMword data);
77extern unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type,
78 ARMword instr);
79extern unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg,
80 ARMword * data);
81extern unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg,
82 ARMword data);
83extern unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
84 unsigned cpnum);
85
86/* Dummy Co-processors. */
87
88static unsigned
89NoCoPro3R (ARMul_State * state,
90 unsigned a, ARMword b)
91{
92 return ARMul_CANT;
93}
94
95static unsigned
96NoCoPro4R (ARMul_State * state,
97 unsigned a,
98 ARMword b, ARMword c)
99{
100 return ARMul_CANT;
101}
102
103static unsigned
104NoCoPro4W (ARMul_State * state,
105 unsigned a,
106 ARMword b, ARMword * c)
107{
108 return ARMul_CANT;
109}
110
111static unsigned
112NoCoPro5R (ARMul_State * state,
113 unsigned a,
114 ARMword b,
115 ARMword c, ARMword d)
116{
117 return ARMul_CANT;
118}
119
120static unsigned
121NoCoPro5W (ARMul_State * state,
122 unsigned a,
123 ARMword b,
124 ARMword * c, ARMword * d )
125{
126 return ARMul_CANT;
127}
128
129/* The XScale Co-processors. */
130
131/* Coprocessor 15: System Control. */
132static void write_cp14_reg (unsigned, ARMword);
133static ARMword read_cp14_reg (unsigned);
134
135/* There are two sets of registers for copro 15.
136 One set is available when opcode_2 is 0 and
137 the other set when opcode_2 >= 1. */
138static ARMword XScale_cp15_opcode_2_is_0_Regs[16];
139static ARMword XScale_cp15_opcode_2_is_not_0_Regs[16];
140/* There are also a set of breakpoint registers
141 which are accessed via CRm instead of opcode_2. */
142static ARMword XScale_cp15_DBR1;
143static ARMword XScale_cp15_DBCON;
144static ARMword XScale_cp15_IBCR0;
145static ARMword XScale_cp15_IBCR1;
146
147static unsigned
148XScale_cp15_init (ARMul_State * state)
149{
150 int i;
151
152 for (i = 16; i--;) {
153 XScale_cp15_opcode_2_is_0_Regs[i] = 0;
154 XScale_cp15_opcode_2_is_not_0_Regs[i] = 0;
155 }
156
157 /* Initialise the processor ID. */
158 //chy 2003-03-24, is same as cpu id in skyeye_options.c
159 //XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000;
160 XScale_cp15_opcode_2_is_0_Regs[0] = 0x69050000;
161
162 /* Initialise the cache type. */
163 XScale_cp15_opcode_2_is_not_0_Regs[0] = 0x0B1AA1AA;
164
165 /* Initialise the ARM Control Register. */
166 XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078;
167
168 return No_exp;
169}
170
171/* Check an access to a register. */
172
173static unsigned
174check_cp15_access (ARMul_State * state,
175 unsigned reg,
176 unsigned CRm, unsigned opcode_1, unsigned opcode_2)
177{
178 /* Do not allow access to these register in USER mode. */
179 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
180 if (state->Mode == USER26MODE || state->Mode == USER32MODE )
181 return ARMul_CANT;
182
183 /* Opcode_1should be zero. */
184 if (opcode_1 != 0)
185 return ARMul_CANT;
186
187 /* Different register have different access requirements. */
188 switch (reg) {
189 case 0:
190 case 1:
191 /* CRm must be 0. Opcode_2 can be anything. */
192 if (CRm != 0)
193 return ARMul_CANT;
194 break;
195 case 2:
196 case 3:
197 /* CRm must be 0. Opcode_2 must be zero. */
198 if ((CRm != 0) || (opcode_2 != 0))
199 return ARMul_CANT;
200 break;
201 case 4:
202 /* Access not allowed. */
203 return ARMul_CANT;
204 case 5:
205 case 6:
206 /* Opcode_2 must be zero. CRm must be 0. */
207 if ((CRm != 0) || (opcode_2 != 0))
208 return ARMul_CANT;
209 break;
210 case 7:
211 /* Permissable combinations:
212 Opcode_2 CRm
213 0 5
214 0 6
215 0 7
216 1 5
217 1 6
218 1 10
219 4 10
220 5 2
221 6 5 */
222 switch (opcode_2) {
223 default:
224 return ARMul_CANT;
225 case 6:
226 if (CRm != 5)
227 return ARMul_CANT;
228 break;
229 case 5:
230 if (CRm != 2)
231 return ARMul_CANT;
232 break;
233 case 4:
234 if (CRm != 10)
235 return ARMul_CANT;
236 break;
237 case 1:
238 if ((CRm != 5) && (CRm != 6) && (CRm != 10))
239 return ARMul_CANT;
240 break;
241 case 0:
242 if ((CRm < 5) || (CRm > 7))
243 return ARMul_CANT;
244 break;
245 }
246 break;
247
248 case 8:
249 /* Permissable combinations:
250 Opcode_2 CRm
251 0 5
252 0 6
253 0 7
254 1 5
255 1 6 */
256 if (opcode_2 > 1)
257 return ARMul_CANT;
258 if ((CRm < 5) || (CRm > 7))
259 return ARMul_CANT;
260 if (opcode_2 == 1 && CRm == 7)
261 return ARMul_CANT;
262 break;
263 case 9:
264 /* Opcode_2 must be zero or one. CRm must be 1 or 2. */
265 if (((CRm != 0) && (CRm != 1))
266 || ((opcode_2 != 1) && (opcode_2 != 2)))
267 return ARMul_CANT;
268 break;
269 case 10:
270 /* Opcode_2 must be zero or one. CRm must be 4 or 8. */
271 if (((CRm != 0) && (CRm != 1))
272 || ((opcode_2 != 4) && (opcode_2 != 8)))
273 return ARMul_CANT;
274 break;
275 case 11:
276 /* Access not allowed. */
277 return ARMul_CANT;
278 case 12:
279 /* Access not allowed. */
280 return ARMul_CANT;
281 case 13:
282 /* Opcode_2 must be zero. CRm must be 0. */
283 if ((CRm != 0) || (opcode_2 != 0))
284 return ARMul_CANT;
285 break;
286 case 14:
287 /* Opcode_2 must be 0. CRm must be 0, 3, 4, 8 or 9. */
288 if (opcode_2 != 0)
289 return ARMul_CANT;
290
291 if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8)
292 && (CRm != 9))
293 return ARMul_CANT;
294 break;
295 case 15:
296 /* Opcode_2 must be zero. CRm must be 1. */
297 if ((CRm != 1) || (opcode_2 != 0))
298 return ARMul_CANT;
299 break;
300 default:
301 /* Should never happen. */
302 return ARMul_CANT;
303 }
304
305 return ARMul_DONE;
306}
307
308/* Coprocessor 13: Interrupt Controller and Bus Controller. */
309
310/* There are two sets of registers for copro 13.
311 One set (of three registers) is available when CRm is 0
312 and the other set (of six registers) when CRm is 1. */
313
314static ARMword XScale_cp13_CR0_Regs[16];
315static ARMword XScale_cp13_CR1_Regs[16];
316
317static unsigned
318XScale_cp13_init (ARMul_State * state)
319{
320 int i;
321
322 for (i = 16; i--;) {
323 XScale_cp13_CR0_Regs[i] = 0;
324 XScale_cp13_CR1_Regs[i] = 0;
325 }
326
327 return No_exp;
328}
329
330/* Check an access to a register. */
331
332static unsigned
333check_cp13_access (ARMul_State * state,
334 unsigned reg,
335 unsigned CRm, unsigned opcode_1, unsigned opcode_2)
336{
337 /* Do not allow access to these registers in USER mode. */
338 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
339 if (state->Mode == USER26MODE || state->Mode == USER32MODE )
340 return ARMul_CANT;
341
342 /* The opcodes should be zero. */
343 if ((opcode_1 != 0) || (opcode_2 != 0))
344 return ARMul_CANT;
345
346 /* Do not allow access to these register if bit
347 13 of coprocessor 15's register 15 is zero. */
348 if (!CP_ACCESS_ALLOWED (state, 13))
349 return ARMul_CANT;
350
351 /* Registers 0, 4 and 8 are defined when CRm == 0.
352 Registers 0, 1, 4, 5, 6, 7, 8 are defined when CRm == 1.
353 For all other CRm values undefined behaviour results. */
354 if (CRm == 0) {
355 if (reg == 0 || reg == 4 || reg == 8)
356 return ARMul_DONE;
357 }
358 else if (CRm == 1) {
359 if (reg == 0 || reg == 1 || (reg >= 4 && reg <= 8))
360 return ARMul_DONE;
361 }
362
363 return ARMul_CANT;
364}
365
366/* Coprocessor 14: Performance Monitoring, Clock and Power management,
367 Software Debug. */
368
369static ARMword XScale_cp14_Regs[16];
370
371static unsigned
372XScale_cp14_init (ARMul_State * state)
373{
374 int i;
375
376 for (i = 16; i--;)
377 XScale_cp14_Regs[i] = 0;
378
379 return No_exp;
380}
381
382/* Check an access to a register. */
383
384static unsigned
385check_cp14_access (ARMul_State * state,
386 unsigned reg,
387 unsigned CRm, unsigned opcode1, unsigned opcode2)
388{
389 /* Not allowed to access these register in USER mode. */
390 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
391 if (state->Mode == USER26MODE || state->Mode == USER32MODE )
392 return ARMul_CANT;
393
394 /* CRm should be zero. */
395 if (CRm != 0)
396 return ARMul_CANT;
397
398 /* OPcodes should be zero. */
399 if (opcode1 != 0 || opcode2 != 0)
400 return ARMul_CANT;
401
402 /* Accessing registers 4 or 5 has unpredicatable results. */
403 if (reg >= 4 && reg <= 5)
404 return ARMul_CANT;
405
406 return ARMul_DONE;
407}
408
409/* Here's ARMulator's MMU definition. A few things to note:
410 1) It has eight registers, but only two are defined.
411 2) You can only access its registers with MCR and MRC.
412 3) MMU Register 0 (ID) returns 0x41440110
413 4) Register 1 only has 4 bits defined. Bits 0 to 3 are unused, bit 4
414 controls 32/26 bit program space, bit 5 controls 32/26 bit data space,
415 bit 6 controls late abort timimg and bit 7 controls big/little endian. */
416
417static ARMword MMUReg[8];
418
419static unsigned
420MMUInit (ARMul_State * state)
421{
422/* 2004-05-09 chy
423-------------------------------------------------------------
424read ARM Architecture Reference Manual
4252.6.5 Data Abort
426There are three Abort Model in ARM arch.
427
428Early Abort Model: used in some ARMv3 and earlier implementations. In this
429model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and
430the base register was unchanged for all other instructions. (oldest)
431
432Base Restored Abort Model: If a Data Abort occurs in an instruction which
433specifies base register writeback, the value in the base register is
434unchanged. (strongarm, xscale)
435
436Base Updated Abort Model: If a Data Abort occurs in an instruction which
437specifies base register writeback, the base register writeback still occurs.
438(arm720T)
439
440read PART B
441chap2 The System Control Coprocessor CP15
4422.4 Register1:control register
443L(bit 6): in some ARMv3 and earlier implementations, the abort model of the
444processor could be configured:
4450=early Abort Model Selected(now obsolete)
4461=Late Abort Model selceted(same as Base Updated Abort Model)
447
448on later processors, this bit reads as 1 and ignores writes.
449-------------------------------------------------------------
450So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
451 if lateabtSig=0, then it means Base Restored Abort Model
452because the ARMs which skyeye simulates are all belonged to ARMv4,
453so I think MMUReg[1]'s bit 6 should always be 1
454
455*/
456
457 MMUReg[1] = state->prog32Sig << 4 |
458 state->data32Sig << 5 | 1 << 6 | state->bigendSig << 7;
459 //state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7;
460
461
462 NOTICE_LOG(ARM11, "ARMul_ConsolePrint: MMU present");
463
464 return TRUE;
465}
466
467static unsigned
468MMUMRC (ARMul_State * state, unsigned type,
469 ARMword instr, ARMword * value)
470{
471 mmu_mrc (state, instr, value);
472 return (ARMul_DONE);
473}
474
475static unsigned
476MMUMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
477{
478 mmu_mcr (state, instr, value);
479 return (ARMul_DONE);
480}
481
482/* What follows is the Validation Suite Coprocessor. It uses two
483 co-processor numbers (4 and 5) and has the follwing functionality.
484 Sixteen registers. Both co-processor nuimbers can be used in an MCR
485 and MRC to access these registers. CP 4 can LDC and STC to and from
486 the registers. CP 4 and CP 5 CDP 0 will busy wait for the number of
487 cycles specified by a CP register. CP 5 CDP 1 issues a FIQ after a
488 number of cycles (specified in a CP register), CDP 2 issues an IRQW
489 in the same way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5
490 stores a 32 bit time value in a CP register (actually it's the total
491 number of N, S, I, C and F cyles). */
492
493static ARMword ValReg[16];
494
495static unsigned
496ValLDC (ARMul_State * state,
497 unsigned type, ARMword instr, ARMword data)
498{
499 static unsigned words;
500
501 if (type != ARMul_DATA)
502 words = 0;
503 else {
504 ValReg[BITS (12, 15)] = data;
505
506 if (BIT (22))
507 /* It's a long access, get two words. */
508 if (words++ != 4)
509 return ARMul_INC;
510 }
511
512 return ARMul_DONE;
513}
514
515static unsigned
516ValSTC (ARMul_State * state,
517 unsigned type, ARMword instr, ARMword * data)
518{
519 static unsigned words;
520
521 if (type != ARMul_DATA)
522 words = 0;
523 else {
524 *data = ValReg[BITS (12, 15)];
525
526 if (BIT (22))
527 /* It's a long access, get two words. */
528 if (words++ != 4)
529 return ARMul_INC;
530 }
531
532 return ARMul_DONE;
533}
534
535static unsigned
536ValMRC (ARMul_State * state,
537 unsigned type, ARMword instr, ARMword * value)
538{
539 *value = ValReg[BITS (16, 19)];
540
541 return ARMul_DONE;
542}
543
544static unsigned
545ValMCR (ARMul_State * state,
546 unsigned type, ARMword instr, ARMword value)
547{
548 ValReg[BITS (16, 19)] = value;
549
550 return ARMul_DONE;
551}
552
553static unsigned
554ValCDP (ARMul_State * state, unsigned type, ARMword instr)
555{
556 static unsigned int finish = 0;
557
558 if (BITS (20, 23) != 0)
559 return ARMul_CANT;
560
561 if (type == ARMul_FIRST) {
562 ARMword howlong;
563
564 howlong = ValReg[BITS (0, 3)];
565
566 /* First cycle of a busy wait. */
567 finish = ARMul_Time (state) + howlong;
568
569 return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
570 }
571 else if (type == ARMul_BUSY) {
572 if (ARMul_Time (state) >= finish)
573 return ARMul_DONE;
574 else
575 return ARMul_BUSY;
576 }
577
578 return ARMul_CANT;
579}
580
581static unsigned
582DoAFIQ (ARMul_State * state)
583{
584 state->NfiqSig = LOW;
585 return 0;
586}
587
588static unsigned
589DoAIRQ (ARMul_State * state)
590{
591 state->NirqSig = LOW;
592 return 0;
593}
594
595static unsigned
596IntCDP (ARMul_State * state, unsigned type, ARMword instr)
597{
598 static unsigned int finish;
599 ARMword howlong;
600
601 howlong = ValReg[BITS (0, 3)];
602
603 switch ((int) BITS (20, 23)) {
604 case 0:
605 if (type == ARMul_FIRST) {
606 /* First cycle of a busy wait. */
607 finish = ARMul_Time (state) + howlong;
608
609 return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
610 }
611 else if (type == ARMul_BUSY) {
612 if (ARMul_Time (state) >= finish)
613 return ARMul_DONE;
614 else
615 return ARMul_BUSY;
616 }
617 return ARMul_DONE;
618
619 case 1:
620 if (howlong == 0)
621 ARMul_Abort (state, ARMul_FIQV);
622 else
623 ARMul_ScheduleEvent (state, howlong, DoAFIQ);
624 return ARMul_DONE;
625
626 case 2:
627 if (howlong == 0)
628 ARMul_Abort (state, ARMul_IRQV);
629 else
630 ARMul_ScheduleEvent (state, howlong, DoAIRQ);
631 return ARMul_DONE;
632
633 case 3:
634 state->NfiqSig = HIGH;
635 return ARMul_DONE;
636
637 case 4:
638 state->NirqSig = HIGH;
639 return ARMul_DONE;
640
641 case 5:
642 ValReg[BITS (0, 3)] = ARMul_Time (state);
643 return ARMul_DONE;
644 }
645
646 return ARMul_CANT;
647}
648
649/* Install co-processor instruction handlers in this routine. */
650
651unsigned
652ARMul_CoProInit (ARMul_State * state)
653{
654 unsigned int i;
655
656 /* Initialise tham all first. */
657 for (i = 0; i < 16; i++)
658 ARMul_CoProDetach (state, i);
659
660 /* Install CoPro Instruction handlers here.
661 The format is:
662 ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
663 LDC routine, STC routine, MRC routine, MCR routine,
664 CDP routine, Read Reg routine, Write Reg routine). */
665 if (state->is_ep9312) {
666 ARMul_CoProAttach (state, 4, NULL, NULL, DSPLDC4, DSPSTC4,
667 DSPMRC4, DSPMCR4, NULL, NULL, DSPCDP4, NULL, NULL);
668 ARMul_CoProAttach (state, 5, NULL, NULL, DSPLDC5, DSPSTC5,
669 DSPMRC5, DSPMCR5, NULL, NULL, DSPCDP5, NULL, NULL);
670 ARMul_CoProAttach (state, 6, NULL, NULL, NULL, NULL,
671 DSPMRC6, DSPMCR6, NULL, NULL, DSPCDP6, NULL, NULL);
672 }
673 else {
674 ARMul_CoProAttach (state, 4, NULL, NULL, ValLDC, ValSTC,
675 ValMRC, ValMCR, NULL, NULL, ValCDP, NULL, NULL);
676
677 ARMul_CoProAttach (state, 5, NULL, NULL, NULL, NULL,
678 ValMRC, ValMCR, NULL, NULL, IntCDP, NULL, NULL);
679 }
680
681 if (state->is_XScale) {
682 //chy 2005-09-19, for PXA27x's CP6
683 if (state->is_pxa27x) {
684 ARMul_CoProAttach (state, 6, NULL, NULL,
685 NULL, NULL, xscale_cp6_mrc,
686 NULL, NULL, NULL, NULL, NULL, NULL);
687 }
688 //chy 2005-09-19 end-------------
689 ARMul_CoProAttach (state, 13, xscale_cp13_init,
690 xscale_cp13_exit, xscale_cp13_ldc,
691 xscale_cp13_stc, xscale_cp13_mrc,
692 xscale_cp13_mcr, NULL, NULL, xscale_cp13_cdp,
693 xscale_cp13_read_reg,
694 xscale_cp13_write_reg);
695
696 ARMul_CoProAttach (state, 14, xscale_cp14_init,
697 xscale_cp14_exit, xscale_cp14_ldc,
698 xscale_cp14_stc, xscale_cp14_mrc,
699 xscale_cp14_mcr, NULL, NULL, xscale_cp14_cdp,
700 xscale_cp14_read_reg,
701 xscale_cp14_write_reg);
702 //chy: 2003-08-24.
703 ARMul_CoProAttach (state, 15, xscale_cp15_init,
704 xscale_cp15_exit, xscale_cp15_ldc,
705 xscale_cp15_stc, xscale_cp15_mrc,
706 xscale_cp15_mcr, NULL, NULL, xscale_cp15_cdp,
707 xscale_cp15_read_reg,
708 xscale_cp15_write_reg);
709 }
710 else if (state->is_v6) {
711 ARMul_CoProAttach (state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
712 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
713 ARMul_CoProAttach (state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
714 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
715
716 ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
717 MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);
718 }
719 else { //all except xscale
720 ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
721 // MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
722 MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);
723 }
724//chy 2003-09-03 do it in future!!!!????
725#if 0
726 if (state->is_iWMMXt) {
727 ARMul_CoProAttach (state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC,
728 NULL, NULL, IwmmxtCDP, NULL, NULL);
729
730 ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL,
731 IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL,
732 NULL);
733 }
734#endif
735 //-----------------------------------------------------------------------------
736 //chy 2004-05-25, found the user/system code visit CP 1,2, so I add below code.
737 ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL,
738 ValMRC, ValMCR, NULL, NULL, NULL, NULL, NULL);
739 ARMul_CoProAttach (state, 2, NULL, NULL, ValLDC, ValSTC,
740 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
741 //------------------------------------------------------------------------------
742 /* No handlers below here. */
743
744 /* Call all the initialisation routines. */
745 for (i = 0; i < 16; i++)
746 if (state->CPInit[i])
747 (state->CPInit[i]) (state);
748
749 return TRUE;
750}
751
752/* Install co-processor finalisation routines in this routine. */
753
754void
755ARMul_CoProExit (ARMul_State * state)
756{
757 register unsigned i;
758
759 for (i = 0; i < 16; i++)
760 if (state->CPExit[i])
761 (state->CPExit[i]) (state);
762
763 for (i = 0; i < 16; i++) /* Detach all handlers. */
764 ARMul_CoProDetach (state, i);
765}
766
767/* Routines to hook Co-processors into ARMulator. */
768
769void
770ARMul_CoProAttach (ARMul_State * state,
771 unsigned number,
772 ARMul_CPInits * init,
773 ARMul_CPExits * exit,
774 ARMul_LDCs * ldc,
775 ARMul_STCs * stc,
776 ARMul_MRCs * mrc,
777 ARMul_MCRs * mcr,
778 ARMul_MRRCs * mrrc,
779 ARMul_MCRRs * mcrr,
780 ARMul_CDPs * cdp,
781 ARMul_CPReads * read, ARMul_CPWrites * write)
782{
783 if (init != NULL)
784 state->CPInit[number] = init;
785 if (exit != NULL)
786 state->CPExit[number] = exit;
787 if (ldc != NULL)
788 state->LDC[number] = ldc;
789 if (stc != NULL)
790 state->STC[number] = stc;
791 if (mrc != NULL)
792 state->MRC[number] = mrc;
793 if (mcr != NULL)
794 state->MCR[number] = mcr;
795 if (mrrc != NULL)
796 state->MRRC[number] = mrrc;
797 if (mcrr != NULL)
798 state->MCRR[number] = mcrr;
799 if (cdp != NULL)
800 state->CDP[number] = cdp;
801 if (read != NULL)
802 state->CPRead[number] = read;
803 if (write != NULL)
804 state->CPWrite[number] = write;
805}
806
807void
808ARMul_CoProDetach (ARMul_State * state, unsigned number)
809{
810 ARMul_CoProAttach (state, number, NULL, NULL,
811 NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
812 NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL);
813
814 state->CPInit[number] = NULL;
815 state->CPExit[number] = NULL;
816 state->CPRead[number] = NULL;
817 state->CPWrite[number] = NULL;
818}
819
820//chy 2003-09-03:below funs just replace the old ones
821
822/* Set the XScale FSR and FAR registers. */
823
824void
825XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far)
826{
827 //if (!state->is_XScale || (read_cp14_reg (10) & (1UL << 31)) == 0)
828 if (!state->is_XScale)
829 return;
830 //assume opcode2=0 crm =0
831 xscale_cp15_write_reg (state, 5, fsr);
832 xscale_cp15_write_reg (state, 6, _far);
833}
834
835//chy 2003-09-03 seems 0 is CANT, 1 is DONE ????
836int
837XScale_debug_moe (ARMul_State * state, int moe)
838{
839 //chy 2003-09-03 , W/R CP14 reg, now it's no use ????
840 printf ("SKYEYE: XScale_debug_moe called !!!!\n");
841 return 1;
842}
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 1af684fe3..87141653f 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -23,17 +23,6 @@
23#include "armemu.h" 23#include "armemu.h"
24#include "armos.h" 24#include "armos.h"
25 25
26void
27XScale_set_fsr_far(ARMul_State * state, ARMword fsr, ARMword _far)
28{
29 _dbg_assert_msg_(ARM11, false, "ImplementMe: XScale_set_fsr_far!");
30 //if (!state->is_XScale || (read_cp14_reg(10) & (1UL << 31)) == 0)
31 // return;
32 //
33 //write_cp15_reg(state, 5, 0, 0, fsr);
34 //write_cp15_reg(state, 6, 0, 0, _far);
35}
36
37#define ARMul_Debug(x,y,z) 0 // Disabling this /bunnei 26#define ARMul_Debug(x,y,z) 0 // Disabling this /bunnei
38 27
39//#include "skyeye_callback.h" 28//#include "skyeye_callback.h"
diff --git a/src/core/arm/interpreter/armemu.h b/src/core/arm/interpreter/armemu.h
index 7c118948a..7ccb07e8d 100644
--- a/src/core/arm/interpreter/armemu.h
+++ b/src/core/arm/interpreter/armemu.h
@@ -17,9 +17,9 @@
17#ifndef __ARMEMU_H__ 17#ifndef __ARMEMU_H__
18#define __ARMEMU_H__ 18#define __ARMEMU_H__
19 19
20#include "common/common.h" 20
21#include "armdefs.h" 21#include "core/arm/interpreter/skyeye_defs.h"
22//#include "skyeye.h" 22#include "core/arm/interpreter/armdefs.h"
23 23
24extern ARMword isize; 24extern ARMword isize;
25 25
@@ -73,9 +73,7 @@ extern ARMword isize;
73#define ASSIGNT(res) state->TFlag = res 73#define ASSIGNT(res) state->TFlag = res
74#define INSN_SIZE (TFLAG ? 2 : 4) 74#define INSN_SIZE (TFLAG ? 2 : 4)
75#else 75#else
76#define TBIT (1L << 5)
77#define INSN_SIZE 4 76#define INSN_SIZE 4
78#define TFLAG 0
79#endif 77#endif
80 78
81/*add armv6 CPSR feature*/ 79/*add armv6 CPSR feature*/
@@ -166,6 +164,7 @@ extern ARMword isize;
166#define PCWRAP(pc) ((pc) & R15PCBITS) 164#define PCWRAP(pc) ((pc) & R15PCBITS)
167#endif 165#endif
168 166
167#define PC (state->Reg[15] & PCMASK)
169#define R15CCINTMODE (state->Reg[15] & (CCBITS | R15INTBITS | R15MODEBITS)) 168#define R15CCINTMODE (state->Reg[15] & (CCBITS | R15INTBITS | R15MODEBITS))
170#define R15INT (state->Reg[15] & R15INTBITS) 169#define R15INT (state->Reg[15] & R15INTBITS)
171#define R15INTPC (state->Reg[15] & (R15INTBITS | R15PCBITS)) 170#define R15INTPC (state->Reg[15] & (R15INTBITS | R15PCBITS))
@@ -180,11 +179,11 @@ extern ARMword isize;
180#define ER15INT (IFFLAGS << 26) 179#define ER15INT (IFFLAGS << 26)
181#define EMODE (state->Mode) 180#define EMODE (state->Mode)
182 181
183//#ifdef MODET 182#ifdef MODET
184//#define CPSR (ECC | EINT | EMODE | (TFLAG << 5)) 183#define CPSR (ECC | EINT | EMODE | (TFLAG << 5))
185//#else 184#else
186//#define CPSR (ECC | EINT | EMODE) 185#define CPSR (ECC | EINT | EMODE)
187//#endif 186#endif
188 187
189#ifdef MODE32 188#ifdef MODE32
190#define PATCHR15 189#define PATCHR15
@@ -240,12 +239,12 @@ extern ARMword isize;
240 } \ 239 } \
241 while (0) 240 while (0)
242 241
243//#ifndef MODE32 242#ifndef MODE32
244#define VECTORS 0x20 243#define VECTORS 0x20
245#define LEGALADDR 0x03ffffff 244#define LEGALADDR 0x03ffffff
246#define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig) 245#define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig)
247#define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig) 246#define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig)
248//#endif 247#endif
249 248
250#define INTERNALABORT(address) \ 249#define INTERNALABORT(address) \
251 do \ 250 do \
@@ -420,12 +419,10 @@ extern ARMword isize;
420 || (! (STATE)->is_XScale) \ 419 || (! (STATE)->is_XScale) \
421 || (read_cp15_reg (15, 0, 1) & (1 << (CP)))) 420 || (read_cp15_reg (15, 0, 1) & (1 << (CP))))
422*/ 421*/
423//#define CP_ACCESS_ALLOWED(STATE, CP) \ 422#define CP_ACCESS_ALLOWED(STATE, CP) \
424// (((CP) >= 14) \ 423 ( ((CP) >= 14) \
425// || (!(STATE)->is_XScale) \ 424 || (! (STATE)->is_XScale) \
426// || (xscale_cp15_cp_access_allowed(STATE, 15, CP))) 425 || (xscale_cp15_cp_access_allowed(STATE,15,CP)))
427
428#define CP_ACCESS_ALLOWED(STATE, CP) false // Disabled coprocessor shit /bunnei
429 426
430/* Macro to rotate n right by b bits. */ 427/* Macro to rotate n right by b bits. */
431#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b)))) 428#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b))))
@@ -517,7 +514,7 @@ tdstate;
517 * out-of-updated with the newer ISA. 514 * out-of-updated with the newer ISA.
518 * -- Michael.Kang 515 * -- Michael.Kang
519 ********************************************************************************/ 516 ********************************************************************************/
520#define UNDEF_WARNING ERROR_LOG(ARM11, "undefined or unpredicted behavior for arm instruction.\n"); 517#define UNDEF_WARNING WARN_LOG(ARM11, "undefined or unpredicted behavior for arm instruction.\n");
521 518
522/* Macros to scrutinize instructions. */ 519/* Macros to scrutinize instructions. */
523#define UNDEF_Test UNDEF_WARNING 520#define UNDEF_Test UNDEF_WARNING
diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp
index a8aeecdea..2c771cdda 100644
--- a/src/core/arm/interpreter/arminit.cpp
+++ b/src/core/arm/interpreter/arminit.cpp
@@ -23,8 +23,8 @@
23 23
24#include <math.h> 24#include <math.h>
25 25
26#include "armdefs.h" 26#include "core/arm/interpreter/armdefs.h"
27#include "armemu.h" 27#include "core/arm/interpreter/armemu.h"
28 28
29/***************************************************************************\ 29/***************************************************************************\
30* Definitions for the emulator architecture * 30* Definitions for the emulator architecture *
@@ -271,7 +271,7 @@ below line sould be in skyeye_mach_XXX.c 's XXX_mach_init function
271 271
272 /* Only initialse the coprocessor support once we 272 /* Only initialse the coprocessor support once we
273 know what kind of chip we are dealing with. */ 273 know what kind of chip we are dealing with. */
274 //ARMul_CoProInit (state); Commented out /bunnei 274 ARMul_CoProInit (state);
275 275
276} 276}
277 277
@@ -318,7 +318,7 @@ ARMul_Reset (ARMul_State * state)
318 state->NumFcycles = 0; 318 state->NumFcycles = 0;
319 319
320 //fprintf(stderr,"armul_reset 3: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode); 320 //fprintf(stderr,"armul_reset 3: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);
321 //mmu_reset (state); Commented out /bunnei 321 mmu_reset (state);
322 //fprintf(stderr,"armul_reset 4: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode); 322 //fprintf(stderr,"armul_reset 4: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);
323 323
324 //mem_reset (state); /* move to memory/ram.c */ 324 //mem_reset (state); /* move to memory/ram.c */
diff --git a/src/core/arm/interpreter/armmmu.h b/src/core/arm/interpreter/armmmu.h
index 8b24e6151..818108c9c 100644
--- a/src/core/arm/interpreter/armmmu.h
+++ b/src/core/arm/interpreter/armmmu.h
@@ -172,18 +172,18 @@ typedef struct mmu_ops_s
172} mmu_ops_t; 172} mmu_ops_t;
173 173
174 174
175#include "core/arm/mmu/tlb.h" 175#include "core/arm/interpreter/mmu/tlb.h"
176#include "core/arm/mmu/rb.h" 176#include "core/arm/interpreter/mmu/rb.h"
177#include "core/arm/mmu/wb.h" 177#include "core/arm/interpreter/mmu/wb.h"
178#include "core/arm/mmu/cache.h" 178#include "core/arm/interpreter/mmu/cache.h"
179 179
180/*special process mmu.h*/ 180/*special process mmu.h*/
181//#include "core/arm/mmu/sa_mmu.h" 181#include "core/arm/interpreter/mmu/sa_mmu.h"
182//#include "core/arm/mmu/arm7100_mmu.h" 182//#include "core/arm/interpreter/mmu/arm7100_mmu.h"
183//#include "core/arm/mmu/arm920t_mmu.h" 183//#include "core/arm/interpreter/mmu/arm920t_mmu.h"
184//#include "core/arm/mmu/arm926ejs_mmu.h" 184//#include "core/arm/interpreter/mmu/arm926ejs_mmu.h"
185#include "core/arm/mmu/arm1176jzf_s_mmu.h" 185#include "core/arm/interpreter/mmu/arm1176jzf_s_mmu.h"
186//#include "core/arm/mmu/cortex_a9_mmu.h" 186//#include "core/arm/interpreter/mmu/cortex_a9_mmu.h"
187 187
188typedef struct mmu_state_t 188typedef struct mmu_state_t
189{ 189{
@@ -213,13 +213,13 @@ typedef struct mmu_state_t
213 ARMword copro_access; // 15 213 ARMword copro_access; // 15
214 214
215 mmu_ops_t ops; 215 mmu_ops_t ops;
216 //union 216 union
217 //{ 217 {
218 //sa_mmu_t sa_mmu; 218 sa_mmu_t sa_mmu;
219 //arm7100_mmu_t arm7100_mmu; 219 //arm7100_mmu_t arm7100_mmu;
220 //arm920t_mmu_t arm920t_mmu; 220 //arm920t_mmu_t arm920t_mmu;
221 //arm926ejs_mmu_t arm926ejs_mmu; 221 //arm926ejs_mmu_t arm926ejs_mmu;
222 //} u; 222 } u;
223} mmu_state_t; 223} mmu_state_t;
224 224
225int mmu_init (ARMul_State * state); 225int mmu_init (ARMul_State * state);
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index e531dceda..7816c4c42 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -15,11 +15,9 @@
15 along with this program; if not, write to the Free Software 15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17 17
18#include "armdefs.h" 18#include "core/arm/interpreter/armdefs.h"
19#include "armemu.h" 19#include "core/arm/interpreter/armemu.h"
20 20#include "core/arm/interpreter/skyeye_defs.h"
21//#include "ansidecl.h"
22#include "skyeye_defs.h"
23#include "core/hle/coprocessor.h" 21#include "core/hle/coprocessor.h"
24#include "core/arm/disassembler/arm_disasm.h" 22#include "core/arm/disassembler/arm_disasm.h"
25 23
@@ -127,8 +125,7 @@ ARMul_GetCPSR (ARMul_State * state)
127{ 125{
128 //chy 2003-08-20: below is from gdb20030716, maybe isn't suitable for system simulator 126 //chy 2003-08-20: below is from gdb20030716, maybe isn't suitable for system simulator
129 //return (CPSR | state->Cpsr); for gdb20030716 127 //return (CPSR | state->Cpsr); for gdb20030716
130 // NOTE(bunnei): Changed this from [now] commented out macro "CPSR" 128 return (CPSR); //had be tested in old skyeye with gdb5.0-5.3
131 return ((ECC | EINT | EMODE | (TFLAG << 5))); //had be tested in old skyeye with gdb5.0-5.3
132} 129}
133 130
134/* This routine sets the value of the CPSR. */ 131/* This routine sets the value of the CPSR. */
@@ -145,7 +142,7 @@ ARMul_SetCPSR (ARMul_State * state, ARMword value)
145 142
146void 143void
147ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs) 144ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
148{ 145{
149 state->Cpsr = ARMul_GetCPSR (state); 146 state->Cpsr = ARMul_GetCPSR (state);
150 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode 147 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
151 if (state->Mode != USER26MODE && state->Mode != USER32MODE ) { 148 if (state->Mode != USER26MODE && state->Mode != USER32MODE ) {
@@ -500,8 +497,8 @@ ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
500 return; 497 return;
501 } 498 }
502 499
503 if (ADDREXCEPT (address)) 500 //if (ADDREXCEPT (address))
504 INTERNALABORT (address); 501 // INTERNALABORT (address);
505 502
506 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0); 503 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
507 while (cpab == ARMul_BUSY) { 504 while (cpab == ARMul_BUSY) {
@@ -594,8 +591,8 @@ ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
594 return; 591 return;
595 } 592 }
596 593
597 if (ADDREXCEPT (address) || VECTORACCESS (address)) 594 //if (ADDREXCEPT (address) || VECTORACCESS (address))
598 INTERNALABORT (address); 595 // INTERNALABORT (address);
599 596
600 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data); 597 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
601 while (cpab == ARMul_BUSY) { 598 while (cpab == ARMul_BUSY) {
@@ -661,40 +658,39 @@ ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
661void 658void
662ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) 659ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
663{ 660{
664 HLE::CallMCR(instr, source); 661 unsigned cpab;
665 //unsigned cpab; 662
666 663 //printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source);
667 ////printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source); 664 if (!CP_ACCESS_ALLOWED (state, CPNum)) {
668 //if (!CP_ACCESS_ALLOWED (state, CPNum)) { 665 //chy 2004-07-19 should fix in the future ????!!!!
669 // //chy 2004-07-19 should fix in the future ????!!!! 666 //printf("SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x\n",CPNum, source);
670 // //printf("SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x\n",CPNum, source); 667 ARMul_UndefInstr (state, instr);
671 // ARMul_UndefInstr (state, instr); 668 return;
672 // return; 669 }
673 //} 670
674 671 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
675 //cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source); 672
676 673 while (cpab == ARMul_BUSY) {
677 //while (cpab == ARMul_BUSY) { 674 ARMul_Icycles (state, 1, 0);
678 // ARMul_Icycles (state, 1, 0); 675
679 676 if (IntPending (state)) {
680 // if (IntPending (state)) { 677 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT,
681 // cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, 678 instr, 0);
682 // instr, 0); 679 return;
683 // return; 680 }
684 // } 681 else
685 // else 682 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr,
686 // cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, 683 source);
687 // source); 684 }
688 //} 685
689 686 if (cpab == ARMul_CANT) {
690 //if (cpab == ARMul_CANT) { 687 printf ("SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x\n", instr, CPNum, source);
691 // printf ("SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x\n", instr, CPNum, source); 688 ARMul_Abort (state, ARMul_UndefinedInstrV);
692 // ARMul_Abort (state, ARMul_UndefinedInstrV); 689 }
693 //} 690 else {
694 //else { 691 BUSUSEDINCPCN;
695 // BUSUSEDINCPCN; 692 ARMul_Ccycles (state, 1, 0);
696 // ARMul_Ccycles (state, 1, 0); 693 }
697 //}
698} 694}
699 695
700/* This function does the Busy-Waiting for an MCRR instruction. */ 696/* This function does the Busy-Waiting for an MCRR instruction. */
@@ -742,37 +738,41 @@ ARMul_MRC (ARMul_State * state, ARMword instr)
742 738
743 ARMword result = HLE::CallMRC(instr); 739 ARMword result = HLE::CallMRC(instr);
744 740
745 ////printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr); 741 if (result != -1) {
746 //if (!CP_ACCESS_ALLOWED (state, CPNum)) { 742 return result;
747 // //chy 2004-07-19 should fix in the future????!!!! 743 }
748 // //printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x\n",CPNum, instr); 744
749 // ARMul_UndefInstr (state, instr); 745 //printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
750 // return -1; 746 if (!CP_ACCESS_ALLOWED (state, CPNum)) {
751 //} 747 //chy 2004-07-19 should fix in the future????!!!!
752 748 //printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x\n",CPNum, instr);
753 //cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result); 749 ARMul_UndefInstr (state, instr);
754 //while (cpab == ARMul_BUSY) { 750 return -1;
755 // ARMul_Icycles (state, 1, 0); 751 }
756 // if (IntPending (state)) { 752
757 // cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, 753 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
758 // instr, 0); 754 while (cpab == ARMul_BUSY) {
759 // return (0); 755 ARMul_Icycles (state, 1, 0);
760 // } 756 if (IntPending (state)) {
761 // else 757 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT,
762 // cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, 758 instr, 0);
763 // &result); 759 return (0);
764 //} 760 }
765 //if (cpab == ARMul_CANT) { 761 else
766 // printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n", CPNum, instr); 762 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr,
767 // ARMul_Abort (state, ARMul_UndefinedInstrV); 763 &result);
768 // /* Parent will destroy the flags otherwise. */ 764 }
769 // result = ECC; 765 if (cpab == ARMul_CANT) {
770 //} 766 printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n", CPNum, instr);
771 //else { 767 ARMul_Abort (state, ARMul_UndefinedInstrV);
772 // BUSUSEDINCPCN; 768 /* Parent will destroy the flags otherwise. */
773 // ARMul_Ccycles (state, 1, 0); 769 result = ECC;
774 // ARMul_Icycles (state, 1, 0); 770 }
775 //} 771 else {
772 BUSUSEDINCPCN;
773 ARMul_Ccycles (state, 1, 0);
774 ARMul_Icycles (state, 1, 0);
775 }
776 776
777 return result; 777 return result;
778} 778}
@@ -907,9 +907,7 @@ ARMul_ScheduleEvent (ARMul_State * state, unsigned int delay,
907 state->Now = ARMul_Time (state); 907 state->Now = ARMul_Time (state);
908 when = (state->Now + delay) % EVENTLISTSIZE; 908 when = (state->Now + delay) % EVENTLISTSIZE;
909 event = (struct EventNode *) malloc (sizeof (struct EventNode)); 909 event = (struct EventNode *) malloc (sizeof (struct EventNode));
910
911 _dbg_assert_msg_(ARM11, event, "SKYEYE:ARMul_ScheduleEvent: malloc event error\n"); 910 _dbg_assert_msg_(ARM11, event, "SKYEYE:ARMul_ScheduleEvent: malloc event error\n");
912
913 event->func = what; 911 event->func = what;
914 event->next = *(state->EventPtr + when); 912 event->next = *(state->EventPtr + when);
915 *(state->EventPtr + when) = event; 913 *(state->EventPtr + when) = event;
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/interpreter/mmu/cache.cpp b/src/core/arm/interpreter/mmu/cache.cpp
new file mode 100644
index 000000000..f3c4e0531
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/cache.cpp
@@ -0,0 +1,370 @@
1#include "core/arm/interpreter/armdefs.h"
2
3/* mmu cache init
4 *
5 * @cache_t :cache_t to init
6 * @width :cache line width in byte
7 * @way :way of each cache set
8 * @set :cache set num
9 *
10 * $ -1: error
11 * 0: sucess
12 */
13int
14mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode)
15{
16 int i, j;
17 cache_set_t *sets;
18 cache_line_t *lines;
19
20 /*alloc cache set */
21 sets = NULL;
22 lines = NULL;
23 //fprintf(stderr, "mmu_cache_init: mallloc beg size %d,sets 0x%x\n", sizeof(cache_set_t) * set,sets);
24 //exit(-1);
25 sets = (cache_set_t *) malloc (sizeof (cache_set_t) * set);
26 if (sets == NULL) {
27 ERROR_LOG(ARM11, "set malloc size %d\n", sizeof (cache_set_t) * set);
28 goto sets_error;
29 }
30 //fprintf(stderr, "mmu_cache_init: mallloc end sets 0x%x\n", sets);
31 cache_t->sets = sets;
32
33 /*init cache set */
34 for (i = 0; i < set; i++) {
35 /*alloc cache line */
36 lines = (cache_line_t *) malloc (sizeof (cache_line_t) * way);
37 if (lines == NULL) {
38 ERROR_LOG(ARM11, "line malloc size %d\n",
39 sizeof (cache_line_t) * way);
40 goto lines_error;
41 }
42 /*init cache line */
43 for (j = 0; j < way; j++) {
44 lines[j].tag = 0; //invalid
45 lines[j].data = (ARMword *) malloc (width);
46 if (lines[j].data == NULL) {
47 ERROR_LOG(ARM11, "data alloc size %d\n", width);
48 goto data_error;
49 }
50 }
51
52 sets[i].lines = lines;
53 sets[i].cycle = 0;
54
55 }
56 cache_t->width = width;
57 cache_t->set = set;
58 cache_t->way = way;
59 cache_t->w_mode = w_mode;
60 return 0;
61
62 data_error:
63 /*free data */
64 while (j-- > 0)
65 free (lines[j].data);
66 /*free data error line */
67 free (lines);
68 lines_error:
69 /*free lines already alloced */
70 while (i-- > 0) {
71 for (j = 0; j < way; j++)
72 free (sets[i].lines[j].data);
73 free (sets[i].lines);
74 }
75 /*free sets */
76 free (sets);
77 sets_error:
78 return -1;
79};
80
81/* free a cache_t's inner data, the ptr self is not freed,
82 * when needed do like below:
83 * mmu_cache_exit(cache);
84 * free(cache_t);
85 *
86 * @cache_t : the cache_t to free
87 */
88
89void
90mmu_cache_exit (cache_s * cache_t)
91{
92 int i, j;
93 cache_set_t *sets, *set;
94 cache_line_t *lines, *line;
95
96 /*free all set */
97 sets = cache_t->sets;
98 for (set = sets, i = 0; i < cache_t->set; i++, set++) {
99 /*free all line */
100 lines = set->lines;
101 for (line = lines, j = 0; j < cache_t->way; j++, line++)
102 free (line->data);
103 free (lines);
104 }
105 free (sets);
106}
107
108/* mmu cache search
109 *
110 * @state :ARMul_State
111 * @cache_t :cache_t to search
112 * @va :virtual address
113 *
114 * $ NULL: no cache match
115 * cache :cache matched
116 */
117cache_line_t *
118mmu_cache_search (ARMul_State * state, cache_s * cache_t, ARMword va)
119{
120 int i;
121 int set = va_cache_set (va, cache_t);
122 ARMword tag = va_cache_align (va, cache_t);
123 cache_line_t *cache;
124
125 cache_set_t *cache_set = cache_t->sets + set;
126 for (i = 0, cache = cache_set->lines; i < cache_t->way; i++, cache++) {
127 if ((cache->tag & TAG_VALID_FLAG)
128 && (tag == va_cache_align (cache->tag, cache_t)))
129 return cache;
130 }
131 return NULL;
132}
133
134/* mmu cache search by set/index
135 *
136 * @state :ARMul_State
137 * @cache_t :cache_t to search
138 * @index :set/index value.
139 *
140 * $ NULL: no cache match
141 * cache :cache matched
142 */
143cache_line_t *
144mmu_cache_search_by_index (ARMul_State * state, cache_s * cache_t,
145 ARMword index)
146{
147 int way = cache_t->way;
148 int set_v = index_cache_set (index, cache_t);
149 int i = 0, index_v = 0;
150 cache_set_t *set;
151
152 while ((way >>= 1) >= 1)
153 i++;
154 index_v = index >> (32 - i);
155 set = cache_t->sets + set_v;
156
157 return set->lines + index_v;
158}
159
160
161/* mmu cache alloc
162 *
163 * @state :ARMul_State
164 * @cache_t :cache_t to alloc from
165 * @va :virtual address that require cache alloc, need not cache aligned
166 * @pa :physical address of va
167 *
168 * $ cache_alloced, always alloc OK
169 */
170cache_line_t *
171mmu_cache_alloc (ARMul_State * state, cache_s * cache_t, ARMword va,
172 ARMword pa)
173{
174 cache_line_t *cache;
175 cache_set_t *set;
176 int i;
177
178 va = va_cache_align (va, cache_t);
179 pa = va_cache_align (pa, cache_t);
180
181 set = &cache_t->sets[va_cache_set (va, cache_t)];
182
183 /*robin-round */
184 cache = &set->lines[set->cycle++];
185 if (set->cycle == cache_t->way)
186 set->cycle = 0;
187
188 if (cache_t->w_mode == CACHE_WRITE_BACK) {
189 ARMword t;
190
191 /*if cache valid, try to write back */
192 if (cache->tag & TAG_VALID_FLAG) {
193 mmu_cache_write_back (state, cache_t, cache);
194 }
195 /*read in cache_line */
196 t = pa;
197 for (i = 0; i < (cache_t->width >> WORD_SHT);
198 i++, t += WORD_SIZE) {
199 //cache->data[i] = mem_read_word (state, t);
200 bus_read(32, t, &cache->data[i]);
201 }
202 }
203 /*store tag and pa */
204 cache->tag = va | TAG_VALID_FLAG;
205 cache->pa = pa;
206
207 return cache;
208};
209
210/* mmu_cache_write_back write cache data to memory
211 * @state
212 * @cache_t :cache_t of the cache line
213 * @cache : cache line
214 */
215void
216mmu_cache_write_back (ARMul_State * state, cache_s * cache_t,
217 cache_line_t * cache)
218{
219 ARMword pa = cache->pa;
220 int nw = cache_t->width >> WORD_SHT;
221 ARMword *data = cache->data;
222 int i;
223 int t0, t1, t2;
224
225 if ((cache->tag & 1) == 0)
226 return;
227
228 switch (cache->
229 tag & ~1 & (TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY)) {
230 case 0:
231 return;
232 case TAG_FIRST_HALF_DIRTY:
233 nw /= 2;
234 break;
235 case TAG_LAST_HALF_DIRTY:
236 nw /= 2;
237 pa += nw << WORD_SHT;
238 data += nw;
239 break;
240 case TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY:
241 break;
242 }
243 for (i = 0; i < nw; i++, data++, pa += WORD_SIZE)
244 //mem_write_word (state, pa, *data);
245 bus_write(32, pa, *data);
246
247 cache->tag &= ~(TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY);
248};
249
250
251/* mmu_cache_clean: clean a cache of va in cache_t
252 *
253 * @state :ARMul_State
254 * @cache_t :cache_t to clean
255 * @va :virtaul address
256 */
257void
258mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va)
259{
260 cache_line_t *cache;
261
262 cache = mmu_cache_search (state, cache_t, va);
263 if (cache)
264 mmu_cache_write_back (state, cache_t, cache);
265}
266
267/* mmu_cache_clean_by_index: clean a cache by set/index format value
268 *
269 * @state :ARMul_State
270 * @cache_t :cache_t to clean
271 * @va :set/index format value
272 */
273void
274mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t,
275 ARMword index)
276{
277 cache_line_t *cache;
278
279 cache = mmu_cache_search_by_index (state, cache_t, index);
280 if (cache)
281 mmu_cache_write_back (state, cache_t, cache);
282}
283
284/* mmu_cache_invalidate : invalidate a cache of va
285 *
286 * @state :ARMul_State
287 * @cache_t :cache_t to invalid
288 * @va :virt_addr to invalid
289 */
290void
291mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va)
292{
293 cache_line_t *cache;
294
295 cache = mmu_cache_search (state, cache_t, va);
296 if (cache) {
297 mmu_cache_write_back (state, cache_t, cache);
298 cache->tag = 0;
299 }
300}
301
302/* mmu_cache_invalidate_by_index : invalidate a cache by index format
303 *
304 * @state :ARMul_State
305 * @cache_t :cache_t to invalid
306 * @index :set/index data
307 */
308void
309mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t,
310 ARMword index)
311{
312 cache_line_t *cache;
313
314 cache = mmu_cache_search_by_index (state, cache_t, index);
315 if (cache) {
316 mmu_cache_write_back (state, cache_t, cache);
317 cache->tag = 0;
318 }
319}
320
321/* mmu_cache_invalidate_all
322 *
323 * @state:
324 * @cache_t
325 * */
326void
327mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t)
328{
329 int i, j;
330 cache_set_t *set;
331 cache_line_t *cache;
332
333 set = cache_t->sets;
334 for (i = 0; i < cache_t->set; i++, set++) {
335 cache = set->lines;
336 for (j = 0; j < cache_t->way; j++, cache++) {
337 mmu_cache_write_back (state, cache_t, cache);
338 cache->tag = 0;
339 }
340 }
341};
342
343void
344mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa)
345{
346 ARMword set, way;
347 cache_line_t *cache;
348 pa = (pa / cache_t->width);
349 way = pa & (cache_t->way - 1);
350 set = (pa / cache_t->way) & (cache_t->set - 1);
351 cache = &cache_t->sets[set].lines[way];
352
353 mmu_cache_write_back (state, cache_t, cache);
354 cache->tag = 0;
355}
356
357cache_line_t* mmu_cache_dirty_cache(ARMul_State *state,cache_s *cache){
358 int i;
359 int j;
360 cache_line_t *cache_line = NULL;
361 cache_set_t *cache_set = cache->sets;
362 int sets = cache->set;
363 for (i = 0; i < sets; i++){
364 for(j = 0,cache_line = &cache_set[i].lines[0]; j < cache->way; j++,cache_line++){
365 if((cache_line->tag & TAG_FIRST_HALF_DIRTY) || (cache_line->tag & TAG_LAST_HALF_DIRTY))
366 return cache_line;
367 }
368 }
369 return NULL;
370}
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/interpreter/mmu/maverick.cpp b/src/core/arm/interpreter/mmu/maverick.cpp
new file mode 100644
index 000000000..0e98ef22b
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/maverick.cpp
@@ -0,0 +1,1206 @@
1/* maverick.c -- Cirrus/DSP co-processor interface.
2 Copyright (C) 2003 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez (aldyh@redhat.com).
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19#include <assert.h>
20
21#include "core/arm/interpreter/armdefs.h"
22#include "core/arm/interpreter/armemu.h"
23
24
25/*#define CIRRUS_DEBUG 1 */
26#if CIRRUS_DEBUG
27# define printfdbg printf
28#else
29# define printfdbg printf_nothing
30#endif
31
32#define POS64(i) ( (~(i)) >> 63 )
33#define NEG64(i) ( (i) >> 63 )
34
35/* Define Co-Processor instruction handlers here. */
36
37/* Here's ARMulator's DSP definition. A few things to note:
38 1) it has 16 64-bit registers and 4 72-bit accumulators
39 2) you can only access its registers with MCR and MRC. */
40
41/* We can't define these in here because this file might not be linked
42 unless the target is arm9e-*. They are defined in wrapper.c.
43 Eventually the simulator should be made to handle any coprocessor
44 at run time. */
45struct maverick_regs
46{
47 union
48 {
49 int i;
50 float f;
51 } upper;
52
53 union
54 {
55 int i;
56 float f;
57 } lower;
58};
59
60union maverick_acc_regs
61{
62 long double ld; /* Acc registers are 72-bits. */
63};
64
65struct maverick_regs DSPregs[16];
66union maverick_acc_regs DSPacc[4];
67ARMword DSPsc;
68
69#define DEST_REG (BITS (12, 15))
70#define SRC1_REG (BITS (16, 19))
71#define SRC2_REG (BITS (0, 3))
72
73static int lsw_int_index, msw_int_index;
74static int lsw_float_index, msw_float_index;
75
76static double mv_getRegDouble (int);
77static long long mv_getReg64int (int);
78static void mv_setRegDouble (int, double val);
79static void mv_setReg64int (int, long long val);
80
81static union
82{
83 double d;
84 long long ll;
85 int ints[2];
86} reg_conv;
87
88static void
89printf_nothing (void *foo, ...)
90{
91}
92
93static void
94cirrus_not_implemented (char *insn)
95{
96 fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
97 fprintf (stderr, "aborting!\n");
98
99 // skyeye_exit (1);
100}
101
102static unsigned
103DSPInit (ARMul_State * state)
104{
105 NOTICE_LOG(ARM11, "ARMul_ConsolePrint: DSP present");
106 return TRUE;
107}
108
109unsigned
110DSPMRC4 (ARMul_State * state,
111 unsigned type, ARMword instr, ARMword * value)
112{
113 switch (BITS (5, 7)) {
114 case 0: /* cfmvrdl */
115 /* Move lower half of a DF stored in a DSP reg into an Arm reg. */
116 printfdbg ("cfmvrdl\n");
117 printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i);
118 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
119
120 *value = (ARMword) DSPregs[SRC1_REG].lower.i;
121 break;
122
123 case 1: /* cfmvrdh */
124 /* Move upper half of a DF stored in a DSP reg into an Arm reg. */
125 printfdbg ("cfmvrdh\n");
126 printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i);
127 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
128
129 *value = (ARMword) DSPregs[SRC1_REG].upper.i;
130 break;
131
132 case 2: /* cfmvrs */
133 /* Move SF from upper half of a DSP register to an Arm register. */
134 *value = (ARMword) DSPregs[SRC1_REG].upper.i;
135 printfdbg ("cfmvrs = mvf%d <-- %f\n",
136 SRC1_REG, DSPregs[SRC1_REG].upper.f);
137 break;
138
139#ifdef doesnt_work
140 case 4: /* cfcmps */
141 {
142 float a, b;
143 int n, z, c, v;
144
145 a = DSPregs[SRC1_REG].upper.f;
146 b = DSPregs[SRC2_REG].upper.f;
147
148 printfdbg ("cfcmps\n");
149 printfdbg ("\tcomparing %f and %f\n", a, b);
150
151 z = a == b; /* zero */
152 n = a != b; /* negative */
153 v = a > b; /* overflow */
154 c = 0; /* carry */
155 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
156 28);
157 break;
158 }
159
160 case 5: /* cfcmpd */
161 {
162 double a, b;
163 int n, z, c, v;
164
165 a = mv_getRegDouble (SRC1_REG);
166 b = mv_getRegDouble (SRC2_REG);
167
168 printfdbg ("cfcmpd\n");
169 printfdbg ("\tcomparing %g and %g\n", a, b);
170
171 z = a == b; /* zero */
172 n = a != b; /* negative */
173 v = a > b; /* overflow */
174 c = 0; /* carry */
175 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
176 28);
177 break;
178 }
179#else
180 case 4: /* cfcmps */
181 {
182 float a, b;
183 int n, z, c, v;
184
185 a = DSPregs[SRC1_REG].upper.f;
186 b = DSPregs[SRC2_REG].upper.f;
187
188 printfdbg ("cfcmps\n");
189 printfdbg ("\tcomparing %f and %f\n", a, b);
190
191 z = a == b; /* zero */
192 n = a < b; /* negative */
193 c = a > b; /* carry */
194 v = 0; /* fixme */
195 printfdbg ("\tz = %d, n = %d\n", z, n);
196 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
197 28);
198 break;
199 }
200
201 case 5: /* cfcmpd */
202 {
203 double a, b;
204 int n, z, c, v;
205
206 a = mv_getRegDouble (SRC1_REG);
207 b = mv_getRegDouble (SRC2_REG);
208
209 printfdbg ("cfcmpd\n");
210 printfdbg ("\tcomparing %g and %g\n", a, b);
211
212 z = a == b; /* zero */
213 n = a < b; /* negative */
214 c = a > b; /* carry */
215 v = 0; /* fixme */
216 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
217 28);
218 break;
219 }
220#endif
221 default:
222 fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
223 cirrus_not_implemented ("unknown");
224 break;
225 }
226
227 return ARMul_DONE;
228}
229
230unsigned
231DSPMRC5 (ARMul_State * state,
232 unsigned type, ARMword instr, ARMword * value)
233{
234 switch (BITS (5, 7)) {
235 case 0: /* cfmvr64l */
236 /* Move lower half of 64bit int from Cirrus to Arm. */
237 *value = (ARMword) DSPregs[SRC1_REG].lower.i;
238 printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
239 DEST_REG, (int) *value);
240 break;
241
242 case 1: /* cfmvr64h */
243 /* Move upper half of 64bit int from Cirrus to Arm. */
244 *value = (ARMword) DSPregs[SRC1_REG].upper.i;
245 printfdbg ("cfmvr64h <-- %d\n", (int) *value);
246 break;
247
248 case 4: /* cfcmp32 */
249 {
250 int res;
251 int n, z, c, v;
252 unsigned int a, b;
253
254 printfdbg ("cfcmp32 mvfx%d - mvfx%d\n", SRC1_REG,
255 SRC2_REG);
256
257 /* FIXME: see comment for cfcmps. */
258 a = DSPregs[SRC1_REG].lower.i;
259 b = DSPregs[SRC2_REG].lower.i;
260
261 res = DSPregs[SRC1_REG].lower.i -
262 DSPregs[SRC2_REG].lower.i;
263 /* zero */
264 z = res == 0;
265 /* negative */
266 n = res < 0;
267 /* overflow */
268 v = SubOverflow (DSPregs[SRC1_REG].lower.i,
269 DSPregs[SRC2_REG].lower.i, res);
270 /* carry */
271 c = (NEG (a) && POS (b) ||
272 (NEG (a) && POS (res)) || (POS (b)
273 && POS (res)));
274
275 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
276 28);
277 break;
278 }
279
280 case 5: /* cfcmp64 */
281 {
282 long long res;
283 int n, z, c, v;
284 unsigned long long a, b;
285
286 printfdbg ("cfcmp64 mvdx%d - mvdx%d\n", SRC1_REG,
287 SRC2_REG);
288
289 /* fixme: see comment for cfcmps. */
290
291 a = mv_getReg64int (SRC1_REG);
292 b = mv_getReg64int (SRC2_REG);
293
294 res = mv_getReg64int (SRC1_REG) -
295 mv_getReg64int (SRC2_REG);
296 /* zero */
297 z = res == 0;
298 /* negative */
299 n = res < 0;
300 /* overflow */
301 v = ((NEG64 (a) && POS64 (b) && POS64 (res))
302 || (POS64 (a) && NEG64 (b) && NEG64 (res)));
303 /* carry */
304 c = (NEG64 (a) && POS64 (b) ||
305 (NEG64 (a) && POS64 (res)) || (POS64 (b)
306 && POS64 (res)));
307
308 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
309 28);
310 break;
311 }
312
313 default:
314 fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
315 cirrus_not_implemented ("unknown");
316 break;
317 }
318
319 return ARMul_DONE;
320}
321
322unsigned
323DSPMRC6 (ARMul_State * state,
324 unsigned type, ARMword instr, ARMword * value)
325{
326 switch (BITS (5, 7)) {
327 case 0: /* cfmval32 */
328 cirrus_not_implemented ("cfmval32");
329 break;
330
331 case 1: /* cfmvam32 */
332 cirrus_not_implemented ("cfmvam32");
333 break;
334
335 case 2: /* cfmvah32 */
336 cirrus_not_implemented ("cfmvah32");
337 break;
338
339 case 3: /* cfmva32 */
340 cirrus_not_implemented ("cfmva32");
341 break;
342
343 case 4: /* cfmva64 */
344 cirrus_not_implemented ("cfmva64");
345 break;
346
347 case 5: /* cfmvsc32 */
348 cirrus_not_implemented ("cfmvsc32");
349 break;
350
351 default:
352 fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
353 cirrus_not_implemented ("unknown");
354 break;
355 }
356
357 return ARMul_DONE;
358}
359
360unsigned
361DSPMCR4 (ARMul_State * state,
362 unsigned type, ARMword instr, ARMword value)
363{
364 switch (BITS (5, 7)) {
365 case 0: /* cfmvdlr */
366 /* Move the lower half of a DF value from an Arm register into
367 the lower half of a Cirrus register. */
368 printfdbg ("cfmvdlr <-- 0x%x\n", (int) value);
369 DSPregs[SRC1_REG].lower.i = (int) value;
370 break;
371
372 case 1: /* cfmvdhr */
373 /* Move the upper half of a DF value from an Arm register into
374 the upper half of a Cirrus register. */
375 printfdbg ("cfmvdhr <-- 0x%x\n", (int) value);
376 DSPregs[SRC1_REG].upper.i = (int) value;
377 break;
378
379 case 2: /* cfmvsr */
380 /* Move SF from Arm register into upper half of Cirrus register. */
381 printfdbg ("cfmvsr <-- 0x%x\n", (int) value);
382 DSPregs[SRC1_REG].upper.i = (int) value;
383 break;
384
385 default:
386 fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
387 cirrus_not_implemented ("unknown");
388 break;
389 }
390
391 return ARMul_DONE;
392}
393
394unsigned
395DSPMCR5 (ARMul_State * state,
396 unsigned type, ARMword instr, ARMword value)
397{
398 union
399 {
400 int s;
401 unsigned int us;
402 } val;
403
404 switch (BITS (5, 7)) {
405 case 0: /* cfmv64lr */
406 /* Move lower half of a 64bit int from an ARM register into the
407 lower half of a DSP register and sign extend it. */
408 printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG,
409 (int) value);
410 DSPregs[SRC1_REG].lower.i = (int) value;
411 break;
412
413 case 1: /* cfmv64hr */
414 /* Move upper half of a 64bit int from an ARM register into the
415 upper half of a DSP register. */
416 printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
417 SRC1_REG, (int) value);
418 DSPregs[SRC1_REG].upper.i = (int) value;
419 break;
420
421 case 2: /* cfrshl32 */
422 printfdbg ("cfrshl32\n");
423 val.us = value;
424 if (val.s > 0)
425 DSPregs[SRC2_REG].lower.i =
426 DSPregs[SRC1_REG].lower.i << value;
427 else
428 DSPregs[SRC2_REG].lower.i =
429 DSPregs[SRC1_REG].lower.i >> -value;
430 break;
431
432 case 3: /* cfrshl64 */
433 printfdbg ("cfrshl64\n");
434 val.us = value;
435 if (val.s > 0)
436 mv_setReg64int (SRC2_REG,
437 mv_getReg64int (SRC1_REG) << value);
438 else
439 mv_setReg64int (SRC2_REG,
440 mv_getReg64int (SRC1_REG) >> -value);
441 break;
442
443 default:
444 fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
445 cirrus_not_implemented ("unknown");
446 break;
447 }
448
449 return ARMul_DONE;
450}
451
452unsigned
453DSPMCR6 (ARMul_State * state,
454 unsigned type, ARMword instr, ARMword value)
455{
456 switch (BITS (5, 7)) {
457 case 0: /* cfmv32al */
458 cirrus_not_implemented ("cfmv32al");
459 break;
460
461 case 1: /* cfmv32am */
462 cirrus_not_implemented ("cfmv32am");
463 break;
464
465 case 2: /* cfmv32ah */
466 cirrus_not_implemented ("cfmv32ah");
467 break;
468
469 case 3: /* cfmv32a */
470 cirrus_not_implemented ("cfmv32a");
471 break;
472
473 case 4: /* cfmv64a */
474 cirrus_not_implemented ("cfmv64a");
475 break;
476
477 case 5: /* cfmv32sc */
478 cirrus_not_implemented ("cfmv32sc");
479 break;
480
481 default:
482 fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
483 cirrus_not_implemented ("unknown");
484 break;
485 }
486
487 return ARMul_DONE;
488}
489
490unsigned
491DSPLDC4 (ARMul_State * state,
492 unsigned type, ARMword instr, ARMword data)
493{
494 static unsigned words;
495
496 if (type != ARMul_DATA) {
497 words = 0;
498 return ARMul_DONE;
499 }
500
501 if (BIT (22)) { /* it's a long access, get two words */
502 /* cfldrd */
503
504 printfdbg
505 ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
506 data, words, state->bigendSig, DEST_REG);
507
508 if (words == 0) {
509 if (state->bigendSig)
510 DSPregs[DEST_REG].upper.i = (int) data;
511 else
512 DSPregs[DEST_REG].lower.i = (int) data;
513 }
514 else {
515 if (state->bigendSig)
516 DSPregs[DEST_REG].lower.i = (int) data;
517 else
518 DSPregs[DEST_REG].upper.i = (int) data;
519 }
520
521 ++words;
522
523 if (words == 2) {
524 printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
525 mv_getRegDouble (DEST_REG));
526
527 return ARMul_DONE;
528 }
529 else
530 return ARMul_INC;
531 }
532 else {
533 /* Get just one word. */
534
535 /* cfldrs */
536 printfdbg ("cfldrs\n");
537
538 DSPregs[DEST_REG].upper.i = (int) data;
539
540 printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
541 DSPregs[DEST_REG].upper.f);
542
543 return ARMul_DONE;
544 }
545}
546
547unsigned
548DSPLDC5 (ARMul_State * state,
549 unsigned type, ARMword instr, ARMword data)
550{
551 static unsigned words;
552
553 if (type != ARMul_DATA) {
554 words = 0;
555 return ARMul_DONE;
556 }
557
558 if (BIT (22)) {
559 /* It's a long access, get two words. */
560
561 /* cfldr64 */
562 printfdbg ("cfldr64: %d\n", data);
563
564 if (words == 0) {
565 if (state->bigendSig)
566 DSPregs[DEST_REG].upper.i = (int) data;
567 else
568 DSPregs[DEST_REG].lower.i = (int) data;
569 }
570 else {
571 if (state->bigendSig)
572 DSPregs[DEST_REG].lower.i = (int) data;
573 else
574 DSPregs[DEST_REG].upper.i = (int) data;
575 }
576
577 ++words;
578
579 if (words == 2) {
580 printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
581 mv_getReg64int (DEST_REG));
582
583 return ARMul_DONE;
584 }
585 else
586 return ARMul_INC;
587 }
588 else {
589 /* Get just one word. */
590
591 /* cfldr32 */
592 printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
593
594 /* 32bit ints should be sign extended to 64bits when loaded. */
595 mv_setReg64int (DEST_REG, (long long) data);
596
597 return ARMul_DONE;
598 }
599}
600
601unsigned
602DSPSTC4 (ARMul_State * state,
603 unsigned type, ARMword instr, ARMword * data)
604{
605 static unsigned words;
606
607 if (type != ARMul_DATA) {
608 words = 0;
609 return ARMul_DONE;
610 }
611
612 if (BIT (22)) {
613 /* It's a long access, get two words. */
614 /* cfstrd */
615 printfdbg ("cfstrd\n");
616
617 if (words == 0) {
618 if (state->bigendSig)
619 *data = (ARMword) DSPregs[DEST_REG].upper.i;
620 else
621 *data = (ARMword) DSPregs[DEST_REG].lower.i;
622 }
623 else {
624 if (state->bigendSig)
625 *data = (ARMword) DSPregs[DEST_REG].lower.i;
626 else
627 *data = (ARMword) DSPregs[DEST_REG].upper.i;
628 }
629
630 ++words;
631
632 if (words == 2) {
633 printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
634 mv_getRegDouble (DEST_REG));
635
636 return ARMul_DONE;
637 }
638 else
639 return ARMul_INC;
640 }
641 else {
642 /* Get just one word. */
643 /* cfstrs */
644 printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
645 DSPregs[DEST_REG].upper.f);
646
647 *data = (ARMword) DSPregs[DEST_REG].upper.i;
648
649 return ARMul_DONE;
650 }
651}
652
653unsigned
654DSPSTC5 (ARMul_State * state,
655 unsigned type, ARMword instr, ARMword * data)
656{
657 static unsigned words;
658
659 if (type != ARMul_DATA) {
660 words = 0;
661 return ARMul_DONE;
662 }
663
664 if (BIT (22)) {
665 /* It's a long access, store two words. */
666 /* cfstr64 */
667 printfdbg ("cfstr64\n");
668
669 if (words == 0) {
670 if (state->bigendSig)
671 *data = (ARMword) DSPregs[DEST_REG].upper.i;
672 else
673 *data = (ARMword) DSPregs[DEST_REG].lower.i;
674 }
675 else {
676 if (state->bigendSig)
677 *data = (ARMword) DSPregs[DEST_REG].lower.i;
678 else
679 *data = (ARMword) DSPregs[DEST_REG].upper.i;
680 }
681
682 ++words;
683
684 if (words == 2) {
685 printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
686 mv_getReg64int (DEST_REG));
687
688 return ARMul_DONE;
689 }
690 else
691 return ARMul_INC;
692 }
693 else {
694 /* Store just one word. */
695 /* cfstr32 */
696 *data = (ARMword) DSPregs[DEST_REG].lower.i;
697
698 printfdbg ("cfstr32 MEM = %d\n", (int) *data);
699
700 return ARMul_DONE;
701 }
702}
703
704unsigned
705DSPCDP4 (ARMul_State * state, unsigned type, ARMword instr)
706{
707 int opcode2;
708
709 opcode2 = BITS (5, 7);
710
711 switch (BITS (20, 21)) {
712 case 0:
713 switch (opcode2) {
714 case 0: /* cfcpys */
715 printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
716 DEST_REG, SRC1_REG,
717 DSPregs[SRC1_REG].upper.f);
718 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f;
719 break;
720
721 case 1: /* cfcpyd */
722 printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
723 DEST_REG, SRC1_REG,
724 mv_getRegDouble (SRC1_REG));
725 mv_setRegDouble (DEST_REG,
726 mv_getRegDouble (SRC1_REG));
727 break;
728
729 case 2: /* cfcvtds */
730 printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
731 DEST_REG, SRC1_REG,
732 (float) mv_getRegDouble (SRC1_REG));
733 DSPregs[DEST_REG].upper.f =
734 (float) mv_getRegDouble (SRC1_REG);
735 break;
736
737 case 3: /* cfcvtsd */
738 printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
739 DEST_REG, SRC1_REG,
740 (double) DSPregs[SRC1_REG].upper.f);
741 mv_setRegDouble (DEST_REG,
742 (double) DSPregs[SRC1_REG].upper.f);
743 break;
744
745 case 4: /* cfcvt32s */
746 printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
747 DEST_REG, SRC1_REG,
748 (float) DSPregs[SRC1_REG].lower.i);
749 DSPregs[DEST_REG].upper.f =
750 (float) DSPregs[SRC1_REG].lower.i;
751 break;
752
753 case 5: /* cfcvt32d */
754 printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
755 DEST_REG, SRC1_REG,
756 (double) DSPregs[SRC1_REG].lower.i);
757 mv_setRegDouble (DEST_REG,
758 (double) DSPregs[SRC1_REG].lower.i);
759 break;
760
761 case 6: /* cfcvt64s */
762 printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
763 DEST_REG, SRC1_REG,
764 (float) mv_getReg64int (SRC1_REG));
765 DSPregs[DEST_REG].upper.f =
766 (float) mv_getReg64int (SRC1_REG);
767 break;
768
769 case 7: /* cfcvt64d */
770 printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
771 DEST_REG, SRC1_REG,
772 (double) mv_getReg64int (SRC1_REG));
773 mv_setRegDouble (DEST_REG,
774 (double) mv_getReg64int (SRC1_REG));
775 break;
776 }
777 break;
778
779 case 1:
780 switch (opcode2) {
781 case 0: /* cfmuls */
782 printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
783 DEST_REG,
784 SRC1_REG,
785 DSPregs[SRC1_REG].upper.f *
786 DSPregs[SRC2_REG].upper.f);
787
788 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
789 * DSPregs[SRC2_REG].upper.f;
790 break;
791
792 case 1: /* cfmuld */
793 printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
794 DEST_REG,
795 SRC1_REG,
796 mv_getRegDouble (SRC1_REG) *
797 mv_getRegDouble (SRC2_REG));
798
799 mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG)
800 * mv_getRegDouble (SRC2_REG));
801 break;
802
803 default:
804 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n",
805 instr);
806 cirrus_not_implemented ("unknown");
807 break;
808 }
809 break;
810
811 case 3:
812 switch (opcode2) {
813 case 0: /* cfabss */
814 DSPregs[DEST_REG].upper.f =
815 (DSPregs[SRC1_REG].upper.f <
816 0.0F ? -DSPregs[SRC1_REG].upper.
817 f : DSPregs[SRC1_REG].upper.f);
818 printfdbg ("cfabss mvf%d = |mvf%d| = %f\n", DEST_REG,
819 SRC1_REG, DSPregs[DEST_REG].upper.f);
820 break;
821
822 case 1: /* cfabsd */
823 mv_setRegDouble (DEST_REG,
824 (mv_getRegDouble (SRC1_REG) < 0.0 ?
825 -mv_getRegDouble (SRC1_REG)
826 : mv_getRegDouble (SRC1_REG)));
827 printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
828 DEST_REG, SRC1_REG,
829 mv_getRegDouble (DEST_REG));
830 break;
831
832 case 2: /* cfnegs */
833 DSPregs[DEST_REG].upper.f =
834 -DSPregs[SRC1_REG].upper.f;
835 printfdbg ("cfnegs mvf%d = -mvf%d = %f\n", DEST_REG,
836 SRC1_REG, DSPregs[DEST_REG].upper.f);
837 break;
838
839 case 3: /* cfnegd */
840 mv_setRegDouble (DEST_REG,
841 -mv_getRegDouble (SRC1_REG));
842 printfdbg ("cfnegd mvd%d = -mvd%d = %g\n", DEST_REG,
843 mv_getRegDouble (DEST_REG));
844 break;
845
846 case 4: /* cfadds */
847 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
848 + DSPregs[SRC2_REG].upper.f;
849 printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
850 DEST_REG, SRC1_REG, SRC2_REG,
851 DSPregs[DEST_REG].upper.f);
852 break;
853
854 case 5: /* cfaddd */
855 mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG)
856 + mv_getRegDouble (SRC2_REG));
857 printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
858 DEST_REG,
859 SRC1_REG, SRC2_REG,
860 mv_getRegDouble (DEST_REG));
861 break;
862
863 case 6: /* cfsubs */
864 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
865 - DSPregs[SRC2_REG].upper.f;
866 printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
867 DEST_REG, SRC1_REG, SRC2_REG,
868 DSPregs[DEST_REG].upper.f);
869 break;
870
871 case 7: /* cfsubd */
872 mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG)
873 - mv_getRegDouble (SRC2_REG));
874 printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
875 DEST_REG,
876 SRC1_REG, SRC2_REG,
877 mv_getRegDouble (DEST_REG));
878 break;
879 }
880 break;
881
882 default:
883 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
884 cirrus_not_implemented ("unknown");
885 break;
886 }
887
888 return ARMul_DONE;
889}
890
891unsigned
892DSPCDP5 (ARMul_State * state, unsigned type, ARMword instr)
893{
894 int opcode2;
895 char shift;
896
897 opcode2 = BITS (5, 7);
898
899 /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */
900 shift = BITS (0, 3) | (BITS (5, 7)) << 4;
901 if (shift & 0x40)
902 shift |= 0xc0;
903
904 switch (BITS (20, 21)) {
905 case 0:
906 /* cfsh32 */
907 printfdbg ("cfsh32 %s amount=%d\n",
908 shift < 0 ? "right" : "left", shift);
909 if (shift < 0)
910 /* Negative shift is a right shift. */
911 DSPregs[DEST_REG].lower.i =
912 DSPregs[SRC1_REG].lower.i >> -shift;
913 else
914 /* Positive shift is a left shift. */
915 DSPregs[DEST_REG].lower.i =
916 DSPregs[SRC1_REG].lower.i << shift;
917 break;
918
919 case 1:
920 switch (opcode2) {
921 case 0: /* cfmul32 */
922 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
923 * DSPregs[SRC2_REG].lower.i;
924 printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
925 DEST_REG, SRC1_REG, SRC2_REG,
926 DSPregs[DEST_REG].lower.i);
927 break;
928
929 case 1: /* cfmul64 */
930 mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG)
931 * mv_getReg64int (SRC2_REG));
932 printfdbg
933 ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
934 DEST_REG, SRC1_REG, SRC2_REG,
935 mv_getReg64int (DEST_REG));
936 break;
937
938 case 2: /* cfmac32 */
939 DSPregs[DEST_REG].lower.i
940 +=
941 DSPregs[SRC1_REG].lower.i *
942 DSPregs[SRC2_REG].lower.i;
943 printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
944 DEST_REG, SRC1_REG, SRC2_REG,
945 DSPregs[DEST_REG].lower.i);
946 break;
947
948 case 3: /* cfmsc32 */
949 DSPregs[DEST_REG].lower.i
950 -=
951 DSPregs[SRC1_REG].lower.i *
952 DSPregs[SRC2_REG].lower.i;
953 printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
954 DEST_REG, SRC1_REG, SRC2_REG,
955 DSPregs[DEST_REG].lower.i);
956 break;
957
958 case 4: /* cfcvts32 */
959 /* fixme: this should round */
960 DSPregs[DEST_REG].lower.i =
961 (int) DSPregs[SRC1_REG].upper.f;
962 printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n", DEST_REG,
963 SRC1_REG, DSPregs[DEST_REG].lower.i);
964 break;
965
966 case 5: /* cfcvtd32 */
967 /* fixme: this should round */
968 DSPregs[DEST_REG].lower.i =
969 (int) mv_getRegDouble (SRC1_REG);
970 printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n", DEST_REG,
971 SRC1_REG, DSPregs[DEST_REG].lower.i);
972 break;
973
974 case 6: /* cftruncs32 */
975 DSPregs[DEST_REG].lower.i =
976 (int) DSPregs[SRC1_REG].upper.f;
977 printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
978 DEST_REG, SRC1_REG,
979 DSPregs[DEST_REG].lower.i);
980 break;
981
982 case 7: /* cftruncd32 */
983 DSPregs[DEST_REG].lower.i =
984 (int) mv_getRegDouble (SRC1_REG);
985 printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
986 DEST_REG, SRC1_REG,
987 DSPregs[DEST_REG].lower.i);
988 break;
989 }
990 break;
991
992 case 2:
993 /* cfsh64 */
994 printfdbg ("cfsh64\n");
995
996 if (shift < 0)
997 /* Negative shift is a right shift. */
998 mv_setReg64int (DEST_REG,
999 mv_getReg64int (SRC1_REG) >> -shift);
1000 else
1001 /* Positive shift is a left shift. */
1002 mv_setReg64int (DEST_REG,
1003 mv_getReg64int (SRC1_REG) << shift);
1004 printfdbg ("\t%llx\n", mv_getReg64int (DEST_REG));
1005 break;
1006
1007 case 3:
1008 switch (opcode2) {
1009 case 0: /* cfabs32 */
1010 DSPregs[DEST_REG].lower.i =
1011 (DSPregs[SRC1_REG].lower.i <
1012 0 ? -DSPregs[SRC1_REG].lower.
1013 i : DSPregs[SRC1_REG].lower.i);
1014 printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
1015 DEST_REG, SRC1_REG, SRC2_REG,
1016 DSPregs[DEST_REG].lower.i);
1017 break;
1018
1019 case 1: /* cfabs64 */
1020 mv_setReg64int (DEST_REG,
1021 (mv_getReg64int (SRC1_REG) < 0
1022 ? -mv_getReg64int (SRC1_REG)
1023 : mv_getReg64int (SRC1_REG)));
1024 printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
1025 DEST_REG, SRC1_REG, SRC2_REG,
1026 mv_getReg64int (DEST_REG));
1027 break;
1028
1029 case 2: /* cfneg32 */
1030 DSPregs[DEST_REG].lower.i =
1031 -DSPregs[SRC1_REG].lower.i;
1032 printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
1033 DEST_REG, SRC1_REG, SRC2_REG,
1034 DSPregs[DEST_REG].lower.i);
1035 break;
1036
1037 case 3: /* cfneg64 */
1038 mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG));
1039 printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
1040 DEST_REG, SRC1_REG, SRC2_REG,
1041 mv_getReg64int (DEST_REG));
1042 break;
1043
1044 case 4: /* cfadd32 */
1045 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
1046 + DSPregs[SRC2_REG].lower.i;
1047 printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
1048 DEST_REG, SRC1_REG, SRC2_REG,
1049 DSPregs[DEST_REG].lower.i);
1050 break;
1051
1052 case 5: /* cfadd64 */
1053 mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG)
1054 + mv_getReg64int (SRC2_REG));
1055 printfdbg
1056 ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
1057 DEST_REG, SRC1_REG, SRC2_REG,
1058 mv_getReg64int (DEST_REG));
1059 break;
1060
1061 case 6: /* cfsub32 */
1062 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
1063 - DSPregs[SRC2_REG].lower.i;
1064 printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
1065 DEST_REG, SRC1_REG, SRC2_REG,
1066 DSPregs[DEST_REG].lower.i);
1067 break;
1068
1069 case 7: /* cfsub64 */
1070 mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG)
1071 - mv_getReg64int (SRC2_REG));
1072 printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
1073 DEST_REG, SRC1_REG, SRC2_REG,
1074 mv_getReg64int (DEST_REG));
1075 break;
1076 }
1077 break;
1078
1079 default:
1080 fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
1081 cirrus_not_implemented ("unknown");
1082 break;
1083 }
1084
1085 return ARMul_DONE;
1086}
1087
1088unsigned
1089DSPCDP6 (ARMul_State * state, unsigned type, ARMword instr)
1090{
1091 int opcode2;
1092
1093 opcode2 = BITS (5, 7);
1094
1095 switch (BITS (20, 21)) {
1096 case 0:
1097 /* cfmadd32 */
1098 cirrus_not_implemented ("cfmadd32");
1099 break;
1100
1101 case 1:
1102 /* cfmsub32 */
1103 cirrus_not_implemented ("cfmsub32");
1104 break;
1105
1106 case 2:
1107 /* cfmadda32 */
1108 cirrus_not_implemented ("cfmadda32");
1109 break;
1110
1111 case 3:
1112 /* cfmsuba32 */
1113 cirrus_not_implemented ("cfmsuba32");
1114 break;
1115
1116 default:
1117 fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
1118 }
1119
1120 return ARMul_DONE;
1121}
1122
1123/* Conversion functions.
1124
1125 32-bit integers are stored in the LOWER half of a 64-bit physical
1126 register.
1127
1128 Single precision floats are stored in the UPPER half of a 64-bit
1129 physical register. */
1130
1131static double
1132mv_getRegDouble (int regnum)
1133{
1134 reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i;
1135 reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i;
1136 return reg_conv.d;
1137}
1138
1139static void
1140mv_setRegDouble (int regnum, double val)
1141{
1142 reg_conv.d = val;
1143 DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index];
1144 DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index];
1145}
1146
1147static long long
1148mv_getReg64int (int regnum)
1149{
1150 reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i;
1151 reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i;
1152 return reg_conv.ll;
1153}
1154
1155static void
1156mv_setReg64int (int regnum, long long val)
1157{
1158 reg_conv.ll = val;
1159 DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index];
1160 DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index];
1161}
1162
1163/* Compute LSW in a double and a long long. */
1164
1165void
1166mv_compute_host_endianness (ARMul_State * state)
1167{
1168 static union
1169 {
1170 long long ll;
1171 int ints[2];
1172 int i;
1173 double d;
1174 float floats[2];
1175 float f;
1176 } conv;
1177
1178 /* Calculate where's the LSW in a 64bit int. */
1179 conv.ll = 45;
1180
1181 if (conv.ints[0] == 0) {
1182 msw_int_index = 0;
1183 lsw_int_index = 1;
1184 }
1185 else {
1186 assert (conv.ints[1] == 0);
1187 msw_int_index = 1;
1188 lsw_int_index = 0;
1189 }
1190
1191 /* Calculate where's the LSW in a double. */
1192 conv.d = 3.0;
1193
1194 if (conv.ints[0] == 0) {
1195 msw_float_index = 0;
1196 lsw_float_index = 1;
1197 }
1198 else {
1199 assert (conv.ints[1] == 0);
1200 msw_float_index = 1;
1201 lsw_float_index = 0;
1202 }
1203
1204 printfdbg ("lsw_int_index %d\n", lsw_int_index);
1205 printfdbg ("lsw_float_index %d\n", lsw_float_index);
1206}
diff --git a/src/core/arm/interpreter/mmu/rb.cpp b/src/core/arm/interpreter/mmu/rb.cpp
new file mode 100644
index 000000000..07b11e311
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/rb.cpp
@@ -0,0 +1,126 @@
1#include "core/arm/interpreter/armdefs.h"
2
3/*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu*/
4ARMword rb_masks[] = {
5 0x0, //RB_INVALID
6 4, //RB_1
7 16, //RB_4
8 32, //RB_8
9};
10
11/*mmu_rb_init
12 * @rb_t :rb_t to init
13 * @num :number of entry
14 * */
15int
16mmu_rb_init (rb_s * rb_t, int num)
17{
18 int i;
19 rb_entry_t *entrys;
20
21 entrys = (rb_entry_t *) malloc (sizeof (*entrys) * num);
22 if (entrys == NULL) {
23 printf ("SKYEYE:mmu_rb_init malloc error\n");
24 return -1;
25 }
26 for (i = 0; i < num; i++) {
27 entrys[i].type = RB_INVALID;
28 entrys[i].fault = NO_FAULT;
29 }
30
31 rb_t->entrys = entrys;
32 rb_t->num = num;
33 return 0;
34}
35
36/*mmu_rb_exit*/
37void
38mmu_rb_exit (rb_s * rb_t)
39{
40 free (rb_t->entrys);
41};
42
43/*mmu_rb_search
44 * @rb_t :rb_t to serach
45 * @va :va address to math
46 *
47 * $ NULL :not match
48 * NO-NULL:
49 * */
50rb_entry_t *
51mmu_rb_search (rb_s * rb_t, ARMword va)
52{
53 int i;
54 rb_entry_t *rb = rb_t->entrys;
55
56 DEBUG_LOG(ARM11, "va = %x\n", va);
57 for (i = 0; i < rb_t->num; i++, rb++) {
58 //2004-06-06 lyh bug from wenye@cs.ucsb.edu
59 if (rb->type) {
60 if ((va >= rb->va)
61 && (va < (rb->va + rb_masks[rb->type])))
62 return rb;
63 }
64 }
65 return NULL;
66};
67
68void
69mmu_rb_invalidate_entry (rb_s * rb_t, int i)
70{
71 rb_t->entrys[i].type = RB_INVALID;
72}
73
74void
75mmu_rb_invalidate_all (rb_s * rb_t)
76{
77 int i;
78
79 for (i = 0; i < rb_t->num; i++)
80 mmu_rb_invalidate_entry (rb_t, i);
81};
82
83void
84mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb, int type, ARMword va)
85{
86 rb_entry_t *rb;
87 int i;
88 ARMword max_start, min_end;
89 fault_t fault;
90 tlb_entry_t *tlb;
91
92 /*align va according to type */
93 va &= ~(rb_masks[type] - 1);
94 /*invalidate all RB match [va, va + rb_masks[type]] */
95 for (rb = rb_t->entrys, i = 0; i < rb_t->num; i++, rb++) {
96 if (rb->type) {
97 max_start = max (va, rb->va);
98 min_end =
99 min (va + rb_masks[type],
100 rb->va + rb_masks[rb->type]);
101 if (max_start < min_end)
102 rb->type = RB_INVALID;
103 }
104 }
105 /*load word */
106 rb = &rb_t->entrys[i_rb];
107 rb->type = type;
108 fault = translate (state, va, D_TLB (), &tlb);
109 if (fault) {
110 rb->fault = fault;
111 return;
112 }
113 fault = check_access (state, va, tlb, 1);
114 if (fault) {
115 rb->fault = fault;
116 return;
117 }
118
119 rb->fault = NO_FAULT;
120 va = tlb_va_to_pa (tlb, va);
121 //2004-06-06 lyh bug from wenye@cs.ucsb.edu
122 for (i = 0; i < (rb_masks[type] / 4); i++, va += WORD_SIZE) {
123 //rb->data[i] = mem_read_word (state, va);
124 bus_read(32, va, &rb->data[i]);
125 };
126}
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/interpreter/mmu/sa_mmu.cpp b/src/core/arm/interpreter/mmu/sa_mmu.cpp
new file mode 100644
index 000000000..eff5002de
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/sa_mmu.cpp
@@ -0,0 +1,864 @@
1/*
2 armmmu.c - Memory Management Unit emulation.
3 ARMulator extensions for the ARM7100 family.
4 Copyright (C) 1999 Ben Williamson
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#include <assert.h>
22#include <string.h>
23
24#include "core/arm/interpreter/armdefs.h"
25
26/**
27 * The interface of read data from bus
28 */
29int bus_read(short size, int addr, uint32_t * value) {
30 ERROR_LOG(ARM11, "unimplemented bus_read");
31 return 0;
32}
33
34/**
35 * The interface of write data from bus
36 */
37int bus_write(short size, int addr, uint32_t value) {
38 ERROR_LOG(ARM11, "unimplemented bus_write");
39 return 0;
40}
41
42
43typedef struct sa_mmu_desc_s
44{
45 int i_tlb;
46 cache_desc_t i_cache;
47
48 int d_tlb;
49 cache_desc_t main_d_cache;
50 cache_desc_t mini_d_cache;
51 int rb;
52 wb_desc_t wb;
53} sa_mmu_desc_t;
54
55static sa_mmu_desc_t sa11xx_mmu_desc = {
56 32,
57 {32, 32, 16, CACHE_WRITE_BACK},
58
59 32,
60 {32, 32, 8, CACHE_WRITE_BACK},
61 {32, 2, 8, CACHE_WRITE_BACK},
62 4,
63 //{8, 4}, for word size
64 {8, 16}, //for byte size, chy 2003-07-11
65};
66
67static fault_t sa_mmu_write (ARMul_State * state, ARMword va, ARMword data,
68 ARMword datatype);
69static fault_t sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
70 ARMword datatype);
71static fault_t update_cache (ARMul_State * state, ARMword va, ARMword data,
72 ARMword datatype, cache_line_t * cache,
73 cache_s * cache_t, ARMword real_va);
74
75void
76mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa,
77 ARMbyte * data, int n);
78int
79sa_mmu_init (ARMul_State * state)
80{
81 sa_mmu_desc_t *desc;
82 cache_desc_t *c_desc;
83
84 state->mmu.control = 0x70;
85 state->mmu.translation_table_base = 0xDEADC0DE;
86 state->mmu.domain_access_control = 0xDEADC0DE;
87 state->mmu.fault_status = 0;
88 state->mmu.fault_address = 0;
89 state->mmu.process_id = 0;
90
91 desc = &sa11xx_mmu_desc;
92 if (mmu_tlb_init (I_TLB (), desc->i_tlb)) {
93 ERROR_LOG(ARM11, "i_tlb init %d\n", -1);
94 goto i_tlb_init_error;
95 }
96
97 c_desc = &desc->i_cache;
98 if (mmu_cache_init (I_CACHE (), c_desc->width, c_desc->way,
99 c_desc->set, c_desc->w_mode)) {
100 ERROR_LOG(ARM11, "i_cache init %d\n", -1);
101 goto i_cache_init_error;
102 }
103
104 if (mmu_tlb_init (D_TLB (), desc->d_tlb)) {
105 ERROR_LOG(ARM11, "d_tlb init %d\n", -1);
106 goto d_tlb_init_error;
107 }
108
109 c_desc = &desc->main_d_cache;
110 if (mmu_cache_init (MAIN_D_CACHE (), c_desc->width, c_desc->way,
111 c_desc->set, c_desc->w_mode)) {
112 ERROR_LOG(ARM11, "main_d_cache init %d\n", -1);
113 goto main_d_cache_init_error;
114 }
115
116 c_desc = &desc->mini_d_cache;
117 if (mmu_cache_init (MINI_D_CACHE (), c_desc->width, c_desc->way,
118 c_desc->set, c_desc->w_mode)) {
119 ERROR_LOG(ARM11, "mini_d_cache init %d\n", -1);
120 goto mini_d_cache_init_error;
121 }
122
123 if (mmu_wb_init (WB (), desc->wb.num, desc->wb.nb)) {
124 ERROR_LOG(ARM11, "wb init %d\n", -1);
125 goto wb_init_error;
126 }
127
128 if (mmu_rb_init (RB (), desc->rb)) {
129 ERROR_LOG(ARM11, "rb init %d\n", -1);
130 goto rb_init_error;
131 }
132 return 0;
133
134 rb_init_error:
135 mmu_wb_exit (WB ());
136 wb_init_error:
137 mmu_cache_exit (MINI_D_CACHE ());
138 mini_d_cache_init_error:
139 mmu_cache_exit (MAIN_D_CACHE ());
140 main_d_cache_init_error:
141 mmu_tlb_exit (D_TLB ());
142 d_tlb_init_error:
143 mmu_cache_exit (I_CACHE ());
144 i_cache_init_error:
145 mmu_tlb_exit (I_TLB ());
146 i_tlb_init_error:
147 return -1;
148}
149
150void
151sa_mmu_exit (ARMul_State * state)
152{
153 mmu_rb_exit (RB ());
154 mmu_wb_exit (WB ());
155 mmu_cache_exit (MINI_D_CACHE ());
156 mmu_cache_exit (MAIN_D_CACHE ());
157 mmu_tlb_exit (D_TLB ());
158 mmu_cache_exit (I_CACHE ());
159 mmu_tlb_exit (I_TLB ());
160};
161
162
163static fault_t
164sa_mmu_load_instr (ARMul_State * state, ARMword va, ARMword * instr)
165{
166 fault_t fault;
167 tlb_entry_t *tlb;
168 cache_line_t *cache;
169 int c; //cache bit
170 ARMword pa; //physical addr
171
172 static int debug_count = 0; //used for debug
173
174 DEBUG_LOG(ARM11, "va = %x\n", va);
175
176 va = mmu_pid_va_map (va);
177 if (MMU_Enabled) {
178 /*align check */
179 if ((va & (WORD_SIZE - 1)) && MMU_Aligned) {
180 DEBUG_LOG(ARM11, "align\n");
181 return ALIGNMENT_FAULT;
182 }
183 else
184 va &= ~(WORD_SIZE - 1);
185
186 /*translate tlb */
187 fault = translate (state, va, I_TLB (), &tlb);
188 if (fault) {
189 DEBUG_LOG(ARM11, "translate\n");
190 return fault;
191 }
192
193 /*check access */
194 fault = check_access (state, va, tlb, 1);
195 if (fault) {
196 DEBUG_LOG(ARM11, "check_fault\n");
197 return fault;
198 }
199 }
200
201 /*search cache no matter MMU enabled/disabled */
202 cache = mmu_cache_search (state, I_CACHE (), va);
203 if (cache) {
204 *instr = cache->data[va_cache_index (va, I_CACHE ())];
205 return NO_FAULT;
206 }
207
208 /*if MMU disabled or C flag is set alloc cache */
209 if (MMU_Disabled) {
210 c = 1;
211 pa = va;
212 }
213 else {
214 c = tlb_c_flag (tlb);
215 pa = tlb_va_to_pa (tlb, va);
216 }
217
218 if (c) {
219 int index;
220
221 debug_count++;
222 cache = mmu_cache_alloc (state, I_CACHE (), va, pa);
223 index = va_cache_index (va, I_CACHE ());
224 *instr = cache->data[va_cache_index (va, I_CACHE ())];
225 }
226 else
227 //*instr = mem_read_word (state, pa);
228 bus_read(32, pa, instr);
229
230 return NO_FAULT;
231};
232
233
234
235static fault_t
236sa_mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data)
237{
238 //ARMword temp,offset;
239 fault_t fault;
240 fault = sa_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE);
241 return fault;
242}
243
244static fault_t
245sa_mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data)
246{
247 //ARMword temp,offset;
248 fault_t fault;
249 fault = sa_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE);
250 return fault;
251}
252
253static fault_t
254sa_mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data)
255{
256 return sa_mmu_read (state, virt_addr, data, ARM_WORD_TYPE);
257}
258
259
260
261
262static fault_t
263sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
264 ARMword datatype)
265{
266 fault_t fault;
267 rb_entry_t *rb;
268 tlb_entry_t *tlb;
269 cache_line_t *cache;
270 ARMword pa, real_va, temp, offset;
271
272 DEBUG_LOG(ARM11, "va = %x\n", va);
273
274 va = mmu_pid_va_map (va);
275 real_va = va;
276 /*if MMU disabled, memory_read */
277 if (MMU_Disabled) {
278 //*data = mem_read_word(state, va);
279 if (datatype == ARM_BYTE_TYPE)
280 //*data = mem_read_byte (state, va);
281 bus_read(8, va, data);
282 else if (datatype == ARM_HALFWORD_TYPE)
283 //*data = mem_read_halfword (state, va);
284 bus_read(16, va, data);
285 else if (datatype == ARM_WORD_TYPE)
286 //*data = mem_read_word (state, va);
287 bus_read(32, va, data);
288 else {
289 printf ("SKYEYE:1 sa_mmu_read error: unknown data type %d\n", datatype);
290 // skyeye_exit (-1);
291 }
292
293 return NO_FAULT;
294 }
295
296 /*align check */
297 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
298 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
299 DEBUG_LOG(ARM11, "align\n");
300 return ALIGNMENT_FAULT;
301 } // else
302
303 va &= ~(WORD_SIZE - 1);
304
305 /*translate va to tlb */
306 fault = translate (state, va, D_TLB (), &tlb);
307 if (fault) {
308 DEBUG_LOG(ARM11, "translate\n");
309 return fault;
310 }
311 /*check access permission */
312 fault = check_access (state, va, tlb, 1);
313 if (fault)
314 return fault;
315 /*search in read buffer */
316 rb = mmu_rb_search (RB (), va);
317 if (rb) {
318 if (rb->fault)
319 return rb->fault;
320 *data = rb->data[(va & (rb_masks[rb->type] - 1)) >> WORD_SHT];
321 goto datatrans;
322 //return 0;
323 };
324 /*search main cache */
325 cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
326 if (cache) {
327 *data = cache->data[va_cache_index (va, MAIN_D_CACHE ())];
328 goto datatrans;
329 //return 0;
330 }
331 /*search mini cache */
332 cache = mmu_cache_search (state, MINI_D_CACHE (), va);
333 if (cache) {
334 *data = cache->data[va_cache_index (va, MINI_D_CACHE ())];
335 goto datatrans;
336 //return 0;
337 }
338
339 /*get phy_addr */
340 pa = tlb_va_to_pa (tlb, va);
341 if ((pa >= 0xe0000000) && (pa < 0xe8000000)) {
342 if (tlb_c_flag (tlb)) {
343 if (tlb_b_flag (tlb)) {
344 mmu_cache_soft_flush (state, MAIN_D_CACHE (),
345 pa);
346 }
347 else {
348 mmu_cache_soft_flush (state, MINI_D_CACHE (),
349 pa);
350 }
351 }
352 return NO_FAULT;
353 }
354
355 /*if Buffer, drain Write Buffer first */
356 if (tlb_b_flag (tlb))
357 mmu_wb_drain_all (state, WB ());
358
359 /*alloc cache or mem_read */
360 if (tlb_c_flag (tlb) && MMU_DCacheEnabled) {
361 cache_s *cache_t;
362
363 if (tlb_b_flag (tlb))
364 cache_t = MAIN_D_CACHE ();
365 else
366 cache_t = MINI_D_CACHE ();
367 cache = mmu_cache_alloc (state, cache_t, va, pa);
368 *data = cache->data[va_cache_index (va, cache_t)];
369 }
370 else {
371 //*data = mem_read_word(state, pa);
372 if (datatype == ARM_BYTE_TYPE)
373 //*data = mem_read_byte (state, pa | (real_va & 3));
374 bus_read(8, pa | (real_va & 3), data);
375 else if (datatype == ARM_HALFWORD_TYPE)
376 //*data = mem_read_halfword (state, pa | (real_va & 2));
377 bus_read(16, pa | (real_va & 2), data);
378 else if (datatype == ARM_WORD_TYPE)
379 //*data = mem_read_word (state, pa);
380 bus_read(32, pa, data);
381 else {
382 printf ("SKYEYE:2 sa_mmu_read error: unknown data type %d\n", datatype);
383 // skyeye_exit (-1);
384 }
385 return NO_FAULT;
386 }
387
388
389 datatrans:
390 if (datatype == ARM_HALFWORD_TYPE) {
391 temp = *data;
392 offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
393 *data = (temp >> offset) & 0xffff;
394 }
395 else if (datatype == ARM_BYTE_TYPE) {
396 temp = *data;
397 offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
398 *data = (temp >> offset & 0xffL);
399 }
400 end:
401 return NO_FAULT;
402}
403
404
405static fault_t
406sa_mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data)
407{
408 return sa_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE);
409}
410
411static fault_t
412sa_mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data)
413{
414 return sa_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE);
415}
416
417static fault_t
418sa_mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data)
419{
420 return sa_mmu_write (state, virt_addr, data, ARM_WORD_TYPE);
421}
422
423
424
425static fault_t
426sa_mmu_write (ARMul_State * state, ARMword va, ARMword data, ARMword datatype)
427{
428 tlb_entry_t *tlb;
429 cache_line_t *cache;
430 int b;
431 ARMword pa, real_va;
432 fault_t fault;
433
434 DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data);
435 va = mmu_pid_va_map (va);
436 real_va = va;
437
438 /*search instruction cache */
439 cache = mmu_cache_search (state, I_CACHE (), va);
440 if (cache) {
441 update_cache (state, va, data, datatype, cache, I_CACHE (),
442 real_va);
443 }
444
445 if (MMU_Disabled) {
446 //mem_write_word(state, va, data);
447 if (datatype == ARM_BYTE_TYPE)
448 //mem_write_byte (state, va, data);
449 bus_write(8, va, data);
450 else if (datatype == ARM_HALFWORD_TYPE)
451 //mem_write_halfword (state, va, data);
452 bus_write(16, va, data);
453 else if (datatype == ARM_WORD_TYPE)
454 //mem_write_word (state, va, data);
455 bus_write(32, va, data);
456 else {
457 printf ("SKYEYE:1 sa_mmu_write error: unknown data type %d\n", datatype);
458 // skyeye_exit (-1);
459 }
460
461 return NO_FAULT;
462 }
463 /*align check */
464 //if ((va & (WORD_SIZE - 1)) && MMU_Aligned){
465 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
466 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
467 DEBUG_LOG(ARM11, "align\n");
468 return ALIGNMENT_FAULT;
469 } //else
470 va &= ~(WORD_SIZE - 1);
471 /*tlb translate */
472 fault = translate (state, va, D_TLB (), &tlb);
473 if (fault) {
474 DEBUG_LOG(ARM11, "translate\n");
475 return fault;
476 }
477 /*tlb check access */
478 fault = check_access (state, va, tlb, 0);
479 if (fault) {
480 DEBUG_LOG(ARM11, "check_access\n");
481 return fault;
482 }
483 /*search main cache */
484 cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
485 if (cache) {
486 update_cache (state, va, data, datatype, cache,
487 MAIN_D_CACHE (), real_va);
488 }
489 else {
490 /*search mini cache */
491 cache = mmu_cache_search (state, MINI_D_CACHE (), va);
492 if (cache) {
493 update_cache (state, va, data, datatype, cache,
494 MINI_D_CACHE (), real_va);
495 }
496 }
497
498 if (!cache) {
499 b = tlb_b_flag (tlb);
500 pa = tlb_va_to_pa (tlb, va);
501 if (b) {
502 if (MMU_WBEnabled) {
503 if (datatype == ARM_WORD_TYPE)
504 mmu_wb_write_bytes (state, WB (), pa,
505 (ARMbyte*)&data, 4);
506 else if (datatype == ARM_HALFWORD_TYPE)
507 mmu_wb_write_bytes (state, WB (),
508 (pa |
509 (real_va & 2)),
510 (ARMbyte*)&data, 2);
511 else if (datatype == ARM_BYTE_TYPE)
512 mmu_wb_write_bytes (state, WB (),
513 (pa |
514 (real_va & 3)),
515 (ARMbyte*)&data, 1);
516
517 }
518 else {
519 if (datatype == ARM_WORD_TYPE)
520 //mem_write_word (state, pa, data);
521 bus_write(32, pa, data);
522 else if (datatype == ARM_HALFWORD_TYPE)
523 /*
524 mem_write_halfword (state,
525 (pa |
526 (real_va & 2)),
527 data);
528 */
529 bus_write(16, pa | (real_va & 2), data);
530 else if (datatype == ARM_BYTE_TYPE)
531 /*
532 mem_write_byte (state,
533 (pa | (real_va & 3)),
534 data);
535 */
536 bus_write(8, pa | (real_va & 3), data);
537 }
538 }
539 else {
540 mmu_wb_drain_all (state, WB ());
541
542 if (datatype == ARM_WORD_TYPE)
543 //mem_write_word (state, pa, data);
544 bus_write(32, pa, data);
545 else if (datatype == ARM_HALFWORD_TYPE)
546 /*
547 mem_write_halfword (state,
548 (pa | (real_va & 2)),
549 data);
550 */
551 bus_write(16, pa | (real_va & 2), data);
552 else if (datatype == ARM_BYTE_TYPE)
553 /*
554 mem_write_byte (state, (pa | (real_va & 3)),
555 data);
556 */
557 bus_write(8, pa | (real_va & 3), data);
558 }
559 }
560 return NO_FAULT;
561}
562
563static fault_t
564update_cache (ARMul_State * state, ARMword va, ARMword data, ARMword datatype,
565 cache_line_t * cache, cache_s * cache_t, ARMword real_va)
566{
567 ARMword temp, offset;
568
569 ARMword index = va_cache_index (va, cache_t);
570
571 //cache->data[index] = data;
572
573 if (datatype == ARM_WORD_TYPE)
574 cache->data[index] = data;
575 else if (datatype == ARM_HALFWORD_TYPE) {
576 temp = cache->data[index];
577 offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
578 cache->data[index] =
579 (temp & ~(0xffffL << offset)) | ((data & 0xffffL) <<
580 offset);
581 }
582 else if (datatype == ARM_BYTE_TYPE) {
583 temp = cache->data[index];
584 offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
585 cache->data[index] =
586 (temp & ~(0xffL << offset)) | ((data & 0xffL) <<
587 offset);
588 }
589
590 if (index < (cache_t->width >> (WORD_SHT + 1)))
591 cache->tag |= TAG_FIRST_HALF_DIRTY;
592 else
593 cache->tag |= TAG_LAST_HALF_DIRTY;
594
595 return NO_FAULT;
596}
597
598ARMword
599sa_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
600{
601 mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15);
602 ARMword data;
603
604 switch (creg) {
605 case MMU_ID:
606// printf("mmu_mrc read ID ");
607 data = 0x41007100; /* v3 */
608 data = state->cpu->cpu_val;
609 break;
610 case MMU_CONTROL:
611// printf("mmu_mrc read CONTROL");
612 data = state->mmu.control;
613 break;
614 case MMU_TRANSLATION_TABLE_BASE:
615// printf("mmu_mrc read TTB ");
616 data = state->mmu.translation_table_base;
617 break;
618 case MMU_DOMAIN_ACCESS_CONTROL:
619// printf("mmu_mrc read DACR ");
620 data = state->mmu.domain_access_control;
621 break;
622 case MMU_FAULT_STATUS:
623// printf("mmu_mrc read FSR ");
624 data = state->mmu.fault_status;
625 break;
626 case MMU_FAULT_ADDRESS:
627// printf("mmu_mrc read FAR ");
628 data = state->mmu.fault_address;
629 break;
630 case MMU_PID:
631 data = state->mmu.process_id;
632 default:
633 printf ("mmu_mrc read UNKNOWN - reg %d\n", creg);
634 data = 0;
635 break;
636 }
637// printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]);
638 *value = data;
639 return data;
640}
641
642void
643sa_mmu_cache_ops (ARMul_State * state, ARMword instr, ARMword value)
644{
645 int CRm, OPC_2;
646
647 CRm = BITS (0, 3);
648 OPC_2 = BITS (5, 7);
649
650 if (OPC_2 == 0 && CRm == 7) {
651 mmu_cache_invalidate_all (state, I_CACHE ());
652 mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
653 mmu_cache_invalidate_all (state, MINI_D_CACHE ());
654 return;
655 }
656
657 if (OPC_2 == 0 && CRm == 5) {
658 mmu_cache_invalidate_all (state, I_CACHE ());
659 return;
660 }
661
662 if (OPC_2 == 0 && CRm == 6) {
663 mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
664 mmu_cache_invalidate_all (state, MINI_D_CACHE ());
665 return;
666 }
667
668 if (OPC_2 == 1 && CRm == 6) {
669 mmu_cache_invalidate (state, MAIN_D_CACHE (), value);
670 mmu_cache_invalidate (state, MINI_D_CACHE (), value);
671 return;
672 }
673
674 if (OPC_2 == 1 && CRm == 0xa) {
675 mmu_cache_clean (state, MAIN_D_CACHE (), value);
676 mmu_cache_clean (state, MINI_D_CACHE (), value);
677 return;
678 }
679
680 if (OPC_2 == 4 && CRm == 0xa) {
681 mmu_wb_drain_all (state, WB ());
682 return;
683 }
684 ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
685}
686
687static void
688sa_mmu_tlb_ops (ARMul_State * state, ARMword instr, ARMword value)
689{
690 int CRm, OPC_2;
691
692 CRm = BITS (0, 3);
693 OPC_2 = BITS (5, 7);
694
695
696 if (OPC_2 == 0 && CRm == 0x7) {
697 mmu_tlb_invalidate_all (state, I_TLB ());
698 mmu_tlb_invalidate_all (state, D_TLB ());
699 return;
700 }
701
702 if (OPC_2 == 0 && CRm == 0x5) {
703 mmu_tlb_invalidate_all (state, I_TLB ());
704 return;
705 }
706
707 if (OPC_2 == 0 && CRm == 0x6) {
708 mmu_tlb_invalidate_all (state, D_TLB ());
709 return;
710 }
711
712 if (OPC_2 == 1 && CRm == 0x6) {
713 mmu_tlb_invalidate_entry (state, D_TLB (), value);
714 return;
715 }
716
717 ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
718}
719
720static void
721sa_mmu_rb_ops (ARMul_State * state, ARMword instr, ARMword value)
722{
723 int CRm, OPC_2;
724
725 CRm = BITS (0, 3);
726 OPC_2 = BITS (5, 7);
727
728 if (OPC_2 == 0x0 && CRm == 0x0) {
729 mmu_rb_invalidate_all (RB ());
730 return;
731 }
732
733 if (OPC_2 == 0x2) {
734 int idx = CRm & 0x3;
735 int type = ((CRm >> 2) & 0x3) + 1;
736
737 if ((idx < 4) && (type < 4))
738 mmu_rb_load (state, RB (), idx, type, value);
739 return;
740 }
741
742 if ((OPC_2 == 1) && (CRm < 4)) {
743 mmu_rb_invalidate_entry (RB (), CRm);
744 return;
745 }
746
747 ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
748}
749
750static ARMword
751sa_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
752{
753 mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15);
754 if (!strncmp (state->cpu->cpu_arch_name, "armv4", 5)) {
755 switch (creg) {
756 case MMU_CONTROL:
757// printf("mmu_mcr wrote CONTROL ");
758 state->mmu.control = (value | 0x70) & 0xFFFD;
759 break;
760 case MMU_TRANSLATION_TABLE_BASE:
761// printf("mmu_mcr wrote TTB ");
762 state->mmu.translation_table_base =
763 value & 0xFFFFC000;
764 break;
765 case MMU_DOMAIN_ACCESS_CONTROL:
766// printf("mmu_mcr wrote DACR ");
767 state->mmu.domain_access_control = value;
768 break;
769
770 case MMU_FAULT_STATUS:
771 state->mmu.fault_status = value & 0xFF;
772 break;
773 case MMU_FAULT_ADDRESS:
774 state->mmu.fault_address = value;
775 break;
776
777 case MMU_CACHE_OPS:
778 sa_mmu_cache_ops (state, instr, value);
779 break;
780 case MMU_TLB_OPS:
781 sa_mmu_tlb_ops (state, instr, value);
782 break;
783 case MMU_SA_RB_OPS:
784 sa_mmu_rb_ops (state, instr, value);
785 break;
786 case MMU_SA_DEBUG:
787 break;
788 case MMU_SA_CP15_R15:
789 break;
790 case MMU_PID:
791 //2004-06-06 lyh, bug provided by wen ye wenye@cs.ucsb.edu
792 state->mmu.process_id = value & 0x7e000000;
793 break;
794
795 default:
796 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
797 break;
798 }
799 }
800 return 0;
801}
802
803//teawater add for arm2x86 2005.06.24-------------------------------------------
804static int
805sa_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr)
806{
807 fault_t fault;
808 tlb_entry_t *tlb;
809
810 virt_addr = mmu_pid_va_map (virt_addr);
811 if (MMU_Enabled) {
812
813 /*align check */
814 if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) {
815 DEBUG_LOG(ARM11, "align\n");
816 return ALIGNMENT_FAULT;
817 }
818 else
819 virt_addr &= ~(WORD_SIZE - 1);
820
821 /*translate tlb */
822 fault = translate (state, virt_addr, I_TLB (), &tlb);
823 if (fault) {
824 DEBUG_LOG(ARM11, "translate\n");
825 return fault;
826 }
827
828 /*check access */
829 fault = check_access (state, virt_addr, tlb, 1);
830 if (fault) {
831 DEBUG_LOG(ARM11, "check_fault\n");
832 return fault;
833 }
834 }
835
836 if (MMU_Disabled) {
837 *phys_addr = virt_addr;
838 }
839 else {
840 *phys_addr = tlb_va_to_pa (tlb, virt_addr);
841 }
842
843 return (0);
844}
845
846//AJ2D--------------------------------------------------------------------------
847
848/*sa mmu_ops_t*/
849mmu_ops_t sa_mmu_ops = {
850 sa_mmu_init,
851 sa_mmu_exit,
852 sa_mmu_read_byte,
853 sa_mmu_write_byte,
854 sa_mmu_read_halfword,
855 sa_mmu_write_halfword,
856 sa_mmu_read_word,
857 sa_mmu_write_word,
858 sa_mmu_load_instr,
859 sa_mmu_mcr,
860 sa_mmu_mrc,
861//teawater add for arm2x86 2005.06.24-------------------------------------------
862 sa_mmu_v2p_dbct,
863//AJ2D--------------------------------------------------------------------------
864};
diff --git a/src/core/arm/interpreter/mmu/sa_mmu.h b/src/core/arm/interpreter/mmu/sa_mmu.h
new file mode 100644
index 000000000..64b1c5470
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/sa_mmu.h
@@ -0,0 +1,58 @@
1/*
2 sa_mmu.h - StrongARM Memory Management Unit emulation.
3 ARMulator extensions for SkyEye.
4 <lyhost@263.net>
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 _SA_MMU_H_
22#define _SA_MMU_H_
23
24
25/**
26 * The interface of read data from bus
27 */
28int bus_read(short size, int addr, uint32_t * value);
29
30/**
31 * The interface of write data from bus
32 */
33int bus_write(short size, int addr, uint32_t value);
34
35
36typedef struct sa_mmu_s
37{
38 tlb_s i_tlb;
39 cache_s i_cache;
40
41 tlb_s d_tlb;
42 cache_s main_d_cache;
43 cache_s mini_d_cache;
44 rb_s rb_t;
45 wb_s wb_t;
46} sa_mmu_t;
47
48#define I_TLB() (&state->mmu.u.sa_mmu.i_tlb)
49#define I_CACHE() (&state->mmu.u.sa_mmu.i_cache)
50
51#define D_TLB() (&state->mmu.u.sa_mmu.d_tlb)
52#define MAIN_D_CACHE() (&state->mmu.u.sa_mmu.main_d_cache)
53#define MINI_D_CACHE() (&state->mmu.u.sa_mmu.mini_d_cache)
54#define WB() (&state->mmu.u.sa_mmu.wb_t)
55#define RB() (&state->mmu.u.sa_mmu.rb_t)
56
57extern mmu_ops_t sa_mmu_ops;
58#endif /*_SA_MMU_H_*/
diff --git a/src/core/arm/interpreter/mmu/tlb.cpp b/src/core/arm/interpreter/mmu/tlb.cpp
new file mode 100644
index 000000000..ca60ac1a1
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/tlb.cpp
@@ -0,0 +1,307 @@
1#include <assert.h>
2
3#include "core/arm/interpreter/armdefs.h"
4
5ARMword tlb_masks[] = {
6 0x00000000, /* TLB_INVALID */
7 0xFFFFF000, /* TLB_SMALLPAGE */
8 0xFFFF0000, /* TLB_LARGEPAGE */
9 0xFFF00000, /* TLB_SECTION */
10 0xFFFFF000, /*TLB_ESMALLPAGE, have TEX attirbute, only for XScale */
11 0xFFFFFC00 /* TLB_TINYPAGE */
12};
13
14/* This function encodes table 8-2 Interpreting AP bits,
15 returning non-zero if access is allowed. */
16static int
17check_perms (ARMul_State * state, int ap, int read)
18{
19 int s, r, user;
20
21 s = state->mmu.control & CONTROL_SYSTEM;
22 r = state->mmu.control & CONTROL_ROM;
23 //chy 2006-02-15 , should consider system mode, don't conside 26bit mode
24 user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE);
25
26 switch (ap) {
27 case 0:
28 return read && ((s && !user) || r);
29 case 1:
30 return !user;
31 case 2:
32 return read || !user;
33 case 3:
34 return 1;
35 }
36 return 0;
37}
38
39fault_t
40check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,
41 int read)
42{
43 int access;
44
45 state->mmu.last_domain = tlb->domain;
46 access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3;
47 if ((access == 0) || (access == 2)) {
48 /* It's unclear from the documentation whether this
49 should always raise a section domain fault, or if
50 it should be a page domain fault in the case of an
51 L1 that describes a page table. In the ARM710T
52 datasheets, "Figure 8-9: Sequence for checking faults"
53 seems to indicate the former, while "Table 8-4: Priority
54 encoding of fault status" gives a value for FS[3210] in
55 the event of a domain fault for a page. Hmm. */
56 return SECTION_DOMAIN_FAULT;
57 }
58 if (access == 1) {
59 /* client access - check perms */
60 int subpage, ap;
61
62 switch (tlb->mapping) {
63 /*ks 2004-05-09
64 * only for XScale
65 * Extend Small Page(ESP) Format
66 * 31-12 bits the base addr of ESP
67 * 11-10 bits SBZ
68 * 9-6 bits TEX
69 * 5-4 bits AP
70 * 3 bit C
71 * 2 bit B
72 * 1-0 bits 11
73 * */
74 case TLB_ESMALLPAGE: //xj
75 subpage = 0;
76 //printf("TLB_ESMALLPAGE virt_addr=0x%x \n",virt_addr );
77 break;
78
79 case TLB_TINYPAGE:
80 subpage = 0;
81 //printf("TLB_TINYPAGE virt_addr=0x%x \n",virt_addr );
82 break;
83
84 case TLB_SMALLPAGE:
85 subpage = (virt_addr >> 10) & 3;
86 break;
87 case TLB_LARGEPAGE:
88 subpage = (virt_addr >> 14) & 3;
89 break;
90 case TLB_SECTION:
91 subpage = 3;
92 break;
93 default:
94 assert (0);
95 subpage = 0; /* cleans a warning */
96 }
97 ap = (tlb->perms >> (subpage * 2 + 4)) & 3;
98 if (!check_perms (state, ap, read)) {
99 if (tlb->mapping == TLB_SECTION) {
100 return SECTION_PERMISSION_FAULT;
101 }
102 else {
103 return SUBPAGE_PERMISSION_FAULT;
104 }
105 }
106 }
107 else { /* access == 3 */
108 /* manager access - don't check perms */
109 }
110 return NO_FAULT;
111}
112
113fault_t
114translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t,
115 tlb_entry_t ** tlb)
116{
117 *tlb = mmu_tlb_search (state, tlb_t, virt_addr);
118 if (!*tlb) {
119 /* walk the translation tables */
120 ARMword l1addr, l1desc;
121 tlb_entry_t entry;
122
123 l1addr = state->mmu.translation_table_base & 0xFFFFC000;
124 l1addr = (l1addr | (virt_addr >> 18)) & ~3;
125 //l1desc = mem_read_word (state, l1addr);
126 bus_read(32, l1addr, &l1desc);
127 switch (l1desc & 3) {
128 case 0:
129 /*
130 * according to Figure 3-9 Sequence for checking faults in arm manual,
131 * section translation fault should be returned here.
132 */
133 {
134 return SECTION_TRANSLATION_FAULT;
135 }
136 case 3:
137 /* fine page table */
138 // dcl 2006-01-08
139 {
140 ARMword l2addr, l2desc;
141
142 l2addr = l1desc & 0xFFFFF000;
143 l2addr = (l2addr |
144 ((virt_addr & 0x000FFC00) >> 8)) &
145 ~3;
146 //l2desc = mem_read_word (state, l2addr);
147 bus_read(32, l2addr, &l2desc);
148
149 entry.virt_addr = virt_addr;
150 entry.phys_addr = l2desc;
151 entry.perms = l2desc & 0x00000FFC;
152 entry.domain = (l1desc >> 5) & 0x0000000F;
153 switch (l2desc & 3) {
154 case 0:
155 state->mmu.last_domain = entry.domain;
156 return PAGE_TRANSLATION_FAULT;
157 case 3:
158 entry.mapping = TLB_TINYPAGE;
159 break;
160 case 1:
161 // this is untested
162 entry.mapping = TLB_LARGEPAGE;
163 break;
164 case 2:
165 // this is untested
166 entry.mapping = TLB_SMALLPAGE;
167 break;
168 }
169 }
170 break;
171 case 1:
172 /* coarse page table */
173 {
174 ARMword l2addr, l2desc;
175
176 l2addr = l1desc & 0xFFFFFC00;
177 l2addr = (l2addr |
178 ((virt_addr & 0x000FF000) >> 10)) &
179 ~3;
180 //l2desc = mem_read_word (state, l2addr);
181 bus_read(32, l2addr, &l2desc);
182
183 entry.virt_addr = virt_addr;
184 entry.phys_addr = l2desc;
185 entry.perms = l2desc & 0x00000FFC;
186 entry.domain = (l1desc >> 5) & 0x0000000F;
187 //printf("SKYEYE:PAGE virt_addr = %x,l1desc=%x,phys_addr=%x\n",virt_addr,l1desc,entry.phys_addr);
188 //chy 2003-09-02 for xscale
189 switch (l2desc & 3) {
190 case 0:
191 state->mmu.last_domain = entry.domain;
192 return PAGE_TRANSLATION_FAULT;
193 case 3:
194 if (!state->is_XScale) {
195 state->mmu.last_domain =
196 entry.domain;
197 return PAGE_TRANSLATION_FAULT;
198 };
199 //ks 2004-05-09 xscale shold use Extend Small Page
200 //entry.mapping = TLB_SMALLPAGE;
201 entry.mapping = TLB_ESMALLPAGE; //xj
202 break;
203 case 1:
204 entry.mapping = TLB_LARGEPAGE;
205 break;
206 case 2:
207 entry.mapping = TLB_SMALLPAGE;
208 break;
209 }
210 }
211 break;
212 case 2:
213 /* section */
214 //printf("SKYEYE:WARNING: not implement section mapping incompletely\n");
215 //printf("SKYEYE:SECTION virt_addr = %x,l1desc=%x\n",virt_addr,l1desc);
216 //return SECTION_DOMAIN_FAULT;
217 //#if 0
218 entry.virt_addr = virt_addr;
219 entry.phys_addr = l1desc;
220 entry.perms = l1desc & 0x00000C0C;
221 entry.domain = (l1desc >> 5) & 0x0000000F;
222 entry.mapping = TLB_SECTION;
223 break;
224 //#endif
225 }
226 entry.virt_addr &= tlb_masks[entry.mapping];
227 entry.phys_addr &= tlb_masks[entry.mapping];
228
229 /* place entry in the tlb */
230 *tlb = &tlb_t->entrys[tlb_t->cycle];
231 tlb_t->cycle = (tlb_t->cycle + 1) % tlb_t->num;
232 **tlb = entry;
233 }
234 state->mmu.last_domain = (*tlb)->domain;
235 return NO_FAULT;
236}
237
238int
239mmu_tlb_init (tlb_s * tlb_t, int num)
240{
241 tlb_entry_t *e;
242 int i;
243
244 e = (tlb_entry_t *) malloc (sizeof (*e) * num);
245 if (e == NULL) {
246 ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*e) * num);
247 goto tlb_malloc_error;
248 }
249 tlb_t->entrys = e;
250 for (i = 0; i < num; i++, e++)
251 e->mapping = TLB_INVALID;
252 tlb_t->cycle = 0;
253 tlb_t->num = num;
254 return 0;
255
256 tlb_malloc_error:
257 return -1;
258}
259
260void
261mmu_tlb_exit (tlb_s * tlb_t)
262{
263 free (tlb_t->entrys);
264};
265
266void
267mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t)
268{
269 int entry;
270
271 for (entry = 0; entry < tlb_t->num; entry++) {
272 tlb_t->entrys[entry].mapping = TLB_INVALID;
273 }
274 tlb_t->cycle = 0;
275}
276
277void
278mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr)
279{
280 tlb_entry_t *tlb;
281
282 tlb = mmu_tlb_search (state, tlb_t, addr);
283 if (tlb) {
284 tlb->mapping = TLB_INVALID;
285 }
286}
287
288tlb_entry_t *
289mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t, ARMword virt_addr)
290{
291 int entry;
292
293 for (entry = 0; entry < tlb_t->num; entry++) {
294 tlb_entry_t *tlb;
295 ARMword mask;
296
297 tlb = &(tlb_t->entrys[entry]);
298 if (tlb->mapping == TLB_INVALID) {
299 continue;
300 }
301 mask = tlb_masks[tlb->mapping];
302 if ((virt_addr & mask) == (tlb->virt_addr & mask)) {
303 return tlb;
304 }
305 }
306 return NULL;
307}
diff --git a/src/core/arm/mmu/tlb.h b/src/core/arm/interpreter/mmu/tlb.h
index 938c01786..40856567b 100644
--- a/src/core/arm/mmu/tlb.h
+++ b/src/core/arm/interpreter/mmu/tlb.h
@@ -63,14 +63,7 @@ typedef struct tlb_s
63#define tlb_b_flag(tlb) \ 63#define tlb_b_flag(tlb) \
64 ((tlb)->perms & 0x4) 64 ((tlb)->perms & 0x4)
65 65
66#define tlb_va_to_pa(tlb, va) \ 66#define tlb_va_to_pa(tlb, va) ((tlb->phys_addr & tlb_masks[tlb->mapping]) | (va & ~tlb_masks[tlb->mapping]))
67(\
68 {\
69 ARMword mask = tlb_masks[tlb->mapping]; \
70 (tlb->phys_addr & mask) | (va & ~mask);\
71 }\
72)
73
74fault_t 67fault_t
75check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb, 68check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,
76 int read); 69 int read);
diff --git a/src/core/arm/interpreter/mmu/wb.cpp b/src/core/arm/interpreter/mmu/wb.cpp
new file mode 100644
index 000000000..82c0cec02
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/wb.cpp
@@ -0,0 +1,149 @@
1#include "core/arm/interpreter/armdefs.h"
2
3/* wb_init
4 * @wb_t :wb_t to init
5 * @num :num of entrys
6 * @nb :num of byte of each entry
7 *
8 * $ -1:error
9 * 0:ok
10 * */
11int
12mmu_wb_init (wb_s * wb_t, int num, int nb)
13{
14 int i;
15 wb_entry_t *entrys, *wb;
16
17 entrys = (wb_entry_t *) malloc (sizeof (*entrys) * num);
18 if (entrys == NULL) {
19 ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*entrys) * num);
20 goto entrys_malloc_error;
21 }
22
23 for (wb = entrys, i = 0; i < num; i++, wb++) {
24 /*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu */
25 //wb->data = (ARMword *)malloc(sizeof(ARMword) * nb);
26 wb->data = (ARMbyte *) malloc (nb);
27 if (wb->data == NULL) {
28 ERROR_LOG(ARM11, "malloc size of %d\n", nb);
29 goto data_malloc_error;
30 }
31
32 };
33
34 wb_t->first = wb_t->last = wb_t->used = 0;
35 wb_t->num = num;
36 wb_t->nb = nb;
37 wb_t->entrys = entrys;
38 return 0;
39
40 data_malloc_error:
41 while (--i >= 0)
42 free (entrys[i].data);
43 free (entrys);
44 entrys_malloc_error:
45 return -1;
46};
47
48/* wb_exit
49 * @wb_t :wb_t to exit
50 * */
51void
52mmu_wb_exit (wb_s * wb_t)
53{
54 int i;
55 wb_entry_t *wb;
56
57 wb = wb_t->entrys;
58 for (i = 0; i < wb_t->num; i++, wb++) {
59 free (wb->data);
60 }
61 free (wb_t->entrys);
62};
63
64/* wb_write_words :put words in Write Buffer
65 * @state: ARMul_State
66 * @wb_t: write buffer
67 * @pa: physical address
68 * @data: data ptr
69 * @n number of word to write
70 *
71 * Note: write buffer merge is not implemented, can be done late
72 * */
73void
74mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa,
75 ARMbyte * data, int n)
76{
77 int i;
78 wb_entry_t *wb;
79
80 while (n) {
81 if (wb_t->num == wb_t->used) {
82 /*clean the last wb entry */
83 ARMword t;
84
85 wb = &wb_t->entrys[wb_t->last];
86 t = wb->pa;
87 for (i = 0; i < wb->nb; i++) {
88 //mem_write_byte (state, t, wb->data[i]);
89 bus_write(8, t, wb->data[i]);
90 //t += WORD_SIZE;
91 t++;
92 }
93 wb_t->last++;
94 if (wb_t->last == wb_t->num)
95 wb_t->last = 0;
96 wb_t->used--;
97 }
98
99 wb = &wb_t->entrys[wb_t->first];
100 i = (n < wb_t->nb) ? n : wb_t->nb;
101
102 wb->pa = pa;
103 //pa += i << WORD_SHT;
104 pa += i;
105
106 wb->nb = i;
107 //memcpy(wb->data, data, i << WORD_SHT);
108 memcpy (wb->data, data, i);
109 data += i;
110 n -= i;
111 wb_t->first++;
112 if (wb_t->first == wb_t->num)
113 wb_t->first = 0;
114 wb_t->used++;
115 };
116//teawater add for set_dirty fflash cache function 2005.07.18-------------------
117#ifdef DBCT
118 if (!skyeye_config.no_dbct) {
119 tb_setdirty (state, pa, NULL);
120 }
121#endif
122//AJ2D--------------------------------------------------------------------------
123}
124
125/* wb_drain_all
126 * @wb_t wb_t to drain
127 * */
128void
129mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t)
130{
131 ARMword pa;
132 wb_entry_t *wb;
133 int i;
134
135 while (wb_t->used) {
136 wb = &wb_t->entrys[wb_t->last];
137 pa = wb->pa;
138 for (i = 0; i < wb->nb; i++) {
139 //mem_write_byte (state, pa, wb->data[i]);
140 bus_write(8, pa, wb->data[i]);
141 //pa += WORD_SIZE;
142 pa++;
143 }
144 wb_t->last++;
145 if (wb_t->last == wb_t->num)
146 wb_t->last = 0;
147 wb_t->used--;
148 };
149}
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/mmu/xscale_copro.cpp b/src/core/arm/interpreter/mmu/xscale_copro.cpp
new file mode 100644
index 000000000..433ce8e02
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/xscale_copro.cpp
@@ -0,0 +1,1391 @@
1/*
2 armmmu.c - Memory Management Unit emulation.
3 ARMulator extensions for the ARM7100 family.
4 Copyright (C) 1999 Ben Williamson
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#include <assert.h>
22#include <string.h>
23
24#include "core/arm/interpreter/armdefs.h"
25#include "core/arm/interpreter/armemu.h"
26
27/*#include "pxa.h" */
28
29/* chy 2005-09-19 */
30
31/* extern pxa270_io_t pxa270_io; */
32/* chy 2005-09-19 -----end */
33
34typedef struct xscale_mmu_desc_s
35{
36 int i_tlb;
37 cache_desc_t i_cache;
38
39 int d_tlb;
40 cache_desc_t main_d_cache;
41 cache_desc_t mini_d_cache;
42 //int rb; xscale has no read buffer
43 wb_desc_t wb;
44} xscale_mmu_desc_t;
45
46static xscale_mmu_desc_t pxa_mmu_desc = {
47 32,
48 {32, 32, 32, CACHE_WRITE_BACK},
49
50 32,
51 {32, 32, 32, CACHE_WRITE_BACK},
52 {32, 2, 8, CACHE_WRITE_BACK},
53 {8, 16}, //for byte size,
54};
55
56//chy 2005-09-19 for cp6
57#define CR0_ICIP 0
58#define CR1_ICMR 1
59//chy 2005-09-19 ---end
60//----------- for cp14-----------------
61#define CCLKCFG 6
62#define PWRMODE 7
63typedef struct xscale_cp14_reg_s
64{
65 unsigned cclkcfg; //reg6
66 unsigned pwrmode; //reg7
67} xscale_cp14_reg_s;
68
69xscale_cp14_reg_s pxa_cp14_regs;
70
71//--------------------------------------
72
73static fault_t xscale_mmu_write (ARMul_State * state, ARMword va,
74 ARMword data, ARMword datatype);
75static fault_t xscale_mmu_read (ARMul_State * state, ARMword va,
76 ARMword * data, ARMword datatype);
77
78ARMword xscale_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value);
79ARMword xscale_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value);
80
81
82/* jeff add 2010.9.26 for pxa270 cp6*/
83#define PXA270_ICMR 0x40D00004
84#define PXA270_ICPR 0x40D00010
85#define PXA270_ICLR 0x40D00008
86//chy 2005-09-19 for xscale pxa27x cp6
87unsigned
88xscale_cp6_mrc (ARMul_State * state, unsigned type, ARMword instr,
89 ARMword * data)
90{
91 unsigned opcode_2 = BITS (5, 7);
92 unsigned CRm = BITS (0, 3);
93 unsigned reg = BITS (16, 19);
94 unsigned result;
95
96 //printf("SKYEYE: xscale_cp6_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,state->Reg[15], instr);
97
98 switch (reg) {
99 case CR0_ICIP: { // cp 6 reg 0
100 //printf("cp6_mrc cr0 ICIP \n");
101 /* *data = (pxa270_io.icmr & pxa270_io.icpr) & ~pxa270_io.iclr; */
102 /* use bus_read get the pxa270 machine registers 2010.9.26 jeff*/
103 int icmr, icpr, iclr;
104 bus_read(32, PXA270_ICMR, (uint32_t*)&icmr);
105 bus_read(32, PXA270_ICPR, (uint32_t*)&icpr);
106 bus_read(32, PXA270_ICLR, (uint32_t*)&iclr);
107 *data = (icmr & icpr) & ~iclr;
108 }
109 break;
110 case CR1_ICMR: { // cp 6 reg 1
111 //printf("cp6_mrc cr1 ICMR\n");
112 /* *data = pxa270_io.icmr; */
113 int icmr;
114 /* use bus_read get the pxa270 machine registers 2010.9.26 jeff*/
115 bus_read(32, PXA270_ICMR, (uint32_t*)&icmr);
116 *data = icmr;
117 }
118 break;
119 default:
120 *data = 0;
121 printf ("SKYEYE:cp6_mrc unknown cp6 regs!!!!!!\n");
122 printf ("SKYEYE: xscale_cp6_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n", opcode_2, CRm, reg, state->Reg[15], instr);
123 break;
124 }
125 return 0;
126}
127
128//chy 2005-09-19 end
129//xscale cp13 ----------------------------------------------------
130unsigned
131xscale_cp13_init (ARMul_State * state)
132{
133 //printf("SKYEYE: xscale_cp13_init: begin\n");
134 return 0;
135}
136
137unsigned
138xscale_cp13_exit (ARMul_State * state)
139{
140 //printf("SKYEYE: xscale_cp13_exit: begin\n");
141 return 0;
142}
143
144unsigned
145xscale_cp13_ldc (ARMul_State * state, unsigned type, ARMword instr,
146 ARMword data)
147{
148 printf ("SKYEYE: xscale_cp13_ldc: ERROR isn't existed,");
149 SKYEYE_OUTREGS (stderr);
150 fprintf (stderr, "\n");
151 // skyeye_exit (-1);
152 return 0; //No matter return value, only for compiler.
153}
154
155unsigned
156xscale_cp13_stc (ARMul_State * state, unsigned type, ARMword instr,
157 ARMword * data)
158{
159 printf ("SKYEYE: xscale_cp13_stc: ERROR isn't existed,");
160 SKYEYE_OUTREGS (stderr);
161 fprintf (stderr, "\n");
162 // skyeye_exit (-1);
163 return 0; //No matter return value, only for compiler.
164}
165
166unsigned
167xscale_cp13_mrc (ARMul_State * state, unsigned type, ARMword instr,
168 ARMword * data)
169{
170 printf ("SKYEYE: xscale_cp13_mrc: ERROR isn't existed,");
171 SKYEYE_OUTREGS (stderr);
172 fprintf (stderr, "\n");
173 // skyeye_exit (-1);
174 return 0; //No matter return value, only for compiler.
175}
176
177unsigned
178xscale_cp13_mcr (ARMul_State * state, unsigned type, ARMword instr,
179 ARMword data)
180{
181 printf ("SKYEYE: xscale_cp13_mcr: ERROR isn't existed,");
182 SKYEYE_OUTREGS (stderr);
183 fprintf (stderr, "\n");
184 // skyeye_exit (-1);
185 return 0; //No matter return value, only for compiler.
186}
187
188unsigned
189xscale_cp13_cdp (ARMul_State * state, unsigned type, ARMword instr)
190{
191 printf ("SKYEYE: xscale_cp13_cdp: ERROR isn't existed,");
192 SKYEYE_OUTREGS (stderr);
193 fprintf (stderr, "\n");
194 // skyeye_exit (-1);
195 return 0; //No matter return value, only for compiler.
196}
197
198unsigned
199xscale_cp13_read_reg (ARMul_State * state, unsigned reg, ARMword * data)
200{
201 printf ("SKYEYE: xscale_cp13_read_reg: ERROR isn't existed,");
202 SKYEYE_OUTREGS (stderr);
203 fprintf (stderr, "\n");
204 return 0;
205 //exit(-1);
206}
207
208unsigned
209xscale_cp13_write_reg (ARMul_State * state, unsigned reg, ARMword data)
210{
211 printf ("SKYEYE: xscale_cp13_write_reg: ERROR isn't existed,");
212 SKYEYE_OUTREGS (stderr);
213 fprintf (stderr, "\n");
214 // skyeye_exit (-1);
215 return 0; //No matter return value, only for compiler.
216}
217
218//------------------------------------------------------------------
219//xscale cp14 ----------------------------------------------------
220unsigned
221xscale_cp14_init (ARMul_State * state)
222{
223 //printf("SKYEYE: xscale_cp14_init: begin\n");
224 pxa_cp14_regs.cclkcfg = 0;
225 pxa_cp14_regs.pwrmode = 0;
226 return 0;
227}
228
229unsigned
230xscale_cp14_exit (ARMul_State * state)
231{
232 //printf("SKYEYE: xscale_cp14_exit: begin\n");
233 return 0;
234}
235
236unsigned
237xscale_cp14_ldc (ARMul_State * state, unsigned type, ARMword instr,
238 ARMword data)
239{
240 printf ("SKYEYE: xscale_cp14_ldc: ERROR isn't existed, reg15 0x%x\n",
241 state->Reg[15]);
242 SKYEYE_OUTREGS (stderr);
243 // skyeye_exit (-1);
244 return 0; //No matter return value, only for compiler.
245}
246
247unsigned
248xscale_cp14_stc (ARMul_State * state, unsigned type, ARMword instr,
249 ARMword * data)
250{
251 printf ("SKYEYE: xscale_cp14_stc: ERROR isn't existed, reg15 0x%x\n",
252 state->Reg[15]);
253 SKYEYE_OUTREGS (stderr);
254 // skyeye_exit (-1);
255 return 0; //No matter return value, only for compiler.
256}
257
258unsigned
259xscale_cp14_mrc (ARMul_State * state, unsigned type, ARMword instr,
260 ARMword * data)
261{
262 unsigned opcode_2 = BITS (5, 7);
263 unsigned CRm = BITS (0, 3);
264 unsigned reg = BITS (16, 19);
265 unsigned result;
266
267 //printf("SKYEYE: xscale_cp14_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\
268 state->Reg[15], instr);
269
270 switch (reg) {
271 case CCLKCFG: // cp 14 reg 6
272 //printf("cp14_mrc cclkcfg \n");
273 *data = pxa_cp14_regs.cclkcfg;
274 break;
275 case PWRMODE: // cp 14 reg 7
276 //printf("cp14_mrc pwrmode \n");
277 *data = pxa_cp14_regs.pwrmode;
278 break;
279 default:
280 *data = 0;
281 printf ("SKYEYE:cp14_mrc unknown cp14 regs!!!!!!\n");
282 break;
283 }
284 return 0;
285}
286unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type, ARMword instr,
287 ARMword data)
288{
289 unsigned opcode_2 = BITS (5, 7);
290 unsigned CRm = BITS (0, 3);
291 unsigned reg = BITS (16, 19);
292 unsigned result;
293
294 //printf("SKYEYE: xscale_cp14_mcr:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\
295 state->Reg[15], instr);
296
297 switch (reg) {
298 case CCLKCFG: // cp 14 reg 6
299 //printf("cp14_mcr cclkcfg \n");
300 pxa_cp14_regs.cclkcfg = data & 0xf;
301 break;
302 case PWRMODE: // cp 14 reg 7
303 //printf("cp14_mcr pwrmode \n");
304 pxa_cp14_regs.pwrmode = data & 0x3;
305 break;
306 default:printf ("SKYEYE: cp14_mcr unknown cp14 regs!!!!!!\n");
307 break;
308 }
309 return 0;
310}
311unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type, ARMword instr)
312{
313 printf ("SKYEYE: xscale_cp14_cdp: ERROR isn't existed, reg15 0x%x\n",
314 state->Reg[15]);
315 SKYEYE_OUTREGS (stderr);
316 // skyeye_exit (-1);
317 return 0; //No matter return value, only for compiler.
318}
319unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg,
320 ARMword * data)
321{
322 printf ("SKYEYE: xscale_cp14_read_reg: ERROR isn't existed, reg15 0x%x\n", state->Reg[15]);
323 SKYEYE_OUTREGS (stderr);
324 // skyeye_exit (-1);
325 return 0; //No matter return value, only for compiler.
326}
327unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg,
328 ARMword data)
329{
330 printf ("SKYEYE: xscale_cp14_write_reg: ERROR isn't existed, reg15 0x%x\n", state->Reg[15]);
331 SKYEYE_OUTREGS (stderr);
332 // skyeye_exit (-1);
333
334 return 0; //No matter return value, only for compiler.
335}
336
337//------------------------------------------------------------------
338//cp15 -------------------------------------
339unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type, ARMword instr,
340 ARMword data)
341{
342 printf ("SKYEYE: xscale_cp15_ldc: ERROR isn't existed\n");
343 SKYEYE_OUTREGS (stderr);
344 // skyeye_exit (-1);
345
346 return 0; //No matter return value, only for compiler.
347}
348unsigned xscale_cp15_stc (ARMul_State * state, unsigned type, ARMword instr,
349 ARMword * data)
350{
351 printf ("SKYEYE: xscale_cp15_stc: ERROR isn't existed\n");
352 SKYEYE_OUTREGS (stderr);
353 // skyeye_exit (-1);
354
355 return 0; //No matter return value, only for compiler.
356}
357unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type, ARMword instr)
358{
359 printf ("SKYEYE: xscale_cp15_cdp: ERROR isn't existed\n");
360 SKYEYE_OUTREGS (stderr);
361 // skyeye_exit (-1);
362
363 return 0; //No matter return value, only for compiler.
364}
365unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg,
366 ARMword * data)
367{
368//chy 2003-09-03: for xsacle_cp15_cp_access_allowed
369 if (reg == 15) {
370 *data = state->mmu.copro_access;
371 //printf("SKYEYE: xscale_cp15_read_reg: reg 0x%x,data %x\n",reg,*data);
372 return 0;
373 }
374 printf ("SKYEYE: xscale_cp15_read_reg: reg 0x%x, ERROR isn't existed\n", reg);
375 SKYEYE_OUTREGS (stderr);
376 // skyeye_exit (-1);
377
378 return 0; //No matter return value, only for compiler.
379}
380
381//chy 2003-09-03 used by macro CP_ACCESS_ALLOWED in armemu.h
382unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
383 unsigned cpnum)
384{
385 unsigned data;
386
387 xscale_cp15_read_reg (state, reg, &data);
388 //printf("SKYEYE: cp15_cp_access_allowed data %x, cpnum %x, result %x\n", data, cpnum, (data & 1<<cpnum));
389 if (data & 1 << cpnum)
390 return 1;
391 else
392 return 0;
393}
394
395unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg,
396 ARMword value)
397{
398 switch (reg) {
399 case MMU_FAULT_STATUS:
400 //printf("SKYEYE:cp15_write_reg wrote FS val 0x%x \n",value);
401 state->mmu.fault_status = value & 0x6FF;
402 break;
403 case MMU_FAULT_ADDRESS:
404 //printf("SKYEYE:cp15_write_reg wrote FA val 0x%x \n",value);
405 state->mmu.fault_address = value;
406 break;
407 default:
408 printf ("SKYEYE: xscale_cp15_write_reg: reg 0x%x R15 %x ERROR isn't existed\n", reg, state->Reg[15]);
409 SKYEYE_OUTREGS (stderr);
410 // skyeye_exit (-1);
411 }
412 return 0;
413}
414
415unsigned
416xscale_cp15_init (ARMul_State * state)
417{
418 xscale_mmu_desc_t *desc;
419 cache_desc_t *c_desc;
420
421 state->mmu.control = 0;
422 state->mmu.translation_table_base = 0xDEADC0DE;
423 state->mmu.domain_access_control = 0xDEADC0DE;
424 state->mmu.fault_status = 0;
425 state->mmu.fault_address = 0;
426 state->mmu.process_id = 0;
427 state->mmu.cache_type = 0xB1AA1AA; //0000 1011 0001 1010 1010 0001 1010 1010
428 state->mmu.aux_control = 0;
429
430 desc = &pxa_mmu_desc;
431
432 if (mmu_tlb_init (I_TLB (), desc->i_tlb)) {
433 ERROR_LOG(ARM11, "i_tlb init %d\n", -1);
434 goto i_tlb_init_error;
435 }
436
437 c_desc = &desc->i_cache;
438 if (mmu_cache_init (I_CACHE (), c_desc->width, c_desc->way,
439 c_desc->set, c_desc->w_mode)) {
440 ERROR_LOG(ARM11, "i_cache init %d\n", -1);
441 goto i_cache_init_error;
442 }
443
444 if (mmu_tlb_init (D_TLB (), desc->d_tlb)) {
445 ERROR_LOG(ARM11, "d_tlb init %d\n", -1);
446 goto d_tlb_init_error;
447 }
448
449 c_desc = &desc->main_d_cache;
450 if (mmu_cache_init (MAIN_D_CACHE (), c_desc->width, c_desc->way,
451 c_desc->set, c_desc->w_mode)) {
452 ERROR_LOG(ARM11, "main_d_cache init %d\n", -1);
453 goto main_d_cache_init_error;
454 }
455
456 c_desc = &desc->mini_d_cache;
457 if (mmu_cache_init (MINI_D_CACHE (), c_desc->width, c_desc->way,
458 c_desc->set, c_desc->w_mode)) {
459 ERROR_LOG(ARM11, "mini_d_cache init %d\n", -1);
460 goto mini_d_cache_init_error;
461 }
462
463 if (mmu_wb_init (WB (), desc->wb.num, desc->wb.nb)) {
464 ERROR_LOG(ARM11, "wb init %d\n", -1);
465 goto wb_init_error;
466 }
467#if 0
468 if (mmu_rb_init (RB (), desc->rb)) {
469 ERROR_LOG(ARM11, "rb init %d\n", -1);
470 goto rb_init_error;
471 }
472#endif
473
474 return 0;
475#if 0
476 rb_init_error:
477 mmu_wb_exit (WB ());
478#endif
479 wb_init_error:
480 mmu_cache_exit (MINI_D_CACHE ());
481 mini_d_cache_init_error:
482 mmu_cache_exit (MAIN_D_CACHE ());
483 main_d_cache_init_error:
484 mmu_tlb_exit (D_TLB ());
485 d_tlb_init_error:
486 mmu_cache_exit (I_CACHE ());
487 i_cache_init_error:
488 mmu_tlb_exit (I_TLB ());
489 i_tlb_init_error:
490 return -1;
491}
492
493unsigned
494xscale_cp15_exit (ARMul_State * state)
495{
496 //mmu_rb_exit(RB());
497 mmu_wb_exit (WB ());
498 mmu_cache_exit (MINI_D_CACHE ());
499 mmu_cache_exit (MAIN_D_CACHE ());
500 mmu_tlb_exit (D_TLB ());
501 mmu_cache_exit (I_CACHE ());
502 mmu_tlb_exit (I_TLB ());
503 return 0;
504};
505
506
507static fault_t
508 xscale_mmu_load_instr (ARMul_State * state, ARMword va,
509 ARMword * instr)
510{
511 fault_t fault;
512 tlb_entry_t *tlb;
513 cache_line_t *cache;
514 int c; //cache bit
515 ARMword pa; //physical addr
516
517 static int debug_count = 0; //used for debug
518
519 DEBUG_LOG(ARM11, "va = %x\n", va);
520
521 va = mmu_pid_va_map (va);
522 if (MMU_Enabled) {
523 /*align check */
524 if ((va & (INSN_SIZE - 1)) && MMU_Aligned) {
525 DEBUG_LOG(ARM11, "align\n");
526 return ALIGNMENT_FAULT;
527 }
528 else
529 va &= ~(INSN_SIZE - 1);
530
531 /*translate tlb */
532 fault = translate (state, va, I_TLB (), &tlb);
533 if (fault) {
534 DEBUG_LOG(ARM11, "translate\n");
535 return fault;
536 }
537
538 /*check access */
539 fault = check_access (state, va, tlb, 1);
540 if (fault) {
541 DEBUG_LOG(ARM11, "check_fault\n");
542 return fault;
543 }
544 }
545 //chy 2003-09-02 for test, don't use cache ?????
546#if 0
547 /*search cache no matter MMU enabled/disabled */
548 cache = mmu_cache_search (state, I_CACHE (), va);
549 if (cache) {
550 *instr = cache->data[va_cache_index (va, I_CACHE ())];
551 return 0;
552 }
553#endif
554 /*if MMU disabled or C flag is set alloc cache */
555 if (MMU_Disabled) {
556 c = 1;
557 pa = va;
558 }
559 else {
560 c = tlb_c_flag (tlb);
561 pa = tlb_va_to_pa (tlb, va);
562 }
563
564 //chy 2003-09-03 only read mem, don't use cache now,will change later ????
565 //*instr = mem_read_word (state, pa);
566 bus_read(32, pa, instr);
567#if 0
568//-----------------------------------------------------------
569 //chy 2003-09-02 for test????
570 if (pa >= 0xa01c8000 && pa <= 0xa01c8020) {
571 printf ("SKYEYE:load_instr: pa %x, va %x,instr %x, R15 %x\n",
572 pa, va, *instr, state->Reg[15]);
573 }
574
575//----------------------------------------------------------------------
576#endif
577 return NO_FAULT;
578
579 if (c) {
580 int index;
581
582 debug_count++;
583 cache = mmu_cache_alloc (state, I_CACHE (), va, pa);
584 index = va_cache_index (va, I_CACHE ());
585 *instr = cache->data[va_cache_index (va, I_CACHE ())];
586 }
587 else
588 //*instr = mem_read_word (state, pa);
589 bus_read(32, pa, instr);
590
591 return NO_FAULT;
592};
593
594
595
596static fault_t
597 xscale_mmu_read_byte (ARMul_State * state, ARMword virt_addr,
598 ARMword * data)
599{
600 //ARMword temp,offset;
601 fault_t fault;
602 fault = xscale_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE);
603 return fault;
604}
605
606static fault_t
607 xscale_mmu_read_halfword (ARMul_State * state, ARMword virt_addr,
608 ARMword * data)
609{
610 //ARMword temp,offset;
611 fault_t fault;
612 fault = xscale_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE);
613 return fault;
614}
615
616static fault_t
617 xscale_mmu_read_word (ARMul_State * state, ARMword virt_addr,
618 ARMword * data)
619{
620 return xscale_mmu_read (state, virt_addr, data, ARM_WORD_TYPE);
621}
622
623
624
625
626static fault_t
627 xscale_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
628 ARMword datatype)
629{
630 fault_t fault;
631// rb_entry_t *rb;
632 tlb_entry_t *tlb;
633 cache_line_t *cache;
634 ARMword pa, real_va, temp, offset;
635 //chy 2003-09-02 for test ????
636 static unsigned chyst1 = 0, chyst2 = 0;
637
638 DEBUG_LOG(ARM11, "va = %x\n", va);
639
640 va = mmu_pid_va_map (va);
641 real_va = va;
642 /*if MMU disabled, memory_read */
643 if (MMU_Disabled) {
644 //*data = mem_read_word(state, va);
645 if (datatype == ARM_BYTE_TYPE)
646 //*data = mem_read_byte (state, va);
647 bus_read(8, va, data);
648 else if (datatype == ARM_HALFWORD_TYPE)
649 //*data = mem_read_halfword (state, va);
650 bus_read(16, va, data);
651 else if (datatype == ARM_WORD_TYPE)
652 //*data = mem_read_word (state, va);
653 bus_read(32, va, data);
654 else {
655 printf ("SKYEYE:1 xscale_mmu_read error: unknown data type %d\n", datatype);
656 // skyeye_exit (-1);
657 }
658
659 return NO_FAULT;
660 }
661
662 /*align check */
663 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
664 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
665 DEBUG_LOG(ARM11, "align\n");
666 return ALIGNMENT_FAULT;
667 } // else
668
669 va &= ~(WORD_SIZE - 1);
670
671 /*translate va to tlb */
672 fault = translate (state, va, D_TLB (), &tlb);
673 if (fault) {
674 DEBUG_LOG(ARM11, "translate\n");
675 return fault;
676 }
677 /*check access permission */
678 fault = check_access (state, va, tlb, 1);
679 if (fault)
680 return fault;
681
682#if 0
683//------------------------------------------------
684//chy 2003-09-02 for test only ,should commit ????
685 if (datatype == ARM_WORD_TYPE) {
686 if (real_va >= 0xffff0000 && real_va <= 0xffff0020) {
687 pa = tlb_va_to_pa (tlb, va);
688 *data = mem_read_word (state, pa);
689 chyst1++;
690 printf ("**SKYEYE:mmu_read word %d: pa %x, va %x, data %x, R15 %x\n", chyst1, pa, real_va, *data, state->Reg[15]);
691 /*
692 cache==mmu_cache_search(state,MAIN_D_CACHE(),va);
693 if(cache){
694 *data = cache->data[va_cache_index(va, MAIN_D_CACHE())];
695 printf("cached data %x\n",*data);
696 }else printf("no cached data\n");
697 */
698 }
699 }
700//-------------------------------------------------
701#endif
702#if 0
703 /*search in read buffer */
704 rb = mmu_rb_search (RB (), va);
705 if (rb) {
706 if (rb->fault)
707 return rb->fault;
708 *data = rb->data[(va & (rb_masks[rb->type] - 1)) >> WORD_SHT];
709 goto datatrans;
710 //return 0;
711 };
712#endif
713
714 /*2004-07-19 chy: add support of xscale MMU CacheDisabled option */
715 if (MMU_CacheDisabled) {
716 //if(1){ can be used to test cache error
717 /*get phy_addr */
718 pa = tlb_va_to_pa (tlb, real_va);
719 if (datatype == ARM_BYTE_TYPE)
720 //*data = mem_read_byte (state, pa);
721 bus_read(8, pa, data);
722 else if (datatype == ARM_HALFWORD_TYPE)
723 //*data = mem_read_halfword (state, pa);
724 bus_read(16, pa, data);
725 else if (datatype == ARM_WORD_TYPE)
726 //*data = mem_read_word (state, pa);
727 bus_read(32, pa, data);
728 else {
729 printf ("SKYEYE:MMU_CacheDisabled xscale_mmu_read error: unknown data type %d\n", datatype);
730 // skyeye_exit (-1);
731 }
732 return NO_FAULT;
733 }
734
735
736 /*search main cache */
737 cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
738 if (cache) {
739 *data = cache->data[va_cache_index (va, MAIN_D_CACHE ())];
740#if 0
741//------------------------------------------------------------------------
742//chy 2003-09-02 for test only ,should commit ????
743 if (real_va >= 0xffff0000 && real_va <= 0xffff0020) {
744 pa = tlb_va_to_pa (tlb, va);
745 chyst2++;
746 printf ("**SKYEYE:mmu_read wordk:cache %d: pa %x, va %x, data %x, R15 %x\n", chyst2, pa, real_va, *data, state->Reg[15]);
747 }
748//-------------------------------------------------------------------
749#endif
750 goto datatrans;
751 //return 0;
752 }
753 //chy 2003-08-24, now maybe we don't need minidcache ????
754#if 0
755 /*search mini cache */
756 cache = mmu_cache_search (state, MINI_D_CACHE (), va);
757 if (cache) {
758 *data = cache->data[va_cache_index (va, MINI_D_CACHE ())];
759 goto datatrans;
760 //return 0;
761 }
762#endif
763 /*get phy_addr */
764 pa = tlb_va_to_pa (tlb, va);
765 //chy 2003-08-24 , in xscale it means what ?????
766#if 0
767 if ((pa >= 0xe0000000) && (pa < 0xe8000000)) {
768
769 if (tlb_c_flag (tlb)) {
770 if (tlb_b_flag (tlb)) {
771 mmu_cache_soft_flush (state, MAIN_D_CACHE (),
772 pa);
773 }
774 else {
775 mmu_cache_soft_flush (state, MINI_D_CACHE (),
776 pa);
777 }
778 }
779 return 0;
780 }
781#endif
782 //chy 2003-08-24, check phy addr
783 //ywc 2004-11-30, inactive this check because of using 0xc0000000 as the framebuffer start address
784 /*
785 if(pa >= 0xb0000000){
786 printf("SKYEYE:xscale_mmu_read: phy address 0x%x error,reg[15] 0x%x\n",pa,state->Reg[15]);
787 return 0;
788 }
789 */
790
791 //chy 2003-08-24, now maybe we don't need wb ????
792#if 0
793 /*if Buffer, drain Write Buffer first */
794 if (tlb_b_flag (tlb))
795 mmu_wb_drain_all (state, WB ());
796#endif
797 /*alloc cache or mem_read */
798 if (tlb_c_flag (tlb) && MMU_DCacheEnabled) {
799 cache_s *cache_t;
800
801 if (tlb_b_flag (tlb))
802 cache_t = MAIN_D_CACHE ();
803 else
804 cache_t = MINI_D_CACHE ();
805 cache = mmu_cache_alloc (state, cache_t, va, pa);
806 *data = cache->data[va_cache_index (va, cache_t)];
807 }
808 else {
809 //*data = mem_read_word(state, pa);
810 if (datatype == ARM_BYTE_TYPE)
811 //*data = mem_read_byte (state, pa | (real_va & 3));
812 bus_read(8, pa | (real_va & 3), data);
813 else if (datatype == ARM_HALFWORD_TYPE)
814 //*data = mem_read_halfword (state, pa | (real_va & 2));
815 bus_read(16, pa | (real_va & 2), data);
816 else if (datatype == ARM_WORD_TYPE)
817 //*data = mem_read_word (state, pa);
818 bus_read(32, pa, data);
819 else {
820 printf ("SKYEYE:2 xscale_mmu_read error: unknown data type %d\n", datatype);
821 // skyeye_exit (-1);
822 }
823 return NO_FAULT;
824 }
825
826
827 datatrans:
828 if (datatype == ARM_HALFWORD_TYPE) {
829 temp = *data;
830 offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
831 *data = (temp >> offset) & 0xffff;
832 }
833 else if (datatype == ARM_BYTE_TYPE) {
834 temp = *data;
835 offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
836 *data = (temp >> offset & 0xffL);
837 }
838 end:
839 return NO_FAULT;
840}
841
842
843static fault_t
844 xscale_mmu_write_byte (ARMul_State * state, ARMword virt_addr,
845 ARMword data)
846{
847 return xscale_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE);
848}
849
850static fault_t
851 xscale_mmu_write_halfword (ARMul_State * state, ARMword virt_addr,
852 ARMword data)
853{
854 return xscale_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE);
855}
856
857static fault_t
858 xscale_mmu_write_word (ARMul_State * state, ARMword virt_addr,
859 ARMword data)
860{
861 return xscale_mmu_write (state, virt_addr, data, ARM_WORD_TYPE);
862}
863
864
865
866static fault_t
867 xscale_mmu_write (ARMul_State * state, ARMword va, ARMword data,
868 ARMword datatype)
869{
870 tlb_entry_t *tlb;
871 cache_line_t *cache;
872 cache_s *cache_t;
873 int b;
874 ARMword pa, real_va, temp, offset;
875 fault_t fault;
876
877 ARMword index;
878//chy 2003-09-02 for test ????
879// static unsigned chyst1=0,chyst2=0;
880
881 DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data);
882 va = mmu_pid_va_map (va);
883 real_va = va;
884
885 if (MMU_Disabled) {
886 //mem_write_word(state, va, data);
887 if (datatype == ARM_BYTE_TYPE)
888 //mem_write_byte (state, va, data);
889 bus_write(8, va, data);
890 else if (datatype == ARM_HALFWORD_TYPE)
891 //mem_write_halfword (state, va, data);
892 bus_write(16, va, data);
893 else if (datatype == ARM_WORD_TYPE)
894 //mem_write_word (state, va, data);
895 bus_write(32, va, data);
896 else {
897 printf ("SKYEYE:1 xscale_mmu_write error: unknown data type %d\n", datatype);
898 // skyeye_exit (-1);
899 }
900
901 return NO_FAULT;
902 }
903 /*align check */
904 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
905 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
906 DEBUG_LOG(ARM11, "align\n");
907 return ALIGNMENT_FAULT;
908 } //else
909 va &= ~(WORD_SIZE - 1);
910 /*tlb translate */
911 fault = translate (state, va, D_TLB (), &tlb);
912 if (fault) {
913 DEBUG_LOG(ARM11, "translate\n");
914 return fault;
915 }
916 /*tlb check access */
917 fault = check_access (state, va, tlb, 0);
918 if (fault) {
919 DEBUG_LOG(ARM11, "check_access\n");
920 return fault;
921 }
922
923 /*2004-07-19 chy: add support for xscale MMU_CacheDisabled */
924 if (MMU_CacheDisabled) {
925 //if(1){ can be used to test the cache error
926 /*get phy_addr */
927 pa = tlb_va_to_pa (tlb, real_va);
928 if (datatype == ARM_BYTE_TYPE)
929 //mem_write_byte (state, pa, data);
930 bus_write(8, pa, data);
931 else if (datatype == ARM_HALFWORD_TYPE)
932 //mem_write_halfword (state, pa, data);
933 bus_write(16, pa, data);
934 else if (datatype == ARM_WORD_TYPE)
935 //mem_write_word (state, pa, data);
936 bus_write(32, pa , data);
937 else {
938 printf ("SKYEYE:MMU_CacheDisabled xscale_mmu_write error: unknown data type %d\n", datatype);
939 // skyeye_exit (-1);
940 }
941
942 return NO_FAULT;
943 }
944
945 /*search main cache */
946 b = tlb_b_flag (tlb);
947 pa = tlb_va_to_pa (tlb, va);
948 cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
949 if (cache) {
950 cache_t = MAIN_D_CACHE ();
951 goto has_cache;
952 }
953 //chy 2003-08-24, now maybe we don't need minidcache ????
954#if 0
955 /*search mini cache */
956 cache = mmu_cache_search (state, MINI_D_CACHE (), va);
957 if (cache) {
958 cache_t = MINI_D_CACHE ();
959 goto has_cache;
960 }
961#endif
962 b = tlb_b_flag (tlb);
963 pa = tlb_va_to_pa (tlb, va);
964 //chy 2003-08-24, check phy addr 0xa0000000, size 0x04000000
965 //ywc 2004-11-30, inactive this check because of using 0xc0000000 as the framebuffer start address
966 /*
967 if(pa >= 0xb0000000){
968 printf("SKYEYE:xscale_mmu_write phy address 0x%x error,reg[15] 0x%x\n",pa,state->Reg[15]);
969 return 0;
970 }
971 */
972
973 //chy 2003-08-24, now maybe we don't need WB ????
974#if 0
975 if (b) {
976 if (MMU_WBEnabled) {
977 if (datatype == ARM_WORD_TYPE)
978 mmu_wb_write_bytes (state, WB (), pa, &data,
979 4);
980 else if (datatype == ARM_HALFWORD_TYPE)
981 mmu_wb_write_bytes (state, WB (),
982 (pa | (real_va & 2)),
983 &data, 2);
984 else if (datatype == ARM_BYTE_TYPE)
985 mmu_wb_write_bytes (state, WB (),
986 (pa | (real_va & 3)),
987 &data, 1);
988
989 }
990 else {
991 if (datatype == ARM_WORD_TYPE)
992 mem_write_word (state, pa, data);
993 else if (datatype == ARM_HALFWORD_TYPE)
994 mem_write_halfword (state,
995 (pa | (real_va & 2)),
996 data);
997 else if (datatype == ARM_BYTE_TYPE)
998 mem_write_byte (state, (pa | (real_va & 3)),
999 data);
1000 }
1001 }
1002 else {
1003
1004 mmu_wb_drain_all (state, WB ());
1005
1006 if (datatype == ARM_WORD_TYPE)
1007 mem_write_word (state, pa, data);
1008 else if (datatype == ARM_HALFWORD_TYPE)
1009 mem_write_halfword (state, (pa | (real_va & 2)),
1010 data);
1011 else if (datatype == ARM_BYTE_TYPE)
1012 mem_write_byte (state, (pa | (real_va & 3)), data);
1013 }
1014#endif
1015 //chy 2003-08-24, just write phy addr
1016 if (datatype == ARM_WORD_TYPE)
1017 //mem_write_word (state, pa, data);
1018 bus_write(32, pa, data);
1019 else if (datatype == ARM_HALFWORD_TYPE)
1020 //mem_write_halfword (state, (pa | (real_va & 2)), data);
1021 bus_write(16, pa | (real_va & 2), data);
1022 else if (datatype == ARM_BYTE_TYPE)
1023 //mem_write_byte (state, (pa | (real_va & 3)), data);
1024 bus_write(8, (pa | (real_va & 3)), data);
1025#if 0
1026//-------------------------------------------------------------
1027//chy 2003-09-02 for test ????
1028 if (datatype == ARM_WORD_TYPE) {
1029 if (real_va >= 0xffff0000 && real_va <= 0xffff0020) {
1030 printf ("**SKYEYE:mmu_write word: pa %x, va %x, data %x, R15 %x \n", pa, real_va, data, state->Reg[15]);
1031 }
1032 }
1033//--------------------------------------------------------------
1034#endif
1035 return NO_FAULT;
1036
1037 has_cache:
1038 index = va_cache_index (va, cache_t);
1039 //cache->data[index] = data;
1040
1041 if (datatype == ARM_WORD_TYPE)
1042 cache->data[index] = data;
1043 else if (datatype == ARM_HALFWORD_TYPE) {
1044 temp = cache->data[index];
1045 offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
1046 cache->data[index] =
1047 (temp & ~(0xffffL << offset)) | ((data & 0xffffL) <<
1048 offset);
1049 }
1050 else if (datatype == ARM_BYTE_TYPE) {
1051 temp = cache->data[index];
1052 offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
1053 cache->data[index] =
1054 (temp & ~(0xffL << offset)) | ((data & 0xffL) <<
1055 offset);
1056 }
1057
1058 if (index < (cache_t->width >> (WORD_SHT + 1)))
1059 cache->tag |= TAG_FIRST_HALF_DIRTY;
1060 else
1061 cache->tag |= TAG_LAST_HALF_DIRTY;
1062//-------------------------------------------------------------
1063//chy 2003-09-03 be sure the changed value will be in memory as soon as possible, so I cache can get the newest value
1064#if 0
1065 {
1066 if (datatype == ARM_WORD_TYPE)
1067 mem_write_word (state, pa, data);
1068 else if (datatype == ARM_HALFWORD_TYPE)
1069 mem_write_halfword (state, (pa | (real_va & 2)),
1070 data);
1071 else if (datatype == ARM_BYTE_TYPE)
1072 mem_write_byte (state, (pa | (real_va & 3)), data);
1073 }
1074#endif
1075#if 0
1076//chy 2003-09-02 for test ????
1077 if (datatype == ARM_WORD_TYPE) {
1078 if (real_va >= 0xffff0000 && real_va <= 0xffff0020) {
1079 printf ("**SKYEYE:mmu_write word:cache: pa %x, va %x, data %x, R15 %x\n", pa, real_va, data, state->Reg[15]);
1080 }
1081 }
1082//-------------------------------------------------------------
1083#endif
1084 if (datatype == ARM_WORD_TYPE)
1085 //mem_write_word (state, pa, data);
1086 bus_write(32, pa, data);
1087 else if (datatype == ARM_HALFWORD_TYPE)
1088 //mem_write_halfword (state, (pa | (real_va & 2)), data);
1089 bus_write(16, pa | (real_va & 2), data);
1090 else if (datatype == ARM_BYTE_TYPE)
1091 //mem_write_byte (state, (pa | (real_va & 3)), data);
1092 bus_write(8, (pa | (real_va & 3)), data);
1093 return NO_FAULT;
1094}
1095
1096ARMword xscale_cp15_mrc (ARMul_State * state,
1097 unsigned type, ARMword instr, ARMword * value)
1098{
1099 return xscale_mmu_mrc (state, instr, value);
1100}
1101
1102ARMword xscale_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
1103{
1104 ARMword data;
1105 unsigned opcode_2 = BITS (5, 7);
1106 unsigned CRm = BITS (0, 3);
1107 unsigned reg = BITS (16, 19);
1108 unsigned result;
1109 mmu_regnum_t creg = (mmu_regnum_t)reg;
1110
1111/*
1112 printf("SKYEYE: xscale_cp15_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\
1113 state->Reg[15], instr);
1114*/
1115 switch (creg) {
1116 case MMU_ID: //XSCALE_CP15
1117 //printf("mmu_mrc read ID \n");
1118 data = (opcode_2 ? state->mmu.cache_type : state->cpu->
1119 cpu_val);
1120 break;
1121 case MMU_CONTROL: //XSCALE_CP15_AUX_CONTROL
1122 //printf("mmu_mrc read CONTROL \n");
1123 data = (opcode_2 ? state->mmu.aux_control : state->mmu.
1124 control);
1125 break;
1126 case MMU_TRANSLATION_TABLE_BASE:
1127 //printf("mmu_mrc read TTB \n");
1128 data = state->mmu.translation_table_base;
1129 break;
1130 case MMU_DOMAIN_ACCESS_CONTROL:
1131 //printf("mmu_mrc read DACR \n");
1132 data = state->mmu.domain_access_control;
1133 break;
1134 case MMU_FAULT_STATUS:
1135 //printf("mmu_mrc read FSR \n");
1136 data = state->mmu.fault_status;
1137 break;
1138 case MMU_FAULT_ADDRESS:
1139 //printf("mmu_mrc read FAR \n");
1140 data = state->mmu.fault_address;
1141 break;
1142 case MMU_PID:
1143 //printf("mmu_mrc read PID \n");
1144 data = state->mmu.process_id;
1145 case XSCALE_CP15_COPRO_ACCESS:
1146 //printf("xscale cp15 read coprocessor access\n");
1147 data = state->mmu.copro_access;
1148 break;
1149 default:
1150 data = 0;
1151 printf ("SKYEYE: xscale_cp15_mrc read UNKNOWN - reg %d, pc 0x%x\n", creg, state->Reg[15]);
1152 // skyeye_exit (-1);
1153 break;
1154 }
1155 *value = data;
1156 //printf("SKYEYE: xscale_cp15_mrc:end value 0x%x\n",data);
1157 return ARMul_DONE;
1158}
1159
1160void xscale_cp15_cache_ops (ARMul_State * state, ARMword instr, ARMword value)
1161{
1162//chy: 2003-08-24 now, the BTB isn't simualted ....????
1163
1164 unsigned CRm, OPC_2;
1165
1166 CRm = BITS (0, 3);
1167 OPC_2 = BITS (5, 7);
1168 //err_msg("SKYEYE: xscale cp15_cache_ops:OPC_2 = 0x%x CRm = 0x%x, Reg15 0x%x\n", OPC_2, CRm,state->Reg[15]);
1169
1170 if (OPC_2 == 0 && CRm == 7) {
1171 mmu_cache_invalidate_all (state, I_CACHE ());
1172 mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
1173 return;
1174 }
1175
1176 if (OPC_2 == 0 && CRm == 5) {
1177 mmu_cache_invalidate_all (state, I_CACHE ());
1178 return;
1179 }
1180 if (OPC_2 == 1 && CRm == 5) {
1181 mmu_cache_invalidate (state, I_CACHE (), value);
1182 return;
1183 }
1184
1185 if (OPC_2 == 0 && CRm == 6) {
1186 mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
1187 return;
1188 }
1189
1190 if (OPC_2 == 1 && CRm == 6) {
1191 mmu_cache_invalidate (state, MAIN_D_CACHE (), value);
1192 return;
1193 }
1194
1195 if (OPC_2 == 1 && CRm == 0xa) {
1196 mmu_cache_clean (state, MAIN_D_CACHE (), value);
1197 return;
1198 }
1199
1200 if (OPC_2 == 4 && CRm == 0xa) {
1201 mmu_wb_drain_all (state, WB ());
1202 return;
1203 }
1204
1205 if (OPC_2 == 6 && CRm == 5) {
1206 //chy 2004-07-19 shoud fix in the future????!!!!
1207 //printf("SKYEYE: xscale_cp15_cache_ops:invalidate BTB CANT!!!!!!!!!!\n");
1208 //exit(-1);
1209 return;
1210 }
1211
1212 if (OPC_2 == 5 && CRm == 2) {
1213 //printf("SKYEYE: cp15_c_o: A L in D C, value %x, reg15 %x\n",value, state->Reg[15]);
1214 //exit(-1);
1215 //chy 2003-09-01 for test
1216 mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
1217 return;
1218 }
1219
1220 ERROR_LOG(ARM11, "SKYEYE: xscale cp15_cache_ops:Unknown OPC_2 = 0x%x CRm = 0x%x, Reg15 0x%x\n", OPC_2, CRm, state->Reg[15]);
1221 // skyeye_exit (-1);
1222}
1223
1224static void
1225 xscale_cp15_tlb_ops (ARMul_State * state, ARMword instr,
1226 ARMword value)
1227{
1228 int CRm, OPC_2;
1229
1230 CRm = BITS (0, 3);
1231 OPC_2 = BITS (5, 7);
1232
1233
1234 //err_msg("SKYEYE:xscale_cp15_tlb_ops:OPC_2 = 0x%x CRm = 0x%x,Reg[15] 0x%x\n", OPC_2, CRm,state->Reg[15]);
1235 if (OPC_2 == 0 && CRm == 0x7) {
1236 mmu_tlb_invalidate_all (state, I_TLB ());
1237 mmu_tlb_invalidate_all (state, D_TLB ());
1238 return;
1239 }
1240
1241 if (OPC_2 == 0 && CRm == 0x5) {
1242 mmu_tlb_invalidate_all (state, I_TLB ());
1243 return;
1244 }
1245
1246 if (OPC_2 == 1 && CRm == 0x5) {
1247 mmu_tlb_invalidate_entry (state, I_TLB (), value);
1248 return;
1249 }
1250
1251 if (OPC_2 == 0 && CRm == 0x6) {
1252 mmu_tlb_invalidate_all (state, D_TLB ());
1253 return;
1254 }
1255
1256 if (OPC_2 == 1 && CRm == 0x6) {
1257 mmu_tlb_invalidate_entry (state, D_TLB (), value);
1258 return;
1259 }
1260
1261 ERROR_LOG(ARM11, "SKYEYE:xscale_cp15_tlb_ops:Unknow OPC_2 = 0x%x CRm = 0x%x,Reg[15] 0x%x\n", OPC_2, CRm, state->Reg[15]);
1262 // skyeye_exit (-1);
1263}
1264
1265
1266ARMword xscale_cp15_mcr (ARMul_State * state,
1267 unsigned type, ARMword instr, ARMword value)
1268{
1269 return xscale_mmu_mcr (state, instr, value);
1270}
1271
1272ARMword xscale_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
1273{
1274 ARMword data;
1275 unsigned opcode_2 = BITS (5, 7);
1276 unsigned CRm = BITS (0, 3);
1277 unsigned reg = BITS (16, 19);
1278 unsigned result;
1279 mmu_regnum_t creg = (mmu_regnum_t)reg;
1280
1281 //printf("SKYEYE: xscale_cp15_mcr: opcode_2 0x%x, CRm 0x%x, reg ox%x, value 0x%x, reg[15] 0x%x, instr 0x%x\n",opcode_2,CRm,reg, value, state->Reg[15], instr);
1282
1283 switch (creg) {
1284 case MMU_CONTROL:
1285 //printf("mmu_mcr wrote CONTROL val 0x%x \n",value);
1286 state->mmu.control =
1287 (opcode_2 ? (value & 0x33) : (value & 0x3FFF));
1288 break;
1289 case MMU_TRANSLATION_TABLE_BASE:
1290 //printf("mmu_mcr wrote TTB val 0x%x \n",value);
1291 state->mmu.translation_table_base = value & 0xFFFFC000;
1292 break;
1293 case MMU_DOMAIN_ACCESS_CONTROL:
1294 //printf("mmu_mcr wrote DACR val 0x%x \n",value);
1295 state->mmu.domain_access_control = value;
1296 break;
1297
1298 case MMU_FAULT_STATUS:
1299 //printf("mmu_mcr wrote FS val 0x%x \n",value);
1300 state->mmu.fault_status = value & 0x6FF;
1301 break;
1302 case MMU_FAULT_ADDRESS:
1303 //printf("mmu_mcr wrote FA val 0x%x \n",value);
1304 state->mmu.fault_address = value;
1305 break;
1306
1307 case MMU_CACHE_OPS:
1308// printf("mmu_mcr wrote CO val 0x%x \n",value);
1309 xscale_cp15_cache_ops (state, instr, value);
1310 break;
1311 case MMU_TLB_OPS:
1312 //printf("mmu_mcr wrote TO val 0x%x \n",value);
1313 xscale_cp15_tlb_ops (state, instr, value);
1314 break;
1315 case MMU_PID:
1316 //printf("mmu_mcr wrote PID val 0x%x \n",value);
1317 state->mmu.process_id = value & 0xfe000000;
1318 break;
1319 case XSCALE_CP15_COPRO_ACCESS:
1320 //printf("xscale cp15 write coprocessor access val 0x %x\n",value);
1321 state->mmu.copro_access = value & 0x3ff;
1322 break;
1323
1324 default:
1325 printf ("SKYEYE: xscale_cp15_mcr wrote UNKNOWN - reg %d, reg15 0x%x\n", creg, state->Reg[15]);
1326 break;
1327 }
1328 //printf("SKYEYE: xscale_cp15_mcr wrote val 0x%x\n", value);
1329 return 0;
1330}
1331
1332//teawater add for arm2x86 2005.06.24-------------------------------------------
1333static int xscale_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr,
1334 ARMword * phys_addr)
1335{
1336 fault_t fault;
1337 tlb_entry_t *tlb;
1338
1339 virt_addr = mmu_pid_va_map (virt_addr);
1340 if (MMU_Enabled) {
1341
1342 /*align check */
1343 if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) {
1344 DEBUG_LOG(ARM11, "align\n");
1345 return ALIGNMENT_FAULT;
1346 }
1347 else
1348 virt_addr &= ~(WORD_SIZE - 1);
1349
1350 /*translate tlb */
1351 fault = translate (state, virt_addr, I_TLB (), &tlb);
1352 if (fault) {
1353 DEBUG_LOG(ARM11, "translate\n");
1354 return fault;
1355 }
1356
1357 /*check access */
1358 fault = check_access (state, virt_addr, tlb, 1);
1359 if (fault) {
1360 DEBUG_LOG(ARM11, "check_fault\n");
1361 return fault;
1362 }
1363 }
1364
1365 if (MMU_Disabled) {
1366 *phys_addr = virt_addr;
1367 }
1368 else {
1369 *phys_addr = tlb_va_to_pa (tlb, virt_addr);
1370 }
1371
1372 return (0);
1373}
1374
1375//AJ2D--------------------------------------------------------------------------
1376
1377/*xscale mmu_ops_t*/
1378//mmu_ops_t xscale_mmu_ops = {
1379// xscale_cp15_init,
1380// xscale_cp15_exit,
1381// xscale_mmu_read_byte,
1382// xscale_mmu_write_byte,
1383// xscale_mmu_read_halfword,
1384// xscale_mmu_write_halfword,
1385// xscale_mmu_read_word,
1386// xscale_mmu_write_word,
1387// xscale_mmu_load_instr, xscale_mmu_mcr, xscale_mmu_mrc,
1388////teawater add for arm2x86 2005.06.24-------------------------------------------
1389// xscale_mmu_v2p_dbct,
1390////AJ2D--------------------------------------------------------------------------
1391//};
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..f738a615b
--- /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(...) DEBUG_LOG(ARM11, __VA_ARGS__)
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);
87u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
88u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 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..cd5b5afa4
--- /dev/null
+++ b/src/core/arm/interpreter/vfp/vfpdouble.cpp
@@ -0,0 +1,1263 @@
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 "core/arm/interpreter/vfp/vfp.h"
55#include "core/arm/interpreter/vfp/vfp_helper.h"
56#include "core/arm/interpreter/vfp/asm_vfp.h"
57
58static struct vfp_double vfp_double_default_qnan = {
59 //.exponent = 2047,
60 //.sign = 0,
61 //.significand = VFP_DOUBLE_SIGNIFICAND_QNAN,
62};
63
64static void vfp_double_dump(const char *str, struct vfp_double *d)
65{
66 pr_debug("VFP: %s: sign=%d exponent=%d significand=%016llx\n",
67 str, d->sign != 0, d->exponent, d->significand);
68}
69
70static void vfp_double_normalise_denormal(struct vfp_double *vd)
71{
72 int bits = 31 - fls(vd->significand >> 32);
73 if (bits == 31)
74 bits = 63 - fls(vd->significand);
75
76 vfp_double_dump("normalise_denormal: in", vd);
77
78 if (bits) {
79 vd->exponent -= bits - 1;
80 vd->significand <<= bits;
81 }
82
83 vfp_double_dump("normalise_denormal: out", vd);
84}
85
86u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func)
87{
88 u64 significand, incr;
89 int exponent, shift, underflow;
90 u32 rmode;
91
92 vfp_double_dump("pack: in", vd);
93
94 /*
95 * Infinities and NaNs are a special case.
96 */
97 if (vd->exponent == 2047 && (vd->significand == 0 || exceptions))
98 goto pack;
99
100 /*
101 * Special-case zero.
102 */
103 if (vd->significand == 0) {
104 vd->exponent = 0;
105 goto pack;
106 }
107
108 exponent = vd->exponent;
109 significand = vd->significand;
110
111 shift = 32 - fls(significand >> 32);
112 if (shift == 32)
113 shift = 64 - fls(significand);
114 if (shift) {
115 exponent -= shift;
116 significand <<= shift;
117 }
118
119#if 1
120 vd->exponent = exponent;
121 vd->significand = significand;
122 vfp_double_dump("pack: normalised", vd);
123#endif
124
125 /*
126 * Tiny number?
127 */
128 underflow = exponent < 0;
129 if (underflow) {
130 significand = vfp_shiftright64jamming(significand, -exponent);
131 exponent = 0;
132#if 1
133 vd->exponent = exponent;
134 vd->significand = significand;
135 vfp_double_dump("pack: tiny number", vd);
136#endif
137 if (!(significand & ((1ULL << (VFP_DOUBLE_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 = 1ULL << VFP_DOUBLE_LOW_BITS;
149 if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0)
150 incr -= 1;
151 } else if (rmode == FPSCR_ROUND_TOZERO) {
152 incr = 0;
153 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0))
154 incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1;
155
156 pr_debug("VFP: rounding increment = 0x%08llx\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 vd->exponent = exponent;
167 vd->significand = significand;
168 vfp_double_dump("pack: overflow", vd);
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_DOUBLE_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 >= 2046) {
188 exceptions |= FPSCR_OFC | FPSCR_IXC;
189 if (incr == 0) {
190 vd->exponent = 2045;
191 vd->significand = 0x7fffffffffffffffULL;
192 } else {
193 vd->exponent = 2047; /* infinity */
194 vd->significand = 0;
195 }
196 } else {
197 if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0)
198 exponent = 0;
199 if (exponent || significand > 0x8000000000000000ULL)
200 underflow = 0;
201 if (underflow)
202 exceptions |= FPSCR_UFC;
203 vd->exponent = exponent;
204 vd->significand = significand >> 1;
205 }
206
207 pack:
208 vfp_double_dump("pack: final", vd);
209 {
210 s64 d = vfp_double_pack(vd);
211 pr_debug("VFP: %s: d(d%d)=%016llx exceptions=%08x\n", func,
212 dd, d, exceptions);
213 vfp_put_double(state, d, dd);
214 }
215 return exceptions;
216}
217
218/*
219 * Propagate the NaN, setting exceptions if it is signalling.
220 * 'n' is always a NaN. 'm' may be a number, NaN or infinity.
221 */
222static u32
223vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn,
224 struct vfp_double *vdm, u32 fpscr)
225{
226 struct vfp_double *nan;
227 int tn, tm = 0;
228
229 tn = vfp_double_type(vdn);
230
231 if (vdm)
232 tm = vfp_double_type(vdm);
233
234 if (fpscr & FPSCR_DEFAULT_NAN)
235 /*
236 * Default NaN mode - always returns a quiet NaN
237 */
238 nan = &vfp_double_default_qnan;
239 else {
240 /*
241 * Contemporary mode - select the first signalling
242 * NAN, or if neither are signalling, the first
243 * quiet NAN.
244 */
245 if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN))
246 nan = vdn;
247 else
248 nan = vdm;
249 /*
250 * Make the NaN quiet.
251 */
252 nan->significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
253 }
254
255 *vdd = *nan;
256
257 /*
258 * If one was a signalling NAN, raise invalid operation.
259 */
260 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG;
261}
262
263/*
264 * Extended operations
265 */
266static u32 vfp_double_fabs(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
267{
268 pr_debug("In %s\n", __FUNCTION__);
269 vfp_put_double(state, vfp_double_packed_abs(vfp_get_double(state, dm)), dd);
270 return 0;
271}
272
273static u32 vfp_double_fcpy(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
274{
275 pr_debug("In %s\n", __FUNCTION__);
276 vfp_put_double(state, vfp_get_double(state, dm), dd);
277 return 0;
278}
279
280static u32 vfp_double_fneg(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
281{
282 pr_debug("In %s\n", __FUNCTION__);
283 vfp_put_double(state, vfp_double_packed_negate(vfp_get_double(state, dm)), dd);
284 return 0;
285}
286
287static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
288{
289 pr_debug("In %s\n", __FUNCTION__);
290 struct vfp_double vdm, vdd, *vdp;
291 int ret, tm;
292
293 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
294 tm = vfp_double_type(&vdm);
295 if (tm & (VFP_NAN|VFP_INFINITY)) {
296 vdp = &vdd;
297
298 if (tm & VFP_NAN)
299 ret = vfp_propagate_nan(vdp, &vdm, NULL, fpscr);
300 else if (vdm.sign == 0) {
301 sqrt_copy:
302 vdp = &vdm;
303 ret = 0;
304 } else {
305 sqrt_invalid:
306 vdp = &vfp_double_default_qnan;
307 ret = FPSCR_IOC;
308 }
309 vfp_put_double(state, vfp_double_pack(vdp), dd);
310 return ret;
311 }
312
313 /*
314 * sqrt(+/- 0) == +/- 0
315 */
316 if (tm & VFP_ZERO)
317 goto sqrt_copy;
318
319 /*
320 * Normalise a denormalised number
321 */
322 if (tm & VFP_DENORMAL)
323 vfp_double_normalise_denormal(&vdm);
324
325 /*
326 * sqrt(<0) = invalid
327 */
328 if (vdm.sign)
329 goto sqrt_invalid;
330
331 vfp_double_dump("sqrt", &vdm);
332
333 /*
334 * Estimate the square root.
335 */
336 vdd.sign = 0;
337 vdd.exponent = ((vdm.exponent - 1023) >> 1) + 1023;
338 vdd.significand = (u64)vfp_estimate_sqrt_significand(vdm.exponent, vdm.significand >> 32) << 31;
339
340 vfp_double_dump("sqrt estimate1", &vdd);
341
342 vdm.significand >>= 1 + (vdm.exponent & 1);
343 vdd.significand += 2 + vfp_estimate_div128to64(vdm.significand, 0, vdd.significand);
344
345 vfp_double_dump("sqrt estimate2", &vdd);
346
347 /*
348 * And now adjust.
349 */
350 if ((vdd.significand & VFP_DOUBLE_LOW_BITS_MASK) <= 5) {
351 if (vdd.significand < 2) {
352 vdd.significand = ~0ULL;
353 } else {
354 u64 termh, terml, remh, reml;
355 vdm.significand <<= 2;
356 mul64to128(&termh, &terml, vdd.significand, vdd.significand);
357 sub128(&remh, &reml, vdm.significand, 0, termh, terml);
358 while ((s64)remh < 0) {
359 vdd.significand -= 1;
360 shift64left(&termh, &terml, vdd.significand);
361 terml |= 1;
362 add128(&remh, &reml, remh, reml, termh, terml);
363 }
364 vdd.significand |= (remh | reml) != 0;
365 }
366 }
367 vdd.significand = vfp_shiftright64jamming(vdd.significand, 1);
368
369 return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fsqrt");
370}
371
372/*
373 * Equal := ZC
374 * Less than := N
375 * Greater than := C
376 * Unordered := CV
377 */
378static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u32 fpscr)
379{
380 s64 d, m;
381 u32 ret = 0;
382
383 pr_debug("In %s, state=0x%x, fpscr=0x%x\n", __FUNCTION__, state, fpscr);
384 m = vfp_get_double(state, dm);
385 if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) {
386 ret |= FPSCR_C | FPSCR_V;
387 if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
388 /*
389 * Signalling NaN, or signalling on quiet NaN
390 */
391 ret |= FPSCR_IOC;
392 }
393
394 d = vfp_get_double(state, dd);
395 if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) {
396 ret |= FPSCR_C | FPSCR_V;
397 if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
398 /*
399 * Signalling NaN, or signalling on quiet NaN
400 */
401 ret |= FPSCR_IOC;
402 }
403
404 if (ret == 0) {
405 //printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m);
406 if (d == m || vfp_double_packed_abs(d | m) == 0) {
407 /*
408 * equal
409 */
410 ret |= FPSCR_Z | FPSCR_C;
411 //printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret);
412 } else if (vfp_double_packed_sign(d ^ m)) {
413 /*
414 * different signs
415 */
416 if (vfp_double_packed_sign(d))
417 /*
418 * d is negative, so d < m
419 */
420 ret |= FPSCR_N;
421 else
422 /*
423 * d is positive, so d > m
424 */
425 ret |= FPSCR_C;
426 } else if ((vfp_double_packed_sign(d) != 0) ^ (d < m)) {
427 /*
428 * d < m
429 */
430 ret |= FPSCR_N;
431 } else if ((vfp_double_packed_sign(d) != 0) ^ (d > m)) {
432 /*
433 * d > m
434 */
435 ret |= FPSCR_C;
436 }
437 }
438 pr_debug("In %s, state=0x%x, ret=0x%x\n", __FUNCTION__, state, ret);
439
440 return ret;
441}
442
443static u32 vfp_double_fcmp(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
444{
445 pr_debug("In %s\n", __FUNCTION__);
446 return vfp_compare(state, dd, 0, dm, fpscr);
447}
448
449static u32 vfp_double_fcmpe(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
450{
451 pr_debug("In %s\n", __FUNCTION__);
452 return vfp_compare(state, dd, 1, dm, fpscr);
453}
454
455static u32 vfp_double_fcmpz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
456{
457 pr_debug("In %s\n", __FUNCTION__);
458 return vfp_compare(state, dd, 0, VFP_REG_ZERO, fpscr);
459}
460
461static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
462{
463 pr_debug("In %s\n", __FUNCTION__);
464 return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr);
465}
466
467static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
468{
469 struct vfp_double vdm;
470 struct vfp_single vsd;
471 int tm;
472 u32 exceptions = 0;
473
474 pr_debug("In %s\n", __FUNCTION__);
475 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
476
477 tm = vfp_double_type(&vdm);
478
479 /*
480 * If we have a signalling NaN, signal invalid operation.
481 */
482 if (tm == VFP_SNAN)
483 exceptions = FPSCR_IOC;
484
485 if (tm & VFP_DENORMAL)
486 vfp_double_normalise_denormal(&vdm);
487
488 vsd.sign = vdm.sign;
489 vsd.significand = vfp_hi64to32jamming(vdm.significand);
490
491 /*
492 * If we have an infinity or a NaN, the exponent must be 255
493 */
494 if (tm & (VFP_INFINITY|VFP_NAN)) {
495 vsd.exponent = 255;
496 if (tm == VFP_QNAN)
497 vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
498 goto pack_nan;
499 } else if (tm & VFP_ZERO)
500 vsd.exponent = 0;
501 else
502 vsd.exponent = vdm.exponent - (1023 - 127);
503
504 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fcvts");
505
506 pack_nan:
507 vfp_put_float(state, vfp_single_pack(&vsd), sd);
508 return exceptions;
509}
510
511static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
512{
513 struct vfp_double vdm;
514 u32 m = vfp_get_float(state, dm);
515
516 pr_debug("In %s\n", __FUNCTION__);
517 vdm.sign = 0;
518 vdm.exponent = 1023 + 63 - 1;
519 vdm.significand = (u64)m;
520
521 return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fuito");
522}
523
524static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
525{
526 struct vfp_double vdm;
527 u32 m = vfp_get_float(state, dm);
528
529 pr_debug("In %s\n", __FUNCTION__);
530 vdm.sign = (m & 0x80000000) >> 16;
531 vdm.exponent = 1023 + 63 - 1;
532 vdm.significand = vdm.sign ? -m : m;
533
534 return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fsito");
535}
536
537static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
538{
539 struct vfp_double vdm;
540 u32 d, exceptions = 0;
541 int rmode = fpscr & FPSCR_RMODE_MASK;
542 int tm;
543
544 pr_debug("In %s\n", __FUNCTION__);
545 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
546
547 /*
548 * Do we have a denormalised number?
549 */
550 tm = vfp_double_type(&vdm);
551 if (tm & VFP_DENORMAL)
552 exceptions |= FPSCR_IDC;
553
554 if (tm & VFP_NAN)
555 vdm.sign = 0;
556
557 if (vdm.exponent >= 1023 + 32) {
558 d = vdm.sign ? 0 : 0xffffffff;
559 exceptions = FPSCR_IOC;
560 } else if (vdm.exponent >= 1023 - 1) {
561 int shift = 1023 + 63 - vdm.exponent;
562 u64 rem, incr = 0;
563
564 /*
565 * 2^0 <= m < 2^32-2^8
566 */
567 d = (vdm.significand << 1) >> shift;
568 rem = vdm.significand << (65 - shift);
569
570 if (rmode == FPSCR_ROUND_NEAREST) {
571 incr = 0x8000000000000000ULL;
572 if ((d & 1) == 0)
573 incr -= 1;
574 } else if (rmode == FPSCR_ROUND_TOZERO) {
575 incr = 0;
576 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) {
577 incr = ~0ULL;
578 }
579
580 if ((rem + incr) < rem) {
581 if (d < 0xffffffff)
582 d += 1;
583 else
584 exceptions |= FPSCR_IOC;
585 }
586
587 if (d && vdm.sign) {
588 d = 0;
589 exceptions |= FPSCR_IOC;
590 } else if (rem)
591 exceptions |= FPSCR_IXC;
592 } else {
593 d = 0;
594 if (vdm.exponent | vdm.significand) {
595 exceptions |= FPSCR_IXC;
596 if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0)
597 d = 1;
598 else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) {
599 d = 0;
600 exceptions |= FPSCR_IOC;
601 }
602 }
603 }
604
605 pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
606
607 vfp_put_float(state, d, sd);
608
609 return exceptions;
610}
611
612static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
613{
614 pr_debug("In %s\n", __FUNCTION__);
615 return vfp_double_ftoui(state, sd, unused, dm, FPSCR_ROUND_TOZERO);
616}
617
618static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
619{
620 struct vfp_double vdm;
621 u32 d, exceptions = 0;
622 int rmode = fpscr & FPSCR_RMODE_MASK;
623 int tm;
624
625 pr_debug("In %s\n", __FUNCTION__);
626 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
627 vfp_double_dump("VDM", &vdm);
628
629 /*
630 * Do we have denormalised number?
631 */
632 tm = vfp_double_type(&vdm);
633 if (tm & VFP_DENORMAL)
634 exceptions |= FPSCR_IDC;
635
636 if (tm & VFP_NAN) {
637 d = 0;
638 exceptions |= FPSCR_IOC;
639 } else if (vdm.exponent >= 1023 + 32) {
640 d = 0x7fffffff;
641 if (vdm.sign)
642 d = ~d;
643 exceptions |= FPSCR_IOC;
644 } else if (vdm.exponent >= 1023 - 1) {
645 int shift = 1023 + 63 - vdm.exponent; /* 58 */
646 u64 rem, incr = 0;
647
648 d = (vdm.significand << 1) >> shift;
649 rem = vdm.significand << (65 - shift);
650
651 if (rmode == FPSCR_ROUND_NEAREST) {
652 incr = 0x8000000000000000ULL;
653 if ((d & 1) == 0)
654 incr -= 1;
655 } else if (rmode == FPSCR_ROUND_TOZERO) {
656 incr = 0;
657 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) {
658 incr = ~0ULL;
659 }
660
661 if ((rem + incr) < rem && d < 0xffffffff)
662 d += 1;
663 if (d > 0x7fffffff + (vdm.sign != 0)) {
664 d = 0x7fffffff + (vdm.sign != 0);
665 exceptions |= FPSCR_IOC;
666 } else if (rem)
667 exceptions |= FPSCR_IXC;
668
669 if (vdm.sign)
670 d = -d;
671 } else {
672 d = 0;
673 if (vdm.exponent | vdm.significand) {
674 exceptions |= FPSCR_IXC;
675 if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0)
676 d = 1;
677 else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign)
678 d = -1;
679 }
680 }
681
682 pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
683
684 vfp_put_float(state, (s32)d, sd);
685
686 return exceptions;
687}
688
689static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
690{
691 pr_debug("In %s\n", __FUNCTION__);
692 return vfp_double_ftosi(state, dd, unused, dm, FPSCR_ROUND_TOZERO);
693}
694
695static struct op fops_ext[] = {
696 { vfp_double_fcpy, 0 }, //0x00000000 - FEXT_FCPY
697 { vfp_double_fabs, 0 }, //0x00000001 - FEXT_FABS
698 { vfp_double_fneg, 0 }, //0x00000002 - FEXT_FNEG
699 { vfp_double_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT
700 { NULL, 0 },
701 { NULL, 0 },
702 { NULL, 0 },
703 { NULL, 0 },
704 { vfp_double_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP
705 { vfp_double_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE
706 { vfp_double_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ
707 { vfp_double_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ
708 { NULL, 0 },
709 { NULL, 0 },
710 { NULL, 0 },
711 { vfp_double_fcvts, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT
712 { vfp_double_fuito, OP_SCALAR }, //0x00000010 - FEXT_FUITO
713 { vfp_double_fsito, OP_SCALAR }, //0x00000011 - FEXT_FSITO
714 { NULL, 0 },
715 { NULL, 0 },
716 { NULL, 0 },
717 { NULL, 0 },
718 { NULL, 0 },
719 { NULL, 0 },
720 { vfp_double_ftoui, OP_SCALAR }, //0x00000018 - FEXT_FTOUI
721 { vfp_double_ftouiz, OP_SCALAR }, //0x00000019 - FEXT_FTOUIZ
722 { vfp_double_ftosi, OP_SCALAR }, //0x0000001A - FEXT_FTOSI
723 { vfp_double_ftosiz, OP_SCALAR }, //0x0000001B - FEXT_FTOSIZ
724};
725
726
727
728
729static u32
730vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn,
731 struct vfp_double *vdm, u32 fpscr)
732{
733 struct vfp_double *vdp;
734 u32 exceptions = 0;
735 int tn, tm;
736
737 tn = vfp_double_type(vdn);
738 tm = vfp_double_type(vdm);
739
740 if (tn & tm & VFP_INFINITY) {
741 /*
742 * Two infinities. Are they different signs?
743 */
744 if (vdn->sign ^ vdm->sign) {
745 /*
746 * different signs -> invalid
747 */
748 exceptions = FPSCR_IOC;
749 vdp = &vfp_double_default_qnan;
750 } else {
751 /*
752 * same signs -> valid
753 */
754 vdp = vdn;
755 }
756 } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) {
757 /*
758 * One infinity and one number -> infinity
759 */
760 vdp = vdn;
761 } else {
762 /*
763 * 'n' is a NaN of some type
764 */
765 return vfp_propagate_nan(vdd, vdn, vdm, fpscr);
766 }
767 *vdd = *vdp;
768 return exceptions;
769}
770
771static u32
772vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,
773 struct vfp_double *vdm, u32 fpscr)
774{
775 u32 exp_diff;
776 u64 m_sig;
777
778 if (vdn->significand & (1ULL << 63) ||
779 vdm->significand & (1ULL << 63)) {
780 pr_info("VFP: bad FP values\n");
781 vfp_double_dump("VDN", vdn);
782 vfp_double_dump("VDM", vdm);
783 }
784
785 /*
786 * Ensure that 'n' is the largest magnitude number. Note that
787 * if 'n' and 'm' have equal exponents, we do not swap them.
788 * This ensures that NaN propagation works correctly.
789 */
790 if (vdn->exponent < vdm->exponent) {
791 struct vfp_double *t = vdn;
792 vdn = vdm;
793 vdm = t;
794 }
795
796 /*
797 * Is 'n' an infinity or a NaN? Note that 'm' may be a number,
798 * infinity or a NaN here.
799 */
800 if (vdn->exponent == 2047)
801 return vfp_double_fadd_nonnumber(vdd, vdn, vdm, fpscr);
802
803 /*
804 * We have two proper numbers, where 'vdn' is the larger magnitude.
805 *
806 * Copy 'n' to 'd' before doing the arithmetic.
807 */
808 *vdd = *vdn;
809
810 /*
811 * Align 'm' with the result.
812 */
813 exp_diff = vdn->exponent - vdm->exponent;
814 m_sig = vfp_shiftright64jamming(vdm->significand, exp_diff);
815
816 /*
817 * If the signs are different, we are really subtracting.
818 */
819 if (vdn->sign ^ vdm->sign) {
820 m_sig = vdn->significand - m_sig;
821 if ((s64)m_sig < 0) {
822 vdd->sign = vfp_sign_negate(vdd->sign);
823 m_sig = -m_sig;
824 } else if (m_sig == 0) {
825 vdd->sign = (fpscr & FPSCR_RMODE_MASK) ==
826 FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
827 }
828 } else {
829 m_sig += vdn->significand;
830 }
831 vdd->significand = m_sig;
832
833 return 0;
834}
835
836static u32
837vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn,
838 struct vfp_double *vdm, u32 fpscr)
839{
840 vfp_double_dump("VDN", vdn);
841 vfp_double_dump("VDM", vdm);
842
843 /*
844 * Ensure that 'n' is the largest magnitude number. Note that
845 * if 'n' and 'm' have equal exponents, we do not swap them.
846 * This ensures that NaN propagation works correctly.
847 */
848 if (vdn->exponent < vdm->exponent) {
849 struct vfp_double *t = vdn;
850 vdn = vdm;
851 vdm = t;
852 pr_debug("VFP: swapping M <-> N\n");
853 }
854
855 vdd->sign = vdn->sign ^ vdm->sign;
856
857 /*
858 * If 'n' is an infinity or NaN, handle it. 'm' may be anything.
859 */
860 if (vdn->exponent == 2047) {
861 if (vdn->significand || (vdm->exponent == 2047 && vdm->significand))
862 return vfp_propagate_nan(vdd, vdn, vdm, fpscr);
863 if ((vdm->exponent | vdm->significand) == 0) {
864 *vdd = vfp_double_default_qnan;
865 return FPSCR_IOC;
866 }
867 vdd->exponent = vdn->exponent;
868 vdd->significand = 0;
869 return 0;
870 }
871
872 /*
873 * If 'm' is zero, the result is always zero. In this case,
874 * 'n' may be zero or a number, but it doesn't matter which.
875 */
876 if ((vdm->exponent | vdm->significand) == 0) {
877 vdd->exponent = 0;
878 vdd->significand = 0;
879 return 0;
880 }
881
882 /*
883 * We add 2 to the destination exponent for the same reason
884 * as the addition case - though this time we have +1 from
885 * each input operand.
886 */
887 vdd->exponent = vdn->exponent + vdm->exponent - 1023 + 2;
888 vdd->significand = vfp_hi64multiply64(vdn->significand, vdm->significand);
889
890 vfp_double_dump("VDD", vdd);
891 return 0;
892}
893
894#define NEG_MULTIPLY (1 << 0)
895#define NEG_SUBTRACT (1 << 1)
896
897static u32
898vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr, u32 negate, char *func)
899{
900 struct vfp_double vdd, vdp, vdn, vdm;
901 u32 exceptions;
902
903 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
904 if (vdn.exponent == 0 && vdn.significand)
905 vfp_double_normalise_denormal(&vdn);
906
907 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
908 if (vdm.exponent == 0 && vdm.significand)
909 vfp_double_normalise_denormal(&vdm);
910
911 exceptions = vfp_double_multiply(&vdp, &vdn, &vdm, fpscr);
912 if (negate & NEG_MULTIPLY)
913 vdp.sign = vfp_sign_negate(vdp.sign);
914
915 vfp_double_unpack(&vdn, vfp_get_double(state, dd));
916 if (negate & NEG_SUBTRACT)
917 vdn.sign = vfp_sign_negate(vdn.sign);
918
919 exceptions |= vfp_double_add(&vdd, &vdn, &vdp, fpscr);
920
921 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, func);
922}
923
924/*
925 * Standard operations
926 */
927
928/*
929 * sd = sd + (sn * sm)
930 */
931static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
932{
933 pr_debug("In %s\n", __FUNCTION__);
934 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, 0, "fmac");
935}
936
937/*
938 * sd = sd - (sn * sm)
939 */
940static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
941{
942 pr_debug("In %s\n", __FUNCTION__);
943 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac");
944}
945
946/*
947 * sd = -sd + (sn * sm)
948 */
949static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
950{
951 pr_debug("In %s\n", __FUNCTION__);
952 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc");
953}
954
955/*
956 * sd = -sd - (sn * sm)
957 */
958static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
959{
960 pr_debug("In %s\n", __FUNCTION__);
961 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
962}
963
964/*
965 * sd = sn * sm
966 */
967static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
968{
969 struct vfp_double vdd, vdn, vdm;
970 u32 exceptions;
971
972 pr_debug("In %s\n", __FUNCTION__);
973 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
974 if (vdn.exponent == 0 && vdn.significand)
975 vfp_double_normalise_denormal(&vdn);
976
977 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
978 if (vdm.exponent == 0 && vdm.significand)
979 vfp_double_normalise_denormal(&vdm);
980
981 exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr);
982 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fmul");
983}
984
985/*
986 * sd = -(sn * sm)
987 */
988static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
989{
990 struct vfp_double vdd, vdn, vdm;
991 u32 exceptions;
992
993 pr_debug("In %s\n", __FUNCTION__);
994 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
995 if (vdn.exponent == 0 && vdn.significand)
996 vfp_double_normalise_denormal(&vdn);
997
998 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
999 if (vdm.exponent == 0 && vdm.significand)
1000 vfp_double_normalise_denormal(&vdm);
1001
1002 exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr);
1003 vdd.sign = vfp_sign_negate(vdd.sign);
1004
1005 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fnmul");
1006}
1007
1008/*
1009 * sd = sn + sm
1010 */
1011static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
1012{
1013 struct vfp_double vdd, vdn, vdm;
1014 u32 exceptions;
1015
1016 pr_debug("In %s\n", __FUNCTION__);
1017 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
1018 if (vdn.exponent == 0 && vdn.significand)
1019 vfp_double_normalise_denormal(&vdn);
1020
1021 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
1022 if (vdm.exponent == 0 && vdm.significand)
1023 vfp_double_normalise_denormal(&vdm);
1024
1025 exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr);
1026
1027 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fadd");
1028}
1029
1030/*
1031 * sd = sn - sm
1032 */
1033static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
1034{
1035 struct vfp_double vdd, vdn, vdm;
1036 u32 exceptions;
1037
1038 pr_debug("In %s\n", __FUNCTION__);
1039 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
1040 if (vdn.exponent == 0 && vdn.significand)
1041 vfp_double_normalise_denormal(&vdn);
1042
1043 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
1044 if (vdm.exponent == 0 && vdm.significand)
1045 vfp_double_normalise_denormal(&vdm);
1046
1047 /*
1048 * Subtraction is like addition, but with a negated operand.
1049 */
1050 vdm.sign = vfp_sign_negate(vdm.sign);
1051
1052 exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr);
1053
1054 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fsub");
1055}
1056
1057/*
1058 * sd = sn / sm
1059 */
1060static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
1061{
1062 struct vfp_double vdd, vdn, vdm;
1063 u32 exceptions = 0;
1064 int tm, tn;
1065
1066 pr_debug("In %s\n", __FUNCTION__);
1067 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
1068 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
1069
1070 vdd.sign = vdn.sign ^ vdm.sign;
1071
1072 tn = vfp_double_type(&vdn);
1073 tm = vfp_double_type(&vdm);
1074
1075 /*
1076 * Is n a NAN?
1077 */
1078 if (tn & VFP_NAN)
1079 goto vdn_nan;
1080
1081 /*
1082 * Is m a NAN?
1083 */
1084 if (tm & VFP_NAN)
1085 goto vdm_nan;
1086
1087 /*
1088 * If n and m are infinity, the result is invalid
1089 * If n and m are zero, the result is invalid
1090 */
1091 if (tm & tn & (VFP_INFINITY|VFP_ZERO))
1092 goto invalid;
1093
1094 /*
1095 * If n is infinity, the result is infinity
1096 */
1097 if (tn & VFP_INFINITY)
1098 goto infinity;
1099
1100 /*
1101 * If m is zero, raise div0 exceptions
1102 */
1103 if (tm & VFP_ZERO)
1104 goto divzero;
1105
1106 /*
1107 * If m is infinity, or n is zero, the result is zero
1108 */
1109 if (tm & VFP_INFINITY || tn & VFP_ZERO)
1110 goto zero;
1111
1112 if (tn & VFP_DENORMAL)
1113 vfp_double_normalise_denormal(&vdn);
1114 if (tm & VFP_DENORMAL)
1115 vfp_double_normalise_denormal(&vdm);
1116
1117 /*
1118 * Ok, we have two numbers, we can perform division.
1119 */
1120 vdd.exponent = vdn.exponent - vdm.exponent + 1023 - 1;
1121 vdm.significand <<= 1;
1122 if (vdm.significand <= (2 * vdn.significand)) {
1123 vdn.significand >>= 1;
1124 vdd.exponent++;
1125 }
1126 vdd.significand = vfp_estimate_div128to64(vdn.significand, 0, vdm.significand);
1127 if ((vdd.significand & 0x1ff) <= 2) {
1128 u64 termh, terml, remh, reml;
1129 mul64to128(&termh, &terml, vdm.significand, vdd.significand);
1130 sub128(&remh, &reml, vdn.significand, 0, termh, terml);
1131 while ((s64)remh < 0) {
1132 vdd.significand -= 1;
1133 add128(&remh, &reml, remh, reml, 0, vdm.significand);
1134 }
1135 vdd.significand |= (reml != 0);
1136 }
1137 return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fdiv");
1138
1139 vdn_nan:
1140 exceptions = vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr);
1141 pack:
1142 vfp_put_double(state, vfp_double_pack(&vdd), dd);
1143 return exceptions;
1144
1145 vdm_nan:
1146 exceptions = vfp_propagate_nan(&vdd, &vdm, &vdn, fpscr);
1147 goto pack;
1148
1149 zero:
1150 vdd.exponent = 0;
1151 vdd.significand = 0;
1152 goto pack;
1153
1154 divzero:
1155 exceptions = FPSCR_DZC;
1156 infinity:
1157 vdd.exponent = 2047;
1158 vdd.significand = 0;
1159 goto pack;
1160
1161 invalid:
1162 vfp_put_double(state, vfp_double_pack(&vfp_double_default_qnan), dd);
1163 return FPSCR_IOC;
1164}
1165
1166static struct op fops[] = {
1167 { vfp_double_fmac, 0 },
1168 { vfp_double_fmsc, 0 },
1169 { vfp_double_fmul, 0 },
1170 { vfp_double_fadd, 0 },
1171 { vfp_double_fnmac, 0 },
1172 { vfp_double_fnmsc, 0 },
1173 { vfp_double_fnmul, 0 },
1174 { vfp_double_fsub, 0 },
1175 { vfp_double_fdiv, 0 },
1176};
1177
1178#define FREG_BANK(x) ((x) & 0x0c)
1179#define FREG_IDX(x) ((x) & 3)
1180
1181u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1182{
1183 u32 op = inst & FOP_MASK;
1184 u32 exceptions = 0;
1185 unsigned int dest;
1186 unsigned int dn = vfp_get_dn(inst);
1187 unsigned int dm;
1188 unsigned int vecitr, veclen, vecstride;
1189 struct op *fop;
1190
1191 pr_debug("In %s\n", __FUNCTION__);
1192 vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK));
1193
1194 fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
1195
1196 /*
1197 * fcvtds takes an sN register number as destination, not dN.
1198 * It also always operates on scalars.
1199 */
1200 if (fop->flags & OP_SD)
1201 dest = vfp_get_sd(inst);
1202 else
1203 dest = vfp_get_dd(inst);
1204
1205 /*
1206 * f[us]ito takes a sN operand, not a dN operand.
1207 */
1208 if (fop->flags & OP_SM)
1209 dm = vfp_get_sm(inst);
1210 else
1211 dm = vfp_get_dm(inst);
1212
1213 /*
1214 * If destination bank is zero, vector length is always '1'.
1215 * ARM DDI0100F C5.1.3, C5.3.2.
1216 */
1217 if ((fop->flags & OP_SCALAR) || (FREG_BANK(dest) == 0))
1218 veclen = 0;
1219 else
1220 veclen = fpscr & FPSCR_LENGTH_MASK;
1221
1222 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
1223 (veclen >> FPSCR_LENGTH_BIT) + 1);
1224
1225 if (!fop->fn) {
1226 printf("VFP: could not find double op %d\n", FEXT_TO_IDX(inst));
1227 goto invalid;
1228 }
1229
1230 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
1231 u32 except;
1232 char type;
1233
1234 type = fop->flags & OP_SD ? 's' : 'd';
1235 if (op == FOP_EXT)
1236 pr_debug("VFP: itr%d (%c%u) = op[%u] (d%u)\n",
1237 vecitr >> FPSCR_LENGTH_BIT,
1238 type, dest, dn, dm);
1239 else
1240 pr_debug("VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)\n",
1241 vecitr >> FPSCR_LENGTH_BIT,
1242 type, dest, dn, FOP_TO_IDX(op), dm);
1243
1244 except = fop->fn(state, dest, dn, dm, fpscr);
1245 pr_debug("VFP: itr%d: exceptions=%08x\n",
1246 vecitr >> FPSCR_LENGTH_BIT, except);
1247
1248 exceptions |= except;
1249
1250 /*
1251 * CHECK: It appears to be undefined whether we stop when
1252 * we encounter an exception. We continue.
1253 */
1254 dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 3);
1255 dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 3);
1256 if (FREG_BANK(dm) != 0)
1257 dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 3);
1258 }
1259 return exceptions;
1260
1261 invalid:
1262 return ~0;
1263}
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..05279f5ce
--- /dev/null
+++ b/src/core/arm/interpreter/vfp/vfpsingle.cpp
@@ -0,0 +1,1278 @@
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 "core/arm/interpreter/vfp/vfp_helper.h"
55#include "core/arm/interpreter/vfp/asm_vfp.h"
56#include "core/arm/interpreter/vfp/vfp.h"
57
58static struct vfp_single vfp_single_default_qnan = {
59 //.exponent = 255,
60 //.sign = 0,
61 //.significand = VFP_SINGLE_SIGNIFICAND_QNAN,
62};
63
64static void vfp_single_dump(const char *str, struct vfp_single *s)
65{
66 pr_debug("VFP: %s: sign=%d exponent=%d significand=%08x\n",
67 str, s->sign != 0, s->exponent, s->significand);
68}
69
70static void vfp_single_normalise_denormal(struct vfp_single *vs)
71{
72 int bits = 31 - fls(vs->significand);
73
74 vfp_single_dump("normalise_denormal: in", vs);
75
76 if (bits) {
77 vs->exponent -= bits - 1;
78 vs->significand <<= bits;
79 }
80
81 vfp_single_dump("normalise_denormal: out", vs);
82}
83
84
85u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func)
86{
87 u32 significand, incr, rmode;
88 int exponent, shift, underflow;
89
90 vfp_single_dump("pack: in", vs);
91
92 /*
93 * Infinities and NaNs are a special case.
94 */
95 if (vs->exponent == 255 && (vs->significand == 0 || exceptions))
96 goto pack;
97
98 /*
99 * Special-case zero.
100 */
101 if (vs->significand == 0) {
102 vs->exponent = 0;
103 goto pack;
104 }
105
106 exponent = vs->exponent;
107 significand = vs->significand;
108
109 /*
110 * Normalise first. Note that we shift the significand up to
111 * bit 31, so we have VFP_SINGLE_LOW_BITS + 1 below the least
112 * significant bit.
113 */
114 shift = 32 - fls(significand);
115 if (shift < 32 && shift) {
116 exponent -= shift;
117 significand <<= shift;
118 }
119
120#if 1
121 vs->exponent = exponent;
122 vs->significand = significand;
123 vfp_single_dump("pack: normalised", vs);
124#endif
125
126 /*
127 * Tiny number?
128 */
129 underflow = exponent < 0;
130 if (underflow) {
131 significand = vfp_shiftright32jamming(significand, -exponent);
132 exponent = 0;
133#if 1
134 vs->exponent = exponent;
135 vs->significand = significand;
136 vfp_single_dump("pack: tiny number", vs);
137#endif
138 if (!(significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1)))
139 underflow = 0;
140 }
141
142 /*
143 * Select rounding increment.
144 */
145 incr = 0;
146 rmode = fpscr & FPSCR_RMODE_MASK;
147
148 if (rmode == FPSCR_ROUND_NEAREST) {
149 incr = 1 << VFP_SINGLE_LOW_BITS;
150 if ((significand & (1 << (VFP_SINGLE_LOW_BITS + 1))) == 0)
151 incr -= 1;
152 } else if (rmode == FPSCR_ROUND_TOZERO) {
153 incr = 0;
154 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vs->sign != 0))
155 incr = (1 << (VFP_SINGLE_LOW_BITS + 1)) - 1;
156
157 pr_debug("VFP: rounding increment = 0x%08x\n", incr);
158
159 /*
160 * Is our rounding going to overflow?
161 */
162 if ((significand + incr) < significand) {
163 exponent += 1;
164 significand = (significand >> 1) | (significand & 1);
165 incr >>= 1;
166#if 1
167 vs->exponent = exponent;
168 vs->significand = significand;
169 vfp_single_dump("pack: overflow", vs);
170#endif
171 }
172
173 /*
174 * If any of the low bits (which will be shifted out of the
175 * number) are non-zero, the result is inexact.
176 */
177 if (significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1))
178 exceptions |= FPSCR_IXC;
179
180 /*
181 * Do our rounding.
182 */
183 significand += incr;
184
185 /*
186 * Infinity?
187 */
188 if (exponent >= 254) {
189 exceptions |= FPSCR_OFC | FPSCR_IXC;
190 if (incr == 0) {
191 vs->exponent = 253;
192 vs->significand = 0x7fffffff;
193 } else {
194 vs->exponent = 255; /* infinity */
195 vs->significand = 0;
196 }
197 } else {
198 if (significand >> (VFP_SINGLE_LOW_BITS + 1) == 0)
199 exponent = 0;
200 if (exponent || significand > 0x80000000)
201 underflow = 0;
202 if (underflow)
203 exceptions |= FPSCR_UFC;
204 vs->exponent = exponent;
205 vs->significand = significand >> 1;
206 }
207
208 pack:
209 vfp_single_dump("pack: final", vs);
210 {
211 s32 d = vfp_single_pack(vs);
212#if 1
213 pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func,
214 sd, d, exceptions);
215#endif
216 vfp_put_float(state, d, sd);
217 }
218
219 return exceptions;
220}
221
222/*
223 * Propagate the NaN, setting exceptions if it is signalling.
224 * 'n' is always a NaN. 'm' may be a number, NaN or infinity.
225 */
226static u32
227vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn,
228 struct vfp_single *vsm, u32 fpscr)
229{
230 struct vfp_single *nan;
231 int tn, tm = 0;
232
233 tn = vfp_single_type(vsn);
234
235 if (vsm)
236 tm = vfp_single_type(vsm);
237
238 if (fpscr & FPSCR_DEFAULT_NAN)
239 /*
240 * Default NaN mode - always returns a quiet NaN
241 */
242 nan = &vfp_single_default_qnan;
243 else {
244 /*
245 * Contemporary mode - select the first signalling
246 * NAN, or if neither are signalling, the first
247 * quiet NAN.
248 */
249 if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN))
250 nan = vsn;
251 else
252 nan = vsm;
253 /*
254 * Make the NaN quiet.
255 */
256 nan->significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
257 }
258
259 *vsd = *nan;
260
261 /*
262 * If one was a signalling NAN, raise invalid operation.
263 */
264 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG;
265}
266
267
268/*
269 * Extended operations
270 */
271static u32 vfp_single_fabs(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
272{
273 vfp_put_float(state, vfp_single_packed_abs(m), sd);
274 return 0;
275}
276
277static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
278{
279 vfp_put_float(state, m, sd);
280 return 0;
281}
282
283static u32 vfp_single_fneg(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
284{
285 vfp_put_float(state, vfp_single_packed_negate(m), sd);
286 return 0;
287}
288
289static const u16 sqrt_oddadjust[] = {
290 0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0,
291 0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67
292};
293
294static const u16 sqrt_evenadjust[] = {
295 0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e,
296 0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002
297};
298
299u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand)
300{
301 int index;
302 u32 z, a;
303
304 if ((significand & 0xc0000000) != 0x40000000) {
305 pr_debug("VFP: estimate_sqrt: invalid significand\n");
306 }
307
308 a = significand << 1;
309 index = (a >> 27) & 15;
310 if (exponent & 1) {
311 z = 0x4000 + (a >> 17) - sqrt_oddadjust[index];
312 z = ((a / z) << 14) + (z << 15);
313 a >>= 1;
314 } else {
315 z = 0x8000 + (a >> 17) - sqrt_evenadjust[index];
316 z = a / z + z;
317 z = (z >= 0x20000) ? 0xffff8000 : (z << 15);
318 if (z <= a)
319 return (s32)a >> 1;
320 }
321 {
322 u64 v = (u64)a << 31;
323 do_div(v, z);
324 return v + (z >> 1);
325 }
326}
327
328static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
329{
330 struct vfp_single vsm, vsd, *vsp;
331 int ret, tm;
332
333 vfp_single_unpack(&vsm, m);
334 tm = vfp_single_type(&vsm);
335 if (tm & (VFP_NAN|VFP_INFINITY)) {
336 vsp = &vsd;
337
338 if (tm & VFP_NAN)
339 ret = vfp_propagate_nan(vsp, &vsm, NULL, fpscr);
340 else if (vsm.sign == 0) {
341 sqrt_copy:
342 vsp = &vsm;
343 ret = 0;
344 } else {
345 sqrt_invalid:
346 vsp = &vfp_single_default_qnan;
347 ret = FPSCR_IOC;
348 }
349 vfp_put_float(state, vfp_single_pack(vsp), sd);
350 return ret;
351 }
352
353 /*
354 * sqrt(+/- 0) == +/- 0
355 */
356 if (tm & VFP_ZERO)
357 goto sqrt_copy;
358
359 /*
360 * Normalise a denormalised number
361 */
362 if (tm & VFP_DENORMAL)
363 vfp_single_normalise_denormal(&vsm);
364
365 /*
366 * sqrt(<0) = invalid
367 */
368 if (vsm.sign)
369 goto sqrt_invalid;
370
371 vfp_single_dump("sqrt", &vsm);
372
373 /*
374 * Estimate the square root.
375 */
376 vsd.sign = 0;
377 vsd.exponent = ((vsm.exponent - 127) >> 1) + 127;
378 vsd.significand = vfp_estimate_sqrt_significand(vsm.exponent, vsm.significand) + 2;
379
380 vfp_single_dump("sqrt estimate", &vsd);
381
382 /*
383 * And now adjust.
384 */
385 if ((vsd.significand & VFP_SINGLE_LOW_BITS_MASK) <= 5) {
386 if (vsd.significand < 2) {
387 vsd.significand = 0xffffffff;
388 } else {
389 u64 term;
390 s64 rem;
391 vsm.significand <<= !(vsm.exponent & 1);
392 term = (u64)vsd.significand * vsd.significand;
393 rem = ((u64)vsm.significand << 32) - term;
394
395 pr_debug("VFP: term=%016llx rem=%016llx\n", term, rem);
396
397 while (rem < 0) {
398 vsd.significand -= 1;
399 rem += ((u64)vsd.significand << 1) | 1;
400 }
401 vsd.significand |= rem != 0;
402 }
403 }
404 vsd.significand = vfp_shiftright32jamming(vsd.significand, 1);
405
406 return vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fsqrt");
407}
408
409/*
410 * Equal := ZC
411 * Less than := N
412 * Greater than := C
413 * Unordered := CV
414 */
415static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u32 fpscr)
416{
417 s32 d;
418 u32 ret = 0;
419
420 d = vfp_get_float(state, sd);
421 if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) {
422 ret |= FPSCR_C | FPSCR_V;
423 if (signal_on_qnan || !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
424 /*
425 * Signalling NaN, or signalling on quiet NaN
426 */
427 ret |= FPSCR_IOC;
428 }
429
430 if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) {
431 ret |= FPSCR_C | FPSCR_V;
432 if (signal_on_qnan || !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
433 /*
434 * Signalling NaN, or signalling on quiet NaN
435 */
436 ret |= FPSCR_IOC;
437 }
438
439 if (ret == 0) {
440 if (d == m || vfp_single_packed_abs(d | m) == 0) {
441 /*
442 * equal
443 */
444 ret |= FPSCR_Z | FPSCR_C;
445 } else if (vfp_single_packed_sign(d ^ m)) {
446 /*
447 * different signs
448 */
449 if (vfp_single_packed_sign(d))
450 /*
451 * d is negative, so d < m
452 */
453 ret |= FPSCR_N;
454 else
455 /*
456 * d is positive, so d > m
457 */
458 ret |= FPSCR_C;
459 } else if ((vfp_single_packed_sign(d) != 0) ^ (d < m)) {
460 /*
461 * d < m
462 */
463 ret |= FPSCR_N;
464 } else if ((vfp_single_packed_sign(d) != 0) ^ (d > m)) {
465 /*
466 * d > m
467 */
468 ret |= FPSCR_C;
469 }
470 }
471 return ret;
472}
473
474static u32 vfp_single_fcmp(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
475{
476 return vfp_compare(state, sd, 0, m, fpscr);
477}
478
479static u32 vfp_single_fcmpe(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
480{
481 return vfp_compare(state, sd, 1, m, fpscr);
482}
483
484static u32 vfp_single_fcmpz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
485{
486 return vfp_compare(state, sd, 0, 0, fpscr);
487}
488
489static u32 vfp_single_fcmpez(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
490{
491 return vfp_compare(state, sd, 1, 0, fpscr);
492}
493
494static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr)
495{
496 struct vfp_single vsm;
497 struct vfp_double vdd;
498 int tm;
499 u32 exceptions = 0;
500
501 vfp_single_unpack(&vsm, m);
502
503 tm = vfp_single_type(&vsm);
504
505 /*
506 * If we have a signalling NaN, signal invalid operation.
507 */
508 if (tm == VFP_SNAN)
509 exceptions = FPSCR_IOC;
510
511 if (tm & VFP_DENORMAL)
512 vfp_single_normalise_denormal(&vsm);
513
514 vdd.sign = vsm.sign;
515 vdd.significand = (u64)vsm.significand << 32;
516
517 /*
518 * If we have an infinity or NaN, the exponent must be 2047.
519 */
520 if (tm & (VFP_INFINITY|VFP_NAN)) {
521 vdd.exponent = 2047;
522 if (tm == VFP_QNAN)
523 vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
524 goto pack_nan;
525 } else if (tm & VFP_ZERO)
526 vdd.exponent = 0;
527 else
528 vdd.exponent = vsm.exponent + (1023 - 127);
529
530 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fcvtd");
531
532 pack_nan:
533 vfp_put_double(state, vfp_double_pack(&vdd), dd);
534 return exceptions;
535}
536
537static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
538{
539 struct vfp_single vs;
540
541 vs.sign = 0;
542 vs.exponent = 127 + 31 - 1;
543 vs.significand = (u32)m;
544
545 return vfp_single_normaliseround(state, sd, &vs, fpscr, 0, "fuito");
546}
547
548static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
549{
550 struct vfp_single vs;
551
552 vs.sign = (m & 0x80000000) >> 16;
553 vs.exponent = 127 + 31 - 1;
554 vs.significand = vs.sign ? -m : m;
555
556 return vfp_single_normaliseround(state, sd, &vs, fpscr, 0, "fsito");
557}
558
559static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
560{
561 struct vfp_single vsm;
562 u32 d, exceptions = 0;
563 int rmode = fpscr & FPSCR_RMODE_MASK;
564 int tm;
565
566 vfp_single_unpack(&vsm, m);
567 vfp_single_dump("VSM", &vsm);
568
569 /*
570 * Do we have a denormalised number?
571 */
572 tm = vfp_single_type(&vsm);
573 if (tm & VFP_DENORMAL)
574 exceptions |= FPSCR_IDC;
575
576 if (tm & VFP_NAN)
577 vsm.sign = 0;
578
579 if (vsm.exponent >= 127 + 32) {
580 d = vsm.sign ? 0 : 0xffffffff;
581 exceptions = FPSCR_IOC;
582 } else if (vsm.exponent >= 127 - 1) {
583 int shift = 127 + 31 - vsm.exponent;
584 u32 rem, incr = 0;
585
586 /*
587 * 2^0 <= m < 2^32-2^8
588 */
589 d = (vsm.significand << 1) >> shift;
590 rem = vsm.significand << (33 - shift);
591
592 if (rmode == FPSCR_ROUND_NEAREST) {
593 incr = 0x80000000;
594 if ((d & 1) == 0)
595 incr -= 1;
596 } else if (rmode == FPSCR_ROUND_TOZERO) {
597 incr = 0;
598 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) {
599 incr = ~0;
600 }
601
602 if ((rem + incr) < rem) {
603 if (d < 0xffffffff)
604 d += 1;
605 else
606 exceptions |= FPSCR_IOC;
607 }
608
609 if (d && vsm.sign) {
610 d = 0;
611 exceptions |= FPSCR_IOC;
612 } else if (rem)
613 exceptions |= FPSCR_IXC;
614 } else {
615 d = 0;
616 if (vsm.exponent | vsm.significand) {
617 exceptions |= FPSCR_IXC;
618 if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0)
619 d = 1;
620 else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) {
621 d = 0;
622 exceptions |= FPSCR_IOC;
623 }
624 }
625 }
626
627 pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
628
629 vfp_put_float(state, d, sd);
630
631 return exceptions;
632}
633
634static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
635{
636 return vfp_single_ftoui(state, sd, unused, m, FPSCR_ROUND_TOZERO);
637}
638
639static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
640{
641 struct vfp_single vsm;
642 u32 d, exceptions = 0;
643 int rmode = fpscr & FPSCR_RMODE_MASK;
644 int tm;
645
646 vfp_single_unpack(&vsm, m);
647 vfp_single_dump("VSM", &vsm);
648
649 /*
650 * Do we have a denormalised number?
651 */
652 tm = vfp_single_type(&vsm);
653 if (vfp_single_type(&vsm) & VFP_DENORMAL)
654 exceptions |= FPSCR_IDC;
655
656 if (tm & VFP_NAN) {
657 d = 0;
658 exceptions |= FPSCR_IOC;
659 } else if (vsm.exponent >= 127 + 32) {
660 /*
661 * m >= 2^31-2^7: invalid
662 */
663 d = 0x7fffffff;
664 if (vsm.sign)
665 d = ~d;
666 exceptions |= FPSCR_IOC;
667 } else if (vsm.exponent >= 127 - 1) {
668 int shift = 127 + 31 - vsm.exponent;
669 u32 rem, incr = 0;
670
671 /* 2^0 <= m <= 2^31-2^7 */
672 d = (vsm.significand << 1) >> shift;
673 rem = vsm.significand << (33 - shift);
674
675 if (rmode == FPSCR_ROUND_NEAREST) {
676 incr = 0x80000000;
677 if ((d & 1) == 0)
678 incr -= 1;
679 } else if (rmode == FPSCR_ROUND_TOZERO) {
680 incr = 0;
681 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) {
682 incr = ~0;
683 }
684
685 if ((rem + incr) < rem && d < 0xffffffff)
686 d += 1;
687 if (d > 0x7fffffff + (vsm.sign != 0)) {
688 d = 0x7fffffff + (vsm.sign != 0);
689 exceptions |= FPSCR_IOC;
690 } else if (rem)
691 exceptions |= FPSCR_IXC;
692
693 if (vsm.sign)
694 d = -d;
695 } else {
696 d = 0;
697 if (vsm.exponent | vsm.significand) {
698 exceptions |= FPSCR_IXC;
699 if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0)
700 d = 1;
701 else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign)
702 d = -1;
703 }
704 }
705
706 pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
707
708 vfp_put_float(state, (s32)d, sd);
709
710 return exceptions;
711}
712
713static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
714{
715 return vfp_single_ftosi(state, sd, unused, m, FPSCR_ROUND_TOZERO);
716}
717
718static struct op fops_ext[] = {
719 { vfp_single_fcpy, 0 }, //0x00000000 - FEXT_FCPY
720 { vfp_single_fabs, 0 }, //0x00000001 - FEXT_FABS
721 { vfp_single_fneg, 0 }, //0x00000002 - FEXT_FNEG
722 { vfp_single_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT
723 { NULL, 0 },
724 { NULL, 0 },
725 { NULL, 0 },
726 { NULL, 0 },
727 { vfp_single_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP
728 { vfp_single_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE
729 { vfp_single_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ
730 { vfp_single_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ
731 { NULL, 0 },
732 { NULL, 0 },
733 { NULL, 0 },
734 { vfp_single_fcvtd, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT
735 { vfp_single_fuito, OP_SCALAR }, //0x00000010 - FEXT_FUITO
736 { vfp_single_fsito, OP_SCALAR }, //0x00000011 - FEXT_FSITO
737 { NULL, 0 },
738 { NULL, 0 },
739 { NULL, 0 },
740 { NULL, 0 },
741 { NULL, 0 },
742 { NULL, 0 },
743 { vfp_single_ftoui, OP_SCALAR }, //0x00000018 - FEXT_FTOUI
744 { vfp_single_ftouiz, OP_SCALAR }, //0x00000019 - FEXT_FTOUIZ
745 { vfp_single_ftosi, OP_SCALAR }, //0x0000001A - FEXT_FTOSI
746 { vfp_single_ftosiz, OP_SCALAR }, //0x0000001B - FEXT_FTOSIZ
747};
748
749
750
751
752
753static u32
754vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn,
755 struct vfp_single *vsm, u32 fpscr)
756{
757 struct vfp_single *vsp;
758 u32 exceptions = 0;
759 int tn, tm;
760
761 tn = vfp_single_type(vsn);
762 tm = vfp_single_type(vsm);
763
764 if (tn & tm & VFP_INFINITY) {
765 /*
766 * Two infinities. Are they different signs?
767 */
768 if (vsn->sign ^ vsm->sign) {
769 /*
770 * different signs -> invalid
771 */
772 exceptions = FPSCR_IOC;
773 vsp = &vfp_single_default_qnan;
774 } else {
775 /*
776 * same signs -> valid
777 */
778 vsp = vsn;
779 }
780 } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) {
781 /*
782 * One infinity and one number -> infinity
783 */
784 vsp = vsn;
785 } else {
786 /*
787 * 'n' is a NaN of some type
788 */
789 return vfp_propagate_nan(vsd, vsn, vsm, fpscr);
790 }
791 *vsd = *vsp;
792 return exceptions;
793}
794
795static u32
796vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
797 struct vfp_single *vsm, u32 fpscr)
798{
799 u32 exp_diff, m_sig;
800
801 if (vsn->significand & 0x80000000 ||
802 vsm->significand & 0x80000000) {
803 pr_info("VFP: bad FP values\n");
804 vfp_single_dump("VSN", vsn);
805 vfp_single_dump("VSM", vsm);
806 }
807
808 /*
809 * Ensure that 'n' is the largest magnitude number. Note that
810 * if 'n' and 'm' have equal exponents, we do not swap them.
811 * This ensures that NaN propagation works correctly.
812 */
813 if (vsn->exponent < vsm->exponent) {
814 struct vfp_single *t = vsn;
815 vsn = vsm;
816 vsm = t;
817 }
818
819 /*
820 * Is 'n' an infinity or a NaN? Note that 'm' may be a number,
821 * infinity or a NaN here.
822 */
823 if (vsn->exponent == 255)
824 return vfp_single_fadd_nonnumber(vsd, vsn, vsm, fpscr);
825
826 /*
827 * We have two proper numbers, where 'vsn' is the larger magnitude.
828 *
829 * Copy 'n' to 'd' before doing the arithmetic.
830 */
831 *vsd = *vsn;
832
833 /*
834 * Align both numbers.
835 */
836 exp_diff = vsn->exponent - vsm->exponent;
837 m_sig = vfp_shiftright32jamming(vsm->significand, exp_diff);
838
839 /*
840 * If the signs are different, we are really subtracting.
841 */
842 if (vsn->sign ^ vsm->sign) {
843 m_sig = vsn->significand - m_sig;
844 if ((s32)m_sig < 0) {
845 vsd->sign = vfp_sign_negate(vsd->sign);
846 m_sig = -m_sig;
847 } else if (m_sig == 0) {
848 vsd->sign = (fpscr & FPSCR_RMODE_MASK) ==
849 FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
850 }
851 } else {
852 m_sig = vsn->significand + m_sig;
853 }
854 vsd->significand = m_sig;
855
856 return 0;
857}
858
859static u32
860vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_single *vsm, u32 fpscr)
861{
862 vfp_single_dump("VSN", vsn);
863 vfp_single_dump("VSM", vsm);
864
865 /*
866 * Ensure that 'n' is the largest magnitude number. Note that
867 * if 'n' and 'm' have equal exponents, we do not swap them.
868 * This ensures that NaN propagation works correctly.
869 */
870 if (vsn->exponent < vsm->exponent) {
871 struct vfp_single *t = vsn;
872 vsn = vsm;
873 vsm = t;
874 pr_debug("VFP: swapping M <-> N\n");
875 }
876
877 vsd->sign = vsn->sign ^ vsm->sign;
878
879 /*
880 * If 'n' is an infinity or NaN, handle it. 'm' may be anything.
881 */
882 if (vsn->exponent == 255) {
883 if (vsn->significand || (vsm->exponent == 255 && vsm->significand))
884 return vfp_propagate_nan(vsd, vsn, vsm, fpscr);
885 if ((vsm->exponent | vsm->significand) == 0) {
886 *vsd = vfp_single_default_qnan;
887 return FPSCR_IOC;
888 }
889 vsd->exponent = vsn->exponent;
890 vsd->significand = 0;
891 return 0;
892 }
893
894 /*
895 * If 'm' is zero, the result is always zero. In this case,
896 * 'n' may be zero or a number, but it doesn't matter which.
897 */
898 if ((vsm->exponent | vsm->significand) == 0) {
899 vsd->exponent = 0;
900 vsd->significand = 0;
901 return 0;
902 }
903
904 /*
905 * We add 2 to the destination exponent for the same reason as
906 * the addition case - though this time we have +1 from each
907 * input operand.
908 */
909 vsd->exponent = vsn->exponent + vsm->exponent - 127 + 2;
910 vsd->significand = vfp_hi64to32jamming((u64)vsn->significand * vsm->significand);
911
912 vfp_single_dump("VSD", vsd);
913 return 0;
914}
915
916#define NEG_MULTIPLY (1 << 0)
917#define NEG_SUBTRACT (1 << 1)
918
919static u32
920vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr, u32 negate, char *func)
921{
922 struct vfp_single vsd, vsp, vsn, vsm;
923 u32 exceptions;
924 s32 v;
925
926 v = vfp_get_float(state, sn);
927 pr_debug("VFP: s%u = %08x\n", sn, v);
928 vfp_single_unpack(&vsn, v);
929 if (vsn.exponent == 0 && vsn.significand)
930 vfp_single_normalise_denormal(&vsn);
931
932 vfp_single_unpack(&vsm, m);
933 if (vsm.exponent == 0 && vsm.significand)
934 vfp_single_normalise_denormal(&vsm);
935
936 exceptions = vfp_single_multiply(&vsp, &vsn, &vsm, fpscr);
937 if (negate & NEG_MULTIPLY)
938 vsp.sign = vfp_sign_negate(vsp.sign);
939
940 v = vfp_get_float(state, sd);
941 pr_debug("VFP: s%u = %08x\n", sd, v);
942 vfp_single_unpack(&vsn, v);
943 if (negate & NEG_SUBTRACT)
944 vsn.sign = vfp_sign_negate(vsn.sign);
945
946 exceptions |= vfp_single_add(&vsd, &vsn, &vsp, fpscr);
947
948 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, func);
949}
950
951/*
952 * Standard operations
953 */
954
955/*
956 * sd = sd + (sn * sm)
957 */
958static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
959{
960 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
961 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac");
962}
963
964/*
965 * sd = sd - (sn * sm)
966 */
967static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
968{
969 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sd, sn);
970 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac");
971}
972
973/*
974 * sd = -sd + (sn * sm)
975 */
976static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
977{
978 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
979 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc");
980}
981
982/*
983 * sd = -sd - (sn * sm)
984 */
985static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
986{
987 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
988 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
989}
990
991/*
992 * sd = sn * sm
993 */
994static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
995{
996 struct vfp_single vsd, vsn, vsm;
997 u32 exceptions;
998 s32 n = vfp_get_float(state, sn);
999
1000 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, n);
1001
1002 vfp_single_unpack(&vsn, n);
1003 if (vsn.exponent == 0 && vsn.significand)
1004 vfp_single_normalise_denormal(&vsn);
1005
1006 vfp_single_unpack(&vsm, m);
1007 if (vsm.exponent == 0 && vsm.significand)
1008 vfp_single_normalise_denormal(&vsm);
1009
1010 exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr);
1011 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fmul");
1012}
1013
1014/*
1015 * sd = -(sn * sm)
1016 */
1017static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1018{
1019 struct vfp_single vsd, vsn, vsm;
1020 u32 exceptions;
1021 s32 n = vfp_get_float(state, sn);
1022
1023 pr_debug("VFP: s%u = %08x\n", sn, n);
1024
1025 vfp_single_unpack(&vsn, n);
1026 if (vsn.exponent == 0 && vsn.significand)
1027 vfp_single_normalise_denormal(&vsn);
1028
1029 vfp_single_unpack(&vsm, m);
1030 if (vsm.exponent == 0 && vsm.significand)
1031 vfp_single_normalise_denormal(&vsm);
1032
1033 exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr);
1034 vsd.sign = vfp_sign_negate(vsd.sign);
1035 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fnmul");
1036}
1037
1038/*
1039 * sd = sn + sm
1040 */
1041static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1042{
1043 struct vfp_single vsd, vsn, vsm;
1044 u32 exceptions;
1045 s32 n = vfp_get_float(state, sn);
1046
1047 pr_debug("VFP: s%u = %08x\n", sn, n);
1048
1049 /*
1050 * Unpack and normalise denormals.
1051 */
1052 vfp_single_unpack(&vsn, n);
1053 if (vsn.exponent == 0 && vsn.significand)
1054 vfp_single_normalise_denormal(&vsn);
1055
1056 vfp_single_unpack(&vsm, m);
1057 if (vsm.exponent == 0 && vsm.significand)
1058 vfp_single_normalise_denormal(&vsm);
1059
1060 exceptions = vfp_single_add(&vsd, &vsn, &vsm, fpscr);
1061
1062 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fadd");
1063}
1064
1065/*
1066 * sd = sn - sm
1067 */
1068static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1069{
1070 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
1071 /*
1072 * Subtraction is addition with one sign inverted.
1073 */
1074 return vfp_single_fadd(state, sd, sn, vfp_single_packed_negate(m), fpscr);
1075}
1076
1077/*
1078 * sd = sn / sm
1079 */
1080static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1081{
1082 struct vfp_single vsd, vsn, vsm;
1083 u32 exceptions = 0;
1084 s32 n = vfp_get_float(state, sn);
1085 int tm, tn;
1086
1087 pr_debug("VFP: s%u = %08x\n", sn, n);
1088
1089 vfp_single_unpack(&vsn, n);
1090 vfp_single_unpack(&vsm, m);
1091
1092 vsd.sign = vsn.sign ^ vsm.sign;
1093
1094 tn = vfp_single_type(&vsn);
1095 tm = vfp_single_type(&vsm);
1096
1097 /*
1098 * Is n a NAN?
1099 */
1100 if (tn & VFP_NAN)
1101 goto vsn_nan;
1102
1103 /*
1104 * Is m a NAN?
1105 */
1106 if (tm & VFP_NAN)
1107 goto vsm_nan;
1108
1109 /*
1110 * If n and m are infinity, the result is invalid
1111 * If n and m are zero, the result is invalid
1112 */
1113 if (tm & tn & (VFP_INFINITY|VFP_ZERO))
1114 goto invalid;
1115
1116 /*
1117 * If n is infinity, the result is infinity
1118 */
1119 if (tn & VFP_INFINITY)
1120 goto infinity;
1121
1122 /*
1123 * If m is zero, raise div0 exception
1124 */
1125 if (tm & VFP_ZERO)
1126 goto divzero;
1127
1128 /*
1129 * If m is infinity, or n is zero, the result is zero
1130 */
1131 if (tm & VFP_INFINITY || tn & VFP_ZERO)
1132 goto zero;
1133
1134 if (tn & VFP_DENORMAL)
1135 vfp_single_normalise_denormal(&vsn);
1136 if (tm & VFP_DENORMAL)
1137 vfp_single_normalise_denormal(&vsm);
1138
1139 /*
1140 * Ok, we have two numbers, we can perform division.
1141 */
1142 vsd.exponent = vsn.exponent - vsm.exponent + 127 - 1;
1143 vsm.significand <<= 1;
1144 if (vsm.significand <= (2 * vsn.significand)) {
1145 vsn.significand >>= 1;
1146 vsd.exponent++;
1147 }
1148 {
1149 u64 significand = (u64)vsn.significand << 32;
1150 do_div(significand, vsm.significand);
1151 vsd.significand = significand;
1152 }
1153 if ((vsd.significand & 0x3f) == 0)
1154 vsd.significand |= ((u64)vsm.significand * vsd.significand != (u64)vsn.significand << 32);
1155
1156 return vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fdiv");
1157
1158 vsn_nan:
1159 exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr);
1160 pack:
1161 vfp_put_float(state, vfp_single_pack(&vsd), sd);
1162 return exceptions;
1163
1164 vsm_nan:
1165 exceptions = vfp_propagate_nan(&vsd, &vsm, &vsn, fpscr);
1166 goto pack;
1167
1168 zero:
1169 vsd.exponent = 0;
1170 vsd.significand = 0;
1171 goto pack;
1172
1173 divzero:
1174 exceptions = FPSCR_DZC;
1175 infinity:
1176 vsd.exponent = 255;
1177 vsd.significand = 0;
1178 goto pack;
1179
1180 invalid:
1181 vfp_put_float(state, vfp_single_pack(&vfp_single_default_qnan), sd);
1182 return FPSCR_IOC;
1183}
1184
1185static struct op fops[] = {
1186 { vfp_single_fmac, 0 },
1187 { vfp_single_fmsc, 0 },
1188 { vfp_single_fmul, 0 },
1189 { vfp_single_fadd, 0 },
1190 { vfp_single_fnmac, 0 },
1191 { vfp_single_fnmsc, 0 },
1192 { vfp_single_fnmul, 0 },
1193 { vfp_single_fsub, 0 },
1194 { vfp_single_fdiv, 0 },
1195};
1196
1197#define FREG_BANK(x) ((x) & 0x18)
1198#define FREG_IDX(x) ((x) & 7)
1199
1200u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1201{
1202 u32 op = inst & FOP_MASK;
1203 u32 exceptions = 0;
1204 unsigned int dest;
1205 unsigned int sn = vfp_get_sn(inst);
1206 unsigned int sm = vfp_get_sm(inst);
1207 unsigned int vecitr, veclen, vecstride;
1208 struct op *fop;
1209 pr_debug("In %s\n", __FUNCTION__);
1210
1211 vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
1212
1213 fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
1214
1215 /*
1216 * fcvtsd takes a dN register number as destination, not sN.
1217 * Technically, if bit 0 of dd is set, this is an invalid
1218 * instruction. However, we ignore this for efficiency.
1219 * It also only operates on scalars.
1220 */
1221 if (fop->flags & OP_DD)
1222 dest = vfp_get_dd(inst);
1223 else
1224 dest = vfp_get_sd(inst);
1225
1226 /*
1227 * If destination bank is zero, vector length is always '1'.
1228 * ARM DDI0100F C5.1.3, C5.3.2.
1229 */
1230 if ((fop->flags & OP_SCALAR) || FREG_BANK(dest) == 0)
1231 veclen = 0;
1232 else
1233 veclen = fpscr & FPSCR_LENGTH_MASK;
1234
1235 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
1236 (veclen >> FPSCR_LENGTH_BIT) + 1);
1237
1238 if (!fop->fn) {
1239 printf("VFP: could not find single op %d, inst=0x%x@0x%x\n", FEXT_TO_IDX(inst), inst, state->Reg[15]);
1240 exit(-1);
1241 goto invalid;
1242 }
1243
1244 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
1245 s32 m = vfp_get_float(state, sm);
1246 u32 except;
1247 char type;
1248
1249 type = fop->flags & OP_DD ? 'd' : 's';
1250 if (op == FOP_EXT)
1251 pr_debug("VFP: itr%d (%c%u) = op[%u] (s%u=%08x)\n",
1252 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
1253 sm, m);
1254 else
1255 pr_debug("VFP: itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)\n",
1256 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
1257 FOP_TO_IDX(op), sm, m);
1258
1259 except = fop->fn(state, dest, sn, m, fpscr);
1260 pr_debug("VFP: itr%d: exceptions=%08x\n",
1261 vecitr >> FPSCR_LENGTH_BIT, except);
1262
1263 exceptions |= except;
1264
1265 /*
1266 * CHECK: It appears to be undefined whether we stop when
1267 * we encounter an exception. We continue.
1268 */
1269 dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7);
1270 sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7);
1271 if (FREG_BANK(sm) != 0)
1272 sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7);
1273 }
1274 return exceptions;
1275
1276 invalid:
1277 return (u32)-1;
1278}
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index b56661e48..41af5801d 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -139,6 +139,7 @@
139 <ItemGroup> 139 <ItemGroup>
140 <ClCompile Include="arm\disassembler\arm_disasm.cpp" /> 140 <ClCompile Include="arm\disassembler\arm_disasm.cpp" />
141 <ClCompile Include="arm\disassembler\load_symbol_map.cpp" /> 141 <ClCompile Include="arm\disassembler\load_symbol_map.cpp" />
142 <ClCompile Include="arm\interpreter\armcopro.cpp" />
142 <ClCompile Include="arm\interpreter\armemu.cpp" /> 143 <ClCompile Include="arm\interpreter\armemu.cpp" />
143 <ClCompile Include="arm\interpreter\arminit.cpp" /> 144 <ClCompile Include="arm\interpreter\arminit.cpp" />
144 <ClCompile Include="arm\interpreter\armmmu.cpp" /> 145 <ClCompile Include="arm\interpreter\armmmu.cpp" />
@@ -146,8 +147,19 @@
146 <ClCompile Include="arm\interpreter\armsupp.cpp" /> 147 <ClCompile Include="arm\interpreter\armsupp.cpp" />
147 <ClCompile Include="arm\interpreter\armvirt.cpp" /> 148 <ClCompile Include="arm\interpreter\armvirt.cpp" />
148 <ClCompile Include="arm\interpreter\arm_interpreter.cpp" /> 149 <ClCompile Include="arm\interpreter\arm_interpreter.cpp" />
150 <ClCompile Include="arm\interpreter\mmu\arm1176jzf_s_mmu.cpp" />
151 <ClCompile Include="arm\interpreter\mmu\cache.cpp" />
152 <ClCompile Include="arm\interpreter\mmu\maverick.cpp" />
153 <ClCompile Include="arm\interpreter\mmu\rb.cpp" />
154 <ClCompile Include="arm\interpreter\mmu\sa_mmu.cpp" />
155 <ClCompile Include="arm\interpreter\mmu\tlb.cpp" />
156 <ClCompile Include="arm\interpreter\mmu\wb.cpp" />
157 <ClCompile Include="arm\interpreter\mmu\xscale_copro.cpp" />
149 <ClCompile Include="arm\interpreter\thumbemu.cpp" /> 158 <ClCompile Include="arm\interpreter\thumbemu.cpp" />
150 <ClCompile Include="arm\mmu\arm1176jzf_s_mmu.cpp" /> 159 <ClCompile Include="arm\interpreter\vfp\vfp.cpp" />
160 <ClCompile Include="arm\interpreter\vfp\vfpdouble.cpp" />
161 <ClCompile Include="arm\interpreter\vfp\vfpinstr.cpp" />
162 <ClCompile Include="arm\interpreter\vfp\vfpsingle.cpp" />
151 <ClCompile Include="core.cpp" /> 163 <ClCompile Include="core.cpp" />
152 <ClCompile Include="core_timing.cpp" /> 164 <ClCompile Include="core_timing.cpp" />
153 <ClCompile Include="elf\elf_reader.cpp" /> 165 <ClCompile Include="elf\elf_reader.cpp" />
@@ -181,12 +193,16 @@
181 <ClInclude Include="arm\interpreter\armos.h" /> 193 <ClInclude Include="arm\interpreter\armos.h" />
182 <ClInclude Include="arm\interpreter\arm_interpreter.h" /> 194 <ClInclude Include="arm\interpreter\arm_interpreter.h" />
183 <ClInclude Include="arm\interpreter\arm_regformat.h" /> 195 <ClInclude Include="arm\interpreter\arm_regformat.h" />
196 <ClInclude Include="arm\interpreter\mmu\arm1176jzf_s_mmu.h" />
197 <ClInclude Include="arm\interpreter\mmu\cache.h" />
198 <ClInclude Include="arm\interpreter\mmu\rb.h" />
199 <ClInclude Include="arm\interpreter\mmu\sa_mmu.h" />
200 <ClInclude Include="arm\interpreter\mmu\tlb.h" />
201 <ClInclude Include="arm\interpreter\mmu\wb.h" />
184 <ClInclude Include="arm\interpreter\skyeye_defs.h" /> 202 <ClInclude Include="arm\interpreter\skyeye_defs.h" />
185 <ClInclude Include="arm\mmu\arm1176jzf_s_mmu.h" /> 203 <ClInclude Include="arm\interpreter\vfp\asm_vfp.h" />
186 <ClInclude Include="arm\mmu\cache.h" /> 204 <ClInclude Include="arm\interpreter\vfp\vfp.h" />
187 <ClInclude Include="arm\mmu\rb.h" /> 205 <ClInclude Include="arm\interpreter\vfp\vfp_helper.h" />
188 <ClInclude Include="arm\mmu\tlb.h" />
189 <ClInclude Include="arm\mmu\wb.h" />
190 <ClInclude Include="core.h" /> 206 <ClInclude Include="core.h" />
191 <ClInclude Include="core_timing.h" /> 207 <ClInclude Include="core_timing.h" />
192 <ClInclude Include="elf\elf_reader.h" /> 208 <ClInclude Include="elf\elf_reader.h" />
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 5c947ec23..edf34ce2f 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -7,9 +7,6 @@
7 <Filter Include="arm\disassembler"> 7 <Filter Include="arm\disassembler">
8 <UniqueIdentifier>{61100188-a726-4024-ab16-95ee242b446e}</UniqueIdentifier> 8 <UniqueIdentifier>{61100188-a726-4024-ab16-95ee242b446e}</UniqueIdentifier>
9 </Filter> 9 </Filter>
10 <Filter Include="arm\mmu">
11 <UniqueIdentifier>{a64d3c8a-747a-491b-b782-6e2622bedf24}</UniqueIdentifier>
12 </Filter>
13 <Filter Include="file_sys"> 10 <Filter Include="file_sys">
14 <UniqueIdentifier>{7f618562-73d1-4f55-9628-887497c27654}</UniqueIdentifier> 11 <UniqueIdentifier>{7f618562-73d1-4f55-9628-887497c27654}</UniqueIdentifier>
15 </Filter> 12 </Filter>
@@ -28,6 +25,12 @@
28 <Filter Include="hle\service"> 25 <Filter Include="hle\service">
29 <UniqueIdentifier>{812c5189-ca49-4704-b842-3ffad09092d3}</UniqueIdentifier> 26 <UniqueIdentifier>{812c5189-ca49-4704-b842-3ffad09092d3}</UniqueIdentifier>
30 </Filter> 27 </Filter>
28 <Filter Include="arm\interpreter\vfp">
29 <UniqueIdentifier>{de62238f-a28e-4a33-8495-23fed6784588}</UniqueIdentifier>
30 </Filter>
31 <Filter Include="arm\interpreter\mmu">
32 <UniqueIdentifier>{13ef9860-2ba0-47e9-a93d-b4052adab269}</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">
@@ -57,9 +60,6 @@
57 <ClCompile Include="arm\interpreter\thumbemu.cpp"> 60 <ClCompile Include="arm\interpreter\thumbemu.cpp">
58 <Filter>arm\interpreter</Filter> 61 <Filter>arm\interpreter</Filter>
59 </ClCompile> 62 </ClCompile>
60 <ClCompile Include="arm\mmu\arm1176jzf_s_mmu.cpp">
61 <Filter>arm\mmu</Filter>
62 </ClCompile>
63 <ClCompile Include="file_sys\directory_file_system.cpp"> 63 <ClCompile Include="file_sys\directory_file_system.cpp">
64 <Filter>file_sys</Filter> 64 <Filter>file_sys</Filter>
65 </ClCompile> 65 </ClCompile>
@@ -114,6 +114,45 @@
114 <ClCompile Include="hle\config_mem.cpp"> 114 <ClCompile Include="hle\config_mem.cpp">
115 <Filter>hle</Filter> 115 <Filter>hle</Filter>
116 </ClCompile> 116 </ClCompile>
117 <ClCompile Include="arm\interpreter\vfp\vfp.cpp">
118 <Filter>arm\interpreter\vfp</Filter>
119 </ClCompile>
120 <ClCompile Include="arm\interpreter\vfp\vfpinstr.cpp">
121 <Filter>arm\interpreter\vfp</Filter>
122 </ClCompile>
123 <ClCompile Include="arm\interpreter\vfp\vfpdouble.cpp">
124 <Filter>arm\interpreter\vfp</Filter>
125 </ClCompile>
126 <ClCompile Include="arm\interpreter\vfp\vfpsingle.cpp">
127 <Filter>arm\interpreter\vfp</Filter>
128 </ClCompile>
129 <ClCompile Include="arm\interpreter\mmu\arm1176jzf_s_mmu.cpp">
130 <Filter>arm\interpreter\mmu</Filter>
131 </ClCompile>
132 <ClCompile Include="arm\interpreter\mmu\xscale_copro.cpp">
133 <Filter>arm\interpreter\mmu</Filter>
134 </ClCompile>
135 <ClCompile Include="arm\interpreter\mmu\sa_mmu.cpp">
136 <Filter>arm\interpreter\mmu</Filter>
137 </ClCompile>
138 <ClCompile Include="arm\interpreter\mmu\cache.cpp">
139 <Filter>arm\interpreter\mmu</Filter>
140 </ClCompile>
141 <ClCompile Include="arm\interpreter\mmu\rb.cpp">
142 <Filter>arm\interpreter\mmu</Filter>
143 </ClCompile>
144 <ClCompile Include="arm\interpreter\mmu\tlb.cpp">
145 <Filter>arm\interpreter\mmu</Filter>
146 </ClCompile>
147 <ClCompile Include="arm\interpreter\mmu\wb.cpp">
148 <Filter>arm\interpreter\mmu</Filter>
149 </ClCompile>
150 <ClCompile Include="arm\interpreter\armcopro.cpp">
151 <Filter>arm</Filter>
152 </ClCompile>
153 <ClCompile Include="arm\interpreter\mmu\maverick.cpp">
154 <Filter>arm\interpreter\mmu</Filter>
155 </ClCompile>
117 </ItemGroup> 156 </ItemGroup>
118 <ItemGroup> 157 <ItemGroup>
119 <ClInclude Include="arm\disassembler\arm_disasm.h"> 158 <ClInclude Include="arm\disassembler\arm_disasm.h">
@@ -143,21 +182,6 @@
143 <ClInclude Include="arm\interpreter\skyeye_defs.h"> 182 <ClInclude Include="arm\interpreter\skyeye_defs.h">
144 <Filter>arm\interpreter</Filter> 183 <Filter>arm\interpreter</Filter>
145 </ClInclude> 184 </ClInclude>
146 <ClInclude Include="arm\mmu\arm1176jzf_s_mmu.h">
147 <Filter>arm\mmu</Filter>
148 </ClInclude>
149 <ClInclude Include="arm\mmu\cache.h">
150 <Filter>arm\mmu</Filter>
151 </ClInclude>
152 <ClInclude Include="arm\mmu\rb.h">
153 <Filter>arm\mmu</Filter>
154 </ClInclude>
155 <ClInclude Include="arm\mmu\tlb.h">
156 <Filter>arm\mmu</Filter>
157 </ClInclude>
158 <ClInclude Include="arm\mmu\wb.h">
159 <Filter>arm\mmu</Filter>
160 </ClInclude>
161 <ClInclude Include="file_sys\directory_file_system.h"> 185 <ClInclude Include="file_sys\directory_file_system.h">
162 <Filter>file_sys</Filter> 186 <Filter>file_sys</Filter>
163 </ClInclude> 187 </ClInclude>
@@ -223,6 +247,33 @@
223 <ClInclude Include="hle\config_mem.h"> 247 <ClInclude Include="hle\config_mem.h">
224 <Filter>hle</Filter> 248 <Filter>hle</Filter>
225 </ClInclude> 249 </ClInclude>
250 <ClInclude Include="arm\interpreter\vfp\asm_vfp.h">
251 <Filter>arm\interpreter\vfp</Filter>
252 </ClInclude>
253 <ClInclude Include="arm\interpreter\vfp\vfp.h">
254 <Filter>arm\interpreter\vfp</Filter>
255 </ClInclude>
256 <ClInclude Include="arm\interpreter\vfp\vfp_helper.h">
257 <Filter>arm\interpreter\vfp</Filter>
258 </ClInclude>
259 <ClInclude Include="arm\interpreter\mmu\arm1176jzf_s_mmu.h">
260 <Filter>arm\interpreter\mmu</Filter>
261 </ClInclude>
262 <ClInclude Include="arm\interpreter\mmu\cache.h">
263 <Filter>arm\interpreter\mmu</Filter>
264 </ClInclude>
265 <ClInclude Include="arm\interpreter\mmu\rb.h">
266 <Filter>arm\interpreter\mmu</Filter>
267 </ClInclude>
268 <ClInclude Include="arm\interpreter\mmu\tlb.h">
269 <Filter>arm\interpreter\mmu</Filter>
270 </ClInclude>
271 <ClInclude Include="arm\interpreter\mmu\wb.h">
272 <Filter>arm\interpreter\mmu</Filter>
273 </ClInclude>
274 <ClInclude Include="arm\interpreter\mmu\sa_mmu.h">
275 <Filter>arm\interpreter\mmu</Filter>
276 </ClInclude>
226 </ItemGroup> 277 </ItemGroup>
227 <ItemGroup> 278 <ItemGroup>
228 <Text Include="CMakeLists.txt" /> 279 <Text Include="CMakeLists.txt" />
diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp
index 74305331c..39674ee64 100644
--- a/src/core/hle/coprocessor.cpp
+++ b/src/core/hle/coprocessor.cpp
@@ -9,42 +9,26 @@
9 9
10namespace HLE { 10namespace HLE {
11 11
12/// Data synchronization barrier
13u32 DataSynchronizationBarrier() {
14 return 0;
15}
16
17/// Returns the coprocessor (in this case, syscore) command buffer pointer 12/// Returns the coprocessor (in this case, syscore) command buffer pointer
18Addr GetThreadCommandBuffer() { 13Addr GetThreadCommandBuffer() {
19 // Called on insruction: mrc p15, 0, r0, c13, c0, 3 14 // Called on insruction: mrc p15, 0, r0, c13, c0, 3
20 return Memory::KERNEL_MEMORY_VADDR; 15 return Memory::KERNEL_MEMORY_VADDR;
21} 16}
22 17
23/// Call an MCR (move to coprocessor from ARM register) instruction in HLE
24s32 CallMCR(u32 instruction, u32 value) {
25 CoprocessorOperation operation = (CoprocessorOperation)((instruction >> 20) & 0xFF);
26 ERROR_LOG(OSHLE, "unimplemented MCR instruction=0x%08X, operation=%02X, value=%08X",
27 instruction, operation, value);
28 return 0;
29}
30
31/// Call an MRC (move to ARM register from coprocessor) instruction in HLE 18/// Call an MRC (move to ARM register from coprocessor) instruction in HLE
32s32 CallMRC(u32 instruction) { 19s32 CallMRC(u32 instruction) {
33 CoprocessorOperation operation = (CoprocessorOperation)((instruction >> 20) & 0xFF); 20 CoprocessorOperation operation = (CoprocessorOperation)((instruction >> 20) & 0xFF);
34 21
35 switch (operation) { 22 switch (operation) {
36 23
37 case DATA_SYNCHRONIZATION_BARRIER:
38 return DataSynchronizationBarrier();
39
40 case CALL_GET_THREAD_COMMAND_BUFFER: 24 case CALL_GET_THREAD_COMMAND_BUFFER:
41 return GetThreadCommandBuffer(); 25 return GetThreadCommandBuffer();
42 26
43 default: 27 default:
44 ERROR_LOG(OSHLE, "unimplemented MRC instruction 0x%08X", instruction); 28 //DEBUG_LOG(OSHLE, "unknown MRC call 0x%08X", instruction);
45 break; 29 break;
46 } 30 }
47 return 0; 31 return -1;
48} 32}
49 33
50} // namespace 34} // namespace
diff --git a/src/core/hle/coprocessor.h b/src/core/hle/coprocessor.h
index 03822af13..b08d6f3ee 100644
--- a/src/core/hle/coprocessor.h
+++ b/src/core/hle/coprocessor.h
@@ -14,9 +14,6 @@ enum CoprocessorOperation {
14 CALL_GET_THREAD_COMMAND_BUFFER = 0xE1, 14 CALL_GET_THREAD_COMMAND_BUFFER = 0xE1,
15}; 15};
16 16
17/// Call an MCR (move to coprocessor from ARM register) instruction in HLE
18s32 CallMCR(u32 instruction, u32 value);
19
20/// Call an MRC (move to ARM register from coprocessor) instruction in HLE 17/// Call an MRC (move to ARM register from coprocessor) instruction in HLE
21s32 CallMRC(u32 instruction); 18s32 CallMRC(u32 instruction);
22 19