summaryrefslogtreecommitdiff
path: root/src/core/arm/interpreter
diff options
context:
space:
mode:
authorGravatar bunnei2014-09-10 21:27:14 -0400
committerGravatar bunnei2014-10-25 14:11:39 -0400
commitb5e65245948647b94dfd60c1288f030a76c69a83 (patch)
tree1c8e2afd3ff59f8c5b93970b62f4f1d1bc251852 /src/core/arm/interpreter
parentMerge pull request #149 from linkmauve/open-file-directly-fix (diff)
downloadyuzu-b5e65245948647b94dfd60c1288f030a76c69a83.tar.gz
yuzu-b5e65245948647b94dfd60c1288f030a76c69a83.tar.xz
yuzu-b5e65245948647b94dfd60c1288f030a76c69a83.zip
ARM: Reorganized file structure to move shared SkyEye code to a more common area.
Removed s_ prefix
Diffstat (limited to 'src/core/arm/interpreter')
-rw-r--r--src/core/arm/interpreter/arm_interpreter.cpp4
-rw-r--r--src/core/arm/interpreter/arm_interpreter.h4
-rw-r--r--src/core/arm/interpreter/arm_regformat.h103
-rw-r--r--src/core/arm/interpreter/armcopro.cpp8
-rw-r--r--src/core/arm/interpreter/armcpu.h83
-rw-r--r--src/core/arm/interpreter/armdefs.h931
-rw-r--r--src/core/arm/interpreter/armemu.cpp6
-rw-r--r--src/core/arm/interpreter/armemu.h656
-rw-r--r--src/core/arm/interpreter/arminit.cpp4
-rw-r--r--src/core/arm/interpreter/armmmu.cpp4
-rw-r--r--src/core/arm/interpreter/armmmu.h254
-rw-r--r--src/core/arm/interpreter/armos.cpp8
-rw-r--r--src/core/arm/interpreter/armos.h138
-rw-r--r--src/core/arm/interpreter/armvirt.cpp4
-rw-r--r--src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp4
-rw-r--r--src/core/arm/interpreter/mmu/cache.cpp2
-rw-r--r--src/core/arm/interpreter/mmu/maverick.cpp4
-rw-r--r--src/core/arm/interpreter/mmu/rb.cpp2
-rw-r--r--src/core/arm/interpreter/mmu/sa_mmu.cpp2
-rw-r--r--src/core/arm/interpreter/mmu/tlb.cpp2
-rw-r--r--src/core/arm/interpreter/mmu/wb.cpp2
-rw-r--r--src/core/arm/interpreter/mmu/xscale_copro.cpp4
-rw-r--r--src/core/arm/interpreter/skyeye_defs.h111
-rw-r--r--src/core/arm/interpreter/thumbemu.cpp8
-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
31 files changed, 36 insertions, 11069 deletions
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp
index 0842d2f8e..6f6a5913c 100644
--- a/src/core/arm/interpreter/arm_interpreter.cpp
+++ b/src/core/arm/interpreter/arm_interpreter.cpp
@@ -4,7 +4,7 @@
4 4
5#include "core/arm/interpreter/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 arm11_cpu_info = {
8 "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE 8 "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
9}; 9};
10 10
@@ -17,7 +17,7 @@ ARM_Interpreter::ARM_Interpreter() {
17 ARMul_NewState(state); 17 ARMul_NewState(state);
18 18
19 state->abort_model = 0; 19 state->abort_model = 0;
20 state->cpu = (cpu_config_t*)&s_arm11_cpu_info; 20 state->cpu = (cpu_config_t*)&arm11_cpu_info;
21 state->bigendSig = LOW; 21 state->bigendSig = LOW;
22 22
23 ARMul_SelectProcessor(state, ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop); 23 ARMul_SelectProcessor(state, ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop);
diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h
index 1e82883a2..64760500c 100644
--- a/src/core/arm/interpreter/arm_interpreter.h
+++ b/src/core/arm/interpreter/arm_interpreter.h
@@ -7,8 +7,8 @@
7#include "common/common.h" 7#include "common/common.h"
8 8
9#include "core/arm/arm_interface.h" 9#include "core/arm/arm_interface.h"
10#include "core/arm/interpreter/armdefs.h" 10#include "core/arm/skyeye_common/armdefs.h"
11#include "core/arm/interpreter/armemu.h" 11#include "core/arm/skyeye_common/armemu.h"
12 12
13class ARM_Interpreter : virtual public ARM_Interface { 13class ARM_Interpreter : virtual public ARM_Interface {
14public: 14public:
diff --git a/src/core/arm/interpreter/arm_regformat.h b/src/core/arm/interpreter/arm_regformat.h
deleted file mode 100644
index 0ca62780b..000000000
--- a/src/core/arm/interpreter/arm_regformat.h
+++ /dev/null
@@ -1,103 +0,0 @@
1#ifndef __ARM_REGFORMAT_H__
2#define __ARM_REGFORMAT_H__
3
4enum arm_regno{
5 R0 = 0,
6 R1,
7 R2,
8 R3,
9 R4,
10 R5,
11 R6,
12 R7,
13 R8,
14 R9,
15 R10,
16 R11,
17 R12,
18 R13,
19 LR,
20 R15, //PC,
21 CPSR_REG,
22 SPSR_REG,
23#if 1
24 PHYS_PC,
25 R13_USR,
26 R14_USR,
27 R13_SVC,
28 R14_SVC,
29 R13_ABORT,
30 R14_ABORT,
31 R13_UNDEF,
32 R14_UNDEF,
33 R13_IRQ,
34 R14_IRQ,
35 R8_FIRQ,
36 R9_FIRQ,
37 R10_FIRQ,
38 R11_FIRQ,
39 R12_FIRQ,
40 R13_FIRQ,
41 R14_FIRQ,
42 SPSR_INVALID1,
43 SPSR_INVALID2,
44 SPSR_SVC,
45 SPSR_ABORT,
46 SPSR_UNDEF,
47 SPSR_IRQ,
48 SPSR_FIRQ,
49 MODE_REG, /* That is the cpsr[4 : 0], just for calculation easily */
50 BANK_REG,
51 EXCLUSIVE_TAG,
52 EXCLUSIVE_STATE,
53 EXCLUSIVE_RESULT,
54 CP15_BASE,
55 CP15_C0 = CP15_BASE,
56 CP15_C0_C0 = CP15_C0,
57 CP15_MAIN_ID = CP15_C0_C0,
58 CP15_CACHE_TYPE,
59 CP15_TCM_STATUS,
60 CP15_TLB_TYPE,
61 CP15_C0_C1,
62 CP15_PROCESSOR_FEATURE_0 = CP15_C0_C1,
63 CP15_PROCESSOR_FEATURE_1,
64 CP15_DEBUG_FEATURE_0,
65 CP15_AUXILIARY_FEATURE_0,
66 CP15_C1_C0,
67 CP15_CONTROL = CP15_C1_C0,
68 CP15_AUXILIARY_CONTROL,
69 CP15_COPROCESSOR_ACCESS_CONTROL,
70 CP15_C2,
71 CP15_C2_C0 = CP15_C2,
72 CP15_TRANSLATION_BASE = CP15_C2_C0,
73 CP15_TRANSLATION_BASE_TABLE_0 = CP15_TRANSLATION_BASE,
74 CP15_TRANSLATION_BASE_TABLE_1,
75 CP15_TRANSLATION_BASE_CONTROL,
76 CP15_DOMAIN_ACCESS_CONTROL,
77 CP15_RESERVED,
78 /* Fault status */
79 CP15_FAULT_STATUS,
80 CP15_INSTR_FAULT_STATUS,
81 CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS,
82 CP15_INST_FSR,
83 /* Fault Address register */
84 CP15_FAULT_ADDRESS,
85 CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS,
86 CP15_WFAR,
87 CP15_IFAR,
88 CP15_PID,
89 CP15_CONTEXT_ID,
90 CP15_THREAD_URO,
91 CP15_TLB_FAULT_ADDR, /* defined by SkyEye */
92 CP15_TLB_FAULT_STATUS, /* defined by SkyEye */
93 /* VFP registers */
94 VFP_BASE,
95 VFP_FPSID = VFP_BASE,
96 VFP_FPSCR,
97 VFP_FPEXC,
98#endif
99 MAX_REG_NUM,
100};
101
102#define VFP_OFFSET(x) (x - VFP_BASE)
103#endif
diff --git a/src/core/arm/interpreter/armcopro.cpp b/src/core/arm/interpreter/armcopro.cpp
index 6a75e6601..ee9fa255a 100644
--- a/src/core/arm/interpreter/armcopro.cpp
+++ b/src/core/arm/interpreter/armcopro.cpp
@@ -16,10 +16,10 @@
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 18
19#include "core/arm/interpreter/armdefs.h" 19#include "core/arm/skyeye_common/armdefs.h"
20#include "core/arm/interpreter/armos.h" 20#include "core/arm/skyeye_common/armos.h"
21#include "core/arm/interpreter/armemu.h" 21#include "core/arm/skyeye_common/armemu.h"
22#include "core/arm/interpreter/vfp/vfp.h" 22#include "core/arm/skyeye_common/vfp/vfp.h"
23 23
24//chy 2005-07-08 24//chy 2005-07-08
25//#include "ansidecl.h" 25//#include "ansidecl.h"
diff --git a/src/core/arm/interpreter/armcpu.h b/src/core/arm/interpreter/armcpu.h
deleted file mode 100644
index 6b5ea8566..000000000
--- a/src/core/arm/interpreter/armcpu.h
+++ /dev/null
@@ -1,83 +0,0 @@
1/*
2 * arm
3 * armcpu.h
4 *
5 * Copyright (C) 2003, 2004 Sebastian Biallas (sb@biallas.net)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#ifndef __ARM_CPU_H__
22#define __ARM_CPU_H__
23//#include <skyeye_thread.h>
24//#include <skyeye_obj.h>
25//#include <skyeye_mach.h>
26//#include <skyeye_exec.h>
27
28#include <stddef.h>
29#include <stdio.h>
30
31#include "common/thread.h"
32
33
34typedef struct ARM_CPU_State_s {
35 ARMul_State * core;
36 uint32_t core_num;
37 /* The core id that boot from
38 */
39 uint32_t boot_core_id;
40}ARM_CPU_State;
41
42//static ARM_CPU_State* get_current_cpu(){
43// machine_config_t* mach = get_current_mach();
44// /* Casting a conf_obj_t to ARM_CPU_State type */
45// ARM_CPU_State* cpu = (ARM_CPU_State*)mach->cpu_data->obj;
46//
47// return cpu;
48//}
49
50/**
51* @brief Get the core instance boot from
52*
53* @return
54*/
55//static ARMul_State* get_boot_core(){
56// ARM_CPU_State* cpu = get_current_cpu();
57// return &cpu->core[cpu->boot_core_id];
58//}
59/**
60* @brief Get the instance of running core
61*
62* @return the core instance
63*/
64//static ARMul_State* get_current_core(){
65// /* Casting a conf_obj_t to ARM_CPU_State type */
66// int id = Common::CurrentThreadId();
67// /* If thread is not in running mode, we should give the boot core */
68// if(get_thread_state(id) != Running_state){
69// return get_boot_core();
70// }
71// /* Judge if we are running in paralell or sequenial */
72// if(thread_exist(id)){
73// conf_object_t* conf_obj = get_current_exec_priv(id);
74// return (ARMul_State*)get_cast_conf_obj(conf_obj, "arm_core_t");
75// }
76//
77// return NULL;
78//}
79
80#define CURRENT_CORE get_current_core()
81
82#endif
83
diff --git a/src/core/arm/interpreter/armdefs.h b/src/core/arm/interpreter/armdefs.h
deleted file mode 100644
index dd5983be3..000000000
--- a/src/core/arm/interpreter/armdefs.h
+++ /dev/null
@@ -1,931 +0,0 @@
1/* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator.
2 Copyright (C) 1994 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#ifndef _ARMDEFS_H_
19#define _ARMDEFS_H_
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <errno.h>
24
25#include "common/platform.h"
26
27//teawater add for arm2x86 2005.02.14-------------------------------------------
28// koodailar remove it for mingw 2005.12.18----------------
29//anthonylee modify it for portable 2007.01.30
30//#include "portable/mman.h"
31
32#include "arm_regformat.h"
33#include "common/platform.h"
34#include "skyeye_defs.h"
35
36//AJ2D--------------------------------------------------------------------------
37
38//teawater add for arm2x86 2005.07.03-------------------------------------------
39
40#include <sys/types.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#if EMU_PLATFORM == PLATFORM_LINUX
45#include <unistd.h>
46#endif
47#include <errno.h>
48#include <sys/stat.h>
49#include <fcntl.h>
50
51//#include <memory_space.h>
52//AJ2D--------------------------------------------------------------------------
53#if 0
54#if 0
55#define DIFF_STATE 1
56#define __FOLLOW_MODE__ 0
57#else
58#define DIFF_STATE 0
59#define __FOLLOW_MODE__ 1
60#endif
61#endif
62
63#ifndef FALSE
64#define FALSE 0
65#define TRUE 1
66#endif
67
68#define LOW 0
69#define HIGH 1
70#define LOWHIGH 1
71#define HIGHLOW 2
72
73//teawater add DBCT_TEST_SPEED 2005.10.04---------------------------------------
74#include <signal.h>
75
76#include "common/platform.h"
77
78#if EMU_PLATFORM == PLATFORM_LINUX
79#include <sys/time.h>
80#endif
81
82//#define DBCT_TEST_SPEED
83#define DBCT_TEST_SPEED_SEC 10
84//AJ2D--------------------------------------------------------------------------
85
86//teawater add compile switch for DBCT GDB RSP function 2005.10.21--------------
87//#define DBCT_GDBRSP
88//AJ2D--------------------------------------------------------------------------
89
90//#include <skyeye_defs.h>
91//#include <skyeye_types.h>
92
93#define ARM_BYTE_TYPE 0
94#define ARM_HALFWORD_TYPE 1
95#define ARM_WORD_TYPE 2
96
97//the define of cachetype
98#define NONCACHE 0
99#define DATACACHE 1
100#define INSTCACHE 2
101
102#ifndef __STDC__
103typedef char *VoidStar;
104#endif
105
106typedef unsigned long long ARMdword; /* must be 64 bits wide */
107typedef unsigned int ARMword; /* must be 32 bits wide */
108typedef unsigned char ARMbyte; /* must be 8 bits wide */
109typedef unsigned short ARMhword; /* must be 16 bits wide */
110typedef struct ARMul_State ARMul_State;
111typedef struct ARMul_io ARMul_io;
112typedef struct ARMul_Energy ARMul_Energy;
113
114//teawater add for arm2x86 2005.06.24-------------------------------------------
115#include <stdint.h>
116//AJ2D--------------------------------------------------------------------------
117/*
118//chy 2005-05-11
119#ifndef __CYGWIN__
120//teawater add for arm2x86 2005.02.14-------------------------------------------
121typedef unsigned char uint8_t;
122typedef unsigned short uint16_t;
123typedef unsigned int u32;
124#if defined (__x86_64__)
125typedef unsigned long uint64_t;
126#else
127typedef unsigned long long uint64_t;
128#endif
129////AJ2D--------------------------------------------------------------------------
130#endif
131*/
132
133#include "armmmu.h"
134//#include "lcd/skyeye_lcd.h"
135
136
137//#include "skyeye.h"
138//#include "skyeye_device.h"
139//#include "net/skyeye_net.h"
140//#include "skyeye_config.h"
141
142
143typedef unsigned ARMul_CPInits (ARMul_State * state);
144typedef unsigned ARMul_CPExits (ARMul_State * state);
145typedef unsigned ARMul_LDCs (ARMul_State * state, unsigned type,
146 ARMword instr, ARMword value);
147typedef unsigned ARMul_STCs (ARMul_State * state, unsigned type,
148 ARMword instr, ARMword * value);
149typedef unsigned ARMul_MRCs (ARMul_State * state, unsigned type,
150 ARMword instr, ARMword * value);
151typedef unsigned ARMul_MCRs (ARMul_State * state, unsigned type,
152 ARMword instr, ARMword value);
153typedef unsigned ARMul_MRRCs (ARMul_State * state, unsigned type,
154 ARMword instr, ARMword * value1, ARMword * value2);
155typedef unsigned ARMul_MCRRs (ARMul_State * state, unsigned type,
156 ARMword instr, ARMword value1, ARMword value2);
157typedef unsigned ARMul_CDPs (ARMul_State * state, unsigned type,
158 ARMword instr);
159typedef unsigned ARMul_CPReads (ARMul_State * state, unsigned reg,
160 ARMword * value);
161typedef unsigned ARMul_CPWrites (ARMul_State * state, unsigned reg,
162 ARMword value);
163
164
165//added by ksh,2004-3-5
166struct ARMul_io
167{
168 ARMword *instr; //to display the current interrupt state
169 ARMword *net_flag; //to judge if network is enabled
170 ARMword *net_int; //netcard interrupt
171
172 //ywc,2004-04-01
173 ARMword *ts_int;
174 ARMword *ts_is_enable;
175 ARMword *ts_addr_begin;
176 ARMword *ts_addr_end;
177 ARMword *ts_buffer;
178};
179
180/* added by ksh,2004-11-26,some energy profiling */
181struct ARMul_Energy
182{
183 int energy_prof; /* <tktan> BUG200103282109 : for energy profiling */
184 int enable_func_energy; /* <tktan> BUG200105181702 */
185 char *func_energy;
186 int func_display; /* <tktan> BUG200103311509 : for function call display */
187 int func_disp_start; /* <tktan> BUG200104191428 : to start func profiling */
188 char *start_func; /* <tktan> BUG200104191428 */
189
190 FILE *outfile; /* <tktan> BUG200105201531 : direct console to file */
191 long long tcycle, pcycle;
192 float t_energy;
193 void *cur_task; /* <tktan> BUG200103291737 */
194 long long t_mem_cycle, t_idle_cycle, t_uart_cycle;
195 long long p_mem_cycle, p_idle_cycle, p_uart_cycle;
196 long long p_io_update_tcycle;
197 /*record CCCR,to get current core frequency */
198 ARMword cccr;
199};
200#if 0
201#define MAX_BANK 8
202#define MAX_STR 1024
203
204typedef struct mem_bank
205{
206 ARMword (*read_byte) (ARMul_State * state, ARMword addr);
207 void (*write_byte) (ARMul_State * state, ARMword addr, ARMword data);
208 ARMword (*read_halfword) (ARMul_State * state, ARMword addr);
209 void (*write_halfword) (ARMul_State * state, ARMword addr,
210 ARMword data);
211 ARMword (*read_word) (ARMul_State * state, ARMword addr);
212 void (*write_word) (ARMul_State * state, ARMword addr, ARMword data);
213 unsigned int addr, len;
214 char filename[MAX_STR];
215 unsigned type; //chy 2003-09-21: maybe io,ram,rom
216} mem_bank_t;
217typedef struct
218{
219 int bank_num;
220 int current_num; /*current num of bank */
221 mem_bank_t mem_banks[MAX_BANK];
222} mem_config_t;
223#endif
224#define VFP_REG_NUM 64
225struct ARMul_State
226{
227 ARMword Emulate; /* to start and stop emulation */
228 unsigned EndCondition; /* reason for stopping */
229 unsigned ErrorCode; /* type of illegal instruction */
230
231 /* Order of the following register should not be modified */
232 ARMword Reg[16]; /* the current register file */
233 ARMword Cpsr; /* the current psr */
234 ARMword Spsr_copy;
235 ARMword phys_pc;
236 ARMword Reg_usr[2];
237 ARMword Reg_svc[2]; /* R13_SVC R14_SVC */
238 ARMword Reg_abort[2]; /* R13_ABORT R14_ABORT */
239 ARMword Reg_undef[2]; /* R13 UNDEF R14 UNDEF */
240 ARMword Reg_irq[2]; /* R13_IRQ R14_IRQ */
241 ARMword Reg_firq[7]; /* R8---R14 FIRQ */
242 ARMword Spsr[7]; /* the exception psr's */
243 ARMword Mode; /* the current mode */
244 ARMword Bank; /* the current register bank */
245 ARMword exclusive_tag;
246 ARMword exclusive_state;
247 ARMword exclusive_result;
248 ARMword CP15[VFP_BASE - CP15_BASE];
249 ARMword VFP[3]; /* FPSID, FPSCR, and FPEXC */
250 /* VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31).
251 VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31),
252 and only 32 singleword registers are accessible (S0-S31). */
253 ARMword ExtReg[VFP_REG_NUM];
254 /* ---- End of the ordered registers ---- */
255
256 ARMword RegBank[7][16]; /* all the registers */
257 //chy:2003-08-19, used in arm xscale
258 /* 40 bit accumulator. We always keep this 64 bits wide,
259 and move only 40 bits out of it in an MRA insn. */
260 ARMdword Accumulator;
261
262 ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; /* dummy flags for speed */
263 unsigned long long int icounter, debug_icounter, kernel_icounter;
264 unsigned int shifter_carry_out;
265 //ARMword translate_pc;
266
267 /* add armv6 flags dyf:2010-08-09 */
268 ARMword GEFlag, EFlag, AFlag, QFlags;
269 //chy:2003-08-19, used in arm v5e|xscale
270 ARMword SFlag;
271#ifdef MODET
272 ARMword TFlag; /* Thumb state */
273#endif
274 ARMword instr, pc, temp; /* saved register state */
275 ARMword loaded, decoded; /* saved pipeline state */
276 //chy 2006-04-12 for ICE breakpoint
277 ARMword loaded_addr, decoded_addr; /* saved pipeline state addr*/
278 unsigned int NumScycles, NumNcycles, NumIcycles, NumCcycles, NumFcycles; /* emulated cycles used */
279 unsigned long long NumInstrs; /* the number of instructions executed */
280 unsigned NumInstrsToExecute;
281
282 ARMword currentexaddr;
283 ARMword currentexval;
284 ARMword servaddr;
285
286 unsigned NextInstr;
287 unsigned VectorCatch; /* caught exception mask */
288 unsigned CallDebug; /* set to call the debugger */
289 unsigned CanWatch; /* set by memory interface if its willing to suffer the
290 overhead of checking for watchpoints on each memory
291 access */
292 unsigned int StopHandle;
293
294 char *CommandLine; /* Command Line from ARMsd */
295
296 ARMul_CPInits *CPInit[16]; /* coprocessor initialisers */
297 ARMul_CPExits *CPExit[16]; /* coprocessor finalisers */
298 ARMul_LDCs *LDC[16]; /* LDC instruction */
299 ARMul_STCs *STC[16]; /* STC instruction */
300 ARMul_MRCs *MRC[16]; /* MRC instruction */
301 ARMul_MCRs *MCR[16]; /* MCR instruction */
302 ARMul_MRRCs *MRRC[16]; /* MRRC instruction */
303 ARMul_MCRRs *MCRR[16]; /* MCRR instruction */
304 ARMul_CDPs *CDP[16]; /* CDP instruction */
305 ARMul_CPReads *CPRead[16]; /* Read CP register */
306 ARMul_CPWrites *CPWrite[16]; /* Write CP register */
307 unsigned char *CPData[16]; /* Coprocessor data */
308 unsigned char const *CPRegWords[16]; /* map of coprocessor register sizes */
309
310 unsigned EventSet; /* the number of events in the queue */
311 unsigned int Now; /* time to the nearest cycle */
312 struct EventNode **EventPtr; /* the event list */
313
314 unsigned Debug; /* show instructions as they are executed */
315 unsigned NresetSig; /* reset the processor */
316 unsigned NfiqSig;
317 unsigned NirqSig;
318
319 unsigned abortSig;
320 unsigned NtransSig;
321 unsigned bigendSig;
322 unsigned prog32Sig;
323 unsigned data32Sig;
324 unsigned syscallSig;
325
326/* 2004-05-09 chy
327----------------------------------------------------------
328read ARM Architecture Reference Manual
3292.6.5 Data Abort
330There are three Abort Model in ARM arch.
331
332Early Abort Model: used in some ARMv3 and earlier implementations. In this
333model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and
334the base register was unchanged for all other instructions. (oldest)
335
336Base Restored Abort Model: If a Data Abort occurs in an instruction which
337specifies base register writeback, the value in the base register is
338unchanged. (strongarm, xscale)
339
340Base Updated Abort Model: If a Data Abort occurs in an instruction which
341specifies base register writeback, the base register writeback still occurs.
342(arm720T)
343
344read PART B
345chap2 The System Control Coprocessor CP15
3462.4 Register1:control register
347L(bit 6): in some ARMv3 and earlier implementations, the abort model of the
348processor could be configured:
3490=early Abort Model Selected(now obsolete)
3501=Late Abort Model selceted(same as Base Updated Abort Model)
351
352on later processors, this bit reads as 1 and ignores writes.
353-------------------------------------------------------------
354So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
355 if lateabtSig=0, then it means Base Restored Abort Model
356*/
357 unsigned lateabtSig;
358
359 ARMword Vector; /* synthesize aborts in cycle modes */
360 ARMword Aborted; /* sticky flag for aborts */
361 ARMword Reseted; /* sticky flag for Reset */
362 ARMword Inted, LastInted; /* sticky flags for interrupts */
363 ARMword Base; /* extra hand for base writeback */
364 ARMword AbortAddr; /* to keep track of Prefetch aborts */
365
366 const struct Dbg_HostosInterface *hostif;
367
368 int verbose; /* non-zero means print various messages like the banner */
369
370 mmu_state_t mmu;
371 int mmu_inited;
372 //mem_state_t mem;
373 /*remove io_state to skyeye_mach_*.c files */
374 //io_state_t io;
375 /* point to a interrupt pending register. now for skyeye-ne2k.c
376 * later should move somewhere. e.g machine_config_t*/
377
378
379 //chy: 2003-08-11, for different arm core type
380 unsigned is_v4; /* Are we emulating a v4 architecture (or higher) ? */
381 unsigned is_v5; /* Are we emulating a v5 architecture ? */
382 unsigned is_v5e; /* Are we emulating a v5e architecture ? */
383 unsigned is_v6; /* Are we emulating a v6 architecture ? */
384 unsigned is_v7; /* Are we emulating a v7 architecture ? */
385 unsigned is_XScale; /* Are we emulating an XScale architecture ? */
386 unsigned is_iWMMXt; /* Are we emulating an iWMMXt co-processor ? */
387 unsigned is_ep9312; /* Are we emulating a Cirrus Maverick co-processor ? */
388 //chy 2005-09-19
389 unsigned is_pxa27x; /* Are we emulating a Intel PXA27x co-processor ? */
390 //chy: seems only used in xscale's CP14
391 unsigned int LastTime; /* Value of last call to ARMul_Time() */
392 ARMword CP14R0_CCD; /* used to count 64 clock cycles with CP14 R0 bit 3 set */
393
394
395//added by ksh:for handle different machs io 2004-3-5
396 ARMul_io mach_io;
397
398/*added by ksh,2004-11-26,some energy profiling*/
399 ARMul_Energy energy;
400
401//teawater add for next_dis 2004.10.27-----------------------
402 int disassemble;
403//AJ2D------------------------------------------
404
405//teawater add for arm2x86 2005.02.15-------------------------------------------
406 u32 trap;
407 u32 tea_break_addr;
408 u32 tea_break_ok;
409 int tea_pc;
410//AJ2D--------------------------------------------------------------------------
411//teawater add for arm2x86 2005.07.03-------------------------------------------
412
413 /*
414 * 2007-01-24 removed the term-io functions by Anthony Lee,
415 * moved to "device/uart/skyeye_uart_stdio.c".
416 */
417
418//AJ2D--------------------------------------------------------------------------
419//teawater add for arm2x86 2005.07.05-------------------------------------------
420 //arm_arm A2-18
421 int abort_model; //0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model
422//AJ2D--------------------------------------------------------------------------
423//teawater change for return if running tb dirty 2005.07.09---------------------
424 void *tb_now;
425//AJ2D--------------------------------------------------------------------------
426
427//teawater add for record reg value to ./reg.txt 2005.07.10---------------------
428 FILE *tea_reg_fd;
429//AJ2D--------------------------------------------------------------------------
430
431/*added by ksh in 2005-10-1*/
432 cpu_config_t *cpu;
433 //mem_config_t *mem_bank;
434
435/* added LPC remap function */
436 int vector_remap_flag;
437 u32 vector_remap_addr;
438 u32 vector_remap_size;
439
440 u32 step;
441 u32 cycle;
442 int stop_simulator;
443 conf_object_t *dyncom_cpu;
444//teawater add DBCT_TEST_SPEED 2005.10.04---------------------------------------
445#ifdef DBCT_TEST_SPEED
446 uint64_t instr_count;
447#endif //DBCT_TEST_SPEED
448// FILE * state_log;
449//diff log
450//#if DIFF_STATE
451 FILE * state_log;
452//#endif
453 /* monitored memory for exclusice access */
454 ARMword exclusive_tag_array[128];
455 /* 1 means exclusive access and 0 means open access */
456 ARMword exclusive_access_state;
457
458 memory_space_intf space;
459 u32 CurrInstr;
460 u32 last_pc; /* the last pc executed */
461 u32 last_instr; /* the last inst executed */
462 u32 WriteAddr[17];
463 u32 WriteData[17];
464 u32 WritePc[17];
465 u32 CurrWrite;
466};
467#define DIFF_WRITE 0
468
469typedef ARMul_State arm_core_t;
470#define ResetPin NresetSig
471#define FIQPin NfiqSig
472#define IRQPin NirqSig
473#define AbortPin abortSig
474#define TransPin NtransSig
475#define BigEndPin bigendSig
476#define Prog32Pin prog32Sig
477#define Data32Pin data32Sig
478#define LateAbortPin lateabtSig
479
480/***************************************************************************\
481* Types of ARM we know about *
482\***************************************************************************/
483
484/* The bitflags */
485#define ARM_Fix26_Prop 0x01
486#define ARM_Nexec_Prop 0x02
487#define ARM_Debug_Prop 0x10
488#define ARM_Isync_Prop ARM_Debug_Prop
489#define ARM_Lock_Prop 0x20
490//chy 2003-08-11
491#define ARM_v4_Prop 0x40
492#define ARM_v5_Prop 0x80
493/*jeff.du 2010-08-05 */
494#define ARM_v6_Prop 0xc0
495
496#define ARM_v5e_Prop 0x100
497#define ARM_XScale_Prop 0x200
498#define ARM_ep9312_Prop 0x400
499#define ARM_iWMMXt_Prop 0x800
500//chy 2005-09-19
501#define ARM_PXA27X_Prop 0x1000
502#define ARM_v7_Prop 0x2000
503
504/* ARM2 family */
505#define ARM2 (ARM_Fix26_Prop)
506#define ARM2as ARM2
507#define ARM61 ARM2
508#define ARM3 ARM2
509
510#ifdef ARM60 /* previous definition in armopts.h */
511#undef ARM60
512#endif
513
514/* ARM6 family */
515#define ARM6 (ARM_Lock_Prop)
516#define ARM60 ARM6
517#define ARM600 ARM6
518#define ARM610 ARM6
519#define ARM620 ARM6
520
521
522/***************************************************************************\
523* Macros to extract instruction fields *
524\***************************************************************************/
525
526#define BIT(n) ( (ARMword)(instr>>(n))&1) /* bit n of instruction */
527#define BITS(m,n) ( (ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) ) /* bits m to n of instr */
528#define TOPBITS(n) (instr >> (n)) /* bits 31 to n of instr */
529
530/***************************************************************************\
531* The hardware vector addresses *
532\***************************************************************************/
533
534#define ARMResetV 0L
535#define ARMUndefinedInstrV 4L
536#define ARMSWIV 8L
537#define ARMPrefetchAbortV 12L
538#define ARMDataAbortV 16L
539#define ARMAddrExceptnV 20L
540#define ARMIRQV 24L
541#define ARMFIQV 28L
542#define ARMErrorV 32L /* This is an offset, not an address ! */
543
544#define ARMul_ResetV ARMResetV
545#define ARMul_UndefinedInstrV ARMUndefinedInstrV
546#define ARMul_SWIV ARMSWIV
547#define ARMul_PrefetchAbortV ARMPrefetchAbortV
548#define ARMul_DataAbortV ARMDataAbortV
549#define ARMul_AddrExceptnV ARMAddrExceptnV
550#define ARMul_IRQV ARMIRQV
551#define ARMul_FIQV ARMFIQV
552
553/***************************************************************************\
554* Mode and Bank Constants *
555\***************************************************************************/
556
557#define USER26MODE 0L
558#define FIQ26MODE 1L
559#define IRQ26MODE 2L
560#define SVC26MODE 3L
561#define USER32MODE 16L
562#define FIQ32MODE 17L
563#define IRQ32MODE 18L
564#define SVC32MODE 19L
565#define ABORT32MODE 23L
566#define UNDEF32MODE 27L
567//chy 2006-02-15 add system32 mode
568#define SYSTEM32MODE 31L
569
570#define ARM32BITMODE (state->Mode > 3)
571#define ARM26BITMODE (state->Mode <= 3)
572#define ARMMODE (state->Mode)
573#define ARMul_MODEBITS 0x1fL
574#define ARMul_MODE32BIT ARM32BITMODE
575#define ARMul_MODE26BIT ARM26BITMODE
576
577#define USERBANK 0
578#define FIQBANK 1
579#define IRQBANK 2
580#define SVCBANK 3
581#define ABORTBANK 4
582#define UNDEFBANK 5
583#define DUMMYBANK 6
584#define SYSTEMBANK USERBANK
585#define BANK_CAN_ACCESS_SPSR(bank) \
586 ((bank) != USERBANK && (bank) != SYSTEMBANK && (bank) != DUMMYBANK)
587
588
589/***************************************************************************\
590* Definitons of things in the emulator *
591\***************************************************************************/
592#ifdef __cplusplus
593extern "C" {
594#endif
595extern void ARMul_EmulateInit (void);
596extern void ARMul_Reset (ARMul_State * state);
597#ifdef __cplusplus
598 }
599#endif
600extern ARMul_State *ARMul_NewState (ARMul_State * state);
601extern ARMword ARMul_DoProg (ARMul_State * state);
602extern ARMword ARMul_DoInstr (ARMul_State * state);
603/***************************************************************************\
604* Definitons of things for event handling *
605\***************************************************************************/
606
607extern void ARMul_ScheduleEvent (ARMul_State * state, unsigned int delay,
608 unsigned (*func) ());
609extern void ARMul_EnvokeEvent (ARMul_State * state);
610extern unsigned int ARMul_Time (ARMul_State * state);
611
612/***************************************************************************\
613* Useful support routines *
614\***************************************************************************/
615
616extern ARMword ARMul_GetReg (ARMul_State * state, unsigned mode,
617 unsigned reg);
618extern void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg,
619 ARMword value);
620extern ARMword ARMul_GetPC (ARMul_State * state);
621extern ARMword ARMul_GetNextPC (ARMul_State * state);
622extern void ARMul_SetPC (ARMul_State * state, ARMword value);
623extern ARMword ARMul_GetR15 (ARMul_State * state);
624extern void ARMul_SetR15 (ARMul_State * state, ARMword value);
625
626extern ARMword ARMul_GetCPSR (ARMul_State * state);
627extern void ARMul_SetCPSR (ARMul_State * state, ARMword value);
628extern ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode);
629extern void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value);
630
631/***************************************************************************\
632* Definitons of things to handle aborts *
633\***************************************************************************/
634
635extern void ARMul_Abort (ARMul_State * state, ARMword address);
636#ifdef MODET
637#define ARMul_ABORTWORD (state->TFlag ? 0xefffdfff : 0xefffffff) /* SWI -1 */
638#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \
639 state->AbortAddr = (address & (state->TFlag ? ~1L : ~3L))
640#else
641#define ARMul_ABORTWORD 0xefffffff /* SWI -1 */
642#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \
643 state->AbortAddr = (address & ~3L)
644#endif
645#define ARMul_DATAABORT(address) state->abortSig = HIGH ; \
646 state->Aborted = ARMul_DataAbortV ;
647#define ARMul_CLEARABORT state->abortSig = LOW
648
649/***************************************************************************\
650* Definitons of things in the memory interface *
651\***************************************************************************/
652
653extern unsigned ARMul_MemoryInit (ARMul_State * state,
654 unsigned int initmemsize);
655extern void ARMul_MemoryExit (ARMul_State * state);
656
657extern ARMword ARMul_LoadInstrS (ARMul_State * state, ARMword address,
658 ARMword isize);
659extern ARMword ARMul_LoadInstrN (ARMul_State * state, ARMword address,
660 ARMword isize);
661#ifdef __cplusplus
662extern "C" {
663#endif
664extern ARMword ARMul_ReLoadInstr (ARMul_State * state, ARMword address,
665 ARMword isize);
666#ifdef __cplusplus
667 }
668#endif
669extern ARMword ARMul_LoadWordS (ARMul_State * state, ARMword address);
670extern ARMword ARMul_LoadWordN (ARMul_State * state, ARMword address);
671extern ARMword ARMul_LoadHalfWord (ARMul_State * state, ARMword address);
672extern ARMword ARMul_LoadByte (ARMul_State * state, ARMword address);
673
674extern void ARMul_StoreWordS (ARMul_State * state, ARMword address,
675 ARMword data);
676extern void ARMul_StoreWordN (ARMul_State * state, ARMword address,
677 ARMword data);
678extern void ARMul_StoreHalfWord (ARMul_State * state, ARMword address,
679 ARMword data);
680extern void ARMul_StoreByte (ARMul_State * state, ARMword address,
681 ARMword data);
682
683extern ARMword ARMul_SwapWord (ARMul_State * state, ARMword address,
684 ARMword data);
685extern ARMword ARMul_SwapByte (ARMul_State * state, ARMword address,
686 ARMword data);
687
688extern void ARMul_Icycles (ARMul_State * state, unsigned number,
689 ARMword address);
690extern void ARMul_Ccycles (ARMul_State * state, unsigned number,
691 ARMword address);
692
693extern ARMword ARMul_ReadWord (ARMul_State * state, ARMword address);
694extern ARMword ARMul_ReadByte (ARMul_State * state, ARMword address);
695extern void ARMul_WriteWord (ARMul_State * state, ARMword address,
696 ARMword data);
697extern void ARMul_WriteByte (ARMul_State * state, ARMword address,
698 ARMword data);
699
700extern ARMword ARMul_MemAccess (ARMul_State * state, ARMword, ARMword,
701 ARMword, ARMword, ARMword, ARMword, ARMword,
702 ARMword, ARMword, ARMword);
703
704/***************************************************************************\
705* Definitons of things in the co-processor interface *
706\***************************************************************************/
707
708#define ARMul_FIRST 0
709#define ARMul_TRANSFER 1
710#define ARMul_BUSY 2
711#define ARMul_DATA 3
712#define ARMul_INTERRUPT 4
713#define ARMul_DONE 0
714#define ARMul_CANT 1
715#define ARMul_INC 3
716
717#define ARMul_CP13_R0_FIQ 0x1
718#define ARMul_CP13_R0_IRQ 0x2
719#define ARMul_CP13_R8_PMUS 0x1
720
721#define ARMul_CP14_R0_ENABLE 0x0001
722#define ARMul_CP14_R0_CLKRST 0x0004
723#define ARMul_CP14_R0_CCD 0x0008
724#define ARMul_CP14_R0_INTEN0 0x0010
725#define ARMul_CP14_R0_INTEN1 0x0020
726#define ARMul_CP14_R0_INTEN2 0x0040
727#define ARMul_CP14_R0_FLAG0 0x0100
728#define ARMul_CP14_R0_FLAG1 0x0200
729#define ARMul_CP14_R0_FLAG2 0x0400
730#define ARMul_CP14_R10_MOE_IB 0x0004
731#define ARMul_CP14_R10_MOE_DB 0x0008
732#define ARMul_CP14_R10_MOE_BT 0x000c
733#define ARMul_CP15_R1_ENDIAN 0x0080
734#define ARMul_CP15_R1_ALIGN 0x0002
735#define ARMul_CP15_R5_X 0x0400
736#define ARMul_CP15_R5_ST_ALIGN 0x0001
737#define ARMul_CP15_R5_IMPRE 0x0406
738#define ARMul_CP15_R5_MMU_EXCPT 0x0400
739#define ARMul_CP15_DBCON_M 0x0100
740#define ARMul_CP15_DBCON_E1 0x000c
741#define ARMul_CP15_DBCON_E0 0x0003
742
743extern unsigned ARMul_CoProInit (ARMul_State * state);
744extern void ARMul_CoProExit (ARMul_State * state);
745extern void ARMul_CoProAttach (ARMul_State * state, unsigned number,
746 ARMul_CPInits * init, ARMul_CPExits * exit,
747 ARMul_LDCs * ldc, ARMul_STCs * stc,
748 ARMul_MRCs * mrc, ARMul_MCRs * mcr,
749 ARMul_MRRCs * mrrc, ARMul_MCRRs * mcrr,
750 ARMul_CDPs * cdp,
751 ARMul_CPReads * read, ARMul_CPWrites * write);
752extern void ARMul_CoProDetach (ARMul_State * state, unsigned number);
753
754/***************************************************************************\
755* Definitons of things in the host environment *
756\***************************************************************************/
757
758extern unsigned ARMul_OSInit (ARMul_State * state);
759extern void ARMul_OSExit (ARMul_State * state);
760
761#ifdef __cplusplus
762 extern "C" {
763#endif
764
765extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number);
766#ifdef __cplusplus
767}
768#endif
769
770
771extern ARMword ARMul_OSLastErrorP (ARMul_State * state);
772
773extern ARMword ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr);
774extern unsigned ARMul_OSException (ARMul_State * state, ARMword vector,
775 ARMword pc);
776extern int rdi_log;
777
778/***************************************************************************\
779* Host-dependent stuff *
780\***************************************************************************/
781
782#ifdef macintosh
783pascal void SpinCursor (short increment); /* copied from CursorCtl.h */
784# define HOURGLASS SpinCursor( 1 )
785# define HOURGLASS_RATE 1023 /* 2^n - 1 */
786#endif
787
788//teawater add for arm2x86 2005.02.14-------------------------------------------
789/*ywc 2005-03-31*/
790/*
791#include "arm2x86.h"
792#include "arm2x86_dp.h"
793#include "arm2x86_movl.h"
794#include "arm2x86_psr.h"
795#include "arm2x86_shift.h"
796#include "arm2x86_mem.h"
797#include "arm2x86_mul.h"
798#include "arm2x86_test.h"
799#include "arm2x86_other.h"
800#include "list.h"
801#include "tb.h"
802*/
803#define EQ 0
804#define NE 1
805#define CS 2
806#define CC 3
807#define MI 4
808#define PL 5
809#define VS 6
810#define VC 7
811#define HI 8
812#define LS 9
813#define GE 10
814#define LT 11
815#define GT 12
816#define LE 13
817#define AL 14
818#define NV 15
819
820#ifndef NFLAG
821#define NFLAG state->NFlag
822#endif //NFLAG
823
824#ifndef ZFLAG
825#define ZFLAG state->ZFlag
826#endif //ZFLAG
827
828#ifndef CFLAG
829#define CFLAG state->CFlag
830#endif //CFLAG
831
832#ifndef VFLAG
833#define VFLAG state->VFlag
834#endif //VFLAG
835
836#ifndef IFLAG
837#define IFLAG (state->IFFlags >> 1)
838#endif //IFLAG
839
840#ifndef FFLAG
841#define FFLAG (state->IFFlags & 1)
842#endif //FFLAG
843
844#ifndef IFFLAGS
845#define IFFLAGS state->IFFlags
846#endif //VFLAG
847
848#define FLAG_MASK 0xf0000000
849#define NBIT_SHIFT 31
850#define ZBIT_SHIFT 30
851#define CBIT_SHIFT 29
852#define VBIT_SHIFT 28
853#ifdef DBCT
854//teawater change for local tb branch directly jump 2005.10.18------------------
855#include "dbct/list.h"
856#include "dbct/arm2x86.h"
857#include "dbct/arm2x86_dp.h"
858#include "dbct/arm2x86_movl.h"
859#include "dbct/arm2x86_psr.h"
860#include "dbct/arm2x86_shift.h"
861#include "dbct/arm2x86_mem.h"
862#include "dbct/arm2x86_mul.h"
863#include "dbct/arm2x86_test.h"
864#include "dbct/arm2x86_other.h"
865#include "dbct/arm2x86_coproc.h"
866#include "dbct/tb.h"
867#endif
868//AJ2D--------------------------------------------------------------------------
869//AJ2D--------------------------------------------------------------------------
870#define SKYEYE_OUTREGS(fd) { fprintf ((fd), "R %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,C %x,S %x,%x,%x,%x,%x,%x,%x,M %x,B %x,E %x,I %x,P %x,T %x,L %x,D %x,",\
871 state->Reg[0],state->Reg[1],state->Reg[2],state->Reg[3], \
872 state->Reg[4],state->Reg[5],state->Reg[6],state->Reg[7], \
873 state->Reg[8],state->Reg[9],state->Reg[10],state->Reg[11], \
874 state->Reg[12],state->Reg[13],state->Reg[14],state->Reg[15], \
875 state->Cpsr, state->Spsr[0], state->Spsr[1], state->Spsr[2],\
876 state->Spsr[3],state->Spsr[4], state->Spsr[5], state->Spsr[6],\
877 state->Mode,state->Bank,state->ErrorCode,state->instr,state->pc,\
878 state->temp,state->loaded,state->decoded);}
879
880#define SKYEYE_OUTMOREREGS(fd) { fprintf ((fd),"\
881RUs %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
882RF %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
883RI %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
884RS %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
885RA %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
886RUn %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",\
887 state->RegBank[0][0],state->RegBank[0][1],state->RegBank[0][2],state->RegBank[0][3], \
888 state->RegBank[0][4],state->RegBank[0][5],state->RegBank[0][6],state->RegBank[0][7], \
889 state->RegBank[0][8],state->RegBank[0][9],state->RegBank[0][10],state->RegBank[0][11], \
890 state->RegBank[0][12],state->RegBank[0][13],state->RegBank[0][14],state->RegBank[0][15], \
891 state->RegBank[1][0],state->RegBank[1][1],state->RegBank[1][2],state->RegBank[1][3], \
892 state->RegBank[1][4],state->RegBank[1][5],state->RegBank[1][6],state->RegBank[1][7], \
893 state->RegBank[1][8],state->RegBank[1][9],state->RegBank[1][10],state->RegBank[1][11], \
894 state->RegBank[1][12],state->RegBank[1][13],state->RegBank[1][14],state->RegBank[1][15], \
895 state->RegBank[2][0],state->RegBank[2][1],state->RegBank[2][2],state->RegBank[2][3], \
896 state->RegBank[2][4],state->RegBank[2][5],state->RegBank[2][6],state->RegBank[2][7], \
897 state->RegBank[2][8],state->RegBank[2][9],state->RegBank[2][10],state->RegBank[2][11], \
898 state->RegBank[2][12],state->RegBank[2][13],state->RegBank[2][14],state->RegBank[2][15], \
899 state->RegBank[3][0],state->RegBank[3][1],state->RegBank[3][2],state->RegBank[3][3], \
900 state->RegBank[3][4],state->RegBank[3][5],state->RegBank[3][6],state->RegBank[3][7], \
901 state->RegBank[3][8],state->RegBank[3][9],state->RegBank[3][10],state->RegBank[3][11], \
902 state->RegBank[3][12],state->RegBank[3][13],state->RegBank[3][14],state->RegBank[3][15], \
903 state->RegBank[4][0],state->RegBank[4][1],state->RegBank[4][2],state->RegBank[4][3], \
904 state->RegBank[4][4],state->RegBank[4][5],state->RegBank[4][6],state->RegBank[4][7], \
905 state->RegBank[4][8],state->RegBank[4][9],state->RegBank[4][10],state->RegBank[4][11], \
906 state->RegBank[4][12],state->RegBank[4][13],state->RegBank[4][14],state->RegBank[4][15], \
907 state->RegBank[5][0],state->RegBank[5][1],state->RegBank[5][2],state->RegBank[5][3], \
908 state->RegBank[5][4],state->RegBank[5][5],state->RegBank[5][6],state->RegBank[5][7], \
909 state->RegBank[5][8],state->RegBank[5][9],state->RegBank[5][10],state->RegBank[5][11], \
910 state->RegBank[5][12],state->RegBank[5][13],state->RegBank[5][14],state->RegBank[5][15] \
911 );}
912
913
914#define SA1110 0x6901b110
915#define SA1100 0x4401a100
916#define PXA250 0x69052100
917#define PXA270 0x69054110
918//#define PXA250 0x69052903
919// 0x69052903; //PXA250 B1 from intel 278522-001.pdf
920
921
922extern void ARMul_UndefInstr (ARMul_State *, ARMword);
923extern void ARMul_FixCPSR (ARMul_State *, ARMword, ARMword);
924extern void ARMul_FixSPSR (ARMul_State *, ARMword, ARMword);
925extern void ARMul_ConsolePrint (ARMul_State *, const char *, ...);
926extern void ARMul_SelectProcessor (ARMul_State *, unsigned);
927
928#define DIFF_LOG 0
929#define SAVE_LOG 0
930
931#endif /* _ARMDEFS_H_ */
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index f9130ef88..7ffc16429 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -18,9 +18,9 @@
18 18
19//#include <util.h> // DEBUG() 19//#include <util.h> // DEBUG()
20 20
21#include "arm_regformat.h" 21#include "core/arm/skyeye_common/arm_regformat.h"
22#include "armdefs.h" 22#include "core/arm/skyeye_common/armdefs.h"
23#include "armemu.h" 23#include "core/arm/skyeye_common/armemu.h"
24#include "core/hle/hle.h" 24#include "core/hle/hle.h"
25 25
26//#include "svc.h" 26//#include "svc.h"
diff --git a/src/core/arm/interpreter/armemu.h b/src/core/arm/interpreter/armemu.h
deleted file mode 100644
index 36fb2d09b..000000000
--- a/src/core/arm/interpreter/armemu.h
+++ /dev/null
@@ -1,656 +0,0 @@
1/* armemu.h -- ARMulator emulation macros: ARM6 Instruction Emulator.
2 Copyright (C) 1994 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#ifndef __ARMEMU_H__
18#define __ARMEMU_H__
19
20
21#include "armdefs.h"
22//#include "skyeye.h"
23
24//extern ARMword isize;
25
26#define DEBUG(...) DEBUG_LOG(ARM11, __VA_ARGS__)
27
28/* Condition code values. */
29#define EQ 0
30#define NE 1
31#define CS 2
32#define CC 3
33#define MI 4
34#define PL 5
35#define VS 6
36#define VC 7
37#define HI 8
38#define LS 9
39#define GE 10
40#define LT 11
41#define GT 12
42#define LE 13
43#define AL 14
44#define NV 15
45
46/* Shift Opcodes. */
47#define LSL 0
48#define LSR 1
49#define ASR 2
50#define ROR 3
51
52/* Macros to twiddle the status flags and mode. */
53#define NBIT ((unsigned)1L << 31)
54#define ZBIT (1L << 30)
55#define CBIT (1L << 29)
56#define VBIT (1L << 28)
57#define SBIT (1L << 27)
58#define IBIT (1L << 7)
59#define FBIT (1L << 6)
60#define IFBITS (3L << 6)
61#define R15IBIT (1L << 27)
62#define R15FBIT (1L << 26)
63#define R15IFBITS (3L << 26)
64
65#define POS(i) ( (~(i)) >> 31 )
66#define NEG(i) ( (i) >> 31 )
67
68#ifdef MODET /* Thumb support. */
69/* ??? This bit is actually in the low order bit of the PC in the hardware.
70 It isn't clear if the simulator needs to model that or not. */
71#define TBIT (1L << 5)
72#define TFLAG state->TFlag
73#define SETT state->TFlag = 1
74#define CLEART state->TFlag = 0
75#define ASSIGNT(res) state->TFlag = res
76#define INSN_SIZE (TFLAG ? 2 : 4)
77#else
78#define INSN_SIZE 4
79#endif
80
81/*add armv6 CPSR feature*/
82#define EFLAG state->EFlag
83#define SETE state->EFlag = 1
84#define CLEARE state->EFlag = 0
85#define ASSIGNE(res) state->NFlag = res
86
87#define AFLAG state->AFlag
88#define SETA state->AFlag = 1
89#define CLEARA state->AFlag = 0
90#define ASSIGNA(res) state->NFlag = res
91
92#define QFLAG state->QFlag
93#define SETQ state->QFlag = 1
94#define CLEARQ state->AFlag = 0
95#define ASSIGNQ(res) state->QFlag = res
96
97/* add end */
98
99#define NFLAG state->NFlag
100#define SETN state->NFlag = 1
101#define CLEARN state->NFlag = 0
102#define ASSIGNN(res) state->NFlag = res
103
104#define ZFLAG state->ZFlag
105#define SETZ state->ZFlag = 1
106#define CLEARZ state->ZFlag = 0
107#define ASSIGNZ(res) state->ZFlag = res
108
109#define CFLAG state->CFlag
110#define SETC state->CFlag = 1
111#define CLEARC state->CFlag = 0
112#define ASSIGNC(res) state->CFlag = res
113
114#define VFLAG state->VFlag
115#define SETV state->VFlag = 1
116#define CLEARV state->VFlag = 0
117#define ASSIGNV(res) state->VFlag = res
118
119#define SFLAG state->SFlag
120#define SETS state->SFlag = 1
121#define CLEARS state->SFlag = 0
122#define ASSIGNS(res) state->SFlag = res
123
124#define IFLAG (state->IFFlags >> 1)
125#define FFLAG (state->IFFlags & 1)
126#define IFFLAGS state->IFFlags
127#define ASSIGNINT(res) state->IFFlags = (((res) >> 6) & 3)
128#define ASSIGNR15INT(res) state->IFFlags = (((res) >> 26) & 3) ;
129
130#define PSR_FBITS (0xff000000L)
131#define PSR_SBITS (0x00ff0000L)
132#define PSR_XBITS (0x0000ff00L)
133#define PSR_CBITS (0x000000ffL)
134
135#if defined MODE32 || defined MODET
136#define CCBITS (0xf8000000L)
137#else
138#define CCBITS (0xf0000000L)
139#endif
140
141#define INTBITS (0xc0L)
142
143#if defined MODET && defined MODE32
144#define PCBITS (0xffffffffL)
145#else
146#define PCBITS (0xfffffffcL)
147#endif
148
149#define MODEBITS (0x1fL)
150#define R15INTBITS (3L << 26)
151
152#if defined MODET && defined MODE32
153#define R15PCBITS (0x03ffffffL)
154#else
155#define R15PCBITS (0x03fffffcL)
156#endif
157
158#define R15PCMODEBITS (0x03ffffffL)
159#define R15MODEBITS (0x3L)
160
161#ifdef MODE32
162#define PCMASK PCBITS
163#define PCWRAP(pc) (pc)
164#else
165#define PCMASK R15PCBITS
166#define PCWRAP(pc) ((pc) & R15PCBITS)
167#endif
168
169#define PC (state->Reg[15] & PCMASK)
170#define R15CCINTMODE (state->Reg[15] & (CCBITS | R15INTBITS | R15MODEBITS))
171#define R15INT (state->Reg[15] & R15INTBITS)
172#define R15INTPC (state->Reg[15] & (R15INTBITS | R15PCBITS))
173#define R15INTPCMODE (state->Reg[15] & (R15INTBITS | R15PCBITS | R15MODEBITS))
174#define R15INTMODE (state->Reg[15] & (R15INTBITS | R15MODEBITS))
175#define R15PC (state->Reg[15] & R15PCBITS)
176#define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS))
177#define R15MODE (state->Reg[15] & R15MODEBITS)
178
179#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (SFLAG << 27))
180#define EINT (IFFLAGS << 6)
181#define ER15INT (IFFLAGS << 26)
182#define EMODE (state->Mode)
183
184#ifdef MODET
185#define CPSR (ECC | EINT | EMODE | (TFLAG << 5))
186#else
187#define CPSR (ECC | EINT | EMODE)
188#endif
189
190#ifdef MODE32
191#define PATCHR15
192#else
193#define PATCHR15 state->Reg[15] = ECC | ER15INT | EMODE | R15PC
194#endif
195
196#define GETSPSR(bank) (ARMul_GetSPSR (state, EMODE))
197#define SETPSR_F(d,s) d = ((d) & ~PSR_FBITS) | ((s) & PSR_FBITS)
198#define SETPSR_S(d,s) d = ((d) & ~PSR_SBITS) | ((s) & PSR_SBITS)
199#define SETPSR_X(d,s) d = ((d) & ~PSR_XBITS) | ((s) & PSR_XBITS)
200#define SETPSR_C(d,s) d = ((d) & ~PSR_CBITS) | ((s) & PSR_CBITS)
201
202#define SETR15PSR(s) \
203 do \
204 { \
205 if (state->Mode == USER26MODE) \
206 { \
207 state->Reg[15] = ((s) & CCBITS) | R15PC | ER15INT | EMODE; \
208 ASSIGNN ((state->Reg[15] & NBIT) != 0); \
209 ASSIGNZ ((state->Reg[15] & ZBIT) != 0); \
210 ASSIGNC ((state->Reg[15] & CBIT) != 0); \
211 ASSIGNV ((state->Reg[15] & VBIT) != 0); \
212 } \
213 else \
214 { \
215 state->Reg[15] = R15PC | ((s) & (CCBITS | R15INTBITS | R15MODEBITS)); \
216 ARMul_R15Altered (state); \
217 } \
218 } \
219 while (0)
220
221#define SETABORT(i, m, d) \
222 do \
223 { \
224 int SETABORT_mode = (m); \
225 \
226 ARMul_SetSPSR (state, SETABORT_mode, ARMul_GetCPSR (state)); \
227 ARMul_SetCPSR (state, ((ARMul_GetCPSR (state) & ~(EMODE | TBIT)) \
228 | (i) | SETABORT_mode)); \
229 state->Reg[14] = temp - (d); \
230 } \
231 while (0)
232
233#ifndef MODE32
234#define VECTORS 0x20
235#define LEGALADDR 0x03ffffff
236#define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig)
237#define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig)
238#endif
239
240#define INTERNALABORT(address) \
241 do \
242 { \
243 if (address < VECTORS) \
244 state->Aborted = ARMul_DataAbortV; \
245 else \
246 state->Aborted = ARMul_AddrExceptnV; \
247 } \
248 while (0)
249
250#ifdef MODE32
251#define TAKEABORT ARMul_Abort (state, ARMul_DataAbortV)
252#else
253#define TAKEABORT \
254 do \
255 { \
256 if (state->Aborted == ARMul_AddrExceptnV) \
257 ARMul_Abort (state, ARMul_AddrExceptnV); \
258 else \
259 ARMul_Abort (state, ARMul_DataAbortV); \
260 } \
261 while (0)
262#endif
263
264#define CPTAKEABORT \
265 do \
266 { \
267 if (!state->Aborted) \
268 ARMul_Abort (state, ARMul_UndefinedInstrV); \
269 else if (state->Aborted == ARMul_AddrExceptnV) \
270 ARMul_Abort (state, ARMul_AddrExceptnV); \
271 else \
272 ARMul_Abort (state, ARMul_DataAbortV); \
273 } \
274 while (0);
275
276
277/* Different ways to start the next instruction. */
278#define SEQ 0
279#define NONSEQ 1
280#define PCINCEDSEQ 2
281#define PCINCEDNONSEQ 3
282#define PRIMEPIPE 4
283#define RESUME 8
284
285/************************************/
286/* shenoubang 2012-3-11 */
287/* for armv7 DBG DMB DSB instr*/
288/************************************/
289#define MBReqTypes_Writes 0
290#define MBReqTypes_All 1
291
292#define NORMALCYCLE state->NextInstr = 0
293#define BUSUSEDN state->NextInstr |= 1 /* The next fetch will be an N cycle. */
294#define BUSUSEDINCPCS \
295 do \
296 { \
297 if (! state->is_v4) \
298 { \
299 /* A standard PC inc and an S cycle. */ \
300 state->Reg[15] += INSN_SIZE; \
301 state->NextInstr = (state->NextInstr & 0xff) | 2; \
302 } \
303 } \
304 while (0)
305
306#define BUSUSEDINCPCN \
307 do \
308 { \
309 if (state->is_v4) \
310 BUSUSEDN; \
311 else \
312 { \
313 /* A standard PC inc and an N cycle. */ \
314 state->Reg[15] += INSN_SIZE; \
315 state->NextInstr |= 3; \
316 } \
317 } \
318 while (0)
319
320#define INCPC \
321 do \
322 { \
323 /* A standard PC inc. */ \
324 state->Reg[15] += INSN_SIZE; \
325 state->NextInstr |= 2; \
326 } \
327 while (0)
328
329#define FLUSHPIPE state->NextInstr |= PRIMEPIPE
330
331/* Cycle based emulation. */
332
333#define OUTPUTCP(i,a,b)
334#define NCYCLE
335#define SCYCLE
336#define ICYCLE
337#define CCYCLE
338#define NEXTCYCLE(c)
339
340/* Macros to extract parts of instructions. */
341#define DESTReg (BITS (12, 15))
342#define LHSReg (BITS (16, 19))
343#define RHSReg (BITS ( 0, 3))
344
345#define DEST (state->Reg[DESTReg])
346
347#ifdef MODE32
348#ifdef MODET
349#define LHS ((LHSReg == 15) ? (state->Reg[15] & 0xFFFFFFFC) : (state->Reg[LHSReg]))
350#define RHS ((RHSReg == 15) ? (state->Reg[15] & 0xFFFFFFFC) : (state->Reg[RHSReg]))
351#else
352#define LHS (state->Reg[LHSReg])
353#define RHS (state->Reg[RHSReg])
354#endif
355#else
356#define LHS ((LHSReg == 15) ? R15PC : (state->Reg[LHSReg]))
357#define RHS ((RHSReg == 15) ? R15PC : (state->Reg[RHSReg]))
358#endif
359
360#define MULDESTReg (BITS (16, 19))
361#define MULLHSReg (BITS ( 0, 3))
362#define MULRHSReg (BITS ( 8, 11))
363#define MULACCReg (BITS (12, 15))
364
365#define DPImmRHS (ARMul_ImmedTable[BITS(0, 11)])
366#define DPSImmRHS temp = BITS(0,11) ; \
367 rhs = ARMul_ImmedTable[temp] ; \
368 if (temp > 255) /* There was a shift. */ \
369 ASSIGNC (rhs >> 31) ;
370
371#ifdef MODE32
372#define DPRegRHS ((BITS (4,11) == 0) ? state->Reg[RHSReg] \
373 : GetDPRegRHS (state, instr))
374#define DPSRegRHS ((BITS (4,11) == 0) ? state->Reg[RHSReg] \
375 : GetDPSRegRHS (state, instr))
376#else
377#define DPRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
378 : GetDPRegRHS (state, instr))
379#define DPSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
380 : GetDPSRegRHS (state, instr))
381#endif
382
383#define LSBase state->Reg[LHSReg]
384#define LSImmRHS (BITS(0,11))
385
386#ifdef MODE32
387#define LSRegRHS ((BITS (4, 11) == 0) ? state->Reg[RHSReg] \
388 : GetLSRegRHS (state, instr))
389#else
390#define LSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
391 : GetLSRegRHS (state, instr))
392#endif
393
394#define LSMNumRegs ((ARMword) ARMul_BitList[BITS (0, 7)] + \
395 (ARMword) ARMul_BitList[BITS (8, 15)] )
396#define LSMBaseFirst ((LHSReg == 0 && BIT (0)) || \
397 (BIT (LHSReg) && BITS (0, LHSReg - 1) == 0))
398
399#define SWAPSRC (state->Reg[RHSReg])
400
401#define LSCOff (BITS (0, 7) << 2)
402#define CPNum BITS (8, 11)
403
404/* Determine if access to coprocessor CP is permitted.
405 The XScale has a register in CP15 which controls access to CP0 - CP13. */
406//chy 2003-09-03, new CP_ACCESS_ALLOWED
407/*
408#define CP_ACCESS_ALLOWED(STATE, CP) \
409 ( ((CP) >= 14) \
410 || (! (STATE)->is_XScale) \
411 || (read_cp15_reg (15, 0, 1) & (1 << (CP))))
412*/
413#define CP_ACCESS_ALLOWED(STATE, CP) \
414 ( ((CP) >= 14) ) \
415
416/* Macro to rotate n right by b bits. */
417#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b))))
418
419/* Macros to store results of instructions. */
420#define WRITEDEST(d) \
421 do \
422 { \
423 if (DESTReg == 15) \
424 WriteR15 (state, d); \
425 else \
426 DEST = d; \
427 } \
428 while (0)
429
430#define WRITESDEST(d) \
431 do \
432 { \
433 if (DESTReg == 15) \
434 WriteSR15 (state, d); \
435 else \
436 { \
437 DEST = d; \
438 ARMul_NegZero (state, d); \
439 } \
440 } \
441 while (0)
442
443#define WRITEDESTB(d) \
444 do \
445 { \
446 if (DESTReg == 15){ \
447 WriteR15Branch (state, d); \
448 } \
449 else{ \
450 DEST = d; \
451 } \
452 } \
453 while (0)
454
455#define BYTETOBUS(data) ((data & 0xff) | \
456 ((data & 0xff) << 8) | \
457 ((data & 0xff) << 16) | \
458 ((data & 0xff) << 24))
459
460#define BUSTOBYTE(address, data) \
461 do \
462 { \
463 if (state->bigendSig) \
464 temp = (data >> (((address ^ 3) & 3) << 3)) & 0xff; \
465 else \
466 temp = (data >> ((address & 3) << 3)) & 0xff; \
467 } \
468 while (0)
469
470#define LOADMULT(instr, address, wb) LoadMult (state, instr, address, wb)
471#define LOADSMULT(instr, address, wb) LoadSMult (state, instr, address, wb)
472#define STOREMULT(instr, address, wb) StoreMult (state, instr, address, wb)
473#define STORESMULT(instr, address, wb) StoreSMult (state, instr, address, wb)
474
475#define POSBRANCH ((instr & 0x7fffff) << 2)
476#define NEGBRANCH ((0xff000000 |(instr & 0xffffff)) << 2)
477
478
479/* Values for Emulate. */
480#define STOP 0 /* stop */
481#define CHANGEMODE 1 /* change mode */
482#define ONCE 2 /* execute just one interation */
483#define RUN 3 /* continuous execution */
484
485/* Stuff that is shared across modes. */
486extern unsigned ARMul_MultTable[]; /* Number of I cycles for a mult. */
487extern ARMword ARMul_ImmedTable[]; /* Immediate DP LHS values. */
488extern char ARMul_BitList[]; /* Number of bits in a byte table. */
489
490#define EVENTLISTSIZE 1024L
491
492/* Thumb support. */
493typedef enum
494{
495 t_undefined, /* Undefined Thumb instruction. */
496 t_decoded, /* Instruction decoded to ARM equivalent. */
497 t_branch /* Thumb branch (already processed). */
498}
499tdstate;
500
501/*********************************************************************************
502 * Check all the possible undef or unpredict behavior, Some of them probably is
503 * out-of-updated with the newer ISA.
504 * -- Michael.Kang
505 ********************************************************************************/
506#define UNDEF_WARNING WARN_LOG(ARM11, "undefined or unpredicted behavior for arm instruction.\n");
507
508/* Macros to scrutinize instructions. */
509#define UNDEF_Test UNDEF_WARNING
510//#define UNDEF_Test
511
512//#define UNDEF_Shift UNDEF_WARNING
513#define UNDEF_Shift
514
515//#define UNDEF_MSRPC UNDEF_WARNING
516#define UNDEF_MSRPC
517
518//#define UNDEF_MRSPC UNDEF_WARNING
519#define UNDEF_MRSPC
520
521#define UNDEF_MULPCDest UNDEF_WARNING
522//#define UNDEF_MULPCDest
523
524#define UNDEF_MULDestEQOp1 UNDEF_WARNING
525//#define UNDEF_MULDestEQOp1
526
527//#define UNDEF_LSRBPC UNDEF_WARNING
528#define UNDEF_LSRBPC
529
530//#define UNDEF_LSRBaseEQOffWb UNDEF_WARNING
531#define UNDEF_LSRBaseEQOffWb
532
533//#define UNDEF_LSRBaseEQDestWb UNDEF_WARNING
534#define UNDEF_LSRBaseEQDestWb
535
536//#define UNDEF_LSRPCBaseWb UNDEF_WARNING
537#define UNDEF_LSRPCBaseWb
538
539//#define UNDEF_LSRPCOffWb UNDEF_WARNING
540#define UNDEF_LSRPCOffWb
541
542//#define UNDEF_LSMNoRegs UNDEF_WARNING
543#define UNDEF_LSMNoRegs
544
545//#define UNDEF_LSMPCBase UNDEF_WARNING
546#define UNDEF_LSMPCBase
547
548//#define UNDEF_LSMUserBankWb UNDEF_WARNING
549#define UNDEF_LSMUserBankWb
550
551//#define UNDEF_LSMBaseInListWb UNDEF_WARNING
552#define UNDEF_LSMBaseInListWb
553
554#define UNDEF_SWPPC UNDEF_WARNING
555//#define UNDEF_SWPPC
556
557#define UNDEF_CoProHS UNDEF_WARNING
558//#define UNDEF_CoProHS
559
560#define UNDEF_MCRPC UNDEF_WARNING
561//#define UNDEF_MCRPC
562
563//#define UNDEF_LSCPCBaseWb UNDEF_WARNING
564#define UNDEF_LSCPCBaseWb
565
566#define UNDEF_UndefNotBounced UNDEF_WARNING
567//#define UNDEF_UndefNotBounced
568
569#define UNDEF_ShortInt UNDEF_WARNING
570//#define UNDEF_ShortInt
571
572#define UNDEF_IllegalMode UNDEF_WARNING
573//#define UNDEF_IllegalMode
574
575#define UNDEF_Prog32SigChange UNDEF_WARNING
576//#define UNDEF_Prog32SigChange
577
578#define UNDEF_Data32SigChange UNDEF_WARNING
579//#define UNDEF_Data32SigChange
580
581/* Prototypes for exported functions. */
582extern unsigned ARMul_NthReg (ARMword, unsigned);
583extern int AddOverflow (ARMword, ARMword, ARMword);
584extern int SubOverflow (ARMword, ARMword, ARMword);
585/* Prototypes for exported functions. */
586#ifdef __cplusplus
587 extern "C" {
588#endif
589extern ARMword ARMul_Emulate26 (ARMul_State *);
590extern ARMword ARMul_Emulate32 (ARMul_State *);
591#ifdef __cplusplus
592 }
593#endif
594extern unsigned IntPending (ARMul_State *);
595extern void ARMul_CPSRAltered (ARMul_State *);
596extern void ARMul_R15Altered (ARMul_State *);
597extern ARMword ARMul_GetPC (ARMul_State *);
598extern ARMword ARMul_GetNextPC (ARMul_State *);
599extern ARMword ARMul_GetR15 (ARMul_State *);
600extern ARMword ARMul_GetCPSR (ARMul_State *);
601extern void ARMul_EnvokeEvent (ARMul_State *);
602extern unsigned int ARMul_Time (ARMul_State *);
603extern void ARMul_NegZero (ARMul_State *, ARMword);
604extern void ARMul_SetPC (ARMul_State *, ARMword);
605extern void ARMul_SetR15 (ARMul_State *, ARMword);
606extern void ARMul_SetCPSR (ARMul_State *, ARMword);
607extern ARMword ARMul_GetSPSR (ARMul_State *, ARMword);
608extern void ARMul_Abort26 (ARMul_State *, ARMword);
609extern void ARMul_Abort32 (ARMul_State *, ARMword);
610extern ARMword ARMul_MRC (ARMul_State *, ARMword);
611extern void ARMul_MRRC (ARMul_State *, ARMword, ARMword *, ARMword *);
612extern void ARMul_CDP (ARMul_State *, ARMword);
613extern void ARMul_LDC (ARMul_State *, ARMword, ARMword);
614extern void ARMul_STC (ARMul_State *, ARMword, ARMword);
615extern void ARMul_MCR (ARMul_State *, ARMword, ARMword);
616extern void ARMul_MCRR (ARMul_State *, ARMword, ARMword, ARMword);
617extern void ARMul_SetSPSR (ARMul_State *, ARMword, ARMword);
618extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
619extern ARMword ARMul_Align (ARMul_State *, ARMword, ARMword);
620extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
621extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword);
622extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword);
623extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword);
624extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword);
625extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword);
626extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *);
627extern ARMword ARMul_GetReg (ARMul_State *, unsigned, unsigned);
628extern void ARMul_SetReg (ARMul_State *, unsigned, unsigned, ARMword);
629extern void ARMul_ScheduleEvent (ARMul_State *, unsigned int,
630 unsigned (*)(ARMul_State *));
631/* Coprocessor support functions. */
632extern unsigned ARMul_CoProInit (ARMul_State *);
633extern void ARMul_CoProExit (ARMul_State *);
634extern void ARMul_CoProAttach (ARMul_State *, unsigned, ARMul_CPInits *,
635 ARMul_CPExits *, ARMul_LDCs *, ARMul_STCs *,
636 ARMul_MRCs *, ARMul_MCRs *, ARMul_MRRCs *, ARMul_MCRRs *,
637 ARMul_CDPs *, ARMul_CPReads *, ARMul_CPWrites *);
638extern void ARMul_CoProDetach (ARMul_State *, unsigned);
639extern ARMword read_cp15_reg (unsigned, unsigned, unsigned);
640
641extern unsigned DSPLDC4 (ARMul_State *, unsigned, ARMword, ARMword);
642extern unsigned DSPMCR4 (ARMul_State *, unsigned, ARMword, ARMword);
643extern unsigned DSPMRC4 (ARMul_State *, unsigned, ARMword, ARMword *);
644extern unsigned DSPSTC4 (ARMul_State *, unsigned, ARMword, ARMword *);
645extern unsigned DSPCDP4 (ARMul_State *, unsigned, ARMword);
646extern unsigned DSPMCR5 (ARMul_State *, unsigned, ARMword, ARMword);
647extern unsigned DSPMRC5 (ARMul_State *, unsigned, ARMword, ARMword *);
648extern unsigned DSPLDC5 (ARMul_State *, unsigned, ARMword, ARMword);
649extern unsigned DSPSTC5 (ARMul_State *, unsigned, ARMword, ARMword *);
650extern unsigned DSPCDP5 (ARMul_State *, unsigned, ARMword);
651extern unsigned DSPMCR6 (ARMul_State *, unsigned, ARMword, ARMword);
652extern unsigned DSPMRC6 (ARMul_State *, unsigned, ARMword, ARMword *);
653extern unsigned DSPCDP6 (ARMul_State *, unsigned, ARMword);
654
655
656#endif
diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp
index 6fbab3bfb..03bca2870 100644
--- a/src/core/arm/interpreter/arminit.cpp
+++ b/src/core/arm/interpreter/arminit.cpp
@@ -17,8 +17,8 @@
17 17
18//#include <unistd.h> 18//#include <unistd.h>
19 19
20#include "core/arm/interpreter/armdefs.h" 20#include "core/arm/skyeye_common/armdefs.h"
21#include "core/arm/interpreter/armemu.h" 21#include "core/arm/skyeye_common/armemu.h"
22 22
23/***************************************************************************\ 23/***************************************************************************\
24* Definitions for the emulator architecture * 24* Definitions for the emulator architecture *
diff --git a/src/core/arm/interpreter/armmmu.cpp b/src/core/arm/interpreter/armmmu.cpp
index 242e6a83c..98fc17ddb 100644
--- a/src/core/arm/interpreter/armmmu.cpp
+++ b/src/core/arm/interpreter/armmmu.cpp
@@ -20,10 +20,10 @@
20 20
21#include <assert.h> 21#include <assert.h>
22#include <string.h> 22#include <string.h>
23#include "armdefs.h" 23#include "core/arm/skyeye_common/armdefs.h"
24/* two header for arm disassemble */ 24/* two header for arm disassemble */
25//#include "skyeye_arch.h" 25//#include "skyeye_arch.h"
26#include "armcpu.h" 26#include "core/arm/skyeye_common/armcpu.h"
27 27
28 28
29extern mmu_ops_t xscale_mmu_ops; 29extern mmu_ops_t xscale_mmu_ops;
diff --git a/src/core/arm/interpreter/armmmu.h b/src/core/arm/interpreter/armmmu.h
deleted file mode 100644
index 818108c9c..000000000
--- a/src/core/arm/interpreter/armmmu.h
+++ /dev/null
@@ -1,254 +0,0 @@
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#ifndef _ARMMMU_H_
22#define _ARMMMU_H_
23
24
25#define WORD_SHT 2
26#define WORD_SIZE (1<<WORD_SHT)
27/* The MMU is accessible with MCR and MRC operations to copro 15: */
28
29#define MMU_COPRO (15)
30
31/* Register numbers in the MMU: */
32
33typedef enum mmu_regnum_t
34{
35 MMU_ID = 0,
36 MMU_CONTROL = 1,
37 MMU_TRANSLATION_TABLE_BASE = 2,
38 MMU_DOMAIN_ACCESS_CONTROL = 3,
39 MMU_FAULT_STATUS = 5,
40 MMU_FAULT_ADDRESS = 6,
41 MMU_CACHE_OPS = 7,
42 MMU_TLB_OPS = 8,
43 MMU_CACHE_LOCKDOWN = 9,
44 MMU_TLB_LOCKDOWN = 10,
45 MMU_PID = 13,
46
47 /*MMU_V4 */
48 MMU_V4_CACHE_OPS = 7,
49 MMU_V4_TLB_OPS = 8,
50
51 /*MMU_V3 */
52 MMU_V3_FLUSH_TLB = 5,
53 MMU_V3_FLUSH_TLB_ENTRY = 6,
54 MMU_V3_FLUSH_CACHE = 7,
55
56 /*MMU Intel SA-1100 */
57 MMU_SA_RB_OPS = 9,
58 MMU_SA_DEBUG = 14,
59 MMU_SA_CP15_R15 = 15,
60 //chy 2003-08-24
61 /*Intel xscale CP15 */
62 XSCALE_CP15_CACHE_TYPE = 0,
63 XSCALE_CP15_AUX_CONTROL = 1,
64 XSCALE_CP15_COPRO_ACCESS = 15,
65
66} mmu_regnum_t;
67
68/* Bits in the control register */
69
70#define CONTROL_MMU (1<<0)
71#define CONTROL_ALIGN_FAULT (1<<1)
72#define CONTROL_CACHE (1<<2)
73#define CONTROL_DATA_CACHE (1<<2)
74#define CONTROL_WRITE_BUFFER (1<<3)
75#define CONTROL_BIG_ENDIAN (1<<7)
76#define CONTROL_SYSTEM (1<<8)
77#define CONTROL_ROM (1<<9)
78#define CONTROL_UNDEFINED (1<<10)
79#define CONTROL_BRANCH_PREDICT (1<<11)
80#define CONTROL_INSTRUCTION_CACHE (1<<12)
81#define CONTROL_VECTOR (1<<13)
82#define CONTROL_RR (1<<14)
83#define CONTROL_L4 (1<<15)
84#define CONTROL_XP (1<<23)
85#define CONTROL_EE (1<<25)
86
87/*Macro defines for MMU state*/
88#define MMU_CTL (state->mmu.control)
89#define MMU_Enabled (state->mmu.control & CONTROL_MMU)
90#define MMU_Disabled (!(MMU_Enabled))
91#define MMU_Aligned (state->mmu.control & CONTROL_ALIGN_FAULT)
92
93#define MMU_ICacheEnabled (MMU_CTL & CONTROL_INSTRUCTION_CACHE)
94#define MMU_ICacheDisabled (!(MMU_ICacheDisabled))
95
96#define MMU_DCacheEnabled (MMU_CTL & CONTROL_DATA_CACHE)
97#define MMU_DCacheDisabled (!(MMU_DCacheEnabled))
98
99#define MMU_CacheEnabled (MMU_CTL & CONTROL_CACHE)
100#define MMU_CacheDisabled (!(MMU_CacheEnabled))
101
102#define MMU_WBEnabled (MMU_CTL & CONTROL_WRITE_BUFFER)
103#define MMU_WBDisabled (!(MMU_WBEnabled))
104
105/*virt_addr exchange according to CP15.R13(process id virtul mapping)*/
106#define PID_VA_MAP_MASK 0xfe000000
107//#define mmu_pid_va_map(va) ({\
108// ARMword ret; \
109// if ((va) & PID_VA_MAP_MASK)\
110// ret = (va); \
111// else \
112// ret = ((va) | (state->mmu.process_id & PID_VA_MAP_MASK));\
113// ret;\
114//})
115#define mmu_pid_va_map(va) ((va) & PID_VA_MAP_MASK) ? (va) : ((va) | (state->mmu.process_id & PID_VA_MAP_MASK))
116
117/* FS[3:0] in the fault status register: */
118
119typedef enum fault_t
120{
121 NO_FAULT = 0x0,
122 ALIGNMENT_FAULT = 0x1,
123
124 SECTION_TRANSLATION_FAULT = 0x5,
125 PAGE_TRANSLATION_FAULT = 0x7,
126 SECTION_DOMAIN_FAULT = 0x9,
127 PAGE_DOMAIN_FAULT = 0xB,
128 SECTION_PERMISSION_FAULT = 0xD,
129 SUBPAGE_PERMISSION_FAULT = 0xF,
130
131 /* defined by skyeye */
132 TLB_READ_MISS = 0x30,
133 TLB_WRITE_MISS = 0x40,
134
135} fault_t;
136
137typedef struct mmu_ops_s
138{
139 /*initilization */
140 int (*init) (ARMul_State * state);
141 /*free on exit */
142 void (*exit) (ARMul_State * state);
143 /*read byte data */
144 fault_t (*read_byte) (ARMul_State * state, ARMword va,
145 ARMword * data);
146 /*write byte data */
147 fault_t (*write_byte) (ARMul_State * state, ARMword va,
148 ARMword data);
149 /*read halfword data */
150 fault_t (*read_halfword) (ARMul_State * state, ARMword va,
151 ARMword * data);
152 /*write halfword data */
153 fault_t (*write_halfword) (ARMul_State * state, ARMword va,
154 ARMword data);
155 /*read word data */
156 fault_t (*read_word) (ARMul_State * state, ARMword va,
157 ARMword * data);
158 /*write word data */
159 fault_t (*write_word) (ARMul_State * state, ARMword va,
160 ARMword data);
161 /*load instr */
162 fault_t (*load_instr) (ARMul_State * state, ARMword va,
163 ARMword * instr);
164 /*mcr */
165 ARMword (*mcr) (ARMul_State * state, ARMword instr, ARMword val);
166 /*mrc */
167 ARMword (*mrc) (ARMul_State * state, ARMword instr, ARMword * val);
168
169 /*ywc 2005-04-16 convert virtual address to physics address */
170 int (*v2p_dbct) (ARMul_State * state, ARMword virt_addr,
171 ARMword * phys_addr);
172} mmu_ops_t;
173
174
175#include "core/arm/interpreter/mmu/tlb.h"
176#include "core/arm/interpreter/mmu/rb.h"
177#include "core/arm/interpreter/mmu/wb.h"
178#include "core/arm/interpreter/mmu/cache.h"
179
180/*special process mmu.h*/
181#include "core/arm/interpreter/mmu/sa_mmu.h"
182//#include "core/arm/interpreter/mmu/arm7100_mmu.h"
183//#include "core/arm/interpreter/mmu/arm920t_mmu.h"
184//#include "core/arm/interpreter/mmu/arm926ejs_mmu.h"
185#include "core/arm/interpreter/mmu/arm1176jzf_s_mmu.h"
186//#include "core/arm/interpreter/mmu/cortex_a9_mmu.h"
187
188typedef struct mmu_state_t
189{
190 ARMword control;
191 ARMword translation_table_base;
192/* dyf 201-08-11 for arm1176 */
193 ARMword auxiliary_control;
194 ARMword coprocessor_access_control;
195 ARMword translation_table_base0;
196 ARMword translation_table_base1;
197 ARMword translation_table_ctrl;
198/* arm1176 end */
199
200 ARMword domain_access_control;
201 ARMword fault_status;
202 ARMword fault_statusi; /* prefetch fault status */
203 ARMword fault_address;
204 ARMword last_domain;
205 ARMword process_id;
206 ARMword context_id;
207 ARMword thread_uro_id;
208 ARMword cache_locked_down;
209 ARMword tlb_locked_down;
210//chy 2003-08-24 for xscale
211 ARMword cache_type; // 0
212 ARMword aux_control; // 1
213 ARMword copro_access; // 15
214
215 mmu_ops_t ops;
216 union
217 {
218 sa_mmu_t sa_mmu;
219 //arm7100_mmu_t arm7100_mmu;
220 //arm920t_mmu_t arm920t_mmu;
221 //arm926ejs_mmu_t arm926ejs_mmu;
222 } u;
223} mmu_state_t;
224
225int mmu_init (ARMul_State * state);
226int mmu_reset (ARMul_State * state);
227void mmu_exit (ARMul_State * state);
228
229fault_t mmu_read_word (ARMul_State * state, ARMword virt_addr,
230 ARMword * data);
231fault_t mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data);
232fault_t mmu_load_instr (ARMul_State * state, ARMword virt_addr,
233 ARMword * instr);
234
235ARMword mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value);
236void mmu_mcr (ARMul_State * state, ARMword instr, ARMword value);
237
238/*ywc 20050416*/
239int mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr,
240 ARMword * phys_addr);
241
242fault_t
243mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data);
244fault_t
245mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data);
246fault_t
247mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data);
248fault_t
249mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data);
250fault_t
251mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data);
252fault_t
253mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data);
254#endif /* _ARMMMU_H_ */
diff --git a/src/core/arm/interpreter/armos.cpp b/src/core/arm/interpreter/armos.cpp
index 43484ee5f..90eb20acc 100644
--- a/src/core/arm/interpreter/armos.cpp
+++ b/src/core/arm/interpreter/armos.cpp
@@ -28,7 +28,7 @@ fun, and definign VAILDATE will define SWI 1 to enter SVC mode, and SWI
28#include <time.h> 28#include <time.h>
29#include <errno.h> 29#include <errno.h>
30#include <string.h> 30#include <string.h>
31#include "skyeye_defs.h" 31#include "core/arm/skyeye_common/skyeye_defs.h"
32#ifndef __USE_LARGEFILE64 32#ifndef __USE_LARGEFILE64
33#define __USE_LARGEFILE64 /* When use 64 bit large file need define it! for stat64*/ 33#define __USE_LARGEFILE64 /* When use 64 bit large file need define it! for stat64*/
34#endif 34#endif
@@ -74,9 +74,9 @@ extern int _fisatty (FILE *);
74#endif 74#endif
75#endif 75#endif
76 76
77#include "armdefs.h" 77#include "core/arm/skyeye_common/armdefs.h"
78#include "armos.h" 78#include "core/arm/skyeye_common/armos.h"
79#include "armemu.h" 79#include "core/arm/skyeye_common/armemu.h"
80 80
81#ifndef NOOS 81#ifndef NOOS
82#ifndef VALIDATE 82#ifndef VALIDATE
diff --git a/src/core/arm/interpreter/armos.h b/src/core/arm/interpreter/armos.h
deleted file mode 100644
index 4b58801ad..000000000
--- a/src/core/arm/interpreter/armos.h
+++ /dev/null
@@ -1,138 +0,0 @@
1/* armos.h -- ARMulator OS definitions: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18//#include "bank_defs.h"
19//#include "dyncom/defines.h"
20
21//typedef struct mmap_area{
22// mem_bank_t bank;
23// void *mmap_addr;
24// struct mmap_area *next;
25//}mmap_area_t;
26
27#if FAST_MEMORY
28/* in user mode, mmap_base will be on initial brk,
29 set at the first mmap request */
30#define mmap_base -1
31#else
32#define mmap_base 0x50000000
33#endif
34static long mmap_next_base = mmap_base;
35
36//static mmap_area_t* new_mmap_area(int sim_addr, int len);
37static char mmap_mem_write(short size, int addr, uint32_t value);
38static char mmap_mem_read(short size, int addr, uint32_t * value);
39
40/***************************************************************************\
41* SWI numbers *
42\***************************************************************************/
43
44#define SWI_Syscall 0x0
45#define SWI_Exit 0x1
46#define SWI_Read 0x3
47#define SWI_Write 0x4
48#define SWI_Open 0x5
49#define SWI_Close 0x6
50#define SWI_Seek 0x13
51#define SWI_Rename 0x26
52#define SWI_Break 0x11
53
54#define SWI_Times 0x2b
55#define SWI_Brk 0x2d
56
57#define SWI_Mmap 0x5a
58#define SWI_Munmap 0x5b
59#define SWI_Mmap2 0xc0
60
61#define SWI_GetUID32 0xc7
62#define SWI_GetGID32 0xc8
63#define SWI_GetEUID32 0xc9
64#define SWI_GetEGID32 0xca
65
66#define SWI_ExitGroup 0xf8
67
68#if 0
69#define SWI_Time 0xd
70#define SWI_Clock 0x61
71#define SWI_Time 0x63
72#define SWI_Remove 0x64
73#define SWI_Rename 0x65
74#define SWI_Flen 0x6c
75#endif
76
77#define SWI_Uname 0x7a
78#define SWI_Fcntl 0xdd
79#define SWI_Fstat64 0xc5
80#define SWI_Gettimeofday 0x4e
81#define SWI_Set_tls 0xf0005
82
83#define SWI_Breakpoint 0x180000 /* see gdb's tm-arm.h */
84
85/***************************************************************************\
86* SWI structures *
87\***************************************************************************/
88
89/* Arm binaries (for now) only support 32 bit, and expect to receive
90 32-bit compliant structure in return of a systen call. Because
91 we use host system calls to emulate system calls, the returned
92 structure can be 32-bit compliant or 64-bit compliant, depending
93 on the OS running skyeye. Therefore, we need a fixed size structure
94 adapted to arm.*/
95
96/* Borrowed from qemu */
97struct target_stat64 {
98 unsigned short st_dev;
99 unsigned char __pad0[10];
100 uint32_t __st_ino;
101 unsigned int st_mode;
102 unsigned int st_nlink;
103 uint32_t st_uid;
104 uint32_t st_gid;
105 unsigned short st_rdev;
106 unsigned char __pad3[10];
107 unsigned char __pad31[4];
108 long long st_size;
109 uint32_t st_blksize;
110 unsigned char __pad32[4];
111 uint32_t st_blocks;
112 uint32_t __pad4;
113 uint32_t st32_atime;
114 uint32_t __pad5;
115 uint32_t st32_mtime;
116 uint32_t __pad6;
117 uint32_t st32_ctime;
118 uint32_t __pad7;
119 unsigned long long st_ino;
120};// __attribute__((packed));
121
122struct target_tms32 {
123 uint32_t tms_utime;
124 uint32_t tms_stime;
125 uint32_t tms_cutime;
126 uint32_t tms_cstime;
127};
128
129struct target_timeval32 {
130 uint32_t tv_sec; /* seconds */
131 uint32_t tv_usec; /* microseconds */
132};
133
134struct target_timezone32 {
135 int32_t tz_minuteswest; /* minutes west of Greenwich */
136 int32_t tz_dsttime; /* type of DST correction */
137};
138
diff --git a/src/core/arm/interpreter/armvirt.cpp b/src/core/arm/interpreter/armvirt.cpp
index a072b73be..eb3c86cb4 100644
--- a/src/core/arm/interpreter/armvirt.cpp
+++ b/src/core/arm/interpreter/armvirt.cpp
@@ -23,8 +23,8 @@ table. The routines PutWord and GetWord implement this. Pages are never
23freed as they might be needed again. A single area of memory may be 23freed as they might be needed again. A single area of memory may be
24defined to generate aborts. */ 24defined to generate aborts. */
25 25
26#include "armdefs.h" 26#include "core/arm/skyeye_common/armdefs.h"
27#include "skyeye_defs.h" 27#include "core/arm/skyeye_common/skyeye_defs.h"
28//#include "code_cov.h" 28//#include "code_cov.h"
29 29
30#ifdef VALIDATE /* for running the validate suite */ 30#ifdef VALIDATE /* for running the validate suite */
diff --git a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
index a32f076b9..07951e0e6 100644
--- a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
+++ b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
@@ -24,9 +24,9 @@
24 24
25#include "core/mem_map.h" 25#include "core/mem_map.h"
26 26
27#include "core/arm/interpreter/skyeye_defs.h" 27#include "core/arm/skyeye_common/skyeye_defs.h"
28 28
29#include "core/arm/interpreter/armdefs.h" 29#include "core/arm/skyeye_common/armdefs.h"
30//#include "bank_defs.h" 30//#include "bank_defs.h"
31#if 0 31#if 0
32#define TLB_SIZE 1024 * 1024 32#define TLB_SIZE 1024 * 1024
diff --git a/src/core/arm/interpreter/mmu/cache.cpp b/src/core/arm/interpreter/mmu/cache.cpp
index f3c4e0531..cfbc31f1e 100644
--- a/src/core/arm/interpreter/mmu/cache.cpp
+++ b/src/core/arm/interpreter/mmu/cache.cpp
@@ -1,4 +1,4 @@
1#include "core/arm/interpreter/armdefs.h" 1#include "core/arm/skyeye_common/armdefs.h"
2 2
3/* mmu cache init 3/* mmu cache init
4 * 4 *
diff --git a/src/core/arm/interpreter/mmu/maverick.cpp b/src/core/arm/interpreter/mmu/maverick.cpp
index adcc2efb5..a07d4742b 100644
--- a/src/core/arm/interpreter/mmu/maverick.cpp
+++ b/src/core/arm/interpreter/mmu/maverick.cpp
@@ -18,8 +18,8 @@
18 18
19#include <assert.h> 19#include <assert.h>
20 20
21#include "core/arm/interpreter/armdefs.h" 21#include "core/arm/skyeye_common/armdefs.h"
22#include "core/arm/interpreter/armemu.h" 22#include "core/arm/skyeye_common/armemu.h"
23 23
24 24
25/*#define CIRRUS_DEBUG 1 */ 25/*#define CIRRUS_DEBUG 1 */
diff --git a/src/core/arm/interpreter/mmu/rb.cpp b/src/core/arm/interpreter/mmu/rb.cpp
index 07b11e311..600c9d8c8 100644
--- a/src/core/arm/interpreter/mmu/rb.cpp
+++ b/src/core/arm/interpreter/mmu/rb.cpp
@@ -1,4 +1,4 @@
1#include "core/arm/interpreter/armdefs.h" 1#include "core/arm/skyeye_common/armdefs.h"
2 2
3/*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu*/ 3/*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu*/
4ARMword rb_masks[] = { 4ARMword rb_masks[] = {
diff --git a/src/core/arm/interpreter/mmu/sa_mmu.cpp b/src/core/arm/interpreter/mmu/sa_mmu.cpp
index eff5002de..27f9ec8e0 100644
--- a/src/core/arm/interpreter/mmu/sa_mmu.cpp
+++ b/src/core/arm/interpreter/mmu/sa_mmu.cpp
@@ -21,7 +21,7 @@
21#include <assert.h> 21#include <assert.h>
22#include <string.h> 22#include <string.h>
23 23
24#include "core/arm/interpreter/armdefs.h" 24#include "core/arm/skyeye_common/armdefs.h"
25 25
26/** 26/**
27 * The interface of read data from bus 27 * The interface of read data from bus
diff --git a/src/core/arm/interpreter/mmu/tlb.cpp b/src/core/arm/interpreter/mmu/tlb.cpp
index ca60ac1a1..88c2a8bc5 100644
--- a/src/core/arm/interpreter/mmu/tlb.cpp
+++ b/src/core/arm/interpreter/mmu/tlb.cpp
@@ -1,6 +1,6 @@
1#include <assert.h> 1#include <assert.h>
2 2
3#include "core/arm/interpreter/armdefs.h" 3#include "core/arm/skyeye_common/armdefs.h"
4 4
5ARMword tlb_masks[] = { 5ARMword tlb_masks[] = {
6 0x00000000, /* TLB_INVALID */ 6 0x00000000, /* TLB_INVALID */
diff --git a/src/core/arm/interpreter/mmu/wb.cpp b/src/core/arm/interpreter/mmu/wb.cpp
index 82c0cec02..5ddda41ee 100644
--- a/src/core/arm/interpreter/mmu/wb.cpp
+++ b/src/core/arm/interpreter/mmu/wb.cpp
@@ -1,4 +1,4 @@
1#include "core/arm/interpreter/armdefs.h" 1#include "core/arm/skyeye_common/armdefs.h"
2 2
3/* wb_init 3/* wb_init
4 * @wb_t :wb_t to init 4 * @wb_t :wb_t to init
diff --git a/src/core/arm/interpreter/mmu/xscale_copro.cpp b/src/core/arm/interpreter/mmu/xscale_copro.cpp
index 433ce8e02..cf91fd933 100644
--- a/src/core/arm/interpreter/mmu/xscale_copro.cpp
+++ b/src/core/arm/interpreter/mmu/xscale_copro.cpp
@@ -21,8 +21,8 @@
21#include <assert.h> 21#include <assert.h>
22#include <string.h> 22#include <string.h>
23 23
24#include "core/arm/interpreter/armdefs.h" 24#include "core/arm/skyeye_common/armdefs.h"
25#include "core/arm/interpreter/armemu.h" 25#include "core/arm/skyeye_common/armemu.h"
26 26
27/*#include "pxa.h" */ 27/*#include "pxa.h" */
28 28
diff --git a/src/core/arm/interpreter/skyeye_defs.h b/src/core/arm/interpreter/skyeye_defs.h
deleted file mode 100644
index b6713ebad..000000000
--- a/src/core/arm/interpreter/skyeye_defs.h
+++ /dev/null
@@ -1,111 +0,0 @@
1#ifndef CORE_ARM_SKYEYE_DEFS_H_
2#define CORE_ARM_SKYEYE_DEFS_H_
3
4#include "common/common.h"
5
6#define MODE32
7#define MODET
8
9typedef struct
10{
11 const char *cpu_arch_name; /*cpu architecture version name.e.g. armv4t */
12 const char *cpu_name; /*cpu name. e.g. arm7tdmi or arm720t */
13 u32 cpu_val; /*CPU value; also call MMU ID or processor id;see
14 ARM Architecture Reference Manual B2-6 */
15 u32 cpu_mask; /*cpu_val's mask. */
16 u32 cachetype; /*this cpu has what kind of cache */
17} cpu_config_t;
18
19typedef struct conf_object_s{
20 char* objname;
21 void* obj;
22 char* class_name;
23}conf_object_t;
24
25typedef enum{
26 /* No exception */
27 No_exp = 0,
28 /* Memory allocation exception */
29 Malloc_exp,
30 /* File open exception */
31 File_open_exp,
32 /* DLL open exception */
33 Dll_open_exp,
34 /* Invalid argument exception */
35 Invarg_exp,
36 /* Invalid module exception */
37 Invmod_exp,
38 /* wrong format exception for config file parsing */
39 Conf_format_exp,
40 /* some reference excess the predefiend range. Such as the index out of array range */
41 Excess_range_exp,
42 /* Can not find the desirable result */
43 Not_found_exp,
44
45 /* Unknown exception */
46 Unknown_exp
47}exception_t;
48
49typedef enum {
50 Align = 0,
51 UnAlign
52}align_t;
53
54typedef enum {
55 Little_endian = 0,
56 Big_endian
57}endian_t;
58//typedef int exception_t;
59
60typedef enum{
61 Phys_addr = 0,
62 Virt_addr
63}addr_type_t;
64
65typedef exception_t(*read_byte_t)(conf_object_t* target, u32 addr, void *buf, size_t count);
66typedef exception_t(*write_byte_t)(conf_object_t* target, u32 addr, const void *buf, size_t count);
67
68typedef struct memory_space{
69 conf_object_t* conf_obj;
70 read_byte_t read;
71 write_byte_t write;
72}memory_space_intf;
73
74
75/*
76 * a running instance for a specific archteciture.
77 */
78typedef struct generic_arch_s
79{
80 char* arch_name;
81 void (*init) (void);
82 void (*reset) (void);
83 void (*step_once) (void);
84 void (*set_pc)(u32 addr);
85 u32 (*get_pc)(void);
86 u32 (*get_step)(void);
87 //chy 2004-04-15
88 //int (*ICE_write_byte) (u32 addr, uint8_t v);
89 //int (*ICE_read_byte)(u32 addr, uint8_t *pv);
90 u32 (*get_regval_by_id)(int id);
91 u32 (*get_regnum)(void);
92 char* (*get_regname_by_id)(int id);
93 exception_t (*set_regval_by_id)(int id, u32 value);
94 /*
95 * read a data by virtual address.
96 */
97 exception_t (*mmu_read)(short size, u32 addr, u32 * value);
98 /*
99 * write a data by a virtual address.
100 */
101 exception_t (*mmu_write)(short size, u32 addr, u32 value);
102 /**
103 * get a signal from external
104 */
105 //exception_t (*signal)(interrupt_signal_t* signal);
106
107 endian_t endianess;
108 align_t alignment;
109} generic_arch_t;
110
111#endif \ No newline at end of file
diff --git a/src/core/arm/interpreter/thumbemu.cpp b/src/core/arm/interpreter/thumbemu.cpp
index 032d84b65..f7f11f714 100644
--- a/src/core/arm/interpreter/thumbemu.cpp
+++ b/src/core/arm/interpreter/thumbemu.cpp
@@ -19,7 +19,7 @@
19instruction into its corresponding ARM instruction, and using the 19instruction into its corresponding ARM instruction, and using the
20existing ARM simulator. */ 20existing ARM simulator. */
21 21
22#include "skyeye_defs.h" 22#include "core/arm/skyeye_common/skyeye_defs.h"
23 23
24#ifndef MODET /* required for the Thumb instruction support */ 24#ifndef MODET /* required for the Thumb instruction support */
25#if 1 25#if 1
@@ -29,9 +29,9 @@ existing ARM simulator. */
29#endif 29#endif
30#endif 30#endif
31 31
32#include "armdefs.h" 32#include "core/arm/skyeye_common/armdefs.h"
33#include "armemu.h" 33#include "core/arm/skyeye_common/armemu.h"
34#include "armos.h" 34#include "core/arm/skyeye_common/armos.h"
35 35
36 36
37/* Decode a 16bit Thumb instruction. The instruction is in the low 37/* Decode a 16bit Thumb instruction. The instruction is in the low
diff --git a/src/core/arm/interpreter/vfp/asm_vfp.h b/src/core/arm/interpreter/vfp/asm_vfp.h
deleted file mode 100644
index f4ab34fd4..000000000
--- a/src/core/arm/interpreter/vfp/asm_vfp.h
+++ /dev/null
@@ -1,84 +0,0 @@
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
deleted file mode 100644
index eea5e24a9..000000000
--- a/src/core/arm/interpreter/vfp/vfp.cpp
+++ /dev/null
@@ -1,357 +0,0 @@
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
deleted file mode 100644
index bbf4caeb0..000000000
--- a/src/core/arm/interpreter/vfp/vfp.h
+++ /dev/null
@@ -1,111 +0,0 @@
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
deleted file mode 100644
index b222e79f1..000000000
--- a/src/core/arm/interpreter/vfp/vfp_helper.h
+++ /dev/null
@@ -1,541 +0,0 @@
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 vfp_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 u32 vfp_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
deleted file mode 100644
index 5ae99b88a..000000000
--- a/src/core/arm/interpreter/vfp/vfpdouble.cpp
+++ /dev/null
@@ -1,1263 +0,0 @@
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 - vfp_fls(vd->significand >> 32);
73 if (bits == 31)
74 bits = 63 - vfp_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 - vfp_fls(significand >> 32);
112 if (shift == 32)
113 shift = 64 - vfp_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, const 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
deleted file mode 100644
index a57047911..000000000
--- a/src/core/arm/interpreter/vfp/vfpinstr.cpp
+++ /dev/null
@@ -1,5123 +0,0 @@
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
deleted file mode 100644
index 0fcc85266..000000000
--- a/src/core/arm/interpreter/vfp/vfpsingle.cpp
+++ /dev/null
@@ -1,1278 +0,0 @@
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 - vfp_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 - vfp_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, const 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}