summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Doxyfile2369
-rw-r--r--doc-icon.pngbin0 -> 8791 bytes
-rw-r--r--src/citra/citra.cpp2
-rw-r--r--src/citra/config.cpp5
-rw-r--r--src/citra/config.h1
-rw-r--r--src/citra/default_ini.h3
-rw-r--r--src/citra/emu_window/emu_window_glfw.cpp5
-rw-r--r--src/citra/emu_window/emu_window_glfw.h11
-rw-r--r--src/citra_qt/bootmanager.cpp4
-rw-r--r--src/citra_qt/bootmanager.hxx16
-rw-r--r--src/citra_qt/config.cpp14
-rw-r--r--src/citra_qt/config.h3
-rw-r--r--src/citra_qt/debugger/disassembler.cpp2
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.hxx2
-rw-r--r--src/citra_qt/main.hxx2
-rw-r--r--src/common/bit_field.h2
-rw-r--r--src/common/common_types.h43
-rw-r--r--src/common/console_listener.h2
-rw-r--r--src/common/emu_window.h12
-rw-r--r--src/common/file_util.cpp7
-rw-r--r--src/common/log_manager.h4
-rw-r--r--src/common/string_util.cpp11
-rw-r--r--src/common/string_util.h1
-rw-r--r--src/common/swap.h1
-rw-r--r--src/common/timer.cpp7
-rw-r--r--src/core/CMakeLists.txt57
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp163
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h90
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp402
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.h155
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp6563
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.h7
-rw-r--r--src/core/arm/dyncom/arm_dyncom_run.cpp120
-rw-r--r--src/core/arm/dyncom/arm_dyncom_run.h55
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp521
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.h51
-rw-r--r--src/core/arm/interpreter/arm_interpreter.cpp5
-rw-r--r--src/core/arm/interpreter/arm_interpreter.h28
-rw-r--r--src/core/arm/interpreter/armcopro.cpp1007
-rw-r--r--src/core/arm/interpreter/armemu.cpp9
-rw-r--r--src/core/arm/interpreter/arminit.cpp4
-rw-r--r--src/core/arm/interpreter/armmmu.cpp238
-rw-r--r--src/core/arm/interpreter/armos.cpp742
-rw-r--r--src/core/arm/interpreter/armsupp.cpp15
-rw-r--r--src/core/arm/interpreter/armvirt.cpp685
-rw-r--r--src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp1132
-rw-r--r--src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h37
-rw-r--r--src/core/arm/interpreter/mmu/cache.cpp370
-rw-r--r--src/core/arm/interpreter/mmu/cache.h168
-rw-r--r--src/core/arm/interpreter/mmu/maverick.cpp1206
-rw-r--r--src/core/arm/interpreter/mmu/rb.cpp126
-rw-r--r--src/core/arm/interpreter/mmu/rb.h55
-rw-r--r--src/core/arm/interpreter/mmu/sa_mmu.cpp864
-rw-r--r--src/core/arm/interpreter/mmu/sa_mmu.h58
-rw-r--r--src/core/arm/interpreter/mmu/tlb.cpp307
-rw-r--r--src/core/arm/interpreter/mmu/tlb.h87
-rw-r--r--src/core/arm/interpreter/mmu/wb.cpp149
-rw-r--r--src/core/arm/interpreter/mmu/wb.h63
-rw-r--r--src/core/arm/interpreter/mmu/xscale_copro.cpp1391
-rw-r--r--src/core/arm/interpreter/thumbemu.cpp8
-rw-r--r--src/core/arm/skyeye_common/arm_regformat.h (renamed from src/core/arm/interpreter/arm_regformat.h)4
-rw-r--r--src/core/arm/skyeye_common/armcpu.h (renamed from src/core/arm/interpreter/armcpu.h)5
-rw-r--r--src/core/arm/skyeye_common/armdefs.h (renamed from src/core/arm/interpreter/armdefs.h)5
-rw-r--r--src/core/arm/skyeye_common/armemu.h (renamed from src/core/arm/interpreter/armemu.h)2
-rw-r--r--src/core/arm/skyeye_common/armmmu.h (renamed from src/core/arm/interpreter/armmmu.h)117
-rw-r--r--src/core/arm/skyeye_common/armos.h (renamed from src/core/arm/interpreter/armos.h)9
-rw-r--r--src/core/arm/skyeye_common/skyeye_defs.h (renamed from src/core/arm/interpreter/skyeye_defs.h)4
-rw-r--r--src/core/arm/skyeye_common/skyeye_types.h55
-rw-r--r--src/core/arm/skyeye_common/vfp/asm_vfp.h (renamed from src/core/arm/interpreter/vfp/asm_vfp.h)0
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp (renamed from src/core/arm/interpreter/vfp/vfp.cpp)32
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h (renamed from src/core/arm/interpreter/vfp/vfp.h)2
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h (renamed from src/core/arm/interpreter/vfp/vfp_helper.h)10
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp (renamed from src/core/arm/interpreter/vfp/vfpdouble.cpp)6
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp (renamed from src/core/arm/interpreter/vfp/vfpinstr.cpp)48
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp (renamed from src/core/arm/interpreter/vfp/vfpsingle.cpp)6
-rw-r--r--src/core/core.h2
-rw-r--r--src/core/file_sys/archive_sdmc.cpp10
-rw-r--r--src/core/hle/coprocessor.h20
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp8
-rw-r--r--src/core/hle/kernel/archive.cpp30
-rw-r--r--src/core/hle/kernel/event.cpp8
-rw-r--r--src/core/hle/kernel/mutex.cpp10
-rw-r--r--src/core/hle/kernel/shared_memory.cpp6
-rw-r--r--src/core/hle/kernel/thread.cpp8
-rw-r--r--src/core/hle/service/apt.h2
-rw-r--r--src/core/hle/service/fs.cpp15
-rw-r--r--src/core/hle/service/fs.h2
-rw-r--r--src/core/hle/service/gsp.h2
-rw-r--r--src/core/hle/service/hid.h2
-rw-r--r--src/core/hle/service/ndm.h2
-rw-r--r--src/core/hle/service/service.h10
-rw-r--r--src/core/hle/service/srv.h2
-rw-r--r--src/core/settings.h2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.cpp15
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h8
96 files changed, 11152 insertions, 8785 deletions
diff --git a/.gitignore b/.gitignore
index cc8abe9ff..659736ff5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
1# Build directory 1# Build directory
2build/ 2build/
3doc-build/
3 4
4# Generated source files 5# Generated source files
5src/common/scm_rev.cpp 6src/common/scm_rev.cpp
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 000000000..981121d92
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,2369 @@
1# Doxyfile 1.8.8
2
3# This file describes the settings to be used by the documentation system
4# doxygen (www.doxygen.org) for a project.
5#
6# All text after a double hash (##) is considered a comment and is placed in
7# front of the TAG it is preceding.
8#
9# All text after a single hash (#) is considered a comment and will be ignored.
10# The format is:
11# TAG = value [value, ...]
12# For lists, items can also be appended using:
13# TAG += value [value, ...]
14# Values that contain spaces should be placed between quotes (\" \").
15
16#---------------------------------------------------------------------------
17# Project related configuration options
18#---------------------------------------------------------------------------
19
20# This tag specifies the encoding used for all characters in the config file
21# that follow. The default is UTF-8 which is also the encoding used for all text
22# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
23# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
24# for the list of possible encodings.
25# The default value is: UTF-8.
26
27DOXYFILE_ENCODING = UTF-8
28
29# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
30# double-quotes, unless you are using Doxywizard) that should identify the
31# project for which the documentation is generated. This name is used in the
32# title of most generated pages and in a few other places.
33# The default value is: My Project.
34
35PROJECT_NAME = Citra
36
37# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
38# could be handy for archiving the generated documentation or if some version
39# control system is used.
40
41PROJECT_NUMBER =
42
43# Using the PROJECT_BRIEF tag one can provide an optional one line description
44# for a project that appears at the top of each page and should give viewer a
45# quick idea about the purpose of the project. Keep the description short.
46
47PROJECT_BRIEF = "Nintendo 3DS emulator/debugger"
48
49# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
50# the documentation. The maximum height of the logo should not exceed 55 pixels
51# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
52# to the output directory.
53
54PROJECT_LOGO = doc-icon.png
55
56# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
57# into which the generated documentation will be written. If a relative path is
58# entered, it will be relative to the location where doxygen was started. If
59# left blank the current directory will be used.
60
61OUTPUT_DIRECTORY = doc-build/
62
63# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
64# directories (in 2 levels) under the output directory of each output format and
65# will distribute the generated files over these directories. Enabling this
66# option can be useful when feeding doxygen a huge amount of source files, where
67# putting all generated files in the same directory would otherwise causes
68# performance problems for the file system.
69# The default value is: NO.
70
71CREATE_SUBDIRS = NO
72
73# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
74# characters to appear in the names of generated files. If set to NO, non-ASCII
75# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
76# U+3044.
77# The default value is: NO.
78
79ALLOW_UNICODE_NAMES = NO
80
81# The OUTPUT_LANGUAGE tag is used to specify the language in which all
82# documentation generated by doxygen is written. Doxygen will use this
83# information to generate all constant output in the proper language.
84# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
85# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
86# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
87# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
88# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
89# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
90# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
91# Ukrainian and Vietnamese.
92# The default value is: English.
93
94OUTPUT_LANGUAGE = English
95
96# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
97# descriptions after the members that are listed in the file and class
98# documentation (similar to Javadoc). Set to NO to disable this.
99# The default value is: YES.
100
101BRIEF_MEMBER_DESC = YES
102
103# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
104# description of a member or function before the detailed description
105#
106# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
107# brief descriptions will be completely suppressed.
108# The default value is: YES.
109
110REPEAT_BRIEF = YES
111
112# This tag implements a quasi-intelligent brief description abbreviator that is
113# used to form the text in various listings. Each string in this list, if found
114# as the leading text of the brief description, will be stripped from the text
115# and the result, after processing the whole list, is used as the annotated
116# text. Otherwise, the brief description is used as-is. If left blank, the
117# following values are used ($name is automatically replaced with the name of
118# the entity):The $name class, The $name widget, The $name file, is, provides,
119# specifies, contains, represents, a, an and the.
120
121ABBREVIATE_BRIEF = "The $name class" \
122 "The $name widget" \
123 "The $name file" \
124 is \
125 provides \
126 specifies \
127 contains \
128 represents \
129 a \
130 an \
131 the
132
133# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
134# doxygen will generate a detailed section even if there is only a brief
135# description.
136# The default value is: NO.
137
138ALWAYS_DETAILED_SEC = NO
139
140# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
141# inherited members of a class in the documentation of that class as if those
142# members were ordinary class members. Constructors, destructors and assignment
143# operators of the base classes will not be shown.
144# The default value is: NO.
145
146INLINE_INHERITED_MEMB = NO
147
148# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
149# before files name in the file list and in the header files. If set to NO the
150# shortest path that makes the file name unique will be used
151# The default value is: YES.
152
153FULL_PATH_NAMES = YES
154
155# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
156# Stripping is only done if one of the specified strings matches the left-hand
157# part of the path. The tag can be used to show relative paths in the file list.
158# If left blank the directory from which doxygen is run is used as the path to
159# strip.
160#
161# Note that you can specify absolute paths here, but also relative paths, which
162# will be relative from the directory where doxygen is started.
163# This tag requires that the tag FULL_PATH_NAMES is set to YES.
164
165STRIP_FROM_PATH =
166
167# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
168# path mentioned in the documentation of a class, which tells the reader which
169# header file to include in order to use a class. If left blank only the name of
170# the header file containing the class definition is used. Otherwise one should
171# specify the list of include paths that are normally passed to the compiler
172# using the -I flag.
173
174STRIP_FROM_INC_PATH =
175
176# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
177# less readable) file names. This can be useful is your file systems doesn't
178# support long names like on DOS, Mac, or CD-ROM.
179# The default value is: NO.
180
181SHORT_NAMES = NO
182
183# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
184# first line (until the first dot) of a Javadoc-style comment as the brief
185# description. If set to NO, the Javadoc-style will behave just like regular Qt-
186# style comments (thus requiring an explicit @brief command for a brief
187# description.)
188# The default value is: NO.
189
190JAVADOC_AUTOBRIEF = YES
191
192# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
193# line (until the first dot) of a Qt-style comment as the brief description. If
194# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
195# requiring an explicit \brief command for a brief description.)
196# The default value is: NO.
197
198QT_AUTOBRIEF = NO
199
200# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
201# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
202# a brief description. This used to be the default behavior. The new default is
203# to treat a multi-line C++ comment block as a detailed description. Set this
204# tag to YES if you prefer the old behavior instead.
205#
206# Note that setting this tag to YES also means that rational rose comments are
207# not recognized any more.
208# The default value is: NO.
209
210MULTILINE_CPP_IS_BRIEF = YES
211
212# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
213# documentation from any documented member that it re-implements.
214# The default value is: YES.
215
216INHERIT_DOCS = YES
217
218# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
219# new page for each member. If set to NO, the documentation of a member will be
220# part of the file/class/namespace that contains it.
221# The default value is: NO.
222
223SEPARATE_MEMBER_PAGES = NO
224
225# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
226# uses this value to replace tabs by spaces in code fragments.
227# Minimum value: 1, maximum value: 16, default value: 4.
228
229TAB_SIZE = 4
230
231# This tag can be used to specify a number of aliases that act as commands in
232# the documentation. An alias has the form:
233# name=value
234# For example adding
235# "sideeffect=@par Side Effects:\n"
236# will allow you to put the command \sideeffect (or @sideeffect) in the
237# documentation, which will result in a user-defined paragraph with heading
238# "Side Effects:". You can put \n's in the value part of an alias to insert
239# newlines.
240
241ALIASES =
242
243# This tag can be used to specify a number of word-keyword mappings (TCL only).
244# A mapping has the form "name=value". For example adding "class=itcl::class"
245# will allow you to use the command class in the itcl::class meaning.
246
247TCL_SUBST =
248
249# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
250# only. Doxygen will then generate output that is more tailored for C. For
251# instance, some of the names that are used will be different. The list of all
252# members will be omitted, etc.
253# The default value is: NO.
254
255OPTIMIZE_OUTPUT_FOR_C = NO
256
257# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
258# Python sources only. Doxygen will then generate output that is more tailored
259# for that language. For instance, namespaces will be presented as packages,
260# qualified scopes will look different, etc.
261# The default value is: NO.
262
263OPTIMIZE_OUTPUT_JAVA = NO
264
265# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
266# sources. Doxygen will then generate output that is tailored for Fortran.
267# The default value is: NO.
268
269OPTIMIZE_FOR_FORTRAN = NO
270
271# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
272# sources. Doxygen will then generate output that is tailored for VHDL.
273# The default value is: NO.
274
275OPTIMIZE_OUTPUT_VHDL = NO
276
277# Doxygen selects the parser to use depending on the extension of the files it
278# parses. With this tag you can assign which parser to use for a given
279# extension. Doxygen has a built-in mapping, but you can override or extend it
280# using this tag. The format is ext=language, where ext is a file extension, and
281# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
282# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
283# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
284# Fortran. In the later case the parser tries to guess whether the code is fixed
285# or free formatted code, this is the default for Fortran type files), VHDL. For
286# instance to make doxygen treat .inc files as Fortran files (default is PHP),
287# and .f files as C (default is Fortran), use: inc=Fortran f=C.
288#
289# Note For files without extension you can use no_extension as a placeholder.
290#
291# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
292# the files are not read by doxygen.
293
294EXTENSION_MAPPING =
295
296# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
297# according to the Markdown format, which allows for more readable
298# documentation. See http://daringfireball.net/projects/markdown/ for details.
299# The output of markdown processing is further processed by doxygen, so you can
300# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
301# case of backward compatibilities issues.
302# The default value is: YES.
303
304MARKDOWN_SUPPORT = YES
305
306# When enabled doxygen tries to link words that correspond to documented
307# classes, or namespaces to their corresponding documentation. Such a link can
308# be prevented in individual cases by by putting a % sign in front of the word
309# or globally by setting AUTOLINK_SUPPORT to NO.
310# The default value is: YES.
311
312AUTOLINK_SUPPORT = YES
313
314# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
315# to include (a tag file for) the STL sources as input, then you should set this
316# tag to YES in order to let doxygen match functions declarations and
317# definitions whose arguments contain STL classes (e.g. func(std::string);
318# versus func(std::string) {}). This also make the inheritance and collaboration
319# diagrams that involve STL classes more complete and accurate.
320# The default value is: NO.
321
322BUILTIN_STL_SUPPORT = NO
323
324# If you use Microsoft's C++/CLI language, you should set this option to YES to
325# enable parsing support.
326# The default value is: NO.
327
328CPP_CLI_SUPPORT = NO
329
330# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
331# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
332# will parse them like normal C++ but will assume all classes use public instead
333# of private inheritance when no explicit protection keyword is present.
334# The default value is: NO.
335
336SIP_SUPPORT = NO
337
338# For Microsoft's IDL there are propget and propput attributes to indicate
339# getter and setter methods for a property. Setting this option to YES will make
340# doxygen to replace the get and set methods by a property in the documentation.
341# This will only work if the methods are indeed getting or setting a simple
342# type. If this is not the case, or you want to show the methods anyway, you
343# should set this option to NO.
344# The default value is: YES.
345
346IDL_PROPERTY_SUPPORT = NO
347
348# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
349# tag is set to YES, then doxygen will reuse the documentation of the first
350# member in the group (if any) for the other members of the group. By default
351# all members of a group must be documented explicitly.
352# The default value is: NO.
353
354DISTRIBUTE_GROUP_DOC = NO
355
356# Set the SUBGROUPING tag to YES to allow class member groups of the same type
357# (for instance a group of public functions) to be put as a subgroup of that
358# type (e.g. under the Public Functions section). Set it to NO to prevent
359# subgrouping. Alternatively, this can be done per class using the
360# \nosubgrouping command.
361# The default value is: YES.
362
363SUBGROUPING = YES
364
365# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
366# are shown inside the group in which they are included (e.g. using \ingroup)
367# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
368# and RTF).
369#
370# Note that this feature does not work in combination with
371# SEPARATE_MEMBER_PAGES.
372# The default value is: NO.
373
374INLINE_GROUPED_CLASSES = NO
375
376# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
377# with only public data fields or simple typedef fields will be shown inline in
378# the documentation of the scope in which they are defined (i.e. file,
379# namespace, or group documentation), provided this scope is documented. If set
380# to NO, structs, classes, and unions are shown on a separate page (for HTML and
381# Man pages) or section (for LaTeX and RTF).
382# The default value is: NO.
383
384INLINE_SIMPLE_STRUCTS = YES
385
386# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
387# enum is documented as struct, union, or enum with the name of the typedef. So
388# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
389# with name TypeT. When disabled the typedef will appear as a member of a file,
390# namespace, or class. And the struct will be named TypeS. This can typically be
391# useful for C code in case the coding convention dictates that all compound
392# types are typedef'ed and only the typedef is referenced, never the tag name.
393# The default value is: NO.
394
395TYPEDEF_HIDES_STRUCT = NO
396
397# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
398# cache is used to resolve symbols given their name and scope. Since this can be
399# an expensive process and often the same symbol appears multiple times in the
400# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
401# doxygen will become slower. If the cache is too large, memory is wasted. The
402# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
403# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
404# symbols. At the end of a run doxygen will report the cache usage and suggest
405# the optimal cache size from a speed point of view.
406# Minimum value: 0, maximum value: 9, default value: 0.
407
408LOOKUP_CACHE_SIZE = 0
409
410#---------------------------------------------------------------------------
411# Build related configuration options
412#---------------------------------------------------------------------------
413
414# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
415# documentation are documented, even if no documentation was available. Private
416# class members and static file members will be hidden unless the
417# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
418# Note: This will also disable the warnings about undocumented members that are
419# normally produced when WARNINGS is set to YES.
420# The default value is: NO.
421
422EXTRACT_ALL = NO
423
424# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
425# be included in the documentation.
426# The default value is: NO.
427
428EXTRACT_PRIVATE = YES
429
430# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
431# scope will be included in the documentation.
432# The default value is: NO.
433
434EXTRACT_PACKAGE = NO
435
436# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
437# included in the documentation.
438# The default value is: NO.
439
440EXTRACT_STATIC = YES
441
442# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
443# locally in source files will be included in the documentation. If set to NO
444# only classes defined in header files are included. Does not have any effect
445# for Java sources.
446# The default value is: YES.
447
448EXTRACT_LOCAL_CLASSES = YES
449
450# This flag is only useful for Objective-C code. When set to YES local methods,
451# which are defined in the implementation section but not in the interface are
452# included in the documentation. If set to NO only methods in the interface are
453# included.
454# The default value is: NO.
455
456EXTRACT_LOCAL_METHODS = NO
457
458# If this flag is set to YES, the members of anonymous namespaces will be
459# extracted and appear in the documentation as a namespace called
460# 'anonymous_namespace{file}', where file will be replaced with the base name of
461# the file that contains the anonymous namespace. By default anonymous namespace
462# are hidden.
463# The default value is: NO.
464
465EXTRACT_ANON_NSPACES = NO
466
467# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
468# undocumented members inside documented classes or files. If set to NO these
469# members will be included in the various overviews, but no documentation
470# section is generated. This option has no effect if EXTRACT_ALL is enabled.
471# The default value is: NO.
472
473HIDE_UNDOC_MEMBERS = NO
474
475# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
476# undocumented classes that are normally visible in the class hierarchy. If set
477# to NO these classes will be included in the various overviews. This option has
478# no effect if EXTRACT_ALL is enabled.
479# The default value is: NO.
480
481HIDE_UNDOC_CLASSES = NO
482
483# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
484# (class|struct|union) declarations. If set to NO these declarations will be
485# included in the documentation.
486# The default value is: NO.
487
488HIDE_FRIEND_COMPOUNDS = NO
489
490# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
491# documentation blocks found inside the body of a function. If set to NO these
492# blocks will be appended to the function's detailed documentation block.
493# The default value is: NO.
494
495HIDE_IN_BODY_DOCS = NO
496
497# The INTERNAL_DOCS tag determines if documentation that is typed after a
498# \internal command is included. If the tag is set to NO then the documentation
499# will be excluded. Set it to YES to include the internal documentation.
500# The default value is: NO.
501
502INTERNAL_DOCS = NO
503
504# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
505# names in lower-case letters. If set to YES upper-case letters are also
506# allowed. This is useful if you have classes or files whose names only differ
507# in case and if your file system supports case sensitive file names. Windows
508# and Mac users are advised to set this option to NO.
509# The default value is: system dependent.
510
511CASE_SENSE_NAMES = NO
512
513# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
514# their full class and namespace scopes in the documentation. If set to YES the
515# scope will be hidden.
516# The default value is: NO.
517
518HIDE_SCOPE_NAMES = NO
519
520# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
521# the files that are included by a file in the documentation of that file.
522# The default value is: YES.
523
524SHOW_INCLUDE_FILES = YES
525
526# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
527# grouped member an include statement to the documentation, telling the reader
528# which file to include in order to use the member.
529# The default value is: NO.
530
531SHOW_GROUPED_MEMB_INC = NO
532
533# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
534# files with double quotes in the documentation rather than with sharp brackets.
535# The default value is: NO.
536
537FORCE_LOCAL_INCLUDES = NO
538
539# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
540# documentation for inline members.
541# The default value is: YES.
542
543INLINE_INFO = YES
544
545# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
546# (detailed) documentation of file and class members alphabetically by member
547# name. If set to NO the members will appear in declaration order.
548# The default value is: YES.
549
550SORT_MEMBER_DOCS = YES
551
552# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
553# descriptions of file, namespace and class members alphabetically by member
554# name. If set to NO the members will appear in declaration order. Note that
555# this will also influence the order of the classes in the class list.
556# The default value is: NO.
557
558SORT_BRIEF_DOCS = NO
559
560# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
561# (brief and detailed) documentation of class members so that constructors and
562# destructors are listed first. If set to NO the constructors will appear in the
563# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
564# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
565# member documentation.
566# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
567# detailed member documentation.
568# The default value is: NO.
569
570SORT_MEMBERS_CTORS_1ST = NO
571
572# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
573# of group names into alphabetical order. If set to NO the group names will
574# appear in their defined order.
575# The default value is: NO.
576
577SORT_GROUP_NAMES = NO
578
579# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
580# fully-qualified names, including namespaces. If set to NO, the class list will
581# be sorted only by class name, not including the namespace part.
582# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
583# Note: This option applies only to the class list, not to the alphabetical
584# list.
585# The default value is: NO.
586
587SORT_BY_SCOPE_NAME = NO
588
589# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
590# type resolution of all parameters of a function it will reject a match between
591# the prototype and the implementation of a member function even if there is
592# only one candidate or it is obvious which candidate to choose by doing a
593# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
594# accept a match between prototype and implementation in such cases.
595# The default value is: NO.
596
597STRICT_PROTO_MATCHING = NO
598
599# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
600# todo list. This list is created by putting \todo commands in the
601# documentation.
602# The default value is: YES.
603
604GENERATE_TODOLIST = YES
605
606# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
607# test list. This list is created by putting \test commands in the
608# documentation.
609# The default value is: YES.
610
611GENERATE_TESTLIST = YES
612
613# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
614# list. This list is created by putting \bug commands in the documentation.
615# The default value is: YES.
616
617GENERATE_BUGLIST = YES
618
619# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
620# the deprecated list. This list is created by putting \deprecated commands in
621# the documentation.
622# The default value is: YES.
623
624GENERATE_DEPRECATEDLIST= YES
625
626# The ENABLED_SECTIONS tag can be used to enable conditional documentation
627# sections, marked by \if <section_label> ... \endif and \cond <section_label>
628# ... \endcond blocks.
629
630ENABLED_SECTIONS =
631
632# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
633# initial value of a variable or macro / define can have for it to appear in the
634# documentation. If the initializer consists of more lines than specified here
635# it will be hidden. Use a value of 0 to hide initializers completely. The
636# appearance of the value of individual variables and macros / defines can be
637# controlled using \showinitializer or \hideinitializer command in the
638# documentation regardless of this setting.
639# Minimum value: 0, maximum value: 10000, default value: 30.
640
641MAX_INITIALIZER_LINES = 30
642
643# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
644# the bottom of the documentation of classes and structs. If set to YES the list
645# will mention the files that were used to generate the documentation.
646# The default value is: YES.
647
648SHOW_USED_FILES = YES
649
650# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
651# will remove the Files entry from the Quick Index and from the Folder Tree View
652# (if specified).
653# The default value is: YES.
654
655SHOW_FILES = YES
656
657# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
658# page. This will remove the Namespaces entry from the Quick Index and from the
659# Folder Tree View (if specified).
660# The default value is: YES.
661
662SHOW_NAMESPACES = YES
663
664# The FILE_VERSION_FILTER tag can be used to specify a program or script that
665# doxygen should invoke to get the current version for each file (typically from
666# the version control system). Doxygen will invoke the program by executing (via
667# popen()) the command command input-file, where command is the value of the
668# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
669# by doxygen. Whatever the program writes to standard output is used as the file
670# version. For an example see the documentation.
671
672FILE_VERSION_FILTER =
673
674# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
675# by doxygen. The layout file controls the global structure of the generated
676# output files in an output format independent way. To create the layout file
677# that represents doxygen's defaults, run doxygen with the -l option. You can
678# optionally specify a file name after the option, if omitted DoxygenLayout.xml
679# will be used as the name of the layout file.
680#
681# Note that if you run doxygen from a directory containing a file called
682# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
683# tag is left empty.
684
685LAYOUT_FILE =
686
687# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
688# the reference definitions. This must be a list of .bib files. The .bib
689# extension is automatically appended if omitted. This requires the bibtex tool
690# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
691# For LaTeX the style of the bibliography can be controlled using
692# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
693# search path. See also \cite for info how to create references.
694
695CITE_BIB_FILES =
696
697#---------------------------------------------------------------------------
698# Configuration options related to warning and progress messages
699#---------------------------------------------------------------------------
700
701# The QUIET tag can be used to turn on/off the messages that are generated to
702# standard output by doxygen. If QUIET is set to YES this implies that the
703# messages are off.
704# The default value is: NO.
705
706QUIET = YES
707
708# The WARNINGS tag can be used to turn on/off the warning messages that are
709# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
710# this implies that the warnings are on.
711#
712# Tip: Turn warnings on while writing the documentation.
713# The default value is: YES.
714
715WARNINGS = YES
716
717# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
718# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
719# will automatically be disabled.
720# The default value is: YES.
721
722WARN_IF_UNDOCUMENTED = NO
723
724# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
725# potential errors in the documentation, such as not documenting some parameters
726# in a documented function, or documenting parameters that don't exist or using
727# markup commands wrongly.
728# The default value is: YES.
729
730WARN_IF_DOC_ERROR = YES
731
732# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
733# are documented, but have no documentation for their parameters or return
734# value. If set to NO doxygen will only warn about wrong or incomplete parameter
735# documentation, but not about the absence of documentation.
736# The default value is: NO.
737
738WARN_NO_PARAMDOC = NO
739
740# The WARN_FORMAT tag determines the format of the warning messages that doxygen
741# can produce. The string should contain the $file, $line, and $text tags, which
742# will be replaced by the file and line number from which the warning originated
743# and the warning text. Optionally the format may contain $version, which will
744# be replaced by the version of the file (if it could be obtained via
745# FILE_VERSION_FILTER)
746# The default value is: $file:$line: $text.
747
748WARN_FORMAT = "$file:$line: $text"
749
750# The WARN_LOGFILE tag can be used to specify a file to which warning and error
751# messages should be written. If left blank the output is written to standard
752# error (stderr).
753
754WARN_LOGFILE =
755
756#---------------------------------------------------------------------------
757# Configuration options related to the input files
758#---------------------------------------------------------------------------
759
760# The INPUT tag is used to specify the files and/or directories that contain
761# documented source files. You may enter file names like myfile.cpp or
762# directories like /usr/src/myproject. Separate the files or directories with
763# spaces.
764# Note: If this tag is empty the current directory is searched.
765
766INPUT = src/
767
768# This tag can be used to specify the character encoding of the source files
769# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
770# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
771# documentation (see: http://www.gnu.org/software/libiconv) for the list of
772# possible encodings.
773# The default value is: UTF-8.
774
775INPUT_ENCODING = UTF-8
776
777# If the value of the INPUT tag contains directories, you can use the
778# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
779# *.h) to filter out the source-files in the directories. If left blank the
780# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
781# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
782# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
783# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
784# *.qsf, *.as and *.js.
785
786FILE_PATTERNS = *.c \
787 *.cc \
788 *.cxx \
789 *.cpp \
790 *.c++ \
791 *.h \
792 *.hh \
793 *.hxx \
794 *.hpp \
795 *.h++
796
797# The RECURSIVE tag can be used to specify whether or not subdirectories should
798# be searched for input files as well.
799# The default value is: NO.
800
801RECURSIVE = YES
802
803# The EXCLUDE tag can be used to specify files and/or directories that should be
804# excluded from the INPUT source files. This way you can easily exclude a
805# subdirectory from a directory tree whose root is specified with the INPUT tag.
806#
807# Note that relative paths are relative to the directory from which doxygen is
808# run.
809
810EXCLUDE =
811
812# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
813# directories that are symbolic links (a Unix file system feature) are excluded
814# from the input.
815# The default value is: NO.
816
817EXCLUDE_SYMLINKS = NO
818
819# If the value of the INPUT tag contains directories, you can use the
820# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
821# certain files from those directories.
822#
823# Note that the wildcards are matched against the file with absolute path, so to
824# exclude all test directories for example use the pattern */test/*
825
826EXCLUDE_PATTERNS =
827
828# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
829# (namespaces, classes, functions, etc.) that should be excluded from the
830# output. The symbol name can be a fully qualified name, a word, or if the
831# wildcard * is used, a substring. Examples: ANamespace, AClass,
832# AClass::ANamespace, ANamespace::*Test
833#
834# Note that the wildcards are matched against the file with absolute path, so to
835# exclude all test directories use the pattern */test/*
836
837EXCLUDE_SYMBOLS =
838
839# The EXAMPLE_PATH tag can be used to specify one or more files or directories
840# that contain example code fragments that are included (see the \include
841# command).
842
843EXAMPLE_PATH =
844
845# If the value of the EXAMPLE_PATH tag contains directories, you can use the
846# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
847# *.h) to filter out the source-files in the directories. If left blank all
848# files are included.
849
850EXAMPLE_PATTERNS = *
851
852# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
853# searched for input files to be used with the \include or \dontinclude commands
854# irrespective of the value of the RECURSIVE tag.
855# The default value is: NO.
856
857EXAMPLE_RECURSIVE = NO
858
859# The IMAGE_PATH tag can be used to specify one or more files or directories
860# that contain images that are to be included in the documentation (see the
861# \image command).
862
863IMAGE_PATH =
864
865# The INPUT_FILTER tag can be used to specify a program that doxygen should
866# invoke to filter for each input file. Doxygen will invoke the filter program
867# by executing (via popen()) the command:
868#
869# <filter> <input-file>
870#
871# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
872# name of an input file. Doxygen will then use the output that the filter
873# program writes to standard output. If FILTER_PATTERNS is specified, this tag
874# will be ignored.
875#
876# Note that the filter must not add or remove lines; it is applied before the
877# code is scanned, but not when the output code is generated. If lines are added
878# or removed, the anchors will not be placed correctly.
879
880INPUT_FILTER =
881
882# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
883# basis. Doxygen will compare the file name with each pattern and apply the
884# filter if there is a match. The filters are a list of the form: pattern=filter
885# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
886# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
887# patterns match the file name, INPUT_FILTER is applied.
888
889FILTER_PATTERNS =
890
891# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
892# INPUT_FILTER ) will also be used to filter the input files that are used for
893# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
894# The default value is: NO.
895
896FILTER_SOURCE_FILES = NO
897
898# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
899# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
900# it is also possible to disable source filtering for a specific pattern using
901# *.ext= (so without naming a filter).
902# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
903
904FILTER_SOURCE_PATTERNS =
905
906# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
907# is part of the input, its contents will be placed on the main page
908# (index.html). This can be useful if you have a project on for instance GitHub
909# and want to reuse the introduction page also for the doxygen output.
910
911USE_MDFILE_AS_MAINPAGE =
912
913#---------------------------------------------------------------------------
914# Configuration options related to source browsing
915#---------------------------------------------------------------------------
916
917# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
918# generated. Documented entities will be cross-referenced with these sources.
919#
920# Note: To get rid of all source code in the generated output, make sure that
921# also VERBATIM_HEADERS is set to NO.
922# The default value is: NO.
923
924SOURCE_BROWSER = YES
925
926# Setting the INLINE_SOURCES tag to YES will include the body of functions,
927# classes and enums directly into the documentation.
928# The default value is: NO.
929
930INLINE_SOURCES = NO
931
932# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
933# special comment blocks from generated source code fragments. Normal C, C++ and
934# Fortran comments will always remain visible.
935# The default value is: YES.
936
937STRIP_CODE_COMMENTS = YES
938
939# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
940# function all documented functions referencing it will be listed.
941# The default value is: NO.
942
943REFERENCED_BY_RELATION = NO
944
945# If the REFERENCES_RELATION tag is set to YES then for each documented function
946# all documented entities called/used by that function will be listed.
947# The default value is: NO.
948
949REFERENCES_RELATION = NO
950
951# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
952# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
953# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
954# link to the documentation.
955# The default value is: YES.
956
957REFERENCES_LINK_SOURCE = YES
958
959# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
960# source code will show a tooltip with additional information such as prototype,
961# brief description and links to the definition and documentation. Since this
962# will make the HTML file larger and loading of large files a bit slower, you
963# can opt to disable this feature.
964# The default value is: YES.
965# This tag requires that the tag SOURCE_BROWSER is set to YES.
966
967SOURCE_TOOLTIPS = YES
968
969# If the USE_HTAGS tag is set to YES then the references to source code will
970# point to the HTML generated by the htags(1) tool instead of doxygen built-in
971# source browser. The htags tool is part of GNU's global source tagging system
972# (see http://www.gnu.org/software/global/global.html). You will need version
973# 4.8.6 or higher.
974#
975# To use it do the following:
976# - Install the latest version of global
977# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
978# - Make sure the INPUT points to the root of the source tree
979# - Run doxygen as normal
980#
981# Doxygen will invoke htags (and that will in turn invoke gtags), so these
982# tools must be available from the command line (i.e. in the search path).
983#
984# The result: instead of the source browser generated by doxygen, the links to
985# source code will now point to the output of htags.
986# The default value is: NO.
987# This tag requires that the tag SOURCE_BROWSER is set to YES.
988
989USE_HTAGS = NO
990
991# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
992# verbatim copy of the header file for each class for which an include is
993# specified. Set to NO to disable this.
994# See also: Section \class.
995# The default value is: YES.
996
997VERBATIM_HEADERS = YES
998
999# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
1000# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
1001# cost of reduced performance. This can be particularly helpful with template
1002# rich C++ code for which doxygen's built-in parser lacks the necessary type
1003# information.
1004# Note: The availability of this option depends on whether or not doxygen was
1005# compiled with the --with-libclang option.
1006# The default value is: NO.
1007
1008CLANG_ASSISTED_PARSING = NO
1009
1010# If clang assisted parsing is enabled you can provide the compiler with command
1011# line options that you would normally use when invoking the compiler. Note that
1012# the include paths will already be set by doxygen for the files and directories
1013# specified with INPUT and INCLUDE_PATH.
1014# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
1015
1016CLANG_OPTIONS =
1017
1018#---------------------------------------------------------------------------
1019# Configuration options related to the alphabetical class index
1020#---------------------------------------------------------------------------
1021
1022# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
1023# compounds will be generated. Enable this if the project contains a lot of
1024# classes, structs, unions or interfaces.
1025# The default value is: YES.
1026
1027ALPHABETICAL_INDEX = YES
1028
1029# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
1030# which the alphabetical index list will be split.
1031# Minimum value: 1, maximum value: 20, default value: 5.
1032# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
1033
1034COLS_IN_ALPHA_INDEX = 5
1035
1036# In case all classes in a project start with a common prefix, all classes will
1037# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
1038# can be used to specify a prefix (or a list of prefixes) that should be ignored
1039# while generating the index headers.
1040# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
1041
1042IGNORE_PREFIX =
1043
1044#---------------------------------------------------------------------------
1045# Configuration options related to the HTML output
1046#---------------------------------------------------------------------------
1047
1048# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
1049# The default value is: YES.
1050
1051GENERATE_HTML = YES
1052
1053# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
1054# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1055# it.
1056# The default directory is: html.
1057# This tag requires that the tag GENERATE_HTML is set to YES.
1058
1059HTML_OUTPUT = html
1060
1061# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
1062# generated HTML page (for example: .htm, .php, .asp).
1063# The default value is: .html.
1064# This tag requires that the tag GENERATE_HTML is set to YES.
1065
1066HTML_FILE_EXTENSION = .html
1067
1068# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
1069# each generated HTML page. If the tag is left blank doxygen will generate a
1070# standard header.
1071#
1072# To get valid HTML the header file that includes any scripts and style sheets
1073# that doxygen needs, which is dependent on the configuration options used (e.g.
1074# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
1075# default header using
1076# doxygen -w html new_header.html new_footer.html new_stylesheet.css
1077# YourConfigFile
1078# and then modify the file new_header.html. See also section "Doxygen usage"
1079# for information on how to generate the default header that doxygen normally
1080# uses.
1081# Note: The header is subject to change so you typically have to regenerate the
1082# default header when upgrading to a newer version of doxygen. For a description
1083# of the possible markers and block names see the documentation.
1084# This tag requires that the tag GENERATE_HTML is set to YES.
1085
1086HTML_HEADER =
1087
1088# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
1089# generated HTML page. If the tag is left blank doxygen will generate a standard
1090# footer. See HTML_HEADER for more information on how to generate a default
1091# footer and what special commands can be used inside the footer. See also
1092# section "Doxygen usage" for information on how to generate the default footer
1093# that doxygen normally uses.
1094# This tag requires that the tag GENERATE_HTML is set to YES.
1095
1096HTML_FOOTER =
1097
1098# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
1099# sheet that is used by each HTML page. It can be used to fine-tune the look of
1100# the HTML output. If left blank doxygen will generate a default style sheet.
1101# See also section "Doxygen usage" for information on how to generate the style
1102# sheet that doxygen normally uses.
1103# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
1104# it is more robust and this tag (HTML_STYLESHEET) will in the future become
1105# obsolete.
1106# This tag requires that the tag GENERATE_HTML is set to YES.
1107
1108HTML_STYLESHEET =
1109
1110# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
1111# cascading style sheets that are included after the standard style sheets
1112# created by doxygen. Using this option one can overrule certain style aspects.
1113# This is preferred over using HTML_STYLESHEET since it does not replace the
1114# standard style sheet and is therefor more robust against future updates.
1115# Doxygen will copy the style sheet files to the output directory.
1116# Note: The order of the extra stylesheet files is of importance (e.g. the last
1117# stylesheet in the list overrules the setting of the previous ones in the
1118# list). For an example see the documentation.
1119# This tag requires that the tag GENERATE_HTML is set to YES.
1120
1121HTML_EXTRA_STYLESHEET =
1122
1123# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
1124# other source files which should be copied to the HTML output directory. Note
1125# that these files will be copied to the base HTML output directory. Use the
1126# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
1127# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
1128# files will be copied as-is; there are no commands or markers available.
1129# This tag requires that the tag GENERATE_HTML is set to YES.
1130
1131HTML_EXTRA_FILES =
1132
1133# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
1134# will adjust the colors in the stylesheet and background images according to
1135# this color. Hue is specified as an angle on a colorwheel, see
1136# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
1137# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
1138# purple, and 360 is red again.
1139# Minimum value: 0, maximum value: 359, default value: 220.
1140# This tag requires that the tag GENERATE_HTML is set to YES.
1141
1142HTML_COLORSTYLE_HUE = 220
1143
1144# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
1145# in the HTML output. For a value of 0 the output will use grayscales only. A
1146# value of 255 will produce the most vivid colors.
1147# Minimum value: 0, maximum value: 255, default value: 100.
1148# This tag requires that the tag GENERATE_HTML is set to YES.
1149
1150HTML_COLORSTYLE_SAT = 100
1151
1152# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
1153# luminance component of the colors in the HTML output. Values below 100
1154# gradually make the output lighter, whereas values above 100 make the output
1155# darker. The value divided by 100 is the actual gamma applied, so 80 represents
1156# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
1157# change the gamma.
1158# Minimum value: 40, maximum value: 240, default value: 80.
1159# This tag requires that the tag GENERATE_HTML is set to YES.
1160
1161HTML_COLORSTYLE_GAMMA = 80
1162
1163# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
1164# page will contain the date and time when the page was generated. Setting this
1165# to NO can help when comparing the output of multiple runs.
1166# The default value is: YES.
1167# This tag requires that the tag GENERATE_HTML is set to YES.
1168
1169HTML_TIMESTAMP = YES
1170
1171# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
1172# documentation will contain sections that can be hidden and shown after the
1173# page has loaded.
1174# The default value is: NO.
1175# This tag requires that the tag GENERATE_HTML is set to YES.
1176
1177HTML_DYNAMIC_SECTIONS = NO
1178
1179# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
1180# shown in the various tree structured indices initially; the user can expand
1181# and collapse entries dynamically later on. Doxygen will expand the tree to
1182# such a level that at most the specified number of entries are visible (unless
1183# a fully collapsed tree already exceeds this amount). So setting the number of
1184# entries 1 will produce a full collapsed tree by default. 0 is a special value
1185# representing an infinite number of entries and will result in a full expanded
1186# tree by default.
1187# Minimum value: 0, maximum value: 9999, default value: 100.
1188# This tag requires that the tag GENERATE_HTML is set to YES.
1189
1190HTML_INDEX_NUM_ENTRIES = 100
1191
1192# If the GENERATE_DOCSET tag is set to YES, additional index files will be
1193# generated that can be used as input for Apple's Xcode 3 integrated development
1194# environment (see: http://developer.apple.com/tools/xcode/), introduced with
1195# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
1196# Makefile in the HTML output directory. Running make will produce the docset in
1197# that directory and running make install will install the docset in
1198# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
1199# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
1200# for more information.
1201# The default value is: NO.
1202# This tag requires that the tag GENERATE_HTML is set to YES.
1203
1204GENERATE_DOCSET = NO
1205
1206# This tag determines the name of the docset feed. A documentation feed provides
1207# an umbrella under which multiple documentation sets from a single provider
1208# (such as a company or product suite) can be grouped.
1209# The default value is: Doxygen generated docs.
1210# This tag requires that the tag GENERATE_DOCSET is set to YES.
1211
1212DOCSET_FEEDNAME = "Doxygen generated docs"
1213
1214# This tag specifies a string that should uniquely identify the documentation
1215# set bundle. This should be a reverse domain-name style string, e.g.
1216# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
1217# The default value is: org.doxygen.Project.
1218# This tag requires that the tag GENERATE_DOCSET is set to YES.
1219
1220DOCSET_BUNDLE_ID = org.doxygen.Project
1221
1222# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
1223# the documentation publisher. This should be a reverse domain-name style
1224# string, e.g. com.mycompany.MyDocSet.documentation.
1225# The default value is: org.doxygen.Publisher.
1226# This tag requires that the tag GENERATE_DOCSET is set to YES.
1227
1228DOCSET_PUBLISHER_ID = org.doxygen.Publisher
1229
1230# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
1231# The default value is: Publisher.
1232# This tag requires that the tag GENERATE_DOCSET is set to YES.
1233
1234DOCSET_PUBLISHER_NAME = Publisher
1235
1236# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
1237# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
1238# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
1239# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
1240# Windows.
1241#
1242# The HTML Help Workshop contains a compiler that can convert all HTML output
1243# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
1244# files are now used as the Windows 98 help format, and will replace the old
1245# Windows help format (.hlp) on all Windows platforms in the future. Compressed
1246# HTML files also contain an index, a table of contents, and you can search for
1247# words in the documentation. The HTML workshop also contains a viewer for
1248# compressed HTML files.
1249# The default value is: NO.
1250# This tag requires that the tag GENERATE_HTML is set to YES.
1251
1252GENERATE_HTMLHELP = NO
1253
1254# The CHM_FILE tag can be used to specify the file name of the resulting .chm
1255# file. You can add a path in front of the file if the result should not be
1256# written to the html output directory.
1257# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1258
1259CHM_FILE =
1260
1261# The HHC_LOCATION tag can be used to specify the location (absolute path
1262# including file name) of the HTML help compiler ( hhc.exe). If non-empty
1263# doxygen will try to run the HTML help compiler on the generated index.hhp.
1264# The file has to be specified with full path.
1265# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1266
1267HHC_LOCATION =
1268
1269# The GENERATE_CHI flag controls if a separate .chi index file is generated (
1270# YES) or that it should be included in the master .chm file ( NO).
1271# The default value is: NO.
1272# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1273
1274GENERATE_CHI = NO
1275
1276# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
1277# and project file content.
1278# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1279
1280CHM_INDEX_ENCODING =
1281
1282# The BINARY_TOC flag controls whether a binary table of contents is generated (
1283# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
1284# enables the Previous and Next buttons.
1285# The default value is: NO.
1286# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1287
1288BINARY_TOC = NO
1289
1290# The TOC_EXPAND flag can be set to YES to add extra items for group members to
1291# the table of contents of the HTML help documentation and to the tree view.
1292# The default value is: NO.
1293# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1294
1295TOC_EXPAND = NO
1296
1297# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
1298# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
1299# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
1300# (.qch) of the generated HTML documentation.
1301# The default value is: NO.
1302# This tag requires that the tag GENERATE_HTML is set to YES.
1303
1304GENERATE_QHP = NO
1305
1306# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
1307# the file name of the resulting .qch file. The path specified is relative to
1308# the HTML output folder.
1309# This tag requires that the tag GENERATE_QHP is set to YES.
1310
1311QCH_FILE =
1312
1313# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
1314# Project output. For more information please see Qt Help Project / Namespace
1315# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
1316# The default value is: org.doxygen.Project.
1317# This tag requires that the tag GENERATE_QHP is set to YES.
1318
1319QHP_NAMESPACE = org.doxygen.Project
1320
1321# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
1322# Help Project output. For more information please see Qt Help Project / Virtual
1323# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
1324# folders).
1325# The default value is: doc.
1326# This tag requires that the tag GENERATE_QHP is set to YES.
1327
1328QHP_VIRTUAL_FOLDER = doc
1329
1330# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
1331# filter to add. For more information please see Qt Help Project / Custom
1332# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
1333# filters).
1334# This tag requires that the tag GENERATE_QHP is set to YES.
1335
1336QHP_CUST_FILTER_NAME =
1337
1338# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
1339# custom filter to add. For more information please see Qt Help Project / Custom
1340# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
1341# filters).
1342# This tag requires that the tag GENERATE_QHP is set to YES.
1343
1344QHP_CUST_FILTER_ATTRS =
1345
1346# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
1347# project's filter section matches. Qt Help Project / Filter Attributes (see:
1348# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
1349# This tag requires that the tag GENERATE_QHP is set to YES.
1350
1351QHP_SECT_FILTER_ATTRS =
1352
1353# The QHG_LOCATION tag can be used to specify the location of Qt's
1354# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
1355# generated .qhp file.
1356# This tag requires that the tag GENERATE_QHP is set to YES.
1357
1358QHG_LOCATION =
1359
1360# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
1361# generated, together with the HTML files, they form an Eclipse help plugin. To
1362# install this plugin and make it available under the help contents menu in
1363# Eclipse, the contents of the directory containing the HTML and XML files needs
1364# to be copied into the plugins directory of eclipse. The name of the directory
1365# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
1366# After copying Eclipse needs to be restarted before the help appears.
1367# The default value is: NO.
1368# This tag requires that the tag GENERATE_HTML is set to YES.
1369
1370GENERATE_ECLIPSEHELP = NO
1371
1372# A unique identifier for the Eclipse help plugin. When installing the plugin
1373# the directory name containing the HTML and XML files should also have this
1374# name. Each documentation set should have its own identifier.
1375# The default value is: org.doxygen.Project.
1376# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
1377
1378ECLIPSE_DOC_ID = org.doxygen.Project
1379
1380# If you want full control over the layout of the generated HTML pages it might
1381# be necessary to disable the index and replace it with your own. The
1382# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
1383# of each HTML page. A value of NO enables the index and the value YES disables
1384# it. Since the tabs in the index contain the same information as the navigation
1385# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
1386# The default value is: NO.
1387# This tag requires that the tag GENERATE_HTML is set to YES.
1388
1389DISABLE_INDEX = NO
1390
1391# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
1392# structure should be generated to display hierarchical information. If the tag
1393# value is set to YES, a side panel will be generated containing a tree-like
1394# index structure (just like the one that is generated for HTML Help). For this
1395# to work a browser that supports JavaScript, DHTML, CSS and frames is required
1396# (i.e. any modern browser). Windows users are probably better off using the
1397# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
1398# further fine-tune the look of the index. As an example, the default style
1399# sheet generated by doxygen has an example that shows how to put an image at
1400# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
1401# the same information as the tab index, you could consider setting
1402# DISABLE_INDEX to YES when enabling this option.
1403# The default value is: NO.
1404# This tag requires that the tag GENERATE_HTML is set to YES.
1405
1406GENERATE_TREEVIEW = YES
1407
1408# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
1409# doxygen will group on one line in the generated HTML documentation.
1410#
1411# Note that a value of 0 will completely suppress the enum values from appearing
1412# in the overview section.
1413# Minimum value: 0, maximum value: 20, default value: 4.
1414# This tag requires that the tag GENERATE_HTML is set to YES.
1415
1416ENUM_VALUES_PER_LINE = 4
1417
1418# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
1419# to set the initial width (in pixels) of the frame in which the tree is shown.
1420# Minimum value: 0, maximum value: 1500, default value: 250.
1421# This tag requires that the tag GENERATE_HTML is set to YES.
1422
1423TREEVIEW_WIDTH = 250
1424
1425# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
1426# external symbols imported via tag files in a separate window.
1427# The default value is: NO.
1428# This tag requires that the tag GENERATE_HTML is set to YES.
1429
1430EXT_LINKS_IN_WINDOW = NO
1431
1432# Use this tag to change the font size of LaTeX formulas included as images in
1433# the HTML documentation. When you change the font size after a successful
1434# doxygen run you need to manually remove any form_*.png images from the HTML
1435# output directory to force them to be regenerated.
1436# Minimum value: 8, maximum value: 50, default value: 10.
1437# This tag requires that the tag GENERATE_HTML is set to YES.
1438
1439FORMULA_FONTSIZE = 10
1440
1441# Use the FORMULA_TRANPARENT tag to determine whether or not the images
1442# generated for formulas are transparent PNGs. Transparent PNGs are not
1443# supported properly for IE 6.0, but are supported on all modern browsers.
1444#
1445# Note that when changing this option you need to delete any form_*.png files in
1446# the HTML output directory before the changes have effect.
1447# The default value is: YES.
1448# This tag requires that the tag GENERATE_HTML is set to YES.
1449
1450FORMULA_TRANSPARENT = YES
1451
1452# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
1453# http://www.mathjax.org) which uses client side Javascript for the rendering
1454# instead of using prerendered bitmaps. Use this if you do not have LaTeX
1455# installed or if you want to formulas look prettier in the HTML output. When
1456# enabled you may also need to install MathJax separately and configure the path
1457# to it using the MATHJAX_RELPATH option.
1458# The default value is: NO.
1459# This tag requires that the tag GENERATE_HTML is set to YES.
1460
1461USE_MATHJAX = NO
1462
1463# When MathJax is enabled you can set the default output format to be used for
1464# the MathJax output. See the MathJax site (see:
1465# http://docs.mathjax.org/en/latest/output.html) for more details.
1466# Possible values are: HTML-CSS (which is slower, but has the best
1467# compatibility), NativeMML (i.e. MathML) and SVG.
1468# The default value is: HTML-CSS.
1469# This tag requires that the tag USE_MATHJAX is set to YES.
1470
1471MATHJAX_FORMAT = HTML-CSS
1472
1473# When MathJax is enabled you need to specify the location relative to the HTML
1474# output directory using the MATHJAX_RELPATH option. The destination directory
1475# should contain the MathJax.js script. For instance, if the mathjax directory
1476# is located at the same level as the HTML output directory, then
1477# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
1478# Content Delivery Network so you can quickly see the result without installing
1479# MathJax. However, it is strongly recommended to install a local copy of
1480# MathJax from http://www.mathjax.org before deployment.
1481# The default value is: http://cdn.mathjax.org/mathjax/latest.
1482# This tag requires that the tag USE_MATHJAX is set to YES.
1483
1484MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
1485
1486# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
1487# extension names that should be enabled during MathJax rendering. For example
1488# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
1489# This tag requires that the tag USE_MATHJAX is set to YES.
1490
1491MATHJAX_EXTENSIONS =
1492
1493# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
1494# of code that will be used on startup of the MathJax code. See the MathJax site
1495# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
1496# example see the documentation.
1497# This tag requires that the tag USE_MATHJAX is set to YES.
1498
1499MATHJAX_CODEFILE =
1500
1501# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
1502# the HTML output. The underlying search engine uses javascript and DHTML and
1503# should work on any modern browser. Note that when using HTML help
1504# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
1505# there is already a search function so this one should typically be disabled.
1506# For large projects the javascript based search engine can be slow, then
1507# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
1508# search using the keyboard; to jump to the search box use <access key> + S
1509# (what the <access key> is depends on the OS and browser, but it is typically
1510# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
1511# key> to jump into the search results window, the results can be navigated
1512# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
1513# the search. The filter options can be selected when the cursor is inside the
1514# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
1515# to select a filter and <Enter> or <escape> to activate or cancel the filter
1516# option.
1517# The default value is: YES.
1518# This tag requires that the tag GENERATE_HTML is set to YES.
1519
1520SEARCHENGINE = YES
1521
1522# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
1523# implemented using a web server instead of a web client using Javascript. There
1524# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
1525# setting. When disabled, doxygen will generate a PHP script for searching and
1526# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
1527# and searching needs to be provided by external tools. See the section
1528# "External Indexing and Searching" for details.
1529# The default value is: NO.
1530# This tag requires that the tag SEARCHENGINE is set to YES.
1531
1532SERVER_BASED_SEARCH = NO
1533
1534# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
1535# script for searching. Instead the search results are written to an XML file
1536# which needs to be processed by an external indexer. Doxygen will invoke an
1537# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
1538# search results.
1539#
1540# Doxygen ships with an example indexer ( doxyindexer) and search engine
1541# (doxysearch.cgi) which are based on the open source search engine library
1542# Xapian (see: http://xapian.org/).
1543#
1544# See the section "External Indexing and Searching" for details.
1545# The default value is: NO.
1546# This tag requires that the tag SEARCHENGINE is set to YES.
1547
1548EXTERNAL_SEARCH = NO
1549
1550# The SEARCHENGINE_URL should point to a search engine hosted by a web server
1551# which will return the search results when EXTERNAL_SEARCH is enabled.
1552#
1553# Doxygen ships with an example indexer ( doxyindexer) and search engine
1554# (doxysearch.cgi) which are based on the open source search engine library
1555# Xapian (see: http://xapian.org/). See the section "External Indexing and
1556# Searching" for details.
1557# This tag requires that the tag SEARCHENGINE is set to YES.
1558
1559SEARCHENGINE_URL =
1560
1561# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
1562# search data is written to a file for indexing by an external tool. With the
1563# SEARCHDATA_FILE tag the name of this file can be specified.
1564# The default file is: searchdata.xml.
1565# This tag requires that the tag SEARCHENGINE is set to YES.
1566
1567SEARCHDATA_FILE = searchdata.xml
1568
1569# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
1570# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
1571# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
1572# projects and redirect the results back to the right project.
1573# This tag requires that the tag SEARCHENGINE is set to YES.
1574
1575EXTERNAL_SEARCH_ID =
1576
1577# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
1578# projects other than the one defined by this configuration file, but that are
1579# all added to the same external search index. Each project needs to have a
1580# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
1581# to a relative location where the documentation can be found. The format is:
1582# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
1583# This tag requires that the tag SEARCHENGINE is set to YES.
1584
1585EXTRA_SEARCH_MAPPINGS =
1586
1587#---------------------------------------------------------------------------
1588# Configuration options related to the LaTeX output
1589#---------------------------------------------------------------------------
1590
1591# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
1592# The default value is: YES.
1593
1594GENERATE_LATEX = NO
1595
1596# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
1597# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1598# it.
1599# The default directory is: latex.
1600# This tag requires that the tag GENERATE_LATEX is set to YES.
1601
1602LATEX_OUTPUT = latex
1603
1604# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
1605# invoked.
1606#
1607# Note that when enabling USE_PDFLATEX this option is only used for generating
1608# bitmaps for formulas in the HTML output, but not in the Makefile that is
1609# written to the output directory.
1610# The default file is: latex.
1611# This tag requires that the tag GENERATE_LATEX is set to YES.
1612
1613LATEX_CMD_NAME = latex
1614
1615# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
1616# index for LaTeX.
1617# The default file is: makeindex.
1618# This tag requires that the tag GENERATE_LATEX is set to YES.
1619
1620MAKEINDEX_CMD_NAME = makeindex
1621
1622# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
1623# documents. This may be useful for small projects and may help to save some
1624# trees in general.
1625# The default value is: NO.
1626# This tag requires that the tag GENERATE_LATEX is set to YES.
1627
1628COMPACT_LATEX = NO
1629
1630# The PAPER_TYPE tag can be used to set the paper type that is used by the
1631# printer.
1632# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
1633# 14 inches) and executive (7.25 x 10.5 inches).
1634# The default value is: a4.
1635# This tag requires that the tag GENERATE_LATEX is set to YES.
1636
1637PAPER_TYPE = a4
1638
1639# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
1640# that should be included in the LaTeX output. To get the times font for
1641# instance you can specify
1642# EXTRA_PACKAGES=times
1643# If left blank no extra packages will be included.
1644# This tag requires that the tag GENERATE_LATEX is set to YES.
1645
1646EXTRA_PACKAGES =
1647
1648# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
1649# generated LaTeX document. The header should contain everything until the first
1650# chapter. If it is left blank doxygen will generate a standard header. See
1651# section "Doxygen usage" for information on how to let doxygen write the
1652# default header to a separate file.
1653#
1654# Note: Only use a user-defined header if you know what you are doing! The
1655# following commands have a special meaning inside the header: $title,
1656# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
1657# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
1658# for the replacement values of the other commands the user is refered to
1659# HTML_HEADER.
1660# This tag requires that the tag GENERATE_LATEX is set to YES.
1661
1662LATEX_HEADER =
1663
1664# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
1665# generated LaTeX document. The footer should contain everything after the last
1666# chapter. If it is left blank doxygen will generate a standard footer. See
1667# LATEX_HEADER for more information on how to generate a default footer and what
1668# special commands can be used inside the footer.
1669#
1670# Note: Only use a user-defined footer if you know what you are doing!
1671# This tag requires that the tag GENERATE_LATEX is set to YES.
1672
1673LATEX_FOOTER =
1674
1675# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
1676# other source files which should be copied to the LATEX_OUTPUT output
1677# directory. Note that the files will be copied as-is; there are no commands or
1678# markers available.
1679# This tag requires that the tag GENERATE_LATEX is set to YES.
1680
1681LATEX_EXTRA_FILES =
1682
1683# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
1684# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
1685# contain links (just like the HTML output) instead of page references. This
1686# makes the output suitable for online browsing using a PDF viewer.
1687# The default value is: YES.
1688# This tag requires that the tag GENERATE_LATEX is set to YES.
1689
1690PDF_HYPERLINKS = YES
1691
1692# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
1693# the PDF file directly from the LaTeX files. Set this option to YES to get a
1694# higher quality PDF documentation.
1695# The default value is: YES.
1696# This tag requires that the tag GENERATE_LATEX is set to YES.
1697
1698USE_PDFLATEX = YES
1699
1700# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
1701# command to the generated LaTeX files. This will instruct LaTeX to keep running
1702# if errors occur, instead of asking the user for help. This option is also used
1703# when generating formulas in HTML.
1704# The default value is: NO.
1705# This tag requires that the tag GENERATE_LATEX is set to YES.
1706
1707LATEX_BATCHMODE = NO
1708
1709# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
1710# index chapters (such as File Index, Compound Index, etc.) in the output.
1711# The default value is: NO.
1712# This tag requires that the tag GENERATE_LATEX is set to YES.
1713
1714LATEX_HIDE_INDICES = NO
1715
1716# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
1717# code with syntax highlighting in the LaTeX output.
1718#
1719# Note that which sources are shown also depends on other settings such as
1720# SOURCE_BROWSER.
1721# The default value is: NO.
1722# This tag requires that the tag GENERATE_LATEX is set to YES.
1723
1724LATEX_SOURCE_CODE = NO
1725
1726# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
1727# bibliography, e.g. plainnat, or ieeetr. See
1728# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
1729# The default value is: plain.
1730# This tag requires that the tag GENERATE_LATEX is set to YES.
1731
1732LATEX_BIB_STYLE = plain
1733
1734#---------------------------------------------------------------------------
1735# Configuration options related to the RTF output
1736#---------------------------------------------------------------------------
1737
1738# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
1739# RTF output is optimized for Word 97 and may not look too pretty with other RTF
1740# readers/editors.
1741# The default value is: NO.
1742
1743GENERATE_RTF = NO
1744
1745# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
1746# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1747# it.
1748# The default directory is: rtf.
1749# This tag requires that the tag GENERATE_RTF is set to YES.
1750
1751RTF_OUTPUT = rtf
1752
1753# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
1754# documents. This may be useful for small projects and may help to save some
1755# trees in general.
1756# The default value is: NO.
1757# This tag requires that the tag GENERATE_RTF is set to YES.
1758
1759COMPACT_RTF = NO
1760
1761# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
1762# contain hyperlink fields. The RTF file will contain links (just like the HTML
1763# output) instead of page references. This makes the output suitable for online
1764# browsing using Word or some other Word compatible readers that support those
1765# fields.
1766#
1767# Note: WordPad (write) and others do not support links.
1768# The default value is: NO.
1769# This tag requires that the tag GENERATE_RTF is set to YES.
1770
1771RTF_HYPERLINKS = NO
1772
1773# Load stylesheet definitions from file. Syntax is similar to doxygen's config
1774# file, i.e. a series of assignments. You only have to provide replacements,
1775# missing definitions are set to their default value.
1776#
1777# See also section "Doxygen usage" for information on how to generate the
1778# default style sheet that doxygen normally uses.
1779# This tag requires that the tag GENERATE_RTF is set to YES.
1780
1781RTF_STYLESHEET_FILE =
1782
1783# Set optional variables used in the generation of an RTF document. Syntax is
1784# similar to doxygen's config file. A template extensions file can be generated
1785# using doxygen -e rtf extensionFile.
1786# This tag requires that the tag GENERATE_RTF is set to YES.
1787
1788RTF_EXTENSIONS_FILE =
1789
1790#---------------------------------------------------------------------------
1791# Configuration options related to the man page output
1792#---------------------------------------------------------------------------
1793
1794# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
1795# classes and files.
1796# The default value is: NO.
1797
1798GENERATE_MAN = NO
1799
1800# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
1801# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1802# it. A directory man3 will be created inside the directory specified by
1803# MAN_OUTPUT.
1804# The default directory is: man.
1805# This tag requires that the tag GENERATE_MAN is set to YES.
1806
1807MAN_OUTPUT = man
1808
1809# The MAN_EXTENSION tag determines the extension that is added to the generated
1810# man pages. In case the manual section does not start with a number, the number
1811# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
1812# optional.
1813# The default value is: .3.
1814# This tag requires that the tag GENERATE_MAN is set to YES.
1815
1816MAN_EXTENSION = .3
1817
1818# The MAN_SUBDIR tag determines the name of the directory created within
1819# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
1820# MAN_EXTENSION with the initial . removed.
1821# This tag requires that the tag GENERATE_MAN is set to YES.
1822
1823MAN_SUBDIR =
1824
1825# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
1826# will generate one additional man file for each entity documented in the real
1827# man page(s). These additional files only source the real man page, but without
1828# them the man command would be unable to find the correct page.
1829# The default value is: NO.
1830# This tag requires that the tag GENERATE_MAN is set to YES.
1831
1832MAN_LINKS = NO
1833
1834#---------------------------------------------------------------------------
1835# Configuration options related to the XML output
1836#---------------------------------------------------------------------------
1837
1838# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
1839# captures the structure of the code including all documentation.
1840# The default value is: NO.
1841
1842GENERATE_XML = NO
1843
1844# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
1845# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1846# it.
1847# The default directory is: xml.
1848# This tag requires that the tag GENERATE_XML is set to YES.
1849
1850XML_OUTPUT = xml
1851
1852# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
1853# listings (including syntax highlighting and cross-referencing information) to
1854# the XML output. Note that enabling this will significantly increase the size
1855# of the XML output.
1856# The default value is: YES.
1857# This tag requires that the tag GENERATE_XML is set to YES.
1858
1859XML_PROGRAMLISTING = YES
1860
1861#---------------------------------------------------------------------------
1862# Configuration options related to the DOCBOOK output
1863#---------------------------------------------------------------------------
1864
1865# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
1866# that can be used to generate PDF.
1867# The default value is: NO.
1868
1869GENERATE_DOCBOOK = NO
1870
1871# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
1872# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
1873# front of it.
1874# The default directory is: docbook.
1875# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
1876
1877DOCBOOK_OUTPUT = docbook
1878
1879# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
1880# program listings (including syntax highlighting and cross-referencing
1881# information) to the DOCBOOK output. Note that enabling this will significantly
1882# increase the size of the DOCBOOK output.
1883# The default value is: NO.
1884# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
1885
1886DOCBOOK_PROGRAMLISTING = NO
1887
1888#---------------------------------------------------------------------------
1889# Configuration options for the AutoGen Definitions output
1890#---------------------------------------------------------------------------
1891
1892# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
1893# Definitions (see http://autogen.sf.net) file that captures the structure of
1894# the code including all documentation. Note that this feature is still
1895# experimental and incomplete at the moment.
1896# The default value is: NO.
1897
1898GENERATE_AUTOGEN_DEF = NO
1899
1900#---------------------------------------------------------------------------
1901# Configuration options related to the Perl module output
1902#---------------------------------------------------------------------------
1903
1904# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
1905# file that captures the structure of the code including all documentation.
1906#
1907# Note that this feature is still experimental and incomplete at the moment.
1908# The default value is: NO.
1909
1910GENERATE_PERLMOD = NO
1911
1912# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
1913# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
1914# output from the Perl module output.
1915# The default value is: NO.
1916# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1917
1918PERLMOD_LATEX = NO
1919
1920# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
1921# formatted so it can be parsed by a human reader. This is useful if you want to
1922# understand what is going on. On the other hand, if this tag is set to NO the
1923# size of the Perl module output will be much smaller and Perl will parse it
1924# just the same.
1925# The default value is: YES.
1926# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1927
1928PERLMOD_PRETTY = YES
1929
1930# The names of the make variables in the generated doxyrules.make file are
1931# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
1932# so different doxyrules.make files included by the same Makefile don't
1933# overwrite each other's variables.
1934# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1935
1936PERLMOD_MAKEVAR_PREFIX =
1937
1938#---------------------------------------------------------------------------
1939# Configuration options related to the preprocessor
1940#---------------------------------------------------------------------------
1941
1942# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
1943# C-preprocessor directives found in the sources and include files.
1944# The default value is: YES.
1945
1946ENABLE_PREPROCESSING = YES
1947
1948# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
1949# in the source code. If set to NO only conditional compilation will be
1950# performed. Macro expansion can be done in a controlled way by setting
1951# EXPAND_ONLY_PREDEF to YES.
1952# The default value is: NO.
1953# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1954
1955MACRO_EXPANSION = NO
1956
1957# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
1958# the macro expansion is limited to the macros specified with the PREDEFINED and
1959# EXPAND_AS_DEFINED tags.
1960# The default value is: NO.
1961# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1962
1963EXPAND_ONLY_PREDEF = NO
1964
1965# If the SEARCH_INCLUDES tag is set to YES the includes files in the
1966# INCLUDE_PATH will be searched if a #include is found.
1967# The default value is: YES.
1968# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1969
1970SEARCH_INCLUDES = YES
1971
1972# The INCLUDE_PATH tag can be used to specify one or more directories that
1973# contain include files that are not input files but should be processed by the
1974# preprocessor.
1975# This tag requires that the tag SEARCH_INCLUDES is set to YES.
1976
1977INCLUDE_PATH =
1978
1979# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
1980# patterns (like *.h and *.hpp) to filter out the header-files in the
1981# directories. If left blank, the patterns specified with FILE_PATTERNS will be
1982# used.
1983# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1984
1985INCLUDE_FILE_PATTERNS =
1986
1987# The PREDEFINED tag can be used to specify one or more macro names that are
1988# defined before the preprocessor is started (similar to the -D option of e.g.
1989# gcc). The argument of the tag is a list of macros of the form: name or
1990# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
1991# is assumed. To prevent a macro definition from being undefined via #undef or
1992# recursively expanded use the := operator instead of the = operator.
1993# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1994
1995PREDEFINED =
1996
1997# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
1998# tag can be used to specify a list of macro names that should be expanded. The
1999# macro definition that is found in the sources will be used. Use the PREDEFINED
2000# tag if you want to use a different macro definition that overrules the
2001# definition found in the source code.
2002# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2003
2004EXPAND_AS_DEFINED =
2005
2006# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
2007# remove all references to function-like macros that are alone on a line, have
2008# an all uppercase name, and do not end with a semicolon. Such function macros
2009# are typically used for boiler-plate code, and will confuse the parser if not
2010# removed.
2011# The default value is: YES.
2012# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2013
2014SKIP_FUNCTION_MACROS = YES
2015
2016#---------------------------------------------------------------------------
2017# Configuration options related to external references
2018#---------------------------------------------------------------------------
2019
2020# The TAGFILES tag can be used to specify one or more tag files. For each tag
2021# file the location of the external documentation should be added. The format of
2022# a tag file without this location is as follows:
2023# TAGFILES = file1 file2 ...
2024# Adding location for the tag files is done as follows:
2025# TAGFILES = file1=loc1 "file2 = loc2" ...
2026# where loc1 and loc2 can be relative or absolute paths or URLs. See the
2027# section "Linking to external documentation" for more information about the use
2028# of tag files.
2029# Note: Each tag file must have a unique name (where the name does NOT include
2030# the path). If a tag file is not located in the directory in which doxygen is
2031# run, you must also specify the path to the tagfile here.
2032
2033TAGFILES =
2034
2035# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
2036# tag file that is based on the input files it reads. See section "Linking to
2037# external documentation" for more information about the usage of tag files.
2038
2039GENERATE_TAGFILE =
2040
2041# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
2042# class index. If set to NO only the inherited external classes will be listed.
2043# The default value is: NO.
2044
2045ALLEXTERNALS = NO
2046
2047# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
2048# the modules index. If set to NO, only the current project's groups will be
2049# listed.
2050# The default value is: YES.
2051
2052EXTERNAL_GROUPS = YES
2053
2054# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
2055# the related pages index. If set to NO, only the current project's pages will
2056# be listed.
2057# The default value is: YES.
2058
2059EXTERNAL_PAGES = YES
2060
2061# The PERL_PATH should be the absolute path and name of the perl script
2062# interpreter (i.e. the result of 'which perl').
2063# The default file (with absolute path) is: /usr/bin/perl.
2064
2065PERL_PATH = /usr/bin/perl
2066
2067#---------------------------------------------------------------------------
2068# Configuration options related to the dot tool
2069#---------------------------------------------------------------------------
2070
2071# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
2072# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
2073# NO turns the diagrams off. Note that this option also works with HAVE_DOT
2074# disabled, but it is recommended to install and use dot, since it yields more
2075# powerful graphs.
2076# The default value is: YES.
2077
2078CLASS_DIAGRAMS = YES
2079
2080# You can define message sequence charts within doxygen comments using the \msc
2081# command. Doxygen will then run the mscgen tool (see:
2082# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
2083# documentation. The MSCGEN_PATH tag allows you to specify the directory where
2084# the mscgen tool resides. If left empty the tool is assumed to be found in the
2085# default search path.
2086
2087MSCGEN_PATH =
2088
2089# You can include diagrams made with dia in doxygen documentation. Doxygen will
2090# then run dia to produce the diagram and insert it in the documentation. The
2091# DIA_PATH tag allows you to specify the directory where the dia binary resides.
2092# If left empty dia is assumed to be found in the default search path.
2093
2094DIA_PATH =
2095
2096# If set to YES, the inheritance and collaboration graphs will hide inheritance
2097# and usage relations if the target is undocumented or is not a class.
2098# The default value is: YES.
2099
2100HIDE_UNDOC_RELATIONS = YES
2101
2102# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
2103# available from the path. This tool is part of Graphviz (see:
2104# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
2105# Bell Labs. The other options in this section have no effect if this option is
2106# set to NO
2107# The default value is: NO.
2108
2109HAVE_DOT = NO
2110
2111# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
2112# to run in parallel. When set to 0 doxygen will base this on the number of
2113# processors available in the system. You can set it explicitly to a value
2114# larger than 0 to get control over the balance between CPU load and processing
2115# speed.
2116# Minimum value: 0, maximum value: 32, default value: 0.
2117# This tag requires that the tag HAVE_DOT is set to YES.
2118
2119DOT_NUM_THREADS = 0
2120
2121# When you want a differently looking font in the dot files that doxygen
2122# generates you can specify the font name using DOT_FONTNAME. You need to make
2123# sure dot is able to find the font, which can be done by putting it in a
2124# standard location or by setting the DOTFONTPATH environment variable or by
2125# setting DOT_FONTPATH to the directory containing the font.
2126# The default value is: Helvetica.
2127# This tag requires that the tag HAVE_DOT is set to YES.
2128
2129DOT_FONTNAME = Helvetica
2130
2131# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
2132# dot graphs.
2133# Minimum value: 4, maximum value: 24, default value: 10.
2134# This tag requires that the tag HAVE_DOT is set to YES.
2135
2136DOT_FONTSIZE = 10
2137
2138# By default doxygen will tell dot to use the default font as specified with
2139# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
2140# the path where dot can find it using this tag.
2141# This tag requires that the tag HAVE_DOT is set to YES.
2142
2143DOT_FONTPATH =
2144
2145# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
2146# each documented class showing the direct and indirect inheritance relations.
2147# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
2148# The default value is: YES.
2149# This tag requires that the tag HAVE_DOT is set to YES.
2150
2151CLASS_GRAPH = YES
2152
2153# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
2154# graph for each documented class showing the direct and indirect implementation
2155# dependencies (inheritance, containment, and class references variables) of the
2156# class with other documented classes.
2157# The default value is: YES.
2158# This tag requires that the tag HAVE_DOT is set to YES.
2159
2160COLLABORATION_GRAPH = YES
2161
2162# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
2163# groups, showing the direct groups dependencies.
2164# The default value is: YES.
2165# This tag requires that the tag HAVE_DOT is set to YES.
2166
2167GROUP_GRAPHS = YES
2168
2169# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
2170# collaboration diagrams in a style similar to the OMG's Unified Modeling
2171# Language.
2172# The default value is: NO.
2173# This tag requires that the tag HAVE_DOT is set to YES.
2174
2175UML_LOOK = NO
2176
2177# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
2178# class node. If there are many fields or methods and many nodes the graph may
2179# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
2180# number of items for each type to make the size more manageable. Set this to 0
2181# for no limit. Note that the threshold may be exceeded by 50% before the limit
2182# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
2183# but if the number exceeds 15, the total amount of fields shown is limited to
2184# 10.
2185# Minimum value: 0, maximum value: 100, default value: 10.
2186# This tag requires that the tag HAVE_DOT is set to YES.
2187
2188UML_LIMIT_NUM_FIELDS = 10
2189
2190# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
2191# collaboration graphs will show the relations between templates and their
2192# instances.
2193# The default value is: NO.
2194# This tag requires that the tag HAVE_DOT is set to YES.
2195
2196TEMPLATE_RELATIONS = NO
2197
2198# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
2199# YES then doxygen will generate a graph for each documented file showing the
2200# direct and indirect include dependencies of the file with other documented
2201# files.
2202# The default value is: YES.
2203# This tag requires that the tag HAVE_DOT is set to YES.
2204
2205INCLUDE_GRAPH = YES
2206
2207# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
2208# set to YES then doxygen will generate a graph for each documented file showing
2209# the direct and indirect include dependencies of the file with other documented
2210# files.
2211# The default value is: YES.
2212# This tag requires that the tag HAVE_DOT is set to YES.
2213
2214INCLUDED_BY_GRAPH = YES
2215
2216# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
2217# dependency graph for every global function or class method.
2218#
2219# Note that enabling this option will significantly increase the time of a run.
2220# So in most cases it will be better to enable call graphs for selected
2221# functions only using the \callgraph command.
2222# The default value is: NO.
2223# This tag requires that the tag HAVE_DOT is set to YES.
2224
2225CALL_GRAPH = NO
2226
2227# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
2228# dependency graph for every global function or class method.
2229#
2230# Note that enabling this option will significantly increase the time of a run.
2231# So in most cases it will be better to enable caller graphs for selected
2232# functions only using the \callergraph command.
2233# The default value is: NO.
2234# This tag requires that the tag HAVE_DOT is set to YES.
2235
2236CALLER_GRAPH = NO
2237
2238# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
2239# hierarchy of all classes instead of a textual one.
2240# The default value is: YES.
2241# This tag requires that the tag HAVE_DOT is set to YES.
2242
2243GRAPHICAL_HIERARCHY = YES
2244
2245# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
2246# dependencies a directory has on other directories in a graphical way. The
2247# dependency relations are determined by the #include relations between the
2248# files in the directories.
2249# The default value is: YES.
2250# This tag requires that the tag HAVE_DOT is set to YES.
2251
2252DIRECTORY_GRAPH = YES
2253
2254# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
2255# generated by dot.
2256# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
2257# to make the SVG files visible in IE 9+ (other browsers do not have this
2258# requirement).
2259# Possible values are: png, jpg, gif and svg.
2260# The default value is: png.
2261# This tag requires that the tag HAVE_DOT is set to YES.
2262
2263DOT_IMAGE_FORMAT = png
2264
2265# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
2266# enable generation of interactive SVG images that allow zooming and panning.
2267#
2268# Note that this requires a modern browser other than Internet Explorer. Tested
2269# and working are Firefox, Chrome, Safari, and Opera.
2270# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
2271# the SVG files visible. Older versions of IE do not have SVG support.
2272# The default value is: NO.
2273# This tag requires that the tag HAVE_DOT is set to YES.
2274
2275INTERACTIVE_SVG = NO
2276
2277# The DOT_PATH tag can be used to specify the path where the dot tool can be
2278# found. If left blank, it is assumed the dot tool can be found in the path.
2279# This tag requires that the tag HAVE_DOT is set to YES.
2280
2281DOT_PATH =
2282
2283# The DOTFILE_DIRS tag can be used to specify one or more directories that
2284# contain dot files that are included in the documentation (see the \dotfile
2285# command).
2286# This tag requires that the tag HAVE_DOT is set to YES.
2287
2288DOTFILE_DIRS =
2289
2290# The MSCFILE_DIRS tag can be used to specify one or more directories that
2291# contain msc files that are included in the documentation (see the \mscfile
2292# command).
2293
2294MSCFILE_DIRS =
2295
2296# The DIAFILE_DIRS tag can be used to specify one or more directories that
2297# contain dia files that are included in the documentation (see the \diafile
2298# command).
2299
2300DIAFILE_DIRS =
2301
2302# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
2303# path where java can find the plantuml.jar file. If left blank, it is assumed
2304# PlantUML is not used or called during a preprocessing step. Doxygen will
2305# generate a warning when it encounters a \startuml command in this case and
2306# will not generate output for the diagram.
2307# This tag requires that the tag HAVE_DOT is set to YES.
2308
2309PLANTUML_JAR_PATH =
2310
2311# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
2312# that will be shown in the graph. If the number of nodes in a graph becomes
2313# larger than this value, doxygen will truncate the graph, which is visualized
2314# by representing a node as a red box. Note that doxygen if the number of direct
2315# children of the root node in a graph is already larger than
2316# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
2317# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
2318# Minimum value: 0, maximum value: 10000, default value: 50.
2319# This tag requires that the tag HAVE_DOT is set to YES.
2320
2321DOT_GRAPH_MAX_NODES = 50
2322
2323# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
2324# generated by dot. A depth value of 3 means that only nodes reachable from the
2325# root by following a path via at most 3 edges will be shown. Nodes that lay
2326# further from the root node will be omitted. Note that setting this option to 1
2327# or 2 may greatly reduce the computation time needed for large code bases. Also
2328# note that the size of a graph can be further restricted by
2329# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
2330# Minimum value: 0, maximum value: 1000, default value: 0.
2331# This tag requires that the tag HAVE_DOT is set to YES.
2332
2333MAX_DOT_GRAPH_DEPTH = 0
2334
2335# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
2336# background. This is disabled by default, because dot on Windows does not seem
2337# to support this out of the box.
2338#
2339# Warning: Depending on the platform used, enabling this option may lead to
2340# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
2341# read).
2342# The default value is: NO.
2343# This tag requires that the tag HAVE_DOT is set to YES.
2344
2345DOT_TRANSPARENT = NO
2346
2347# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
2348# files in one run (i.e. multiple -o and -T options on the command line). This
2349# makes dot run faster, but since only newer versions of dot (>1.8.10) support
2350# this, this feature is disabled by default.
2351# The default value is: NO.
2352# This tag requires that the tag HAVE_DOT is set to YES.
2353
2354DOT_MULTI_TARGETS = NO
2355
2356# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
2357# explaining the meaning of the various boxes and arrows in the dot generated
2358# graphs.
2359# The default value is: YES.
2360# This tag requires that the tag HAVE_DOT is set to YES.
2361
2362GENERATE_LEGEND = YES
2363
2364# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
2365# files that are used to generate the various graphs.
2366# The default value is: YES.
2367# This tag requires that the tag HAVE_DOT is set to YES.
2368
2369DOT_CLEANUP = YES
diff --git a/doc-icon.png b/doc-icon.png
new file mode 100644
index 000000000..420b1546f
--- /dev/null
+++ b/doc-icon.png
Binary files differ
diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp
index 46781defa..6ac5c5dc5 100644
--- a/src/citra/citra.cpp
+++ b/src/citra/citra.cpp
@@ -34,7 +34,7 @@ int __cdecl main(int argc, char **argv) {
34 return -1; 34 return -1;
35 } 35 }
36 36
37 while(true) { 37 while (emu_window->IsOpen()) {
38 Core::RunLoop(); 38 Core::RunLoop();
39 } 39 }
40 40
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 1d5e9c717..03a0ce606 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -55,9 +55,14 @@ void Config::ReadControls() {
55 Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT); 55 Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT);
56} 56}
57 57
58void Config::ReadData() {
59 Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true);
60}
61
58void Config::Reload() { 62void Config::Reload() {
59 LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file); 63 LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file);
60 ReadControls(); 64 ReadControls();
65 ReadData();
61} 66}
62 67
63Config::~Config() { 68Config::~Config() {
diff --git a/src/citra/config.h b/src/citra/config.h
index de0570b42..c4fac2459 100644
--- a/src/citra/config.h
+++ b/src/citra/config.h
@@ -16,6 +16,7 @@ class Config {
16 16
17 bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true); 17 bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true);
18 void ReadControls(); 18 void ReadControls();
19 void ReadData();
19public: 20public:
20 Config(); 21 Config();
21 ~Config(); 22 ~Config();
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h
index 11b985e1b..e7e45f4a9 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -25,6 +25,9 @@ pad_sup =
25pad_sdown = 25pad_sdown =
26pad_sleft = 26pad_sleft =
27pad_sright = 27pad_sright =
28
29[Data Storage]
30use_virtual_sd =
28)"; 31)";
29 32
30} 33}
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp
index 6cdba2b87..0c774bbc5 100644
--- a/src/citra/emu_window/emu_window_glfw.cpp
+++ b/src/citra/emu_window/emu_window_glfw.cpp
@@ -29,6 +29,11 @@ void EmuWindow_GLFW::OnKeyEvent(GLFWwindow* win, int key, int scancode, int acti
29 HID_User::PadUpdateComplete(); 29 HID_User::PadUpdateComplete();
30} 30}
31 31
32/// Whether the window is still open, and a close request hasn't yet been sent
33const bool EmuWindow_GLFW::IsOpen() {
34 return glfwWindowShouldClose(m_render_window) == 0;
35}
36
32/// EmuWindow_GLFW constructor 37/// EmuWindow_GLFW constructor
33EmuWindow_GLFW::EmuWindow_GLFW() { 38EmuWindow_GLFW::EmuWindow_GLFW() {
34 keyboard_id = KeyMap::NewDeviceId(); 39 keyboard_id = KeyMap::NewDeviceId();
diff --git a/src/citra/emu_window/emu_window_glfw.h b/src/citra/emu_window/emu_window_glfw.h
index d38a11c2c..7c3072145 100644
--- a/src/citra/emu_window/emu_window_glfw.h
+++ b/src/citra/emu_window/emu_window_glfw.h
@@ -14,19 +14,22 @@ public:
14 ~EmuWindow_GLFW(); 14 ~EmuWindow_GLFW();
15 15
16 /// Swap buffers to display the next frame 16 /// Swap buffers to display the next frame
17 void SwapBuffers(); 17 void SwapBuffers() override;
18 18
19 /// Polls window events 19 /// Polls window events
20 void PollEvents(); 20 void PollEvents() override;
21 21
22 /// Makes the graphics context current for the caller thread 22 /// Makes the graphics context current for the caller thread
23 void MakeCurrent(); 23 void MakeCurrent() override;
24 24
25 /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread 25 /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
26 void DoneCurrent(); 26 void DoneCurrent() override;
27 27
28 static void OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods); 28 static void OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods);
29 29
30 /// Whether the window is still open, and a close request hasn't yet been sent
31 const bool IsOpen();
32
30 void ReloadSetKeymaps() override; 33 void ReloadSetKeymaps() override;
31 34
32private: 35private:
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 0430aa1ed..8f3799351 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -90,10 +90,10 @@ public:
90 parent_ = parent; 90 parent_ = parent;
91 } 91 }
92 92
93 void paintEvent(QPaintEvent* ev) 93 void paintEvent(QPaintEvent* ev) override
94 { 94 {
95 } 95 }
96 void resizeEvent(QResizeEvent* ev) { 96 void resizeEvent(QResizeEvent* ev) override {
97 parent_->SetClientAreaWidth(size().width()); 97 parent_->SetClientAreaWidth(size().width());
98 parent_->SetClientAreaHeight(size().height()); 98 parent_->SetClientAreaHeight(size().height());
99 } 99 }
diff --git a/src/citra_qt/bootmanager.hxx b/src/citra_qt/bootmanager.hxx
index 816ffed2e..f8afc403e 100644
--- a/src/citra_qt/bootmanager.hxx
+++ b/src/citra_qt/bootmanager.hxx
@@ -25,7 +25,7 @@ public:
25 * 25 *
26 * @warning Only call when not running! 26 * @warning Only call when not running!
27 */ 27 */
28 void run(); 28 void run() override;
29 29
30 /** 30 /**
31 * Allow the CPU to process a single instruction (if cpu is not running) 31 * Allow the CPU to process a single instruction (if cpu is not running)
@@ -89,13 +89,13 @@ public:
89 GRenderWindow(QWidget* parent = NULL); 89 GRenderWindow(QWidget* parent = NULL);
90 ~GRenderWindow(); 90 ~GRenderWindow();
91 91
92 void closeEvent(QCloseEvent*); 92 void closeEvent(QCloseEvent*) override;
93 93
94 // EmuWindow implementation 94 // EmuWindow implementation
95 void SwapBuffers(); 95 void SwapBuffers() override;
96 void MakeCurrent(); 96 void MakeCurrent() override;
97 void DoneCurrent(); 97 void DoneCurrent() override;
98 void PollEvents(); 98 void PollEvents() override;
99 99
100 void BackupGeometry(); 100 void BackupGeometry();
101 void RestoreGeometry(); 101 void RestoreGeometry();
@@ -104,8 +104,8 @@ public:
104 104
105 EmuThread& GetEmuThread(); 105 EmuThread& GetEmuThread();
106 106
107 void keyPressEvent(QKeyEvent* event); 107 void keyPressEvent(QKeyEvent* event) override;
108 void keyReleaseEvent(QKeyEvent* event); 108 void keyReleaseEvent(QKeyEvent* event) override;
109 109
110 void ReloadSetKeymaps() override; 110 void ReloadSetKeymaps() override;
111 111
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index 1b116edc5..0c4f75a96 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -64,12 +64,26 @@ void Config::SaveControls() {
64 qt_config->endGroup(); 64 qt_config->endGroup();
65} 65}
66 66
67void Config::ReadData() {
68 qt_config->beginGroup("Data Storage");
69 Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
70 qt_config->endGroup();
71}
72
73void Config::SaveData() {
74 qt_config->beginGroup("Data Storage");
75 qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd);
76 qt_config->endGroup();
77}
78
67void Config::Reload() { 79void Config::Reload() {
68 ReadControls(); 80 ReadControls();
81 ReadData();
69} 82}
70 83
71void Config::Save() { 84void Config::Save() {
72 SaveControls(); 85 SaveControls();
86 SaveData();
73} 87}
74 88
75Config::~Config() { 89Config::~Config() {
diff --git a/src/citra_qt/config.h b/src/citra_qt/config.h
index ae390be6b..74c9ff11d 100644
--- a/src/citra_qt/config.h
+++ b/src/citra_qt/config.h
@@ -14,6 +14,9 @@ class Config {
14 14
15 void ReadControls(); 15 void ReadControls();
16 void SaveControls(); 16 void SaveControls();
17
18 void ReadData();
19 void SaveData();
17public: 20public:
18 Config(); 21 Config();
19 ~Config(); 22 ~Config();
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp
index 856baf63d..2ee877743 100644
--- a/src/citra_qt/debugger/disassembler.cpp
+++ b/src/citra_qt/debugger/disassembler.cpp
@@ -9,7 +9,7 @@
9#include "core/core.h" 9#include "core/core.h"
10#include "common/break_points.h" 10#include "common/break_points.h"
11#include "common/symbols.h" 11#include "common/symbols.h"
12#include "core/arm/interpreter/armdefs.h" 12#include "core/arm/skyeye_common/armdefs.h"
13#include "core/arm/disassembler/arm_disasm.h" 13#include "core/arm/disassembler/arm_disasm.h"
14 14
15DisassemblerModel::DisassemblerModel(QObject* parent) : QAbstractItemModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) { 15DisassemblerModel::DisassemblerModel(QObject* parent) : QAbstractItemModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) {
diff --git a/src/citra_qt/debugger/graphics_cmdlists.hxx b/src/citra_qt/debugger/graphics_cmdlists.hxx
index 479ef0326..1523e724f 100644
--- a/src/citra_qt/debugger/graphics_cmdlists.hxx
+++ b/src/citra_qt/debugger/graphics_cmdlists.hxx
@@ -17,7 +17,7 @@ class GPUCommandListModel : public QAbstractListModel
17public: 17public:
18 GPUCommandListModel(QObject* parent); 18 GPUCommandListModel(QObject* parent);
19 19
20 int columnCount(const QModelIndex& parent = QModelIndex()) const; 20 int columnCount(const QModelIndex& parent = QModelIndex()) const override;
21 int rowCount(const QModelIndex& parent = QModelIndex()) const override; 21 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
22 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; 22 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
23 23
diff --git a/src/citra_qt/main.hxx b/src/citra_qt/main.hxx
index a0b41f5f4..b1b40df46 100644
--- a/src/citra_qt/main.hxx
+++ b/src/citra_qt/main.hxx
@@ -32,7 +32,7 @@ public:
32private: 32private:
33 void BootGame(std::string filename); 33 void BootGame(std::string filename);
34 34
35 void closeEvent(QCloseEvent* event); 35 void closeEvent(QCloseEvent* event) override;
36 36
37private slots: 37private slots:
38 void OnStartGame(); 38 void OnStartGame();
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index b6f0179c6..9e02210f9 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -68,7 +68,7 @@
68 * u32 hex; 68 * u32 hex;
69 * 69 *
70 * BitField<0,7,u32> first_seven_bits; // unsigned 70 * BitField<0,7,u32> first_seven_bits; // unsigned
71 * BitField<7,8,32> next_eight_bits; // unsigned 71 * BitField<7,8,u32> next_eight_bits; // unsigned
72 * BitField<3,15,s32> some_signed_fields; // signed 72 * BitField<3,15,s32> some_signed_fields; // signed
73 * }; 73 * };
74 * 74 *
diff --git a/src/common/common_types.h b/src/common/common_types.h
index 00fde828d..7ce6b2240 100644
--- a/src/common/common_types.h
+++ b/src/common/common_types.h
@@ -25,42 +25,21 @@
25#pragma once 25#pragma once
26 26
27#include <cmath> 27#include <cmath>
28#include <cstdint>
28#include <xmmintrin.h> // data_types__m128.cpp 29#include <xmmintrin.h> // data_types__m128.cpp
29 30
30#ifdef _WIN32 31typedef std::uint8_t u8; ///< 8-bit unsigned byte
32typedef std::uint16_t u16; ///< 16-bit unsigned short
33typedef std::uint32_t u32; ///< 32-bit unsigned word
34typedef std::uint64_t u64; ///< 64-bit unsigned int
31 35
32#include <tchar.h> 36typedef std::int8_t s8; ///< 8-bit signed byte
37typedef std::int16_t s16; ///< 16-bit signed short
38typedef std::int32_t s32; ///< 32-bit signed word
39typedef std::int64_t s64; ///< 64-bit signed int
33 40
34typedef unsigned __int8 u8; ///< 8-bit unsigned byte 41typedef float f32; ///< 32-bit floating point
35typedef unsigned __int16 u16; ///< 16-bit unsigned short 42typedef double f64; ///< 64-bit floating point
36typedef unsigned __int32 u32; ///< 32-bit unsigned word
37typedef unsigned __int64 u64; ///< 64-bit unsigned int
38
39typedef signed __int8 s8; ///< 8-bit signed byte
40typedef signed __int16 s16; ///< 16-bit signed short
41typedef signed __int32 s32; ///< 32-bit signed word
42typedef signed __int64 s64; ///< 64-bit signed int
43
44#else
45
46typedef unsigned char u8; ///< 8-bit unsigned byte
47typedef unsigned short u16; ///< 16-bit unsigned short
48typedef unsigned int u32; ///< 32-bit unsigned word
49typedef unsigned long long u64; ///< 64-bit unsigned int
50
51typedef signed char s8; ///< 8-bit signed byte
52typedef signed short s16; ///< 16-bit signed short
53typedef signed int s32; ///< 32-bit signed word
54typedef signed long long s64; ///< 64-bit signed int
55
56// For using windows lock code
57#define TCHAR char
58#define LONG int
59
60#endif // _WIN32
61
62typedef float f32; ///< 32-bit floating point
63typedef double f64; ///< 64-bit floating point
64 43
65#include "common/common.h" 44#include "common/common.h"
66 45
diff --git a/src/common/console_listener.h b/src/common/console_listener.h
index 3c0e420c6..ebd90a105 100644
--- a/src/common/console_listener.h
+++ b/src/common/console_listener.h
@@ -26,7 +26,7 @@ public:
26#ifdef _WIN32 26#ifdef _WIN32
27 COORD GetCoordinates(int BytesRead, int BufferWidth); 27 COORD GetCoordinates(int BytesRead, int BufferWidth);
28#endif 28#endif
29 void Log(LogTypes::LOG_LEVELS, const char *Text); 29 void Log(LogTypes::LOG_LEVELS, const char *Text) override;
30 void ClearScreen(bool Cursor = true); 30 void ClearScreen(bool Cursor = true);
31 31
32private: 32private:
diff --git a/src/common/emu_window.h b/src/common/emu_window.h
index 34cecb40b..4d09acb8b 100644
--- a/src/common/emu_window.h
+++ b/src/common/emu_window.h
@@ -6,7 +6,7 @@
6 6
7#include "common/common.h" 7#include "common/common.h"
8#include "common/scm_rev.h" 8#include "common/scm_rev.h"
9 9#include "common/string_util.h"
10#include "common/key_map.h" 10#include "common/key_map.h"
11 11
12// Abstraction class used to provide an interface between emulation code and the frontend (e.g. SDL, 12// Abstraction class used to provide an interface between emulation code and the frontend (e.g. SDL,
@@ -75,11 +75,11 @@ public:
75 } 75 }
76 76
77protected: 77protected:
78 EmuWindow() : m_client_area_width(640), m_client_area_height(480) { 78 EmuWindow():
79 char window_title[255]; 79 m_client_area_width(640),
80 sprintf(window_title, "Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); 80 m_client_area_height(480),
81 m_window_title = window_title; 81 m_window_title(Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc))
82 } 82 {}
83 virtual ~EmuWindow() {} 83 virtual ~EmuWindow() {}
84 84
85 std::string m_window_title; ///< Current window title, should be used by window impl. 85 std::string m_window_title; ///< Current window title, should be used by window impl.
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 78a642599..35da07306 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -13,6 +13,7 @@
13#include <commdlg.h> // for GetSaveFileName 13#include <commdlg.h> // for GetSaveFileName
14#include <io.h> 14#include <io.h>
15#include <direct.h> // getcwd 15#include <direct.h> // getcwd
16#include <tchar.h>
16#else 17#else
17#include <sys/param.h> 18#include <sys/param.h>
18#include <dirent.h> 19#include <dirent.h>
@@ -190,8 +191,10 @@ bool CreateFullPath(const std::string &fullPath)
190 191
191 // Include the '/' so the first call is CreateDir("/") rather than CreateDir("") 192 // Include the '/' so the first call is CreateDir("/") rather than CreateDir("")
192 std::string const subPath(fullPath.substr(0, position + 1)); 193 std::string const subPath(fullPath.substr(0, position + 1));
193 if (!FileUtil::IsDirectory(subPath)) 194 if (!FileUtil::IsDirectory(subPath) && !FileUtil::CreateDir(subPath)) {
194 FileUtil::CreateDir(subPath); 195 ERROR_LOG(COMMON, "CreateFullPath: directory creation failed");
196 return false;
197 }
195 198
196 // A safety check 199 // A safety check
197 panicCounter--; 200 panicCounter--;
diff --git a/src/common/log_manager.h b/src/common/log_manager.h
index ce62d0361..de1d16ee5 100644
--- a/src/common/log_manager.h
+++ b/src/common/log_manager.h
@@ -30,7 +30,7 @@ class FileLogListener : public LogListener
30public: 30public:
31 FileLogListener(const char *filename); 31 FileLogListener(const char *filename);
32 32
33 void Log(LogTypes::LOG_LEVELS, const char *msg); 33 void Log(LogTypes::LOG_LEVELS, const char *msg) override;
34 34
35 bool IsValid() { return !m_logfile.fail(); } 35 bool IsValid() { return !m_logfile.fail(); }
36 bool IsEnabled() const { return m_enable; } 36 bool IsEnabled() const { return m_enable; }
@@ -47,7 +47,7 @@ private:
47class DebuggerLogListener : public LogListener 47class DebuggerLogListener : public LogListener
48{ 48{
49public: 49public:
50 void Log(LogTypes::LOG_LEVELS, const char *msg); 50 void Log(LogTypes::LOG_LEVELS, const char *msg) override;
51}; 51};
52 52
53class LogContainer 53class LogContainer
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 9199e30bc..61f0939c4 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -186,9 +186,9 @@ bool TryParse(const std::string &str, u32 *const output)
186 186
187bool TryParse(const std::string &str, bool *const output) 187bool TryParse(const std::string &str, bool *const output)
188{ 188{
189 if ("1" == str || !strcasecmp("true", str.c_str())) 189 if ("1" == str || "true" == ToLower(str))
190 *output = true; 190 *output = true;
191 else if ("0" == str || !strcasecmp("false", str.c_str())) 191 else if ("0" == str || "false" == ToLower(str))
192 *output = false; 192 *output = false;
193 else 193 else
194 return false; 194 return false;
@@ -196,13 +196,6 @@ bool TryParse(const std::string &str, bool *const output)
196 return true; 196 return true;
197} 197}
198 198
199std::string StringFromInt(int value)
200{
201 char temp[16];
202 sprintf(temp, "%i", value);
203 return temp;
204}
205
206std::string StringFromBool(bool value) 199std::string StringFromBool(bool value)
207{ 200{
208 return value ? "True" : "False"; 201 return value ? "True" : "False";
diff --git a/src/common/string_util.h b/src/common/string_util.h
index 16ce39bc1..a41ccc691 100644
--- a/src/common/string_util.h
+++ b/src/common/string_util.h
@@ -54,7 +54,6 @@ std::string ThousandSeparate(I value, int spaces = 0)
54 return oss.str(); 54 return oss.str();
55} 55}
56 56
57std::string StringFromInt(int value);
58std::string StringFromBool(bool value); 57std::string StringFromBool(bool value);
59 58
60bool TryParse(const std::string &str, bool *output); 59bool TryParse(const std::string &str, bool *output);
diff --git a/src/common/swap.h b/src/common/swap.h
index 123019fd1..4f8f39efb 100644
--- a/src/common/swap.h
+++ b/src/common/swap.h
@@ -85,7 +85,6 @@ public:
85 return *this; 85 return *this;
86 } 86 }
87 87
88 operator long() const { return (long)swap(); }
89 operator s8() const { return (s8)swap(); } 88 operator s8() const { return (s8)swap(); }
90 operator u8() const { return (u8)swap(); } 89 operator u8() const { return (u8)swap(); }
91 operator s16() const { return (s16)swap(); } 90 operator s16() const { return (s16)swap(); }
diff --git a/src/common/timer.cpp b/src/common/timer.cpp
index f8e1fadca..ded4a344e 100644
--- a/src/common/timer.cpp
+++ b/src/common/timer.cpp
@@ -169,7 +169,6 @@ std::string Timer::GetTimeFormatted()
169{ 169{
170 time_t sysTime; 170 time_t sysTime;
171 struct tm * gmTime; 171 struct tm * gmTime;
172 char formattedTime[13];
173 char tmp[13]; 172 char tmp[13];
174 173
175 time(&sysTime); 174 time(&sysTime);
@@ -181,14 +180,12 @@ std::string Timer::GetTimeFormatted()
181#ifdef _WIN32 180#ifdef _WIN32
182 struct timeb tp; 181 struct timeb tp;
183 (void)::ftime(&tp); 182 (void)::ftime(&tp);
184 sprintf(formattedTime, "%s:%03i", tmp, tp.millitm); 183 return StringFromFormat("%s:%03i", tmp, tp.millitm);
185#else 184#else
186 struct timeval t; 185 struct timeval t;
187 (void)gettimeofday(&t, NULL); 186 (void)gettimeofday(&t, NULL);
188 sprintf(formattedTime, "%s:%03d", tmp, (int)(t.tv_usec / 1000)); 187 return StringFromFormat("%s:%03d", tmp, (int)(t.tv_usec / 1000));
189#endif 188#endif
190
191 return std::string(formattedTime);
192} 189}
193 190
194// Returns a timestamp with decimals for precise time comparisons 191// Returns a timestamp with decimals for precise time comparisons
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 06df9a677..aefbe3375 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,27 +1,22 @@
1set(SRCS 1set(SRCS
2 arm/disassembler/arm_disasm.cpp 2 arm/disassembler/arm_disasm.cpp
3 arm/disassembler/load_symbol_map.cpp 3 arm/disassembler/load_symbol_map.cpp
4 arm/interpreter/mmu/arm1176jzf_s_mmu.cpp 4 arm/dyncom/arm_dyncom.cpp
5 arm/interpreter/mmu/cache.cpp 5 arm/dyncom/arm_dyncom_dec.cpp
6 arm/interpreter/mmu/maverick.cpp 6 arm/dyncom/arm_dyncom_interpreter.cpp
7 arm/interpreter/mmu/rb.cpp 7 arm/dyncom/arm_dyncom_run.cpp
8 arm/interpreter/mmu/sa_mmu.cpp 8 arm/dyncom/arm_dyncom_thumb.cpp
9 arm/interpreter/mmu/tlb.cpp
10 arm/interpreter/mmu/wb.cpp
11 arm/interpreter/mmu/xscale_copro.cpp
12 arm/interpreter/vfp/vfp.cpp
13 arm/interpreter/vfp/vfpdouble.cpp
14 arm/interpreter/vfp/vfpinstr.cpp
15 arm/interpreter/vfp/vfpsingle.cpp
16 arm/interpreter/arm_interpreter.cpp 9 arm/interpreter/arm_interpreter.cpp
17 arm/interpreter/armcopro.cpp 10 arm/interpreter/armcopro.cpp
18 arm/interpreter/armemu.cpp 11 arm/interpreter/armemu.cpp
19 arm/interpreter/arminit.cpp 12 arm/interpreter/arminit.cpp
20 arm/interpreter/armmmu.cpp
21 arm/interpreter/armos.cpp
22 arm/interpreter/armsupp.cpp 13 arm/interpreter/armsupp.cpp
23 arm/interpreter/armvirt.cpp 14 arm/interpreter/armvirt.cpp
24 arm/interpreter/thumbemu.cpp 15 arm/interpreter/thumbemu.cpp
16 arm/skyeye_common/vfp/vfp.cpp
17 arm/skyeye_common/vfp/vfpdouble.cpp
18 arm/skyeye_common/vfp/vfpinstr.cpp
19 arm/skyeye_common/vfp/vfpsingle.cpp
25 file_sys/archive_romfs.cpp 20 file_sys/archive_romfs.cpp
26 file_sys/archive_sdmc.cpp 21 file_sys/archive_sdmc.cpp
27 file_sys/file_romfs.cpp 22 file_sys/file_romfs.cpp
@@ -43,7 +38,6 @@ set(SRCS
43 hle/service/service.cpp 38 hle/service/service.cpp
44 hle/service/srv.cpp 39 hle/service/srv.cpp
45 hle/config_mem.cpp 40 hle/config_mem.cpp
46 hle/coprocessor.cpp
47 hle/hle.cpp 41 hle/hle.cpp
48 hle/svc.cpp 42 hle/svc.cpp
49 hw/gpu.cpp 43 hw/gpu.cpp
@@ -63,23 +57,23 @@ set(SRCS
63set(HEADERS 57set(HEADERS
64 arm/disassembler/arm_disasm.h 58 arm/disassembler/arm_disasm.h
65 arm/disassembler/load_symbol_map.h 59 arm/disassembler/load_symbol_map.h
66 arm/interpreter/mmu/arm1176jzf_s_mmu.h 60 arm/dyncom/arm_dyncom.h
67 arm/interpreter/mmu/cache.h 61 arm/dyncom/arm_dyncom_dec.h
68 arm/interpreter/mmu/rb.h 62 arm/dyncom/arm_dyncom_interpreter.h
69 arm/interpreter/mmu/sa_mmu.h 63 arm/dyncom/arm_dyncom_run.h
70 arm/interpreter/mmu/tlb.h 64 arm/dyncom/arm_dyncom_thumb.h
71 arm/interpreter/mmu/wb.h
72 arm/interpreter/vfp/asm_vfp.h
73 arm/interpreter/vfp/vfp.h
74 arm/interpreter/vfp/vfp_helper.h
75 arm/interpreter/arm_interpreter.h 65 arm/interpreter/arm_interpreter.h
76 arm/interpreter/arm_regformat.h 66 arm/skyeye_common/arm_regformat.h
77 arm/interpreter/armcpu.h 67 arm/skyeye_common/armcpu.h
78 arm/interpreter/armdefs.h 68 arm/skyeye_common/armdefs.h
79 arm/interpreter/armemu.h 69 arm/skyeye_common/armemu.h
80 arm/interpreter/armmmu.h 70 arm/skyeye_common/armmmu.h
81 arm/interpreter/armos.h 71 arm/skyeye_common/armos.h
82 arm/interpreter/skyeye_defs.h 72 arm/skyeye_common/skyeye_defs.h
73 arm/skyeye_common/skyeye_types.h
74 arm/skyeye_common/vfp/asm_vfp.h
75 arm/skyeye_common/vfp/vfp.h
76 arm/skyeye_common/vfp/vfp_helper.h
83 arm/arm_interface.h 77 arm/arm_interface.h
84 file_sys/archive.h 78 file_sys/archive.h
85 file_sys/archive_romfs.h 79 file_sys/archive_romfs.h
@@ -105,7 +99,6 @@ set(HEADERS
105 hle/service/service.h 99 hle/service/service.h
106 hle/service/srv.h 100 hle/service/srv.h
107 hle/config_mem.h 101 hle/config_mem.h
108 hle/coprocessor.h
109 hle/function_wrappers.h 102 hle/function_wrappers.h
110 hle/hle.h 103 hle/hle.h
111 hle/svc.h 104 hle/svc.h
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
new file mode 100644
index 000000000..669b612fc
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -0,0 +1,163 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "core/arm/skyeye_common/armcpu.h"
6#include "core/arm/skyeye_common/armemu.h"
7#include "core/arm/skyeye_common/vfp/vfp.h"
8
9#include "core/arm/dyncom/arm_dyncom.h"
10#include "core/arm/dyncom/arm_dyncom_interpreter.h"
11
12const static cpu_config_t s_arm11_cpu_info = {
13 "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
14};
15
16ARM_DynCom::ARM_DynCom() : ticks(0) {
17 state = std::unique_ptr<ARMul_State>(new ARMul_State);
18
19 ARMul_EmulateInit();
20 memset(state.get(), 0, sizeof(ARMul_State));
21
22 ARMul_NewState((ARMul_State*)state.get());
23
24 state->abort_model = 0;
25 state->cpu = (cpu_config_t*)&s_arm11_cpu_info;
26 state->bigendSig = LOW;
27
28 ARMul_SelectProcessor(state.get(), ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop);
29 state->lateabtSig = LOW;
30
31 // Reset the core to initial state
32 ARMul_CoProInit(state.get());
33 ARMul_Reset(state.get());
34 state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext
35 state->Emulate = 3;
36
37 state->pc = state->Reg[15] = 0x00000000;
38 state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack
39 state->servaddr = 0xFFFF0000;
40 state->NirqSig = HIGH;
41
42 VFPInit(state.get()); // Initialize the VFP
43
44 ARMul_EmulateInit();
45}
46
47ARM_DynCom::~ARM_DynCom() {
48}
49
50/**
51 * Set the Program Counter to an address
52 * @param addr Address to set PC to
53 */
54void ARM_DynCom::SetPC(u32 pc) {
55 state->pc = state->Reg[15] = pc;
56}
57
58/*
59 * Get the current Program Counter
60 * @return Returns current PC
61 */
62u32 ARM_DynCom::GetPC() const {
63 return state->pc;
64}
65
66/**
67 * Get an ARM register
68 * @param index Register index (0-15)
69 * @return Returns the value in the register
70 */
71u32 ARM_DynCom::GetReg(int index) const {
72 return state->Reg[index];
73}
74
75/**
76 * Set an ARM register
77 * @param index Register index (0-15)
78 * @param value Value to set register to
79 */
80void ARM_DynCom::SetReg(int index, u32 value) {
81 state->Reg[index] = value;
82}
83
84/**
85 * Get the current CPSR register
86 * @return Returns the value of the CPSR register
87 */
88u32 ARM_DynCom::GetCPSR() const {
89 return state->Cpsr;
90}
91
92/**
93 * Set the current CPSR register
94 * @param cpsr Value to set CPSR to
95 */
96void ARM_DynCom::SetCPSR(u32 cpsr) {
97 state->Cpsr = cpsr;
98}
99
100/**
101 * Returns the number of clock ticks since the last reset
102 * @return Returns number of clock ticks
103 */
104u64 ARM_DynCom::GetTicks() const {
105 return ticks;
106}
107
108/**
109 * Executes the given number of instructions
110 * @param num_instructions Number of instructions to executes
111 */
112void ARM_DynCom::ExecuteInstructions(int num_instructions) {
113 ticks += num_instructions;
114 state->NumInstrsToExecute = num_instructions;
115 InterpreterMainLoop(state.get());
116}
117
118/**
119 * Saves the current CPU context
120 * @param ctx Thread context to save
121 * @todo Do we need to save Reg[15] and NextInstr?
122 */
123void ARM_DynCom::SaveContext(ThreadContext& ctx) {
124 memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
125 memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
126
127 ctx.sp = state->Reg[13];
128 ctx.lr = state->Reg[14];
129 ctx.pc = state->pc;
130 ctx.cpsr = state->Cpsr;
131
132 ctx.fpscr = state->VFP[1];
133 ctx.fpexc = state->VFP[2];
134
135 ctx.reg_15 = state->Reg[15];
136 ctx.mode = state->NextInstr;
137}
138
139/**
140 * Loads a CPU context
141 * @param ctx Thread context to load
142 * @param Do we need to load Reg[15] and NextInstr?
143 */
144void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
145 memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));
146 memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers));
147
148 state->Reg[13] = ctx.sp;
149 state->Reg[14] = ctx.lr;
150 state->pc = ctx.pc;
151 state->Cpsr = ctx.cpsr;
152
153 state->VFP[1] = ctx.fpscr;
154 state->VFP[2] = ctx.fpexc;
155
156 state->Reg[15] = ctx.reg_15;
157 state->NextInstr = ctx.mode;
158}
159
160/// Prepare core for thread reschedule (if needed to correctly handle state)
161void ARM_DynCom::PrepareReschedule() {
162 state->NumInstrsToExecute = 0;
163}
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
new file mode 100644
index 000000000..1f8cd3a3a
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -0,0 +1,90 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8
9#include "common/common_types.h"
10
11#include "core/arm/arm_interface.h"
12#include "core/arm/skyeye_common/armdefs.h"
13
14class ARM_DynCom final : virtual public ARM_Interface {
15public:
16
17 ARM_DynCom();
18 ~ARM_DynCom();
19
20 /**
21 * Set the Program Counter to an address
22 * @param addr Address to set PC to
23 */
24 void SetPC(u32 pc) override;
25
26 /*
27 * Get the current Program Counter
28 * @return Returns current PC
29 */
30 u32 GetPC() const;
31
32 /**
33 * Get an ARM register
34 * @param index Register index (0-15)
35 * @return Returns the value in the register
36 */
37 u32 GetReg(int index) const;
38
39 /**
40 * Set an ARM register
41 * @param index Register index (0-15)
42 * @param value Value to set register to
43 */
44 void SetReg(int index, u32 value) override;
45
46 /**
47 * Get the current CPSR register
48 * @return Returns the value of the CPSR register
49 */
50 u32 GetCPSR() const;
51
52 /**
53 * Set the current CPSR register
54 * @param cpsr Value to set CPSR to
55 */
56 void SetCPSR(u32 cpsr) override;
57
58 /**
59 * Returns the number of clock ticks since the last reset
60 * @return Returns number of clock ticks
61 */
62 u64 GetTicks() const;
63
64 /**
65 * Saves the current CPU context
66 * @param ctx Thread context to save
67 */
68 void SaveContext(ThreadContext& ctx) override;
69
70 /**
71 * Loads a CPU context
72 * @param ctx Thread context to load
73 */
74 void LoadContext(const ThreadContext& ctx) override;
75
76 /// Prepare core for thread reschedule (if needed to correctly handle state)
77 void PrepareReschedule() override;
78
79 /**
80 * Executes the given number of instructions
81 * @param num_instructions Number of instructions to executes
82 */
83 void ExecuteInstructions(int num_instructions) override;
84
85private:
86
87 std::unique_ptr<ARMul_State> state;
88 u64 ticks;
89
90};
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp
new file mode 100644
index 000000000..5d174a08f
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp
@@ -0,0 +1,402 @@
1/* Copyright (C)
2* 2012 - Michael.Kang blackfin.kang@gmail.com
3* This program is free software; you can redistribute it and/or
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18/**
19* @file arm_dyncom_dec.cpp
20* @brief Some common utility for arm decoder
21* @author Michael.Kang blackfin.kang@gmail.com
22* @version 7849
23* @date 2012-03-15
24*/
25
26#include "core/arm/skyeye_common/arm_regformat.h"
27#include "core/arm/skyeye_common/armdefs.h"
28#include "core/arm/dyncom/arm_dyncom_dec.h"
29
30const ISEITEM arm_instruction[] = {
31 #define VFP_DECODE
32 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
33 #undef VFP_DECODE
34 {"srs" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000001, 16, 20, 0x0000000d, 8, 11, 0x00000005},
35 {"rfe" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000000, 20, 20, 0x00000001, 8, 11, 0x0000000a},
36 {"bkpt" , 2 , 3 , 20, 31, 0x00000e12, 4, 7, 0x00000007},
37 {"blx" , 1 , 3 , 25, 31, 0x0000007d},
38 {"cps" , 3 , 6 , 20, 31, 0x00000f10, 16, 16, 0x00000000, 5, 5, 0x00000000},
39 {"pld" , 4 , 4 , 26, 31, 0x0000003d, 24, 24, 0x00000001, 20, 22, 0x00000005, 12, 15, 0x0000000f},
40 {"setend" , 2 , 6 , 16, 31, 0x0000f101, 4, 7, 0x00000000},
41 {"clrex" , 1 , 6 , 0, 31, 0xf57ff01f},
42 {"rev16" , 2 , 6 , 16, 27, 0x000006bf, 4, 11, 0x000000fb},
43 {"usad8" , 3 , 6 , 20, 27, 0x00000078, 12, 15, 0x0000000f, 4, 7, 0x00000001},
44 {"sxtb" , 2 , 6 , 16, 27, 0x000006af, 4, 7, 0x00000007},
45 {"uxtb" , 2 , 6 , 16, 27, 0x000006ef, 4, 7, 0x00000007},
46 {"sxth" , 2 , 6 , 16, 27, 0x000006bf, 4, 7, 0x00000007},
47 {"sxtb16" , 2 , 6 , 16, 27, 0x0000068f, 4, 7, 0x00000007},
48 {"uxth" , 2 , 6 , 16, 27, 0x000006ff, 4, 7, 0x00000007},
49 {"uxtb16" , 2 , 6 , 16, 27, 0x000006cf, 4, 7, 0x00000007},
50 {"cpy" , 2 , 6 , 20, 27, 0x0000001a, 4, 11, 0x00000000},
51 {"uxtab" , 2 , 6 , 20, 27, 0x0000006e, 4, 9, 0x00000007},
52 {"ssub8" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x0000000f},
53 {"shsub8" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x0000000f},
54 {"ssubaddx" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000005},
55 {"strex" , 2 , 6 , 20, 27, 0x00000018, 4, 7, 0x00000009},
56 {"strexb" , 2 , 7 , 20, 27, 0x0000001c, 4, 7, 0x00000009},
57 {"swp" , 2 , 0 , 20, 27, 0x00000010, 4, 7, 0x00000009},
58 {"swpb" , 2 , 0 , 20, 27, 0x00000014, 4, 7, 0x00000009},
59 {"ssub16" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000007},
60 {"ssat16" , 2 , 6 , 20, 27, 0x0000006a, 4, 7, 0x00000003},
61 {"shsubaddx" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000005},
62 {"qsubaddx" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000005},
63 {"shaddsubx" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000003},
64 {"shadd8" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000009},
65 {"shadd16" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000001},
66 {"sel" , 2 , 6 , 20, 27, 0x00000068, 4, 7, 0x0000000b},
67 {"saddsubx" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000003},
68 {"sadd8" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000009},
69 {"sadd16" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000001},
70 {"shsub16" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000007},
71 {"umaal" , 2 , 6 , 20, 27, 0x00000004, 4, 7, 0x00000009},
72 {"uxtab16" , 2 , 6 , 20, 27, 0x0000006c, 4, 7, 0x00000007},
73 {"usubaddx" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000005},
74 {"usub8" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x0000000f},
75 {"usub16" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000007},
76 {"usat16" , 2 , 6 , 20, 27, 0x0000006e, 4, 7, 0x00000003},
77 {"usada8" , 2 , 6 , 20, 27, 0x00000078, 4, 7, 0x00000001},
78 {"uqsubaddx" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000005},
79 {"uqsub8" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x0000000f},
80 {"uqsub16" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000007},
81 {"uqaddsubx" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000003},
82 {"uqadd8" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000009},
83 {"uqadd16" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000001},
84 {"sxtab" , 2 , 6 , 20, 27, 0x0000006a, 4, 7, 0x00000007},
85 {"uhsubaddx" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000005},
86 {"uhsub8" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x0000000f},
87 {"uhsub16" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000007},
88 {"uhaddsubx" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000003},
89 {"uhadd8" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000009},
90 {"uhadd16" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000001},
91 {"uaddsubx" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000003},
92 {"uadd8" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000009},
93 {"uadd16" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000001},
94 {"sxtah" , 2 , 6 , 20, 27, 0x0000006b, 4, 7, 0x00000007},
95 {"sxtab16" , 2 , 6 , 20, 27, 0x00000068, 4, 7, 0x00000007},
96 {"qadd8" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000009},
97 {"bxj" , 2 , 5 , 20, 27, 0x00000012, 4, 7, 0x00000002},
98 {"clz" , 2 , 3 , 20, 27, 0x00000016, 4, 7, 0x00000001},
99 {"uxtah" , 2 , 6 , 20, 27, 0x0000006f, 4, 7, 0x00000007},
100 {"bx" , 2 , 2 , 20, 27, 0x00000012, 4, 7, 0x00000001},
101 {"rev" , 2 , 6 , 20, 27, 0x0000006b, 4, 7, 0x00000003},
102 {"blx" , 2 , 3 , 20, 27, 0x00000012, 4, 7, 0x00000003},
103 {"revsh" , 2 , 6 , 20, 27, 0x0000006f, 4, 7, 0x0000000b},
104 {"qadd" , 2 , 4 , 20, 27, 0x00000010, 4, 7, 0x00000005},
105 {"qadd16" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000001},
106 {"qaddsubx" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000003},
107 {"ldrex" , 2 , 0 , 20, 27, 0x00000019, 4, 7, 0x00000009},
108 {"qdadd" , 2 , 4 , 20, 27, 0x00000014, 4, 7, 0x00000005},
109 {"qdsub" , 2 , 4 , 20, 27, 0x00000016, 4, 7, 0x00000005},
110 {"qsub" , 2 , 4 , 20, 27, 0x00000012, 4, 7, 0x00000005},
111 {"ldrexb" , 2 , 7 , 20, 27, 0x0000001d, 4, 7, 0x00000009},
112 {"qsub8" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x0000000f},
113 {"qsub16" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000007},
114 {"smuad" , 4 , 6 , 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001},
115 {"smmul" , 4 , 6 , 20, 27, 0x00000075, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001},
116 {"smusd" , 4 , 6 , 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000001, 4, 4, 0x00000001},
117 {"smlsd" , 3 , 6 , 20, 27, 0x00000070, 6, 7, 0x00000001, 4, 4, 0x00000001},
118 {"smlsld" , 3 , 6 , 20, 27, 0x00000074, 6, 7, 0x00000001, 4, 4, 0x00000001},
119 {"smmla" , 3 , 6 , 20, 27, 0x00000075, 6, 7, 0x00000000, 4, 4, 0x00000001},
120 {"smmls" , 3 , 6 , 20, 27, 0x00000075, 6, 7, 0x00000003, 4, 4, 0x00000001},
121 {"smlald" , 3 , 6 , 20, 27, 0x00000074, 6, 7, 0x00000000, 4, 4, 0x00000001},
122 {"smlad" , 3 , 6 , 20, 27, 0x00000070, 6, 7, 0x00000000, 4, 4, 0x00000001},
123 {"smlaw" , 3 , 4 , 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000000},
124 {"smulw" , 3 , 4 , 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000002},
125 {"pkhtb" , 2 , 6 , 20, 27, 0x00000068, 4, 6, 0x00000005},
126 {"pkhbt" , 2 , 6 , 20, 27, 0x00000068, 4, 6, 0x00000001},
127 {"smul" , 3 , 4 , 20, 27, 0x00000016, 7, 7, 0x00000001, 4, 4, 0x00000000},
128 {"smlalxy" , 3 , 4 , 20, 27, 0x00000014, 7, 7, 0x00000001, 4, 4, 0x00000000},
129// {"smlal" , 2 , 4 , 21, 27, 0x00000007, 4, 7, 0x00000009},
130 {"smla" , 3 , 4 , 20, 27, 0x00000010, 7, 7, 0x00000001, 4, 4, 0x00000000},
131 {"mcrr" , 1 , 6 , 20, 27, 0x000000c4},
132 {"mrrc" , 1 , 6 , 20, 27, 0x000000c5},
133 {"cmp" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000015},
134 {"tst" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000011},
135 {"teq" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000013},
136 {"cmn" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000017},
137 {"smull" , 2 , 0 , 21, 27, 0x00000006, 4, 7, 0x00000009},
138 {"umull" , 2 , 0 , 21, 27, 0x00000004, 4, 7, 0x00000009},
139 {"umlal" , 2 , 0 , 21, 27, 0x00000005, 4, 7, 0x00000009},
140 {"smlal" , 2 , 0 , 21, 27, 0x00000007, 4, 7, 0x00000009},
141 {"mul" , 2 , 0 , 21, 27, 0x00000000, 4, 7, 0x00000009},
142 {"mla" , 2 , 0 , 21, 27, 0x00000001, 4, 7, 0x00000009},
143 {"ssat" , 2 , 6 , 21, 27, 0x00000035, 4, 5, 0x00000001},
144 {"usat" , 2 , 6 , 21, 27, 0x00000037, 4, 5, 0x00000001},
145 {"mrs" , 4 , 0 , 23, 27, 0x00000002, 20, 21, 0x00000000, 16, 19, 0x0000000f, 0, 11, 0x00000000},
146 {"msr" , 3 , 0 , 23, 27, 0x00000002, 20, 21, 0x00000002, 4, 7, 0x00000000},
147 {"and" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000000},
148 {"bic" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000e},
149 {"ldm" , 3 , 0 , 25, 27, 0x00000004, 20, 22, 0x00000005, 15, 15, 0x00000000},
150 {"eor" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000001},
151 {"add" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000004},
152 {"rsb" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000003},
153 {"rsc" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000007},
154 {"sbc" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000006},
155 {"adc" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000005},
156 {"sub" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000002},
157 {"orr" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000c},
158 {"mvn" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000f},
159 {"mov" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000d},
160 {"stm" , 2 , 0 , 25, 27, 0x00000004, 20, 22, 0x00000004},
161 {"ldm" , 4 , 0 , 25, 27, 0x00000004, 22, 22, 0x00000001, 20, 20, 0x00000001, 15, 15, 0x00000001},
162 {"ldrsh" , 3 , 2 , 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000f},
163 {"stm" , 3 , 0 , 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000000},
164 {"ldm" , 3 , 0 , 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000001},
165 {"ldrsb" , 3 , 2 , 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000d},
166 {"strd" , 3 , 4 , 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000f},
167 {"ldrh" , 3 , 0 , 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000b},
168 {"strh" , 3 , 0 , 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000b},
169 {"ldrd" , 3 , 4 , 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000d},
170 {"strt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000002},
171 {"strbt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000006},
172 {"ldrbt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000007},
173 {"ldrt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000003},
174 {"mrc" , 3 , 6 , 24, 27, 0x0000000e, 20, 20, 0x00000001, 4, 4, 0x00000001},
175 {"mcr" , 3 , 0 , 24, 27, 0x0000000e, 20, 20, 0x00000000, 4, 4, 0x00000001},
176 {"msr" , 2 , 0 , 23, 27, 0x00000006, 20, 21, 0x00000002},
177 {"ldrb" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000001},
178 {"strb" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000000},
179 {"ldr" , 4 , 0 , 28, 31, 0x0000000e, 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001},
180 {"ldrcond" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001},
181 {"str" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000000},
182 {"cdp" , 2 , 0 , 24, 27, 0x0000000e, 4, 4, 0x00000000},
183 {"stc" , 2 , 0 , 25, 27, 0x00000006, 20, 20, 0x00000000},
184 {"ldc" , 2 , 0 , 25, 27, 0x00000006, 20, 20, 0x00000001},
185 {"swi" , 1 , 0 , 24, 27, 0x0000000f},
186 {"bbl" , 1 , 0 , 25, 27, 0x00000005},
187};
188
189const ISEITEM arm_exclusion_code[] = {
190 #define VFP_DECODE_EXCLUSION
191 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
192 #undef VFP_DECODE_EXCLUSION
193 {"srs" , 0 , 6 , 0},
194 {"rfe" , 0 , 6 , 0},
195 {"bkpt" , 0 , 3 , 0},
196 {"blx" , 0 , 3 , 0},
197 {"cps" , 0 , 6 , 0},
198 {"pld" , 0 , 4 , 0},
199 {"setend" , 0 , 6 , 0},
200 {"clrex" , 0 , 6 , 0},
201 {"rev16" , 0 , 6 , 0},
202 {"usad8" , 0 , 6 , 0},
203 {"sxtb" , 0 , 6 , 0},
204 {"uxtb" , 0 , 6 , 0},
205 {"sxth" , 0 , 6 , 0},
206 {"sxtb16" , 0 , 6 , 0},
207 {"uxth" , 0 , 6 , 0},
208 {"uxtb16" , 0 , 6 , 0},
209 {"cpy" , 0 , 6 , 0},
210 {"uxtab" , 0 , 6 , 0},
211 {"ssub8" , 0 , 6 , 0},
212 {"shsub8" , 0 , 6 , 0},
213 {"ssubaddx" , 0 , 6 , 0},
214 {"strex" , 0 , 6 , 0},
215 {"strexb" , 0 , 7 , 0},
216 {"swp" , 0 , 0 , 0},
217 {"swpb" , 0 , 0 , 0},
218 {"ssub16" , 0 , 6 , 0},
219 {"ssat16" , 0 , 6 , 0},
220 {"shsubaddx" , 0 , 6 , 0},
221 {"qsubaddx" , 0 , 6 , 0},
222 {"shaddsubx" , 0 , 6 , 0},
223 {"shadd8" , 0 , 6 , 0},
224 {"shadd16" , 0 , 6 , 0},
225 {"sel" , 0 , 6 , 0},
226 {"saddsubx" , 0 , 6 , 0},
227 {"sadd8" , 0 , 6 , 0},
228 {"sadd16" , 0 , 6 , 0},
229 {"shsub16" , 0 , 6 , 0},
230 {"umaal" , 0 , 6 , 0},
231 {"uxtab16" , 0 , 6 , 0},
232 {"usubaddx" , 0 , 6 , 0},
233 {"usub8" , 0 , 6 , 0},
234 {"usub16" , 0 , 6 , 0},
235 {"usat16" , 0 , 6 , 0},
236 {"usada8" , 0 , 6 , 0},
237 {"uqsubaddx" , 0 , 6 , 0},
238 {"uqsub8" , 0 , 6 , 0},
239 {"uqsub16" , 0 , 6 , 0},
240 {"uqaddsubx" , 0 , 6 , 0},
241 {"uqadd8" , 0 , 6 , 0},
242 {"uqadd16" , 0 , 6 , 0},
243 {"sxtab" , 0 , 6 , 0},
244 {"uhsubaddx" , 0 , 6 , 0},
245 {"uhsub8" , 0 , 6 , 0},
246 {"uhsub16" , 0 , 6 , 0},
247 {"uhaddsubx" , 0 , 6 , 0},
248 {"uhadd8" , 0 , 6 , 0},
249 {"uhadd16" , 0 , 6 , 0},
250 {"uaddsubx" , 0 , 6 , 0},
251 {"uadd8" , 0 , 6 , 0},
252 {"uadd16" , 0 , 6 , 0},
253 {"sxtah" , 0 , 6 , 0},
254 {"sxtab16" , 0 , 6 , 0},
255 {"qadd8" , 0 , 6 , 0},
256 {"bxj" , 0 , 5 , 0},
257 {"clz" , 0 , 3 , 0},
258 {"uxtah" , 0 , 6 , 0},
259 {"bx" , 0 , 2 , 0},
260 {"rev" , 0 , 6 , 0},
261 {"blx" , 0 , 3 , 0},
262 {"revsh" , 0 , 6 , 0},
263 {"qadd" , 0 , 4 , 0},
264 {"qadd16" , 0 , 6 , 0},
265 {"qaddsubx" , 0 , 6 , 0},
266 {"ldrex" , 0 , 0 , 0},
267 {"qdadd" , 0 , 4 , 0},
268 {"qdsub" , 0 , 4 , 0},
269 {"qsub" , 0 , 4 , 0},
270 {"ldrexb" , 0 , 7 , 0},
271 {"qsub8" , 0 , 6 , 0},
272 {"qsub16" , 0 , 6 , 0},
273 {"smuad" , 0 , 6 , 0},
274 {"smmul" , 0 , 6 , 0},
275 {"smusd" , 0 , 6 , 0},
276 {"smlsd" , 0 , 6 , 0},
277 {"smlsld" , 0 , 6 , 0},
278 {"smmla" , 0 , 6 , 0},
279 {"smmls" , 0 , 6 , 0},
280 {"smlald" , 0 , 6 , 0},
281 {"smlad" , 0 , 6 , 0},
282 {"smlaw" , 0 , 4 , 0},
283 {"smulw" , 0 , 4 , 0},
284 {"pkhtb" , 0 , 6 , 0},
285 {"pkhbt" , 0 , 6 , 0},
286 {"smul" , 0 , 4 , 0},
287 {"smlal" , 0 , 4 , 0},
288 {"smla" , 0 , 4 , 0},
289 {"mcrr" , 0 , 6 , 0},
290 {"mrrc" , 0 , 6 , 0},
291 {"cmp" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
292 {"tst" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
293 {"teq" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
294 {"cmn" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
295 {"smull" , 0 , 0 , 0},
296 {"umull" , 0 , 0 , 0},
297 {"umlal" , 0 , 0 , 0},
298 {"smlal" , 0 , 0 , 0},
299 {"mul" , 0 , 0 , 0},
300 {"mla" , 0 , 0 , 0},
301 {"ssat" , 0 , 6 , 0},
302 {"usat" , 0 , 6 , 0},
303 {"mrs" , 0 , 0 , 0},
304 {"msr" , 0 , 0 , 0},
305 {"and" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
306 {"bic" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
307 {"ldm" , 0 , 0 , 0},
308 {"eor" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
309 {"add" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
310 {"rsb" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
311 {"rsc" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
312 {"sbc" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
313 {"adc" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
314 {"sub" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
315 {"orr" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
316 {"mvn" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
317 {"mov" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
318 {"stm" , 0 , 0 , 0},
319 {"ldm" , 0 , 0 , 0},
320 {"ldrsh" , 0 , 2 , 0},
321 {"stm" , 0 , 0 , 0},
322 {"ldm" , 0 , 0 , 0},
323 {"ldrsb" , 0 , 2 , 0},
324 {"strd" , 0 , 4 , 0},
325 {"ldrh" , 0 , 0 , 0},
326 {"strh" , 0 , 0 , 0},
327 {"ldrd" , 0 , 4 , 0},
328 {"strt" , 0 , 0 , 0},
329 {"strbt" , 0 , 0 , 0},
330 {"ldrbt" , 0 , 0 , 0},
331 {"ldrt" , 0 , 0 , 0},
332 {"mrc" , 0 , 6 , 0},
333 {"mcr" , 0 , 0 , 0},
334 {"msr" , 0 , 0 , 0},
335 {"ldrb" , 0 , 0 , 0},
336 {"strb" , 0 , 0 , 0},
337 {"ldr" , 0 , 0 , 0},
338 {"ldrcond" , 1 , 0 , 28, 31, 0x0000000e},
339 {"str" , 0 , 0 , 0},
340 {"cdp" , 0 , 0 , 0},
341 {"stc" , 0 , 0 , 0},
342 {"ldc" , 0 , 0 , 0},
343 {"swi" , 0 , 0 , 0},
344 {"bbl" , 0 , 0 , 0},
345 {"bl_1_thumb", 0, INVALID, 0},/* should be table[-4] */
346 {"bl_2_thumb", 0, INVALID, 0}, /* should be located at the end of the table[-3] */
347 {"blx_1_thumb", 0, INVALID, 0}, /* should be located at table[-2] */
348 {"invalid", 0, INVALID, 0}
349};
350
351int decode_arm_instr(uint32_t instr, int32_t *idx)
352{
353 int n = 0;
354 int base = 0;
355 int ret = DECODE_FAILURE;
356 int i = 0;
357 int instr_slots = sizeof(arm_instruction)/sizeof(ISEITEM);
358 for (i = 0; i < instr_slots; i++)
359 {
360// ret = DECODE_SUCCESS;
361 n = arm_instruction[i].attribute_value;
362 base = 0;
363 while (n) {
364 if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) {
365 /* clrex */
366 if (instr != arm_instruction[i].content[base + 2]) {
367 break;
368 }
369 } else if (BITS(arm_instruction[i].content[base], arm_instruction[i].content[base + 1]) != arm_instruction[i].content[base + 2]) {
370 break;
371 }
372 base += 3;
373 n --;
374 }
375 //All conditions is satisfied.
376 if (n == 0)
377 ret = DECODE_SUCCESS;
378
379 if (ret == DECODE_SUCCESS) {
380 n = arm_exclusion_code[i].attribute_value;
381 if (n != 0) {
382 base = 0;
383 while (n) {
384 if (BITS(arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) {
385 break; }
386 base += 3;
387 n --;
388 }
389 //All conditions is satisfied.
390 if (n == 0)
391 ret = DECODE_FAILURE;
392 }
393 }
394
395 if (ret == DECODE_SUCCESS) {
396 *idx = i;
397 return ret;
398 }
399 }
400 return ret;
401}
402
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h
new file mode 100644
index 000000000..19d94f369
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom_dec.h
@@ -0,0 +1,155 @@
1/* Copyright (C)
2* 2012 - Michael.Kang blackfin.kang@gmail.com
3* This program is free software; you can redistribute it and/or
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18
19/**
20* @file arm_dyncom_dec.h
21* @brief Some common utility for arm instruction decoder
22* @author Michael.Kang blackfin.kang@gmail.com
23* @version 7849
24* @date 2012-03-15
25*/
26
27#ifndef __ARM_DYNCOM_DEC__
28#define __ARM_DYNCOM_DEC__
29
30#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1))
31#define BIT(n) ((instr >> (n)) & 1)
32#define BAD do{printf("meet BAD at %s, instr is %x\n", __FUNCTION__, instr ); /*exit(0);*/}while(0);
33#define ptr_N cpu->ptr_N
34#define ptr_Z cpu->ptr_Z
35#define ptr_C cpu->ptr_C
36#define ptr_V cpu->ptr_V
37#define ptr_I cpu->ptr_I
38#define ptr_T cpu->ptr_T
39#define ptr_CPSR cpu->ptr_gpr[16]
40
41/* for MUL instructions */
42/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */
43#define RDHi ((instr >> 16) & 0xF)
44/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */
45#define RDLo ((instr >> 12) & 0xF)
46/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */
47#define MUL_RD ((instr >> 16) & 0xF)
48/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */
49#define MUL_RN ((instr >> 12) & 0xF)
50/*xxxx xxxx xxxx xxxx xxxx 1111 xxxx xxxx */
51#define RS ((instr >> 8) & 0xF)
52
53/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */
54#define RD ((instr >> 12) & 0xF)
55/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */
56#define RN ((instr >> 16) & 0xF)
57/*xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1111 */
58#define RM (instr & 0xF)
59#define BIT(n) ((instr >> (n)) & 1)
60#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1))
61
62/* CP15 registers */
63#define OPCODE_1 BITS(21, 23)
64#define CRn BITS(16, 19)
65#define CRm BITS(0, 3)
66#define OPCODE_2 BITS(5, 7)
67
68/*xxxx xx1x xxxx xxxx xxxx xxxx xxxx xxxx */
69#define I BIT(25)
70/*xxxx xxxx xxx1 xxxx xxxx xxxx xxxx xxxx */
71#define S BIT(20)
72
73#define SHIFT BITS(5,6)
74#define SHIFT_IMM BITS(7,11)
75#define IMMH BITS(8,11)
76#define IMML BITS(0,3)
77
78#define LSPBIT BIT(24)
79#define LSUBIT BIT(23)
80#define LSBBIT BIT(22)
81#define LSWBIT BIT(21)
82#define LSLBIT BIT(20)
83#define LSSHBITS BITS(5,6)
84#define OFFSET12 BITS(0,11)
85#define SBIT BIT(20)
86#define DESTReg (BITS (12, 15))
87
88/* they are in unused state, give a corrent value when using */
89#define IS_V5E 0
90#define IS_V5 0
91#define IS_V6 0
92#define LHSReg 0
93
94/* temp define the using the pc reg need implement a flow */
95#define STORE_CHECK_RD_PC ADD(R(RD), CONST(INSTR_SIZE * 2))
96
97#define OPERAND operand(cpu,instr,bb,NULL)
98#define SCO_OPERAND(sco) operand(cpu,instr,bb,sco)
99#define BOPERAND boperand(instr)
100
101#define CHECK_RN_PC (RN==15? ADD(AND(R(RN), CONST(~0x1)), CONST(INSTR_SIZE * 2)):R(RN))
102#define CHECK_RN_PC_WA (RN==15? ADD(AND(R(RN), CONST(~0x3)), CONST(INSTR_SIZE * 2)):R(RN))
103
104#define GET_USER_MODE() (OR(ICMP_EQ(R(MODE_REG), CONST(USER32MODE)), ICMP_EQ(R(MODE_REG), CONST(SYSTEM32MODE))))
105
106int decode_arm_instr(uint32_t instr, int32_t *idx);
107
108enum DECODE_STATUS {
109 DECODE_SUCCESS,
110 DECODE_FAILURE
111};
112
113struct instruction_set_encoding_item {
114 const char *name;
115 int attribute_value;
116 int version;
117 u32 content[21];
118};
119
120typedef struct instruction_set_encoding_item ISEITEM;
121
122#define RECORD_WB(value, flag) {cpu->dyncom_engine->wb_value = value;cpu->dyncom_engine->wb_flag = flag;}
123#define INIT_WB(wb_value, wb_flag) RECORD_WB(wb_value, wb_flag)
124
125#define EXECUTE_WB(base_reg) {if(cpu->dyncom_engine->wb_flag) \
126 LET(base_reg, cpu->dyncom_engine->wb_value);}
127inline int get_reg_count(uint32_t instr){
128 int i = BITS(0,15);
129 int count = 0;
130 while(i){
131 if(i & 1)
132 count ++;
133 i = i >> 1;
134 }
135 return count;
136}
137
138enum ARMVER {
139 INVALID = 0,
140 ARMALL,
141 ARMV4,
142 ARMV4T,
143 ARMV5T,
144 ARMV5TE,
145 ARMV5TEJ,
146 ARMV6,
147 ARM1176JZF_S,
148 ARMVFP2,
149 ARMVFP3
150};
151
152//extern const INSTRACT arm_instruction_action[];
153extern const ISEITEM arm_instruction[];
154
155#endif
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
new file mode 100644
index 000000000..fe1501b59
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -0,0 +1,6563 @@
1/* Copyright (C)
2* 2012 - Michael.Kang blackfin.kang@gmail.com
3* This program is free software; you can redistribute it and/or
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18/**
19* @file arm_dyncom_interpreter.cpp
20* @brief The fast interpreter for arm
21* @author Michael.Kang blackfin.kang@gmail.com
22* @version 7849
23* @date 2012-03-15
24*/
25
26#define CITRA_IGNORE_EXIT(x)
27
28#include <algorithm>
29#include <map>
30#include <stdio.h>
31#include <assert.h>
32#include <cstdio>
33#include <vector>
34
35using namespace std;
36
37#include "core/arm/skyeye_common/armdefs.h"
38#include "core/arm/skyeye_common/armmmu.h"
39#include "arm_dyncom_thumb.h"
40#include "arm_dyncom_run.h"
41#include "core/arm/skyeye_common/vfp/vfp.h"
42/* shenoubang 2012-6-14 */
43#ifdef __WIN32__
44#include "bank_defs.h"
45#endif
46
47#include "core/mem_map.h"
48#include "core/hle/hle.h"
49
50enum {
51 COND = (1 << 0),
52 NON_BRANCH = (1 << 1),
53 DIRECT_BRANCH = (1 << 2),
54 INDIRECT_BRANCH = (1 << 3),
55 CALL = (1 << 4),
56 RET = (1 << 5),
57 END_OF_PAGE = (1 << 6),
58 THUMB = (1 << 7)
59};
60
61#define USER_MODE_OPT 1
62#define HYBRID_MODE 0 // Enable for JIT mode
63
64#define THRESHOLD 1000
65#define DURATION 500
66//#define PRINT_PROFILE_INFO
67
68#define CHECK_RS if(RS == 15) rs += 8
69#define CHECK_RM if(RM == 15) rm += 8
70
71//#define BITS(s, a, b) (((s) >> (a)) & ((1 << (1 + (b) - (a))) - 1))
72#undef BITS
73#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
74#define BIT(s, n) ((s >> (n)) & 1)
75#define RM BITS(sht_oper, 0, 3)
76#define RS BITS(sht_oper, 8, 11)
77
78#define glue(x, y) x ## y
79#define DPO(s) glue(DataProcessingOperands, s)
80#define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i))
81#define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i))
82#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32)
83#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32)
84
85//#define rotr(x,n) ((((x)>>(n))&((1<<(sizeof(x) * 8)-1))|(x<<(sizeof(x)*8-n))))
86//#define rotl(x,n) ((((x)<<(n))&(-(1<<(n))))|(((x)>>(sizeof(x)*8-n))&((1<<(n))-1)))
87#define rotr(x,n) ( (x >> n) | ((x & ((1 << (n + 1)) - 1)) << (32 - n)) )
88
89extern void switch_mode(arm_core_t *core, uint32_t mode);
90//extern bool InAPrivilegedMode(arm_core_t *core);
91
92typedef arm_core_t arm_processor;
93typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper);
94
95/* exclusive memory access */
96static int exclusive_detect(ARMul_State* state, ARMword addr){
97 int i;
98 #if 0
99 for(i = 0; i < 128; i++){
100 if(state->exclusive_tag_array[i] == addr)
101 return 0;
102 }
103 #endif
104 if(state->exclusive_tag == addr)
105 return 0;
106 else
107 return -1;
108}
109
110static void add_exclusive_addr(ARMul_State* state, ARMword addr){
111 int i;
112 #if 0
113 for(i = 0; i < 128; i++){
114 if(state->exclusive_tag_array[i] == 0xffffffff){
115 state->exclusive_tag_array[i] = addr;
116 //DEBUG_LOG(ARM11, "In %s, add addr 0x%x\n", __func__, addr);
117 return;
118 }
119 }
120 DEBUG_LOG(ARM11, "In %s ,can not monitor the addr, out of array\n", __FUNCTION__);
121 #endif
122 state->exclusive_tag = addr;
123 return;
124}
125
126static void remove_exclusive(ARMul_State* state, ARMword addr){
127 #if 0
128 int i;
129 for(i = 0; i < 128; i++){
130 if(state->exclusive_tag_array[i] == addr){
131 state->exclusive_tag_array[i] = 0xffffffff;
132 //DEBUG_LOG(ARM11, "In %s, remove addr 0x%x\n", __func__, addr);
133 return;
134 }
135 }
136 #endif
137 state->exclusive_tag = 0xFFFFFFFF;
138}
139
140
141unsigned int DPO(Immediate)(arm_processor *cpu, unsigned int sht_oper)
142{
143// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
144 unsigned int immed_8 = BITS(sht_oper, 0, 7);
145 unsigned int rotate_imm = BITS(sht_oper, 8, 11);
146// DEBUG_LOG(ARM11, "immed_8 is %x\n", immed_8);
147// DEBUG_LOG(ARM11, "rotate_imm is %x\n", rotate_imm);
148 unsigned int shifter_operand = ROTATE_RIGHT_32(immed_8, rotate_imm * 2);//ROTATE_RIGHT_32(immed_8, rotate_imm * 2);
149// DEBUG_LOG(ARM11, "shifter_operand : %x\n", shifter_operand);
150 /* set c flag */
151 if (rotate_imm == 0)
152 cpu->shifter_carry_out = cpu->CFlag;
153 else
154 cpu->shifter_carry_out = BIT(shifter_operand, 31);
155 return shifter_operand;
156}
157
158unsigned int DPO(Register)(arm_processor *cpu, unsigned int sht_oper)
159{
160// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
161 unsigned int rm = CHECK_READ_REG15(cpu, RM);
162 //if (RM == 15) rm += 8;
163 unsigned int shifter_operand = rm;
164 cpu->shifter_carry_out = cpu->CFlag;
165 return shifter_operand;
166}
167
168unsigned int DPO(LogicalShiftLeftByImmediate)(arm_processor *cpu, unsigned int sht_oper)
169{
170// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
171 int shift_imm = BITS(sht_oper, 7, 11);
172 unsigned int rm = CHECK_READ_REG15(cpu, RM);
173 //if (RM == 15) rm += 8;
174 unsigned int shifter_operand;
175 if (shift_imm == 0) {
176 shifter_operand = rm;
177 cpu->shifter_carry_out = cpu->CFlag;
178 } else {
179 shifter_operand = rm << shift_imm;
180 cpu->shifter_carry_out = BIT(rm, 32 - shift_imm);
181 }
182 return shifter_operand;
183}
184
185unsigned int DPO(LogicalShiftLeftByRegister)(arm_processor *cpu, unsigned int sht_oper)
186{
187// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
188 int shifter_operand;
189 unsigned int rm = CHECK_READ_REG15(cpu, RM);
190 unsigned int rs = CHECK_READ_REG15(cpu, RS);
191 //if (RM == 15) rm += 8;
192 //if (RS == 15) rs += 8;
193 if (BITS(rs, 0, 7) == 0) {
194 shifter_operand = rm;
195 cpu->shifter_carry_out = cpu->CFlag;
196 } else if (BITS(rs, 0, 7) < 32) {
197 shifter_operand = rm << BITS(rs, 0, 7);
198 cpu->shifter_carry_out = BIT(rm, 32 - BITS(rs, 0, 7));
199 } else if (BITS(rs, 0, 7) == 32) {
200 shifter_operand = 0;
201 cpu->shifter_carry_out = BIT(rm, 0);
202 } else {
203 shifter_operand = 0;
204 cpu->shifter_carry_out = 0;
205 }
206 return shifter_operand;
207}
208
209unsigned int DPO(LogicalShiftRightByImmediate)(arm_processor *cpu, unsigned int sht_oper)
210{
211// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
212 //unsigned int rm = cpu->Reg[RM];
213 unsigned int rm = CHECK_READ_REG15(cpu, RM);
214 //if (RM == 15) rm += 8;
215 unsigned int shifter_operand;
216 int shift_imm = BITS(sht_oper, 7, 11);
217 if (shift_imm == 0) {
218 shifter_operand = 0;
219 cpu->shifter_carry_out = BIT(rm, 31);
220 } else {
221 shifter_operand = rm >> shift_imm;
222 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
223 }
224 return shifter_operand;
225}
226
227unsigned int DPO(LogicalShiftRightByRegister)(arm_processor *cpu, unsigned int sht_oper)
228{
229// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
230 unsigned int rs = CHECK_READ_REG15(cpu, RS);
231 unsigned int rm = CHECK_READ_REG15(cpu, RM);
232 //if (RS == 15) rs += 8;
233 //if (RM == 15) rm += 8;
234 unsigned int shifter_operand;
235 if (BITS(rs, 0, 7) == 0) {
236 shifter_operand = rm;
237 cpu->shifter_carry_out = cpu->CFlag;
238 } else if (BITS(rs, 0, 7) < 32) {
239 shifter_operand = rm >> BITS(rs, 0, 7);
240 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
241 } else if (BITS(rs, 0, 7) == 32) {
242 shifter_operand = 0;
243 cpu->shifter_carry_out = BIT(rm, 31);
244 } else {
245 shifter_operand = 0;
246 cpu->shifter_carry_out = 0;
247 }
248 return shifter_operand;
249}
250
251unsigned int DPO(ArithmeticShiftRightByImmediate)(arm_processor *cpu, unsigned int sht_oper)
252{
253// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
254 //unsigned int rm = cpu->Reg[RM];
255 unsigned int rm = CHECK_READ_REG15(cpu, RM);
256 //if (RM == 15) rm += 8;
257 unsigned int shifter_operand;
258 int shift_imm = BITS(sht_oper, 7, 11);
259 if (shift_imm == 0) {
260 if (BIT(rm, 31)) {
261 shifter_operand = 0;
262 cpu->shifter_carry_out = BIT(rm, 31);
263 } else {
264 shifter_operand = 0xFFFFFFFF;
265 cpu->shifter_carry_out = BIT(rm, 31);
266 }
267 } else {
268 shifter_operand = static_cast<int>(rm) >> shift_imm;
269 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
270 }
271 return shifter_operand;
272}
273
274unsigned int DPO(ArithmeticShiftRightByRegister)(arm_processor *cpu, unsigned int sht_oper)
275{
276// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
277 //unsigned int rs = cpu->Reg[RS];
278 unsigned int rs = CHECK_READ_REG15(cpu, RS);
279 //unsigned int rm = cpu->Reg[RM];
280 unsigned int rm = CHECK_READ_REG15(cpu, RM);
281 //if (RS == 15) rs += 8;
282 //if (RM == 15) rm += 8;
283 unsigned int shifter_operand;
284 if (BITS(rs, 0, 7) == 0) {
285 shifter_operand = rm;
286 cpu->shifter_carry_out = cpu->CFlag;
287 } else if (BITS(rs, 0, 7) < 32) {
288 shifter_operand = static_cast<int>(rm) >> BITS(rs, 0, 7);
289 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
290 } else {
291 if (BIT(rm, 31) == 0) {
292 shifter_operand = 0;
293 } else
294 shifter_operand = 0xffffffff;
295 cpu->shifter_carry_out = BIT(rm, 31);
296 }
297 return shifter_operand;
298}
299
300unsigned int DPO(RotateRightByImmediate)(arm_processor *cpu, unsigned int sht_oper)
301{
302// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
303 unsigned int shifter_operand;
304 //unsigned int rm = cpu->Reg[RM];
305 unsigned int rm = CHECK_READ_REG15(cpu, RM);
306 //if (RM == 15) rm += 8;
307 int shift_imm = BITS(sht_oper, 7, 11);
308 if (shift_imm == 0) {
309 shifter_operand = (cpu->CFlag << 31) |
310 (rm >> 1);
311 cpu->shifter_carry_out = BIT(rm, 0);
312 } else {
313 shifter_operand = ROTATE_RIGHT_32(rm, shift_imm);
314 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
315 }
316 return shifter_operand;
317}
318
319unsigned int DPO(RotateRightByRegister)(arm_processor *cpu, unsigned int sht_oper)
320{
321// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
322 unsigned int rm = CHECK_READ_REG15(cpu, RM);
323 //if (RM == 15) rm += 8;
324 unsigned int rs = CHECK_READ_REG15(cpu, RS);
325 //if (RS == 15) rs += 8;
326 unsigned int shifter_operand;
327 if (BITS(rs, 0, 7) == 0) {
328 shifter_operand = rm;
329 cpu->shifter_carry_out = cpu->CFlag;
330 } else if (BITS(rs, 0, 4) == 0) {
331 shifter_operand = rm;
332 cpu->shifter_carry_out = BIT(rm, 31);
333 } else {
334 shifter_operand = ROTATE_RIGHT_32(rm, BITS(rs, 0, 4));
335 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 4) - 1);
336 }
337 #if 0
338 if (cpu->icounter >= 20371544) {
339 DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
340 DEBUG_LOG(ARM11, "RM:%d\nRS:%d\n", RM, RS);
341 DEBUG_LOG(ARM11, "rm:0x%08x\nrs:0x%08x\n", cpu->Reg[RM], cpu->Reg[RS]);
342 }
343 #endif
344 return shifter_operand;
345}
346
347//typedef unsigned int (*get_addr_fp_t)(arm_processor *cpu);
348typedef struct _MiscImmeData {
349 unsigned int U;
350 unsigned int Rn;
351 unsigned int offset_8;
352} MiscLSData;
353
354typedef struct _MiscRegData {
355 unsigned int U;
356 unsigned int Rn;
357 unsigned int Rm;
358} MiscRegData;
359
360typedef struct _MiscImmePreIdx {
361 unsigned int offset_8;
362 unsigned int U;
363 unsigned int Rn;
364} MiscImmePreIdx;
365
366typedef struct _MiscRegPreIdx {
367 unsigned int U;
368 unsigned int Rn;
369 unsigned int Rm;
370} MiscRegPreIdx;
371
372typedef struct _MiscImmePstIdx {
373 unsigned int offset_8;
374 unsigned int U;
375 unsigned int Rn;
376} MIscImmePstIdx;
377
378typedef struct _MiscRegPstIdx {
379 unsigned int Rn;
380 unsigned int Rm;
381 unsigned int U;
382} MiscRegPstIdx;
383
384typedef struct _LSWordorUnsignedByte {
385} LDnST;
386
387#if USER_MODE_OPT
388static inline fault_t interpreter_read_memory(addr_t virt_addr, addr_t phys_addr, uint32_t &value, uint32_t size){
389 switch(size) {
390 case 8:
391 value = Memory::Read8(virt_addr);
392 break;
393 case 16:
394 value = Memory::Read16(virt_addr);
395 break;
396 case 32:
397 value = Memory::Read32(virt_addr);
398 break;
399 }
400 return NO_FAULT;
401}
402
403//static inline void interpreter_write_memory(void *mem_ptr, uint32_t offset, uint32_t value, int size)
404static inline fault_t interpreter_write_memory(addr_t virt_addr, addr_t phys_addr, uint32_t value, uint32_t size)
405{
406 switch(size) {
407 case 8:
408 Memory::Write8(virt_addr, value & 0xff);
409 break;
410 case 16:
411 Memory::Write16(virt_addr, value & 0xffff);
412 break;
413 case 32:
414 Memory::Write32(virt_addr, value);
415 break;
416 }
417 return NO_FAULT;
418}
419
420static inline fault_t check_address_validity(arm_core_t *core, addr_t virt_addr, addr_t *phys_addr, uint32_t rw){
421 *phys_addr = virt_addr;
422 return NO_FAULT;
423}
424
425#else
426fault_t interpreter_read_memory(cpu_t *cpu, addr_t virt_addr, addr_t phys_addr, uint32_t &value, uint32_t size);
427fault_t interpreter_write_memory(cpu_t *cpu, addr_t virt_addr, addr_t phys_addr, uint32_t value, uint32_t size);
428fault_t interpreter_fetch(cpu_t *cpu, addr_t virt_addr, uint32_t &value, uint32_t size);
429fault_t check_address_validity(arm_core_t *core, addr_t virt_addr, addr_t *phys_addr, uint32_t rw, tlb_type_t access_type = DATA_TLB);
430#endif
431
432typedef fault_t (*get_addr_fp_t)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw);
433
434typedef struct _ldst_inst {
435 unsigned int inst;
436 get_addr_fp_t get_addr;
437} ldst_inst;
438#define DEBUG_MSG DEBUG_LOG(ARM11, "in %s %d\n", __FUNCTION__, __LINE__); \
439 DEBUG_LOG(ARM11, "inst is %x\n", inst); \
440 CITRA_IGNORE_EXIT(0)
441
442int CondPassed(arm_processor *cpu, unsigned int cond);
443#define LnSWoUB(s) glue(LnSWoUB, s)
444#define MLnS(s) glue(MLnS, s)
445#define LdnStM(s) glue(LdnStM, s)
446
447#define W_BIT BIT(inst, 21)
448#define U_BIT BIT(inst, 23)
449#define I_BIT BIT(inst, 25)
450#define P_BIT BIT(inst, 24)
451#define OFFSET_12 BITS(inst, 0, 11)
452fault_t LnSWoUB(ImmediateOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
453{
454 unsigned int Rn = BITS(inst, 16, 19);
455 unsigned int addr;
456 fault_t fault;
457 if (U_BIT) {
458 addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12;
459 } else {
460 addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12;
461 }
462 //if (Rn == 15) rn += 8;
463 virt_addr = addr;
464 fault = check_address_validity(cpu, addr, &phys_addr, rw);
465 return fault;
466// return addr;
467}
468
469fault_t LnSWoUB(RegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
470{
471 fault_t fault;
472 unsigned int Rn = BITS(inst, 16, 19);
473 unsigned int Rm = BITS(inst, 0, 3);
474 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
475 //if (Rn == 15) rn += 8;
476 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
477 //if (Rm == 15) rm += 8;
478 unsigned int addr;
479 if (U_BIT) {
480 addr = rn + rm;
481 } else {
482 addr = rn - rm;
483 }
484 virt_addr = addr;
485 fault = check_address_validity(cpu, addr, &phys_addr, rw);
486 return fault;
487}
488
489fault_t LnSWoUB(ImmediatePostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
490{
491 fault_t fault;
492 unsigned int Rn = BITS(inst, 16, 19);
493 unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn);
494 //if (Rn == 15) addr += 8;
495
496 virt_addr = addr;
497 fault = check_address_validity(cpu, addr, &phys_addr, rw);
498 if (fault) return fault;
499
500 if (U_BIT) {
501 cpu->Reg[Rn] += OFFSET_12;
502 } else {
503 cpu->Reg[Rn] -= OFFSET_12;
504 }
505 return fault;
506}
507
508fault_t LnSWoUB(ImmediatePreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
509{
510 fault_t fault;
511 unsigned int Rn = BITS(inst, 16, 19);
512 unsigned int addr;
513 if (U_BIT) {
514 addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12;
515 } else {
516 addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12;
517 }
518 #if 0
519 if (Rn == 15) {
520 addr += 8;
521 }
522 #endif
523
524 virt_addr = addr;
525 fault = check_address_validity(cpu, addr, &phys_addr, rw);
526 if (fault) return fault;
527
528 if (CondPassed(cpu, BITS(inst, 28, 31))) {
529 cpu->Reg[Rn] = addr;
530 }
531 return fault;
532}
533
534fault_t MLnS(RegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
535{
536 fault_t fault;
537 unsigned int addr;
538 unsigned int Rn = BITS(inst, 16, 19);
539 unsigned int Rm = BITS(inst, 0, 3);
540 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
541 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
542 //if (Rn == 15) rn += 8;
543 //if (Rm == 15) rm += 8;
544 if (U_BIT) {
545 addr = rn + rm;
546 } else
547 addr = rn - rm;
548 if(BIT(inst, 20)){ /* L BIT */
549 }
550 if(BIT(inst, 6)){ /* Sign Bit */
551 }
552 if(BIT(inst, 5)){ /* Half Bit */
553 }
554
555 virt_addr = addr;
556 fault = check_address_validity(cpu, addr, &phys_addr, rw);
557 if (fault) return fault;
558
559 if (CondPassed(cpu, BITS(inst, 28, 31))) {
560 cpu->Reg[Rn] = addr;
561 }
562 return fault;
563}
564
565fault_t LnSWoUB(RegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
566{
567 fault_t fault;
568 unsigned int Rn = BITS(inst, 16, 19);
569 unsigned int Rm = BITS(inst, 0, 3);
570 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
571 //if (Rn == 15) rn += 8;
572 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
573 //if (Rm == 15) rm += 8;
574 unsigned int addr;
575 if (U_BIT) {
576 addr = rn + rm;
577 } else {
578 addr = rn - rm;
579 }
580 virt_addr = addr;
581 fault = check_address_validity(cpu, addr, &phys_addr, rw);
582 if(fault)
583 return fault;
584 if (CondPassed(cpu, BITS(inst, 28, 31))) {
585 cpu->Reg[Rn] = addr;
586 }
587 return fault;
588}
589fault_t LnSWoUB(ScaledRegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
590{
591 fault_t fault;
592 unsigned int shift = BITS(inst, 5, 6);
593 unsigned int shift_imm = BITS(inst, 7, 11);
594 unsigned int Rn = BITS(inst, 16, 19);
595 unsigned int Rm = BITS(inst, 0, 3);
596 unsigned int index;
597 unsigned int addr;
598
599 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
600 //if (Rm == 15) rm += 8;
601 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
602 //if (Rn == 15) rn += 8;
603 switch (shift) {
604 case 0:
605 //DEBUG_MSG;
606 index = rm << shift_imm;
607 break;
608 case 1:
609// DEBUG_MSG;
610 if (shift_imm == 0) {
611 index = 0;
612 } else {
613 index = rm >> shift_imm;
614 }
615 break;
616 case 2:
617 DEBUG_MSG;
618 break;
619 case 3:
620 DEBUG_MSG;
621 break;
622 }
623 if (U_BIT) {
624 addr = rn + index;
625 } else
626 addr = rn - index;
627 virt_addr = addr;
628 fault = check_address_validity(cpu, addr, &phys_addr, rw);
629 if(fault)
630 return fault;
631 if (CondPassed(cpu, BITS(inst, 28, 31))) {
632 cpu->Reg[Rn] = addr;
633 }
634
635 return fault;
636}
637
638fault_t LnSWoUB(ScaledRegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
639{
640 fault_t fault;
641 unsigned int shift = BITS(inst, 5, 6);
642 unsigned int shift_imm = BITS(inst, 7, 11);
643 unsigned int Rn = BITS(inst, 16, 19);
644 unsigned int Rm = BITS(inst, 0, 3);
645 unsigned int index;
646 unsigned int addr;
647
648 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
649 //if (Rm == 15) rm += 8;
650 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
651 //if (Rn == 15) rn += 8;
652 addr = rn;
653 switch (shift) {
654 case 0:
655 //DEBUG_MSG;
656 index = rm << shift_imm;
657 break;
658 case 1:
659// DEBUG_MSG;
660 if (shift_imm == 0) {
661 index = 0;
662 } else {
663 index = rm >> shift_imm;
664 }
665 break;
666 case 2:
667 DEBUG_MSG;
668 break;
669 case 3:
670 DEBUG_MSG;
671 break;
672 }
673 virt_addr = addr;
674 fault = check_address_validity(cpu, addr, &phys_addr, rw);
675 if(fault)
676 return fault;
677 if (CondPassed(cpu, BITS(inst, 28, 31))) {
678 if (U_BIT)
679 cpu->Reg[Rn] += index;
680 else
681 cpu->Reg[Rn] -= index;
682 }
683
684 return fault;
685}
686
687fault_t LnSWoUB(RegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
688{
689 fault_t fault;
690 unsigned int Rn = BITS(inst, 16, 19);
691 unsigned int Rm = BITS(inst, 0, 3);
692 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
693 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
694
695 unsigned int addr = rn;
696 virt_addr = addr;
697 fault = check_address_validity(cpu, addr, &phys_addr, rw);
698 if (fault) return fault;
699
700 if (CondPassed(cpu, BITS(inst, 28, 31))) {
701 if (U_BIT) {
702 cpu->Reg[Rn] += rm;
703 } else {
704 cpu->Reg[Rn] -= rm;
705 }
706 }
707 return fault;
708}
709
710fault_t MLnS(ImmediateOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
711{
712 fault_t fault;
713 unsigned int immedL = BITS(inst, 0, 3);
714 unsigned int immedH = BITS(inst, 8, 11);
715
716 unsigned int Rn = BITS(inst, 16, 19);
717 unsigned int addr;
718
719 unsigned int offset_8 = (immedH << 4) | immedL;
720 if (U_BIT) {
721 addr = CHECK_READ_REG15_WA(cpu, Rn) + offset_8;
722 } else
723 addr = CHECK_READ_REG15_WA(cpu, Rn) - offset_8;
724 #if 0
725 if (Rn == 15) {
726 addr += 8;
727 }
728 #endif
729 virt_addr = addr;
730 fault = check_address_validity(cpu, addr, &phys_addr, rw);
731 return fault;
732}
733
734fault_t MLnS(RegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
735{
736 fault_t fault;
737 unsigned int addr;
738 unsigned int Rn = BITS(inst, 16, 19);
739 unsigned int Rm = BITS(inst, 0, 3);
740 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
741 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
742 //if (Rn == 15) rn += 8;
743 //if (Rm == 15) rm += 8;
744 if (U_BIT) {
745 addr = rn + rm;
746 } else
747 addr = rn - rm;
748 if(BIT(inst, 20)){ /* L BIT */
749 }
750 if(BIT(inst, 6)){ /* Sign Bit */
751 }
752 if(BIT(inst, 5)){ /* Half Bit */
753 }
754 virt_addr = addr;
755 fault = check_address_validity(cpu, addr, &phys_addr, rw);
756 return fault;
757}
758
759fault_t MLnS(ImmediatePreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
760{
761 fault_t fault;
762 unsigned int Rn = BITS(inst, 16, 19);
763 unsigned int immedH = BITS(inst, 8, 11);
764 unsigned int immedL = BITS(inst, 0, 3);
765 unsigned int addr;
766 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
767 //if (Rn == 15) rn += 8;
768
769// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
770 unsigned int offset_8 = (immedH << 4) | immedL;
771 if (U_BIT) {
772 addr = rn + offset_8;
773 } else
774 addr = rn - offset_8;
775
776 virt_addr = addr;
777 fault = check_address_validity(cpu, addr, &phys_addr, rw);
778 if (fault) return fault;
779
780 if (CondPassed(cpu, BITS(inst, 28, 31))) {
781 cpu->Reg[Rn] = addr;
782 }
783 return fault;
784}
785
786fault_t MLnS(ImmediatePostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
787{
788 fault_t fault;
789 unsigned int Rn = BITS(inst, 16, 19);
790 unsigned int immedH = BITS(inst, 8, 11);
791 unsigned int immedL = BITS(inst, 0, 3);
792 unsigned int addr;
793 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
794 addr = rn;
795
796 virt_addr = addr;
797 fault = check_address_validity(cpu, addr, &phys_addr, rw);
798 if (fault) return fault;
799
800 if (CondPassed(cpu, BITS(inst, 28, 31))) {
801 unsigned int offset_8 = (immedH << 4) | immedL;
802 if (U_BIT) {
803 rn += offset_8;
804 } else {
805 rn -= offset_8;
806 }
807 cpu->Reg[Rn] = rn;
808 }
809
810 return fault;
811}
812fault_t MLnS(RegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
813{
814 fault_t fault;
815 unsigned int Rn = BITS(inst, 16, 19);
816 unsigned int Rm = BITS(inst, 0, 3);
817 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
818 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
819
820 unsigned int addr = rn;
821 virt_addr = addr;
822 fault = check_address_validity(cpu, addr, &phys_addr, rw);
823 if (fault) return fault;
824
825 if (CondPassed(cpu, BITS(inst, 28, 31))) {
826 if (U_BIT) {
827 cpu->Reg[Rn] += rm;
828 } else {
829 cpu->Reg[Rn] -= rm;
830 }
831 }
832 return fault;
833}
834
835fault_t LdnStM(DecrementBefore)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
836{
837 fault_t fault;
838 unsigned int Rn = BITS(inst, 16, 19);
839 unsigned int i = BITS(inst, 0, 15);
840 int count = 0;
841 while(i) {
842 if(i & 1) count ++;
843 i = i >> 1;
844 }
845 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
846 //if (Rn == 15) rn += 8;
847 unsigned int start_addr = rn - count * 4;
848 unsigned int end_addr = rn - 4;
849
850 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
851 virt_addr = end_addr;
852 if (fault) return fault;
853
854 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
855 virt_addr = start_addr;
856 if (fault) return fault;
857
858 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
859 cpu->Reg[Rn] -= count * 4;
860 }
861
862 return fault;
863}
864
865fault_t LdnStM(IncrementBefore)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
866{
867 fault_t fault;
868 unsigned int Rn = BITS(inst, 16, 19);
869 unsigned int i = BITS(inst, 0, 15);
870 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
871 //if (Rn == 15) rn += 8;
872 int count = 0;
873 while(i) {
874 if(i & 1) count ++;
875 i = i >> 1;
876 }
877
878 unsigned int start_addr = rn + 4;
879 unsigned int end_addr = rn + count * 4;
880
881 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
882 virt_addr = end_addr;
883 if (fault) return fault;
884
885 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
886 virt_addr = start_addr;
887 if (fault) return fault;
888
889 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
890 cpu->Reg[Rn] += count * 4;
891 }
892 return fault;
893}
894
895fault_t LdnStM(IncrementAfter)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
896{
897 fault_t fault;
898 unsigned int Rn = BITS(inst, 16, 19);
899 unsigned int i = BITS(inst, 0, 15);
900 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
901 int count = 0;
902 while(i) {
903 if(i & 1) count ++;
904 i = i >> 1;
905 }
906 //if (Rn == 15) rn += 8;
907 unsigned int start_addr = rn;
908 unsigned int end_addr = rn + count * 4 - 4;
909
910 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
911 virt_addr = end_addr;
912 if (fault) return fault;
913
914 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
915 virt_addr = start_addr;
916 if (fault) return fault;
917
918 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
919 cpu->Reg[Rn] += count * 4;
920 }
921 return fault;
922}
923
924fault_t LdnStM(DecrementAfter)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
925{
926 fault_t fault;
927 unsigned int Rn = BITS(inst, 16, 19);
928 unsigned int i = BITS(inst, 0, 15);
929 int count = 0;
930 while(i) {
931 if(i & 1) count ++;
932 i = i >> 1;
933 }
934 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
935 //if (Rn == 15) rn += 8;
936 unsigned int start_addr = rn - count * 4 + 4;
937 unsigned int end_addr = rn;
938
939 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
940 virt_addr = end_addr;
941 if (fault) return fault;
942
943 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
944 if (fault) return fault;
945 virt_addr = start_addr;
946
947 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
948 cpu->Reg[Rn] -= count * 4;
949 }
950 return fault;
951}
952
953fault_t LnSWoUB(ScaledRegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
954{
955 fault_t fault;
956 unsigned int shift = BITS(inst, 5, 6);
957 unsigned int shift_imm = BITS(inst, 7, 11);
958 unsigned int Rn = BITS(inst, 16, 19);
959 unsigned int Rm = BITS(inst, 0, 3);
960 unsigned int index;
961 unsigned int addr;
962
963 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
964 //if (Rm == 15) rm += 8;
965 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
966 //if (Rn == 15) rn += 8;
967 switch (shift) {
968 case 0:
969 //DEBUG_MSG;
970 index = rm << shift_imm;
971 break;
972 case 1:
973// DEBUG_MSG;
974 if (shift_imm == 0) {
975 index = 0;
976 } else {
977 index = rm >> shift_imm;
978 }
979 break;
980 case 2:
981 if (shift_imm == 0){ /* ASR #32 */
982 if (rm >> 31)
983 index = 0xFFFFFFFF;
984 else
985 index = 0;
986 }
987 else {
988 index = static_cast<int>(rm) >> shift_imm;
989 }
990 break;
991 case 3:
992 DEBUG_MSG;
993 break;
994 }
995 if (U_BIT) {
996 addr = rn + index;
997 } else
998 addr = rn - index;
999 virt_addr = addr;
1000 fault = check_address_validity(cpu, addr, &phys_addr, rw);
1001 return fault;
1002}
1003
1004#define ISNEG(n) (n < 0)
1005#define ISPOS(n) (n >= 0)
1006
1007//enum {
1008// COND = (1 << 0),
1009// NON_BRANCH = (1 << 1),
1010// DIRECT_BRANCH = (1 << 2),
1011// INDIRECT_BRANCH = (1 << 3),
1012// CALL = (1 << 4),
1013// RET = (1 << 5),
1014// END_OF_PAGE = (1 << 6),
1015// THUMB = (1 << 7)
1016//};
1017
1018typedef struct _arm_inst {
1019 unsigned int idx;
1020 unsigned int cond;
1021 int br;
1022 int load_r15;
1023 char component[0];
1024} arm_inst;
1025
1026typedef struct _adc_inst {
1027 unsigned int I;
1028 unsigned int S;
1029 unsigned int Rn;
1030 unsigned int Rd;
1031 unsigned int shifter_operand;
1032 shtop_fp_t shtop_func;
1033} adc_inst;
1034
1035typedef struct _add_inst {
1036 unsigned int I;
1037 unsigned int S;
1038 unsigned int Rn;
1039 unsigned int Rd;
1040 unsigned int shifter_operand;
1041 shtop_fp_t shtop_func;
1042} add_inst;
1043
1044typedef struct _orr_inst {
1045 unsigned int I;
1046 unsigned int S;
1047 unsigned int Rn;
1048 unsigned int Rd;
1049 unsigned int shifter_operand;
1050 shtop_fp_t shtop_func;
1051} orr_inst;
1052
1053typedef struct _and_inst {
1054 unsigned int I;
1055 unsigned int S;
1056 unsigned int Rn;
1057 unsigned int Rd;
1058 unsigned int shifter_operand;
1059 shtop_fp_t shtop_func;
1060} and_inst;
1061
1062typedef struct _eor_inst {
1063 unsigned int I;
1064 unsigned int S;
1065 unsigned int Rn;
1066 unsigned int Rd;
1067 unsigned int shifter_operand;
1068 shtop_fp_t shtop_func;
1069} eor_inst;
1070
1071typedef struct _bbl_inst {
1072 unsigned int L;
1073 int signed_immed_24;
1074 unsigned int next_addr;
1075 unsigned int jmp_addr;
1076} bbl_inst;
1077
1078typedef struct _bx_inst {
1079 unsigned int Rm;
1080} bx_inst;
1081
1082typedef struct _blx_inst {
1083 union {
1084 int32_t signed_immed_24;
1085 uint32_t Rm;
1086 } val;
1087 unsigned int inst;
1088} blx_inst;
1089
1090typedef struct _clz_inst {
1091 unsigned int Rm;
1092 unsigned int Rd;
1093} clz_inst;
1094
1095typedef struct _cps_inst {
1096 unsigned int imod0;
1097 unsigned int imod1;
1098 unsigned int mmod;
1099 unsigned int A, I, F;
1100 unsigned int mode;
1101} cps_inst;
1102
1103typedef struct _clrex_inst {
1104} clrex_inst;
1105
1106typedef struct _cpy_inst {
1107 unsigned int Rm;
1108 unsigned int Rd;
1109} cpy_inst;
1110
1111typedef struct _bic_inst {
1112 unsigned int I;
1113 unsigned int S;
1114 unsigned int Rn;
1115 unsigned int Rd;
1116 unsigned int shifter_operand;
1117 shtop_fp_t shtop_func;
1118} bic_inst;
1119
1120typedef struct _sub_inst {
1121 unsigned int I;
1122 unsigned int S;
1123 unsigned int Rn;
1124 unsigned int Rd;
1125 unsigned int shifter_operand;
1126 shtop_fp_t shtop_func;
1127} sub_inst;
1128
1129typedef struct _tst_inst {
1130 unsigned int I;
1131 unsigned int S;
1132 unsigned int Rn;
1133 unsigned int Rd;
1134 unsigned int shifter_operand;
1135 shtop_fp_t shtop_func;
1136} tst_inst;
1137
1138typedef struct _cmn_inst {
1139 unsigned int I;
1140 //unsigned int S;
1141 unsigned int Rn;
1142 //unsigned int Rd;
1143 unsigned int shifter_operand;
1144 shtop_fp_t shtop_func;
1145} cmn_inst;
1146
1147typedef struct _teq_inst {
1148 unsigned int I;
1149 unsigned int Rn;
1150 unsigned int shifter_operand;
1151 shtop_fp_t shtop_func;
1152} teq_inst;
1153
1154typedef struct _stm_inst {
1155 unsigned int inst;
1156} stm_inst;
1157
1158struct bkpt_inst {
1159};
1160
1161struct blx1_inst {
1162 unsigned int addr;
1163};
1164
1165struct blx2_inst {
1166 unsigned int Rm;
1167};
1168
1169typedef struct _stc_inst {
1170} stc_inst;
1171
1172typedef struct _ldc_inst {
1173} ldc_inst;
1174
1175typedef struct _swi_inst {
1176 unsigned int num;
1177} swi_inst;
1178
1179typedef struct _cmp_inst {
1180 unsigned int I;
1181 unsigned int Rn;
1182 unsigned int shifter_operand;
1183 shtop_fp_t shtop_func;
1184} cmp_inst;
1185
1186typedef struct _mov_inst {
1187 unsigned int I;
1188 unsigned int S;
1189 unsigned int Rd;
1190 unsigned int shifter_operand;
1191 shtop_fp_t shtop_func;
1192} mov_inst;
1193
1194typedef struct _mvn_inst {
1195 unsigned int I;
1196 unsigned int S;
1197 unsigned int Rd;
1198 unsigned int shifter_operand;
1199 shtop_fp_t shtop_func;
1200} mvn_inst;
1201
1202typedef struct _rev_inst {
1203 unsigned int Rd;
1204 unsigned int Rm;
1205} rev_inst;
1206
1207typedef struct _rsb_inst {
1208 unsigned int I;
1209 unsigned int S;
1210 unsigned int Rn;
1211 unsigned int Rd;
1212 unsigned int shifter_operand;
1213 shtop_fp_t shtop_func;
1214} rsb_inst;
1215
1216typedef struct _rsc_inst {
1217 unsigned int I;
1218 unsigned int S;
1219 unsigned int Rn;
1220 unsigned int Rd;
1221 unsigned int shifter_operand;
1222 shtop_fp_t shtop_func;
1223} rsc_inst;
1224
1225typedef struct _sbc_inst {
1226 unsigned int I;
1227 unsigned int S;
1228 unsigned int Rn;
1229 unsigned int Rd;
1230 unsigned int shifter_operand;
1231 shtop_fp_t shtop_func;
1232} sbc_inst;
1233
1234typedef struct _mul_inst {
1235 unsigned int S;
1236 unsigned int Rd;
1237 unsigned int Rs;
1238 unsigned int Rm;
1239} mul_inst;
1240
1241typedef struct _smul_inst {
1242 unsigned int Rd;
1243 unsigned int Rs;
1244 unsigned int Rm;
1245 unsigned int x;
1246 unsigned int y;
1247} smul_inst;
1248
1249typedef struct _umull_inst {
1250 unsigned int S;
1251 unsigned int RdHi;
1252 unsigned int RdLo;
1253 unsigned int Rs;
1254 unsigned int Rm;
1255} umull_inst;
1256typedef struct _smlad_inst {
1257 unsigned int m;
1258 unsigned int Rm;
1259 unsigned int Rd;
1260 unsigned int Ra;
1261 unsigned int Rn;
1262} smlad_inst;
1263
1264typedef struct _smla_inst {
1265 unsigned int x;
1266 unsigned int y;
1267 unsigned int Rm;
1268 unsigned int Rd;
1269 unsigned int Rs;
1270 unsigned int Rn;
1271} smla_inst;
1272
1273typedef struct _umlal_inst {
1274 unsigned int S;
1275 unsigned int Rm;
1276 unsigned int Rs;
1277 unsigned int RdHi;
1278 unsigned int RdLo;
1279} umlal_inst;
1280
1281typedef struct _smlal_inst {
1282 unsigned int S;
1283 unsigned int Rm;
1284 unsigned int Rs;
1285 unsigned int RdHi;
1286 unsigned int RdLo;
1287} smlal_inst;
1288
1289typedef struct _mla_inst {
1290 unsigned int S;
1291 unsigned int Rn;
1292 unsigned int Rd;
1293 unsigned int Rs;
1294 unsigned int Rm;
1295} mla_inst;
1296
1297typedef struct _mrc_inst {
1298 unsigned int opcode_1;
1299 unsigned int opcode_2;
1300 unsigned int cp_num;
1301 unsigned int crn;
1302 unsigned int crm;
1303 unsigned int Rd;
1304 unsigned int inst;
1305} mrc_inst;
1306
1307typedef struct _mcr_inst {
1308 unsigned int opcode_1;
1309 unsigned int opcode_2;
1310 unsigned int cp_num;
1311 unsigned int crn;
1312 unsigned int crm;
1313 unsigned int Rd;
1314 unsigned int inst;
1315} mcr_inst;
1316
1317typedef struct _mrs_inst {
1318 unsigned int R;
1319 unsigned int Rd;
1320} mrs_inst;
1321
1322typedef struct _msr_inst {
1323 unsigned int field_mask;
1324 unsigned int R;
1325 unsigned int inst;
1326} msr_inst;
1327
1328typedef struct _pld_inst {
1329} pld_inst;
1330
1331typedef struct _sxtb_inst {
1332 unsigned int Rd;
1333 unsigned int Rm;
1334 unsigned int rotate;
1335} sxtb_inst;
1336
1337typedef struct _sxtab_inst {
1338 unsigned int Rd;
1339 unsigned int Rn;
1340 unsigned int Rm;
1341 unsigned rotate;
1342} sxtab_inst;
1343
1344typedef struct _sxtah_inst {
1345 unsigned int Rd;
1346 unsigned int Rn;
1347 unsigned int Rm;
1348 unsigned int rotate;
1349} sxtah_inst;
1350
1351typedef struct _sxth_inst {
1352 unsigned int Rd;
1353 unsigned int Rm;
1354 unsigned int rotate;
1355} sxth_inst;
1356
1357typedef struct _uxtab_inst {
1358 unsigned int Rn;
1359 unsigned int Rd;
1360 unsigned int rotate;
1361 unsigned int Rm;
1362} uxtab_inst;
1363
1364typedef struct _uxtah_inst {
1365 unsigned int Rn;
1366 unsigned int Rd;
1367 unsigned int rotate;
1368 unsigned int Rm;
1369} uxtah_inst;
1370
1371typedef struct _uxth_inst {
1372 unsigned int Rd;
1373 unsigned int Rm;
1374 unsigned int rotate;
1375} uxth_inst;
1376
1377typedef struct _cdp_inst {
1378 unsigned int opcode_1;
1379 unsigned int CRn;
1380 unsigned int CRd;
1381 unsigned int cp_num;
1382 unsigned int opcode_2;
1383 unsigned int CRm;
1384 uint32 inst;
1385}cdp_inst;
1386
1387typedef struct _uxtb_inst {
1388 unsigned int Rd;
1389 unsigned int Rm;
1390 unsigned int rotate;
1391} uxtb_inst;
1392
1393typedef struct _swp_inst {
1394 unsigned int Rn;
1395 unsigned int Rd;
1396 unsigned int Rm;
1397} swp_inst;
1398
1399typedef struct _b_2_thumb {
1400 unsigned int imm;
1401}b_2_thumb;
1402typedef struct _b_cond_thumb {
1403 unsigned int imm;
1404 unsigned int cond;
1405}b_cond_thumb;
1406
1407typedef struct _bl_1_thumb {
1408 unsigned int imm;
1409}bl_1_thumb;
1410typedef struct _bl_2_thumb {
1411 unsigned int imm;
1412}bl_2_thumb;
1413typedef struct _blx_1_thumb {
1414 unsigned int imm;
1415 unsigned int instr;
1416}blx_1_thumb;
1417
1418typedef arm_inst * ARM_INST_PTR;
1419
1420#define CACHE_BUFFER_SIZE (64 * 1024 * 2000)
1421char inst_buf[CACHE_BUFFER_SIZE];
1422int top = 0;
1423inline void *AllocBuffer(unsigned int size)
1424{
1425 int start = top;
1426 top += size;
1427 if (top > CACHE_BUFFER_SIZE) {
1428 DEBUG_LOG(ARM11, "inst_buf is full\n");
1429 CITRA_IGNORE_EXIT(-1);
1430 }
1431 return (void *)&inst_buf[start];
1432}
1433
1434int CondPassed(arm_processor *cpu, unsigned int cond)
1435{
1436 #define NFLAG cpu->NFlag
1437 #define ZFLAG cpu->ZFlag
1438 #define CFLAG cpu->CFlag
1439 #define VFLAG cpu->VFlag
1440 int temp;
1441 switch (cond) {
1442 case 0x0:
1443 temp = ZFLAG;
1444 break;
1445 case 0x1: /* NE */
1446 temp = !ZFLAG;
1447 break;
1448 case 0x6: /* VS */
1449 temp = VFLAG;
1450 break;
1451 case 0x7: /* VC */
1452 temp = !VFLAG;
1453 break;
1454 case 0x4: /* MI */
1455 temp = NFLAG;
1456 break;
1457 case 0x5: /* PL */
1458 temp = !NFLAG;
1459 break;
1460 case 0x2: /* CS */
1461 temp = CFLAG;
1462 break;
1463 case 0x3: /* CC */
1464 temp = !CFLAG;
1465 break;
1466 case 0x8: /* HI */
1467 temp = (CFLAG && !ZFLAG);
1468 break;
1469 case 0x9: /* LS */
1470 temp = (!CFLAG || ZFLAG);
1471 break;
1472 case 0xa: /* GE */
1473 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
1474 break;
1475 case 0xb: /* LT */
1476 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
1477 break;
1478 case 0xc: /* GT */
1479 temp = ((!NFLAG && !VFLAG && !ZFLAG)
1480 || (NFLAG && VFLAG && !ZFLAG));
1481 break;
1482 case 0xd: /* LE */
1483 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG))
1484 || ZFLAG;
1485 break;
1486 case 0xe: /* AL */
1487 temp = 1;
1488 break;
1489 case 0xf:
1490// DEBUG_LOG(ARM11, "inst is %x\n");
1491// DEBUG_LOG(ARM11, "icounter is %lld\n", cpu->icounter);
1492// CITRA_IGNORE_EXIT(-1);
1493 temp = 1;
1494 break;
1495 }
1496 return temp;
1497}
1498
1499enum DECODE_STATUS {
1500 DECODE_SUCCESS,
1501 DECODE_FAILURE
1502};
1503
1504int decode_arm_instr(uint32_t instr, int32_t *idx);
1505
1506shtop_fp_t get_shtop(unsigned int inst)
1507{
1508 if (BIT(inst, 25)) {
1509 return DPO(Immediate);
1510 } else if (BITS(inst, 4, 11) == 0) {
1511 return DPO(Register);
1512 } else if (BITS(inst, 4, 6) == 0) {
1513 return DPO(LogicalShiftLeftByImmediate);
1514 } else if (BITS(inst, 4, 7) == 1) {
1515 return DPO(LogicalShiftLeftByRegister);
1516 } else if (BITS(inst, 4, 6) == 2) {
1517 return DPO(LogicalShiftRightByImmediate);
1518 } else if (BITS(inst, 4, 7) == 3) {
1519 return DPO(LogicalShiftRightByRegister);
1520 } else if (BITS(inst, 4, 6) == 4) {
1521 return DPO(ArithmeticShiftRightByImmediate);
1522 } else if (BITS(inst, 4, 7) == 5) {
1523 return DPO(ArithmeticShiftRightByRegister);
1524 } else if (BITS(inst, 4, 6) == 6) {
1525 return DPO(RotateRightByImmediate);
1526 } else if (BITS(inst, 4, 7) == 7) {
1527 return DPO(RotateRightByRegister);
1528 }
1529 return NULL;
1530}
1531
1532get_addr_fp_t get_calc_addr_op(unsigned int inst)
1533{
1534 /* 1 */
1535 if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 0) {
1536// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1537 return LnSWoUB(ImmediateOffset);
1538 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) {
1539// DEBUG_MSG;
1540// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1541 return LnSWoUB(RegisterOffset);
1542 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
1543// DEBUG_MSG;
1544// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1545 return LnSWoUB(ScaledRegisterOffset);
1546 } else if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 1) {
1547// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1548 return LnSWoUB(ImmediatePreIndexed);
1549 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BITS(inst, 4, 11) == 0) {
1550 return LnSWoUB(RegisterPreIndexed);
1551 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BIT(inst, 4) == 0) {
1552 return LnSWoUB(ScaledRegisterPreIndexed);
1553 } else if (BITS(inst, 24, 27) == 4 && BIT(inst, 21) == 0) {
1554 return LnSWoUB(ImmediatePostIndexed);
1555 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) {
1556// DEBUG_MSG;
1557 return LnSWoUB(RegisterPostIndexed);
1558 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
1559 return LnSWoUB(ScaledRegisterPostIndexed);
1560// DEBUG_MSG;
1561 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1562 /* 2 */
1563// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1564 return MLnS(ImmediateOffset);
1565// DEBUG_MSG;
1566 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1567// DEBUG_LOG(ARM11, "line is %d\n", __LINE__);
1568 return MLnS(RegisterOffset);
1569// DEBUG_MSG;
1570 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1571// DEBUG_LOG(ARM11, "line is %d\n", __LINE__);
1572 return MLnS(ImmediatePreIndexed);
1573// DEBUG_MSG;
1574 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1575 return MLnS(RegisterPreIndexed);
1576 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1577// DEBUG_MSG;
1578 return MLnS(ImmediatePostIndexed);
1579 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1580 //DEBUG_MSG;
1581 return MLnS(RegisterPostIndexed);
1582 } else if (BITS(inst, 23, 27) == 0x11) {
1583 /* 3 */
1584// DEBUG_MSG;
1585// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1586 return LdnStM(IncrementAfter);
1587 } else if (BITS(inst, 23, 27) == 0x13) {
1588// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1589 return LdnStM(IncrementBefore);
1590// DEBUG_MSG;
1591 } else if (BITS(inst, 23, 27) == 0x10) {
1592// DEBUG_MSG;
1593// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1594 return LdnStM(DecrementAfter);
1595 } else if (BITS(inst, 23, 27) == 0x12) {
1596// DEBUG_MSG;
1597// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1598 return LdnStM(DecrementBefore);
1599 }
1600 #if 0
1601 DEBUG_LOG(ARM11, "In %s Unknown addressing mode\n", __FUNCTION__);
1602 DEBUG_LOG(ARM11, "inst:%x\n", inst);
1603 CITRA_IGNORE_EXIT(-1);
1604 #endif
1605 return NULL;
1606}
1607
1608#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s)
1609
1610#define CHECK_RN (inst_cream->Rn == 15)
1611#define CHECK_RM (inst_cream->Rm == 15)
1612#define CHECK_RS (inst_cream->Rs == 15)
1613
1614
1615ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index)
1616{
1617 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst));
1618 adc_inst *inst_cream = (adc_inst *)inst_base->component;
1619
1620 inst_base->cond = BITS(inst, 28, 31);
1621 inst_base->idx = index;
1622 inst_base->br = NON_BRANCH;
1623 inst_base->load_r15 = 0;
1624
1625 inst_cream->I = BIT(inst, 25);
1626 inst_cream->S = BIT(inst, 20);
1627 inst_cream->Rn = BITS(inst, 16, 19);
1628 inst_cream->Rd = BITS(inst, 12, 15);
1629 if (CHECK_RN)
1630 inst_base->load_r15 = 1;
1631 inst_cream->shifter_operand = BITS(inst, 0, 11);
1632 inst_cream->shtop_func = get_shtop(inst);
1633 if (inst_cream->Rd == 15) {
1634 inst_base->br = INDIRECT_BRANCH;
1635 }
1636 return inst_base;
1637}
1638ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index)
1639{
1640 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst));
1641 add_inst *inst_cream = (add_inst *)inst_base->component;
1642
1643 inst_base->cond = BITS(inst, 28, 31);
1644 inst_base->idx = index;
1645 inst_base->br = NON_BRANCH;
1646 inst_base->load_r15 = 0;
1647
1648 inst_cream->I = BIT(inst, 25);
1649 inst_cream->S = BIT(inst, 20);
1650 inst_cream->Rn = BITS(inst, 16, 19);
1651 inst_cream->Rd = BITS(inst, 12, 15);
1652 if (CHECK_RN)
1653 inst_base->load_r15 = 1;
1654 inst_cream->shifter_operand = BITS(inst, 0, 11);
1655 inst_cream->shtop_func = get_shtop(inst);
1656 if (inst_cream->Rd == 15) {
1657 inst_base->br = INDIRECT_BRANCH;
1658 }
1659 return inst_base;
1660}
1661ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index)
1662{
1663 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst));
1664 and_inst *inst_cream = (and_inst *)inst_base->component;
1665
1666 inst_base->cond = BITS(inst, 28, 31);
1667 inst_base->idx = index;
1668 inst_base->br = NON_BRANCH;
1669 inst_base->load_r15 = 0;
1670
1671 inst_cream->I = BIT(inst, 25);
1672 inst_cream->S = BIT(inst, 20);
1673 inst_cream->Rn = BITS(inst, 16, 19);
1674 inst_cream->Rd = BITS(inst, 12, 15);
1675 if (CHECK_RN)
1676 inst_base->load_r15 = 1;
1677 inst_cream->shifter_operand = BITS(inst, 0, 11);
1678 inst_cream->shtop_func = get_shtop(inst);
1679 if (inst_cream->Rd == 15)
1680 inst_base->br = INDIRECT_BRANCH;
1681 return inst_base;
1682}
1683ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index)
1684{
1685 #define POSBRANCH ((inst & 0x7fffff) << 2)
1686 #define NEGBRANCH ((0xff000000 |(inst & 0xffffff)) << 2)
1687
1688 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst));
1689 bbl_inst *inst_cream = (bbl_inst *)inst_base->component;
1690
1691 inst_base->cond = BITS(inst, 28, 31);
1692 inst_base->idx = index;
1693 inst_base->br = DIRECT_BRANCH;
1694
1695 if (BIT(inst, 24))
1696 inst_base->br = CALL;
1697 if (BITS(inst, 28, 31) <= 0xe)
1698 inst_base->br |= COND;
1699
1700 inst_cream->L = BIT(inst, 24);
1701 inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH;
1702
1703 return inst_base;
1704}
1705ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index)
1706{
1707 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst));
1708 bic_inst *inst_cream = (bic_inst *)inst_base->component;
1709
1710 inst_base->cond = BITS(inst, 28, 31);
1711 inst_base->idx = index;
1712 inst_base->br = NON_BRANCH;
1713 inst_base->load_r15 = 0;
1714
1715 inst_cream->I = BIT(inst, 25);
1716 inst_cream->S = BIT(inst, 20);
1717 inst_cream->Rn = BITS(inst, 16, 19);
1718 inst_cream->Rd = BITS(inst, 12, 15);
1719 if (CHECK_RN)
1720 inst_base->load_r15 = 1;
1721 inst_cream->shifter_operand = BITS(inst, 0, 11);
1722 inst_cream->shtop_func = get_shtop(inst);
1723
1724 if (inst_cream->Rd == 15)
1725 inst_base->br = INDIRECT_BRANCH;
1726 return inst_base;
1727}
1728ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
1729ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index)
1730{
1731 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst));
1732 blx_inst *inst_cream = (blx_inst *)inst_base->component;
1733
1734 inst_base->cond = BITS(inst, 28, 31);
1735 inst_base->idx = index;
1736 inst_base->br = INDIRECT_BRANCH;
1737
1738 inst_cream->inst = inst;
1739 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
1740 inst_cream->val.Rm = BITS(inst, 0, 3);
1741 } else {
1742 inst_cream->val.signed_immed_24 = BITS(inst, 0, 23);
1743 //DEBUG_LOG(ARM11, " blx inst is %x\n", inst);
1744 //CITRA_IGNORE_EXIT(-1);
1745// DEBUG_MSG;
1746 }
1747
1748 return inst_base;
1749}
1750ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index)
1751{
1752 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst));
1753 bx_inst *inst_cream = (bx_inst *)inst_base->component;
1754
1755 inst_base->cond = BITS(inst, 28, 31);
1756 inst_base->idx = index;
1757 inst_base->br = INDIRECT_BRANCH;
1758
1759 inst_cream->Rm = BITS(inst, 0, 3);
1760
1761 return inst_base;
1762}
1763ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
1764ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index){
1765 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst));
1766 cdp_inst *inst_cream = (cdp_inst *)inst_base->component;
1767 inst_base->cond = BITS(inst, 28, 31);
1768 inst_base->idx = index;
1769 inst_base->br = NON_BRANCH;
1770 inst_base->load_r15 = 0;
1771
1772 inst_cream->CRm = BITS(inst, 0, 3);
1773 inst_cream->CRd = BITS(inst, 12, 15);
1774 inst_cream->CRn = BITS(inst, 16, 19);
1775 inst_cream->cp_num = BITS(inst, 8, 11);
1776 inst_cream->opcode_2 = BITS(inst, 5, 7);
1777 inst_cream->opcode_1 = BITS(inst, 20, 23);
1778 inst_cream->inst = inst;
1779
1780 DEBUG_LOG(ARM11, "in func %s inst %x index %x\n", __FUNCTION__, inst, index);
1781 return inst_base;
1782}
1783ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index)
1784{
1785 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst));
1786 inst_base->cond = BITS(inst, 28, 31);
1787 inst_base->idx = index;
1788 inst_base->br = NON_BRANCH;
1789
1790 return inst_base;
1791}
1792ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index)
1793{
1794 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst));
1795 clz_inst *inst_cream = (clz_inst *)inst_base->component;
1796
1797 inst_base->cond = BITS(inst, 28, 31);
1798 inst_base->idx = index;
1799 inst_base->br = NON_BRANCH;
1800 inst_base->load_r15 = 0;
1801
1802 inst_cream->Rm = BITS(inst, 0, 3);
1803 inst_cream->Rd = BITS(inst, 12, 15);
1804 if (CHECK_RM)
1805 inst_base->load_r15 = 1;
1806
1807 return inst_base;
1808}
1809ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index)
1810{
1811 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst));
1812 cmn_inst *inst_cream = (cmn_inst *)inst_base->component;
1813
1814 inst_base->cond = BITS(inst, 28, 31);
1815 inst_base->idx = index;
1816 inst_base->br = NON_BRANCH;
1817 inst_base->load_r15 = 0;
1818
1819 inst_cream->I = BIT(inst, 25);
1820 //inst_cream->S = BIT(inst, 20);
1821 inst_cream->Rn = BITS(inst, 16, 19);
1822 //inst_cream->Rd = BITS(inst, 12, 15);
1823 if (CHECK_RN)
1824 inst_base->load_r15 = 1;
1825 inst_cream->shifter_operand = BITS(inst, 0, 11);
1826 inst_cream->shtop_func = get_shtop(inst);
1827 return inst_base;
1828}
1829ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index)
1830{
1831 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst));
1832 cmp_inst *inst_cream = (cmp_inst *)inst_base->component;
1833
1834 inst_base->cond = BITS(inst, 28, 31);
1835 inst_base->idx = index;
1836 inst_base->br = NON_BRANCH;
1837 inst_base->load_r15 = 0;
1838
1839 inst_cream->I = BIT(inst, 25);
1840 inst_cream->Rn = BITS(inst, 16, 19);
1841 if (CHECK_RN)
1842 inst_base->load_r15 = 1;
1843 inst_cream->shifter_operand = BITS(inst, 0, 11);
1844 inst_cream->shtop_func = get_shtop(inst);
1845 return inst_base;
1846}
1847ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index)
1848{
1849 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst));
1850 cps_inst *inst_cream = (cps_inst *)inst_base->component;
1851
1852 inst_base->cond = BITS(inst, 28, 31);
1853 inst_base->idx = index;
1854 inst_base->br = NON_BRANCH;
1855
1856 inst_cream->imod0 = BIT(inst, 18);
1857 inst_cream->imod1 = BIT(inst, 19);
1858 inst_cream->mmod = BIT(inst, 17);
1859 inst_cream->A = BIT(inst, 8);
1860 inst_cream->I = BIT(inst, 7);
1861 inst_cream->F = BIT(inst, 6);
1862 inst_cream->mode = BITS(inst, 0, 4);
1863
1864 return inst_base;
1865}
1866ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index)
1867{
1868 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
1869 mov_inst *inst_cream = (mov_inst *)inst_base->component;
1870
1871 inst_base->cond = BITS(inst, 28, 31);
1872 inst_base->idx = index;
1873 inst_base->br = NON_BRANCH;
1874
1875 inst_cream->I = BIT(inst, 25);
1876 inst_cream->S = BIT(inst, 20);
1877 inst_cream->Rd = BITS(inst, 12, 15);
1878 inst_cream->shifter_operand = BITS(inst, 0, 11);
1879 inst_cream->shtop_func = get_shtop(inst);
1880
1881 if (inst_cream->Rd == 15) {
1882 inst_base->br = INDIRECT_BRANCH;
1883 }
1884 return inst_base;
1885}
1886ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index)
1887{
1888 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst));
1889 eor_inst *inst_cream = (eor_inst *)inst_base->component;
1890
1891 inst_base->cond = BITS(inst, 28, 31);
1892 inst_base->idx = index;
1893 inst_base->br = NON_BRANCH;
1894 inst_base->load_r15 = 0;
1895
1896 inst_cream->I = BIT(inst, 25);
1897 inst_cream->S = BIT(inst, 20);
1898 inst_cream->Rn = BITS(inst, 16, 19);
1899 inst_cream->Rd = BITS(inst, 12, 15);
1900 if (CHECK_RN)
1901 inst_base->load_r15 = 1;
1902 inst_cream->shifter_operand = BITS(inst, 0, 11);
1903 inst_cream->shtop_func = get_shtop(inst);
1904 if (inst_cream->Rd == 15) {
1905 inst_base->br = INDIRECT_BRANCH;
1906 }
1907 return inst_base;
1908}
1909ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index)
1910{
1911 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst));
1912 inst_base->cond = BITS(inst, 28, 31);
1913 inst_base->idx = index;
1914 inst_base->br = NON_BRANCH;
1915
1916 return inst_base;
1917}
1918ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index)
1919{
1920 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1921 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1922
1923 inst_base->cond = BITS(inst, 28, 31);
1924 inst_base->idx = index;
1925 inst_base->br = NON_BRANCH;
1926
1927 inst_cream->inst = inst;
1928 inst_cream->get_addr = get_calc_addr_op(inst);
1929
1930 if (BIT(inst, 15)) {
1931 inst_base->br = INDIRECT_BRANCH;
1932 }
1933 return inst_base;
1934}
1935ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index)
1936{
1937 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
1938 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
1939
1940 inst_base->cond = BITS(inst, 28, 31);
1941 inst_base->idx = index;
1942 inst_base->br = NON_BRANCH;
1943 inst_base->load_r15 = 0;
1944
1945 inst_cream->Rd = BITS(inst, 12, 15);
1946 inst_cream->Rm = BITS(inst, 0, 3);
1947 inst_cream->rotate = BITS(inst, 10, 11);
1948 if (CHECK_RM)
1949 inst_base->load_r15 = 1;
1950
1951 return inst_base;
1952}
1953ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index)
1954{
1955 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1956 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1957
1958 inst_base->cond = BITS(inst, 28, 31);
1959 inst_base->idx = index;
1960 inst_base->br = NON_BRANCH;
1961 inst_base->load_r15 = 0;
1962
1963 inst_cream->inst = inst;
1964 inst_cream->get_addr = get_calc_addr_op(inst);
1965
1966 if (BITS(inst, 12, 15) == 15) {
1967 inst_base->br = INDIRECT_BRANCH;
1968 }
1969 return inst_base;
1970}
1971
1972ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index)
1973{
1974 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1975 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1976
1977 inst_base->cond = BITS(inst, 28, 31);
1978 inst_base->idx = index;
1979 inst_base->br = NON_BRANCH;
1980 inst_base->load_r15 = 0;
1981
1982 inst_cream->inst = inst;
1983 inst_cream->get_addr = get_calc_addr_op(inst);
1984
1985 if (BITS(inst, 12, 15) == 15) {
1986 inst_base->br = INDIRECT_BRANCH;
1987 }
1988 return inst_base;
1989}
1990
1991ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index)
1992{
1993 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
1994 uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
1995
1996 inst_base->cond = BITS(inst, 28, 31);
1997 inst_base->idx = index;
1998 inst_base->br = NON_BRANCH;
1999 inst_base->load_r15 = 0;
2000
2001 inst_cream->Rd = BITS(inst, 12, 15);
2002 inst_cream->rotate = BITS(inst, 10, 11);
2003 inst_cream->Rm = BITS(inst, 0, 3);
2004 if (CHECK_RM)
2005 inst_base->load_r15 = 1;
2006
2007 return inst_base;
2008}
2009ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index)
2010{
2011 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst));
2012 uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component;
2013
2014 inst_base->cond = BITS(inst, 28, 31);
2015 inst_base->idx = index;
2016 inst_base->br = NON_BRANCH;
2017 inst_base->load_r15 = 0;
2018
2019 inst_cream->Rn = BITS(inst, 16, 19);
2020 inst_cream->Rd = BITS(inst, 12, 15);
2021 inst_cream->rotate = BITS(inst, 10, 11);
2022 inst_cream->Rm = BITS(inst, 0, 3);
2023 if (CHECK_RM || CHECK_RN)
2024 inst_base->load_r15 = 1;
2025
2026 return inst_base;
2027}
2028ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index)
2029{
2030 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2031 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2032
2033 inst_base->cond = BITS(inst, 28, 31);
2034 inst_base->idx = index;
2035 inst_base->br = NON_BRANCH;
2036
2037 inst_cream->inst = inst;
2038 inst_cream->get_addr = get_calc_addr_op(inst);
2039
2040 if (BITS(inst, 12, 15) == 15) {
2041 inst_base->br = INDIRECT_BRANCH;
2042 }
2043 return inst_base;
2044}
2045ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index)
2046{
2047 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2048 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2049
2050 inst_base->cond = BITS(inst, 28, 31);
2051 inst_base->idx = index;
2052 inst_base->br = NON_BRANCH;
2053
2054 inst_cream->inst = inst;
2055 if (I_BIT == 0) {
2056 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
2057 } else {
2058 DEBUG_MSG;
2059 }
2060 #if 0
2061 inst_cream->get_addr = get_calc_addr_op(inst);
2062 if(inst == 0x54f13001) {
2063 DEBUG_LOG(ARM11, "get_calc_addr_op:%llx\n", inst_cream->get_addr);
2064 }
2065 #endif
2066
2067 if (BITS(inst, 12, 15) == 15) {
2068 inst_base->br = INDIRECT_BRANCH;
2069 }
2070 return inst_base;
2071}
2072ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index)
2073{
2074 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2075 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2076
2077 inst_base->cond = BITS(inst, 28, 31);
2078 inst_base->idx = index;
2079 inst_base->br = NON_BRANCH;
2080
2081 inst_cream->inst = inst;
2082 inst_cream->get_addr = get_calc_addr_op(inst);
2083
2084 return inst_base;
2085}
2086
2087ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index)
2088{
2089 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2090 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2091
2092 inst_base->cond = BITS(inst, 28, 31);
2093 inst_base->idx = index;
2094 inst_base->br = NON_BRANCH;
2095
2096 inst_cream->inst = inst;
2097 //inst_cream->get_addr = get_calc_addr_op(inst);
2098
2099 if (BITS(inst, 12, 15) == 15) {
2100 inst_base->br = INDIRECT_BRANCH;
2101 }
2102 return inst_base;
2103}
2104ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index)
2105{
2106 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2107 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2108
2109 inst_base->cond = BITS(inst, 28, 31);
2110 inst_base->idx = index;
2111 inst_base->br = NON_BRANCH;
2112
2113 inst_cream->inst = inst;
2114 inst_cream->get_addr = get_calc_addr_op(inst);
2115
2116 if (BITS(inst, 12, 15) == 15) {
2117 inst_base->br = INDIRECT_BRANCH;
2118 }
2119 return inst_base;
2120}
2121ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index)
2122{
2123 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2124 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2125
2126 inst_base->cond = BITS(inst, 28, 31);
2127 inst_base->idx = index;
2128 inst_base->br = NON_BRANCH;
2129
2130 inst_cream->inst = inst;
2131 inst_cream->get_addr = get_calc_addr_op(inst);
2132
2133 if (BITS(inst, 12, 15) == 15) {
2134 inst_base->br = INDIRECT_BRANCH;
2135 }
2136 return inst_base;
2137}
2138ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index)
2139{
2140 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2141 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2142
2143 inst_base->cond = BITS(inst, 28, 31);
2144 inst_base->idx = index;
2145 inst_base->br = NON_BRANCH;
2146
2147 inst_cream->inst = inst;
2148 inst_cream->get_addr = get_calc_addr_op(inst);
2149
2150 if (BITS(inst, 12, 15) == 15) {
2151 inst_base->br = INDIRECT_BRANCH;
2152 }
2153 return inst_base;
2154}
2155ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index)
2156{
2157 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2158 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2159
2160 inst_base->cond = BITS(inst, 28, 31);
2161 inst_base->idx = index;
2162 inst_base->br = NON_BRANCH;
2163
2164 inst_cream->inst = inst;
2165 inst_cream->get_addr = get_calc_addr_op(inst);
2166
2167 if (BITS(inst, 12, 15) == 15) {
2168 inst_base->br = INDIRECT_BRANCH;
2169 }
2170 return inst_base;
2171}
2172ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index)
2173{
2174 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2175 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2176
2177 inst_base->cond = BITS(inst, 28, 31);
2178 inst_base->idx = index;
2179 inst_base->br = NON_BRANCH;
2180
2181 inst_cream->inst = inst;
2182 if (I_BIT == 0) {
2183 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
2184 } else {
2185 DEBUG_MSG;
2186 }
2187
2188 if (BITS(inst, 12, 15) == 15) {
2189 inst_base->br = INDIRECT_BRANCH;
2190 }
2191 return inst_base;
2192}
2193ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index)
2194{
2195 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst));
2196 mcr_inst *inst_cream = (mcr_inst *)inst_base->component;
2197 inst_base->cond = BITS(inst, 28, 31);
2198 inst_base->idx = index;
2199 inst_base->br = NON_BRANCH;
2200
2201 inst_cream->crn = BITS(inst, 16, 19);
2202 inst_cream->crm = BITS(inst, 0, 3);
2203 inst_cream->opcode_1 = BITS(inst, 21, 23);
2204 inst_cream->opcode_2 = BITS(inst, 5, 7);
2205 inst_cream->Rd = BITS(inst, 12, 15);
2206 inst_cream->cp_num = BITS(inst, 8, 11);
2207 inst_cream->inst = inst;
2208 return inst_base;
2209}
2210ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2211ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index)
2212{
2213 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst));
2214 mla_inst *inst_cream = (mla_inst *)inst_base->component;
2215
2216 inst_base->cond = BITS(inst, 28, 31);
2217 inst_base->idx = index;
2218 inst_base->br = NON_BRANCH;
2219 inst_base->load_r15 = 0;
2220
2221 inst_cream->S = BIT(inst, 20);
2222 inst_cream->Rn = BITS(inst, 12, 15);
2223 inst_cream->Rd = BITS(inst, 16, 19);
2224 inst_cream->Rs = BITS(inst, 8, 11);
2225 inst_cream->Rm = BITS(inst, 0, 3);
2226
2227 if (CHECK_RM || CHECK_RN || CHECK_RS)
2228 inst_base->load_r15 = 1;
2229
2230 return inst_base;
2231}
2232ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index)
2233{
2234 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
2235 mov_inst *inst_cream = (mov_inst *)inst_base->component;
2236
2237 inst_base->cond = BITS(inst, 28, 31);
2238 inst_base->idx = index;
2239 inst_base->br = NON_BRANCH;
2240
2241 inst_cream->I = BIT(inst, 25);
2242 inst_cream->S = BIT(inst, 20);
2243 inst_cream->Rd = BITS(inst, 12, 15);
2244 inst_cream->shifter_operand = BITS(inst, 0, 11);
2245 inst_cream->shtop_func = get_shtop(inst);
2246
2247 if (inst_cream->Rd == 15) {
2248 inst_base->br = INDIRECT_BRANCH;
2249 }
2250 return inst_base;
2251}
2252ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index)
2253{
2254 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst));
2255 mrc_inst *inst_cream = (mrc_inst *)inst_base->component;
2256 inst_base->cond = BITS(inst, 28, 31);
2257 inst_base->idx = index;
2258 inst_base->br = NON_BRANCH;
2259
2260 inst_cream->crn = BITS(inst, 16, 19);
2261 inst_cream->crm = BITS(inst, 0, 3);
2262 inst_cream->opcode_1 = BITS(inst, 21, 23);
2263 inst_cream->opcode_2 = BITS(inst, 5, 7);
2264 inst_cream->Rd = BITS(inst, 12, 15);
2265 inst_cream->cp_num = BITS(inst, 8, 11);
2266 inst_cream->inst = inst;
2267 return inst_base;
2268}
2269ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2270ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index)
2271{
2272 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst));
2273 mrs_inst *inst_cream = (mrs_inst *)inst_base->component;
2274
2275 inst_base->cond = BITS(inst, 28, 31);
2276 inst_base->idx = index;
2277 inst_base->br = NON_BRANCH;
2278
2279 inst_cream->Rd = BITS(inst, 12, 15);
2280 inst_cream->R = BIT(inst, 22);
2281
2282 return inst_base;
2283}
2284ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index)
2285{
2286 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst));
2287 msr_inst *inst_cream = (msr_inst *)inst_base->component;
2288
2289 inst_base->cond = BITS(inst, 28, 31);
2290 inst_base->idx = index;
2291 inst_base->br = NON_BRANCH;
2292
2293 inst_cream->field_mask = BITS(inst, 16, 19);
2294 inst_cream->R = BIT(inst, 22);
2295 inst_cream->inst = inst;
2296
2297 return inst_base;
2298}
2299ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index)
2300{
2301 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst));
2302 mul_inst *inst_cream = (mul_inst *)inst_base->component;
2303
2304 inst_base->cond = BITS(inst, 28, 31);
2305 inst_base->idx = index;
2306 inst_base->br = NON_BRANCH;
2307 inst_base->load_r15 = 0;
2308
2309 inst_cream->S = BIT(inst, 20);
2310 inst_cream->Rm = BITS(inst, 0, 3);
2311 inst_cream->Rs = BITS(inst, 8, 11);
2312 inst_cream->Rd = BITS(inst, 16, 19);
2313
2314 if (CHECK_RM || CHECK_RS)
2315 inst_base->load_r15 = 1;
2316 return inst_base;
2317}
2318ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index)
2319{
2320 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst));
2321 mvn_inst *inst_cream = (mvn_inst *)inst_base->component;
2322
2323 inst_base->cond = BITS(inst, 28, 31);
2324 inst_base->idx = index;
2325 inst_base->br = NON_BRANCH;
2326
2327 inst_cream->I = BIT(inst, 25);
2328 inst_cream->S = BIT(inst, 20);
2329 inst_cream->Rd = BITS(inst, 12, 15);
2330 inst_cream->shifter_operand = BITS(inst, 0, 11);
2331 inst_cream->shtop_func = get_shtop(inst);
2332
2333 if (inst_cream->Rd == 15) {
2334 inst_base->br = INDIRECT_BRANCH;
2335 }
2336 return inst_base;
2337
2338}
2339ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index)
2340{
2341 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst));
2342 orr_inst *inst_cream = (orr_inst *)inst_base->component;
2343
2344 inst_base->cond = BITS(inst, 28, 31);
2345 inst_base->idx = index;
2346 inst_base->br = NON_BRANCH;
2347 inst_base->load_r15 = 0;
2348
2349 inst_cream->I = BIT(inst, 25);
2350 inst_cream->S = BIT(inst, 20);
2351 inst_cream->Rd = BITS(inst, 12, 15);
2352 inst_cream->Rn = BITS(inst, 16, 19);
2353 inst_cream->shifter_operand = BITS(inst, 0, 11);
2354 inst_cream->shtop_func = get_shtop(inst);
2355
2356 if (CHECK_RN)
2357 inst_base->load_r15 = 1;
2358 if (inst_cream->Rd == 15) {
2359 inst_base->br = INDIRECT_BRANCH;
2360 }
2361 return inst_base;
2362}
2363ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2364ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2365ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index)
2366{
2367 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst));
2368
2369 inst_base->cond = BITS(inst, 28, 31);
2370 inst_base->idx = index;
2371 inst_base->br = NON_BRANCH;
2372 inst_base->load_r15 = 0;
2373
2374 return inst_base;
2375}
2376ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2377ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2378ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2379ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2380ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2381ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2382ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2383ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2384ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2385ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2386ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index)
2387{
2388 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst));
2389 rev_inst *inst_cream = (rev_inst *)inst_base->component;
2390
2391 inst_base->cond = BITS(inst, 28, 31);
2392 inst_base->idx = index;
2393 inst_base->br = NON_BRANCH;
2394 inst_base->load_r15 = 0;
2395
2396 inst_cream->Rm = BITS(inst, 0, 3);
2397 inst_cream->Rd = BITS(inst, 12, 15);
2398
2399 return inst_base;
2400}
2401ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index){
2402 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst));
2403 rev_inst *inst_cream = (rev_inst *)inst_base->component;
2404
2405 inst_base->cond = BITS(inst, 28, 31);
2406 inst_base->idx = index;
2407 inst_base->br = NON_BRANCH;
2408 inst_base->load_r15 = 0;
2409
2410 inst_cream->Rm = BITS(inst, 0, 3);
2411 inst_cream->Rd = BITS(inst, 12, 15);
2412
2413 return inst_base;
2414}
2415ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2416ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2417ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index)
2418{
2419 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst));
2420 rsb_inst *inst_cream = (rsb_inst *)inst_base->component;
2421
2422 inst_base->cond = BITS(inst, 28, 31);
2423 inst_base->idx = index;
2424 inst_base->br = NON_BRANCH;
2425 inst_base->load_r15 = 0;
2426
2427 inst_cream->I = BIT(inst, 25);
2428 inst_cream->S = BIT(inst, 20);
2429 inst_cream->Rn = BITS(inst, 16, 19);
2430 inst_cream->Rd = BITS(inst, 12, 15);
2431 inst_cream->shifter_operand = BITS(inst, 0, 11);
2432 inst_cream->shtop_func = get_shtop(inst);
2433 if (CHECK_RN)
2434 inst_base->load_r15 = 1;
2435
2436 if (inst_cream->Rd == 15) {
2437 inst_base->br = INDIRECT_BRANCH;
2438 }
2439 return inst_base;
2440}
2441ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index)
2442{
2443 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst));
2444 rsc_inst *inst_cream = (rsc_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->I = BIT(inst, 25);
2452 inst_cream->S = BIT(inst, 20);
2453 inst_cream->Rn = BITS(inst, 16, 19);
2454 inst_cream->Rd = BITS(inst, 12, 15);
2455 inst_cream->shifter_operand = BITS(inst, 0, 11);
2456 inst_cream->shtop_func = get_shtop(inst);
2457 if (CHECK_RN)
2458 inst_base->load_r15 = 1;
2459
2460 if (inst_cream->Rd == 15) {
2461 inst_base->br = INDIRECT_BRANCH;
2462 }
2463 return inst_base;
2464}
2465ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2466ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2467ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2468ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index)
2469{
2470 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst));
2471 sbc_inst *inst_cream = (sbc_inst *)inst_base->component;
2472
2473 inst_base->cond = BITS(inst, 28, 31);
2474 inst_base->idx = index;
2475 inst_base->br = NON_BRANCH;
2476 inst_base->load_r15 = 0;
2477
2478 inst_cream->I = BIT(inst, 25);
2479 inst_cream->S = BIT(inst, 20);
2480 inst_cream->Rn = BITS(inst, 16, 19);
2481 inst_cream->Rd = BITS(inst, 12, 15);
2482 inst_cream->shifter_operand = BITS(inst, 0, 11);
2483 inst_cream->shtop_func = get_shtop(inst);
2484 if (CHECK_RN)
2485 inst_base->load_r15 = 1;
2486
2487 if (inst_cream->Rd == 15) {
2488 inst_base->br = INDIRECT_BRANCH;
2489 }
2490 return inst_base;
2491}
2492ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2493ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2494ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2495ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2496ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2497ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2498ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2499ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2500ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index)
2501{
2502 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst));
2503 smla_inst *inst_cream = (smla_inst *)inst_base->component;
2504
2505 inst_base->cond = BITS(inst, 28, 31);
2506 inst_base->idx = index;
2507 inst_base->br = NON_BRANCH;
2508 inst_base->load_r15 = 0;
2509
2510 inst_cream->x = BIT(inst, 5);
2511 inst_cream->y = BIT(inst, 6);
2512 inst_cream->Rm = BITS(inst, 0, 3);
2513 inst_cream->Rs = BITS(inst, 8, 11);
2514 inst_cream->Rd = BITS(inst, 16, 19);
2515 inst_cream->Rn = BITS(inst, 12, 15);
2516
2517 return inst_base;
2518}
2519ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index){
2520 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
2521 smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
2522
2523 inst_base->cond = BITS(inst, 28, 31);
2524 inst_base->idx = index;
2525 inst_base->br = NON_BRANCH;
2526 inst_base->load_r15 = 0;
2527
2528 inst_cream->m = BIT(inst, 4);
2529 inst_cream->Rn = BITS(inst, 0, 3);
2530 inst_cream->Rm = BITS(inst, 8, 11);
2531 inst_cream->Rd = BITS(inst, 16, 19);
2532 inst_cream->Ra = BITS(inst, 12, 15);
2533
2534 if (CHECK_RM )
2535 inst_base->load_r15 = 1;
2536 return inst_base;
2537}
2538ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index)
2539{
2540 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
2541 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
2542
2543 inst_base->cond = BITS(inst, 28, 31);
2544 inst_base->idx = index;
2545 inst_base->br = NON_BRANCH;
2546 inst_base->load_r15 = 0;
2547
2548 inst_cream->S = BIT(inst, 20);
2549 inst_cream->Rm = BITS(inst, 0, 3);
2550 inst_cream->Rs = BITS(inst, 8, 11);
2551 inst_cream->RdHi = BITS(inst, 16, 19);
2552 inst_cream->RdLo = BITS(inst, 12, 15);
2553
2554 if (CHECK_RM || CHECK_RS)
2555 inst_base->load_r15 = 1;
2556 return inst_base;
2557}
2558ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2559ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2560ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2561ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2562ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2563ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2564ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2565ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2566ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2567ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index)
2568{
2569 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst));
2570 smul_inst *inst_cream = (smul_inst *)inst_base->component;
2571
2572 inst_base->cond = BITS(inst, 28, 31);
2573 inst_base->idx = index;
2574 inst_base->br = NON_BRANCH;
2575 inst_base->load_r15 = 0;
2576
2577 inst_cream->Rd = BITS(inst, 16, 19);
2578 inst_cream->Rs = BITS(inst, 8, 11);
2579 inst_cream->Rm = BITS(inst, 0, 3);
2580
2581 inst_cream->x = BIT(inst, 5);
2582 inst_cream->y = BIT(inst, 6);
2583
2584 if (CHECK_RM || CHECK_RS)
2585 inst_base->load_r15 = 1;
2586 return inst_base;
2587
2588}
2589ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index)
2590{
2591 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
2592 umull_inst *inst_cream = (umull_inst *)inst_base->component;
2593
2594 inst_base->cond = BITS(inst, 28, 31);
2595 inst_base->idx = index;
2596 inst_base->br = NON_BRANCH;
2597 inst_base->load_r15 = 0;
2598
2599 inst_cream->S = BIT(inst, 20);
2600 inst_cream->Rm = BITS(inst, 0, 3);
2601 inst_cream->Rs = BITS(inst, 8, 11);
2602 inst_cream->RdHi = BITS(inst, 16, 19);
2603 inst_cream->RdLo = BITS(inst, 12, 15);
2604
2605 if (CHECK_RM || CHECK_RS)
2606 inst_base->load_r15 = 1;
2607 return inst_base;
2608}
2609
2610ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index)
2611{
2612 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
2613 smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
2614
2615 inst_base->cond = BITS(inst, 28, 31);
2616 inst_base->idx = index;
2617 inst_base->br = NON_BRANCH;
2618 inst_base->load_r15 = 0;
2619
2620 inst_cream->m = BIT(inst, 6);
2621 inst_cream->Rm = BITS(inst, 8, 11);
2622 inst_cream->Rn = BITS(inst, 0, 3);
2623 inst_cream->Rd = BITS(inst, 16, 19);
2624
2625 if (CHECK_RM || CHECK_RN)
2626 inst_base->load_r15 = 1;
2627 return inst_base;
2628}
2629ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2630ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2631ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2632ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2633ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2634ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2635ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2636ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index)
2637{
2638 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst));
2639 inst_base->cond = BITS(inst, 28, 31);
2640 inst_base->idx = index;
2641 inst_base->br = NON_BRANCH;
2642
2643 return inst_base;
2644}
2645ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index)
2646{
2647 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2648 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2649
2650 inst_base->cond = BITS(inst, 28, 31);
2651 inst_base->idx = index;
2652 inst_base->br = NON_BRANCH;
2653
2654 inst_cream->inst = inst;
2655 inst_cream->get_addr = get_calc_addr_op(inst);
2656 return inst_base;
2657}
2658ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index)
2659{
2660 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
2661 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
2662
2663 inst_base->cond = BITS(inst, 28, 31);
2664 inst_base->idx = index;
2665 inst_base->br = NON_BRANCH;
2666 inst_base->load_r15 = 0;
2667
2668 inst_cream->Rd = BITS(inst, 12, 15);
2669 inst_cream->Rm = BITS(inst, 0, 3);
2670 inst_cream->rotate = BITS(inst, 10, 11);
2671
2672 if (CHECK_RM)
2673 inst_base->load_r15 = 1;
2674 return inst_base;
2675}
2676ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index)
2677{
2678 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2679 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2680
2681 inst_base->cond = BITS(inst, 28, 31);
2682 inst_base->idx = index;
2683 inst_base->br = NON_BRANCH;
2684
2685 inst_cream->inst = inst;
2686 inst_cream->get_addr = get_calc_addr_op(inst);
2687
2688 if (BITS(inst, 12, 15) == 15) {
2689 inst_base->br = INDIRECT_BRANCH;
2690 }
2691 return inst_base;
2692}
2693ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index)
2694{
2695 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
2696 uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
2697
2698 inst_base->cond = BITS(inst, 28, 31);
2699 inst_base->idx = index;
2700 inst_base->br = NON_BRANCH;
2701 inst_base->load_r15 = 0;
2702
2703 inst_cream->Rd = BITS(inst, 12, 15);
2704 inst_cream->rotate = BITS(inst, 10, 11);
2705 inst_cream->Rm = BITS(inst, 0, 3);
2706
2707 if (CHECK_RM)
2708 inst_base->load_r15 = 1;
2709 return inst_base;
2710}
2711ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index)
2712{
2713 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
2714 uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component;
2715
2716 inst_base->cond = BITS(inst, 28, 31);
2717 inst_base->idx = index;
2718 inst_base->br = NON_BRANCH;
2719 inst_base->load_r15 = 0;
2720
2721 inst_cream->Rd = BITS(inst, 12, 15);
2722 inst_cream->rotate = BITS(inst, 10, 11);
2723 inst_cream->Rm = BITS(inst, 0, 3);
2724 inst_cream->Rn = BITS(inst, 16, 19);
2725
2726 return inst_base;
2727}
2728ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index)
2729{
2730 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2731 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2732
2733 inst_base->cond = BITS(inst, 28, 31);
2734 inst_base->idx = index;
2735 inst_base->br = NON_BRANCH;
2736
2737 inst_cream->inst = inst;
2738 inst_cream->get_addr = get_calc_addr_op(inst);
2739
2740 if (BITS(inst, 12, 15) == 15) {
2741 inst_base->br = INDIRECT_BRANCH;
2742 }
2743 return inst_base;
2744}
2745ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index)
2746{
2747 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2748 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2749
2750 inst_base->cond = BITS(inst, 28, 31);
2751 inst_base->idx = index;
2752 inst_base->br = NON_BRANCH;
2753
2754 inst_cream->inst = inst;
2755// inst_cream->get_addr = get_calc_addr_op(inst);
2756 if (I_BIT == 0) {
2757 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
2758 } else {
2759 DEBUG_MSG;
2760 }
2761
2762 if (BITS(inst, 12, 15) == 15) {
2763 inst_base->br = INDIRECT_BRANCH;
2764 }
2765 return inst_base;
2766}
2767ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){
2768 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2769 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2770
2771 inst_base->cond = BITS(inst, 28, 31);
2772 inst_base->idx = index;
2773 inst_base->br = NON_BRANCH;
2774
2775 inst_cream->inst = inst;
2776 inst_cream->get_addr = get_calc_addr_op(inst);
2777
2778 if (BITS(inst, 12, 15) == 15) {
2779 inst_base->br = INDIRECT_BRANCH;
2780 }
2781 return inst_base;
2782}
2783ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index)
2784{
2785 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2786 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2787
2788 inst_base->cond = BITS(inst, 28, 31);
2789 inst_base->idx = index;
2790 inst_base->br = NON_BRANCH;
2791
2792 inst_cream->inst = inst;
2793 inst_cream->get_addr = get_calc_addr_op(inst);
2794
2795 if (BITS(inst, 12, 15) == 15) {
2796 inst_base->br = INDIRECT_BRANCH;
2797 }
2798 return inst_base;
2799}
2800ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index)
2801{
2802 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2803 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2804
2805 inst_base->cond = BITS(inst, 28, 31);
2806 inst_base->idx = index;
2807 inst_base->br = NON_BRANCH;
2808
2809 inst_cream->inst = inst;
2810 inst_cream->get_addr = get_calc_addr_op(inst);
2811
2812 if (BITS(inst, 12, 15) == 15) {
2813 inst_base->br = INDIRECT_BRANCH;
2814 }
2815 return inst_base;
2816}
2817ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index)
2818{
2819 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2820 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2821
2822 inst_base->cond = BITS(inst, 28, 31);
2823 inst_base->idx = index;
2824 inst_base->br = NON_BRANCH;
2825
2826 inst_cream->inst = inst;
2827 inst_cream->get_addr = get_calc_addr_op(inst);
2828
2829 if (BITS(inst, 12, 15) == 15) {
2830 inst_base->br = INDIRECT_BRANCH;
2831 }
2832 return inst_base;
2833}
2834ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index)
2835{
2836 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2837 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2838
2839 inst_base->cond = BITS(inst, 28, 31);
2840 inst_base->idx = index;
2841 inst_base->br = NON_BRANCH;
2842
2843 inst_cream->inst = inst;
2844 if (I_BIT == 0) {
2845 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
2846 } else {
2847 DEBUG_MSG;
2848 }
2849
2850 if (BITS(inst, 12, 15) == 15) {
2851 inst_base->br = INDIRECT_BRANCH;
2852 }
2853 return inst_base;
2854}
2855ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index)
2856{
2857 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst));
2858 sub_inst *inst_cream = (sub_inst *)inst_base->component;
2859
2860 inst_base->cond = BITS(inst, 28, 31);
2861 inst_base->idx = index;
2862 inst_base->br = NON_BRANCH;
2863 inst_base->load_r15 = 0;
2864
2865 inst_cream->I = BIT(inst, 25);
2866 inst_cream->S = BIT(inst, 20);
2867 inst_cream->Rn = BITS(inst, 16, 19);
2868 inst_cream->Rd = BITS(inst, 12, 15);
2869 inst_cream->shifter_operand = BITS(inst, 0, 11);
2870 inst_cream->shtop_func = get_shtop(inst);
2871 if (inst_cream->Rd == 15) {
2872 inst_base->br = INDIRECT_BRANCH;
2873 }
2874 if (CHECK_RN)
2875 inst_base->load_r15 = 1;
2876
2877 return inst_base;
2878}
2879ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index)
2880{
2881 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst));
2882 swi_inst *inst_cream = (swi_inst *)inst_base->component;
2883
2884 inst_base->cond = BITS(inst, 28, 31);
2885 inst_base->idx = index;
2886 inst_base->br = NON_BRANCH;
2887
2888 inst_cream->num = BITS(inst, 0, 23);
2889 return inst_base;
2890}
2891ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index)
2892{
2893 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
2894 swp_inst *inst_cream = (swp_inst *)inst_base->component;
2895
2896 inst_base->cond = BITS(inst, 28, 31);
2897 inst_base->idx = index;
2898 inst_base->br = NON_BRANCH;
2899
2900 inst_cream->Rn = BITS(inst, 16, 19);
2901 inst_cream->Rd = BITS(inst, 12, 15);
2902 inst_cream->Rm = BITS(inst, 0, 3);
2903
2904 if (inst_cream->Rd == 15) {
2905 inst_base->br = INDIRECT_BRANCH;
2906 }
2907 return inst_base;
2908}
2909ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){
2910 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
2911 swp_inst *inst_cream = (swp_inst *)inst_base->component;
2912
2913 inst_base->cond = BITS(inst, 28, 31);
2914 inst_base->idx = index;
2915 inst_base->br = NON_BRANCH;
2916
2917 inst_cream->Rn = BITS(inst, 16, 19);
2918 inst_cream->Rd = BITS(inst, 12, 15);
2919 inst_cream->Rm = BITS(inst, 0, 3);
2920
2921 if (inst_cream->Rd == 15) {
2922 inst_base->br = INDIRECT_BRANCH;
2923 }
2924 return inst_base;
2925}
2926ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){
2927 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst));
2928 sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component;
2929
2930 inst_base->cond = BITS(inst, 28, 31);
2931 inst_base->idx = index;
2932 inst_base->br = NON_BRANCH;
2933 inst_base->load_r15 = 0;
2934
2935 inst_cream->Rd = BITS(inst, 12, 15);
2936 inst_cream->rotate = BITS(inst, 10, 11);
2937 inst_cream->Rm = BITS(inst, 0, 3);
2938 inst_cream->Rn = BITS(inst, 16, 19);
2939
2940 return inst_base;
2941}
2942ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2943ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index){
2944 DEBUG_LOG(ARM11, "in func %s, SXTAH untested\n", __func__);
2945 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst));
2946 sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component;
2947
2948 inst_base->cond = BITS(inst, 28, 31);
2949 inst_base->idx = index;
2950 inst_base->br = NON_BRANCH;
2951 inst_base->load_r15 = 0;
2952
2953 inst_cream->Rd = BITS(inst, 12, 15);
2954 inst_cream->rotate = BITS(inst, 10, 11);
2955 inst_cream->Rm = BITS(inst, 0, 3);
2956 inst_cream->Rn = BITS(inst, 16, 19);
2957
2958 return inst_base;
2959}
2960ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
2961ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index)
2962{
2963 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst));
2964 teq_inst *inst_cream = (teq_inst *)inst_base->component;
2965
2966 inst_base->cond = BITS(inst, 28, 31);
2967 inst_base->idx = index;
2968 inst_base->br = NON_BRANCH;
2969 inst_base->load_r15 = 0;
2970
2971 inst_cream->I = BIT(inst, 25);
2972 inst_cream->Rn = BITS(inst, 16, 19);
2973 inst_cream->shifter_operand = BITS(inst, 0, 11);
2974 inst_cream->shtop_func = get_shtop(inst);
2975
2976 if (CHECK_RN)
2977 inst_base->load_r15 = 1;
2978 return inst_base;
2979}
2980ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index)
2981{
2982 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst));
2983 tst_inst *inst_cream = (tst_inst *)inst_base->component;
2984
2985 inst_base->cond = BITS(inst, 28, 31);
2986 inst_base->idx = index;
2987 inst_base->br = NON_BRANCH;
2988 inst_base->load_r15 = 0;
2989
2990 inst_cream->I = BIT(inst, 25);
2991 inst_cream->S = BIT(inst, 20);
2992 inst_cream->Rn = BITS(inst, 16, 19);
2993 inst_cream->Rd = BITS(inst, 12, 15);
2994 inst_cream->shifter_operand = BITS(inst, 0, 11);
2995 inst_cream->shtop_func = get_shtop(inst);
2996 if (inst_cream->Rd == 15) {
2997 inst_base->br = INDIRECT_BRANCH;
2998 }
2999
3000 if (CHECK_RN)
3001 inst_base->load_r15 = 1;
3002 return inst_base;
3003}
3004ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3005ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3006ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3007ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3008ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3009ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3010ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3011ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3012ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3013ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3014ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index)
3015{
3016 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
3017 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
3018
3019 inst_base->cond = BITS(inst, 28, 31);
3020 inst_base->idx = index;
3021 inst_base->br = NON_BRANCH;
3022 inst_base->load_r15 = 0;
3023
3024 inst_cream->S = BIT(inst, 20);
3025 inst_cream->Rm = BITS(inst, 0, 3);
3026 inst_cream->Rs = BITS(inst, 8, 11);
3027 inst_cream->RdHi = BITS(inst, 16, 19);
3028 inst_cream->RdLo = BITS(inst, 12, 15);
3029
3030 if (CHECK_RM || CHECK_RS)
3031 inst_base->load_r15 = 1;
3032 return inst_base;
3033}
3034ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index)
3035{
3036 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
3037 umull_inst *inst_cream = (umull_inst *)inst_base->component;
3038
3039 inst_base->cond = BITS(inst, 28, 31);
3040 inst_base->idx = index;
3041 inst_base->br = NON_BRANCH;
3042 inst_base->load_r15 = 0;
3043
3044 inst_cream->S = BIT(inst, 20);
3045 inst_cream->Rm = BITS(inst, 0, 3);
3046 inst_cream->Rs = BITS(inst, 8, 11);
3047 inst_cream->RdHi = BITS(inst, 16, 19);
3048 inst_cream->RdLo = BITS(inst, 12, 15);
3049
3050 if (CHECK_RM || CHECK_RS)
3051 inst_base->load_r15 = 1;
3052 return inst_base;
3053}
3054
3055ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index)
3056{
3057 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb));
3058 b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component;
3059
3060 inst_cream->imm =((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0);
3061 //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm);
3062 inst_base->idx = index;
3063 inst_base->br = DIRECT_BRANCH;
3064 return inst_base;
3065}
3066
3067ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index)
3068{
3069 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb));
3070 b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component;
3071
3072 inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0));
3073 inst_cream->cond = ((tinst >> 8) & 0xf);
3074 //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x, cond=0x%x\n", __FUNCTION__, tinst, inst_cream->imm, inst_cream->cond);
3075 inst_base->idx = index;
3076 inst_base->br = DIRECT_BRANCH;
3077 return inst_base;
3078}
3079
3080ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index)
3081{
3082 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb));
3083 bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component;
3084
3085 inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0));
3086 //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm);
3087
3088 inst_base->idx = index;
3089 inst_base->br = NON_BRANCH;
3090 return inst_base;
3091}
3092ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index)
3093{
3094 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb));
3095 bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component;
3096
3097 inst_cream->imm = (tinst & 0x07FF) << 1;
3098 //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm);
3099 inst_base->idx = index;
3100 inst_base->br = DIRECT_BRANCH;
3101 return inst_base;
3102}
3103ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index)
3104{
3105 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb));
3106 blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component;
3107
3108 inst_cream->imm = (tinst & 0x07FF) << 1;
3109 //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm);
3110 inst_cream->instr = tinst;
3111 inst_base->idx = index;
3112 inst_base->br = DIRECT_BRANCH;
3113 return inst_base;
3114}
3115
3116ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3117ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3118ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3119ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3120ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3121ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3122ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3123ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3124ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3125ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3126ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3127ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3128ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3129ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3130ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;}
3131
3132
3133
3134/* Floating point VFPv3 structures and instructions */
3135
3136#define VFP_INTERPRETER_STRUCT
3137#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
3138#undef VFP_INTERPRETER_STRUCT
3139
3140#define VFP_INTERPRETER_TRANS
3141#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
3142#undef VFP_INTERPRETER_TRANS
3143
3144
3145
3146typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int);
3147
3148const transop_fp_t arm_instruction_trans[] = {
3149 #define VFP_INTERPRETER_TABLE
3150 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
3151 #undef VFP_INTERPRETER_TABLE
3152 INTERPRETER_TRANSLATE(srs),
3153 INTERPRETER_TRANSLATE(rfe),
3154 INTERPRETER_TRANSLATE(bkpt),
3155 INTERPRETER_TRANSLATE(blx),
3156 INTERPRETER_TRANSLATE(cps),
3157 INTERPRETER_TRANSLATE(pld),
3158 INTERPRETER_TRANSLATE(setend),
3159 INTERPRETER_TRANSLATE(clrex),
3160 INTERPRETER_TRANSLATE(rev16),
3161 INTERPRETER_TRANSLATE(usad8),
3162 INTERPRETER_TRANSLATE(sxtb),
3163 INTERPRETER_TRANSLATE(uxtb),
3164 INTERPRETER_TRANSLATE(sxth),
3165 INTERPRETER_TRANSLATE(sxtb16),
3166 INTERPRETER_TRANSLATE(uxth),
3167 INTERPRETER_TRANSLATE(uxtb16),
3168 INTERPRETER_TRANSLATE(cpy),
3169 INTERPRETER_TRANSLATE(uxtab),
3170 INTERPRETER_TRANSLATE(ssub8),
3171 INTERPRETER_TRANSLATE(shsub8),
3172 INTERPRETER_TRANSLATE(ssubaddx),
3173 INTERPRETER_TRANSLATE(strex),
3174 INTERPRETER_TRANSLATE(strexb),
3175 INTERPRETER_TRANSLATE(swp),
3176 INTERPRETER_TRANSLATE(swpb),
3177 INTERPRETER_TRANSLATE(ssub16),
3178 INTERPRETER_TRANSLATE(ssat16),
3179 INTERPRETER_TRANSLATE(shsubaddx),
3180 INTERPRETER_TRANSLATE(qsubaddx),
3181 INTERPRETER_TRANSLATE(shaddsubx),
3182 INTERPRETER_TRANSLATE(shadd8),
3183 INTERPRETER_TRANSLATE(shadd16),
3184 INTERPRETER_TRANSLATE(sel),
3185 INTERPRETER_TRANSLATE(saddsubx),
3186 INTERPRETER_TRANSLATE(sadd8),
3187 INTERPRETER_TRANSLATE(sadd16),
3188 INTERPRETER_TRANSLATE(shsub16),
3189 INTERPRETER_TRANSLATE(umaal),
3190 INTERPRETER_TRANSLATE(uxtab16),
3191 INTERPRETER_TRANSLATE(usubaddx),
3192 INTERPRETER_TRANSLATE(usub8),
3193 INTERPRETER_TRANSLATE(usub16),
3194 INTERPRETER_TRANSLATE(usat16),
3195 INTERPRETER_TRANSLATE(usada8),
3196 INTERPRETER_TRANSLATE(uqsubaddx),
3197 INTERPRETER_TRANSLATE(uqsub8),
3198 INTERPRETER_TRANSLATE(uqsub16),
3199 INTERPRETER_TRANSLATE(uqaddsubx),
3200 INTERPRETER_TRANSLATE(uqadd8),
3201 INTERPRETER_TRANSLATE(uqadd16),
3202 INTERPRETER_TRANSLATE(sxtab),
3203 INTERPRETER_TRANSLATE(uhsubaddx),
3204 INTERPRETER_TRANSLATE(uhsub8),
3205 INTERPRETER_TRANSLATE(uhsub16),
3206 INTERPRETER_TRANSLATE(uhaddsubx),
3207 INTERPRETER_TRANSLATE(uhadd8),
3208 INTERPRETER_TRANSLATE(uhadd16),
3209 INTERPRETER_TRANSLATE(uaddsubx),
3210 INTERPRETER_TRANSLATE(uadd8),
3211 INTERPRETER_TRANSLATE(uadd16),
3212 INTERPRETER_TRANSLATE(sxtah),
3213 INTERPRETER_TRANSLATE(sxtab16),
3214 INTERPRETER_TRANSLATE(qadd8),
3215 INTERPRETER_TRANSLATE(bxj),
3216 INTERPRETER_TRANSLATE(clz),
3217 INTERPRETER_TRANSLATE(uxtah),
3218 INTERPRETER_TRANSLATE(bx),
3219 INTERPRETER_TRANSLATE(rev),
3220 INTERPRETER_TRANSLATE(blx),
3221 INTERPRETER_TRANSLATE(revsh),
3222 INTERPRETER_TRANSLATE(qadd),
3223 INTERPRETER_TRANSLATE(qadd16),
3224 INTERPRETER_TRANSLATE(qaddsubx),
3225 INTERPRETER_TRANSLATE(ldrex),
3226 INTERPRETER_TRANSLATE(qdadd),
3227 INTERPRETER_TRANSLATE(qdsub),
3228 INTERPRETER_TRANSLATE(qsub),
3229 INTERPRETER_TRANSLATE(ldrexb),
3230 INTERPRETER_TRANSLATE(qsub8),
3231 INTERPRETER_TRANSLATE(qsub16),
3232 INTERPRETER_TRANSLATE(smuad),
3233 INTERPRETER_TRANSLATE(smmul),
3234 INTERPRETER_TRANSLATE(smusd),
3235 INTERPRETER_TRANSLATE(smlsd),
3236 INTERPRETER_TRANSLATE(smlsld),
3237 INTERPRETER_TRANSLATE(smmla),
3238 INTERPRETER_TRANSLATE(smmls),
3239 INTERPRETER_TRANSLATE(smlald),
3240 INTERPRETER_TRANSLATE(smlad),
3241 INTERPRETER_TRANSLATE(smlaw),
3242 INTERPRETER_TRANSLATE(smulw),
3243 INTERPRETER_TRANSLATE(pkhtb),
3244 INTERPRETER_TRANSLATE(pkhbt),
3245 INTERPRETER_TRANSLATE(smul),
3246 INTERPRETER_TRANSLATE(smlalxy),
3247 INTERPRETER_TRANSLATE(smla),
3248 INTERPRETER_TRANSLATE(mcrr),
3249 INTERPRETER_TRANSLATE(mrrc),
3250 INTERPRETER_TRANSLATE(cmp),
3251 INTERPRETER_TRANSLATE(tst),
3252 INTERPRETER_TRANSLATE(teq),
3253 INTERPRETER_TRANSLATE(cmn),
3254 INTERPRETER_TRANSLATE(smull),
3255 INTERPRETER_TRANSLATE(umull),
3256 INTERPRETER_TRANSLATE(umlal),
3257 INTERPRETER_TRANSLATE(smlal),
3258 INTERPRETER_TRANSLATE(mul),
3259 INTERPRETER_TRANSLATE(mla),
3260 INTERPRETER_TRANSLATE(ssat),
3261 INTERPRETER_TRANSLATE(usat),
3262 INTERPRETER_TRANSLATE(mrs),
3263 INTERPRETER_TRANSLATE(msr),
3264 INTERPRETER_TRANSLATE(and),
3265 INTERPRETER_TRANSLATE(bic),
3266 INTERPRETER_TRANSLATE(ldm),
3267 INTERPRETER_TRANSLATE(eor),
3268 INTERPRETER_TRANSLATE(add),
3269 INTERPRETER_TRANSLATE(rsb),
3270 INTERPRETER_TRANSLATE(rsc),
3271 INTERPRETER_TRANSLATE(sbc),
3272 INTERPRETER_TRANSLATE(adc),
3273 INTERPRETER_TRANSLATE(sub),
3274 INTERPRETER_TRANSLATE(orr),
3275 INTERPRETER_TRANSLATE(mvn),
3276 INTERPRETER_TRANSLATE(mov),
3277 INTERPRETER_TRANSLATE(stm),
3278 INTERPRETER_TRANSLATE(ldm),
3279 INTERPRETER_TRANSLATE(ldrsh),
3280 INTERPRETER_TRANSLATE(stm),
3281 INTERPRETER_TRANSLATE(ldm),
3282 INTERPRETER_TRANSLATE(ldrsb),
3283 INTERPRETER_TRANSLATE(strd),
3284 INTERPRETER_TRANSLATE(ldrh),
3285 INTERPRETER_TRANSLATE(strh),
3286 INTERPRETER_TRANSLATE(ldrd),
3287 INTERPRETER_TRANSLATE(strt),
3288 INTERPRETER_TRANSLATE(strbt),
3289 INTERPRETER_TRANSLATE(ldrbt),
3290 INTERPRETER_TRANSLATE(ldrt),
3291 INTERPRETER_TRANSLATE(mrc),
3292 INTERPRETER_TRANSLATE(mcr),
3293 INTERPRETER_TRANSLATE(msr),
3294 INTERPRETER_TRANSLATE(ldrb),
3295 INTERPRETER_TRANSLATE(strb),
3296 INTERPRETER_TRANSLATE(ldr),
3297 INTERPRETER_TRANSLATE(ldrcond),
3298 INTERPRETER_TRANSLATE(str),
3299 INTERPRETER_TRANSLATE(cdp),
3300 INTERPRETER_TRANSLATE(stc),
3301 INTERPRETER_TRANSLATE(ldc),
3302 INTERPRETER_TRANSLATE(swi),
3303 INTERPRETER_TRANSLATE(bbl),
3304 /* All the thumb instructions should be placed the end of table */
3305 INTERPRETER_TRANSLATE(b_2_thumb),
3306 INTERPRETER_TRANSLATE(b_cond_thumb),
3307 INTERPRETER_TRANSLATE(bl_1_thumb),
3308 INTERPRETER_TRANSLATE(bl_2_thumb),
3309 INTERPRETER_TRANSLATE(blx_1_thumb)
3310};
3311
3312typedef map<unsigned int, int> bb_map;
3313bb_map CreamCache[65536];
3314bb_map ProfileCache[65536];
3315
3316//#define USE_DUMMY_CACHE
3317
3318#ifdef USE_DUMMY_CACHE
3319unsigned int DummyCache[0x100000];
3320#endif
3321
3322#define HASH(x) ((x + (x << 3) + (x >> 6)) % 65536)
3323void insert_bb(unsigned int addr, int start)
3324{
3325#ifdef USE_DUMMY_CACHE
3326 DummyCache[addr] = start;
3327#else
3328// CreamCache[addr] = start;
3329 CreamCache[HASH(addr)][addr] = start;
3330#endif
3331}
3332
3333#define TRANS_THRESHOLD 65000
3334int find_bb(unsigned int addr, int &start)
3335{
3336 int ret = -1;
3337#ifdef USE_DUMMY_CACHE
3338 start = DummyCache[addr];
3339 if (start) {
3340 ret = 0;
3341 } else
3342 ret = -1;
3343#else
3344 bb_map::const_iterator it = CreamCache[HASH(addr)].find(addr);
3345 if (it != CreamCache[HASH(addr)].end()) {
3346 start = static_cast<int>(it->second);
3347 ret = 0;
3348#if HYBRID_MODE
3349#if PROFILE
3350#else
3351 /* increase the bb counter */
3352 if(get_bb_prof(cpu, addr, 1) == TRANS_THRESHOLD){
3353 push_to_compiled(cpu, addr);
3354 }
3355#endif
3356#endif
3357 } else {
3358 ret = -1;
3359 }
3360#endif
3361 return ret;
3362}
3363
3364
3365enum {
3366 FETCH_SUCCESS,
3367 FETCH_FAILURE
3368};
3369static tdstate decode_thumb_instr(arm_processor *cpu, uint32_t inst, addr_t addr, uint32_t *arm_inst, uint32_t* inst_size, ARM_INST_PTR* ptr_inst_base){
3370 /* Check if in Thumb mode. */
3371 tdstate ret;
3372 ret = thumb_translate (addr, inst, arm_inst, inst_size);
3373 if(ret == t_branch){
3374 /* FIXME, endian should be judged */
3375 uint32 tinstr;
3376 if((addr & 0x3) != 0)
3377 tinstr = inst >> 16;
3378 else
3379 tinstr = inst & 0xFFFF;
3380
3381 //tinstr = inst & 0xFFFF;
3382 int inst_index;
3383 /* table_length */
3384 int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t);
3385
3386 switch((tinstr & 0xF800) >> 11){
3387 /* we will translate the thumb instruction directly here */
3388 /* we will translate the thumb instruction directly here */
3389 case 26:
3390 case 27:
3391 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){
3392 uint32 cond = (tinstr & 0x0F00) >> 8;
3393 inst_index = table_length - 4;
3394 //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, blx 1 thumb index=%d\n", __FUNCTION__, tinstr, inst_index);
3395 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3396 }
3397 else{
3398 /* something wrong */
3399 DEBUG_LOG(ARM11, "In %s, thumb decoder error\n", __FUNCTION__);
3400 }
3401 break;
3402 case 28:
3403 /* Branch 2, unconditional branch */
3404 inst_index = table_length - 5;
3405 //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, blx 1 thumb index=%d\n", __FUNCTION__, tinstr, inst_index);
3406 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3407 break;
3408
3409 case 8:
3410 case 29:
3411 /* For BLX 1 thumb instruction*/
3412 inst_index = table_length - 1;
3413 //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, blx 1 thumb index=%d, pc=0x%x\n", __FUNCTION__, tinstr, inst_index, cpu->translate_pc);
3414 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3415 break;
3416 case 30:
3417 /* For BL 1 thumb instruction*/
3418 inst_index = table_length - 3;
3419 //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, bl 1 thumb index=%d, pc=0x%x\n", __FUNCTION__, tinstr, inst_index, cpu->translate_pc);
3420 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3421 break;
3422 case 31:
3423 /* For BL 2 thumb instruction*/
3424 inst_index = table_length - 2;
3425 //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, bl 2 thumb index=%d, px=0x%x\n", __FUNCTION__, tinstr, inst_index, cpu->translate_pc);
3426 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3427 break;
3428 default:
3429 ret = t_undefined;
3430 break;
3431 }
3432 }
3433 return ret;
3434}
3435
3436#if 0
3437int FetchInst(cpu_t *core, unsigned int &inst)
3438{
3439 //arm_processor *cpu = (arm_processor *)get_cast_conf_obj(core->cpu_data, "arm_core_t");
3440 arm_processor *cpu = (arm_processor *)(core->cpu_data->obj);
3441// fault_t fault = interpreter_read_memory(cpu->translate_pc, inst, 32);
3442 fault_t fault = interpreter_fetch(core, cpu->translate_pc, inst, 32);
3443 if (!core->is_user_mode) {
3444 if (fault) {
3445 cpu->abortSig = true;
3446 cpu->Aborted = ARMul_PrefetchAbortV;
3447 cpu->AbortAddr = cpu->translate_pc;
3448 cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff;
3449 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->translate_pc;
3450 return FETCH_FAILURE;
3451 }
3452 }
3453 return FETCH_SUCCESS;
3454}
3455#endif
3456
3457unsigned int *InstLength;
3458
3459enum {
3460 KEEP_GOING,
3461 FETCH_EXCEPTION
3462};
3463
3464typedef struct instruction_set_encoding_item ISEITEM;
3465
3466extern const ISEITEM arm_instruction[];
3467
3468vector<uint64_t> code_page_set;
3469
3470void flush_bb(uint32_t addr)
3471{
3472 bb_map::iterator it;
3473 uint32_t start;
3474
3475 addr &= 0xfffff000;
3476 for (int i = 0; i < 65536; i ++) {
3477 for (it = CreamCache[i].begin(); it != CreamCache[i].end(); ) {
3478 start = static_cast<uint32_t>(it->first);
3479 //start = (start >> 12) << 12;
3480 start &= 0xfffff000;
3481 if (start == addr) {
3482 //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first));
3483 CreamCache[i].erase(it ++);
3484 } else
3485 ++it;
3486 }
3487 }
3488
3489 for (int i = 0; i < 65536; i ++) {
3490 for (it = ProfileCache[i].begin(); it != ProfileCache[i].end(); ) {
3491 start = static_cast<uint32_t>(it->first);
3492 //start = (start >> 12) << 12;
3493 start &= 0xfffff000;
3494 if (start == addr) {
3495 //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first));
3496 ProfileCache[i].erase(it ++);
3497 } else
3498 ++it;
3499 }
3500 }
3501
3502 //DEBUG_LOG(ARM11, "flush bb @ %x\n", addr);
3503}
3504
3505//static uint32_t get_bank_addr(void *addr)
3506//{
3507// uint64_t address = (uint64_t)addr;
3508// uint64_t bank0 = get_dma_addr(BANK0_START);
3509// if ((address >= bank0) && (address < (bank0 + BANK0_SIZE))) {
3510// //DEBUG_LOG(ARM11, "1.addr is %llx\n", addr);
3511// return ((uint64_t)addr - bank0) + BANK0_START;
3512// }
3513// return 0;
3514//}
3515
3516/* shenoubang add win32 2012-6-12 */
3517//#ifndef __WIN32__
3518//static void flush_code_cache(int signal_number, siginfo_t *si, void *unused)
3519//{
3520// DEBUG_LOG(ARM11, "in %s, addr=0x%llx\n", __FUNCTION__, si->si_addr);
3521// uint64_t addr = (uint64_t)si->si_addr;
3522// addr = (addr >> 12) << 12;
3523// skyeye_backtrace();
3524// #if 0
3525// if (addr == 0) {
3526// return;
3527// }
3528// const vector<uint64_t>::iterator it = find(code_page_set.begin(),
3529// code_page_set.end(),
3530// (uint64_t)addr);
3531// if (it != code_page_set.end()) {
3532// code_page_set.erase(it);
3533// }
3534// mprotect((void *)addr, 4096, PROT_READ | PROT_WRITE);
3535// //DEBUG_LOG(ARM11, "[flush][ADDR:0x%08llx]\n", addr);
3536// uint32_t phys_addr = get_bank_addr((void *)addr);
3537//// DEBUG_LOG(ARM11, "[PHYSICAL][ADDR:0x%08llx]\n", phys_addr);
3538// flush_bb(phys_addr);
3539// flush_bb(phys_addr + 4096);
3540//#if HYBRID_MODE
3541// /* flush the translated BB of dyncom */
3542// clear_translated_cache(phys_addr);
3543//#endif
3544// #endif
3545//}
3546//#endif /* shenoubang */
3547
3548//void protect_code_page(uint32_t addr)
3549//{
3550// void *mem_ptr = (void *)get_dma_addr(addr);
3551// mem_ptr = (void *)((long long int)mem_ptr & 0xfffffffffffff000LL);
3552//
3553// const vector<uint64_t>::iterator it = find(code_page_set.begin(),
3554// code_page_set.end(),
3555// (uint64_t)mem_ptr);
3556// if (it != code_page_set.end()) {
3557// return;
3558// }
3559// //DEBUG_LOG(ARM11, "[mprotect][ADDR:0x%08llx]\n", mem_ptr);
3560// /* shenoubang add win32 2012-6-12 */
3561//#ifndef __WIN32__
3562// struct sigaction sa;
3563//
3564// memset(&sa, 0, sizeof(sa));
3565// sa.sa_flags = SA_RESTART | SA_SIGINFO;
3566// sa.sa_sigaction = &flush_code_cache;
3567// sigaction(SIGSEGV, &sa, NULL);
3568//
3569// //mprotect(mem_ptr, 4096, PROT_READ);
3570//
3571// code_page_set.push_back((uint64_t)mem_ptr);
3572//#endif /* shenoubang */
3573//}
3574
3575
3576
3577int InterpreterTranslate(arm_processor *cpu, int &bb_start, addr_t addr)
3578{
3579 /* Decode instruction, get index */
3580 /* Allocate memory and init InsCream */
3581 /* Go on next, until terminal instruction */
3582 /* Save start addr of basicblock in CreamCache */
3583 //arm_processor *cpu = (arm_processor *)get_cast_conf_obj(core->cpu_data, "arm_core_t");
3584 //arm_processor *cpu = (arm_processor *)(core->cpu_data->obj);
3585 ARM_INST_PTR inst_base = NULL;
3586 unsigned int inst, inst_size = 4;
3587 int idx;
3588 int ret = NON_BRANCH;
3589 int thumb = 0;
3590 /* instruction size of basic block */
3591 int size = 0;
3592 /* (R15 - 8) ? */
3593 //cpu->translate_pc = cpu->Reg[15];
3594 bb_start = top;
3595
3596 if (cpu->TFlag)
3597 thumb = THUMB;
3598
3599 addr_t phys_addr;
3600 addr_t pc_start;
3601 fault_t fault = NO_FAULT;
3602 //fault = check_address_validity(cpu, addr, &phys_addr, 1, INSN_TLB);
3603 fault = check_address_validity(cpu, addr, &phys_addr, 1);
3604 if(fault != NO_FAULT){
3605 cpu->abortSig = true;
3606 cpu->Aborted = ARMul_PrefetchAbortV;
3607 cpu->AbortAddr = addr;
3608 cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff;
3609 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr;
3610 return FETCH_EXCEPTION;
3611 }
3612 pc_start = phys_addr;
3613 //phys_addr = get_dma_addr(phys_addr);
3614 while(ret == NON_BRANCH) {
3615 /* shenoubang add win32 2012-6-14 */
3616#ifdef __WIN32__
3617 mem_bank_t* bank;
3618 if (bank = bank_ptr(addr)) {
3619 bank->bank_read(32, phys_addr, &inst);
3620 }
3621 else {
3622 DEBUG_LOG(ARM11, "SKYEYE: Read physical addr 0x%x error!!\n", phys_addr);
3623 return FETCH_FAILURE;
3624 }
3625#else
3626 inst = Memory::Read32(phys_addr & 0xFFFFFFFC);//*(uint32_t *)(phys_addr & 0xFFFFFFFC);
3627#endif
3628 //or_tag(core, phys_addr, TAG_FAST_INTERP);
3629
3630 /*if (ret == FETCH_FAILURE) {
3631 return FETCH_EXCEPTION;
3632 }*/
3633
3634 size ++;
3635 /* If we are in thumb instruction, we will translate one thumb to one corresponding arm instruction */
3636 if (cpu->TFlag){
3637 //if(cpu->Cpsr & (1 << THUMB_BIT)){
3638 uint32_t arm_inst;
3639 tdstate state;
3640 state = decode_thumb_instr(cpu, inst, phys_addr, &arm_inst, &inst_size, &inst_base);
3641 //or_tag(core, phys_addr, TAG_THUMB);
3642 //DEBUG_LOG(ARM11, "In thumb state, arm_inst=0x%x, inst_size=0x%x, pc=0x%x\n", arm_inst, inst_size, cpu->translate_pc);
3643 /* we have translated the branch instruction of thumb in thumb decoder */
3644 if(state == t_branch){
3645 goto translated;
3646 }
3647 inst = arm_inst;
3648 }
3649
3650 ret = decode_arm_instr(inst, &idx);
3651 if (ret == DECODE_FAILURE) {
3652 DEBUG_LOG(ARM11, "[info] : Decode failure.\tPC : [0x%x]\tInstruction : [%x]\n", phys_addr, inst);
3653 DEBUG_LOG(ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x\n", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]);
3654 CITRA_IGNORE_EXIT(-1);
3655 }
3656// DEBUG_LOG(ARM11, "PC : [0x%x] INST : %s\n", cpu->translate_pc, arm_instruction[idx].name);
3657 inst_base = arm_instruction_trans[idx](inst, idx);
3658// DEBUG_LOG(ARM11, "translated @ %x INST : %x\n", cpu->translate_pc, inst);
3659// DEBUG_LOG(ARM11, "inst size is %d\n", InstLength[idx]);
3660translated:
3661 phys_addr += inst_size;
3662
3663 if ((phys_addr & 0xfff) == 0) {
3664 inst_base->br = END_OF_PAGE;
3665 }
3666 ret = inst_base->br;
3667 };
3668
3669 //DEBUG_LOG(ARM11, "In %s,insert_bb pc=0x%x, TFlag=0x%x\n", __FUNCTION__, pc_start, cpu->TFlag);
3670 insert_bb(pc_start, bb_start);
3671 return KEEP_GOING;
3672}
3673
3674#define LOG_IN_CLR skyeye_printf_in_color
3675
3676int cmp(const void *x, const void *y)
3677{
3678 return *(unsigned long long int*)x - *(unsigned long long int *)y;
3679}
3680
3681void InterpreterInitInstLength(unsigned long long int *ptr, size_t size)
3682{
3683 int array_size = size / sizeof(void *);
3684 unsigned long long int *InstLabel = new unsigned long long int[array_size];
3685 memcpy(InstLabel, ptr, size);
3686 qsort(InstLabel, array_size, sizeof(void *), cmp);
3687 InstLength = new unsigned int[array_size - 4];
3688 for (int i = 0; i < array_size - 4; i ++) {
3689 for (int j = 0; j < array_size; j ++) {
3690 if (ptr[i] == InstLabel[j]) {
3691 InstLength[i] = InstLabel[j + 1] - InstLabel[j];
3692 break;
3693 }
3694 }
3695 }
3696 for (int i = 0; i < array_size - 4; i ++)
3697 DEBUG_LOG(ARM11, "[%d]:%d\n", i, InstLength[i]);
3698}
3699
3700int clz(unsigned int x)
3701{
3702 int n;
3703 if (x == 0) return (32);
3704 n = 1;
3705 if ((x >> 16) == 0) { n = n + 16; x = x << 16;}
3706 if ((x >> 24) == 0) { n = n + 8; x = x << 8;}
3707 if ((x >> 28) == 0) { n = n + 4; x = x << 4;}
3708 if ((x >> 30) == 0) { n = n + 2; x = x << 2;}
3709 n = n - (x >> 31);
3710 return n;
3711}
3712
3713unsigned arm_dyncom_SWI (ARMul_State * state, ARMword number);
3714
3715static bool InAPrivilegedMode(arm_core_t *core)
3716{
3717 return (core->Mode != USER32MODE);
3718}
3719
3720/* r15 = r15 + 8 */
3721void InterpreterMainLoop(ARMul_State* state)
3722{
3723 #define CRn inst_cream->crn
3724 #define OPCODE_2 inst_cream->opcode_2
3725 #define CRm inst_cream->crm
3726 #define CP15_REG(n) cpu->CP15[CP15(n)]
3727 #define RD cpu->Reg[inst_cream->Rd]
3728 #define RN cpu->Reg[inst_cream->Rn]
3729 #define RM cpu->Reg[inst_cream->Rm]
3730 #define RS cpu->Reg[inst_cream->Rs]
3731 #define RDHI cpu->Reg[inst_cream->RdHi]
3732 #define RDLO cpu->Reg[inst_cream->RdLo]
3733 #define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4)
3734 #define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24)
3735 #define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand)
3736
3737 #if ENABLE_ICOUNTER
3738 #define INC_ICOUNTER cpu->icounter++; \
3739 if(cpu->Reg[15] > 0xc0000000) \
3740 cpu->kernel_icounter++;
3741 //if (debug_function(core)) \
3742 if (core->check_int_flag) \
3743 goto END
3744 //DEBUG_LOG(ARM11, "icounter is %llx line is %d pc is %x\n", cpu->icounter, __LINE__, cpu->Reg[15])
3745 #else
3746 #define INC_ICOUNTER ;
3747 #endif
3748
3749 #define FETCH_INST if (inst_base->br != NON_BRANCH) \
3750 goto PROFILING; \
3751 inst_base = (arm_inst *)&inst_buf[ptr]
3752#define INC_PC(l) ptr += sizeof(arm_inst) + l
3753
3754// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a
3755// clunky switch statement.
3756#if defined __GNUC__ || defined __clang__
3757#define GOTO_NEXT_INST goto *InstLabel[inst_base->idx]
3758#else
3759#define GOTO_NEXT_INST switch(inst_base->idx) { \
3760 case 0: goto VMLA_INST; \
3761 case 1: goto VMLS_INST; \
3762 case 2: goto VNMLA_INST; \
3763 case 3: goto VNMLA_INST; \
3764 case 4: goto VNMLS_INST; \
3765 case 5: goto VNMUL_INST; \
3766 case 6: goto VMUL_INST; \
3767 case 7: goto VADD_INST; \
3768 case 8: goto VSUB_INST; \
3769 case 9: goto VDIV_INST; \
3770 case 10: goto VMOVI_INST; \
3771 case 11: goto VMOVR_INST; \
3772 case 12: goto VABS_INST; \
3773 case 13: goto VNEG_INST; \
3774 case 14: goto VSQRT_INST; \
3775 case 15: goto VCMP_INST; \
3776 case 16: goto VCMP2_INST; \
3777 case 17: goto VCVTBDS_INST; \
3778 case 18: goto VCVTBFF_INST; \
3779 case 19: goto VCVTBFI_INST; \
3780 case 20: goto VMOVBRS_INST; \
3781 case 21: goto VMSR_INST; \
3782 case 22: goto VMOVBRC_INST; \
3783 case 23: goto VMRS_INST; \
3784 case 24: goto VMOVBCR_INST; \
3785 case 25: goto VMOVBRRSS_INST; \
3786 case 26: goto VMOVBRRD_INST; \
3787 case 27: goto VSTR_INST; \
3788 case 28: goto VPUSH_INST; \
3789 case 29: goto VSTM_INST; \
3790 case 30: goto VPOP_INST; \
3791 case 31: goto VLDR_INST; \
3792 case 32: goto VLDM_INST ; \
3793 case 33: goto SRS_INST; \
3794 case 34: goto RFE_INST; \
3795 case 35: goto BKPT_INST; \
3796 case 36: goto BLX_INST; \
3797 case 37: goto CPS_INST; \
3798 case 38: goto PLD_INST; \
3799 case 39: goto SETEND_INST; \
3800 case 40: goto CLREX_INST; \
3801 case 41: goto REV16_INST; \
3802 case 42: goto USAD8_INST; \
3803 case 43: goto SXTB_INST; \
3804 case 44: goto UXTB_INST; \
3805 case 45: goto SXTH_INST; \
3806 case 46: goto SXTB16_INST; \
3807 case 47: goto UXTH_INST; \
3808 case 48: goto UXTB16_INST; \
3809 case 49: goto CPY_INST; \
3810 case 50: goto UXTAB_INST; \
3811 case 51: goto SSUB8_INST; \
3812 case 52: goto SHSUB8_INST; \
3813 case 53: goto SSUBADDX_INST; \
3814 case 54: goto STREX_INST; \
3815 case 55: goto STREXB_INST; \
3816 case 56: goto SWP_INST; \
3817 case 57: goto SWPB_INST; \
3818 case 58: goto SSUB16_INST; \
3819 case 59: goto SSAT16_INST; \
3820 case 60: goto SHSUBADDX_INST; \
3821 case 61: goto QSUBADDX_INST; \
3822 case 62: goto SHADDSUBX_INST; \
3823 case 63: goto SHADD8_INST; \
3824 case 64: goto SHADD16_INST; \
3825 case 65: goto SEL_INST; \
3826 case 66: goto SADDSUBX_INST; \
3827 case 67: goto SADD8_INST; \
3828 case 68: goto SADD16_INST; \
3829 case 69: goto SHSUB16_INST; \
3830 case 70: goto UMAAL_INST; \
3831 case 71: goto UXTAB16_INST; \
3832 case 72: goto USUBADDX_INST; \
3833 case 73: goto USUB8_INST; \
3834 case 74: goto USUB16_INST; \
3835 case 75: goto USAT16_INST; \
3836 case 76: goto USADA8_INST; \
3837 case 77: goto UQSUBADDX_INST; \
3838 case 78: goto UQSUB8_INST; \
3839 case 79: goto UQSUB16_INST; \
3840 case 80: goto UQADDSUBX_INST; \
3841 case 81: goto UQADD8_INST; \
3842 case 82: goto UQADD16_INST; \
3843 case 83: goto SXTAB_INST; \
3844 case 84: goto UHSUBADDX_INST; \
3845 case 85: goto UHSUB8_INST; \
3846 case 86: goto UHSUB16_INST; \
3847 case 87: goto UHADDSUBX_INST; \
3848 case 88: goto UHADD8_INST; \
3849 case 89: goto UHADD16_INST; \
3850 case 90: goto UADDSUBX_INST; \
3851 case 91: goto UADD8_INST; \
3852 case 92: goto UADD16_INST; \
3853 case 93: goto SXTAH_INST; \
3854 case 94: goto SXTAB16_INST; \
3855 case 95: goto QADD8_INST; \
3856 case 96: goto BXJ_INST; \
3857 case 97: goto CLZ_INST; \
3858 case 98: goto UXTAH_INST; \
3859 case 99: goto BX_INST; \
3860 case 100: goto REV_INST; \
3861 case 101: goto BLX_INST; \
3862 case 102: goto REVSH_INST; \
3863 case 103: goto QADD_INST; \
3864 case 104: goto QADD16_INST; \
3865 case 105: goto QADDSUBX_INST; \
3866 case 106: goto LDREX_INST; \
3867 case 107: goto QDADD_INST; \
3868 case 108: goto QDSUB_INST; \
3869 case 109: goto QSUB_INST; \
3870 case 110: goto LDREXB_INST; \
3871 case 111: goto QSUB8_INST; \
3872 case 112: goto QSUB16_INST; \
3873 case 113: goto SMUAD_INST; \
3874 case 114: goto SMMUL_INST; \
3875 case 115: goto SMUSD_INST; \
3876 case 116: goto SMLSD_INST; \
3877 case 117: goto SMLSLD_INST; \
3878 case 118: goto SMMLA_INST; \
3879 case 119: goto SMMLS_INST; \
3880 case 120: goto SMLALD_INST; \
3881 case 121: goto SMLAD_INST; \
3882 case 122: goto SMLAW_INST; \
3883 case 123: goto SMULW_INST; \
3884 case 124: goto PKHTB_INST; \
3885 case 125: goto PKHBT_INST; \
3886 case 126: goto SMUL_INST; \
3887 case 127: goto SMLAL_INST; \
3888 case 128: goto SMLA_INST; \
3889 case 129: goto MCRR_INST; \
3890 case 130: goto MRRC_INST; \
3891 case 131: goto CMP_INST; \
3892 case 132: goto TST_INST; \
3893 case 133: goto TEQ_INST; \
3894 case 134: goto CMN_INST; \
3895 case 135: goto SMULL_INST; \
3896 case 136: goto UMULL_INST; \
3897 case 137: goto UMLAL_INST; \
3898 case 138: goto SMLAL_INST; \
3899 case 139: goto MUL_INST; \
3900 case 140: goto MLA_INST; \
3901 case 141: goto SSAT_INST; \
3902 case 142: goto USAT_INST; \
3903 case 143: goto MRS_INST; \
3904 case 144: goto MSR_INST; \
3905 case 145: goto AND_INST; \
3906 case 146: goto BIC_INST; \
3907 case 147: goto LDM_INST; \
3908 case 148: goto EOR_INST; \
3909 case 149: goto ADD_INST; \
3910 case 150: goto RSB_INST; \
3911 case 151: goto RSC_INST; \
3912 case 152: goto SBC_INST; \
3913 case 153: goto ADC_INST; \
3914 case 154: goto SUB_INST; \
3915 case 155: goto ORR_INST; \
3916 case 156: goto MVN_INST; \
3917 case 157: goto MOV_INST; \
3918 case 158: goto STM_INST; \
3919 case 159: goto LDM_INST; \
3920 case 160: goto LDRSH_INST; \
3921 case 161: goto STM_INST; \
3922 case 162: goto LDM_INST; \
3923 case 163: goto LDRSB_INST; \
3924 case 164: goto STRD_INST; \
3925 case 165: goto LDRH_INST; \
3926 case 166: goto STRH_INST; \
3927 case 167: goto LDRD_INST; \
3928 case 168: goto STRT_INST; \
3929 case 169: goto STRBT_INST; \
3930 case 170: goto LDRBT_INST; \
3931 case 171: goto LDRT_INST; \
3932 case 172: goto MRC_INST; \
3933 case 173: goto MCR_INST; \
3934 case 174: goto MSR_INST; \
3935 case 175: goto LDRB_INST; \
3936 case 176: goto STRB_INST; \
3937 case 177: goto LDR_INST; \
3938 case 178: goto LDRCOND_INST ; \
3939 case 179: goto STR_INST; \
3940 case 180: goto CDP_INST; \
3941 case 181: goto STC_INST; \
3942 case 182: goto LDC_INST; \
3943 case 183: goto SWI_INST; \
3944 case 184: goto BBL_INST; \
3945 case 185: goto B_2_THUMB ; \
3946 case 186: goto B_COND_THUMB ; \
3947 case 187: goto BL_1_THUMB ; \
3948 case 188: goto BL_2_THUMB ; \
3949 case 189: goto BLX_1_THUMB ; \
3950 case 190: goto DISPATCH; \
3951 case 191: goto INIT_INST_LENGTH; \
3952 case 192: goto END; \
3953 }
3954#endif
3955
3956 #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0)
3957 #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1)
3958// #define UPDATE_CFLAG(dst, lop, rop) (cpu->CFlag = ((ISNEG(lop) && ISPOS(rop)) || \
3959 (ISNEG(lop) && ISPOS(dst)) || \
3960 (ISPOS(rop) && ISPOS(dst))))
3961 #define UPDATE_CFLAG(dst, lop, rop) (cpu->CFlag = ((dst < lop) || (dst < rop)))
3962 #define UPDATE_CFLAG_CARRY_FROM_ADD(lop, rop, flag) (cpu->CFlag = (((uint64_t) lop + (uint64_t) rop + (uint64_t) flag) > 0xffffffff) )
3963 #define UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(lop, rop, flag) (cpu->CFlag = ((uint64_t) lop >= ((uint64_t) rop + (uint64_t) flag)))
3964 #define UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop) (cpu->CFlag = (lop >= rop))
3965 #define UPDATE_CFLAG_WITH_NOT(dst, lop, rop) (cpu->CFlag = !(dst < lop))
3966 #define UPDATE_CFLAG_WITH_SC cpu->CFlag = cpu->shifter_carry_out
3967// #define UPDATE_CFLAG_WITH_NOT(dst, lop, rop) cpu->CFlag = !((ISNEG(lop) && ISPOS(rop)) || \
3968 (ISNEG(lop) && ISPOS(dst)) || \
3969 (ISPOS(rop) && ISPOS(dst)))
3970 #define UPDATE_VFLAG(dst, lop, rop) (cpu->VFlag = (((lop < 0) && (rop < 0) && (dst >= 0)) || \
3971 ((lop >= 0) && (rop) >= 0 && (dst < 0))))
3972 #define UPDATE_VFLAG_WITH_NOT(dst, lop, rop) (cpu->VFlag = !(((lop < 0) && (rop < 0) && (dst >= 0)) || \
3973 ((lop >= 0) && (rop) >= 0 && (dst < 0))))
3974 #define UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop) (cpu->VFlag = (((lop ^ rop) & (lop ^ dst)) >> 31))
3975
3976 #define SAVE_NZCVT cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | \
3977 (cpu->NFlag << 31) | \
3978 (cpu->ZFlag << 30) | \
3979 (cpu->CFlag << 29) | \
3980 (cpu->VFlag << 28) | \
3981 (cpu->TFlag << 5)
3982 #define LOAD_NZCVT cpu->NFlag = (cpu->Cpsr >> 31); \
3983 cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \
3984 cpu->CFlag = (cpu->Cpsr >> 29) & 1; \
3985 cpu->VFlag = (cpu->Cpsr >> 28) & 1; \
3986 cpu->TFlag = (cpu->Cpsr >> 5) & 1;
3987
3988 #define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE)
3989 #define PC (cpu->Reg[15])
3990 #define CHECK_EXT_INT if (!cpu->NirqSig) { \
3991 if (!(cpu->Cpsr & 0x80)) { \
3992 goto END; \
3993 } \
3994 }
3995
3996
3997
3998 //arm_processor *cpu = (arm_processor *)get_cast_conf_obj(core->cpu_data, "arm_core_t");
3999 arm_processor *cpu = state; //(arm_processor *)(core->cpu_data->obj);
4000
4001 // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback
4002 // to a clunky switch statement.
4003#if defined __GNUC__ || defined __clang__
4004 void *InstLabel[] = {
4005 #define VFP_INTERPRETER_LABEL
4006 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
4007 #undef VFP_INTERPRETER_LABEL
4008 &&SRS_INST,&&RFE_INST,&&BKPT_INST,&&BLX_INST,&&CPS_INST,&&PLD_INST,&&SETEND_INST,&&CLREX_INST,&&REV16_INST,&&USAD8_INST,&&SXTB_INST,
4009 &&UXTB_INST,&&SXTH_INST,&&SXTB16_INST,&&UXTH_INST,&&UXTB16_INST,&&CPY_INST,&&UXTAB_INST,&&SSUB8_INST,&&SHSUB8_INST,&&SSUBADDX_INST,
4010 &&STREX_INST,&&STREXB_INST,&&SWP_INST,&&SWPB_INST,&&SSUB16_INST,&&SSAT16_INST,&&SHSUBADDX_INST,&&QSUBADDX_INST,&&SHADDSUBX_INST,
4011 &&SHADD8_INST,&&SHADD16_INST,&&SEL_INST,&&SADDSUBX_INST,&&SADD8_INST,&&SADD16_INST,&&SHSUB16_INST,&&UMAAL_INST,&&UXTAB16_INST,
4012 &&USUBADDX_INST,&&USUB8_INST,&&USUB16_INST,&&USAT16_INST,&&USADA8_INST,&&UQSUBADDX_INST,&&UQSUB8_INST,&&UQSUB16_INST,
4013 &&UQADDSUBX_INST,&&UQADD8_INST,&&UQADD16_INST,&&SXTAB_INST,&&UHSUBADDX_INST,&&UHSUB8_INST,&&UHSUB16_INST,&&UHADDSUBX_INST,&&UHADD8_INST,
4014 &&UHADD16_INST,&&UADDSUBX_INST,&&UADD8_INST,&&UADD16_INST,&&SXTAH_INST,&&SXTAB16_INST,&&QADD8_INST,&&BXJ_INST,&&CLZ_INST,&&UXTAH_INST,
4015 &&BX_INST,&&REV_INST,&&BLX_INST,&&REVSH_INST,&&QADD_INST,&&QADD16_INST,&&QADDSUBX_INST,&&LDREX_INST,&&QDADD_INST,&&QDSUB_INST,
4016 &&QSUB_INST,&&LDREXB_INST,&&QSUB8_INST,&&QSUB16_INST,&&SMUAD_INST,&&SMMUL_INST,&&SMUSD_INST,&&SMLSD_INST,&&SMLSLD_INST,&&SMMLA_INST,
4017 &&SMMLS_INST,&&SMLALD_INST,&&SMLAD_INST,&&SMLAW_INST,&&SMULW_INST,&&PKHTB_INST,&&PKHBT_INST,&&SMUL_INST,&&SMLAL_INST,&&SMLA_INST,
4018 &&MCRR_INST,&&MRRC_INST,&&CMP_INST,&&TST_INST,&&TEQ_INST,&&CMN_INST,&&SMULL_INST,&&UMULL_INST,&&UMLAL_INST,&&SMLAL_INST,&&MUL_INST,
4019 &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST,
4020 &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST,
4021 &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST,&&MSR_INST,
4022 &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST,&&SWI_INST,&&BBL_INST,&&B_2_THUMB, &&B_COND_THUMB,
4023 &&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH,&&INIT_INST_LENGTH,&&END
4024 };
4025#endif
4026 arm_inst * inst_base;
4027 unsigned int lop, rop, dst;
4028 unsigned int addr;
4029 unsigned int phys_addr;
4030 unsigned int last_pc = 0;
4031 fault_t fault;
4032 static unsigned int last_physical_base = 0, last_logical_base = 0;
4033 int ptr;
4034
4035 LOAD_NZCVT;
4036 DISPATCH:
4037 {
4038 if (cpu->NumInstrsToExecute == 0)
4039 return;
4040
4041 cpu->NumInstrsToExecute--;
4042
4043 //NOTICE_LOG(ARM11, "instr!");
4044
4045 if (!cpu->NirqSig) {
4046 if (!(cpu->Cpsr & 0x80)) {
4047 goto END;
4048 }
4049 }
4050
4051 if (cpu->TFlag) {
4052 cpu->Reg[15] &= 0xfffffffe;
4053 } else
4054 cpu->Reg[15] &= 0xfffffffc;
4055#if PROFILE
4056 /* check next instruction address is valid. */
4057 last_pc = cpu->Reg[15];
4058#endif
4059#if USER_MODE_OPT
4060 phys_addr = cpu->Reg[15];
4061#else
4062 {
4063 if (last_logical_base == (cpu->Reg[15] & 0xfffff000))
4064 phys_addr = last_physical_base + (cpu->Reg[15] & 0xfff);
4065 else {
4066 /* check next instruction address is valid. */
4067 fault = check_address_validity(cpu, cpu->Reg[15], &phys_addr, 1, INSN_TLB);
4068 if (fault) {
4069 cpu->abortSig = true;
4070 cpu->Aborted = ARMul_PrefetchAbortV;
4071 cpu->AbortAddr = cpu->Reg[15];
4072 cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff;
4073 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->Reg[15];
4074 goto END;
4075 }
4076 last_logical_base = cpu->Reg[15] & 0xfffff000;
4077 last_physical_base = phys_addr & 0xfffff000;
4078 }
4079 }
4080#if HYBRID_MODE
4081 /* check if the native code of dyncom is available */
4082 //fast_map hash_map = core->dyncom_engine->fmap;
4083 //void * pfunc = NULL;
4084 //PFUNC(phys_addr);
4085 //if(pfunc){
4086 if(is_translated_entry(core, phys_addr)){
4087 int rc = JIT_RETURN_NOERR;
4088 //DEBUG_LOG(ARM11, "enter jit icounter is %lld, pc=0x%x\n", core->icounter, cpu->Reg[15]);
4089 SAVE_NZCVT;
4090// resume_timing();
4091 rc = cpu_run(core);
4092 LOAD_NZCVT;
4093 //DEBUG_LOG(ARM11, "out of jit ret is %d icounter is %lld, pc=0x%x\n", rc, core->icounter, cpu->Reg[15]);
4094 if((rc == JIT_RETURN_FUNCNOTFOUND) || (rc == JIT_RETURN_FUNC_BLANK)){
4095 /* keep the tflag same with the bit in CPSR */
4096 //cpu->TFlag = cpu->Cpsr & (1 << THUMB_BIT);
4097 //cpu->TFlag = cpu->Cpsr & (1 << 5);
4098 //switch_mode(cpu, cpu->Cpsr & 0x1f);
4099 //DEBUG_LOG(ARM11, "FUNCTION not found , pc=0x%x\n", cpu->Reg[15]);
4100 fault = check_address_validity(cpu, cpu->Reg[15], &phys_addr, 1, INSN_TLB);
4101 if (fault) {
4102 cpu->abortSig = true;
4103 cpu->Aborted = ARMul_PrefetchAbortV;
4104 cpu->AbortAddr = cpu->Reg[15];
4105 cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff;
4106 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->Reg[15];
4107 goto END;
4108 }
4109 last_logical_base = cpu->Reg[15] & 0xfffff000;
4110 last_physical_base = phys_addr & 0xfffff000;
4111 core->current_page_phys = last_physical_base;
4112 core->current_page_effec = last_logical_base;
4113 //push_to_compiled(core, phys_addr);
4114 }
4115 else{
4116 if((cpu->CP15[CP15(CP15_TLB_FAULT_STATUS)] & 0xf0)){
4117 //DEBUG_LOG(ARM11, "\n\n###############In %s, fsr=0x%x, fault_addr=0x%x, pc=0x%x\n\n", __FUNCTION__, cpu->CP15[CP15(CP15_FAULT_STATUS)], cpu->CP15[CP15(CP15_FAULT_ADDRESS)], cpu->Reg[15]);
4118 //core->Reg[15] -= get_instr_size(cpu_dyncom);
4119 fill_tlb(cpu);
4120 goto END;
4121 }
4122 if (cpu->syscallSig) {
4123 goto END;
4124 }
4125 if (cpu->abortSig) {
4126 cpu->CP15[CP15_TLB_FAULT_STATUS - CP15_BASE] &= 0xFFFFFFF0;
4127 goto END;
4128 }
4129 if (!cpu->NirqSig) {
4130 if (!(cpu->Cpsr & 0x80)) {
4131 goto END;
4132 }
4133 }
4134
4135 /* if regular trap */
4136 cpu->Reg[15] += GET_INST_SIZE(cpu);
4137 /*uint32_t mode = cpu->Cpsr & 0x1f;
4138 if ((mode != cpu->Mode) && (!is_user_mode(core))) {
4139 switch_mode(cpu, mode);
4140 return 1;
4141 }*/
4142
4143 goto END;
4144 }
4145 //phys_addr = cpu->Reg[15];
4146 }
4147 else{
4148 if (last_logical_base == (cpu->Reg[15] & 0xfffff000))
4149 phys_addr = last_physical_base + (cpu->Reg[15] & 0xfff);
4150 else {
4151 /* check next instruction address is valid. */
4152 fault = check_address_validity(cpu, cpu->Reg[15], &phys_addr, 1, INSN_TLB);
4153 if (fault) {
4154 cpu->abortSig = true;
4155 cpu->Aborted = ARMul_PrefetchAbortV;
4156 cpu->AbortAddr = cpu->Reg[15];
4157 cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff;
4158 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->Reg[15];
4159 goto END;
4160 }
4161 last_logical_base = cpu->Reg[15] & 0xfffff000;
4162 last_physical_base = phys_addr & 0xfffff000;
4163 }
4164 }
4165#endif /* #if HYBRID_MODE */
4166#endif /* #if USER_MODE_OPT */
4167 if (true){//if(is_fast_interp_code(core, phys_addr)){
4168 if (find_bb(phys_addr, ptr) == -1)
4169 if (InterpreterTranslate(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
4170 goto END;
4171 }
4172 else{
4173 if (InterpreterTranslate(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
4174 goto END;
4175 }
4176#if PROFILE
4177 resume_timing();
4178#endif
4179 inst_base = (arm_inst *)&inst_buf[ptr];
4180 GOTO_NEXT_INST;
4181 }
4182 PROFILING:
4183 {
4184 goto DISPATCH;
4185 }
4186 ADC_INST:
4187 {
4188 INC_ICOUNTER;
4189 adc_inst *inst_cream = (adc_inst *)inst_base->component;
4190 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4191 lop = RN;
4192 unsigned int sht_op = SHIFTER_OPERAND;
4193 rop = SHIFTER_OPERAND + cpu->CFlag;
4194 RD = dst = lop + rop;
4195 if (inst_cream->S && (inst_cream->Rd == 15)) {
4196 /* cpsr = spsr */
4197 if (CurrentModeHasSPSR) {
4198 cpu->Cpsr = cpu->Spsr_copy;
4199 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
4200 LOAD_NZCVT;
4201 }
4202 } else if (inst_cream->S) {
4203 UPDATE_NFLAG(dst);
4204 UPDATE_ZFLAG(dst);
4205 UPDATE_CFLAG_CARRY_FROM_ADD(lop, sht_op, cpu->CFlag);
4206 UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
4207 }
4208 if (inst_cream->Rd == 15) {
4209 INC_PC(sizeof(adc_inst));
4210 goto PROFILING;
4211 }
4212 }
4213 cpu->Reg[15] += GET_INST_SIZE(cpu);
4214 INC_PC(sizeof(adc_inst));
4215 FETCH_INST;
4216 GOTO_NEXT_INST;
4217 }
4218 ADD_INST:
4219 {
4220 INC_ICOUNTER;
4221 add_inst *inst_cream = (add_inst *)inst_base->component;
4222 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4223 lop = RN;
4224 if (inst_cream->Rn == 15) {
4225 lop += 2 * GET_INST_SIZE(cpu);
4226 }
4227 rop = SHIFTER_OPERAND;
4228 RD = dst = lop + rop;
4229 if (inst_cream->S && (inst_cream->Rd == 15)) {
4230 /* cpsr = spsr*/
4231 if (CurrentModeHasSPSR) {
4232 cpu->Cpsr = cpu->Spsr_copy;
4233 switch_mode(cpu, cpu->Cpsr & 0x1f);
4234 LOAD_NZCVT;
4235 }
4236 } else if (inst_cream->S) {
4237 UPDATE_NFLAG(dst);
4238 UPDATE_ZFLAG(dst);
4239 UPDATE_CFLAG(dst, lop, rop);
4240 UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
4241 }
4242 if (inst_cream->Rd == 15) {
4243 INC_PC(sizeof(add_inst));
4244 goto PROFILING;
4245 }
4246 }
4247 cpu->Reg[15] += GET_INST_SIZE(cpu);
4248 INC_PC(sizeof(add_inst));
4249 FETCH_INST;
4250 GOTO_NEXT_INST;
4251 }
4252 AND_INST:
4253 {
4254 INC_ICOUNTER;
4255 and_inst *inst_cream = (and_inst *)inst_base->component;
4256 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4257 lop = RN;
4258 rop = SHIFTER_OPERAND;
4259 RD = dst = lop & rop;
4260 if (inst_cream->S && (inst_cream->Rd == 15)) {
4261 /* cpsr = spsr*/
4262 if (CurrentModeHasSPSR) {
4263 cpu->Cpsr = cpu->Spsr_copy;
4264 switch_mode(cpu, cpu->Cpsr & 0x1f);
4265 LOAD_NZCVT;
4266 }
4267 } else if (inst_cream->S) {
4268 UPDATE_NFLAG(dst);
4269 UPDATE_ZFLAG(dst);
4270 UPDATE_CFLAG_WITH_SC;
4271 //UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
4272 }
4273 if (inst_cream->Rd == 15) {
4274 INC_PC(sizeof(and_inst));
4275 goto PROFILING;
4276 }
4277 }
4278 cpu->Reg[15] += GET_INST_SIZE(cpu);
4279 INC_PC(sizeof(and_inst));
4280 FETCH_INST;
4281 GOTO_NEXT_INST;
4282 }
4283 BBL_INST:
4284 {
4285 INC_ICOUNTER;
4286 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4287 bbl_inst *inst_cream = (bbl_inst *)inst_base->component;
4288 if (inst_cream->L) {
4289 LINK_RTN_ADDR;
4290 }
4291 SET_PC;
4292 INC_PC(sizeof(bbl_inst));
4293 goto PROFILING;
4294 }
4295 cpu->Reg[15] += GET_INST_SIZE(cpu);
4296 INC_PC(sizeof(bbl_inst));
4297 goto PROFILING;
4298 }
4299 BIC_INST:
4300 {
4301 INC_ICOUNTER;
4302 bic_inst *inst_cream = (bic_inst *)inst_base->component;
4303 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4304 lop = RN;
4305 if (inst_cream->Rn == 15) {
4306 lop += 2 * GET_INST_SIZE(cpu);
4307 }
4308 rop = SHIFTER_OPERAND;
4309// RD = dst = lop & (rop ^ 0xffffffff);
4310 RD = dst = lop & (~rop);
4311 if ((inst_cream->S) && (inst_cream->Rd == 15)) {
4312 /* cpsr = spsr */
4313 if (CurrentModeHasSPSR) {
4314 cpu->Cpsr = cpu->Spsr_copy;
4315 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
4316 LOAD_NZCVT;
4317 }
4318 } else if (inst_cream->S) {
4319 UPDATE_NFLAG(dst);
4320 UPDATE_ZFLAG(dst);
4321 UPDATE_CFLAG_WITH_SC;
4322 }
4323 if (inst_cream->Rd == 15) {
4324 INC_PC(sizeof(bic_inst));
4325 goto PROFILING;
4326 }
4327 }
4328 cpu->Reg[15] += GET_INST_SIZE(cpu);
4329 INC_PC(sizeof(bic_inst));
4330 FETCH_INST;
4331 GOTO_NEXT_INST;
4332 }
4333 BKPT_INST:
4334 BLX_INST:
4335 {
4336 INC_ICOUNTER;
4337 blx_inst *inst_cream = (blx_inst *)inst_base->component;
4338 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4339 unsigned int inst = inst_cream->inst;
4340 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
4341 //LINK_RTN_ADDR;
4342 cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu));
4343 if(cpu->TFlag)
4344 cpu->Reg[14] |= 0x1;
4345 cpu->Reg[15] = cpu->Reg[inst_cream->val.Rm] & 0xfffffffe;
4346 cpu->TFlag = cpu->Reg[inst_cream->val.Rm] & 0x1;
4347 //cpu->Reg[15] = cpu->Reg[BITS(inst, 0, 3)] & 0xfffffffe;
4348 //cpu->TFlag = cpu->Reg[BITS(inst, 0, 3)] & 0x1;
4349 } else {
4350 cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu));
4351 cpu->TFlag = 0x1;
4352 int signed_int = inst_cream->val.signed_immed_24;
4353 signed_int = (signed_int) & 0x800000 ? (0x3F000000 | signed_int) : signed_int;
4354 signed_int = signed_int << 2;
4355 // cpu->Reg[15] = cpu->Reg[15] + 2 * GET_INST_SIZE(cpu)
4356 cpu->Reg[15] = cpu->Reg[15] + 8
4357 + signed_int + (BIT(inst, 24) << 1);
4358 //DEBUG_MSG;
4359 }
4360 INC_PC(sizeof(blx_inst));
4361 goto PROFILING;
4362 }
4363 cpu->Reg[15] += GET_INST_SIZE(cpu);
4364// INC_PC(sizeof(bx_inst));
4365 INC_PC(sizeof(blx_inst));
4366 goto PROFILING;
4367 }
4368 BX_INST:
4369 {
4370 INC_ICOUNTER;
4371 bx_inst *inst_cream = (bx_inst *)inst_base->component;
4372 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4373 if (inst_cream->Rm == 15)
4374 DEBUG_LOG(ARM11, "In %s, BX at pc %x: use of Rm = R15 is discouraged\n", __FUNCTION__, cpu->Reg[15]);
4375 cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1;
4376 cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe;
4377// cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1;
4378 INC_PC(sizeof(bx_inst));
4379 goto PROFILING;
4380 }
4381 cpu->Reg[15] += GET_INST_SIZE(cpu);
4382// INC_PC(sizeof(bx_inst));
4383 INC_PC(sizeof(bx_inst));
4384 goto PROFILING;
4385 }
4386 BXJ_INST:
4387 CDP_INST:
4388 {
4389 INC_ICOUNTER;
4390 cdp_inst *inst_cream = (cdp_inst *)inst_base->component;
4391 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4392 /* FIXME, check if cp access allowed */
4393 #define CP_ACCESS_ALLOW 0
4394 if(CP_ACCESS_ALLOW){
4395 /* undefined instruction here */
4396 return;
4397 }
4398 ERROR_LOG(ARM11, "CDP insn inst=0x%x, pc=0x%x\n", inst_cream->inst, cpu->Reg[15]);
4399 unsigned cpab = (cpu->CDP[inst_cream->cp_num]) (cpu, ARMul_FIRST, inst_cream->inst);
4400 if(cpab != ARMul_DONE){
4401 ERROR_LOG(ARM11, "CDP insn wrong, inst=0x%x, cp_num=0x%x\n", inst_cream->inst, inst_cream->cp_num);
4402 //CITRA_IGNORE_EXIT(-1);
4403 }
4404 }
4405 cpu->Reg[15] += GET_INST_SIZE(cpu);
4406 INC_PC(sizeof(cdp_inst));
4407 FETCH_INST;
4408 GOTO_NEXT_INST;
4409 }
4410
4411 CLREX_INST:
4412 {
4413 INC_ICOUNTER;
4414 remove_exclusive(cpu, 0);
4415 cpu->exclusive_state = 0;
4416
4417 cpu->Reg[15] += GET_INST_SIZE(cpu);
4418 INC_PC(sizeof(clrex_inst));
4419 FETCH_INST;
4420 GOTO_NEXT_INST;
4421 }
4422 CLZ_INST:
4423 {
4424 INC_ICOUNTER;
4425 clz_inst *inst_cream = (clz_inst *)inst_base->component;
4426 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4427 RD = clz(RM);
4428 }
4429 cpu->Reg[15] += GET_INST_SIZE(cpu);
4430 INC_PC(sizeof(clz_inst));
4431 FETCH_INST;
4432 GOTO_NEXT_INST;
4433 }
4434 CMN_INST:
4435 {
4436 INC_ICOUNTER;
4437 cmn_inst *inst_cream = (cmn_inst *)inst_base->component;
4438 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4439// DEBUG_LOG(ARM11, "RN is %x\n", RN);
4440 lop = RN;
4441 rop = SHIFTER_OPERAND;
4442 dst = lop + rop;
4443 UPDATE_NFLAG(dst);
4444 UPDATE_ZFLAG(dst);
4445 UPDATE_CFLAG(dst, lop, rop);
4446 UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
4447 }
4448 cpu->Reg[15] += GET_INST_SIZE(cpu);
4449 INC_PC(sizeof(cmn_inst));
4450 FETCH_INST;
4451 GOTO_NEXT_INST;
4452 }
4453 CMP_INST:
4454 {
4455// DEBUG_LOG(ARM11, "cmp inst\n");
4456// DEBUG_LOG(ARM11, "pc: %x\n", cpu->Reg[15]);
4457 INC_ICOUNTER;
4458 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4459// DEBUG_LOG(ARM11, "r0 is %x\n", cpu->Reg[0]);
4460 cmp_inst *inst_cream = (cmp_inst *)inst_base->component;
4461 lop = RN;
4462 if (inst_cream->Rn == 15) {
4463 lop += 2 * GET_INST_SIZE(cpu);
4464 }
4465 rop = SHIFTER_OPERAND;
4466 dst = lop - rop;
4467
4468 UPDATE_NFLAG(dst);
4469 UPDATE_ZFLAG(dst);
4470// UPDATE_CFLAG(dst, lop, rop);
4471 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
4472// UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
4473 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
4474// UPDATE_VFLAG_WITH_NOT(dst, lop, rop);
4475 }
4476 cpu->Reg[15] += GET_INST_SIZE(cpu);
4477 INC_PC(sizeof(cmp_inst));
4478 FETCH_INST;
4479 GOTO_NEXT_INST;
4480 }
4481 CPS_INST:
4482 {
4483 INC_ICOUNTER;
4484 cps_inst *inst_cream = (cps_inst *)inst_base->component;
4485 uint32_t aif_val = 0;
4486 uint32_t aif_mask = 0;
4487 if (InAPrivilegedMode(cpu)) {
4488 /* isInAPrivilegedMode */
4489 if (inst_cream->imod1) {
4490 if (inst_cream->A) {
4491 aif_val |= (inst_cream->imod0 << 8);
4492 aif_mask |= 1 << 8;
4493 }
4494 if (inst_cream->I) {
4495 aif_val |= (inst_cream->imod0 << 7);
4496 aif_mask |= 1 << 7;
4497 }
4498 if (inst_cream->F) {
4499 aif_val |= (inst_cream->imod0 << 6);
4500 aif_mask |= 1 << 6;
4501 }
4502 aif_mask = ~aif_mask;
4503 cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val;
4504 }
4505 if (inst_cream->mmod) {
4506 cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode;
4507 switch_mode(cpu, inst_cream->mode);
4508 }
4509 }
4510 cpu->Reg[15] += GET_INST_SIZE(cpu);
4511 INC_PC(sizeof(cps_inst));
4512 FETCH_INST;
4513 GOTO_NEXT_INST;
4514 }
4515 CPY_INST:
4516 {
4517 INC_ICOUNTER;
4518 mov_inst *inst_cream = (mov_inst *)inst_base->component;
4519// cpy_inst *inst_cream = (cpy_inst *)inst_base->component;
4520 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4521 RD = SHIFTER_OPERAND;
4522// RD = RM;
4523 if ((inst_cream->Rd == 15)) {
4524 INC_PC(sizeof(mov_inst));
4525 goto PROFILING;
4526 }
4527 }
4528// DEBUG_LOG(ARM11, "cpy inst %x\n", cpu->Reg[15]);
4529 cpu->Reg[15] += GET_INST_SIZE(cpu);
4530 INC_PC(sizeof(mov_inst));
4531 FETCH_INST;
4532 GOTO_NEXT_INST;
4533 }
4534 EOR_INST:
4535 {
4536 INC_ICOUNTER;
4537 eor_inst *inst_cream = (eor_inst *)inst_base->component;
4538 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4539 lop = RN;
4540 if (inst_cream->Rn == 15) {
4541 lop += 2 * GET_INST_SIZE(cpu);
4542 }
4543 rop = SHIFTER_OPERAND;
4544 RD = dst = lop ^ rop;
4545 if (inst_cream->S && (inst_cream->Rd == 15)) {
4546 /* cpsr = spsr*/
4547 if (CurrentModeHasSPSR) {
4548 cpu->Cpsr = cpu->Spsr_copy;
4549 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
4550 LOAD_NZCVT;
4551 }
4552 } else if (inst_cream->S) {
4553 UPDATE_NFLAG(dst);
4554 UPDATE_ZFLAG(dst);
4555 UPDATE_CFLAG_WITH_SC;
4556// UPDATE_CFLAG(dst, lop, rop);
4557// UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
4558 }
4559 if (inst_cream->Rd == 15) {
4560 INC_PC(sizeof(eor_inst));
4561 goto PROFILING;
4562 }
4563 }
4564 cpu->Reg[15] += GET_INST_SIZE(cpu);
4565 INC_PC(sizeof(eor_inst));
4566 FETCH_INST;
4567 GOTO_NEXT_INST;
4568 }
4569 LDC_INST:
4570 {
4571 INC_ICOUNTER;
4572 /* NOT IMPL */
4573 cpu->Reg[15] += GET_INST_SIZE(cpu);
4574 INC_PC(sizeof(ldc_inst));
4575 FETCH_INST;
4576 GOTO_NEXT_INST;
4577 }
4578 LDM_INST:
4579 {
4580 INC_ICOUNTER;
4581 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4582 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4583 int i;
4584 unsigned int ret;
4585 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4586 if (fault) {
4587 goto MMU_EXCEPTION;
4588 }
4589 unsigned int inst = inst_cream->inst;
4590 if (BIT(inst, 22) && !BIT(inst, 15)) {
4591// DEBUG_MSG;
4592 #if 1
4593 /* LDM (2) user */
4594 for (i = 0; i < 13; i++) {
4595 if(BIT(inst, i)){
4596 #if 0
4597 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4598 if (fault) {
4599 goto MMU_EXCEPTION;
4600 }
4601 #endif
4602 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4603 //if (fault) goto MMU_EXCEPTION;
4604 cpu->Reg[i] = ret;
4605 addr += 4;
4606 if ((addr & 0xfff) == 0) {
4607 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4608 } else {
4609 phys_addr += 4;
4610 }
4611 }
4612 }
4613 if (BIT(inst, 13)) {
4614 #if 0
4615 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4616 if (fault) {
4617 goto MMU_EXCEPTION;
4618 }
4619 #endif
4620 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4621 //if (fault) goto MMU_EXCEPTION;
4622 if (cpu->Mode == USER32MODE)
4623 cpu->Reg[13] = ret;
4624 else
4625 cpu->Reg_usr[0] = ret;
4626 addr += 4;
4627 if ((addr & 0xfff) == 0) {
4628 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4629 } else {
4630 phys_addr += 4;
4631 }
4632 }
4633 if (BIT(inst, 14)) {
4634 #if 0
4635 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4636 if (fault) {
4637 goto MMU_EXCEPTION;
4638 }
4639 #endif
4640 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4641 //if (fault) goto MMU_EXCEPTION;
4642 if (cpu->Mode == USER32MODE)
4643 cpu->Reg[14] = ret;
4644 else
4645 cpu->Reg_usr[1] = ret;
4646 }
4647 #endif
4648 } else if (!BIT(inst, 22)) {
4649 for( i = 0; i < 16; i ++ ){
4650 if(BIT(inst, i)){
4651 //bus_read(32, addr, &ret);
4652 #if 0
4653 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4654 if (fault) {
4655 goto MMU_EXCEPTION;
4656 }
4657 #endif
4658 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4659 if (fault) goto MMU_EXCEPTION;
4660 /* For armv5t, should enter thumb when bits[0] is non-zero. */
4661 if(i == 15){
4662 cpu->TFlag = ret & 0x1;
4663 ret &= 0xFFFFFFFE;
4664 //DEBUG_LOG(ARM11, "In %s, TFlag ret=0x%x\n", __FUNCTION__, ret);
4665 }
4666
4667 cpu->Reg[i] = ret;
4668 addr += 4;
4669 if ((addr & 0xfff) == 0) {
4670 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4671 } else {
4672 phys_addr += 4;
4673 }
4674 }
4675 }
4676 } else if (BIT(inst, 22) && BIT(inst, 15)) {
4677 for( i = 0; i < 15; i ++ ){
4678 if(BIT(inst, i)){
4679 #if 0
4680 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4681 if (fault) {
4682 goto MMU_EXCEPTION;
4683 }
4684 #endif
4685 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4686 //if (fault) goto MMU_EXCEPTION;
4687 cpu->Reg[i] = ret;
4688 addr += 4;
4689 if ((addr & 0xfff) == 0) {
4690 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4691 } else {
4692 phys_addr += 4;
4693 }
4694 }
4695 }
4696
4697 if (CurrentModeHasSPSR) {
4698 cpu->Cpsr = cpu->Spsr_copy;
4699 switch_mode(cpu, cpu->Cpsr & 0x1f);
4700 LOAD_NZCVT;
4701 }
4702 #if 0
4703 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4704 if (fault) {
4705 goto MMU_EXCEPTION;
4706 }
4707 #endif
4708 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4709 if (fault) {
4710 goto MMU_EXCEPTION;
4711 }
4712 cpu->Reg[15] = ret;
4713 #if 0
4714 addr += 4;
4715 phys_addr += 4;
4716 #endif
4717 }
4718 if (BIT(inst, 15)) {
4719 INC_PC(sizeof(ldst_inst));
4720 goto PROFILING;
4721 }
4722 }
4723 cpu->Reg[15] += GET_INST_SIZE(cpu);
4724 INC_PC(sizeof(ldst_inst));
4725 FETCH_INST;
4726 GOTO_NEXT_INST;
4727 }
4728 SXTH_INST:
4729 {
4730 INC_ICOUNTER;
4731 sxth_inst *inst_cream = (sxth_inst *)inst_base->component;
4732 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4733 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
4734 if (BIT(operand2, 15)) {
4735 operand2 |= 0xffff0000;
4736 } else {
4737 operand2 &= 0xffff;
4738 }
4739 RD = operand2;
4740 }
4741 cpu->Reg[15] += GET_INST_SIZE(cpu);
4742 INC_PC(sizeof(sxth_inst));
4743 FETCH_INST;
4744 GOTO_NEXT_INST;
4745 }
4746 LDR_INST:
4747 {
4748 INC_ICOUNTER;
4749 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4750 //if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4751 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4752 if (fault) goto MMU_EXCEPTION;
4753 unsigned int value;
4754 //bus_read(32, addr, &value);
4755 fault = interpreter_read_memory(addr, phys_addr, value, 32);
4756 if (BIT(CP15_REG(CP15_CONTROL), 22) == 1)
4757 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4758 else {
4759 value = ROTATE_RIGHT_32(value,(8*(addr&0x3)));
4760 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4761 }
4762 if (BITS(inst_cream->inst, 12, 15) == 15) {
4763 /* For armv5t, should enter thumb when bits[0] is non-zero. */
4764 cpu->TFlag = value & 0x1;
4765 cpu->Reg[15] &= 0xFFFFFFFE;
4766 INC_PC(sizeof(ldst_inst));
4767 goto PROFILING;
4768 }
4769 //}
4770 cpu->Reg[15] += GET_INST_SIZE(cpu);
4771 INC_PC(sizeof(ldst_inst));
4772 FETCH_INST;
4773 GOTO_NEXT_INST;
4774 }
4775 LDRCOND_INST:
4776 {
4777 INC_ICOUNTER;
4778 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4779 if (CondPassed(cpu, inst_base->cond)) {
4780 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4781 if (fault) goto MMU_EXCEPTION;
4782 unsigned int value;
4783 //bus_read(32, addr, &value);
4784 fault = interpreter_read_memory(addr, phys_addr, value, 32);
4785 if (BIT(CP15_REG(CP15_CONTROL), 22) == 1)
4786 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4787 else {
4788 value = ROTATE_RIGHT_32(value,(8*(addr&0x3)));
4789 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4790 }
4791
4792 if (BITS(inst_cream->inst, 12, 15) == 15) {
4793 /* For armv5t, should enter thumb when bits[0] is non-zero. */
4794 cpu->TFlag = value & 0x1;
4795 cpu->Reg[15] &= 0xFFFFFFFE;
4796 INC_PC(sizeof(ldst_inst));
4797 goto PROFILING;
4798 }
4799 }
4800 cpu->Reg[15] += GET_INST_SIZE(cpu);
4801 INC_PC(sizeof(ldst_inst));
4802 FETCH_INST;
4803 GOTO_NEXT_INST;
4804 }
4805 UXTH_INST:
4806 {
4807 INC_ICOUNTER;
4808 uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
4809 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4810 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate)
4811 & 0xffff;
4812 RD = operand2;
4813 }
4814 cpu->Reg[15] += GET_INST_SIZE(cpu);
4815 INC_PC(sizeof(uxth_inst));
4816 FETCH_INST;
4817 GOTO_NEXT_INST;
4818 }
4819 UXTAH_INST:
4820 {
4821 INC_ICOUNTER;
4822 uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component;
4823 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4824 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate)
4825 & 0xffff;
4826 RD = RN + operand2;
4827 if (inst_cream->Rn == 15 || inst_cream->Rm == 15) {
4828 DEBUG_LOG(ARM11, "in line %d\n", __LINE__);
4829 CITRA_IGNORE_EXIT(-1);
4830 }
4831 }
4832 cpu->Reg[15] += GET_INST_SIZE(cpu);
4833 INC_PC(sizeof(uxtah_inst));
4834 FETCH_INST;
4835 GOTO_NEXT_INST;
4836 }
4837 LDRB_INST:
4838 {
4839 INC_ICOUNTER;
4840 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4841 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4842 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4843 if (fault) goto MMU_EXCEPTION;
4844 unsigned int value;
4845 fault = interpreter_read_memory(addr, phys_addr, value, 8);
4846 if (fault) goto MMU_EXCEPTION;
4847 //bus_read(8, addr, &value);
4848 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4849 if (BITS(inst_cream->inst, 12, 15) == 15) {
4850 INC_PC(sizeof(ldst_inst));
4851 goto PROFILING;
4852 }
4853 }
4854 cpu->Reg[15] += GET_INST_SIZE(cpu);
4855 INC_PC(sizeof(ldst_inst));
4856 FETCH_INST;
4857 GOTO_NEXT_INST;
4858 }
4859 LDRBT_INST:
4860 {
4861 INC_ICOUNTER;
4862 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4863 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4864 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4865 if (fault) goto MMU_EXCEPTION;
4866 unsigned int value;
4867 fault = interpreter_read_memory(addr, phys_addr, value, 8);
4868 if (fault) goto MMU_EXCEPTION;
4869 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4870 if (BITS(inst_cream->inst, 12, 15) == 15) {
4871 INC_PC(sizeof(ldst_inst));
4872 goto PROFILING;
4873 }
4874 }
4875 cpu->Reg[15] += GET_INST_SIZE(cpu);
4876 INC_PC(sizeof(ldst_inst));
4877 FETCH_INST;
4878 GOTO_NEXT_INST;
4879 }
4880 LDRD_INST:
4881 {
4882 INC_ICOUNTER;
4883 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4884 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4885 /* Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0) */
4886 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4887 if (fault) goto MMU_EXCEPTION;
4888 uint32_t rear_phys_addr;
4889 fault = check_address_validity(cpu, addr + 4, &rear_phys_addr, 1);
4890 if(fault){
4891 ERROR_LOG(ARM11, "mmu fault , should rollback the above get_addr\n");
4892 CITRA_IGNORE_EXIT(-1);
4893 goto MMU_EXCEPTION;
4894 }
4895 unsigned int value;
4896 fault = interpreter_read_memory(addr, phys_addr, value, 32);
4897 if (fault) goto MMU_EXCEPTION;
4898 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4899 fault = interpreter_read_memory(addr + 4, rear_phys_addr, value, 32);
4900 if (fault) goto MMU_EXCEPTION;
4901 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = value;
4902 /* No dispatch since this operation should not modify R15 */
4903 }
4904 cpu->Reg[15] += 4;
4905 INC_PC(sizeof(ldst_inst));
4906 FETCH_INST;
4907 GOTO_NEXT_INST;
4908 }
4909
4910 LDREX_INST:
4911 {
4912 INC_ICOUNTER;
4913 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4914 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4915 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)];
4916 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4917 if (fault) goto MMU_EXCEPTION;
4918 unsigned int value;
4919 fault = interpreter_read_memory(addr, phys_addr, value, 32);
4920 if (fault) goto MMU_EXCEPTION;
4921
4922 add_exclusive_addr(cpu, phys_addr);
4923 cpu->exclusive_state = 1;
4924
4925 //bus_read(32, addr, &value);
4926 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4927 if (BITS(inst_cream->inst, 12, 15) == 15) {
4928 INC_PC(sizeof(ldst_inst));
4929 goto PROFILING;
4930 }
4931 }
4932 cpu->Reg[15] += GET_INST_SIZE(cpu);
4933 INC_PC(sizeof(ldst_inst));
4934 FETCH_INST;
4935 GOTO_NEXT_INST;
4936 }
4937 LDREXB_INST:
4938 {
4939 INC_ICOUNTER;
4940 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4941 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4942 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)];
4943 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4944 if (fault) goto MMU_EXCEPTION;
4945 unsigned int value;
4946 fault = interpreter_read_memory(addr, phys_addr, value, 8);
4947 if (fault) goto MMU_EXCEPTION;
4948
4949 add_exclusive_addr(cpu, phys_addr);
4950 cpu->exclusive_state = 1;
4951
4952 //bus_read(8, addr, &value);
4953 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4954 if (BITS(inst_cream->inst, 12, 15) == 15) {
4955 INC_PC(sizeof(ldst_inst));
4956 goto PROFILING;
4957 }
4958 }
4959 cpu->Reg[15] += GET_INST_SIZE(cpu);
4960 INC_PC(sizeof(ldst_inst));
4961 FETCH_INST;
4962 GOTO_NEXT_INST;
4963 }
4964 LDRH_INST:
4965 {
4966 INC_ICOUNTER;
4967 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4968 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4969 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4970 if (fault) goto MMU_EXCEPTION;
4971 unsigned int value = 0;
4972 fault = interpreter_read_memory(addr, phys_addr, value, 16);
4973// fault = interpreter_read_memory(addr, value, 32);
4974 if (fault) goto MMU_EXCEPTION;
4975 //if (value == 0xffff && cpu->icounter > 190000000 && cpu->icounter < 210000000) {
4976 // value = 0xffffffff;
4977 //}
4978 //bus_read(16, addr, &value);
4979// cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value & 0xffff;
4980 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4981 if (BITS(inst_cream->inst, 12, 15) == 15) {
4982 INC_PC(sizeof(ldst_inst));
4983 goto PROFILING;
4984 }
4985 }
4986 cpu->Reg[15] += GET_INST_SIZE(cpu);
4987 INC_PC(sizeof(ldst_inst));
4988 FETCH_INST;
4989 GOTO_NEXT_INST;
4990 }
4991 LDRSB_INST:
4992 {
4993 INC_ICOUNTER;
4994 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4995 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4996 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4997 if (fault) goto MMU_EXCEPTION;
4998 unsigned int value;
4999// DEBUG_LOG(ARM11, "ldrsb addr is %x\n", addr);
5000 fault = interpreter_read_memory(addr, phys_addr, value, 8);
5001 if (fault) goto MMU_EXCEPTION;
5002 //bus_read(8, addr, &value);
5003 if (BIT(value, 7)) {
5004 value |= 0xffffff00;
5005 }
5006 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5007 if (BITS(inst_cream->inst, 12, 15) == 15) {
5008 INC_PC(sizeof(ldst_inst));
5009 goto PROFILING;
5010 }
5011 }
5012 cpu->Reg[15] += GET_INST_SIZE(cpu);
5013 INC_PC(sizeof(ldst_inst));
5014 FETCH_INST;
5015 GOTO_NEXT_INST;
5016 }
5017 LDRSH_INST:
5018 {
5019 INC_ICOUNTER;
5020 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5021 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5022 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
5023 if (fault) goto MMU_EXCEPTION;
5024 unsigned int value;
5025 fault = interpreter_read_memory(addr, phys_addr, value, 16);
5026 if (fault) goto MMU_EXCEPTION;
5027 //bus_read(16, addr, &value);
5028 if (BIT(value, 15)) {
5029 value |= 0xffff0000;
5030 }
5031 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5032 if (BITS(inst_cream->inst, 12, 15) == 15) {
5033 INC_PC(sizeof(ldst_inst));
5034 goto PROFILING;
5035 }
5036 }
5037 cpu->Reg[15] += GET_INST_SIZE(cpu);
5038 INC_PC(sizeof(ldst_inst));
5039 FETCH_INST;
5040 GOTO_NEXT_INST;
5041 }
5042 LDRT_INST:
5043 {
5044 INC_ICOUNTER;
5045 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5046 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5047 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
5048 if (fault) goto MMU_EXCEPTION;
5049 unsigned int value;
5050 fault = interpreter_read_memory(addr, phys_addr, value, 32);
5051 if (fault) goto MMU_EXCEPTION;
5052 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5053
5054 if (BIT(CP15_REG(CP15_CONTROL), 22) == 1)
5055 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5056 else
5057 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ROTATE_RIGHT_32(value,(8*(addr&0x3))) ;
5058
5059 if (BITS(inst_cream->inst, 12, 15) == 15) {
5060 INC_PC(sizeof(ldst_inst));
5061 goto PROFILING;
5062 }
5063 }
5064 cpu->Reg[15] += GET_INST_SIZE(cpu);
5065 INC_PC(sizeof(ldst_inst));
5066 FETCH_INST;
5067 GOTO_NEXT_INST;
5068 }
5069 MCR_INST:
5070 {
5071 INC_ICOUNTER;
5072 /* NOT IMPL */
5073 mcr_inst *inst_cream = (mcr_inst *)inst_base->component;
5074 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5075 unsigned int inst = inst_cream->inst;
5076 if (inst_cream->Rd == 15) {
5077 DEBUG_MSG;
5078 } else {
5079 if (inst_cream->cp_num == 15) {
5080 if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) {
5081 //LET(RD, CONST(0x0007b000));
5082 //LET(RD, CONST(0x410FB760));
5083 //LET(CP15_MAIN_ID, R(RD));
5084 CP15_REG(CP15_MAIN_ID) = RD;
5085 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) {
5086 //LET(RD, R(CP15_CONTROL));
5087 CP15_REG(CP15_AUXILIARY_CONTROL) = RD;
5088 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) {
5089 //LET(RD, R(CP15_CONTROL));
5090 CP15_REG(CP15_COPROCESSOR_ACCESS_CONTROL) = RD;
5091 } else if(CRn == 1 && CRm == 0 && OPCODE_2 == 0) {
5092 //LET(CP15_CONTROL, R(RD));
5093 CP15_REG(CP15_CONTROL) = RD;
5094 } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) {
5095 //LET(CP15_DOMAIN_ACCESS_CONTROL, R(RD));
5096 CP15_REG(CP15_DOMAIN_ACCESS_CONTROL) = RD;
5097 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) {
5098 //LET(CP15_TRANSLATION_BASE_TABLE_0, R(RD));
5099 CP15_REG(CP15_TRANSLATION_BASE_TABLE_0) = RD;
5100 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 1) {
5101 //LET(CP15_TRANSLATION_BASE_TABLE_1, R(RD));
5102 CP15_REG(CP15_TRANSLATION_BASE_TABLE_1) = RD;
5103 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 2) {
5104 //LET(CP15_TRANSLATION_BASE_CONTROL, R(RD));
5105 CP15_REG(CP15_TRANSLATION_BASE_CONTROL) = RD;
5106 } else if(CRn == MMU_CACHE_OPS){
5107 //SKYEYE_WARNING("cache operation have not implemented.\n");
5108 } else if(CRn == MMU_TLB_OPS){
5109 switch (CRm) {
5110 case 5: /* ITLB */
5111 switch(OPCODE_2){
5112 case 0: /* invalidate all */
5113 //invalidate_all_tlb(state);
5114 DEBUG_LOG(ARM11, "{TLB} [INSN] invalidate all\n");
5115 //remove_tlb(INSN_TLB);
5116 //erase_all(core, INSN_TLB);
5117 break;
5118 case 1: /* invalidate by MVA */
5119 //invalidate_by_mva(state, value);
5120 //DEBUG_LOG(ARM11, "{TLB} [INSN] invalidate by mva\n");
5121 //remove_tlb_by_mva(RD, INSN_TLB);
5122 //erase_by_mva(core, RD, INSN_TLB);
5123 break;
5124 case 2: /* invalidate by asid */
5125 //invalidate_by_asid(state, value);
5126 //DEBUG_LOG(ARM11, "{TLB} [INSN] invalidate by asid\n");
5127 //erase_by_asid(core, RD, INSN_TLB);
5128 break;
5129 default:
5130 break;
5131 }
5132
5133 break;
5134 case 6: /* DTLB */
5135 switch(OPCODE_2){
5136 case 0: /* invalidate all */
5137 //invalidate_all_tlb(state);
5138 //remove_tlb(DATA_TLB);
5139 //erase_all(core, DATA_TLB);
5140 DEBUG_LOG(ARM11, "{TLB} [DATA] invalidate all\n");
5141 break;
5142 case 1: /* invalidate by MVA */
5143 //invalidate_by_mva(state, value);
5144 //remove_tlb_by_mva(RD, DATA_TLB);
5145 //erase_by_mva(core, RD, DATA_TLB);
5146 //DEBUG_LOG(ARM11, "{TLB} [DATA] invalidate by mva\n");
5147 break;
5148 case 2: /* invalidate by asid */
5149 //invalidate_by_asid(state, value);
5150 //remove_tlb_by_asid(RD, DATA_TLB);
5151 //erase_by_asid(core, RD, DATA_TLB);
5152 //DEBUG_LOG(ARM11, "{TLB} [DATA] invalidate by asid\n");
5153 break;
5154 default:
5155 break;
5156 }
5157 break;
5158 case 7: /* UNIFILED TLB */
5159 switch(OPCODE_2){
5160 case 0: /* invalidate all */
5161 //invalidate_all_tlb(state);
5162 //erase_all(core, INSN_TLB);
5163 //erase_all(core, DATA_TLB);
5164 //remove_tlb(DATA_TLB);
5165 //remove_tlb(INSN_TLB);
5166 //DEBUG_LOG(ARM11, "{TLB} [UNIFILED] invalidate all\n");
5167 break;
5168 case 1: /* invalidate by MVA */
5169 //invalidate_by_mva(state, value);
5170 //erase_by_mva(core, RD, DATA_TLB);
5171 //erase_by_mva(core, RD, INSN_TLB);
5172 DEBUG_LOG(ARM11, "{TLB} [UNIFILED] invalidate by mva\n");
5173 break;
5174 case 2: /* invalidate by asid */
5175 //invalidate_by_asid(state, value);
5176 //erase_by_asid(core, RD, DATA_TLB);
5177 //erase_by_asid(core, RD, INSN_TLB);
5178 DEBUG_LOG(ARM11, "{TLB} [UNIFILED] invalidate by asid\n");
5179 break;
5180 default:
5181 break;
5182 }
5183 break;
5184 default:
5185 break;
5186 }
5187 } else if(CRn == MMU_PID){
5188 if(OPCODE_2 == 0)
5189 CP15_REG(CP15_PID) = RD;
5190 else if(OPCODE_2 == 1)
5191 CP15_REG(CP15_CONTEXT_ID) = RD;
5192 else if(OPCODE_2 == 3){
5193 CP15_REG(CP15_THREAD_URO) = RD;
5194 }
5195 else{
5196 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", CRn);
5197 }
5198
5199 } else {
5200 DEBUG_LOG(ARM11, "mcr is not implementated. CRn is %d, CRm is %d, OPCODE_2 is %d\n", CRn, CRm, OPCODE_2);
5201 }
5202 }
5203 }
5204 }
5205 cpu->Reg[15] += GET_INST_SIZE(cpu);
5206 INC_PC(sizeof(mcr_inst));
5207 FETCH_INST;
5208 GOTO_NEXT_INST;
5209 }
5210 MCRR_INST:
5211 MLA_INST:
5212 {
5213 INC_ICOUNTER;
5214 mla_inst *inst_cream = (mla_inst *)inst_base->component;
5215 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5216 uint64_t rm = RM;
5217 uint64_t rs = RS;
5218 uint64_t rn = RN;
5219 if (inst_cream->Rm == 15 || inst_cream->Rs == 15 || inst_cream->Rn == 15) {
5220 DEBUG_LOG(ARM11, "in __line__\n", __LINE__);
5221 CITRA_IGNORE_EXIT(-1);
5222 }
5223// RD = dst = RM * RS + RN;
5224 RD = dst = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff);
5225 if (inst_cream->S) {
5226 UPDATE_NFLAG(dst);
5227 UPDATE_ZFLAG(dst);
5228 }
5229 if (inst_cream->Rd == 15) {
5230 INC_PC(sizeof(mla_inst));
5231 goto PROFILING;
5232 }
5233 }
5234 cpu->Reg[15] += GET_INST_SIZE(cpu);
5235 INC_PC(sizeof(mla_inst));
5236 FETCH_INST;
5237 GOTO_NEXT_INST;
5238 }
5239 MOV_INST:
5240 {
5241// DEBUG_LOG(ARM11, "mov inst\n");
5242// DEBUG_LOG(ARM11, "pc: %x\n", cpu->Reg[15]);
5243// debug_function(cpu);
5244// cpu->icount ++;
5245 INC_ICOUNTER;
5246 mov_inst *inst_cream = (mov_inst *)inst_base->component;
5247 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5248 RD = dst = SHIFTER_OPERAND;
5249 if (inst_cream->S && (inst_cream->Rd == 15)) {
5250 /* cpsr = spsr */
5251 if (CurrentModeHasSPSR) {
5252 cpu->Cpsr = cpu->Spsr_copy;
5253 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5254 LOAD_NZCVT;
5255 }
5256 } else if (inst_cream->S) {
5257 UPDATE_NFLAG(dst);
5258 UPDATE_ZFLAG(dst);
5259 UPDATE_CFLAG_WITH_SC;
5260 }
5261 if (inst_cream->Rd == 15) {
5262 INC_PC(sizeof(mov_inst));
5263 goto PROFILING;
5264 }
5265// return;
5266 }
5267 cpu->Reg[15] += GET_INST_SIZE(cpu);
5268 INC_PC(sizeof(mov_inst));
5269 FETCH_INST;
5270 GOTO_NEXT_INST;
5271 }
5272 MRC_INST:
5273 {
5274 INC_ICOUNTER;
5275 /* NOT IMPL */
5276 mrc_inst *inst_cream = (mrc_inst *)inst_base->component;
5277 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5278 unsigned int inst = inst_cream->inst;
5279 if (inst_cream->Rd == 15) {
5280 DEBUG_MSG;
5281 }
5282 if (inst_cream->inst == 0xeef04a10) {
5283 /* undefined instruction fmrx */
5284 RD = 0x20000000;
5285 CITRA_IGNORE_EXIT(-1);
5286 goto END;
5287 } else {
5288 if (inst_cream->cp_num == 15) {
5289 if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) {
5290 //LET(RD, CONST(0x0007b000));
5291 //LET(RD, CONST(0x410FB760));
5292 //LET(RD, R(CP15_MAIN_ID));
5293 RD = cpu->CP15[CP15(CP15_MAIN_ID)];
5294 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 0) {
5295 //LET(RD, R(CP15_CONTROL));
5296 RD = cpu->CP15[CP15(CP15_CONTROL)];
5297 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) {
5298 //LET(RD, R(CP15_CONTROL));
5299 RD = cpu->CP15[CP15(CP15_AUXILIARY_CONTROL)];
5300 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) {
5301 //LET(RD, R(CP15_CONTROL));
5302 RD = cpu->CP15[CP15(CP15_COPROCESSOR_ACCESS_CONTROL)];
5303 } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) {
5304 //LET(RD, R(CP15_DOMAIN_ACCESS_CONTROL));
5305 RD = cpu->CP15[CP15(CP15_DOMAIN_ACCESS_CONTROL)];
5306 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) {
5307 //LET(RD, R(CP15_TRANSLATION_BASE_TABLE_0));
5308 RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_0)];
5309 } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 0) {
5310 //LET(RD, R(CP15_FAULT_STATUS));
5311 RD = cpu->CP15[CP15(CP15_FAULT_STATUS)];
5312 } else if (CRn == 6 && CRm == 0 && OPCODE_2 == 0) {
5313 //LET(RD, R(CP15_FAULT_ADDRESS));
5314 RD = cpu->CP15[CP15(CP15_FAULT_ADDRESS)];
5315 } else if (CRn == 0 && CRm == 0 && OPCODE_2 == 1) {
5316 //LET(RD, R(CP15_CACHE_TYPE));
5317 RD = cpu->CP15[CP15(CP15_CACHE_TYPE)];
5318 } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 1) {
5319 //LET(RD, R(CP15_INSTR_FAULT_STATUS));
5320 RD = cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)];
5321 } else if (CRn == 13) {
5322 if(OPCODE_2 == 0)
5323 RD = CP15_REG(CP15_PID);
5324 else if(OPCODE_2 == 1)
5325 RD = CP15_REG(CP15_CONTEXT_ID);
5326 else if(OPCODE_2 == 3){
5327 RD = Memory::KERNEL_MEMORY_VADDR;
5328 }
5329 else{
5330 printf ("mmu_mrr wrote UNKNOWN - reg %d\n", CRn);
5331 }
5332 }
5333 else {
5334 DEBUG_LOG(ARM11, "mrc is not implementated. CRn is %d, CRm is %d, OPCODE_2 is %d\n", CRn, CRm, OPCODE_2);
5335 }
5336 }
5337 //DEBUG_LOG(ARM11, "mrc is not implementated. CRn is %d, CRm is %d, OPCODE_2 is %d\n", CRn, CRm, OPCODE_2);
5338 }
5339 }
5340 cpu->Reg[15] += GET_INST_SIZE(cpu);
5341 INC_PC(sizeof(mrc_inst));
5342 FETCH_INST;
5343 GOTO_NEXT_INST;
5344 }
5345 MRRC_INST:
5346 MRS_INST:
5347 {
5348 INC_ICOUNTER;
5349 mrs_inst *inst_cream = (mrs_inst *)inst_base->component;
5350 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5351 if (inst_cream->R) {
5352 RD = cpu->Spsr_copy;
5353 } else {
5354 SAVE_NZCVT;
5355 RD = cpu->Cpsr;
5356 }
5357 }
5358 cpu->Reg[15] += GET_INST_SIZE(cpu);
5359 INC_PC(sizeof(mrs_inst));
5360 FETCH_INST;
5361 GOTO_NEXT_INST;
5362 }
5363 MSR_INST:
5364 {
5365 INC_ICOUNTER;
5366 msr_inst *inst_cream = (msr_inst *)inst_base->component;
5367 const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
5368 unsigned int inst = inst_cream->inst;
5369 unsigned int operand;
5370
5371 if (BIT(inst, 25)) {
5372 int rot_imm = BITS(inst, 8, 11) * 2;
5373 //operand = ROTL(CONST(BITS(0, 7)), CONST(32 - rot_imm));
5374 operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
5375 } else {
5376 //operand = R(RM);
5377 operand = cpu->Reg[BITS(inst, 0, 3)];
5378 }
5379 uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0)
5380 | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
5381 uint32_t mask;
5382 if (!inst_cream->R) {
5383 if (InAPrivilegedMode(cpu)) {
5384 if ((operand & StateMask) != 0) {
5385 /* UNPREDICTABLE */
5386 DEBUG_MSG;
5387 } else
5388 mask = byte_mask & (UserMask | PrivMask);
5389 } else {
5390 mask = byte_mask & UserMask;
5391 }
5392 //LET(CPSR_REG, OR(AND(R(CPSR_REG), COM(CONST(mask))), AND(operand, CONST(mask))));
5393 SAVE_NZCVT;
5394
5395 cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
5396 switch_mode(cpu, cpu->Cpsr & 0x1f);
5397 LOAD_NZCVT;
5398 } else {
5399 if (CurrentModeHasSPSR) {
5400 mask = byte_mask & (UserMask | PrivMask | StateMask);
5401 //LET(SPSR_REG, OR(AND(R(SPSR_REG), COM(CONST(mask))), AND(operand, CONST(mask))));
5402 cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask);
5403 }
5404 }
5405 cpu->Reg[15] += GET_INST_SIZE(cpu);
5406 INC_PC(sizeof(msr_inst));
5407 FETCH_INST;
5408 GOTO_NEXT_INST;
5409 }
5410 MUL_INST:
5411 {
5412 INC_ICOUNTER;
5413 mul_inst *inst_cream = (mul_inst *)inst_base->component;
5414 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5415// RD = dst = SHIFTER_OPERAND;
5416 uint64_t rm = RM;
5417 uint64_t rs = RS;
5418 RD = dst = static_cast<uint32_t>((rm * rs) & 0xffffffff);
5419 if (inst_cream->S) {
5420 UPDATE_NFLAG(dst);
5421 UPDATE_ZFLAG(dst);
5422 }
5423 if (inst_cream->Rd == 15) {
5424 INC_PC(sizeof(mul_inst));
5425 goto PROFILING;
5426 }
5427 }
5428 cpu->Reg[15] += GET_INST_SIZE(cpu);
5429 INC_PC(sizeof(mul_inst));
5430 FETCH_INST;
5431 GOTO_NEXT_INST;
5432 }
5433 MVN_INST:
5434 {
5435 INC_ICOUNTER;
5436 mvn_inst *inst_cream = (mvn_inst *)inst_base->component;
5437 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5438// RD = dst = (SHIFTER_OPERAND ^ 0xffffffff);
5439 RD = dst = ~SHIFTER_OPERAND;
5440 if (inst_cream->S && (inst_cream->Rd == 15)) {
5441 /* cpsr = spsr */
5442 if (CurrentModeHasSPSR) {
5443 cpu->Cpsr = cpu->Spsr_copy;
5444 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5445 LOAD_NZCVT;
5446 }
5447 } else if (inst_cream->S) {
5448 UPDATE_NFLAG(dst);
5449 UPDATE_ZFLAG(dst);
5450 UPDATE_CFLAG_WITH_SC;
5451 }
5452 if (inst_cream->Rd == 15) {
5453 INC_PC(sizeof(mvn_inst));
5454 goto PROFILING;
5455 }
5456 }
5457 cpu->Reg[15] += GET_INST_SIZE(cpu);
5458 INC_PC(sizeof(mvn_inst));
5459 FETCH_INST;
5460 GOTO_NEXT_INST;
5461 }
5462 ORR_INST:
5463 {
5464 INC_ICOUNTER;
5465 orr_inst *inst_cream = (orr_inst *)inst_base->component;
5466 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5467 lop = RN;
5468 rop = SHIFTER_OPERAND;
5469// DEBUG_LOG(ARM11, "lop is %x, rop is %x, r2 is %x, r3 is %x\n", lop, rop, cpu->Reg[2], cpu->Reg[3]);
5470 RD = dst = lop | rop;
5471 if (inst_cream->S && (inst_cream->Rd == 15)) {
5472 /* cpsr = spsr*/
5473 if (CurrentModeHasSPSR) {
5474 cpu->Cpsr = cpu->Spsr_copy;
5475 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5476 LOAD_NZCVT;
5477 }
5478 } else if (inst_cream->S) {
5479 UPDATE_NFLAG(dst);
5480 UPDATE_ZFLAG(dst);
5481 UPDATE_CFLAG_WITH_SC;
5482// UPDATE_CFLAG(dst, lop, rop);
5483 }
5484 if (inst_cream->Rd == 15) {
5485 INC_PC(sizeof(orr_inst));
5486 goto PROFILING;
5487 }
5488 }
5489 cpu->Reg[15] += GET_INST_SIZE(cpu);
5490 INC_PC(sizeof(orr_inst));
5491 FETCH_INST;
5492 GOTO_NEXT_INST;
5493 }
5494 PKHBT_INST:
5495 PKHTB_INST:
5496 PLD_INST:
5497 {
5498 INC_ICOUNTER;
5499 /* NOT IMPL */
5500 cpu->Reg[15] += GET_INST_SIZE(cpu);
5501 INC_PC(sizeof(stc_inst));
5502 FETCH_INST;
5503 GOTO_NEXT_INST;
5504 }
5505 QADD_INST:
5506 QADD16_INST:
5507 QADD8_INST:
5508 QADDSUBX_INST:
5509 QDADD_INST:
5510 QDSUB_INST:
5511 QSUB_INST:
5512 QSUB16_INST:
5513 QSUB8_INST:
5514 QSUBADDX_INST:
5515 REV_INST:
5516 {
5517 INC_ICOUNTER;
5518 rev_inst *inst_cream = (rev_inst *)inst_base->component;
5519 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5520 RD = ((RM & 0xff) << 24) |
5521 (((RM >> 8) & 0xff) << 16) |
5522 (((RM >> 16) & 0xff) << 8) |
5523 ((RM >> 24) & 0xff);
5524 if (inst_cream->Rm == 15) {
5525 DEBUG_LOG(ARM11, "in line %d\n", __LINE__);
5526 CITRA_IGNORE_EXIT(-1);
5527 }
5528 }
5529 cpu->Reg[15] += GET_INST_SIZE(cpu);
5530 INC_PC(sizeof(rev_inst));
5531 FETCH_INST;
5532 GOTO_NEXT_INST;
5533 }
5534 REV16_INST:
5535 {
5536 INC_ICOUNTER;
5537 rev_inst *inst_cream = (rev_inst *)inst_base->component;
5538 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5539 RD = (BITS(RM, 0, 7) << 8) |
5540 BITS(RM, 8, 15) |
5541 (BITS(RM, 16, 23) << 24) |
5542 (BITS(RM, 24, 31) << 16);
5543 }
5544 cpu->Reg[15] += GET_INST_SIZE(cpu);
5545 INC_PC(sizeof(rev_inst));
5546 FETCH_INST;
5547 GOTO_NEXT_INST;
5548 }
5549 REVSH_INST:
5550 RFE_INST:
5551 RSB_INST:
5552 {
5553 INC_ICOUNTER;
5554 rsb_inst *inst_cream = (rsb_inst *)inst_base->component;
5555 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5556 rop = RN;
5557 lop = SHIFTER_OPERAND;
5558 if (inst_cream->Rn == 15) {
5559 rop += 2 * GET_INST_SIZE(cpu);;
5560 }
5561 RD = dst = lop - rop;
5562 if (inst_cream->S && (inst_cream->Rd == 15)) {
5563 /* cpsr = spsr */
5564 if (CurrentModeHasSPSR) {
5565 cpu->Cpsr = cpu->Spsr_copy;
5566 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5567 LOAD_NZCVT;
5568 }
5569 } else if (inst_cream->S) {
5570 UPDATE_NFLAG(dst);
5571 UPDATE_ZFLAG(dst);
5572 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
5573// UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
5574 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
5575 }
5576 if (inst_cream->Rd == 15) {
5577 INC_PC(sizeof(rsb_inst));
5578 goto PROFILING;
5579 }
5580 }
5581 cpu->Reg[15] += GET_INST_SIZE(cpu);
5582 INC_PC(sizeof(rsb_inst));
5583 FETCH_INST;
5584 GOTO_NEXT_INST;
5585 }
5586 RSC_INST:
5587 {
5588 INC_ICOUNTER;
5589 rsc_inst *inst_cream = (rsc_inst *)inst_base->component;
5590 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5591 //lop = RN + !cpu->CFlag;
5592 //rop = SHIFTER_OPERAND;
5593 //RD = dst = rop - lop;
5594 lop = RN;
5595 rop = SHIFTER_OPERAND;
5596 RD = dst = rop - lop - !cpu->CFlag;
5597 if (inst_cream->S && (inst_cream->Rd == 15)) {
5598 /* cpsr = spsr */
5599 if (CurrentModeHasSPSR) {
5600 cpu->Cpsr = cpu->Spsr_copy;
5601 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5602 LOAD_NZCVT;
5603 }
5604 } else if (inst_cream->S) {
5605 UPDATE_NFLAG(dst);
5606 UPDATE_ZFLAG(dst);
5607// UPDATE_CFLAG(dst, lop, rop);
5608// UPDATE_CFLAG_NOT_BORROW_FROM(rop, lop);
5609 UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(rop, lop, !cpu->CFlag);
5610// cpu->CFlag = !((ISNEG(lop) && ISPOS(rop)) || (ISNEG(lop) && ISPOS(dst)) || (ISPOS(rop) && ISPOS(dst)));
5611 UPDATE_VFLAG_OVERFLOW_FROM((int)dst, (int)rop, (int)lop);
5612 }
5613 if (inst_cream->Rd == 15) {
5614 INC_PC(sizeof(rsc_inst));
5615 goto PROFILING;
5616 }
5617 }
5618 cpu->Reg[15] += GET_INST_SIZE(cpu);
5619 INC_PC(sizeof(rsc_inst));
5620 FETCH_INST;
5621 GOTO_NEXT_INST;
5622 }
5623 SADD16_INST:
5624 SADD8_INST:
5625 SADDSUBX_INST:
5626 SBC_INST:
5627 {
5628 INC_ICOUNTER;
5629 sbc_inst *inst_cream = (sbc_inst *)inst_base->component;
5630 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5631 lop = SHIFTER_OPERAND + !cpu->CFlag;
5632 rop = RN;
5633 RD = dst = rop - lop;
5634 if (inst_cream->S && (inst_cream->Rd == 15)) {
5635 /* cpsr = spsr */
5636 if (CurrentModeHasSPSR) {
5637 cpu->Cpsr = cpu->Spsr_copy;
5638 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5639 LOAD_NZCVT;
5640 }
5641 } else if (inst_cream->S) {
5642 UPDATE_NFLAG(dst);
5643 UPDATE_ZFLAG(dst);
5644// UPDATE_CFLAG(dst, lop, rop);
5645 //UPDATE_CFLAG_NOT_BORROW_FROM(rop, lop);
5646 //rop = rop - !cpu->CFlag;
5647 if(rop >= !cpu->CFlag)
5648 UPDATE_CFLAG_NOT_BORROW_FROM(rop - !cpu->CFlag, SHIFTER_OPERAND);
5649 else
5650 UPDATE_CFLAG_NOT_BORROW_FROM(rop, !cpu->CFlag);
5651// cpu->CFlag = !((ISNEG(lop) && ISPOS(rop)) || (ISNEG(lop) && ISPOS(dst)) || (ISPOS(rop) && ISPOS(dst)));
5652 UPDATE_VFLAG_OVERFLOW_FROM(dst, rop, lop);
5653 }
5654 if (inst_cream->Rd == 15) {
5655 INC_PC(sizeof(sbc_inst));
5656 goto PROFILING;
5657 }
5658 }
5659 cpu->Reg[15] += GET_INST_SIZE(cpu);
5660 INC_PC(sizeof(sbc_inst));
5661 FETCH_INST;
5662 GOTO_NEXT_INST;
5663 }
5664 SEL_INST:
5665 SETEND_INST:
5666 SHADD16_INST:
5667 SHADD8_INST:
5668 SHADDSUBX_INST:
5669 SHSUB16_INST:
5670 SHSUB8_INST:
5671 SHSUBADDX_INST:
5672 SMLA_INST:
5673 {
5674 INC_ICOUNTER;
5675 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5676 smla_inst *inst_cream = (smla_inst *)inst_base->component;
5677 int32_t operand1, operand2;
5678 if (inst_cream->x == 0)
5679 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
5680 else
5681 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
5682
5683 if (inst_cream->y == 0)
5684 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
5685 else
5686 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
5687 RD = operand1 * operand2 + RN;
5688 //FIXME: UPDATE Q FLAGS
5689 }
5690 cpu->Reg[15] += GET_INST_SIZE(cpu);
5691 INC_PC(sizeof(smla_inst));
5692 FETCH_INST;
5693 GOTO_NEXT_INST;
5694 }
5695 SMLAD_INST:
5696 {
5697 INC_ICOUNTER;
5698 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5699 smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
5700 long long int rm = cpu->Reg[inst_cream->Rm];
5701 long long int rn = cpu->Reg[inst_cream->Rn];
5702 long long int ra = cpu->Reg[inst_cream->Ra];
5703 /* see SMUAD */
5704 if(inst_cream->Ra == 15)
5705 CITRA_IGNORE_EXIT(-1);
5706 int operand2 = (inst_cream->m)? ROTATE_RIGHT_32(rm, 16):rm;
5707
5708 int half_rn, half_operand2;
5709 half_rn = rn & 0xFFFF;
5710 half_rn = (half_rn & 0x8000)? (0xFFFF0000|half_rn) : half_rn;
5711
5712 half_operand2 = operand2 & 0xFFFF;
5713 half_operand2 = (half_operand2 & 0x8000)? (0xFFFF0000|half_operand2) : half_operand2;
5714
5715 long long int product1 = half_rn * half_operand2;
5716
5717 half_rn = (rn & 0xFFFF0000) >> 16;
5718 half_rn = (half_rn & 0x8000)? (0xFFFF0000|half_rn) : half_rn;
5719
5720 half_operand2 = (operand2 & 0xFFFF0000) >> 16;
5721 half_operand2 = (half_operand2 & 0x8000)? (0xFFFF0000|half_operand2) : half_operand2;
5722
5723 long long int product2 = half_rn * half_operand2;
5724
5725 long long int signed_ra = (ra & 0x80000000)? (0xFFFFFFFF00000000LL) | ra : ra;
5726 long long int result = product1 + product2 + signed_ra;
5727 cpu->Reg[inst_cream->Rd] = result & 0xFFFFFFFF;
5728 /* FIXME , should check Signed overflow */
5729 }
5730 cpu->Reg[15] += GET_INST_SIZE(cpu);
5731 INC_PC(sizeof(umlal_inst));
5732 FETCH_INST;
5733 GOTO_NEXT_INST;
5734 }
5735
5736 SMLAL_INST:
5737 {
5738 INC_ICOUNTER;
5739 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5740 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
5741 long long int rm = RM;
5742 long long int rs = RS;
5743 if (BIT(rm, 31)) {
5744 rm |= 0xffffffff00000000LL;
5745 }
5746 if (BIT(rs, 31)) {
5747 rs |= 0xffffffff00000000LL;
5748 }
5749 long long int rst = rm * rs;
5750 long long int rdhi32 = RDHI;
5751 long long int hilo = (rdhi32 << 32) + RDLO;
5752 rst += hilo;
5753 RDLO = BITS(rst, 0, 31);
5754 RDHI = BITS(rst, 32, 63);
5755 if (inst_cream->S) {
5756 cpu->NFlag = BIT(RDHI, 31);
5757 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
5758 }
5759 }
5760 cpu->Reg[15] += GET_INST_SIZE(cpu);
5761 INC_PC(sizeof(umlal_inst));
5762 FETCH_INST;
5763 GOTO_NEXT_INST;
5764 }
5765 SMLALXY_INST:
5766 SMLALD_INST:
5767 SMLAW_INST:
5768 SMLSD_INST:
5769 SMLSLD_INST:
5770 SMMLA_INST:
5771 SMMLS_INST:
5772 SMMUL_INST:
5773 SMUAD_INST:
5774 SMUL_INST:
5775 {
5776 INC_ICOUNTER;
5777 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5778 smul_inst *inst_cream = (smul_inst *)inst_base->component;
5779 uint32_t operand1, operand2;
5780 if (inst_cream->x == 0)
5781 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
5782 else
5783 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
5784
5785 if (inst_cream->y == 0)
5786 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
5787 else
5788 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
5789 RD = operand1 * operand2;
5790 }
5791 cpu->Reg[15] += GET_INST_SIZE(cpu);
5792 INC_PC(sizeof(smul_inst));
5793 FETCH_INST;
5794 GOTO_NEXT_INST;
5795 }
5796 SMULL_INST:
5797 {
5798 INC_ICOUNTER;
5799 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5800 umull_inst *inst_cream = (umull_inst *)inst_base->component;
5801// DEBUG_LOG(ARM11, "rm : [%llx] rs : [%llx] rst [%llx]\n", RM, RS, rst);
5802 int64_t rm = RM;
5803 int64_t rs = RS;
5804 if (BIT(rm, 31)) {
5805 rm |= 0xffffffff00000000LL;
5806 }
5807 if (BIT(rs, 31)) {
5808 rs |= 0xffffffff00000000LL;
5809 }
5810 int64_t rst = rm * rs;
5811 RDHI = BITS(rst, 32, 63);
5812 RDLO = BITS(rst, 0, 31);
5813
5814
5815 if (inst_cream->S) {
5816 cpu->NFlag = BIT(RDHI, 31);
5817 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
5818 }
5819 }
5820 cpu->Reg[15] += GET_INST_SIZE(cpu);
5821 INC_PC(sizeof(umull_inst));
5822 FETCH_INST;
5823 GOTO_NEXT_INST;
5824 }
5825 SMULW_INST:
5826 INC_ICOUNTER;
5827 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5828 smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
5829// DEBUG_LOG(ARM11, "rm : [%llx] rs : [%llx] rst [%llx]\n", RM, RS, rst);
5830 int64_t rm = RM;
5831 int64_t rn = RN;
5832 if (inst_cream->m)
5833 rm = BITS(rm,16 , 31);
5834 else
5835 rm = BITS(rm,0 , 15);
5836 int64_t rst = rm * rn;
5837 RD = BITS(rst, 16, 47);
5838 }
5839 cpu->Reg[15] += GET_INST_SIZE(cpu);
5840 INC_PC(sizeof(smlad_inst));
5841 FETCH_INST;
5842 GOTO_NEXT_INST;
5843
5844 SMUSD_INST:
5845 SRS_INST:
5846 SSAT_INST:
5847 SSAT16_INST:
5848 SSUB16_INST:
5849 SSUB8_INST:
5850 SSUBADDX_INST:
5851 STC_INST:
5852 {
5853 INC_ICOUNTER;
5854 /* NOT IMPL */
5855 cpu->Reg[15] += GET_INST_SIZE(cpu);
5856 INC_PC(sizeof(stc_inst));
5857 FETCH_INST;
5858 GOTO_NEXT_INST;
5859 }
5860 STM_INST:
5861 {
5862 INC_ICOUNTER;
5863 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5864 unsigned int inst = inst_cream->inst;
5865 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5866 int i;
5867 unsigned int Rn = BITS(inst, 16, 19);
5868 unsigned int old_RN = cpu->Reg[Rn];
5869
5870 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
5871 if (fault) goto MMU_EXCEPTION;
5872 if (BIT(inst_cream->inst, 22) == 1) {
5873// DEBUG_MSG;
5874 #if 1
5875 for (i = 0; i < 13; i++) {
5876 if(BIT(inst_cream->inst, i)){
5877 fault = check_address_validity(cpu, addr, &phys_addr, 0);
5878 if (fault) {
5879 goto MMU_EXCEPTION;
5880 }
5881 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32);
5882 if (fault) goto MMU_EXCEPTION;
5883 addr += 4;
5884 phys_addr += 4;
5885 }
5886 }
5887 if (BIT(inst_cream->inst, 13)) {
5888 if (cpu->Mode == USER32MODE) {
5889 fault = check_address_validity(cpu, addr, &phys_addr, 0);
5890 if (fault) {
5891 goto MMU_EXCEPTION;
5892 }
5893 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32);
5894 if (fault) goto MMU_EXCEPTION;
5895 addr += 4;
5896 phys_addr += 4;
5897 } else {
5898 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg_usr[0], 32);
5899 if (fault) goto MMU_EXCEPTION;
5900 addr += 4;
5901 phys_addr += 4;
5902 }
5903 }
5904 if (BIT(inst_cream->inst, 14)) {
5905 if (cpu->Mode == USER32MODE) {
5906 fault = check_address_validity(cpu, addr, &phys_addr, 0);
5907 if (fault) {
5908 goto MMU_EXCEPTION;
5909 }
5910 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32);
5911 if (fault) goto MMU_EXCEPTION;
5912 addr += 4;
5913 phys_addr += 4;
5914 } else {
5915 fault = check_address_validity(cpu, addr, &phys_addr, 0);
5916 if (fault) {
5917 goto MMU_EXCEPTION;
5918 }
5919 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg_usr[1], 32);
5920 if (fault) goto MMU_EXCEPTION;
5921 addr += 4;
5922 phys_addr += 4;
5923 }
5924 }
5925 if (BIT(inst_cream->inst, 15)) {
5926 fault = check_address_validity(cpu, addr, &phys_addr, 0);
5927 if (fault) {
5928 goto MMU_EXCEPTION;
5929 }
5930 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i] + 8, 32);
5931 if (fault) goto MMU_EXCEPTION;
5932 }
5933 #endif
5934 } else {
5935 for( i = 0; i < 15; i ++ ){
5936 if(BIT(inst_cream->inst, i)){
5937 //arch_write_memory(cpu, bb, Addr, R(i), 32);
5938 //bus_write(32, addr, cpu->Reg[i]);
5939 fault = check_address_validity(cpu, addr, &phys_addr, 0);
5940 if (fault) {
5941 goto MMU_EXCEPTION;
5942 }
5943 if(i == Rn)
5944 fault = interpreter_write_memory(addr, phys_addr, old_RN, 32);
5945 else
5946 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32);
5947 if (fault) goto MMU_EXCEPTION;
5948 addr += 4;
5949 phys_addr += 4;
5950 //Addr = ADD(Addr, CONST(4));
5951 }
5952 }
5953
5954 /* check pc reg*/
5955 if(BIT(inst_cream->inst, i)){
5956 //arch_write_memory(cpu, bb, Addr, STOREM_CHECK_PC, 32);
5957 //bus_write(32, addr, cpu->Reg[i] + 8);
5958 fault = check_address_validity(cpu, addr, &phys_addr, 0);
5959 if (fault) {
5960 goto MMU_EXCEPTION;
5961 }
5962 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i] + 8, 32);
5963 if (fault) goto MMU_EXCEPTION;
5964 }
5965 }
5966 }
5967 cpu->Reg[15] += GET_INST_SIZE(cpu);
5968 INC_PC(sizeof(ldst_inst));
5969 FETCH_INST;
5970 GOTO_NEXT_INST;
5971 }
5972 SXTB_INST:
5973 {
5974 INC_ICOUNTER;
5975 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
5976 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5977 if (inst_cream->Rm == 15) {
5978 DEBUG_LOG(ARM11, "line is %d\n", __LINE__);
5979 CITRA_IGNORE_EXIT(-1);
5980 }
5981 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
5982 if (BIT(operand2, 7)) {
5983 operand2 |= 0xffffff00;
5984 } else
5985 operand2 &= 0xff;
5986 RD = operand2;
5987 }
5988 cpu->Reg[15] += GET_INST_SIZE(cpu);
5989 INC_PC(sizeof(sxtb_inst));
5990 FETCH_INST;
5991 GOTO_NEXT_INST;
5992 }
5993 STR_INST:
5994 {
5995 INC_ICOUNTER;
5996 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5997 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5998 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
5999 if (fault) goto MMU_EXCEPTION;
6000 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
6001 //bus_write(32, addr, value);
6002 fault = interpreter_write_memory(addr, phys_addr, value, 32);
6003 if (fault) goto MMU_EXCEPTION;
6004 }
6005 cpu->Reg[15] += GET_INST_SIZE(cpu);
6006 INC_PC(sizeof(ldst_inst));
6007 FETCH_INST;
6008 GOTO_NEXT_INST;
6009 }
6010 UXTB_INST:
6011 {
6012 INC_ICOUNTER;
6013 uxtb_inst *inst_cream = (uxtb_inst *)inst_base->component;
6014 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6015 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate)
6016 & 0xff;
6017 RD = operand2;
6018 }
6019 cpu->Reg[15] += GET_INST_SIZE(cpu);
6020 INC_PC(sizeof(uxtb_inst));
6021 FETCH_INST;
6022 GOTO_NEXT_INST;
6023 }
6024 UXTAB_INST:
6025 {
6026 INC_ICOUNTER;
6027 uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component;
6028 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6029 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate)
6030 & 0xff;
6031 RD = RN + operand2;
6032 }
6033 cpu->Reg[15] += GET_INST_SIZE(cpu);
6034 INC_PC(sizeof(uxtab_inst));
6035 FETCH_INST;
6036 GOTO_NEXT_INST;
6037 }
6038 STRB_INST:
6039 {
6040 INC_ICOUNTER;
6041 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6042 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6043 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
6044 if (fault) goto MMU_EXCEPTION;
6045 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
6046 //bus_write(8, addr, value);
6047 fault = interpreter_write_memory(addr, phys_addr, value, 8);
6048 if (fault) goto MMU_EXCEPTION;
6049 }
6050 cpu->Reg[15] += GET_INST_SIZE(cpu);
6051 INC_PC(sizeof(ldst_inst));
6052 FETCH_INST;
6053 GOTO_NEXT_INST;
6054 }
6055 STRBT_INST:
6056 {
6057 INC_ICOUNTER;
6058 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6059 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6060 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
6061 if (fault) goto MMU_EXCEPTION;
6062 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
6063 //bus_write(8, addr, value);
6064 fault = interpreter_write_memory(addr, phys_addr, value, 8);
6065 if (fault) goto MMU_EXCEPTION;
6066 }
6067 cpu->Reg[15] += GET_INST_SIZE(cpu);
6068 //if (BITS(inst_cream->inst, 12, 15) == 15)
6069 // goto PROFILING;
6070 INC_PC(sizeof(ldst_inst));
6071 FETCH_INST;
6072 GOTO_NEXT_INST;
6073 }
6074 STRD_INST:
6075 {
6076 INC_ICOUNTER;
6077 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6078 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6079 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
6080 if (fault) goto MMU_EXCEPTION;
6081 uint32_t rear_phys_addr;
6082 fault = check_address_validity(cpu, addr + 4, &rear_phys_addr, 0);
6083 if (fault){
6084 ERROR_LOG(ARM11, "mmu fault , should rollback the above get_addr\n");
6085 CITRA_IGNORE_EXIT(-1);
6086 goto MMU_EXCEPTION;
6087 }
6088
6089 //fault = inst_cream->get_addr(cpu, inst_cream->inst, addr + 4, phys_addr + 4, 0);
6090 //if (fault) goto MMU_EXCEPTION;
6091
6092 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
6093 //bus_write(32, addr, value);
6094 fault = interpreter_write_memory(addr, phys_addr, value, 32);
6095 if (fault) goto MMU_EXCEPTION;
6096 value = cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1];
6097 //bus_write(32, addr, value);
6098 fault = interpreter_write_memory(addr + 4, rear_phys_addr, value, 32);
6099 if (fault) goto MMU_EXCEPTION;
6100 }
6101 cpu->Reg[15] += GET_INST_SIZE(cpu);
6102 INC_PC(sizeof(ldst_inst));
6103 FETCH_INST;
6104 GOTO_NEXT_INST;
6105 }
6106 STREX_INST:
6107 {
6108 INC_ICOUNTER;
6109 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6110 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6111 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)];
6112 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)];
6113 fault = check_address_validity(cpu, addr, &phys_addr, 0);
6114 if (fault) goto MMU_EXCEPTION;
6115
6116 int dest_reg = BITS(inst_cream->inst, 12, 15);
6117 if((exclusive_detect(cpu, phys_addr) == 0) && (cpu->exclusive_state == 1)){
6118 remove_exclusive(cpu, phys_addr);
6119 cpu->Reg[dest_reg] = 0;
6120 cpu->exclusive_state = 0;
6121
6122 // bus_write(32, addr, value);
6123 fault = interpreter_write_memory(addr, phys_addr, value, 32);
6124 if (fault) goto MMU_EXCEPTION;
6125 }
6126 else{
6127 /* Failed to write due to mutex access */
6128 cpu->Reg[dest_reg] = 1;
6129 }
6130 }
6131 cpu->Reg[15] += GET_INST_SIZE(cpu);
6132 INC_PC(sizeof(ldst_inst));
6133 FETCH_INST;
6134 GOTO_NEXT_INST;
6135 }
6136 STREXB_INST:
6137 {
6138 INC_ICOUNTER;
6139 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6140 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6141 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)];
6142 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)] & 0xff;
6143 fault = check_address_validity(cpu, addr, &phys_addr, 0);
6144 if (fault) goto MMU_EXCEPTION;
6145 //bus_write(8, addr, value);
6146 int dest_reg = BITS(inst_cream->inst, 12, 15);
6147 if((exclusive_detect(cpu, phys_addr) == 0) && (cpu->exclusive_state == 1)){
6148 remove_exclusive(cpu, phys_addr);
6149 cpu->Reg[dest_reg] = 0;
6150 cpu->exclusive_state = 0;
6151 fault = interpreter_write_memory(addr, phys_addr, value, 8);
6152 if (fault) goto MMU_EXCEPTION;
6153
6154 }
6155 else{
6156 cpu->Reg[dest_reg] = 1;
6157 }
6158 }
6159 cpu->Reg[15] += GET_INST_SIZE(cpu);
6160 INC_PC(sizeof(ldst_inst));
6161 FETCH_INST;
6162 GOTO_NEXT_INST;
6163 }
6164 STRH_INST:
6165 {
6166 INC_ICOUNTER;
6167 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6168 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6169 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
6170 if (fault) goto MMU_EXCEPTION;
6171 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
6172 //bus_write(16, addr, value);
6173 fault = interpreter_write_memory(addr, phys_addr, value, 16);
6174 if (fault) goto MMU_EXCEPTION;
6175 }
6176 cpu->Reg[15] += GET_INST_SIZE(cpu);
6177 //if (BITS(inst_cream->inst, 12, 15) == 15)
6178 // goto PROFILING;
6179 INC_PC(sizeof(ldst_inst));
6180 FETCH_INST;
6181 GOTO_NEXT_INST;
6182 }
6183 STRT_INST:
6184 {
6185 INC_ICOUNTER;
6186 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6187 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6188 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
6189 if (fault) goto MMU_EXCEPTION;
6190 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
6191 //bus_write(16, addr, value);
6192 fault = interpreter_write_memory(addr, phys_addr, value, 32);
6193 if (fault) goto MMU_EXCEPTION;
6194 }
6195 cpu->Reg[15] += GET_INST_SIZE(cpu);
6196 INC_PC(sizeof(ldst_inst));
6197 FETCH_INST;
6198 GOTO_NEXT_INST;
6199 }
6200 SUB_INST:
6201 {
6202 INC_ICOUNTER;
6203 sub_inst *inst_cream = (sub_inst *)inst_base->component;
6204 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6205 lop = RN;
6206 if (inst_cream->Rn == 15) {
6207 lop += 8;
6208 }
6209 rop = SHIFTER_OPERAND;
6210 RD = dst = lop - rop;
6211 if (inst_cream->S && (inst_cream->Rd == 15)) {
6212 /* cpsr = spsr */
6213 if (CurrentModeHasSPSR) {
6214 cpu->Cpsr = cpu->Spsr_copy;
6215 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
6216 LOAD_NZCVT;
6217 }
6218 } else if (inst_cream->S) {
6219 UPDATE_NFLAG(dst);
6220 UPDATE_ZFLAG(dst);
6221// UPDATE_CFLAG(dst, lop, rop);
6222 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
6223 // UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
6224 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
6225 }
6226 if (inst_cream->Rd == 15) {
6227 INC_PC(sizeof(sub_inst));
6228 goto PROFILING;
6229 }
6230 }
6231 cpu->Reg[15] += GET_INST_SIZE(cpu);
6232 INC_PC(sizeof(sub_inst));
6233 FETCH_INST;
6234 GOTO_NEXT_INST;
6235 }
6236 SWI_INST:
6237 {
6238 INC_ICOUNTER;
6239 swi_inst *inst_cream = (swi_inst *)inst_base->component;
6240 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6241 if (true){ //if (core->is_user_mode) { --> Citra only emulates user mode
6242 //arm_dyncom_SWI(cpu, inst_cream->num);
6243 HLE::CallSVC(Memory::Read32(cpu->Reg[15]));
6244 } else {
6245 cpu->syscallSig = 1;
6246 goto END;
6247 }
6248 }
6249 cpu->Reg[15] += GET_INST_SIZE(cpu);
6250 INC_PC(sizeof(swi_inst));
6251 FETCH_INST;
6252 GOTO_NEXT_INST;
6253 }
6254 SWP_INST:
6255 {
6256 INC_ICOUNTER;
6257 swp_inst *inst_cream = (swp_inst *)inst_base->component;
6258 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6259 addr = RN;
6260 fault = check_address_validity(cpu, addr, &phys_addr, 1);
6261 if (fault) goto MMU_EXCEPTION;
6262 unsigned int value;
6263 fault = interpreter_read_memory(addr, phys_addr, value, 32);
6264 if (fault) goto MMU_EXCEPTION;
6265 fault = interpreter_write_memory(addr, phys_addr, RM, 32);
6266 if (fault) goto MMU_EXCEPTION;
6267
6268 /* ROR(data, 8*UInt(address<1:0>)); */
6269 assert((phys_addr & 0x3) == 0);
6270 RD = value;
6271 }
6272 cpu->Reg[15] += GET_INST_SIZE(cpu);
6273 INC_PC(sizeof(swp_inst));
6274 FETCH_INST;
6275 GOTO_NEXT_INST;
6276 }
6277 SWPB_INST:
6278 {
6279 INC_ICOUNTER;
6280 swp_inst *inst_cream = (swp_inst *)inst_base->component;
6281 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6282 addr = RN;
6283 fault = check_address_validity(cpu, addr, &phys_addr, 1);
6284 if (fault) goto MMU_EXCEPTION;
6285 unsigned int value;
6286 fault = interpreter_read_memory(addr, phys_addr, value, 8);
6287 if (fault) goto MMU_EXCEPTION;
6288 fault = interpreter_write_memory(addr, phys_addr, (RM & 0xFF), 8);
6289 if (fault) goto MMU_EXCEPTION;
6290
6291 /* FIXME */
6292 #if 0
6293 if Shared(address) then
6294 /* ARMv6 */
6295 physical_address = TLB(address)
6296 ClearExclusiveByAddress(physical_address,processor_id,1)
6297 /* See Summary of operation on page A2-49 */
6298 #endif
6299 }
6300 cpu->Reg[15] += GET_INST_SIZE(cpu);
6301 INC_PC(sizeof(swp_inst));
6302 FETCH_INST;
6303 GOTO_NEXT_INST;
6304 }
6305 SXTAB_INST:
6306 {
6307 INC_ICOUNTER;
6308 sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component;
6309 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6310 /* R15 should be check */
6311 if(inst_cream->Rn == 15 || inst_cream->Rm == 15 || inst_cream->Rd ==15){
6312 CITRA_IGNORE_EXIT(-1);
6313 }
6314 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate)
6315 & 0xff;
6316 /* sign extend for byte */
6317 operand2 = (0x80 & operand2)? (0xFFFFFF00 | operand2):operand2;
6318 RD = RN + operand2;
6319 }
6320 cpu->Reg[15] += GET_INST_SIZE(cpu);
6321 INC_PC(sizeof(uxtab_inst));
6322 FETCH_INST;
6323 GOTO_NEXT_INST;
6324 }
6325 SXTAB16_INST:
6326 SXTAH_INST:
6327 {
6328 INC_ICOUNTER;
6329 sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component;
6330 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6331 /* R15 should be check */
6332 if(inst_cream->Rn == 15 || inst_cream->Rm == 15 || inst_cream->Rd ==15){
6333 CITRA_IGNORE_EXIT(-1);
6334 }
6335 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
6336 /* sign extend for half */
6337 operand2 = (0x8000 & operand2)? (0xFFFF0000 | operand2):operand2;
6338 RD = RN + operand2;
6339 }
6340 cpu->Reg[15] += GET_INST_SIZE(cpu);
6341 INC_PC(sizeof(sxtah_inst));
6342 FETCH_INST;
6343 GOTO_NEXT_INST;
6344 }
6345 SXTB16_INST:
6346 TEQ_INST:
6347 {
6348 INC_ICOUNTER;
6349 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6350 teq_inst *inst_cream = (teq_inst *)inst_base->component;
6351 lop = RN;
6352 if (inst_cream->Rn == 15)
6353 lop += GET_INST_SIZE(cpu) * 2;
6354
6355 rop = SHIFTER_OPERAND;
6356 dst = lop ^ rop;
6357
6358 UPDATE_NFLAG(dst);
6359 UPDATE_ZFLAG(dst);
6360 UPDATE_CFLAG_WITH_SC;
6361 }
6362 cpu->Reg[15] += GET_INST_SIZE(cpu);
6363 INC_PC(sizeof(teq_inst));
6364 FETCH_INST;
6365 GOTO_NEXT_INST;
6366 }
6367 TST_INST:
6368 {
6369 INC_ICOUNTER;
6370 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6371 tst_inst *inst_cream = (tst_inst *)inst_base->component;
6372 lop = RN;
6373 if (inst_cream->Rn == 15)
6374 lop += GET_INST_SIZE(cpu) * 2;
6375 rop = SHIFTER_OPERAND;
6376 dst = lop & rop;
6377
6378 UPDATE_NFLAG(dst);
6379 UPDATE_ZFLAG(dst);
6380 UPDATE_CFLAG_WITH_SC;
6381 }
6382 cpu->Reg[15] += GET_INST_SIZE(cpu);
6383 INC_PC(sizeof(tst_inst));
6384 FETCH_INST;
6385 GOTO_NEXT_INST;
6386 }
6387 UADD16_INST:
6388 UADD8_INST:
6389 UADDSUBX_INST:
6390 UHADD16_INST:
6391 UHADD8_INST:
6392 UHADDSUBX_INST:
6393 UHSUB16_INST:
6394 UHSUB8_INST:
6395 UHSUBADDX_INST:
6396 UMAAL_INST:
6397 UMLAL_INST:
6398 {
6399 INC_ICOUNTER;
6400 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6401 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
6402 unsigned long long int rm = RM;
6403 unsigned long long int rs = RS;
6404 unsigned long long int rst = rm * rs;
6405 unsigned long long int add = ((unsigned long long) RDHI)<<32;
6406 add += RDLO;
6407 //DEBUG_LOG(ARM11, "rm[%llx] * rs[%llx] = rst[%llx] | add[%llx]\n", RM, RS, rst, add);
6408 rst += add;
6409 RDLO = BITS(rst, 0, 31);
6410 RDHI = BITS(rst, 32, 63);
6411
6412 if (inst_cream->S)
6413 {
6414 cpu->NFlag = BIT(RDHI, 31);
6415 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
6416 }
6417 }
6418 cpu->Reg[15] += GET_INST_SIZE(cpu);
6419 INC_PC(sizeof(umlal_inst));
6420 FETCH_INST;
6421 GOTO_NEXT_INST;
6422 }
6423 UMULL_INST:
6424 {
6425 INC_ICOUNTER;
6426 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6427 umull_inst *inst_cream = (umull_inst *)inst_base->component;
6428 unsigned long long int rm = RM;
6429 unsigned long long int rs = RS;
6430 unsigned long long int rst = rm * rs;
6431// DEBUG_LOG(ARM11, "rm : [%llx] rs : [%llx] rst [%llx]\n", RM, RS, rst);
6432 RDHI = BITS(rst, 32, 63);
6433 RDLO = BITS(rst, 0, 31);
6434
6435 if (inst_cream->S) {
6436 cpu->NFlag = BIT(RDHI, 31);
6437 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
6438 }
6439 }
6440 cpu->Reg[15] += GET_INST_SIZE(cpu);
6441 INC_PC(sizeof(umull_inst));
6442 FETCH_INST;
6443 GOTO_NEXT_INST;
6444 }
6445 B_2_THUMB:
6446 {
6447 INC_ICOUNTER;
6448 b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component;
6449 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
6450 //DEBUG_LOG(ARM11, " BL_1_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]);
6451 INC_PC(sizeof(b_2_thumb));
6452 goto PROFILING;
6453 }
6454 B_COND_THUMB:
6455 {
6456 INC_ICOUNTER;
6457 b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component;
6458 if(CondPassed(cpu, inst_cream->cond))
6459 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
6460 else
6461 cpu->Reg[15] += 2;
6462 //DEBUG_LOG(ARM11, " B_COND_THUMB: imm=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[15]);
6463 INC_PC(sizeof(b_cond_thumb));
6464 goto PROFILING;
6465 }
6466 BL_1_THUMB:
6467 {
6468 INC_ICOUNTER;
6469 bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component;
6470 cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm;
6471 //cpu->Reg[15] += 2;
6472 //DEBUG_LOG(ARM11, " BL_1_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]);
6473
6474 cpu->Reg[15] += GET_INST_SIZE(cpu);
6475 INC_PC(sizeof(bl_1_thumb));
6476 FETCH_INST;
6477 GOTO_NEXT_INST;
6478
6479 }
6480 BL_2_THUMB:
6481 {
6482 INC_ICOUNTER;
6483 bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component;
6484 int tmp = ((cpu->Reg[15] + 2) | 1);
6485 cpu->Reg[15] =
6486 (cpu->Reg[14] + inst_cream->imm);
6487 cpu->Reg[14] = tmp;
6488 //DEBUG_LOG(ARM11, " BL_2_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]);
6489 INC_PC(sizeof(bl_2_thumb));
6490 goto PROFILING;
6491 }
6492 BLX_1_THUMB:
6493 {
6494 /* BLX 1 for armv5t and above */
6495 INC_ICOUNTER;
6496 uint32 tmp = cpu->Reg[15];
6497 blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component;
6498 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC;
6499 //DEBUG_LOG(ARM11, "In BLX_1_THUMB, BLX(1),imm=0x%x,r14=0x%x, instr=0x%x\n", inst_cream->imm, cpu->Reg[14], inst_cream->instr);
6500 cpu->Reg[14] = ((tmp + 2) | 1);
6501 //(state->Reg[14] + ((tinstr & 0x07FF) << 1)) & 0xFFFFFFFC;
6502 /* switch to arm state from thumb state */
6503 cpu->TFlag = 0;
6504 //DEBUG_LOG(ARM11, "In BLX_1_THUMB, BLX(1),imm=0x%x,r14=0x%x, r15=0x%x, \n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]);
6505 INC_PC(sizeof(blx_1_thumb));
6506 goto PROFILING;
6507 }
6508
6509 UQADD16_INST:
6510 UQADD8_INST:
6511 UQADDSUBX_INST:
6512 UQSUB16_INST:
6513 UQSUB8_INST:
6514 UQSUBADDX_INST:
6515 USAD8_INST:
6516 USADA8_INST:
6517 USAT_INST:
6518 USAT16_INST:
6519 USUB16_INST:
6520 USUB8_INST:
6521 USUBADDX_INST:
6522 UXTAB16_INST:
6523 UXTB16_INST:
6524 #define VFP_INTERPRETER_IMPL
6525 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
6526 #undef VFP_INTERPRETER_IMPL
6527 MMU_EXCEPTION:
6528 {
6529 SAVE_NZCVT;
6530 cpu->abortSig = true;
6531 cpu->Aborted = ARMul_DataAbortV;
6532 cpu->AbortAddr = addr;
6533 cpu->CP15[CP15(CP15_FAULT_STATUS)] = fault & 0xff;
6534 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr;
6535 return;
6536 }
6537 END:
6538 {
6539 SAVE_NZCVT;
6540 return;
6541 }
6542 INIT_INST_LENGTH:
6543 {
6544#if 0
6545 DEBUG_LOG(ARM11, "InstLabel:%d\n", sizeof(InstLabel));
6546 for (int i = 0; i < (sizeof(InstLabel) / sizeof(void *)); i ++)
6547 DEBUG_LOG(ARM11, "[%llx]\n", InstLabel[i]);
6548 DEBUG_LOG(ARM11, "InstLabel:%d\n", sizeof(InstLabel));
6549#endif
6550#if defined __GNUC__ || defined __clang__
6551 InterpreterInitInstLength((unsigned long long int *)InstLabel, sizeof(InstLabel));
6552#endif
6553#if 0
6554 for (int i = 0; i < (sizeof(InstLabel) / sizeof(void *)); i ++)
6555 DEBUG_LOG(ARM11, "[%llx]\n", InstLabel[i]);
6556 DEBUG_LOG(ARM11, "%llx\n", InstEndLabel[1]);
6557 DEBUG_LOG(ARM11, "%llx\n", InstLabel[1]);
6558 DEBUG_LOG(ARM11, "%lld\n", (char *)InstEndLabel[1] - (char *)InstLabel[1]);
6559#endif
6560 return;
6561 }
6562}
6563
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.h b/src/core/arm/dyncom/arm_dyncom_interpreter.h
new file mode 100644
index 000000000..d73f8f65f
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.h
@@ -0,0 +1,7 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7void InterpreterMainLoop(ARMul_State* state);
diff --git a/src/core/arm/dyncom/arm_dyncom_run.cpp b/src/core/arm/dyncom/arm_dyncom_run.cpp
new file mode 100644
index 000000000..a2026cbf3
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom_run.cpp
@@ -0,0 +1,120 @@
1/* Copyright (C)
2* 2011 - Michael.Kang blackfin.kang@gmail.com
3* This program is free software; you can redistribute it and/or
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18/**
19* @file arm_dyncom_run.cpp
20* @brief The dyncom run implementation for arm
21* @author Michael.Kang blackfin.kang@gmail.com
22* @version 78.77
23* @date 2011-11-20
24*/
25
26#include <assert.h>
27
28#include "core/arm/skyeye_common/armdefs.h"
29
30void switch_mode(arm_core_t *core, uint32_t mode)
31{
32 uint32_t tmp1, tmp2;
33 if (core->Mode == mode) {
34 //Mode not changed.
35 //printf("mode not changed\n");
36 return;
37 }
38 //printf("%d --->>> %d\n", core->Mode, mode);
39 //printf("In %s, Cpsr=0x%x, R15=0x%x, last_pc=0x%x, cpsr=0x%x, spsr_copy=0x%x, icounter=%lld\n", __FUNCTION__, core->Cpsr, core->Reg[15], core->last_pc, core->Cpsr, core->Spsr_copy, core->icounter);
40 if (mode != USERBANK) {
41 switch (core->Mode) {
42 case USER32MODE:
43 core->Reg_usr[0] = core->Reg[13];
44 core->Reg_usr[1] = core->Reg[14];
45 break;
46 case IRQ32MODE:
47 core->Reg_irq[0] = core->Reg[13];
48 core->Reg_irq[1] = core->Reg[14];
49 core->Spsr[IRQBANK] = core->Spsr_copy;
50 break;
51 case SVC32MODE:
52 core->Reg_svc[0] = core->Reg[13];
53 core->Reg_svc[1] = core->Reg[14];
54 core->Spsr[SVCBANK] = core->Spsr_copy;
55 break;
56 case ABORT32MODE:
57 core->Reg_abort[0] = core->Reg[13];
58 core->Reg_abort[1] = core->Reg[14];
59 core->Spsr[ABORTBANK] = core->Spsr_copy;
60 break;
61 case UNDEF32MODE:
62 core->Reg_undef[0] = core->Reg[13];
63 core->Reg_undef[1] = core->Reg[14];
64 core->Spsr[UNDEFBANK] = core->Spsr_copy;
65 break;
66 case FIQ32MODE:
67 core->Reg_firq[0] = core->Reg[13];
68 core->Reg_firq[1] = core->Reg[14];
69 core->Spsr[FIQBANK] = core->Spsr_copy;
70 break;
71
72 }
73
74 switch (mode) {
75 case USER32MODE:
76 core->Reg[13] = core->Reg_usr[0];
77 core->Reg[14] = core->Reg_usr[1];
78 core->Bank = USERBANK;
79 break;
80 case IRQ32MODE:
81 core->Reg[13] = core->Reg_irq[0];
82 core->Reg[14] = core->Reg_irq[1];
83 core->Spsr_copy = core->Spsr[IRQBANK];
84 core->Bank = IRQBANK;
85 break;
86 case SVC32MODE:
87 core->Reg[13] = core->Reg_svc[0];
88 core->Reg[14] = core->Reg_svc[1];
89 core->Spsr_copy = core->Spsr[SVCBANK];
90 core->Bank = SVCBANK;
91 break;
92 case ABORT32MODE:
93 core->Reg[13] = core->Reg_abort[0];
94 core->Reg[14] = core->Reg_abort[1];
95 core->Spsr_copy = core->Spsr[ABORTBANK];
96 core->Bank = ABORTBANK;
97 break;
98 case UNDEF32MODE:
99 core->Reg[13] = core->Reg_undef[0];
100 core->Reg[14] = core->Reg_undef[1];
101 core->Spsr_copy = core->Spsr[UNDEFBANK];
102 core->Bank = UNDEFBANK;
103 break;
104 case FIQ32MODE:
105 core->Reg[13] = core->Reg_firq[0];
106 core->Reg[14] = core->Reg_firq[1];
107 core->Spsr_copy = core->Spsr[FIQBANK];
108 core->Bank = FIQBANK;
109 break;
110
111 }
112 core->Mode = mode;
113 //printf("In %si end, Cpsr=0x%x, R15=0x%x, last_pc=0x%x, cpsr=0x%x, spsr_copy=0x%x, icounter=%lld\n", __FUNCTION__, core->Cpsr, core->Reg[15], core->last_pc, core->Cpsr, core->Spsr_copy, core->icounter);
114 //printf("\n--------------------------------------\n");
115 }
116 else {
117 printf("user mode\n");
118 exit(-2);
119 }
120}
diff --git a/src/core/arm/dyncom/arm_dyncom_run.h b/src/core/arm/dyncom/arm_dyncom_run.h
new file mode 100644
index 000000000..aeabeac16
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom_run.h
@@ -0,0 +1,55 @@
1/* Copyright (C)
2* 2011 - Michael.Kang blackfin.kang@gmail.com
3* This program is free software; you can redistribute it and/or
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18
19#ifndef __ARM_DYNCOM_RUN__
20#define __ARM_DYNCOM_RUN__
21
22#include "core/arm/skyeye_common/skyeye_types.h"
23
24void switch_mode(arm_core_t *core, uint32_t mode);
25
26/* FIXME, we temporarily think thumb instruction is always 16 bit */
27static inline uint32 GET_INST_SIZE(arm_core_t* core){
28 return core->TFlag? 2 : 4;
29}
30
31/**
32* @brief Read R15 and forced R15 to wold align, used address calculation
33*
34* @param core
35* @param Rn
36*
37* @return
38*/
39static inline addr_t CHECK_READ_REG15_WA(arm_core_t* core, int Rn){
40 return (Rn == 15)? ((core->Reg[15] & ~0x3) + GET_INST_SIZE(core) * 2) : core->Reg[Rn];
41}
42
43/**
44* @brief Read R15, used to data processing with pc
45*
46* @param core
47* @param Rn
48*
49* @return
50*/
51static inline uint32 CHECK_READ_REG15(arm_core_t* core, int Rn){
52 return (Rn == 15)? ((core->Reg[15] & ~0x1) + GET_INST_SIZE(core) * 2) : core->Reg[Rn];
53}
54
55#endif
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
new file mode 100644
index 000000000..e10f2f9ee
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
@@ -0,0 +1,521 @@
1/* Copyright (C)
2* 2011 - Michael.Kang blackfin.kang@gmail.com
3* This program is free software; you can redistribute it and/or
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18/**
19* @file arm_dyncom_thumb.c
20* @brief The thumb dynamic interpreter
21* @author Michael.Kang blackfin.kang@gmail.com
22* @version 78.77
23* @date 2011-11-07
24*/
25
26/* We can provide simple Thumb simulation by decoding the Thumb
27instruction into its corresponding ARM instruction, and using the
28existing ARM simulator. */
29
30#include "core/arm/skyeye_common/skyeye_defs.h"
31
32#ifndef MODET /* required for the Thumb instruction support */
33#if 1
34#error "MODET needs to be defined for the Thumb world to work"
35#else
36#define MODET (1)
37#endif
38#endif
39
40#include "core/arm/skyeye_common/armos.h"
41#include "core/arm/dyncom/arm_dyncom_thumb.h"
42
43/* Decode a 16bit Thumb instruction. The instruction is in the low
44 16-bits of the tinstr field, with the following Thumb instruction
45 held in the high 16-bits. Passing in two Thumb instructions allows
46 easier simulation of the special dual BL instruction. */
47
48tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size)
49{
50 tdstate valid = t_uninitialized;
51 ARMword next_instr;
52 ARMword tinstr;
53 tinstr = instr;
54 /* The endian should be judge here */
55 #if 0
56 if (state->bigendSig) {
57 next_instr = tinstr & 0xFFFF;
58 tinstr >>= 16;
59 }
60 else {
61 next_instr = tinstr >> 16;
62 tinstr &= 0xFFFF;
63 }
64 #endif
65 if((addr & 0x3) != 0)
66 tinstr = instr >> 16;
67 else
68 tinstr &= 0xFFFF;
69
70 //printf("In %s, instr=0x%x, tinstr=0x%x, r15=0x%x\n", __FUNCTION__, instr, tinstr, cpu->translate_pc);
71#if 1 /* debugging to catch non updates */
72 *ainstr = 0xDEADC0DE;
73#endif
74
75 switch ((tinstr & 0xF800) >> 11) {
76 case 0: /* LSL */
77 case 1: /* LSR */
78 case 2: /* ASR */
79 /* Format 1 */
80 *ainstr = 0xE1B00000 /* base opcode */
81 | ((tinstr & 0x1800) >> (11 - 5)) /* shift type */
82 |((tinstr & 0x07C0) << (7 - 6)) /* imm5 */
83 |((tinstr & 0x0038) >> 3) /* Rs */
84 |((tinstr & 0x0007) << 12); /* Rd */
85 break;
86 case 3: /* ADD/SUB */
87 /* Format 2 */
88 {
89 ARMword subset[4] = {
90 0xE0900000, /* ADDS Rd,Rs,Rn */
91 0xE0500000, /* SUBS Rd,Rs,Rn */
92 0xE2900000, /* ADDS Rd,Rs,#imm3 */
93 0xE2500000 /* SUBS Rd,Rs,#imm3 */
94 };
95 /* It is quicker indexing into a table, than performing switch
96 or conditionals: */
97 *ainstr = subset[(tinstr & 0x0600) >> 9] /* base opcode */
98 |((tinstr & 0x01C0) >> 6) /* Rn or imm3 */
99 |((tinstr & 0x0038) << (16 - 3)) /* Rs */
100 |((tinstr & 0x0007) << (12 - 0)); /* Rd */
101 }
102 break;
103 case 4: /* MOV */
104 case 5: /* CMP */
105 case 6: /* ADD */
106 case 7: /* SUB */
107 /* Format 3 */
108 {
109 ARMword subset[4] = {
110 0xE3B00000, /* MOVS Rd,#imm8 */
111 0xE3500000, /* CMP Rd,#imm8 */
112 0xE2900000, /* ADDS Rd,Rd,#imm8 */
113 0xE2500000, /* SUBS Rd,Rd,#imm8 */
114 };
115 *ainstr = subset[(tinstr & 0x1800) >> 11] /* base opcode */
116 |((tinstr & 0x00FF) >> 0) /* imm8 */
117 |((tinstr & 0x0700) << (16 - 8)) /* Rn */
118 |((tinstr & 0x0700) << (12 - 8)); /* Rd */
119 }
120 break;
121 case 8: /* Arithmetic and high register transfers */
122 /* TODO: Since the subsets for both Format 4 and Format 5
123 instructions are made up of different ARM encodings, we could
124 save the following conditional, and just have one large
125 subset. */
126 if ((tinstr & (1 << 10)) == 0) {
127 typedef enum
128 { t_norm, t_shift, t_neg, t_mul }otype_t;
129
130 /* Format 4 */
131 struct
132 {
133 ARMword opcode;
134 otype_t otype;
135 }
136 subset[16] = {
137 {
138 0xE0100000, t_norm}, /* ANDS Rd,Rd,Rs */
139 {
140 0xE0300000, t_norm}, /* EORS Rd,Rd,Rs */
141 {
142 0xE1B00010, t_shift}, /* MOVS Rd,Rd,LSL Rs */
143 {
144 0xE1B00030, t_shift}, /* MOVS Rd,Rd,LSR Rs */
145 {
146 0xE1B00050, t_shift}, /* MOVS Rd,Rd,ASR Rs */
147 {
148 0xE0B00000, t_norm}, /* ADCS Rd,Rd,Rs */
149 {
150 0xE0D00000, t_norm}, /* SBCS Rd,Rd,Rs */
151 {
152 0xE1B00070, t_shift}, /* MOVS Rd,Rd,ROR Rs */
153 {
154 0xE1100000, t_norm}, /* TST Rd,Rs */
155 {
156 0xE2700000, t_neg}, /* RSBS Rd,Rs,#0 */
157 {
158 0xE1500000, t_norm}, /* CMP Rd,Rs */
159 {
160 0xE1700000, t_norm}, /* CMN Rd,Rs */
161 {
162 0xE1900000, t_norm}, /* ORRS Rd,Rd,Rs */
163 {
164 0xE0100090, t_mul}, /* MULS Rd,Rd,Rs */
165 {
166 0xE1D00000, t_norm}, /* BICS Rd,Rd,Rs */
167 {
168 0xE1F00000, t_norm} /* MVNS Rd,Rs */
169 };
170 *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; /* base */
171 switch (subset[(tinstr & 0x03C0) >> 6].otype) {
172 case t_norm:
173 *ainstr |= ((tinstr & 0x0007) << 16) /* Rn */
174 |((tinstr & 0x0007) << 12) /* Rd */
175 |((tinstr & 0x0038) >> 3); /* Rs */
176 break;
177 case t_shift:
178 *ainstr |= ((tinstr & 0x0007) << 12) /* Rd */
179 |((tinstr & 0x0007) >> 0) /* Rm */
180 |((tinstr & 0x0038) << (8 - 3)); /* Rs */
181 break;
182 case t_neg:
183 *ainstr |= ((tinstr & 0x0007) << 12) /* Rd */
184 |((tinstr & 0x0038) << (16 - 3)); /* Rn */
185 break;
186 case t_mul:
187 *ainstr |= ((tinstr & 0x0007) << 16) /* Rd */
188 |((tinstr & 0x0007) << 8) /* Rs */
189 |((tinstr & 0x0038) >> 3); /* Rm */
190 break;
191 }
192 }
193 else {
194 /* Format 5 */
195 ARMword Rd = ((tinstr & 0x0007) >> 0);
196 ARMword Rs = ((tinstr & 0x0038) >> 3);
197 if (tinstr & (1 << 7))
198 Rd += 8;
199 if (tinstr & (1 << 6))
200 Rs += 8;
201 switch ((tinstr & 0x03C0) >> 6) {
202 case 0x1: /* ADD Rd,Rd,Hs */
203 case 0x2: /* ADD Hd,Hd,Rs */
204 case 0x3: /* ADD Hd,Hd,Hs */
205 *ainstr = 0xE0800000 /* base */
206 | (Rd << 16) /* Rn */
207 |(Rd << 12) /* Rd */
208 |(Rs << 0); /* Rm */
209 break;
210 case 0x5: /* CMP Rd,Hs */
211 case 0x6: /* CMP Hd,Rs */
212 case 0x7: /* CMP Hd,Hs */
213 *ainstr = 0xE1500000 /* base */
214 | (Rd << 16) /* Rn */
215 |(Rd << 12) /* Rd */
216 |(Rs << 0); /* Rm */
217 break;
218 case 0x9: /* MOV Rd,Hs */
219 case 0xA: /* MOV Hd,Rs */
220 case 0xB: /* MOV Hd,Hs */
221 *ainstr = 0xE1A00000 /* base */
222 | (Rd << 16) /* Rn */
223 |(Rd << 12) /* Rd */
224 |(Rs << 0); /* Rm */
225 break;
226 case 0xC: /* BX Rs */
227 case 0xD: /* BX Hs */
228 *ainstr = 0xE12FFF10 /* base */
229 | ((tinstr & 0x0078) >> 3); /* Rd */
230 break;
231 case 0x0: /* UNDEFINED */
232 case 0x4: /* UNDEFINED */
233 case 0x8: /* UNDEFINED */
234 valid = t_undefined;
235 break;
236 case 0xE: /* BLX */
237 case 0xF: /* BLX */
238
239 //if (state->is_v5) {
240 if(1){
241 //valid = t_branch;
242 #if 1
243 *ainstr = 0xE1200030 /* base */
244 |(Rs << 0); /* Rm */
245 #endif
246 } else {
247 valid = t_undefined;
248 }
249 break;
250 }
251 }
252 break;
253 case 9: /* LDR Rd,[PC,#imm8] */
254 /* Format 6 */
255 *ainstr = 0xE59F0000 /* base */
256 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
257 |((tinstr & 0x00FF) << (2 - 0)); /* off8 */
258 break;
259 case 10:
260 case 11:
261 /* TODO: Format 7 and Format 8 perform the same ARM encoding, so
262 the following could be merged into a single subset, saving on
263 the following boolean: */
264 if ((tinstr & (1 << 9)) == 0) {
265 /* Format 7 */
266 ARMword subset[4] = {
267 0xE7800000, /* STR Rd,[Rb,Ro] */
268 0xE7C00000, /* STRB Rd,[Rb,Ro] */
269 0xE7900000, /* LDR Rd,[Rb,Ro] */
270 0xE7D00000 /* LDRB Rd,[Rb,Ro] */
271 };
272 *ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
273 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
274 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
275 |((tinstr & 0x01C0) >> 6); /* Ro */
276 }
277 else {
278 /* Format 8 */
279 ARMword subset[4] = {
280 0xE18000B0, /* STRH Rd,[Rb,Ro] */
281 0xE19000D0, /* LDRSB Rd,[Rb,Ro] */
282 0xE19000B0, /* LDRH Rd,[Rb,Ro] */
283 0xE19000F0 /* LDRSH Rd,[Rb,Ro] */
284 };
285 *ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
286 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
287 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
288 |((tinstr & 0x01C0) >> 6); /* Ro */
289 }
290 break;
291 case 12: /* STR Rd,[Rb,#imm5] */
292 case 13: /* LDR Rd,[Rb,#imm5] */
293 case 14: /* STRB Rd,[Rb,#imm5] */
294 case 15: /* LDRB Rd,[Rb,#imm5] */
295 /* Format 9 */
296 {
297 ARMword subset[4] = {
298 0xE5800000, /* STR Rd,[Rb,#imm5] */
299 0xE5900000, /* LDR Rd,[Rb,#imm5] */
300 0xE5C00000, /* STRB Rd,[Rb,#imm5] */
301 0xE5D00000 /* LDRB Rd,[Rb,#imm5] */
302 };
303 /* The offset range defends on whether we are transferring a
304 byte or word value: */
305 *ainstr = subset[(tinstr & 0x1800) >> 11] /* base */
306 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
307 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
308 |((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); /* off5 */
309 }
310 break;
311 case 16: /* STRH Rd,[Rb,#imm5] */
312 case 17: /* LDRH Rd,[Rb,#imm5] */
313 /* Format 10 */
314 *ainstr = ((tinstr & (1 << 11)) /* base */
315 ? 0xE1D000B0 /* LDRH */
316 : 0xE1C000B0) /* STRH */
317 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
318 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
319 |((tinstr & 0x01C0) >> (6 - 1)) /* off5, low nibble */
320 |((tinstr & 0x0600) >> (9 - 8)); /* off5, high nibble */
321 break;
322 case 18: /* STR Rd,[SP,#imm8] */
323 case 19: /* LDR Rd,[SP,#imm8] */
324 /* Format 11 */
325 *ainstr = ((tinstr & (1 << 11)) /* base */
326 ? 0xE59D0000 /* LDR */
327 : 0xE58D0000) /* STR */
328 |((tinstr & 0x0700) << (12 - 8)) /* Rd */
329 |((tinstr & 0x00FF) << 2); /* off8 */
330 break;
331 case 20: /* ADD Rd,PC,#imm8 */
332 case 21: /* ADD Rd,SP,#imm8 */
333 /* Format 12 */
334 if ((tinstr & (1 << 11)) == 0) {
335 /* NOTE: The PC value used here should by word aligned */
336 /* We encode shift-left-by-2 in the rotate immediate field,
337 so no shift of off8 is needed. */
338 *ainstr = 0xE28F0F00 /* base */
339 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
340 |(tinstr & 0x00FF); /* off8 */
341 }
342 else {
343 /* We encode shift-left-by-2 in the rotate immediate field,
344 so no shift of off8 is needed. */
345 *ainstr = 0xE28D0F00 /* base */
346 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
347 |(tinstr & 0x00FF); /* off8 */
348 }
349 break;
350 case 22:
351 case 23:
352 if ((tinstr & 0x0F00) == 0x0000) {
353 /* Format 13 */
354 /* NOTE: The instruction contains a shift left of 2
355 equivalent (implemented as ROR #30): */
356 *ainstr = ((tinstr & (1 << 7)) /* base */
357 ? 0xE24DDF00 /* SUB */
358 : 0xE28DDF00) /* ADD */
359 |(tinstr & 0x007F); /* off7 */
360 }
361 else if ((tinstr & 0x0F00) == 0x0e00)
362 *ainstr = 0xEF000000 | SWI_Breakpoint;
363 else {
364 /* Format 14 */
365 ARMword subset[4] = {
366 0xE92D0000, /* STMDB sp!,{rlist} */
367 0xE92D4000, /* STMDB sp!,{rlist,lr} */
368 0xE8BD0000, /* LDMIA sp!,{rlist} */
369 0xE8BD8000 /* LDMIA sp!,{rlist,pc} */
370 };
371 *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] /* base */
372 |(tinstr & 0x00FF); /* mask8 */
373 }
374 break;
375 case 24: /* STMIA */
376 case 25: /* LDMIA */
377 /* Format 15 */
378 *ainstr = ((tinstr & (1 << 11)) /* base */
379 ? 0xE8B00000 /* LDMIA */
380 : 0xE8A00000) /* STMIA */
381 |((tinstr & 0x0700) << (16 - 8)) /* Rb */
382 |(tinstr & 0x00FF); /* mask8 */
383 break;
384 case 26: /* Bcc */
385 case 27: /* Bcc/SWI */
386 if ((tinstr & 0x0F00) == 0x0F00) {
387 #if 0
388 if (tinstr == (ARMul_ABORTWORD & 0xffff) &&
389 state->AbortAddr == pc) {
390 *ainstr = ARMul_ABORTWORD;
391 break;
392 }
393 #endif
394 /* Format 17 : SWI */
395 *ainstr = 0xEF000000;
396 /* Breakpoint must be handled specially. */
397 if ((tinstr & 0x00FF) == 0x18)
398 *ainstr |= ((tinstr & 0x00FF) << 16);
399 /* New breakpoint value. See gdb/arm-tdep.c */
400 else if ((tinstr & 0x00FF) == 0xFE)
401 *ainstr |= SWI_Breakpoint;
402 else
403 *ainstr |= (tinstr & 0x00FF);
404 }
405 else if ((tinstr & 0x0F00) != 0x0E00) {
406 /* Format 16 */
407 #if 0
408 int doit = FALSE;
409 /* TODO: Since we are doing a switch here, we could just add
410 the SWI and undefined instruction checks into this
411 switch to same on a couple of conditionals: */
412 switch ((tinstr & 0x0F00) >> 8) {
413 case EQ:
414 doit = ZFLAG;
415 break;
416 case NE:
417 doit = !ZFLAG;
418 break;
419 case VS:
420 doit = VFLAG;
421 break;
422 case VC:
423 doit = !VFLAG;
424 break;
425 case MI:
426 doit = NFLAG;
427 break;
428 case PL:
429 doit = !NFLAG;
430 break;
431 case CS:
432 doit = CFLAG;
433 break;
434 case CC:
435 doit = !CFLAG;
436 break;
437 case HI:
438 doit = (CFLAG && !ZFLAG);
439 break;
440 case LS:
441 doit = (!CFLAG || ZFLAG);
442 break;
443 case GE:
444 doit = ((!NFLAG && !VFLAG)
445 || (NFLAG && VFLAG));
446 break;
447 case LT:
448 doit = ((NFLAG && !VFLAG)
449 || (!NFLAG && VFLAG));
450 break;
451 case GT:
452 doit = ((!NFLAG && !VFLAG && !ZFLAG)
453 || (NFLAG && VFLAG && !ZFLAG));
454 break;
455 case LE:
456 doit = ((NFLAG && !VFLAG)
457 || (!NFLAG && VFLAG)) || ZFLAG;
458 break;
459 }
460 if (doit) {
461 state->Reg[15] = (pc + 4
462 + (((tinstr & 0x7F) << 1)
463 | ((tinstr & (1 << 7)) ?
464 0xFFFFFF00 : 0)));
465 FLUSHPIPE;
466 }
467 #endif
468 valid = t_branch;
469 }
470 else /* UNDEFINED : cc=1110(AL) uses different format */
471 valid = t_undefined;
472 break;
473 case 28: /* B */
474 /* Format 18 */
475 #if 0
476 state->Reg[15] = (pc + 4 + (((tinstr & 0x3FF) << 1)
477 | ((tinstr & (1 << 10)) ?
478 0xFFFFF800 : 0)));
479 #endif
480 //FLUSHPIPE;
481 valid = t_branch;
482 break;
483 case 29:
484 if(tinstr & 0x1)
485 valid = t_undefined;
486 else{
487 /* BLX 1 for armv5t and above */
488 //printf("In %s, After BLX(1),LR=0x%x,PC=0x%x, offset=0x%x\n", __FUNCTION__, state->Reg[14], state->Reg[15], (tinstr &0x7FF) << 1);
489 valid = t_branch;
490 }
491 break;
492 case 30: /* BL instruction 1 */
493 /* Format 19 */
494 /* There is no single ARM instruction equivalent for this Thumb
495 instruction. To keep the simulation simple (from the user
496 perspective) we check if the following instruction is the
497 second half of this BL, and if it is we simulate it
498 immediately. */
499 valid = t_branch;
500 break;
501 case 31: /* BL instruction 2 */
502 /* Format 19 */
503 /* There is no single ARM instruction equivalent for this
504 instruction. Also, it should only ever be matched with the
505 fmt19 "BL instruction 1" instruction. However, we do allow
506 the simulation of it on its own, with undefined results if
507 r14 is not suitably initialised. */
508 {
509 #if 0
510 ARMword tmp = (pc + 2);
511 state->Reg[15] =
512 (state->Reg[14] + ((tinstr & 0x07FF) << 1));
513 state->Reg[14] = (tmp | 1);
514 #endif
515 valid = t_branch;
516 }
517 break;
518 }
519 *inst_size = 2;
520 return valid;
521}
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h
new file mode 100644
index 000000000..5541de9d1
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.h
@@ -0,0 +1,51 @@
1/* Copyright (C)
2* 2011 - Michael.Kang blackfin.kang@gmail.com
3* This program is free software; you can redistribute it and/or
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18
19/**
20* @file arm_dyncom_thumb.h
21* @brief The thumb dyncom
22* @author Michael.Kang blackfin.kang@gmail.com
23* @version 78.77
24* @date 2011-11-07
25*/
26
27#ifndef __ARM_DYNCOM_THUMB_H__
28#define __ARM_DYNCOM_THUMB_H__
29
30#include "core/arm/skyeye_common/armdefs.h"
31#include "core/arm/skyeye_common/skyeye_types.h"
32
33enum tdstate {
34 t_undefined, // Undefined Thumb instruction
35 t_decoded, // Instruction decoded to ARM equivalent
36 t_branch, // Thumb branch (already processed)
37 t_uninitialized,
38};
39
40tdstate
41thumb_translate(addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size);
42static inline uint32 get_thumb_instr(uint32 instr, addr_t pc){
43 uint32 tinstr;
44 if ((pc & 0x3) != 0)
45 tinstr = instr >> 16;
46 else
47 tinstr = instr & 0xFFFF;
48 return tinstr;
49}
50
51#endif
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp
index 0842d2f8e..ed4415082 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,12 +17,11 @@ 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);
24 state->lateabtSig = LOW; 24 state->lateabtSig = LOW;
25 mmu_init(state);
26 25
27 // Reset the core to initial state 26 // Reset the core to initial state
28 ARMul_CoProInit(state); 27 ARMul_CoProInit(state);
diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h
index 1e82883a2..ceb1be438 100644
--- a/src/core/arm/interpreter/arm_interpreter.h
+++ b/src/core/arm/interpreter/arm_interpreter.h
@@ -7,10 +7,10 @@
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 final : virtual public ARM_Interface {
14public: 14public:
15 15
16 ARM_Interpreter(); 16 ARM_Interpreter();
@@ -20,60 +20,60 @@ public:
20 * Set the Program Counter to an address 20 * Set the Program Counter to an address
21 * @param addr Address to set PC to 21 * @param addr Address to set PC to
22 */ 22 */
23 void SetPC(u32 pc); 23 void SetPC(u32 pc) override;
24 24
25 /* 25 /*
26 * Get the current Program Counter 26 * Get the current Program Counter
27 * @return Returns current PC 27 * @return Returns current PC
28 */ 28 */
29 u32 GetPC() const; 29 u32 GetPC() const override;
30 30
31 /** 31 /**
32 * Get an ARM register 32 * Get an ARM register
33 * @param index Register index (0-15) 33 * @param index Register index (0-15)
34 * @return Returns the value in the register 34 * @return Returns the value in the register
35 */ 35 */
36 u32 GetReg(int index) const; 36 u32 GetReg(int index) const override;
37 37
38 /** 38 /**
39 * Set an ARM register 39 * Set an ARM register
40 * @param index Register index (0-15) 40 * @param index Register index (0-15)
41 * @param value Value to set register to 41 * @param value Value to set register to
42 */ 42 */
43 void SetReg(int index, u32 value); 43 void SetReg(int index, u32 value) override;
44 44
45 /** 45 /**
46 * Get the current CPSR register 46 * Get the current CPSR register
47 * @return Returns the value of the CPSR register 47 * @return Returns the value of the CPSR register
48 */ 48 */
49 u32 GetCPSR() const; 49 u32 GetCPSR() const override;
50 50
51 /** 51 /**
52 * Set the current CPSR register 52 * Set the current CPSR register
53 * @param cpsr Value to set CPSR to 53 * @param cpsr Value to set CPSR to
54 */ 54 */
55 void SetCPSR(u32 cpsr); 55 void SetCPSR(u32 cpsr) override;
56 56
57 /** 57 /**
58 * Returns the number of clock ticks since the last reset 58 * Returns the number of clock ticks since the last reset
59 * @return Returns number of clock ticks 59 * @return Returns number of clock ticks
60 */ 60 */
61 u64 GetTicks() const; 61 u64 GetTicks() const override;
62 62
63 /** 63 /**
64 * Saves the current CPU context 64 * Saves the current CPU context
65 * @param ctx Thread context to save 65 * @param ctx Thread context to save
66 */ 66 */
67 void SaveContext(ThreadContext& ctx); 67 void SaveContext(ThreadContext& ctx) override;
68 68
69 /** 69 /**
70 * Loads a CPU context 70 * Loads a CPU context
71 * @param ctx Thread context to load 71 * @param ctx Thread context to load
72 */ 72 */
73 void LoadContext(const ThreadContext& ctx); 73 void LoadContext(const ThreadContext& ctx) override;
74 74
75 /// Prepare core for thread reschedule (if needed to correctly handle state) 75 /// Prepare core for thread reschedule (if needed to correctly handle state)
76 void PrepareReschedule(); 76 void PrepareReschedule() override;
77 77
78protected: 78protected:
79 79
@@ -81,7 +81,7 @@ protected:
81 * Executes the given number of instructions 81 * Executes the given number of instructions
82 * @param num_instructions Number of instructions to executes 82 * @param num_instructions Number of instructions to executes
83 */ 83 */
84 void ExecuteInstructions(int num_instructions); 84 void ExecuteInstructions(int num_instructions) override;
85 85
86private: 86private:
87 87
diff --git a/src/core/arm/interpreter/armcopro.cpp b/src/core/arm/interpreter/armcopro.cpp
index 6a75e6601..b4ddc3d96 100644
--- a/src/core/arm/interpreter/armcopro.cpp
+++ b/src/core/arm/interpreter/armcopro.cpp
@@ -15,828 +15,311 @@
15 along with this program; if not, write to the Free Software 15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17 17
18 18#include "core/arm/skyeye_common/armdefs.h"
19#include "core/arm/interpreter/armdefs.h" 19#include "core/arm/skyeye_common/armemu.h"
20#include "core/arm/interpreter/armos.h" 20#include "core/arm/skyeye_common/vfp/vfp.h"
21#include "core/arm/interpreter/armemu.h"
22#include "core/arm/interpreter/vfp/vfp.h"
23 21
24//chy 2005-07-08 22//chy 2005-07-08
25//#include "ansidecl.h" 23//#include "ansidecl.h"
26//chy ------- 24//chy -------
27//#include "iwmmxt.h" 25//#include "iwmmxt.h"
28 26
29
30//chy 2005-09-19 add CP6 MRC support (for get irq number and base)
31extern unsigned xscale_cp6_mrc (ARMul_State * state, unsigned type,
32 ARMword instr, ARMword * data);
33//chy 2005-09-19---------------
34
35extern unsigned xscale_cp13_init (ARMul_State * state);
36extern unsigned xscale_cp13_exit (ARMul_State * state);
37extern unsigned xscale_cp13_ldc (ARMul_State * state, unsigned type,
38 ARMword instr, ARMword data);
39extern unsigned xscale_cp13_stc (ARMul_State * state, unsigned type,
40 ARMword instr, ARMword * data);
41extern unsigned xscale_cp13_mrc (ARMul_State * state, unsigned type,
42 ARMword instr, ARMword * data);
43extern unsigned xscale_cp13_mcr (ARMul_State * state, unsigned type,
44 ARMword instr, ARMword data);
45extern unsigned xscale_cp13_cdp (ARMul_State * state, unsigned type,
46 ARMword instr);
47extern unsigned xscale_cp13_read_reg (ARMul_State * state, unsigned reg,
48 ARMword * data);
49extern unsigned xscale_cp13_write_reg (ARMul_State * state, unsigned reg,
50 ARMword data);
51extern unsigned xscale_cp14_init (ARMul_State * state);
52extern unsigned xscale_cp14_exit (ARMul_State * state);
53extern unsigned xscale_cp14_ldc (ARMul_State * state, unsigned type,
54 ARMword instr, ARMword data);
55extern unsigned xscale_cp14_stc (ARMul_State * state, unsigned type,
56 ARMword instr, ARMword * data);
57extern unsigned xscale_cp14_mrc (ARMul_State * state, unsigned type,
58 ARMword instr, ARMword * data);
59extern unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type,
60 ARMword instr, ARMword data);
61extern unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type,
62 ARMword instr);
63extern unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg,
64 ARMword * data);
65extern unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg,
66 ARMword data);
67extern unsigned xscale_cp15_init (ARMul_State * state);
68extern unsigned xscale_cp15_exit (ARMul_State * state);
69extern unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type,
70 ARMword instr, ARMword data);
71extern unsigned xscale_cp15_stc (ARMul_State * state, unsigned type,
72 ARMword instr, ARMword * data);
73extern unsigned xscale_cp15_mrc (ARMul_State * state, unsigned type,
74 ARMword instr, ARMword * data);
75extern unsigned xscale_cp15_mcr (ARMul_State * state, unsigned type,
76 ARMword instr, ARMword data);
77extern unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type,
78 ARMword instr);
79extern unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg,
80 ARMword * data);
81extern unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg,
82 ARMword data);
83extern unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
84 unsigned cpnum);
85
86/* Dummy Co-processors. */ 27/* Dummy Co-processors. */
87 28
88static unsigned 29static unsigned
89NoCoPro3R (ARMul_State * state, 30NoCoPro3R(ARMul_State * state,
90 unsigned a, ARMword b) 31unsigned a, ARMword b)
91{ 32{
92 return ARMul_CANT; 33 return ARMul_CANT;
93} 34}
94 35
95static unsigned 36static unsigned
96NoCoPro4R (ARMul_State * state, 37NoCoPro4R(ARMul_State * state,
97 unsigned a, 38unsigned a,
98 ARMword b, ARMword c) 39ARMword b, ARMword c)
99{ 40{
100 return ARMul_CANT; 41 return ARMul_CANT;
101} 42}
102 43
103static unsigned 44static unsigned
104NoCoPro4W (ARMul_State * state, 45NoCoPro4W(ARMul_State * state,
105 unsigned a, 46unsigned a,
106 ARMword b, ARMword * c) 47ARMword b, ARMword * c)
107{ 48{
108 return ARMul_CANT; 49 return ARMul_CANT;
109} 50}
110 51
111static unsigned 52static unsigned
112NoCoPro5R (ARMul_State * state, 53NoCoPro5R(ARMul_State * state,
113 unsigned a, 54unsigned a,
114 ARMword b, 55ARMword b,
115 ARMword c, ARMword d) 56ARMword c, ARMword d)
116{ 57{
117 return ARMul_CANT; 58 return ARMul_CANT;
118} 59}
119 60
120static unsigned 61static unsigned
121NoCoPro5W (ARMul_State * state, 62NoCoPro5W(ARMul_State * state,
122 unsigned a, 63unsigned a,
123 ARMword b, 64ARMword b,
124 ARMword * c, ARMword * d ) 65ARMword * c, ARMword * d)
125{ 66{
126 return ARMul_CANT; 67 return ARMul_CANT;
127} 68}
128 69
129/* The XScale Co-processors. */ 70/* The XScale Co-processors. */
130 71
131/* Coprocessor 15: System Control. */ 72/* Coprocessor 15: System Control. */
132static void write_cp14_reg (unsigned, ARMword); 73static void write_cp14_reg(unsigned, ARMword);
133static ARMword read_cp14_reg (unsigned); 74static ARMword read_cp14_reg(unsigned);
134
135/* There are two sets of registers for copro 15.
136 One set is available when opcode_2 is 0 and
137 the other set when opcode_2 >= 1. */
138static ARMword XScale_cp15_opcode_2_is_0_Regs[16];
139static ARMword XScale_cp15_opcode_2_is_not_0_Regs[16];
140/* There are also a set of breakpoint registers
141 which are accessed via CRm instead of opcode_2. */
142static ARMword XScale_cp15_DBR1;
143static ARMword XScale_cp15_DBCON;
144static ARMword XScale_cp15_IBCR0;
145static ARMword XScale_cp15_IBCR1;
146
147static unsigned
148XScale_cp15_init (ARMul_State * state)
149{
150 int i;
151
152 for (i = 16; i--;) {
153 XScale_cp15_opcode_2_is_0_Regs[i] = 0;
154 XScale_cp15_opcode_2_is_not_0_Regs[i] = 0;
155 }
156
157 /* Initialise the processor ID. */
158 //chy 2003-03-24, is same as cpu id in skyeye_options.c
159 //XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000;
160 XScale_cp15_opcode_2_is_0_Regs[0] = 0x69050000;
161
162 /* Initialise the cache type. */
163 XScale_cp15_opcode_2_is_not_0_Regs[0] = 0x0B1AA1AA;
164
165 /* Initialise the ARM Control Register. */
166 XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078;
167
168 return No_exp;
169}
170
171/* Check an access to a register. */
172
173static unsigned
174check_cp15_access (ARMul_State * state,
175 unsigned reg,
176 unsigned CRm, unsigned opcode_1, unsigned opcode_2)
177{
178 /* Do not allow access to these register in USER mode. */
179 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
180 if (state->Mode == USER26MODE || state->Mode == USER32MODE )
181 return ARMul_CANT;
182
183 /* Opcode_1should be zero. */
184 if (opcode_1 != 0)
185 return ARMul_CANT;
186
187 /* Different register have different access requirements. */
188 switch (reg) {
189 case 0:
190 case 1:
191 /* CRm must be 0. Opcode_2 can be anything. */
192 if (CRm != 0)
193 return ARMul_CANT;
194 break;
195 case 2:
196 case 3:
197 /* CRm must be 0. Opcode_2 must be zero. */
198 if ((CRm != 0) || (opcode_2 != 0))
199 return ARMul_CANT;
200 break;
201 case 4:
202 /* Access not allowed. */
203 return ARMul_CANT;
204 case 5:
205 case 6:
206 /* Opcode_2 must be zero. CRm must be 0. */
207 if ((CRm != 0) || (opcode_2 != 0))
208 return ARMul_CANT;
209 break;
210 case 7:
211 /* Permissable combinations:
212 Opcode_2 CRm
213 0 5
214 0 6
215 0 7
216 1 5
217 1 6
218 1 10
219 4 10
220 5 2
221 6 5 */
222 switch (opcode_2) {
223 default:
224 return ARMul_CANT;
225 case 6:
226 if (CRm != 5)
227 return ARMul_CANT;
228 break;
229 case 5:
230 if (CRm != 2)
231 return ARMul_CANT;
232 break;
233 case 4:
234 if (CRm != 10)
235 return ARMul_CANT;
236 break;
237 case 1:
238 if ((CRm != 5) && (CRm != 6) && (CRm != 10))
239 return ARMul_CANT;
240 break;
241 case 0:
242 if ((CRm < 5) || (CRm > 7))
243 return ARMul_CANT;
244 break;
245 }
246 break;
247
248 case 8:
249 /* Permissable combinations:
250 Opcode_2 CRm
251 0 5
252 0 6
253 0 7
254 1 5
255 1 6 */
256 if (opcode_2 > 1)
257 return ARMul_CANT;
258 if ((CRm < 5) || (CRm > 7))
259 return ARMul_CANT;
260 if (opcode_2 == 1 && CRm == 7)
261 return ARMul_CANT;
262 break;
263 case 9:
264 /* Opcode_2 must be zero or one. CRm must be 1 or 2. */
265 if (((CRm != 0) && (CRm != 1))
266 || ((opcode_2 != 1) && (opcode_2 != 2)))
267 return ARMul_CANT;
268 break;
269 case 10:
270 /* Opcode_2 must be zero or one. CRm must be 4 or 8. */
271 if (((CRm != 0) && (CRm != 1))
272 || ((opcode_2 != 4) && (opcode_2 != 8)))
273 return ARMul_CANT;
274 break;
275 case 11:
276 /* Access not allowed. */
277 return ARMul_CANT;
278 case 12:
279 /* Access not allowed. */
280 return ARMul_CANT;
281 case 13:
282 /* Opcode_2 must be zero. CRm must be 0. */
283 if ((CRm != 0) || (opcode_2 != 0))
284 return ARMul_CANT;
285 break;
286 case 14:
287 /* Opcode_2 must be 0. CRm must be 0, 3, 4, 8 or 9. */
288 if (opcode_2 != 0)
289 return ARMul_CANT;
290
291 if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8)
292 && (CRm != 9))
293 return ARMul_CANT;
294 break;
295 case 15:
296 /* Opcode_2 must be zero. CRm must be 1. */
297 if ((CRm != 1) || (opcode_2 != 0))
298 return ARMul_CANT;
299 break;
300 default:
301 /* Should never happen. */
302 return ARMul_CANT;
303 }
304
305 return ARMul_DONE;
306}
307
308/* Coprocessor 13: Interrupt Controller and Bus Controller. */
309
310/* There are two sets of registers for copro 13.
311 One set (of three registers) is available when CRm is 0
312 and the other set (of six registers) when CRm is 1. */
313
314static ARMword XScale_cp13_CR0_Regs[16];
315static ARMword XScale_cp13_CR1_Regs[16];
316
317static unsigned
318XScale_cp13_init (ARMul_State * state)
319{
320 int i;
321
322 for (i = 16; i--;) {
323 XScale_cp13_CR0_Regs[i] = 0;
324 XScale_cp13_CR1_Regs[i] = 0;
325 }
326
327 return No_exp;
328}
329
330/* Check an access to a register. */
331
332static unsigned
333check_cp13_access (ARMul_State * state,
334 unsigned reg,
335 unsigned CRm, unsigned opcode_1, unsigned opcode_2)
336{
337 /* Do not allow access to these registers in USER mode. */
338 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
339 if (state->Mode == USER26MODE || state->Mode == USER32MODE )
340 return ARMul_CANT;
341
342 /* The opcodes should be zero. */
343 if ((opcode_1 != 0) || (opcode_2 != 0))
344 return ARMul_CANT;
345
346 /* Do not allow access to these register if bit
347 13 of coprocessor 15's register 15 is zero. */
348 if (!CP_ACCESS_ALLOWED (state, 13))
349 return ARMul_CANT;
350
351 /* Registers 0, 4 and 8 are defined when CRm == 0.
352 Registers 0, 1, 4, 5, 6, 7, 8 are defined when CRm == 1.
353 For all other CRm values undefined behaviour results. */
354 if (CRm == 0) {
355 if (reg == 0 || reg == 4 || reg == 8)
356 return ARMul_DONE;
357 }
358 else if (CRm == 1) {
359 if (reg == 0 || reg == 1 || (reg >= 4 && reg <= 8))
360 return ARMul_DONE;
361 }
362
363 return ARMul_CANT;
364}
365
366/* Coprocessor 14: Performance Monitoring, Clock and Power management,
367 Software Debug. */
368
369static ARMword XScale_cp14_Regs[16];
370
371static unsigned
372XScale_cp14_init (ARMul_State * state)
373{
374 int i;
375
376 for (i = 16; i--;)
377 XScale_cp14_Regs[i] = 0;
378
379 return No_exp;
380}
381 75
382/* Check an access to a register. */ 76/* Check an access to a register. */
383 77
384static unsigned 78static unsigned
385check_cp14_access (ARMul_State * state, 79check_cp15_access(ARMul_State * state,
386 unsigned reg, 80unsigned reg,
387 unsigned CRm, unsigned opcode1, unsigned opcode2) 81unsigned CRm, unsigned opcode_1, unsigned opcode_2)
388{
389 /* Not allowed to access these register in USER mode. */
390 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
391 if (state->Mode == USER26MODE || state->Mode == USER32MODE )
392 return ARMul_CANT;
393
394 /* CRm should be zero. */
395 if (CRm != 0)
396 return ARMul_CANT;
397
398 /* OPcodes should be zero. */
399 if (opcode1 != 0 || opcode2 != 0)
400 return ARMul_CANT;
401
402 /* Accessing registers 4 or 5 has unpredicatable results. */
403 if (reg >= 4 && reg <= 5)
404 return ARMul_CANT;
405
406 return ARMul_DONE;
407}
408
409/* Here's ARMulator's MMU definition. A few things to note:
410 1) It has eight registers, but only two are defined.
411 2) You can only access its registers with MCR and MRC.
412 3) MMU Register 0 (ID) returns 0x41440110
413 4) Register 1 only has 4 bits defined. Bits 0 to 3 are unused, bit 4
414 controls 32/26 bit program space, bit 5 controls 32/26 bit data space,
415 bit 6 controls late abort timimg and bit 7 controls big/little endian. */
416
417static ARMword MMUReg[8];
418
419static unsigned
420MMUInit (ARMul_State * state)
421{
422/* 2004-05-09 chy
423-------------------------------------------------------------
424read ARM Architecture Reference Manual
4252.6.5 Data Abort
426There are three Abort Model in ARM arch.
427
428Early Abort Model: used in some ARMv3 and earlier implementations. In this
429model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and
430the base register was unchanged for all other instructions. (oldest)
431
432Base Restored Abort Model: If a Data Abort occurs in an instruction which
433specifies base register writeback, the value in the base register is
434unchanged. (strongarm, xscale)
435
436Base Updated Abort Model: If a Data Abort occurs in an instruction which
437specifies base register writeback, the base register writeback still occurs.
438(arm720T)
439
440read PART B
441chap2 The System Control Coprocessor CP15
4422.4 Register1:control register
443L(bit 6): in some ARMv3 and earlier implementations, the abort model of the
444processor could be configured:
4450=early Abort Model Selected(now obsolete)
4461=Late Abort Model selceted(same as Base Updated Abort Model)
447
448on later processors, this bit reads as 1 and ignores writes.
449-------------------------------------------------------------
450So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
451 if lateabtSig=0, then it means Base Restored Abort Model
452because the ARMs which skyeye simulates are all belonged to ARMv4,
453so I think MMUReg[1]'s bit 6 should always be 1
454
455*/
456
457 MMUReg[1] = state->prog32Sig << 4 |
458 state->data32Sig << 5 | 1 << 6 | state->bigendSig << 7;
459 //state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7;
460
461
462 NOTICE_LOG(ARM11, "ARMul_ConsolePrint: MMU present");
463
464 return TRUE;
465}
466
467static unsigned
468MMUMRC (ARMul_State * state, unsigned type,
469 ARMword instr, ARMword * value)
470{
471 mmu_mrc (state, instr, value);
472 return (ARMul_DONE);
473}
474
475static unsigned
476MMUMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
477{
478 mmu_mcr (state, instr, value);
479 return (ARMul_DONE);
480}
481
482/* What follows is the Validation Suite Coprocessor. It uses two
483 co-processor numbers (4 and 5) and has the follwing functionality.
484 Sixteen registers. Both co-processor nuimbers can be used in an MCR
485 and MRC to access these registers. CP 4 can LDC and STC to and from
486 the registers. CP 4 and CP 5 CDP 0 will busy wait for the number of
487 cycles specified by a CP register. CP 5 CDP 1 issues a FIQ after a
488 number of cycles (specified in a CP register), CDP 2 issues an IRQW
489 in the same way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5
490 stores a 32 bit time value in a CP register (actually it's the total
491 number of N, S, I, C and F cyles). */
492
493static ARMword ValReg[16];
494
495static unsigned
496ValLDC (ARMul_State * state,
497 unsigned type, ARMword instr, ARMword data)
498{
499 static unsigned words;
500
501 if (type != ARMul_DATA)
502 words = 0;
503 else {
504 ValReg[BITS (12, 15)] = data;
505
506 if (BIT (22))
507 /* It's a long access, get two words. */
508 if (words++ != 4)
509 return ARMul_INC;
510 }
511
512 return ARMul_DONE;
513}
514
515static unsigned
516ValSTC (ARMul_State * state,
517 unsigned type, ARMword instr, ARMword * data)
518{
519 static unsigned words;
520
521 if (type != ARMul_DATA)
522 words = 0;
523 else {
524 *data = ValReg[BITS (12, 15)];
525
526 if (BIT (22))
527 /* It's a long access, get two words. */
528 if (words++ != 4)
529 return ARMul_INC;
530 }
531
532 return ARMul_DONE;
533}
534
535static unsigned
536ValMRC (ARMul_State * state,
537 unsigned type, ARMword instr, ARMword * value)
538{
539 *value = ValReg[BITS (16, 19)];
540
541 return ARMul_DONE;
542}
543
544static unsigned
545ValMCR (ARMul_State * state,
546 unsigned type, ARMword instr, ARMword value)
547{
548 ValReg[BITS (16, 19)] = value;
549
550 return ARMul_DONE;
551}
552
553static unsigned
554ValCDP (ARMul_State * state, unsigned type, ARMword instr)
555{
556 static unsigned int finish = 0;
557
558 if (BITS (20, 23) != 0)
559 return ARMul_CANT;
560
561 if (type == ARMul_FIRST) {
562 ARMword howlong;
563
564 howlong = ValReg[BITS (0, 3)];
565
566 /* First cycle of a busy wait. */
567 finish = ARMul_Time (state) + howlong;
568
569 return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
570 }
571 else if (type == ARMul_BUSY) {
572 if (ARMul_Time (state) >= finish)
573 return ARMul_DONE;
574 else
575 return ARMul_BUSY;
576 }
577
578 return ARMul_CANT;
579}
580
581static unsigned
582DoAFIQ (ARMul_State * state)
583{
584 state->NfiqSig = LOW;
585 return 0;
586}
587
588static unsigned
589DoAIRQ (ARMul_State * state)
590{
591 state->NirqSig = LOW;
592 return 0;
593}
594
595static unsigned
596IntCDP (ARMul_State * state, unsigned type, ARMword instr)
597{ 82{
598 static unsigned int finish; 83 /* Do not allow access to these register in USER mode. */
599 ARMword howlong; 84 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
600 85 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
601 howlong = ValReg[BITS (0, 3)]; 86 return ARMul_CANT;
602 87
603 switch ((int) BITS (20, 23)) { 88 /* Opcode_1should be zero. */
604 case 0: 89 if (opcode_1 != 0)
605 if (type == ARMul_FIRST) { 90 return ARMul_CANT;
606 /* First cycle of a busy wait. */ 91
607 finish = ARMul_Time (state) + howlong; 92 /* Different register have different access requirements. */
608 93 switch (reg) {
609 return howlong == 0 ? ARMul_DONE : ARMul_BUSY; 94 case 0:
610 } 95 case 1:
611 else if (type == ARMul_BUSY) { 96 /* CRm must be 0. Opcode_2 can be anything. */
612 if (ARMul_Time (state) >= finish) 97 if (CRm != 0)
613 return ARMul_DONE; 98 return ARMul_CANT;
614 else 99 break;
615 return ARMul_BUSY; 100 case 2:
616 } 101 case 3:
617 return ARMul_DONE; 102 /* CRm must be 0. Opcode_2 must be zero. */
618 103 if ((CRm != 0) || (opcode_2 != 0))
619 case 1: 104 return ARMul_CANT;
620 if (howlong == 0) 105 break;
621 ARMul_Abort (state, ARMul_FIQV); 106 case 4:
622 else 107 /* Access not allowed. */
623 ARMul_ScheduleEvent (state, howlong, DoAFIQ); 108 return ARMul_CANT;
624 return ARMul_DONE; 109 case 5:
625 110 case 6:
626 case 2: 111 /* Opcode_2 must be zero. CRm must be 0. */
627 if (howlong == 0) 112 if ((CRm != 0) || (opcode_2 != 0))
628 ARMul_Abort (state, ARMul_IRQV); 113 return ARMul_CANT;
629 else 114 break;
630 ARMul_ScheduleEvent (state, howlong, DoAIRQ); 115 case 7:
631 return ARMul_DONE; 116 /* Permissable combinations:
632 117 Opcode_2 CRm
633 case 3: 118 0 5
634 state->NfiqSig = HIGH; 119 0 6
635 return ARMul_DONE; 120 0 7
636 121 1 5
637 case 4: 122 1 6
638 state->NirqSig = HIGH; 123 1 10
639 return ARMul_DONE; 124 4 10
640 125 5 2
641 case 5: 126 6 5 */
642 ValReg[BITS (0, 3)] = ARMul_Time (state); 127 switch (opcode_2) {
643 return ARMul_DONE; 128 default:
644 } 129 return ARMul_CANT;
645 130 case 6:
646 return ARMul_CANT; 131 if (CRm != 5)
132 return ARMul_CANT;
133 break;
134 case 5:
135 if (CRm != 2)
136 return ARMul_CANT;
137 break;
138 case 4:
139 if (CRm != 10)
140 return ARMul_CANT;
141 break;
142 case 1:
143 if ((CRm != 5) && (CRm != 6) && (CRm != 10))
144 return ARMul_CANT;
145 break;
146 case 0:
147 if ((CRm < 5) || (CRm > 7))
148 return ARMul_CANT;
149 break;
150 }
151 break;
152
153 case 8:
154 /* Permissable combinations:
155 Opcode_2 CRm
156 0 5
157 0 6
158 0 7
159 1 5
160 1 6 */
161 if (opcode_2 > 1)
162 return ARMul_CANT;
163 if ((CRm < 5) || (CRm > 7))
164 return ARMul_CANT;
165 if (opcode_2 == 1 && CRm == 7)
166 return ARMul_CANT;
167 break;
168 case 9:
169 /* Opcode_2 must be zero or one. CRm must be 1 or 2. */
170 if (((CRm != 0) && (CRm != 1))
171 || ((opcode_2 != 1) && (opcode_2 != 2)))
172 return ARMul_CANT;
173 break;
174 case 10:
175 /* Opcode_2 must be zero or one. CRm must be 4 or 8. */
176 if (((CRm != 0) && (CRm != 1))
177 || ((opcode_2 != 4) && (opcode_2 != 8)))
178 return ARMul_CANT;
179 break;
180 case 11:
181 /* Access not allowed. */
182 return ARMul_CANT;
183 case 12:
184 /* Access not allowed. */
185 return ARMul_CANT;
186 case 13:
187 /* Opcode_2 must be zero. CRm must be 0. */
188 if ((CRm != 0) || (opcode_2 != 0))
189 return ARMul_CANT;
190 break;
191 case 14:
192 /* Opcode_2 must be 0. CRm must be 0, 3, 4, 8 or 9. */
193 if (opcode_2 != 0)
194 return ARMul_CANT;
195
196 if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8)
197 && (CRm != 9))
198 return ARMul_CANT;
199 break;
200 case 15:
201 /* Opcode_2 must be zero. CRm must be 1. */
202 if ((CRm != 1) || (opcode_2 != 0))
203 return ARMul_CANT;
204 break;
205 default:
206 /* Should never happen. */
207 return ARMul_CANT;
208 }
209
210 return ARMul_DONE;
647} 211}
648 212
649/* Install co-processor instruction handlers in this routine. */ 213/* Install co-processor instruction handlers in this routine. */
650 214
651unsigned 215unsigned
652ARMul_CoProInit (ARMul_State * state) 216ARMul_CoProInit(ARMul_State * state)
653{ 217{
654 unsigned int i; 218 unsigned int i;
655 219
656 /* Initialise tham all first. */ 220 /* Initialise tham all first. */
657 for (i = 0; i < 16; i++) 221 for (i = 0; i < 16; i++)
658 ARMul_CoProDetach (state, i); 222 ARMul_CoProDetach(state, i);
659 223
660 /* Install CoPro Instruction handlers here. 224 /* Install CoPro Instruction handlers here.
661 The format is: 225 The format is:
662 ARMul_CoProAttach (state, CP Number, Init routine, Exit routine 226 ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
663 LDC routine, STC routine, MRC routine, MCR routine, 227 LDC routine, STC routine, MRC routine, MCR routine,
664 CDP routine, Read Reg routine, Write Reg routine). */ 228 CDP routine, Read Reg routine, Write Reg routine). */
665 if (state->is_ep9312) { 229 if (state->is_v6) {
666 ARMul_CoProAttach (state, 4, NULL, NULL, DSPLDC4, DSPSTC4, 230 ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
667 DSPMRC4, DSPMCR4, NULL, NULL, DSPCDP4, NULL, NULL); 231 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
668 ARMul_CoProAttach (state, 5, NULL, NULL, DSPLDC5, DSPSTC5, 232 ARMul_CoProAttach(state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
669 DSPMRC5, DSPMCR5, NULL, NULL, DSPCDP5, NULL, NULL); 233 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
670 ARMul_CoProAttach (state, 6, NULL, NULL, NULL, NULL, 234
671 DSPMRC6, DSPMCR6, NULL, NULL, DSPCDP6, NULL, NULL); 235 /*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
672 } 236 MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/
673 else { 237 }
674 ARMul_CoProAttach (state, 4, NULL, NULL, ValLDC, ValSTC, 238 //chy 2003-09-03 do it in future!!!!????
675 ValMRC, ValMCR, NULL, NULL, ValCDP, NULL, NULL);
676
677 ARMul_CoProAttach (state, 5, NULL, NULL, NULL, NULL,
678 ValMRC, ValMCR, NULL, NULL, IntCDP, NULL, NULL);
679 }
680
681 if (state->is_XScale) {
682 //chy 2005-09-19, for PXA27x's CP6
683 if (state->is_pxa27x) {
684 ARMul_CoProAttach (state, 6, NULL, NULL,
685 NULL, NULL, xscale_cp6_mrc,
686 NULL, NULL, NULL, NULL, NULL, NULL);
687 }
688 //chy 2005-09-19 end-------------
689 ARMul_CoProAttach (state, 13, xscale_cp13_init,
690 xscale_cp13_exit, xscale_cp13_ldc,
691 xscale_cp13_stc, xscale_cp13_mrc,
692 xscale_cp13_mcr, NULL, NULL, xscale_cp13_cdp,
693 xscale_cp13_read_reg,
694 xscale_cp13_write_reg);
695
696 ARMul_CoProAttach (state, 14, xscale_cp14_init,
697 xscale_cp14_exit, xscale_cp14_ldc,
698 xscale_cp14_stc, xscale_cp14_mrc,
699 xscale_cp14_mcr, NULL, NULL, xscale_cp14_cdp,
700 xscale_cp14_read_reg,
701 xscale_cp14_write_reg);
702 //chy: 2003-08-24.
703 ARMul_CoProAttach (state, 15, xscale_cp15_init,
704 xscale_cp15_exit, xscale_cp15_ldc,
705 xscale_cp15_stc, xscale_cp15_mrc,
706 xscale_cp15_mcr, NULL, NULL, xscale_cp15_cdp,
707 xscale_cp15_read_reg,
708 xscale_cp15_write_reg);
709 }
710 else if (state->is_v6) {
711 ARMul_CoProAttach (state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
712 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
713 ARMul_CoProAttach (state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
714 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
715
716 ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
717 MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);
718 }
719 else { //all except xscale
720 ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
721 // MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
722 MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);
723 }
724//chy 2003-09-03 do it in future!!!!????
725#if 0 239#if 0
726 if (state->is_iWMMXt) { 240 if (state->is_iWMMXt) {
727 ARMul_CoProAttach (state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC, 241 ARMul_CoProAttach(state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC,
728 NULL, NULL, IwmmxtCDP, NULL, NULL); 242 NULL, NULL, IwmmxtCDP, NULL, NULL);
729 243
730 ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL, 244 ARMul_CoProAttach(state, 1, NULL, NULL, NULL, NULL,
731 IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL, 245 IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL,
732 NULL); 246 NULL);
733 } 247 }
734#endif 248#endif
735 //----------------------------------------------------------------------------- 249 /* No handlers below here. */
736 //chy 2004-05-25, found the user/system code visit CP 1,2, so I add below code. 250
737 ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL, 251 /* Call all the initialisation routines. */
738 ValMRC, ValMCR, NULL, NULL, NULL, NULL, NULL); 252 for (i = 0; i < 16; i++)
739 ARMul_CoProAttach (state, 2, NULL, NULL, ValLDC, ValSTC, 253 if (state->CPInit[i])
740 NULL, NULL, NULL, NULL, NULL, NULL, NULL); 254 (state->CPInit[i]) (state);
741 //------------------------------------------------------------------------------ 255
742 /* No handlers below here. */ 256 return TRUE;
743
744 /* Call all the initialisation routines. */
745 for (i = 0; i < 16; i++)
746 if (state->CPInit[i])
747 (state->CPInit[i]) (state);
748
749 return TRUE;
750} 257}
751 258
752/* Install co-processor finalisation routines in this routine. */ 259/* Install co-processor finalisation routines in this routine. */
753 260
754void 261void
755ARMul_CoProExit (ARMul_State * state) 262ARMul_CoProExit(ARMul_State * state)
756{ 263{
757 register unsigned i; 264 register unsigned i;
758 265
759 for (i = 0; i < 16; i++) 266 for (i = 0; i < 16; i++)
760 if (state->CPExit[i]) 267 if (state->CPExit[i])
761 (state->CPExit[i]) (state); 268 (state->CPExit[i]) (state);
762 269
763 for (i = 0; i < 16; i++) /* Detach all handlers. */ 270 for (i = 0; i < 16; i++) /* Detach all handlers. */
764 ARMul_CoProDetach (state, i); 271 ARMul_CoProDetach(state, i);
765} 272}
766 273
767/* Routines to hook Co-processors into ARMulator. */ 274/* Routines to hook Co-processors into ARMulator. */
768 275
769void 276void
770ARMul_CoProAttach (ARMul_State * state, 277ARMul_CoProAttach(ARMul_State * state,
771 unsigned number, 278unsigned number,
772 ARMul_CPInits * init, 279ARMul_CPInits * init,
773 ARMul_CPExits * exit, 280ARMul_CPExits * exit,
774 ARMul_LDCs * ldc, 281ARMul_LDCs * ldc,
775 ARMul_STCs * stc, 282ARMul_STCs * stc,
776 ARMul_MRCs * mrc, 283ARMul_MRCs * mrc,
777 ARMul_MCRs * mcr, 284ARMul_MCRs * mcr,
778 ARMul_MRRCs * mrrc, 285ARMul_MRRCs * mrrc,
779 ARMul_MCRRs * mcrr, 286ARMul_MCRRs * mcrr,
780 ARMul_CDPs * cdp, 287ARMul_CDPs * cdp,
781 ARMul_CPReads * read, ARMul_CPWrites * write) 288ARMul_CPReads * read, ARMul_CPWrites * write)
782{
783 if (init != NULL)
784 state->CPInit[number] = init;
785 if (exit != NULL)
786 state->CPExit[number] = exit;
787 if (ldc != NULL)
788 state->LDC[number] = ldc;
789 if (stc != NULL)
790 state->STC[number] = stc;
791 if (mrc != NULL)
792 state->MRC[number] = mrc;
793 if (mcr != NULL)
794 state->MCR[number] = mcr;
795 if (mrrc != NULL)
796 state->MRRC[number] = mrrc;
797 if (mcrr != NULL)
798 state->MCRR[number] = mcrr;
799 if (cdp != NULL)
800 state->CDP[number] = cdp;
801 if (read != NULL)
802 state->CPRead[number] = read;
803 if (write != NULL)
804 state->CPWrite[number] = write;
805}
806
807void
808ARMul_CoProDetach (ARMul_State * state, unsigned number)
809{ 289{
810 ARMul_CoProAttach (state, number, NULL, NULL, 290 if (init != NULL)
811 NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R, 291 state->CPInit[number] = init;
812 NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL); 292 if (exit != NULL)
813 293 state->CPExit[number] = exit;
814 state->CPInit[number] = NULL; 294 if (ldc != NULL)
815 state->CPExit[number] = NULL; 295 state->LDC[number] = ldc;
816 state->CPRead[number] = NULL; 296 if (stc != NULL)
817 state->CPWrite[number] = NULL; 297 state->STC[number] = stc;
298 if (mrc != NULL)
299 state->MRC[number] = mrc;
300 if (mcr != NULL)
301 state->MCR[number] = mcr;
302 if (mrrc != NULL)
303 state->MRRC[number] = mrrc;
304 if (mcrr != NULL)
305 state->MCRR[number] = mcrr;
306 if (cdp != NULL)
307 state->CDP[number] = cdp;
308 if (read != NULL)
309 state->CPRead[number] = read;
310 if (write != NULL)
311 state->CPWrite[number] = write;
818} 312}
819 313
820//chy 2003-09-03:below funs just replace the old ones
821
822/* Set the XScale FSR and FAR registers. */
823
824void 314void
825XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far) 315ARMul_CoProDetach(ARMul_State * state, unsigned number)
826{
827 //if (!state->is_XScale || (read_cp14_reg (10) & (1UL << 31)) == 0)
828 if (!state->is_XScale)
829 return;
830 //assume opcode2=0 crm =0
831 xscale_cp15_write_reg (state, 5, fsr);
832 xscale_cp15_write_reg (state, 6, _far);
833}
834
835//chy 2003-09-03 seems 0 is CANT, 1 is DONE ????
836int
837XScale_debug_moe (ARMul_State * state, int moe)
838{ 316{
839 //chy 2003-09-03 , W/R CP14 reg, now it's no use ???? 317 ARMul_CoProAttach(state, number, NULL, NULL,
840 printf ("SKYEYE: XScale_debug_moe called !!!!\n"); 318 NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
841 return 1; 319 NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL);
320
321 state->CPInit[number] = NULL;
322 state->CPExit[number] = NULL;
323 state->CPRead[number] = NULL;
324 state->CPWrite[number] = NULL;
842} 325}
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index f9130ef88..cdcf47ee1 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"
@@ -28,9 +28,6 @@
28//ichfly 28//ichfly
29//#define callstacker 1 29//#define callstacker 1
30 30
31
32//#include "armos.h"
33
34//#include "skyeye_callback.h" 31//#include "skyeye_callback.h"
35//#include "skyeye_bus.h" 32//#include "skyeye_bus.h"
36//#include "sim_control.h" 33//#include "sim_control.h"
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
deleted file mode 100644
index 242e6a83c..000000000
--- a/src/core/arm/interpreter/armmmu.cpp
+++ /dev/null
@@ -1,238 +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#include <assert.h>
22#include <string.h>
23#include "armdefs.h"
24/* two header for arm disassemble */
25//#include "skyeye_arch.h"
26#include "armcpu.h"
27
28
29extern mmu_ops_t xscale_mmu_ops;
30exception_t arm_mmu_write(short size, u32 addr, uint32_t *value);
31exception_t arm_mmu_read(short size, u32 addr, uint32_t *value);
32#define MMU_OPS (state->mmu.ops)
33ARMword skyeye_cachetype = -1;
34
35int
36mmu_init (ARMul_State * state)
37{
38 int ret;
39
40 state->mmu.control = 0x70;
41 state->mmu.translation_table_base = 0xDEADC0DE;
42 state->mmu.domain_access_control = 0xDEADC0DE;
43 state->mmu.fault_status = 0;
44 state->mmu.fault_address = 0;
45 state->mmu.process_id = 0;
46
47 switch (state->cpu->cpu_val & state->cpu->cpu_mask) {
48 //case SA1100:
49 //case SA1110:
50 // NOTICE_LOG(ARM11, "SKYEYE: use sa11xx mmu ops\n");
51 // state->mmu.ops = sa_mmu_ops;
52 // break;
53 //case PXA250:
54 //case PXA270: //xscale
55 // NOTICE_LOG(ARM11, "SKYEYE: use xscale mmu ops\n");
56 // state->mmu.ops = xscale_mmu_ops;
57 // break;
58 //case 0x41807200: //arm720t
59 //case 0x41007700: //arm7tdmi
60 //case 0x41007100: //arm7100
61 // NOTICE_LOG(ARM11, "SKYEYE: use arm7100 mmu ops\n");
62 // state->mmu.ops = arm7100_mmu_ops;
63 // break;
64 //case 0x41009200:
65 // NOTICE_LOG(ARM11, "SKYEYE: use arm920t mmu ops\n");
66 // state->mmu.ops = arm920t_mmu_ops;
67 // break;
68 //case 0x41069260:
69 // NOTICE_LOG(ARM11, "SKYEYE: use arm926ejs mmu ops\n");
70 // state->mmu.ops = arm926ejs_mmu_ops;
71 // break;
72 /* case 0x560f5810: */
73 case 0x0007b000:
74 NOTICE_LOG(ARM11, "SKYEYE: use arm11jzf-s mmu ops\n");
75 state->mmu.ops = arm1176jzf_s_mmu_ops;
76 break;
77
78 default:
79 ERROR_LOG (ARM11,
80 "SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n",
81 state->cpu->cpu_val & state->cpu->cpu_mask);
82 break;
83
84 };
85 ret = state->mmu.ops.init (state);
86 state->mmu_inited = (ret == 0);
87 /* initialize mmu_read and mmu_write for disassemble */
88 //skyeye_config_t *config = get_current_config();
89 //generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name);
90 //arch_instance->mmu_read = arm_mmu_read;
91 //arch_instance->mmu_write = arm_mmu_write;
92
93 return ret;
94}
95
96int
97mmu_reset (ARMul_State * state)
98{
99 if (state->mmu_inited)
100 mmu_exit (state);
101 return mmu_init (state);
102}
103
104void
105mmu_exit (ARMul_State * state)
106{
107 MMU_OPS.exit (state);
108 state->mmu_inited = 0;
109}
110
111fault_t
112mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data)
113{
114 return MMU_OPS.read_byte (state, virt_addr, data);
115};
116
117fault_t
118mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data)
119{
120 return MMU_OPS.read_halfword (state, virt_addr, data);
121};
122
123fault_t
124mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data)
125{
126 return MMU_OPS.read_word (state, virt_addr, data);
127};
128
129fault_t
130mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data)
131{
132 fault_t fault;
133 //static int count = 0;
134 //count ++;
135 fault = MMU_OPS.write_byte (state, virt_addr, data);
136 return fault;
137}
138
139fault_t
140mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data)
141{
142 fault_t fault;
143 //static int count = 0;
144 //count ++;
145 fault = MMU_OPS.write_halfword (state, virt_addr, data);
146 return fault;
147}
148
149fault_t
150mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data)
151{
152 fault_t fault;
153 fault = MMU_OPS.write_word (state, virt_addr, data);
154
155 /*used for debug for MMU*
156
157 if (!fault){
158 ARMword tmp;
159
160 if (mmu_read_word(state, virt_addr, &tmp)){
161 err_msg("load back\n");
162 exit(-1);
163 }else{
164 if (tmp != data){
165 err_msg("load back not equal %d %x\n", count, virt_addr);
166 }
167 }
168 }
169 */
170
171 return fault;
172};
173
174fault_t
175mmu_load_instr (ARMul_State * state, ARMword virt_addr, ARMword * instr)
176{
177 return MMU_OPS.load_instr (state, virt_addr, instr);
178}
179
180ARMword
181mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
182{
183 return MMU_OPS.mrc (state, instr, value);
184}
185
186void
187mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
188{
189 MMU_OPS.mcr (state, instr, value);
190}
191
192/*ywc 20050416*/
193int
194mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr)
195{
196 return (MMU_OPS.v2p_dbct (state, virt_addr, phys_addr));
197}
198
199//
200//
201///* dis_mmu_read for disassemble */
202//exception_t arm_mmu_read(short size, uint32_t addr, uint32_t * value)
203//{
204// ARMul_State *state;
205// ARM_CPU_State *cpu = get_current_cpu();
206// state = &cpu->core[0];
207// switch(size){
208// case 8:
209// MMU_OPS.read_byte (state, addr, value);
210// break;
211// case 16:
212// case 32:
213// break;
214// default:
215// ERROR_LOG(ARM11, "Error size %d", size);
216// break;
217// }
218// return No_exp;
219//}
220///* dis_mmu_write for disassemble */
221//exception_t arm_mmu_write(short size, uint32_t addr, uint32_t *value)
222//{
223// ARMul_State *state;
224// ARM_CPU_State *cpu = get_current_cpu();
225// state = &cpu->core[0];
226// switch(size){
227// case 8:
228// MMU_OPS.write_byte (state, addr, value);
229// break;
230// case 16:
231// case 32:
232// break;
233// default:
234// printf("In %s error size %d Line %d\n", __func__, size, __LINE__);
235// break;
236// }
237// return No_exp;
238//}
diff --git a/src/core/arm/interpreter/armos.cpp b/src/core/arm/interpreter/armos.cpp
deleted file mode 100644
index 43484ee5f..000000000
--- a/src/core/arm/interpreter/armos.cpp
+++ /dev/null
@@ -1,742 +0,0 @@
1/* armos.c -- ARMulator OS interface: 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/* This file contains a model of Demon, ARM Ltd's Debug Monitor,
19including all the SWI's required to support the C library. The code in
20it is not really for the faint-hearted (especially the abort handling
21code), but it is a complete example. Defining NOOS will disable all the
22fun, and definign VAILDATE will define SWI 1 to enter SVC mode, and SWI
230x11 to halt the emulator. */
24
25//chy 2005-09-12 disable below line
26//#include "config.h"
27
28#include <time.h>
29#include <errno.h>
30#include <string.h>
31#include "skyeye_defs.h"
32#ifndef __USE_LARGEFILE64
33#define __USE_LARGEFILE64 /* When use 64 bit large file need define it! for stat64*/
34#endif
35#include <fcntl.h>
36#include <sys/stat.h>
37
38
39#ifndef O_RDONLY
40#define O_RDONLY 0
41#endif
42#ifndef O_WRONLY
43#define O_WRONLY 1
44#endif
45#ifndef O_RDWR
46#define O_RDWR 2
47#endif
48#ifndef O_BINARY
49#define O_BINARY 0
50#endif
51
52#ifdef __STDC__
53#define unlink(s) remove(s)
54#endif
55
56#ifdef HAVE_UNISTD_H
57#include <unistd.h> /* For SEEK_SET etc */
58#endif
59
60#ifdef __riscos
61extern int _fisatty (FILE *);
62#define isatty_(f) _fisatty(f)
63#else
64#ifdef __ZTC__
65#include <io.h>
66#define isatty_(f) isatty((f)->_file)
67#else
68#ifdef macintosh
69#include <ioctl.h>
70#define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
71#else
72#define isatty_(f) isatty (fileno (f))
73#endif
74#endif
75#endif
76
77#include "armdefs.h"
78#include "armos.h"
79#include "armemu.h"
80
81#ifndef NOOS
82#ifndef VALIDATE
83/* #ifndef ASIM */
84//chy 2005-09-12 disable below line
85//#include "armfpe.h"
86/* #endif */
87#endif
88#endif
89
90#define DUMP_SYSCALL 0
91#define dump(...) do { if (DUMP_SYSCALL) printf(__VA_ARGS__); } while(0)
92//#define debug(...) printf(__VA_ARGS__);
93#define debug(...) ;
94
95extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number);
96
97#ifndef FOPEN_MAX
98#define FOPEN_MAX 64
99#endif
100
101/***************************************************************************\
102* OS private Information *
103\***************************************************************************/
104
105unsigned arm_dyncom_SWI(ARMul_State * state, ARMword number)
106{
107 return ARMul_OSHandleSWI(state, number);
108}
109
110//mmap_area_t *mmap_global = NULL;
111
112static int translate_open_mode[] = {
113 O_RDONLY, /* "r" */
114 O_RDONLY + O_BINARY, /* "rb" */
115 O_RDWR, /* "r+" */
116 O_RDWR + O_BINARY, /* "r+b" */
117 O_WRONLY + O_CREAT + O_TRUNC, /* "w" */
118 O_WRONLY + O_BINARY + O_CREAT + O_TRUNC, /* "wb" */
119 O_RDWR + O_CREAT + O_TRUNC, /* "w+" */
120 O_RDWR + O_BINARY + O_CREAT + O_TRUNC, /* "w+b" */
121 O_WRONLY + O_APPEND + O_CREAT, /* "a" */
122 O_WRONLY + O_BINARY + O_APPEND + O_CREAT, /* "ab" */
123 O_RDWR + O_APPEND + O_CREAT, /* "a+" */
124 O_RDWR + O_BINARY + O_APPEND + O_CREAT /* "a+b" */
125};
126//
127//static void
128//SWIWrite0 (ARMul_State * state, ARMword addr)
129//{
130// ARMword temp;
131//
132// //while ((temp = ARMul_ReadByte (state, addr++)) != 0)
133// while(1){
134// mem_read(8, addr++, &temp);
135// if(temp != 0)
136// (void) fputc ((char) temp, stdout);
137// else
138// break;
139// }
140//}
141//
142//static void
143//WriteCommandLineTo (ARMul_State * state, ARMword addr)
144//{
145// ARMword temp;
146// char *cptr = state->CommandLine;
147// if (cptr == NULL)
148// cptr = "\0";
149// do {
150// temp = (ARMword) * cptr++;
151// //ARMul_WriteByte (state, addr++, temp);
152// mem_write(8, addr++, temp);
153// }
154// while (temp != 0);
155//}
156//
157//static void
158//SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
159//{
160// char dummy[2000];
161// int flags;
162// int i;
163//
164// for (i = 0; (dummy[i] = ARMul_ReadByte (state, name + i)); i++);
165// assert(SWIflags< (sizeof(translate_open_mode)/ sizeof(translate_open_mode[0])));
166// /* Now we need to decode the Demon open mode */
167// flags = translate_open_mode[SWIflags];
168// flags = SWIflags;
169//
170// /* Filename ":tt" is special: it denotes stdin/out */
171// if (strcmp (dummy, ":tt") == 0) {
172// if (flags == O_RDONLY) /* opening tty "r" */
173// state->Reg[0] = 0; /* stdin */
174// else
175// state->Reg[0] = 1; /* stdout */
176// }
177// else {
178// state->Reg[0] = (int) open (dummy, flags, 0666);
179// }
180//}
181//
182//static void
183//SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
184//{
185// int res;
186// int i;
187// char *local = (char*) malloc (len);
188//
189// if (local == NULL) {
190// fprintf (stderr,
191// "sim: Unable to read 0x%ulx bytes - out of memory\n",
192// len);
193// return;
194// }
195//
196// res = read (f, local, len);
197// if (res > 0)
198// for (i = 0; i < res; i++)
199// //ARMul_WriteByte (state, ptr + i, local[i]);
200// mem_write(8, ptr + i, local[i]);
201// free (local);
202// //state->Reg[0] = res == -1 ? -1 : len - res;
203// state->Reg[0] = res;
204//}
205//
206//static void
207//SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
208//{
209// int res;
210// ARMword i;
211// char *local = malloc (len);
212//
213// if (local == NULL) {
214// fprintf (stderr,
215// "sim: Unable to write 0x%lx bytes - out of memory\n",
216// (long unsigned int) len);
217// return;
218// }
219//
220// for (i = 0; i < len; i++){
221// //local[i] = ARMul_ReadByte (state, ptr + i);
222// ARMword data;
223// mem_read(8, ptr + i, &data);
224// local[i] = data & 0xFF;
225// }
226//
227// res = write (f, local, len);
228// //state->Reg[0] = res == -1 ? -1 : len - res;
229// state->Reg[0] = res;
230// free (local);
231//}
232
233//static void
234//SWIflen (ARMul_State * state, ARMword fh)
235//{
236// ARMword addr;
237//
238// if (fh == 0 || fh > FOPEN_MAX) {
239// state->Reg[0] = -1L;
240// return;
241// }
242//
243// addr = lseek (fh, 0, SEEK_CUR);
244//
245// state->Reg[0] = lseek (fh, 0L, SEEK_END);
246// (void) lseek (fh, addr, SEEK_SET);
247//
248//}
249
250/***************************************************************************\
251* The emulator calls this routine when a SWI instruction is encuntered. The *
252* parameter passed is the SWI number (lower 24 bits of the instruction). *
253\***************************************************************************/
254/* ahe-ykl information is retrieved from elf header and the starting value of
255 brk_static is in sky_info_t */
256
257/* brk static hold the value of brk */
258static uint32_t brk_static = -1;
259
260unsigned
261ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
262{
263 number &= 0xfffff;
264 ARMword addr, temp;
265
266 switch (number) {
267// case SWI_Syscall:
268// if (state->Reg[7] != 0)
269// return ARMul_OSHandleSWI(state, state->Reg[7]);
270// else
271// return FALSE;
272// case SWI_Read:
273// SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
274// return TRUE;
275//
276// case SWI_GetUID32:
277// state->Reg[0] = getuid();
278// return TRUE;
279//
280// case SWI_GetGID32:
281// state->Reg[0] = getgid();
282// return TRUE;
283//
284// case SWI_GetEUID32:
285// state->Reg[0] = geteuid();
286// return TRUE;
287//
288// case SWI_GetEGID32:
289// state->Reg[0] = getegid();
290// return TRUE;
291//
292// case SWI_Write:
293// SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
294// return TRUE;
295//
296// case SWI_Open:
297// SWIopen (state, state->Reg[0], state->Reg[1]);
298// return TRUE;
299//
300// case SWI_Close:
301// state->Reg[0] = close (state->Reg[0]);
302// return TRUE;
303//
304// case SWI_Seek:{
305// /* We must return non-zero for failure */
306// state->Reg[0] =
307// lseek (state->Reg[0], state->Reg[1],
308// SEEK_SET);
309// return TRUE;
310// }
311//
312// case SWI_ExitGroup:
313// case SWI_Exit:
314// {
315// struct timeval tv;
316// //gettimeofday(&tv,NULL);
317// //printf("In %s, %d sec, %d usec\n", __FUNCTION__, tv.tv_sec, tv.tv_usec);
318// printf("passed %d sec, %lld usec\n", get_clock_sec(), get_clock_us());
319//
320// /* quit here */
321// run_command("quit");
322// return TRUE;
323// }
324// case SWI_Times:{
325// uint32_t dest = state->Reg[0];
326// struct tms now;
327// struct target_tms32 nowret;
328//
329// uint32_t ret = times(&now);
330//
331// if (ret == -1){
332// debug("syscall %s error %d\n", "SWI_Times", ret);
333// state->Reg[0] = ret;
334// return FALSE;
335// }
336//
337// nowret.tms_cstime = now.tms_cstime;
338// nowret.tms_cutime = now.tms_cutime;
339// nowret.tms_stime = now.tms_stime;
340// nowret.tms_utime = now.tms_utime;
341//
342// uint32_t offset;
343// for (offset = 0; offset < sizeof(nowret); offset++) {
344// bus_write(8, dest + offset, *((uint8_t *) &nowret + offset));
345// }
346//
347// state->Reg[0] = ret;
348// return TRUE;
349// }
350//
351// case SWI_Gettimeofday: {
352// uint32_t dest1 = state->Reg[0];
353// uint32_t dest2 = state->Reg[1]; // Unsure of this
354// struct timeval val;
355// struct timezone zone;
356// struct target_timeval32 valret;
357// struct target_timezone32 zoneret;
358//
359// uint32_t ret = gettimeofday(&val, &zone);
360// valret.tv_sec = val.tv_sec;
361// valret.tv_usec = val.tv_usec;
362// zoneret.tz_dsttime = zoneret.tz_dsttime;
363// zoneret.tz_minuteswest = zoneret.tz_minuteswest;
364//
365// if (ret == -1){
366// debug("syscall %s error %d\n", "SWI_Gettimeofday", ret);
367// state->Reg[0] = ret;
368// return FALSE;
369// }
370//
371// uint32_t offset;
372// if (dest1) {
373// for (offset = 0; offset < sizeof(valret); offset++) {
374// bus_write(8, dest1 + offset, *((uint8_t *) &valret + offset));
375// }
376// state->Reg[0] = ret;
377// }
378// if (dest2) {
379// for (offset = 0; offset < sizeof(zoneret); offset++) {
380// bus_write(8, dest2 + offset, *((uint8_t *) &zoneret + offset));
381// }
382// state->Reg[0] = ret;
383// }
384//
385// return TRUE;
386// }
387// case SWI_Brk:
388// /* initialize brk value */
389// /* suppose that brk_static doesn't reach 0xffffffff... */
390// if (brk_static == -1) {
391// brk_static = (get_skyeye_pref()->info).brk;
392// }
393//
394// /* FIXME there might be a need to do a mmap */
395//
396// if(state->Reg[0]){
397// if (get_skyeye_exec_info()->mmap_access) {
398// /* if new brk is greater than current brk, allocate memory */
399// if (state->Reg[0] > brk_static) {
400// uint32_t ret = mmap( (void *) brk_static, state->Reg[0] - brk_static,
401// PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0 );
402// if (ret != MAP_FAILED)
403// brk_static = ret;
404// }
405// }
406// brk_static = state->Reg[0];
407// //state->Reg[0] = 0; /* FIXME return value of brk set to be the address on success */
408// } else {
409// state->Reg[0] = brk_static;
410// }
411// return TRUE;
412//
413// case SWI_Break:
414// state->Emulate = FALSE;
415// return TRUE;
416//
417// case SWI_Mmap:{
418// int addr = state->Reg[0];
419// int len = state->Reg[1];
420// int prot = state->Reg[2];
421// int flag = state->Reg[3];
422// int fd = state->Reg[4];
423// int offset = state->Reg[5];
424// mmap_area_t *area = new_mmap_area(addr, len);
425// state->Reg[0] = area->bank.addr;
426// //printf("syscall %d mmap(0x%x,%x,0x%x,0x%x,%d,0x%x) = 0x%x\n",\
427// SWI_Mmap, addr, len, prot, flag, fd, offset, state->Reg[0]);
428// return TRUE;
429// }
430//
431// case SWI_Munmap:
432// state->Reg[0] = 0;
433// return TRUE;
434//
435// case SWI_Mmap2:{
436// int addr = state->Reg[0];
437// int len = state->Reg[1];
438// int prot = state->Reg[2];
439// int flag = state->Reg[3];
440// int fd = state->Reg[4];
441// int offset = state->Reg[5] * 4096; /* page offset */
442// mmap_area_t *area = new_mmap_area(addr, len);
443// state->Reg[0] = area->bank.addr;
444//
445// return TRUE;
446// }
447//
448// case SWI_Breakpoint:
449// //chy 2005-09-12 change below line
450// //state->EndCondition = RDIError_BreakpointReached;
451// //printf ("SKYEYE: in armos.c : should not come here!!!!\n");
452// state->EndCondition = 0;
453// /*modified by ksh to support breakpoiont*/
454// state->Emulate = STOP;
455// return (TRUE);
456// case SWI_Uname:
457// {
458// struct utsname *uts = (uintptr_t) state->Reg[0]; /* uname should write data in this address */
459// struct utsname utsbuf;
460// //printf("Uname size is %x\n", sizeof(utsbuf));
461// char *buf;
462// uintptr_t sp ; /* used as a temporary address */
463//
464//#define COPY_UTS_STRING(addr) \
465// buf = addr; \
466// while(*buf != NULL) { \
467// bus_write(8, sp, *buf); \
468// sp++; \
469// buf++; \
470// }
471//#define COPY_UTS(field) /*printf("%s: %s at %p\n", #field, utsbuf.field, uts->field);*/ \
472// sp = (uintptr_t) uts->field; \
473// COPY_UTS_STRING((&utsbuf)->field);
474//
475// if (uname(&utsbuf) < 0) {
476// printf("syscall uname: utsname error\n");
477// state->Reg[0] = -1;
478// return FALSE;
479// }
480//
481// /* FIXME for now, this is just the host system call
482// Some data should be missing, as it depends on
483// the version of utsname */
484// COPY_UTS(sysname);
485// COPY_UTS(nodename);
486// COPY_UTS(release);
487// COPY_UTS(version);
488// COPY_UTS(machine);
489//
490// state->Reg[0] = 0;
491// return TRUE;
492// }
493// case SWI_Fcntl:
494// {
495// uint32_t fd = state->Reg[0];
496// uint32_t cmd = state->Reg[1];
497// uint32_t arg = state->Reg[2];
498// uint32_t ret;
499//
500// switch(cmd){
501// case (F_GETFD):
502// {
503// ret = fcntl(fd, cmd, arg);
504// //printf("syscall fcntl for getfd not implemented, ret %d\n", ret);
505// state->Reg[0] = ret;
506// return FALSE;
507// }
508// default:
509// break;
510// }
511//
512// printf("syscall fcntl unimplemented fd %x cmd %x\n", fd, cmd);
513// state->Reg[0] = -1;
514// return FALSE;
515//
516// }
517// case SWI_Fstat64:
518// {
519// uint32_t dest = state->Reg[1];
520// uint32_t fd = state->Reg[0];
521// struct stat64 statbuf;
522// struct target_stat64 statret;
523// memset(&statret, 0, sizeof(struct target_stat64));
524// uint32_t ret = fstat64(fd, &statbuf);
525//
526// if (ret == -1){
527// printf("syscall %s returned error\n", "SWI_Fstat");
528// state->Reg[0] = ret;
529// return FALSE;
530// }
531//
532// /* copy statbuf to the process memory space
533// FIXME can't say if endian has an effect here */
534// uint32_t offset;
535// //printf("Fstat system is size %x\n", sizeof(statbuf));
536// //printf("Fstat target is size %x\n", sizeof(statret));
537//
538// /* we copy system structure data stat64 into arm fixed size structure target_stat64 */
539// statret.st_dev = statbuf.st_dev;
540// statret.st_ino = statbuf.st_ino;
541// statret.st_mode = statbuf.st_mode;
542// statret.st_nlink = statbuf.st_nlink;
543// statret.st_uid = statbuf.st_uid;
544// statret.st_gid = statbuf.st_gid;
545// statret.st_rdev = statbuf.st_rdev;
546// statret.st_size = statbuf.st_size;
547// statret.st_blksize = statbuf.st_blksize;
548// statret.st_blocks = statbuf.st_blocks;
549// statret.st32_atime = statbuf.st_atime;
550// statret.st32_mtime = statbuf.st_mtime;
551// statret.st32_ctime = statbuf.st_ctime;
552//
553// for (offset = 0; offset < sizeof(statret); offset++) {
554// bus_write(8, dest + offset, *((uint8_t *) &statret + offset));
555// }
556//
557// state->Reg[0] = ret;
558// return TRUE;
559// }
560// case SWI_Set_tls:
561// {
562// //printf("syscall set_tls unimplemented\n");
563// state->mmu.thread_uro_id = state->Reg[0];
564// state->CP15[CP15_THREAD_URO - CP15_BASE] = state->Reg[0];
565// state->Reg[0] = 0;
566// return FALSE;
567// }
568//#if 0
569// case SWI_Clock:
570// /* return number of centi-seconds... */
571// state->Reg[0] =
572//#ifdef CLOCKS_PER_SEC
573// (CLOCKS_PER_SEC >= 100)
574// ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
575// : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
576//#else
577// /* presume unix... clock() returns microseconds */
578// (ARMword) (clock () / 10000);
579//#endif
580// return (TRUE);
581//
582// case SWI_Time:
583// state->Reg[0] = (ARMword) time (NULL);
584// return (TRUE);
585// case SWI_Flen:
586// SWIflen (state, state->Reg[0]);
587// return (TRUE);
588//
589//#endif
590 default:
591
592 _dbg_assert_msg_(ARM11, false, "ImplementMe: ARMul_OSHandleSWI!");
593
594 return (FALSE);
595 }
596}
597//
598///**
599// * @brief For mmap syscall.A mmap_area is a memory bank. Get from ppc.
600// */
601//static mmap_area_t* new_mmap_area(int sim_addr, int len){
602// mmap_area_t *area = (mmap_area_t *)malloc(sizeof(mmap_area_t));
603// if(area == NULL){
604// printf("error, failed %s\n",__FUNCTION__);
605// exit(0);
606// }
607//#if FAST_MEMORY
608// if (mmap_next_base == -1)
609// {
610// mmap_next_base = get_skyeye_exec_info()->brk;
611// }
612//#endif
613//
614// memset(area, 0x0, sizeof(mmap_area_t));
615// area->bank.addr = mmap_next_base;
616// area->bank.len = len;
617// area->bank.bank_write = mmap_mem_write;
618// area->bank.bank_read = mmap_mem_read;
619// area->bank.type = MEMTYPE_RAM;
620// area->bank.objname = "mmap";
621// addr_mapping(&area->bank);
622//
623//#if FAST_MEMORY
624// if (get_skyeye_exec_info()->mmap_access)
625// {
626// /* FIXME check proper flags */
627// /* FIXME we may delete the need of banks up there */
628// uint32_t ret = mmap(mmap_next_base, len, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
629// mmap_next_base = ret;
630// }
631// area->mmap_addr = (uint8_t*)get_dma_addr(mmap_next_base);
632//#else
633// area->mmap_addr = malloc(len);
634// if(area->mmap_addr == NULL){
635// printf("error mmap malloc\n");
636// exit(0);
637// }
638// memset(area->mmap_addr, 0x0, len);
639//#endif
640//
641// area->next = NULL;
642// if(mmap_global){
643// area->next = mmap_global->next;
644// mmap_global->next = area;
645// }else{
646// mmap_global = area;
647// }
648// mmap_next_base = mmap_next_base + len;
649// return area;
650//}
651//
652//static mmap_area_t *get_mmap_area(int addr){
653// mmap_area_t *tmp = mmap_global;
654// while(tmp){
655// if ((tmp->bank.addr <= addr) && (tmp->bank.addr + tmp->bank.len > addr)){
656// return tmp;
657// }
658// tmp = tmp->next;
659// }
660// printf("cannot get mmap area:addr=0x%x\n", addr);
661// return NULL;
662//}
663//
664///**
665// * @brief the mmap_area bank write function. Get from ppc.
666// *
667// * @param size size to write, 8/16/32
668// * @param addr address to write
669// * @param value value to write
670// *
671// * @return sucess return 1,otherwise 0.
672// */
673//static char mmap_mem_write(short size, int addr, uint32_t value){
674// mmap_area_t *area_tmp = get_mmap_area(addr);
675// mem_bank_t *bank_tmp = &area_tmp->bank;
676// int offset = addr - bank_tmp->addr;
677// switch(size){
678// case 8:{
679// //uint8_t value_endian = value;
680// uint8_t value_endian = (uint8_t)value;
681// *(uint8_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
682// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
683// break;
684// }
685// case 16:{
686// //uint16_t value_endian = half_to_BE((uint16_t)value);
687// uint16_t value_endian = ((uint16_t)value);
688// *(uint16_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
689// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
690// break;
691// }
692// case 32:{
693// //uint32_t value_endian = word_to_BE((uint32_t)value);
694// uint32_t value_endian = ((uint32_t)value);
695// *(uint32_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
696// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
697// break;
698// }
699// default:
700// printf("invalid size %d\n",size);
701// return 0;
702// }
703// return 1;
704//}
705//
706///**
707// * @brief the mmap_area bank read function. Get from ppc.
708// *
709// * @param size size to read, 8/16/32
710// * @param addr address to read
711// * @param value value to read
712// *
713// * @return sucess return 1,otherwise 0.
714// */
715//static char mmap_mem_read(short size, int addr, uint32_t * value){
716// mmap_area_t *area_tmp = get_mmap_area(addr);
717// mem_bank_t *bank_tmp = &area_tmp->bank;
718// int offset = addr - bank_tmp->addr;
719// switch(size){
720// case 8:{
721// //*(uint8_t *)value = *(uint8_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]);
722// *value = *(uint8_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]);
723// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint32_t*)value);
724// break;
725// }
726// case 16:{
727// //*(uint16_t *)value = half_from_BE(*(uint16_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
728// *value = (*(uint16_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
729// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint16_t*)value);
730// break;
731// }
732// case 32:
733// //*value = (uint32_t)word_from_BE(*(uint32_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
734// *value = (uint32_t)(*(uint32_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
735// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint32_t*)value);
736// break;
737// default:
738// printf("invalid size %d\n",size);
739// return 0;
740// }
741// return 1;
742//}
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 3d3545c65..2568b93ef 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -15,18 +15,11 @@
15 along with this program; if not, write to the Free Software 15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17 17
18//#include <util.h> 18#include "core/arm/skyeye_common/armdefs.h"
19 19#include "core/arm/skyeye_common/armemu.h"
20#include <string>
21#include "core/arm/interpreter/armdefs.h"
22#include "core/arm/interpreter/armemu.h"
23#include "core/hle/coprocessor.h"
24#include "core/arm/disassembler/arm_disasm.h" 20#include "core/arm/disassembler/arm_disasm.h"
21#include "core/mem_map.h"
25 22
26//#include "ansidecl.h"
27//#include "skyeye.h"
28//extern int skyeye_instr_debug;
29/* Definitions for the support routines. */
30 23
31static ARMword ModeToBank (ARMword); 24static ARMword ModeToBank (ARMword);
32static void EnvokeList (ARMul_State *, unsigned int, unsigned int); 25static void EnvokeList (ARMul_State *, unsigned int, unsigned int);
@@ -751,7 +744,7 @@ ARMword ARMul_MRC (ARMul_State * state, ARMword instr)
751 int cpopc = BITS(21, 23) & 0x7; 744 int cpopc = BITS(21, 23) & 0x7;
752 745
753 if (cn == 13 && cm == 0 && cp == 3) { //c13,c0,3; returns CPU svc buffer 746 if (cn == 13 && cm == 0 && cp == 3) { //c13,c0,3; returns CPU svc buffer
754 ARMword result = HLE::CallMRC(instr); 747 ARMword result = Memory::KERNEL_MEMORY_VADDR;
755 748
756 if (result != -1) { 749 if (result != -1) {
757 return result; 750 return result;
diff --git a/src/core/arm/interpreter/armvirt.cpp b/src/core/arm/interpreter/armvirt.cpp
index a072b73be..7845d1042 100644
--- a/src/core/arm/interpreter/armvirt.cpp
+++ b/src/core/arm/interpreter/armvirt.cpp
@@ -23,658 +23,143 @@ 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/armemu.h"
28//#include "code_cov.h"
29 28
30#ifdef VALIDATE /* for running the validate suite */ 29#include "core/mem_map.h"
31#define TUBE 48 * 1024 * 1024 /* write a char on the screen */
32#define ABORTS 1
33#endif
34
35/* #define ABORTS */
36
37#ifdef ABORTS /* the memory system will abort */
38/* For the old test suite Abort between 32 Kbytes and 32 Mbytes
39 For the new test suite Abort between 8 Mbytes and 26 Mbytes */
40/* #define LOWABORT 32 * 1024
41#define HIGHABORT 32 * 1024 * 1024 */
42#define LOWABORT 8 * 1024 * 1024
43#define HIGHABORT 26 * 1024 * 1024
44
45#endif
46
47#define NUMPAGES 64 * 1024
48#define PAGESIZE 64 * 1024
49#define PAGEBITS 16
50#define OFFSETBITS 0xffff
51//chy 2003-08-19: seems no use ????
52int SWI_vector_installed = FALSE;
53extern ARMword skyeye_cachetype;
54
55/***************************************************************************\
56* Get a byte into Virtual Memory, maybe allocating the page *
57\***************************************************************************/
58static fault_t
59GetByte (ARMul_State * state, ARMword address, ARMword * data)
60{
61 fault_t fault;
62
63 fault = mmu_read_byte (state, address, data);
64 if (fault) {
65//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
66// printf("SKYEYE: GetByte fault %d \n", fault);
67 }
68 return fault;
69}
70
71/***************************************************************************\
72* Get a halfword into Virtual Memory, maybe allocating the page *
73\***************************************************************************/
74static fault_t
75GetHalfWord (ARMul_State * state, ARMword address, ARMword * data)
76{
77 fault_t fault;
78
79 fault = mmu_read_halfword (state, address, data);
80 if (fault) {
81//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
82// printf("SKYEYE: GetHalfWord fault %d \n", fault);
83 }
84 return fault;
85}
86
87/***************************************************************************\
88* Get a Word from Virtual Memory, maybe allocating the page *
89\***************************************************************************/
90 30
91static fault_t 31#define dumpstack 1
92GetWord (ARMul_State * state, ARMword address, ARMword * data) 32#define dumpstacksize 0x10
93{ 33#define maxdmupaddr 0x0033a850
94 fault_t fault;
95 34
96 fault = mmu_read_word (state, address, data); 35/*ARMword ARMul_GetCPSR (ARMul_State * state) {
97 if (fault) { 36return 0;
98//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
99#if 0
100/* XXX */ extern int hack;
101 hack = 1;
102#endif
103#if 0
104 printf ("mmu_read_word at 0x%08x: ", address);
105 switch (fault) {
106 case ALIGNMENT_FAULT:
107 printf ("ALIGNMENT_FAULT");
108 break;
109 case SECTION_TRANSLATION_FAULT:
110 printf ("SECTION_TRANSLATION_FAULT");
111 break;
112 case PAGE_TRANSLATION_FAULT:
113 printf ("PAGE_TRANSLATION_FAULT");
114 break;
115 case SECTION_DOMAIN_FAULT:
116 printf ("SECTION_DOMAIN_FAULT");
117 break;
118 case SECTION_PERMISSION_FAULT:
119 printf ("SECTION_PERMISSION_FAULT");
120 break;
121 case SUBPAGE_PERMISSION_FAULT:
122 printf ("SUBPAGE_PERMISSION_FAULT");
123 break;
124 default:
125 printf ("Unrecognized fault number!");
126 }
127 printf ("\tpc = 0x%08x\n", state->Reg[15]);
128#endif
129 }
130 return fault;
131} 37}
132 38ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode) {
133//2003-07-10 chy: lyh change 39return 0;
134/****************************************************************************\
135 * Load a Instrion Word into Virtual Memory *
136\****************************************************************************/
137static fault_t
138LoadInstr (ARMul_State * state, ARMword address, ARMword * instr)
139{
140 fault_t fault;
141 fault = mmu_load_instr (state, address, instr);
142 return fault;
143 //if (fault)
144 // log_msg("load_instr fault = %d, address = %x\n", fault, address);
145} 40}
41void ARMul_SetCPSR (ARMul_State * state, ARMword value) {
146 42
147/***************************************************************************\
148* Put a byte into Virtual Memory, maybe allocating the page *
149\***************************************************************************/
150static fault_t
151PutByte (ARMul_State * state, ARMword address, ARMword data)
152{
153 fault_t fault;
154
155 fault = mmu_write_byte (state, address, data);
156 if (fault) {
157//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
158// printf("SKYEYE: PutByte fault %d \n", fault);
159 }
160 return fault;
161} 43}
44void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) {
162 45
163/***************************************************************************\ 46}*/
164* Put a halfword into Virtual Memory, maybe allocating the page *
165\***************************************************************************/
166static fault_t
167PutHalfWord (ARMul_State * state, ARMword address, ARMword data)
168{
169 fault_t fault;
170 47
171 fault = mmu_write_halfword (state, address, data); 48void ARMul_Icycles(ARMul_State * state, unsigned number, ARMword address) {
172 if (fault) {
173//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
174// printf("SKYEYE: PutHalfWord fault %d \n", fault);
175 }
176 return fault;
177} 49}
178 50
179/***************************************************************************\ 51void ARMul_Ccycles(ARMul_State * state, unsigned number, ARMword address) {
180* Put a Word into Virtual Memory, maybe allocating the page *
181\***************************************************************************/
182
183static fault_t
184PutWord (ARMul_State * state, ARMword address, ARMword data)
185{
186 fault_t fault;
187
188 fault = mmu_write_word (state, address, data);
189 if (fault) {
190//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
191#if 0
192/* XXX */ extern int hack;
193 hack = 1;
194#endif
195#if 0
196 printf ("mmu_write_word at 0x%08x: ", address);
197 switch (fault) {
198 case ALIGNMENT_FAULT:
199 printf ("ALIGNMENT_FAULT");
200 break;
201 case SECTION_TRANSLATION_FAULT:
202 printf ("SECTION_TRANSLATION_FAULT");
203 break;
204 case PAGE_TRANSLATION_FAULT:
205 printf ("PAGE_TRANSLATION_FAULT");
206 break;
207 case SECTION_DOMAIN_FAULT:
208 printf ("SECTION_DOMAIN_FAULT");
209 break;
210 case SECTION_PERMISSION_FAULT:
211 printf ("SECTION_PERMISSION_FAULT");
212 break;
213 case SUBPAGE_PERMISSION_FAULT:
214 printf ("SUBPAGE_PERMISSION_FAULT");
215 break;
216 default:
217 printf ("Unrecognized fault number!");
218 }
219 printf ("\tpc = 0x%08x\n", state->Reg[15]);
220#endif
221 }
222 return fault;
223} 52}
224 53
225/***************************************************************************\ 54ARMword ARMul_LoadInstrS(ARMul_State * state, ARMword address, ARMword isize) {
226* Initialise the memory interface * 55 state->NumScycles++;
227\***************************************************************************/
228
229unsigned
230ARMul_MemoryInit (ARMul_State * state, unsigned int initmemsize)
231{
232 return TRUE;
233}
234
235/***************************************************************************\
236* Remove the memory interface *
237\***************************************************************************/
238
239void
240ARMul_MemoryExit (ARMul_State * state)
241{
242}
243
244/***************************************************************************\
245* ReLoad Instruction *
246\***************************************************************************/
247
248ARMword
249ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize)
250{
251 ARMword data;
252 fault_t fault;
253
254#ifdef ABORTS
255 if (address >= LOWABORT && address < HIGHABORT) {
256 ARMul_PREFETCHABORT (address);
257 return ARMul_ABORTWORD;
258 }
259 else {
260 ARMul_CLEARABORT;
261 }
262#endif
263#if 0
264 /* do profiling for code coverage */
265 if (skyeye_config.code_cov.prof_on)
266 cov_prof(EXEC_FLAG, address);
267#endif
268#if 1
269 if ((isize == 2) && (address & 0x2)) {
270 ARMword lo, hi;
271 if (!(skyeye_cachetype == INSTCACHE))
272 fault = GetHalfWord (state, address, &lo);
273 else
274 fault = LoadInstr (state, address, &lo);
275#if 0
276 if (!fault) {
277 if (!(skyeye_cachetype == INSTCACHE))
278 fault = GetHalfWord (state, address + isize, &hi);
279 else
280 fault = LoadInstr (state, address + isize, &hi);
281
282 }
283#endif
284 if (fault) {
285 ARMul_PREFETCHABORT (address);
286 return ARMul_ABORTWORD;
287 }
288 else {
289 ARMul_CLEARABORT;
290 }
291 return lo;
292#if 0
293 if (state->bigendSig == HIGH)
294 return (lo << 16) | (hi >> 16);
295 else
296 return ((hi & 0xFFFF) << 16) | (lo >> 16);
297#endif
298 }
299#endif
300 if (!(skyeye_cachetype == INSTCACHE))
301 fault = GetWord (state, address, &data);
302 else
303 fault = LoadInstr (state, address, &data);
304
305 if (fault) {
306
307 /* dyf add for s3c6410 no instcache temporary 2010.9.17 */
308 if (!(skyeye_cachetype == INSTCACHE)) {
309 /* set translation fault on prefetch abort */
310 state->mmu.fault_statusi = fault & 0xFF;
311 state->mmu.fault_address = address;
312 }
313 /* add end */
314
315 ARMul_PREFETCHABORT (address);
316 return ARMul_ABORTWORD;
317 }
318 else {
319 ARMul_CLEARABORT;
320 }
321
322 return data;
323}
324
325/***************************************************************************\
326* Load Instruction, Sequential Cycle *
327\***************************************************************************/
328
329ARMword
330ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
331{
332 state->NumScycles++;
333 56
334#ifdef HOURGLASS 57#ifdef HOURGLASS
335 if ((state->NumScycles & HOURGLASS_RATE) == 0) { 58 if ((state->NumScycles & HOURGLASS_RATE) == 0) {
336 HOURGLASS; 59 HOURGLASS;
337 } 60 }
338#endif 61#endif
339 62 if (isize == 2)
340 return ARMul_ReLoadInstr (state, address, isize); 63 return (u16)Memory::Read16(address);
64 else
65 return (u32)Memory::Read32(address);
341} 66}
342 67
343/***************************************************************************\ 68ARMword ARMul_LoadInstrN(ARMul_State * state, ARMword address, ARMword isize) {
344* Load Instruction, Non Sequential Cycle * 69 state->NumNcycles++;
345\***************************************************************************/
346
347ARMword
348ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize)
349{
350 state->NumNcycles++;
351 70
352 return ARMul_ReLoadInstr (state, address, isize); 71 if (isize == 2)
72 return (u16)Memory::Read16(address);
73 else
74 return (u32)Memory::Read32(address);
353} 75}
354 76
355/***************************************************************************\ 77ARMword ARMul_ReLoadInstr(ARMul_State * state, ARMword address, ARMword isize) {
356* Read Word (but don't tell anyone!) * 78 ARMword data;
357\***************************************************************************/
358 79
359ARMword 80 if ((isize == 2) && (address & 0x2)) {
360ARMul_ReadWord (ARMul_State * state, ARMword address) 81 ARMword lo;
361{ 82 lo = (u16)Memory::Read16(address);
362 ARMword data; 83 return lo;
363 fault_t fault; 84 }
364
365#ifdef ABORTS
366 if (address >= LOWABORT && address < HIGHABORT) {
367 ARMul_DATAABORT (address);
368 return ARMul_ABORTWORD;
369 }
370 else {
371 ARMul_CLEARABORT;
372 }
373#endif
374 85
375 fault = GetWord (state, address, &data); 86 data = (u32)Memory::Read32(address);
376 if (fault) { 87 return data;
377 state->mmu.fault_status =
378 (fault | (state->mmu.last_domain << 4)) & 0xFF;
379 state->mmu.fault_address = address;
380 ARMul_DATAABORT (address);
381 return ARMul_ABORTWORD;
382 }
383 else {
384 ARMul_CLEARABORT;
385 }
386 return data;
387} 88}
388 89
389/***************************************************************************\ 90ARMword ARMul_ReadWord(ARMul_State * state, ARMword address) {
390* Load Word, Sequential Cycle * 91 ARMword data;
391\***************************************************************************/ 92 data = Memory::Read32(address);
392 93 return data;
393ARMword
394ARMul_LoadWordS (ARMul_State * state, ARMword address)
395{
396 state->NumScycles++;
397
398 return ARMul_ReadWord (state, address);
399} 94}
400 95
401/***************************************************************************\ 96ARMword ARMul_LoadWordS(ARMul_State * state, ARMword address) {
402* Load Word, Non Sequential Cycle * 97 state->NumScycles++;
403\***************************************************************************/ 98 return ARMul_ReadWord(state, address);
404
405ARMword
406ARMul_LoadWordN (ARMul_State * state, ARMword address)
407{
408 state->NumNcycles++;
409
410 return ARMul_ReadWord (state, address);
411} 99}
412 100
413/***************************************************************************\ 101ARMword ARMul_LoadWordN(ARMul_State * state, ARMword address) {
414* Load Halfword, (Non Sequential Cycle) * 102 state->NumNcycles++;
415\***************************************************************************/ 103 return ARMul_ReadWord(state, address);
416
417ARMword
418ARMul_LoadHalfWord (ARMul_State * state, ARMword address)
419{
420 ARMword data;
421 fault_t fault;
422
423 state->NumNcycles++;
424 fault = GetHalfWord (state, address, &data);
425
426 if (fault) {
427 state->mmu.fault_status =
428 (fault | (state->mmu.last_domain << 4)) & 0xFF;
429 state->mmu.fault_address = address;
430 ARMul_DATAABORT (address);
431 return ARMul_ABORTWORD;
432 }
433 else {
434 ARMul_CLEARABORT;
435 }
436
437 return data;
438
439} 104}
440 105
441/***************************************************************************\ 106ARMword ARMul_LoadHalfWord(ARMul_State * state, ARMword address) {
442* Read Byte (but don't tell anyone!) * 107 state->NumNcycles++;
443\***************************************************************************/ 108 return (u16)Memory::Read16(address);;
444int ARMul_ICE_ReadByte(ARMul_State * state, ARMword address, ARMword *presult)
445{
446 ARMword data;
447 fault_t fault;
448 fault = GetByte (state, address, &data);
449 if (fault) {
450 *presult=-1; fault=ALIGNMENT_FAULT; return fault;
451 }else{
452 *(char *)presult=(unsigned char)(data & 0xff); fault=NO_FAULT; return fault;
453 }
454} 109}
455
456
457ARMword
458ARMul_ReadByte (ARMul_State * state, ARMword address)
459{
460 ARMword data;
461 fault_t fault;
462
463 fault = GetByte (state, address, &data);
464
465 if (fault) {
466 state->mmu.fault_status =
467 (fault | (state->mmu.last_domain << 4)) & 0xFF;
468 state->mmu.fault_address = address;
469 ARMul_DATAABORT (address);
470 return ARMul_ABORTWORD;
471 }
472 else {
473 ARMul_CLEARABORT;
474 }
475
476 return data;
477
478}
479
480/***************************************************************************\
481* Load Byte, (Non Sequential Cycle) *
482\***************************************************************************/
483
484ARMword
485ARMul_LoadByte (ARMul_State * state, ARMword address)
486{
487 state->NumNcycles++;
488
489 return ARMul_ReadByte (state, address);
490}
491
492/***************************************************************************\
493* Write Word (but don't tell anyone!) *
494\***************************************************************************/
495
496void
497ARMul_WriteWord (ARMul_State * state, ARMword address, ARMword data)
498{
499 fault_t fault;
500
501#ifdef ABORTS
502 if (address >= LOWABORT && address < HIGHABORT) {
503 ARMul_DATAABORT (address);
504 return;
505 }
506 else {
507 ARMul_CLEARABORT;
508 }
509#endif
510 110
511 fault = PutWord (state, address, data); 111ARMword ARMul_ReadByte(ARMul_State * state, ARMword address) {
512 if (fault) { 112 return (u8)Memory::Read8(address);
513 state->mmu.fault_status =
514 (fault | (state->mmu.last_domain << 4)) & 0xFF;
515 state->mmu.fault_address = address;
516 ARMul_DATAABORT (address);
517 return;
518 }
519 else {
520 ARMul_CLEARABORT;
521 }
522} 113}
523 114
524/***************************************************************************\ 115ARMword ARMul_LoadByte(ARMul_State * state, ARMword address) {
525* Store Word, Sequential Cycle * 116 state->NumNcycles++;
526\***************************************************************************/ 117 return ARMul_ReadByte(state, address);
527
528void
529ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data)
530{
531 state->NumScycles++;
532
533 ARMul_WriteWord (state, address, data);
534} 118}
535 119
536/***************************************************************************\ 120void ARMul_StoreHalfWord(ARMul_State * state, ARMword address, ARMword data) {
537* Store Word, Non Sequential Cycle * 121 state->NumNcycles++;
538\***************************************************************************/ 122 Memory::Write16(address, data);
539
540void
541ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data)
542{
543 state->NumNcycles++;
544
545 ARMul_WriteWord (state, address, data);
546} 123}
547 124
548/***************************************************************************\ 125void ARMul_StoreByte(ARMul_State * state, ARMword address, ARMword data) {
549* Store HalfWord, (Non Sequential Cycle) * 126 state->NumNcycles++;
550\***************************************************************************/ 127 ARMul_WriteByte(state, address, data);
551
552void
553ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data)
554{
555 fault_t fault;
556 state->NumNcycles++;
557 fault = PutHalfWord (state, address, data);
558 if (fault) {
559 state->mmu.fault_status =
560 (fault | (state->mmu.last_domain << 4)) & 0xFF;
561 state->mmu.fault_address = address;
562 ARMul_DATAABORT (address);
563 return;
564 }
565 else {
566 ARMul_CLEARABORT;
567 }
568} 128}
569 129
570//chy 2006-04-15 130ARMword ARMul_SwapWord(ARMul_State * state, ARMword address, ARMword data) {
571int ARMul_ICE_WriteByte (ARMul_State * state, ARMword address, ARMword data) 131 ARMword temp;
572{ 132 state->NumNcycles++;
573 fault_t fault; 133 temp = ARMul_ReadWord(state, address);
574 fault = PutByte (state, address, data); 134 state->NumNcycles++;
575 if (fault) 135 Memory::Write32(address, data);
576 return 1; 136 return temp;
577 else
578 return 0;
579}
580/***************************************************************************\
581* Write Byte (but don't tell anyone!) *
582\***************************************************************************/
583//chy 2003-07-10, add real write byte fun
584void
585ARMul_WriteByte (ARMul_State * state, ARMword address, ARMword data)
586{
587 fault_t fault;
588 fault = PutByte (state, address, data);
589 if (fault) {
590 state->mmu.fault_status =
591 (fault | (state->mmu.last_domain << 4)) & 0xFF;
592 state->mmu.fault_address = address;
593 ARMul_DATAABORT (address);
594 return;
595 }
596 else {
597 ARMul_CLEARABORT;
598 }
599} 137}
600 138
601/***************************************************************************\ 139ARMword ARMul_SwapByte(ARMul_State * state, ARMword address, ARMword data) {
602* Store Byte, (Non Sequential Cycle) * 140 ARMword temp;
603\***************************************************************************/ 141 temp = ARMul_LoadByte(state, address);
604 142 Memory::Write8(address, data);
605void 143 return temp;
606ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data)
607{
608 state->NumNcycles++;
609
610#ifdef VALIDATE
611 if (address == TUBE) {
612 if (data == 4)
613 state->Emulate = FALSE;
614 else
615 (void) putc ((char) data, stderr); /* Write Char */
616 return;
617 }
618#endif
619
620 ARMul_WriteByte (state, address, data);
621} 144}
622 145
623/***************************************************************************\ 146void ARMul_WriteWord(ARMul_State * state, ARMword address, ARMword data) {
624* Swap Word, (Two Non Sequential Cycles) * 147 Memory::Write32(address, data);
625\***************************************************************************/
626
627ARMword
628ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data)
629{
630 ARMword temp;
631
632 state->NumNcycles++;
633
634 temp = ARMul_ReadWord (state, address);
635
636 state->NumNcycles++;
637
638 PutWord (state, address, data);
639
640 return temp;
641} 148}
642 149
643/***************************************************************************\ 150void ARMul_WriteByte(ARMul_State * state, ARMword address, ARMword data)
644* Swap Byte, (Two Non Sequential Cycles) *
645\***************************************************************************/
646
647ARMword
648ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data)
649{ 151{
650 ARMword temp; 152 Memory::Write8(address, data);
651
652 temp = ARMul_LoadByte (state, address);
653 ARMul_StoreByte (state, address, data);
654
655 return temp;
656} 153}
657 154
658/***************************************************************************\ 155void ARMul_StoreWordS(ARMul_State * state, ARMword address, ARMword data)
659* Count I Cycles *
660\***************************************************************************/
661
662void
663ARMul_Icycles (ARMul_State * state, unsigned number,
664 ARMword address)
665{ 156{
666 state->NumIcycles += number; 157 state->NumScycles++;
667 ARMul_CLEARABORT; 158 ARMul_WriteWord(state, address, data);
668} 159}
669 160
670/***************************************************************************\ 161void ARMul_StoreWordN(ARMul_State * state, ARMword address, ARMword data)
671* Count C Cycles *
672\***************************************************************************/
673
674void
675ARMul_Ccycles (ARMul_State * state, unsigned number,
676 ARMword address)
677{ 162{
678 state->NumCcycles += number; 163 state->NumNcycles++;
679 ARMul_CLEARABORT; 164 ARMul_WriteWord(state, address, data);
680} 165}
diff --git a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
deleted file mode 100644
index a32f076b9..000000000
--- a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
+++ /dev/null
@@ -1,1132 +0,0 @@
1/*
2 arm1176jzf_s_mmu.c - ARM920T Memory Management Unit emulation.
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#include <assert.h>
22#include <string.h>
23#include <stdint.h>
24
25#include "core/mem_map.h"
26
27#include "core/arm/interpreter/skyeye_defs.h"
28
29#include "core/arm/interpreter/armdefs.h"
30//#include "bank_defs.h"
31#if 0
32#define TLB_SIZE 1024 * 1024
33#define ASID 255
34static uint32_t tlb_entry_array[TLB_SIZE][ASID];
35static inline void invalidate_all_tlb(ARMul_State *state){
36 memset(&tlb_entry_array[0], 0xFF, sizeof(uint32_t) * TLB_SIZE * ASID);
37}
38static inline void invalidate_by_mva(ARMul_State *state, ARMword va){
39 memset(&tlb_entry_array[va >> 12][va & 0xFF], 0xFF, sizeof(uint32_t));
40 return;
41}
42static inline void invalidate_by_asid(ARMul_State *state, ARMword asid){
43 int i;
44 for(i = 0; i < TLB_SIZE; i++)
45 memset(&tlb_entry_array[i][asid & 0xFF], 0xFF, sizeof(uint32_t));
46 return;
47}
48
49static uint32_t get_phys_page(ARMul_State* state, ARMword va){
50 uint32_t phys_page = tlb_entry_array[va >> 12][state->mmu.context_id & 0xFF];
51 //printf("In %s, for va=0x%x, page=0x%x\n", __func__, va, phys_page);
52 return phys_page;
53}
54
55static inline void insert_tlb(ARMul_State* state, ARMword va, ARMword pa){
56 //printf("In %s, insert va=0x%x, pa=0x%x\n", __FUNCTION__, va, pa);
57 //printf("In %s, insert va=0x%x, va>>12=0x%x, pa=0x%x, pa>>12=0x%x\n", __FUNCTION__, va, va >> 12, pa, pa >> 12);
58 tlb_entry_array[va >> 12][state->mmu.context_id & 0xFF] = pa >> 12;
59
60 return;
61}
62#endif
63#define BANK0_START 0x50000000
64static void* mem_ptr = NULL;
65
66static int exclusive_detect(ARMul_State* state, ARMword addr){
67 #if 0
68 for(int i = 0; i < 128; i++){
69 if(state->exclusive_tag_array[i] == addr)
70 return 0;
71 }
72 #endif
73 if(state->exclusive_tag_array[0] == addr)
74 return 0;
75 else
76 return -1;
77}
78
79static void add_exclusive_addr(ARMul_State* state, ARMword addr){
80 #if 0
81 for(int i = 0; i < 128; i++){
82 if(state->exclusive_tag_array[i] == 0xffffffff){
83 state->exclusive_tag_array[i] = addr;
84 //printf("In %s, add addr 0x%x\n", __func__, addr);
85 return;
86 }
87 }
88 printf("In %s ,can not monitor the addr, out of array\n", __FUNCTION__);
89 #endif
90 state->exclusive_tag_array[0] = addr;
91 return;
92}
93
94static void remove_exclusive(ARMul_State* state, ARMword addr){
95 #if 0
96 int i;
97 for(i = 0; i < 128; i++){
98 if(state->exclusive_tag_array[i] == addr){
99 state->exclusive_tag_array[i] = 0xffffffff;
100 //printf("In %s, remove addr 0x%x\n", __func__, addr);
101 return;
102 }
103 }
104 #endif
105 state->exclusive_tag_array[0] = 0xFFFFFFFF;
106}
107
108/* This function encodes table 8-2 Interpreting AP bits,
109 returning non-zero if access is allowed. */
110static int
111check_perms (ARMul_State *state, int ap, int read)
112{
113 int s, r, user;
114
115 s = state->mmu.control & CONTROL_SYSTEM;
116 r = state->mmu.control & CONTROL_ROM;
117 /* chy 2006-02-15 , should consider system mode, don't conside 26bit mode */
118// printf("ap is %x, user is %x, s is %x, read is %x\n", ap, user, s, read);
119// printf("mode is %x\n", state->Mode);
120 user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE);
121
122 switch (ap) {
123 case 0:
124 return read && ((s && !user) || r);
125 case 1:
126 return !user;
127 case 2:
128 return read || !user;
129 case 3:
130 return 1;
131 }
132 return 0;
133}
134
135#if 0
136fault_t
137check_access (ARMul_State *state, ARMword virt_addr, tlb_entry_t *tlb,
138 int read)
139{
140 int access;
141
142 state->mmu.last_domain = tlb->domain;
143 access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3;
144 if ((access == 0) || (access == 2)) {
145 /* It's unclear from the documentation whether this
146 should always raise a section domain fault, or if
147 it should be a page domain fault in the case of an
148 L1 that describes a page table. In the ARM710T
149 datasheets, "Figure 8-9: Sequence for checking faults"
150 seems to indicate the former, while "Table 8-4: Priority
151 encoding of fault status" gives a value for FS[3210] in
152 the event of a domain fault for a page. Hmm. */
153 return SECTION_DOMAIN_FAULT;
154 }
155 if (access == 1) {
156 /* client access - check perms */
157 int subpage, ap;
158#if 0
159 switch (tlb->mapping) {
160 /*ks 2004-05-09
161 * only for XScale
162 * Extend Small Page(ESP) Format
163 * 31-12 bits the base addr of ESP
164 * 11-10 bits SBZ
165 * 9-6 bits TEX
166 * 5-4 bits AP
167 * 3 bit C
168 * 2 bit B
169 * 1-0 bits 11
170 * */
171 case TLB_ESMALLPAGE: /* xj */
172 subpage = 0;
173 /* printf("TLB_ESMALLPAGE virt_addr=0x%x \n",virt_addr ); */
174 break;
175
176 case TLB_TINYPAGE:
177 subpage = 0;
178 /* printf("TLB_TINYPAGE virt_addr=0x%x \n",virt_addr ); */
179 break;
180
181 case TLB_SMALLPAGE:
182 subpage = (virt_addr >> 10) & 3;
183 break;
184 case TLB_LARGEPAGE:
185 subpage = (virt_addr >> 14) & 3;
186 break;
187 case TLB_SECTION:
188 subpage = 3;
189 break;
190 default:
191 assert (0);
192 subpage = 0; /* cleans a warning */
193 }
194 ap = (tlb->perms >> (subpage * 2 + 4)) & 3;
195 if (!check_perms (state, ap, read)) {
196 if (tlb->mapping == TLB_SECTION) {
197 return SECTION_PERMISSION_FAULT;
198 } else {
199 return SUBPAGE_PERMISSION_FAULT;
200 }
201 }
202#endif
203 } else { /* access == 3 */
204 /* manager access - don't check perms */
205 }
206 return NO_FAULT;
207}
208#endif
209
210#if 0
211fault_t
212mmu_translate (ARMul_State *state, ARMword virt_addr, ARMword *phys_addr)
213#endif
214
215/* ap: AP bits value.
216 * sop: section or page description 0:section 1:page
217 */
218fault_t
219mmu_translate (ARMul_State *state, ARMword virt_addr, ARMword *phys_addr, int *ap, int *sop)
220{
221 {
222 /* walk the translation tables */
223 ARMword l1addr, l1desc;
224 if (state->mmu.translation_table_ctrl && virt_addr << state->mmu.translation_table_ctrl >> (32 - state->mmu.translation_table_ctrl - 1)) {
225 l1addr = state->mmu.translation_table_base1;
226 l1addr = (((l1addr >> 14) << 14) | (virt_addr >> 18)) & ~3;
227 } else {
228 l1addr = state->mmu.translation_table_base0;
229 l1addr = (((l1addr >> (14 - state->mmu.translation_table_ctrl)) << (14 - state->mmu.translation_table_ctrl)) | (virt_addr << state->mmu.translation_table_ctrl) >> (18 + state->mmu.translation_table_ctrl)) & ~3;
230 }
231
232 /* l1desc = mem_read_word (state, l1addr); */
233 if (state->space.conf_obj != NULL)
234 state->space.read(state->space.conf_obj, l1addr, &l1desc, 4);
235 else
236 l1desc = Memory::Read32(l1addr); //mem_read_raw(32, l1addr, &l1desc);
237
238 #if 0
239 if (virt_addr == 0xc000d2bc) {
240 printf("mmu_control is %x\n", state->mmu.translation_table_ctrl);
241 printf("mmu_table_0 is %x\n", state->mmu.translation_table_base0);
242 printf("mmu_table_1 is %x\n", state->mmu.translation_table_base1);
243 printf("l1addr is %x l1desc is %x\n", l1addr, l1desc);
244 // exit(-1);
245 }
246 #endif
247 switch (l1desc & 3) {
248 case 0:
249 case 3:
250 /*
251 * according to Figure 3-9 Sequence for checking faults in arm manual,
252 * section translation fault should be returned here.
253 */
254 {
255 return SECTION_TRANSLATION_FAULT;
256 }
257 case 1:
258 /* coarse page table */
259 {
260 ARMword l2addr, l2desc;
261
262
263 l2addr = l1desc & 0xFFFFFC00;
264 l2addr = (l2addr |
265 ((virt_addr & 0x000FF000) >> 10)) &
266 ~3;
267 if(state->space.conf_obj != NULL)
268 state->space.read(state->space.conf_obj, l2addr, &l2desc, 4);
269 else
270 l2desc = Memory::Read32(l2addr); //mem_read_raw(32, l2addr, &l2desc);
271
272 /* chy 2003-09-02 for xscale */
273 *ap = (l2desc >> 4) & 0x3;
274 *sop = 1; /* page */
275
276 switch (l2desc & 3) {
277 case 0:
278 return PAGE_TRANSLATION_FAULT;
279 break;
280 case 1:
281 *phys_addr = (l2desc & 0xFFFF0000) | (virt_addr & 0x0000FFFF);
282 break;
283 case 2:
284 case 3:
285 *phys_addr = (l2desc & 0xFFFFF000) | (virt_addr & 0x00000FFF);
286 break;
287
288 }
289 }
290 break;
291 case 2:
292 /* section */
293
294 *ap = (l1desc >> 10) & 3;
295 *sop = 0; /* section */
296 #if 0
297 if (virt_addr == 0xc000d2bc) {
298 printf("mmu_control is %x\n", state->mmu.translation_table_ctrl);
299 printf("mmu_table_0 is %x\n", state->mmu.translation_table_base0);
300 printf("mmu_table_1 is %x\n", state->mmu.translation_table_base1);
301 printf("l1addr is %x l1desc is %x\n", l1addr, l1desc);
302// printf("l2addr is %x l2desc is %x\n", l2addr, l2desc);
303 printf("ap is %x, sop is %x\n", *ap, *sop);
304 printf("mode is %d\n", state->Mode);
305// exit(-1);
306 }
307 #endif
308
309 if (l1desc & 0x30000)
310 *phys_addr = (l1desc & 0xFF000000) | (virt_addr & 0x00FFFFFF);
311 else
312 *phys_addr = (l1desc & 0xFFF00000) | (virt_addr & 0x000FFFFF);
313 break;
314 }
315 }
316 return NO_FAULT;
317}
318
319
320static fault_t arm1176jzf_s_mmu_write (ARMul_State *state, ARMword va,
321 ARMword data, ARMword datatype);
322static fault_t arm1176jzf_s_mmu_read (ARMul_State *state, ARMword va,
323 ARMword *data, ARMword datatype);
324
325int
326arm1176jzf_s_mmu_init (ARMul_State *state)
327{
328 state->mmu.control = 0x50078;
329 state->mmu.translation_table_base = 0xDEADC0DE;
330 state->mmu.domain_access_control = 0xDEADC0DE;
331 state->mmu.fault_status = 0;
332 state->mmu.fault_address = 0;
333 state->mmu.process_id = 0;
334 state->mmu.context_id = 0;
335 state->mmu.thread_uro_id = 0;
336 //invalidate_all_tlb(state);
337
338 return No_exp;
339}
340
341void
342arm1176jzf_s_mmu_exit (ARMul_State *state)
343{
344}
345
346
347static fault_t
348arm1176jzf_s_mmu_load_instr (ARMul_State *state, ARMword va, ARMword *instr)
349{
350 fault_t fault;
351 int c; /* cache bit */
352 ARMword pa; /* physical addr */
353 ARMword perm; /* physical addr access permissions */
354 int ap, sop;
355
356 static int debug_count = 0; /* used for debug */
357
358 //DEBUG_LOG(ARM11, "va = %x\n", va);
359
360 va = mmu_pid_va_map (va);
361 if (MMU_Enabled) {
362// printf("MMU enabled.\n");
363// sleep(1);
364 /* align check */
365 if ((va & (WORD_SIZE - 1)) && MMU_Aligned) {
366 DEBUG_LOG(ARM11, "align\n");
367 return ALIGNMENT_FAULT;
368 } else
369 va &= ~(WORD_SIZE - 1);
370
371 /* translate tlb */
372 fault = mmu_translate (state, va, &pa, &ap, &sop);
373 if (fault) {
374 DEBUG_LOG(ARM11, "translate\n");
375 printf("va=0x%x, icounter=%lld, fault=%d\n", va, state->NumInstrs, fault);
376 return fault;
377 }
378
379
380 /* no tlb, only check permission */
381 if (!check_perms(state, ap, 1)) {
382 if (sop == 0) {
383 return SECTION_PERMISSION_FAULT;
384 } else {
385 return SUBPAGE_PERMISSION_FAULT;
386 }
387 }
388
389#if 0
390 /*check access */
391 fault = check_access (state, va, tlb, 1);
392 if (fault) {
393 DEBUG_LOG(ARM11, "check_fault\n");
394 return fault;
395 }
396#endif
397 }
398
399 /*if MMU disabled or C flag is set alloc cache */
400 if (MMU_Disabled) {
401// printf("MMU disabled.\n");
402// sleep(1);
403 pa = va;
404 }
405 if(state->space.conf_obj == NULL)
406 state->space.read(state->space.conf_obj, pa, instr, 4);
407 else
408 *instr = Memory::Read32(pa); //mem_read_raw(32, pa, instr);
409
410 return NO_FAULT;
411}
412
413static fault_t
414arm1176jzf_s_mmu_read_byte (ARMul_State *state, ARMword virt_addr, ARMword *data)
415{
416 /* ARMword temp,offset; */
417 fault_t fault;
418 fault = arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE);
419 return fault;
420}
421
422static fault_t
423arm1176jzf_s_mmu_read_halfword (ARMul_State *state, ARMword virt_addr,
424 ARMword *data)
425{
426 /* ARMword temp,offset; */
427 fault_t fault;
428 fault = arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE);
429 return fault;
430}
431
432static fault_t
433arm1176jzf_s_mmu_read_word (ARMul_State *state, ARMword virt_addr, ARMword *data)
434{
435 return arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_WORD_TYPE);
436}
437
438static fault_t
439arm1176jzf_s_mmu_read (ARMul_State *state, ARMword va, ARMword *data,
440 ARMword datatype)
441{
442 fault_t fault;
443 ARMword pa, real_va, temp, offset;
444 ARMword perm; /* physical addr access permissions */
445 int ap, sop;
446
447 //DEBUG_LOG(ARM11, "va = %x\n", va);
448
449 va = mmu_pid_va_map (va);
450 real_va = va;
451 /* if MMU disabled, memory_read */
452 if (MMU_Disabled) {
453// printf("MMU disabled cpu_id:%x addr:%x.\n", state->mmu.process_id, va);
454// sleep(1);
455
456 /* *data = mem_read_word(state, va); */
457 if (datatype == ARM_BYTE_TYPE)
458 /* *data = mem_read_byte (state, va); */
459 if(state->space.conf_obj != NULL)
460 state->space.read(state->space.conf_obj, va, data, 1);
461 else
462 *data = Memory::Read8(va); //mem_read_raw(8, va, data);
463 else if (datatype == ARM_HALFWORD_TYPE)
464 /* *data = mem_read_halfword (state, va); */
465 if(state->space.conf_obj != NULL)
466 state->space.read(state->space.conf_obj, va, data, 2);
467 else
468 *data = Memory::Read16(va); //mem_read_raw(16, va, data);
469 else if (datatype == ARM_WORD_TYPE)
470 /* *data = mem_read_word (state, va); */
471 if(state->space.conf_obj != NULL)
472 state->space.read(state->space.conf_obj, va, data, 4);
473 else
474 *data = Memory::Read32(va); //mem_read_raw(32, va, data);
475 else {
476 ERROR_LOG(ARM11, "SKYEYE:1 arm1176jzf_s_mmu_read error: unknown data type %d\n", datatype);
477 }
478
479 return NO_FAULT;
480 }
481// printf("MMU enabled.\n");
482// sleep(1);
483
484 /* align check */
485 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
486 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
487 DEBUG_LOG(ARM11, "align\n");
488 return ALIGNMENT_FAULT;
489 }
490
491 /* va &= ~(WORD_SIZE - 1); */
492 #if 0
493 uint32_t page_base;
494 page_base = get_phys_page(state, va);
495 if((page_base & 0xFFF) == 0){
496 pa = (page_base << 12) | (va & 0xFFF);
497 goto skip_translation;
498 }
499 #endif
500 /*translate va to tlb */
501#if 0
502 fault = mmu_translate (state, va, ARM920T_D_TLB (), &tlb);
503#endif
504 fault = mmu_translate (state, va, &pa, &ap, &sop);
505#if 0
506 if(va ==0xbebb1774 || state->Reg[15] == 0x400ff594){
507 //printf("In %s, current=0x%x. mode is %x, pc=0x%x\n", __FUNCTION__, state->CurrInstr, state->Mode, state->Reg[15]);
508 printf("In %s, ap is %d, sop is %d, va=0x%x, pa=0x%x, fault=%d, data=0x%x\n", __FUNCTION__, ap, sop, va, pa, fault, data);
509 int i;
510 for(i = 0; i < 16; i++)
511 printf("Reg[%d]=0x%x\t", i, state->Reg[i]);
512 printf("\n");
513 }
514#endif
515 if (fault) {
516 DEBUG_LOG(ARM11, "translate\n");
517 //printf("mmu read fault at %x\n", va);
518 //printf("fault is %d\n", fault);
519 return fault;
520 }
521// printf("va is %x pa is %x\n", va, pa);
522
523 /* no tlb, only check permission */
524 if (!check_perms(state, ap, 1)) {
525 if (sop == 0) {
526 return SECTION_PERMISSION_FAULT;
527 } else {
528 return SUBPAGE_PERMISSION_FAULT;
529 }
530 }
531#if 0
532 /*check access permission */
533 fault = check_access (state, va, tlb, 1);
534 if (fault)
535 return fault;
536#endif
537
538 //insert_tlb(state, va, pa);
539skip_translation:
540 /* *data = mem_read_word(state, pa); */
541 if (datatype == ARM_BYTE_TYPE) {
542 /* *data = mem_read_byte (state, pa | (real_va & 3)); */
543 if(state->space.conf_obj != NULL)
544 state->space.read(state->space.conf_obj, pa | (real_va & 3), data, 1);
545 else
546 *data = Memory::Read8(pa | (real_va & 3)); //mem_read_raw(8, pa | (real_va & 3), data);
547 /* mem_read_raw(32, pa | (real_va & 3), data); */
548 } else if (datatype == ARM_HALFWORD_TYPE) {
549 /* *data = mem_read_halfword (state, pa | (real_va & 2)); */
550 if(state->space.conf_obj != NULL)
551 state->space.read(state->space.conf_obj, pa | (real_va & 3), data, 2);
552 else
553 *data = Memory::Read16(pa | (real_va & 3)); //mem_read_raw(16, pa | (real_va & 3), data);
554 /* mem_read_raw(32, pa | (real_va & 2), data); */
555 } else if (datatype == ARM_WORD_TYPE)
556 /* *data = mem_read_word (state, pa); */
557 if(state->space.conf_obj != NULL)
558 state->space.read(state->space.conf_obj, pa , data, 4);
559 else
560 *data = Memory::Read32(pa); //mem_read_raw(32, pa, data);
561 else {
562 ERROR_LOG(ARM11, "SKYEYE:2 arm1176jzf_s_mmu_read error: unknown data type %d\n", datatype);
563 }
564 if(0 && (va == 0x2869c)){
565 printf("In %s, pa is %x va=0x%x, value is %x pc %x, instr=0x%x\n", __FUNCTION__, pa, va, *data, state->Reg[15], state->CurrInstr);
566 }
567
568 /* ldrex or ldrexb */
569 if(((state->CurrInstr & 0x0FF000F0) == 0x01900090) ||
570 ((state->CurrInstr & 0x0FF000F0) == 0x01d00090)){
571 int rn = (state->CurrInstr & 0xF0000) >> 16;
572 if(state->Reg[rn] == va){
573 add_exclusive_addr(state, pa | (real_va & 3));
574 state->exclusive_access_state = 1;
575 }
576 }
577#if 0
578 if (state->pc == 0xc011a868) {
579 printf("pa is %x value is %x size is %x\n", pa, data, datatype);
580 printf("icounter is %lld\n", state->NumInstrs);
581// exit(-1);
582 }
583#endif
584
585 return NO_FAULT;
586}
587
588
589static fault_t
590arm1176jzf_s_mmu_write_byte (ARMul_State *state, ARMword virt_addr, ARMword data)
591{
592 return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE);
593}
594
595static fault_t
596arm1176jzf_s_mmu_write_halfword (ARMul_State *state, ARMword virt_addr,
597 ARMword data)
598{
599 return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE);
600}
601
602static fault_t
603arm1176jzf_s_mmu_write_word (ARMul_State *state, ARMword virt_addr, ARMword data)
604{
605 return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_WORD_TYPE);
606}
607
608
609
610static fault_t
611arm1176jzf_s_mmu_write (ARMul_State *state, ARMword va, ARMword data,
612 ARMword datatype)
613{
614 int b;
615 ARMword pa, real_va;
616 ARMword perm; /* physical addr access permissions */
617 fault_t fault;
618 int ap, sop;
619
620#if 0
621 /8 for sky_printk debugger.*/
622 if (va == 0xffffffff) {
623 putchar((char)data);
624 return 0;
625 }
626 if (va == 0xBfffffff) {
627 putchar((char)data);
628 return 0;
629 }
630#endif
631
632 //DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data);
633 va = mmu_pid_va_map (va);
634 real_va = va;
635
636 if (MMU_Disabled) {
637 /* mem_write_word(state, va, data); */
638 if (datatype == ARM_BYTE_TYPE)
639 /* mem_write_byte (state, va, data); */
640 if(state->space.conf_obj != NULL)
641 state->space.write(state->space.conf_obj, va, &data, 1);
642 else
643 Memory::Write8(va, data);
644 else if (datatype == ARM_HALFWORD_TYPE)
645 /* mem_write_halfword (state, va, data); */
646 if(state->space.conf_obj != NULL)
647 state->space.write(state->space.conf_obj, va, &data, 2);
648 else
649 Memory::Write16(va, data);
650 else if (datatype == ARM_WORD_TYPE)
651 /* mem_write_word (state, va, data); */
652 if(state->space.conf_obj != NULL)
653 state->space.write(state->space.conf_obj, va, &data, 4);
654 else
655 Memory::Write32(va, data);
656 else {
657 ERROR_LOG (ARM11, "SKYEYE:1 arm1176jzf_s_mmu_write error: unknown data type %d\n", datatype);
658 }
659 goto finished_write;
660 //return 0;
661 }
662 /*align check */
663 /* if ((va & (WORD_SIZE - 1)) && MMU_Aligned){ */
664 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
665 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
666 DEBUG_LOG(ARM11, "align\n");
667 return ALIGNMENT_FAULT;
668 }
669 va &= ~(WORD_SIZE - 1);
670 #if 0
671 uint32_t page_base;
672 page_base = get_phys_page(state, va);
673 if((page_base & 0xFFF) == 0){
674 pa = (page_base << 12) | (va & 0xFFF);
675 goto skip_translation;
676 }
677 #endif
678 /*tlb translate */
679 fault = mmu_translate (state, va, &pa, &ap, &sop);
680#if 0
681 if(va ==0xbebb1774 || state->Reg[15] == 0x40102334){
682 //printf("In %s, current=0x%x. mode is %x, pc=0x%x\n", __FUNCTION__, state->CurrInstr, state->Mode, state->Reg[15]);
683 printf("In %s, ap is %d, sop is %d, va=0x%x, pa=0x%x, fault=%d, data=0x%x\n", __FUNCTION__, ap, sop, va, pa, fault, data);
684 int i;
685 for(i = 0; i < 16; i++)
686 printf("Reg[%d]=0x%x\t", i, state->Reg[i]);
687 printf("\n");
688 }
689#endif
690 if (fault) {
691 DEBUG_LOG(ARM11, "translate\n");
692 //printf("mmu write fault at %x\n", va);
693 return fault;
694 }
695// printf("va is %x pa is %x\n", va, pa);
696
697 /* no tlb, only check permission */
698 if (!check_perms(state, ap, 0)) {
699 if (sop == 0) {
700 return SECTION_PERMISSION_FAULT;
701 } else {
702 return SUBPAGE_PERMISSION_FAULT;
703 }
704 }
705
706#if 0
707 /* tlb check access */
708 fault = check_access (state, va, tlb, 0);
709 if (fault) {
710 DEBUG_LOG(ARM11, "check_access\n");
711 return fault;
712 }
713#endif
714#if 0
715 if (pa <= 0x502860ff && (pa + 1 << datatype) > 0x502860ff) {
716 printf("pa is %x value is %x size is %x\n", pa, data, datatype);
717 }
718#endif
719#if 0
720 if (state->pc == 0xc011a878) {
721 printf("write pa is %x value is %x size is %x\n", pa, data, datatype);
722 printf("icounter is %lld\n", state->NumInstrs);
723 exit(-1);
724 }
725#endif
726 //insert_tlb(state, va, pa);
727skip_translation:
728 /* strex */
729 if(((state->CurrInstr & 0x0FF000F0) == 0x01800090) ||
730 ((state->CurrInstr & 0x0FF000F0) == 0x01c00090)){
731 /* failed , the address is monitord now. */
732 int dest_reg = (state->CurrInstr & 0xF000) >> 12;
733 if((exclusive_detect(state, pa | (real_va & 3)) == 0) && (state->exclusive_access_state == 1)){
734 remove_exclusive(state, pa | (real_va & 3));
735 state->Reg[dest_reg] = 0;
736 state->exclusive_access_state = 0;
737 }
738 else{
739 state->Reg[dest_reg] = 1;
740 //printf("In %s, try to strex a monitored address 0x%x\n", __FUNCTION__, pa);
741 return NO_FAULT;
742 }
743 }
744
745 if (datatype == ARM_BYTE_TYPE) {
746 /* mem_write_byte (state,
747 (pa | (real_va & 3)),
748 data);
749 */
750 if(state->space.conf_obj != NULL)
751 state->space.write(state->space.conf_obj, (pa | (real_va & 3)), &data, 1);
752 else
753 Memory::Write8((pa | (real_va & 3)), data);
754
755 } else if (datatype == ARM_HALFWORD_TYPE)
756 /* mem_write_halfword (state,
757 (pa |
758 (real_va & 2)),
759 data);
760 */
761 if(state->space.conf_obj != NULL)
762 state->space.write(state->space.conf_obj, (pa | (real_va & 3)), &data, 2);
763 else
764 Memory::Write16((pa | (real_va & 3)), data);
765 else if (datatype == ARM_WORD_TYPE)
766 /* mem_write_word (state, pa, data); */
767 if(state->space.conf_obj != NULL)
768 state->space.write(state->space.conf_obj, pa, &data, 4);
769 else
770 Memory::Write32(pa, data);
771#if 0
772 if (state->NumInstrs > 236403) {
773 printf("write memory\n");
774 printf("pa is %x value is %x size is %x\n", pa, data, datatype);
775 printf("icounter is %lld\n", state->NumInstrs);
776 }
777#endif
778finished_write:
779#if DIFF_WRITE
780 if(state->icounter > state->debug_icounter){
781 if(state->CurrWrite >= 17 ){
782 printf("Wrong write array, 0x%x", state->CurrWrite);
783 exit(-1);
784 }
785 uint32 record_data = data;
786 if(datatype == ARM_BYTE_TYPE)
787 record_data &= 0xFF;
788 if(datatype == ARM_HALFWORD_TYPE)
789 record_data &= 0xFFFF;
790
791 state->WriteAddr[state->CurrWrite] = pa | (real_va & 3);
792 state->WriteData[state->CurrWrite] = record_data;
793 state->WritePc[state->CurrWrite] = state->Reg[15];
794 state->CurrWrite++;
795 //printf("In %s, pc=0x%x, addr=0x%x, data=0x%x, CFlag=%d\n", __FUNCTION__, state->Reg[15], pa | (real_va & 3), record_data, state->CFlag);
796 }
797#endif
798
799 return NO_FAULT;
800}
801
802ARMword
803arm1176jzf_s_mmu_mrc (ARMul_State *state, ARMword instr, ARMword *value)
804{
805 int creg = BITS (16, 19) & 0xf;
806 int OPC_1 = BITS (21, 23) & 0x7;
807 int OPC_2 = BITS (5, 7) & 0x7;
808 ARMword data;
809
810 switch (creg) {
811 case MMU_ID:
812 if (OPC_2 == 0) {
813 data = state->cpu->cpu_val;
814 } else if (OPC_2 == 1) {
815 /* Cache type:
816 * 000 0110 1 000 101 110 0 10 000 101 110 0 10
817 * */
818 data = 0x0D172172;
819 }
820 break;
821 case MMU_CONTROL:
822 /*
823 * 6:3 read as 1
824 * 10 read as 0
825 * 18,16 read as 1
826 * */
827 data = (state->mmu.control | 0x50078) & 0xFFFFFBFF;
828 break;
829 case MMU_TRANSLATION_TABLE_BASE:
830#if 0
831 data = state->mmu.translation_table_base;
832#endif
833 switch (OPC_2) {
834 case 0:
835 data = state->mmu.translation_table_base0;
836 break;
837 case 1:
838 data = state->mmu.translation_table_base1;
839 break;
840 case 2:
841 data = state->mmu.translation_table_ctrl;
842 break;
843 default:
844 printf ("mmu_mrc read UNKNOWN - p15 c2 opcode2 %d\n", OPC_2);
845 break;
846 }
847 break;
848 case MMU_DOMAIN_ACCESS_CONTROL:
849 data = state->mmu.domain_access_control;
850 break;
851 case MMU_FAULT_STATUS:
852 /* OPC_2 = 0: data FSR value
853 * */
854 if (OPC_2 == 0)
855 data = state->mmu.fault_status;
856 if (OPC_2 == 1)
857 data = state->mmu.fault_statusi;
858 break;
859 case MMU_FAULT_ADDRESS:
860 data = state->mmu.fault_address;
861 break;
862 case MMU_PID:
863 //data = state->mmu.process_id;
864 if(OPC_2 == 0)
865 data = state->mmu.process_id;
866 else if(OPC_2 == 1)
867 data = state->mmu.context_id;
868 else if(OPC_2 == 3){
869 data = state->mmu.thread_uro_id;
870 }
871 else{
872 printf ("mmu_mcr read UNKNOWN - reg %d\n", creg);
873 }
874 //printf("SKYEYE In %s, read pid 0x%x, OPC_2 %d, instr=0x%x\n", __FUNCTION__, data, OPC_2, instr);
875 //exit(-1);
876 break;
877 default:
878 printf ("mmu_mrc read UNKNOWN - reg %d\n", creg);
879 data = 0;
880 break;
881 }
882/* printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]); */
883 *value = data;
884 return data;
885}
886
887
888static ARMword
889arm1176jzf_s_mmu_mcr (ARMul_State *state, ARMword instr, ARMword value)
890{
891 int creg = BITS (16, 19) & 0xf;
892 int CRm = BITS (0, 3) & 0xf;
893 int OPC_1 = BITS (21, 23) & 0x7;
894 int OPC_2 = BITS (5, 7) & 0x7;
895 if (!strncmp (state->cpu->cpu_arch_name, "armv6", 5)) {
896 switch (creg) {
897 case MMU_CONTROL:
898 /*
899 * 6:3 read as 1
900 * 10 read as 0
901 * 18,16 read as 1
902 * */
903 if(OPC_2 == 0)
904 state->mmu.control = (value | 0x50078) & 0xFFFFFBFF;
905 else if(OPC_2 == 1)
906 state->mmu.auxiliary_control = value;
907 else if(OPC_2 == 2)
908 state->mmu.coprocessor_access_control = value;
909 else
910 fprintf(stderr, "In %s, wrong OPC_2 %d\n", __FUNCTION__, OPC_2);
911 break;
912 case MMU_TRANSLATION_TABLE_BASE:
913 switch (OPC_2) {
914 /* int i; */
915 case 0:
916#if 0
917 /* TTBR0 */
918 if (state->mmu.translation_table_ctrl & 0x7) {
919 for (i = 0; i <= state->mmu.translation_table_ctrl; i++)
920 state->mmu.translation_table_base0 &= ~(1 << (5 + i));
921 }
922#endif
923 state->mmu.translation_table_base0 = (value);
924 break;
925 case 1:
926#if 0
927 /* TTBR1 */
928 if (state->mmu.translation_table_ctrl & 0x7) {
929 for (i = 0; i <= state->mmu.translation_table_ctrl; i++)
930 state->mmu.translation_table_base1 &= 1 << (5 + i);
931 }
932#endif
933 state->mmu.translation_table_base1 = (value);
934 break;
935 case 2:
936 /* TTBC */
937 state->mmu.translation_table_ctrl = value & 0x7;
938 break;
939 default:
940 printf ("mmu_mcr wrote UNKNOWN - cp15 c2 opcode2 %d\n", OPC_2);
941 break;
942 }
943 //printf("SKYEYE In %s, write TLB_BASE 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr);
944 //invalidate_all_tlb(state);
945 break;
946 case MMU_DOMAIN_ACCESS_CONTROL:
947 /* printf("mmu_mcr wrote DACR "); */
948 state->mmu.domain_access_control = value;
949 break;
950
951 case MMU_FAULT_STATUS:
952 if (OPC_2 == 0)
953 state->mmu.fault_status = value & 0xFF;
954 if (OPC_2 == 1) {
955 printf("set fault status instr\n");
956 }
957 break;
958 case MMU_FAULT_ADDRESS:
959 state->mmu.fault_address = value;
960 break;
961
962 case MMU_CACHE_OPS:
963 break;
964 case MMU_TLB_OPS:
965 {
966 switch(CRm){
967 case 5: /* ITLB */
968 {
969 switch(OPC_2){
970 case 0: /* invalidate all */
971 //invalidate_all_tlb(state);
972 break;
973 case 1: /* invalidate by MVA */
974 //invalidate_by_mva(state, value);
975 break;
976 case 2: /* invalidate by asid */
977 //invalidate_by_asid(state, value);
978 break;
979 default:
980 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
981 break;
982 }
983 break;
984 }
985 case 6: /* DTLB */
986 {
987 switch(OPC_2){
988 case 0: /* invalidate all */
989 //invalidate_all_tlb(state);
990 break;
991 case 1: /* invalidate by MVA */
992 //invalidate_by_mva(state, value);
993 break;
994 case 2: /* invalidate by asid */
995 //invalidate_by_asid(state, value);
996 break;
997 default:
998 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
999 break;
1000 }
1001 break;
1002 }
1003 case 7: /* Unified TLB */
1004 {
1005 switch(OPC_2){
1006 case 0: /* invalidate all */
1007 //invalidate_all_tlb(state);
1008 break;
1009 case 1: /* invalidate by MVA */
1010 //invalidate_by_mva(state, value);
1011 break;
1012 case 2: /* invalidate by asid */
1013 //invalidate_by_asid(state, value);
1014 break;
1015 default:
1016 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
1017 break;
1018 }
1019 break;
1020 }
1021
1022 default:
1023 printf ("mmu_mcr wrote UNKNOWN - reg %d, CRm=%d\n", creg, CRm);
1024 break;
1025 }
1026 //printf("SKYEYE In %s, write TLB 0x%x OPC_1=%d, OPC_2=%d , CRm=%d instr=0x%x\n", __FUNCTION__, value, OPC_1, OPC_2, CRm, instr);
1027 }
1028 break;
1029 case MMU_CACHE_LOCKDOWN:
1030 /*
1031 * FIXME: cache lock down*/
1032 break;
1033 case MMU_TLB_LOCKDOWN:
1034 printf("SKYEYE In %s, write TLB_LOCKDOWN 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr);
1035 /* FIXME:tlb lock down */
1036 break;
1037 case MMU_PID:
1038 //printf("SKYEYE In %s, write pid 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr);
1039 //state->mmu.process_id = value;
1040 /*0:24 should be zero. */
1041 //state->mmu.process_id = value & 0xfe000000;
1042 if(OPC_2 == 0)
1043 state->mmu.process_id = value;
1044 else if(OPC_2 == 1)
1045 state->mmu.context_id = value;
1046 else if(OPC_2 == 3){
1047 state->mmu.thread_uro_id = value;
1048 }
1049 else{
1050 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
1051 }
1052 break;
1053
1054 default:
1055 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
1056 break;
1057 }
1058 }
1059
1060 return No_exp;
1061}
1062
1063///* teawater add for arm2x86 2005.06.19------------------------------------------- */
1064//static int
1065//arm1176jzf_s_mmu_v2p_dbct (ARMul_State *state, ARMword virt_addr,
1066// ARMword *phys_addr)
1067//{
1068// fault_t fault;
1069// int ap, sop;
1070//
1071// ARMword perm; /* physical addr access permissions */
1072// virt_addr = mmu_pid_va_map (virt_addr);
1073// if (MMU_Enabled) {
1074//
1075// /*align check */
1076// if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) {
1077// DEBUG_LOG(ARM11, "align\n");
1078// return ALIGNMENT_FAULT;
1079// } else
1080// virt_addr &= ~(WORD_SIZE - 1);
1081//
1082// /*translate tlb */
1083// fault = mmu_translate (state, virt_addr, phys_addr, &ap, &sop);
1084// if (fault) {
1085// DEBUG_LOG(ARM11, "translate\n");
1086// return fault;
1087// }
1088//
1089// /* permission check */
1090// if (!check_perms(state, ap, 1)) {
1091// if (sop == 0) {
1092// return SECTION_PERMISSION_FAULT;
1093// } else {
1094// return SUBPAGE_PERMISSION_FAULT;
1095// }
1096// }
1097//#if 0
1098// /*check access */
1099// fault = check_access (state, virt_addr, tlb, 1);
1100// if (fault) {
1101// DEBUG_LOG(ARM11, "check_fault\n");
1102// return fault;
1103// }
1104//#endif
1105// }
1106//
1107// if (MMU_Disabled) {
1108// *phys_addr = virt_addr;
1109// }
1110//
1111// return 0;
1112//}
1113
1114/* AJ2D-------------------------------------------------------------------------- */
1115
1116/*arm1176jzf-s mmu_ops_t*/
1117mmu_ops_t arm1176jzf_s_mmu_ops = {
1118 arm1176jzf_s_mmu_init,
1119 arm1176jzf_s_mmu_exit,
1120 arm1176jzf_s_mmu_read_byte,
1121 arm1176jzf_s_mmu_write_byte,
1122 arm1176jzf_s_mmu_read_halfword,
1123 arm1176jzf_s_mmu_write_halfword,
1124 arm1176jzf_s_mmu_read_word,
1125 arm1176jzf_s_mmu_write_word,
1126 arm1176jzf_s_mmu_load_instr,
1127 arm1176jzf_s_mmu_mcr,
1128 arm1176jzf_s_mmu_mrc
1129/* teawater add for arm2x86 2005.06.19------------------------------------------- */
1130/* arm1176jzf_s_mmu_v2p_dbct, */
1131/* AJ2D-------------------------------------------------------------------------- */
1132};
diff --git a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h
deleted file mode 100644
index 299c6b46b..000000000
--- a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h
+++ /dev/null
@@ -1,37 +0,0 @@
1/*
2 arm1176JZF-S_mmu.h - ARM1176JZF-S Memory Management Unit emulation.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
18
19#ifndef _ARM1176JZF_S_MMU_H_
20#define _ARM1176JZF_S_MMU_H_
21
22#if 0
23typedef struct arm1176jzf-s_mmu_s
24{
25 tlb_t i_tlb;
26 cache_t i_cache;
27
28 tlb_t d_tlb;
29 cache_t d_cache;
30 wb_t wb_t;
31} arm1176jzf-s_mmu_t;
32#endif
33extern mmu_ops_t arm1176jzf_s_mmu_ops;
34
35ARMword
36arm1176jzf_s_mmu_mrc (ARMul_State *state, ARMword instr, ARMword *value);
37#endif /*_ARM1176JZF_S_MMU_H_*/
diff --git a/src/core/arm/interpreter/mmu/cache.cpp b/src/core/arm/interpreter/mmu/cache.cpp
deleted file mode 100644
index f3c4e0531..000000000
--- a/src/core/arm/interpreter/mmu/cache.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
1#include "core/arm/interpreter/armdefs.h"
2
3/* mmu cache init
4 *
5 * @cache_t :cache_t to init
6 * @width :cache line width in byte
7 * @way :way of each cache set
8 * @set :cache set num
9 *
10 * $ -1: error
11 * 0: sucess
12 */
13int
14mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode)
15{
16 int i, j;
17 cache_set_t *sets;
18 cache_line_t *lines;
19
20 /*alloc cache set */
21 sets = NULL;
22 lines = NULL;
23 //fprintf(stderr, "mmu_cache_init: mallloc beg size %d,sets 0x%x\n", sizeof(cache_set_t) * set,sets);
24 //exit(-1);
25 sets = (cache_set_t *) malloc (sizeof (cache_set_t) * set);
26 if (sets == NULL) {
27 ERROR_LOG(ARM11, "set malloc size %d\n", sizeof (cache_set_t) * set);
28 goto sets_error;
29 }
30 //fprintf(stderr, "mmu_cache_init: mallloc end sets 0x%x\n", sets);
31 cache_t->sets = sets;
32
33 /*init cache set */
34 for (i = 0; i < set; i++) {
35 /*alloc cache line */
36 lines = (cache_line_t *) malloc (sizeof (cache_line_t) * way);
37 if (lines == NULL) {
38 ERROR_LOG(ARM11, "line malloc size %d\n",
39 sizeof (cache_line_t) * way);
40 goto lines_error;
41 }
42 /*init cache line */
43 for (j = 0; j < way; j++) {
44 lines[j].tag = 0; //invalid
45 lines[j].data = (ARMword *) malloc (width);
46 if (lines[j].data == NULL) {
47 ERROR_LOG(ARM11, "data alloc size %d\n", width);
48 goto data_error;
49 }
50 }
51
52 sets[i].lines = lines;
53 sets[i].cycle = 0;
54
55 }
56 cache_t->width = width;
57 cache_t->set = set;
58 cache_t->way = way;
59 cache_t->w_mode = w_mode;
60 return 0;
61
62 data_error:
63 /*free data */
64 while (j-- > 0)
65 free (lines[j].data);
66 /*free data error line */
67 free (lines);
68 lines_error:
69 /*free lines already alloced */
70 while (i-- > 0) {
71 for (j = 0; j < way; j++)
72 free (sets[i].lines[j].data);
73 free (sets[i].lines);
74 }
75 /*free sets */
76 free (sets);
77 sets_error:
78 return -1;
79};
80
81/* free a cache_t's inner data, the ptr self is not freed,
82 * when needed do like below:
83 * mmu_cache_exit(cache);
84 * free(cache_t);
85 *
86 * @cache_t : the cache_t to free
87 */
88
89void
90mmu_cache_exit (cache_s * cache_t)
91{
92 int i, j;
93 cache_set_t *sets, *set;
94 cache_line_t *lines, *line;
95
96 /*free all set */
97 sets = cache_t->sets;
98 for (set = sets, i = 0; i < cache_t->set; i++, set++) {
99 /*free all line */
100 lines = set->lines;
101 for (line = lines, j = 0; j < cache_t->way; j++, line++)
102 free (line->data);
103 free (lines);
104 }
105 free (sets);
106}
107
108/* mmu cache search
109 *
110 * @state :ARMul_State
111 * @cache_t :cache_t to search
112 * @va :virtual address
113 *
114 * $ NULL: no cache match
115 * cache :cache matched
116 */
117cache_line_t *
118mmu_cache_search (ARMul_State * state, cache_s * cache_t, ARMword va)
119{
120 int i;
121 int set = va_cache_set (va, cache_t);
122 ARMword tag = va_cache_align (va, cache_t);
123 cache_line_t *cache;
124
125 cache_set_t *cache_set = cache_t->sets + set;
126 for (i = 0, cache = cache_set->lines; i < cache_t->way; i++, cache++) {
127 if ((cache->tag & TAG_VALID_FLAG)
128 && (tag == va_cache_align (cache->tag, cache_t)))
129 return cache;
130 }
131 return NULL;
132}
133
134/* mmu cache search by set/index
135 *
136 * @state :ARMul_State
137 * @cache_t :cache_t to search
138 * @index :set/index value.
139 *
140 * $ NULL: no cache match
141 * cache :cache matched
142 */
143cache_line_t *
144mmu_cache_search_by_index (ARMul_State * state, cache_s * cache_t,
145 ARMword index)
146{
147 int way = cache_t->way;
148 int set_v = index_cache_set (index, cache_t);
149 int i = 0, index_v = 0;
150 cache_set_t *set;
151
152 while ((way >>= 1) >= 1)
153 i++;
154 index_v = index >> (32 - i);
155 set = cache_t->sets + set_v;
156
157 return set->lines + index_v;
158}
159
160
161/* mmu cache alloc
162 *
163 * @state :ARMul_State
164 * @cache_t :cache_t to alloc from
165 * @va :virtual address that require cache alloc, need not cache aligned
166 * @pa :physical address of va
167 *
168 * $ cache_alloced, always alloc OK
169 */
170cache_line_t *
171mmu_cache_alloc (ARMul_State * state, cache_s * cache_t, ARMword va,
172 ARMword pa)
173{
174 cache_line_t *cache;
175 cache_set_t *set;
176 int i;
177
178 va = va_cache_align (va, cache_t);
179 pa = va_cache_align (pa, cache_t);
180
181 set = &cache_t->sets[va_cache_set (va, cache_t)];
182
183 /*robin-round */
184 cache = &set->lines[set->cycle++];
185 if (set->cycle == cache_t->way)
186 set->cycle = 0;
187
188 if (cache_t->w_mode == CACHE_WRITE_BACK) {
189 ARMword t;
190
191 /*if cache valid, try to write back */
192 if (cache->tag & TAG_VALID_FLAG) {
193 mmu_cache_write_back (state, cache_t, cache);
194 }
195 /*read in cache_line */
196 t = pa;
197 for (i = 0; i < (cache_t->width >> WORD_SHT);
198 i++, t += WORD_SIZE) {
199 //cache->data[i] = mem_read_word (state, t);
200 bus_read(32, t, &cache->data[i]);
201 }
202 }
203 /*store tag and pa */
204 cache->tag = va | TAG_VALID_FLAG;
205 cache->pa = pa;
206
207 return cache;
208};
209
210/* mmu_cache_write_back write cache data to memory
211 * @state
212 * @cache_t :cache_t of the cache line
213 * @cache : cache line
214 */
215void
216mmu_cache_write_back (ARMul_State * state, cache_s * cache_t,
217 cache_line_t * cache)
218{
219 ARMword pa = cache->pa;
220 int nw = cache_t->width >> WORD_SHT;
221 ARMword *data = cache->data;
222 int i;
223 int t0, t1, t2;
224
225 if ((cache->tag & 1) == 0)
226 return;
227
228 switch (cache->
229 tag & ~1 & (TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY)) {
230 case 0:
231 return;
232 case TAG_FIRST_HALF_DIRTY:
233 nw /= 2;
234 break;
235 case TAG_LAST_HALF_DIRTY:
236 nw /= 2;
237 pa += nw << WORD_SHT;
238 data += nw;
239 break;
240 case TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY:
241 break;
242 }
243 for (i = 0; i < nw; i++, data++, pa += WORD_SIZE)
244 //mem_write_word (state, pa, *data);
245 bus_write(32, pa, *data);
246
247 cache->tag &= ~(TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY);
248};
249
250
251/* mmu_cache_clean: clean a cache of va in cache_t
252 *
253 * @state :ARMul_State
254 * @cache_t :cache_t to clean
255 * @va :virtaul address
256 */
257void
258mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va)
259{
260 cache_line_t *cache;
261
262 cache = mmu_cache_search (state, cache_t, va);
263 if (cache)
264 mmu_cache_write_back (state, cache_t, cache);
265}
266
267/* mmu_cache_clean_by_index: clean a cache by set/index format value
268 *
269 * @state :ARMul_State
270 * @cache_t :cache_t to clean
271 * @va :set/index format value
272 */
273void
274mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t,
275 ARMword index)
276{
277 cache_line_t *cache;
278
279 cache = mmu_cache_search_by_index (state, cache_t, index);
280 if (cache)
281 mmu_cache_write_back (state, cache_t, cache);
282}
283
284/* mmu_cache_invalidate : invalidate a cache of va
285 *
286 * @state :ARMul_State
287 * @cache_t :cache_t to invalid
288 * @va :virt_addr to invalid
289 */
290void
291mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va)
292{
293 cache_line_t *cache;
294
295 cache = mmu_cache_search (state, cache_t, va);
296 if (cache) {
297 mmu_cache_write_back (state, cache_t, cache);
298 cache->tag = 0;
299 }
300}
301
302/* mmu_cache_invalidate_by_index : invalidate a cache by index format
303 *
304 * @state :ARMul_State
305 * @cache_t :cache_t to invalid
306 * @index :set/index data
307 */
308void
309mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t,
310 ARMword index)
311{
312 cache_line_t *cache;
313
314 cache = mmu_cache_search_by_index (state, cache_t, index);
315 if (cache) {
316 mmu_cache_write_back (state, cache_t, cache);
317 cache->tag = 0;
318 }
319}
320
321/* mmu_cache_invalidate_all
322 *
323 * @state:
324 * @cache_t
325 * */
326void
327mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t)
328{
329 int i, j;
330 cache_set_t *set;
331 cache_line_t *cache;
332
333 set = cache_t->sets;
334 for (i = 0; i < cache_t->set; i++, set++) {
335 cache = set->lines;
336 for (j = 0; j < cache_t->way; j++, cache++) {
337 mmu_cache_write_back (state, cache_t, cache);
338 cache->tag = 0;
339 }
340 }
341};
342
343void
344mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa)
345{
346 ARMword set, way;
347 cache_line_t *cache;
348 pa = (pa / cache_t->width);
349 way = pa & (cache_t->way - 1);
350 set = (pa / cache_t->way) & (cache_t->set - 1);
351 cache = &cache_t->sets[set].lines[way];
352
353 mmu_cache_write_back (state, cache_t, cache);
354 cache->tag = 0;
355}
356
357cache_line_t* mmu_cache_dirty_cache(ARMul_State *state,cache_s *cache){
358 int i;
359 int j;
360 cache_line_t *cache_line = NULL;
361 cache_set_t *cache_set = cache->sets;
362 int sets = cache->set;
363 for (i = 0; i < sets; i++){
364 for(j = 0,cache_line = &cache_set[i].lines[0]; j < cache->way; j++,cache_line++){
365 if((cache_line->tag & TAG_FIRST_HALF_DIRTY) || (cache_line->tag & TAG_LAST_HALF_DIRTY))
366 return cache_line;
367 }
368 }
369 return NULL;
370}
diff --git a/src/core/arm/interpreter/mmu/cache.h b/src/core/arm/interpreter/mmu/cache.h
deleted file mode 100644
index d308d9b87..000000000
--- a/src/core/arm/interpreter/mmu/cache.h
+++ /dev/null
@@ -1,168 +0,0 @@
1#ifndef _MMU_CACHE_H_
2#define _MMU_CACHE_H_
3
4typedef struct cache_line_t
5{
6 ARMword tag; /* cache line align address |
7 bit2: last half dirty
8 bit1: first half dirty
9 bit0: cache valid flag
10 */
11 ARMword pa; /*physical address */
12 ARMword *data; /*array of cached data */
13} cache_line_t;
14#define TAG_VALID_FLAG 0x00000001
15#define TAG_FIRST_HALF_DIRTY 0x00000002
16#define TAG_LAST_HALF_DIRTY 0x00000004
17
18/*cache set association*/
19typedef struct cache_set_s
20{
21 cache_line_t *lines;
22 int cycle;
23} cache_set_t;
24
25enum
26{
27 CACHE_WRITE_BACK,
28 CACHE_WRITE_THROUGH,
29};
30
31typedef struct cache_s
32{
33 int width; /*bytes in a line */
34 int way; /*way of set asscociate */
35 int set; /*num of set */
36 int w_mode; /*write back or write through */
37 //int a_mode; /*alloc mode: random or round-bin*/
38 cache_set_t *sets;
39 /**/} cache_s;
40
41typedef struct cache_desc_s
42{
43 int width;
44 int way;
45 int set;
46 int w_mode;
47// int a_mode;
48} cache_desc_t;
49
50
51/*virtual address to cache set index*/
52#define va_cache_set(va, cache_t) \
53 (((va) / (cache_t)->width) & ((cache_t)->set - 1))
54/*virtual address to cahce line aligned*/
55#define va_cache_align(va, cache_t) \
56 ((va) & ~((cache_t)->width - 1))
57/*virtaul address to cache line word index*/
58#define va_cache_index(va, cache_t) \
59 (((va) & ((cache_t)->width - 1)) >> WORD_SHT)
60
61/*see Page 558 in arm manual*/
62/*set/index format value to cache set value*/
63#define index_cache_set(index, cache_t) \
64 (((index) / (cache_t)->width) & ((cache_t)->set - 1))
65
66/*************************cache********************/
67/* mmu cache init
68 *
69 * @cache_t :cache_t to init
70 * @width :cache line width in byte
71 * @way :way of each cache set
72 * @set :cache set num
73 * @w_mode :cache w_mode
74 *
75 * $ -1: error
76 * 0: sucess
77 */
78int
79mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode);
80
81/* free a cache_t's inner data, the ptr self is not freed,
82 * when needed do like below:
83 * mmu_cache_exit(cache);
84 * free(cache_t);
85 *
86 * @cache_t : the cache_t to free
87 */
88void mmu_cache_exit (cache_s * cache_t);
89
90/* mmu cache search
91 *
92 * @state :ARMul_State
93 * @cache_t :cache_t to search
94 * @va :virtual address
95 *
96 * $ NULL: no cache match
97 * cache :cache matched
98 * */
99cache_line_t *mmu_cache_search (ARMul_State * state, cache_s * cache_t,
100 ARMword va);
101
102/* mmu cache search by set/index
103 *
104 * @state :ARMul_State
105 * @cache_t :cache_t to search
106 * @index :set/index value.
107 *
108 * $ NULL: no cache match
109 * cache :cache matched
110 * */
111
112cache_line_t *mmu_cache_search_by_index (ARMul_State * state,
113 cache_s * cache_t, ARMword index);
114
115/* mmu cache alloc
116 *
117 * @state :ARMul_State
118 * @cache_t :cache_t to alloc from
119 * @va :virtual address that require cache alloc, need not cache aligned
120 * @pa :physical address of va
121 *
122 * $ cache_alloced, always alloc OK
123 */
124cache_line_t *mmu_cache_alloc (ARMul_State * state, cache_s * cache_t,
125 ARMword va, ARMword pa);
126
127/* mmu_cache_write_back write cache data to memory
128 *
129 * @state:
130 * @cache_t :cache_t of the cache line
131 * @cache : cache line
132 */
133void
134mmu_cache_write_back (ARMul_State * state, cache_s * cache_t,
135 cache_line_t * cache);
136
137/* mmu_cache_clean: clean a cache of va in cache_t
138 *
139 * @state :ARMul_State
140 * @cache_t :cache_t to clean
141 * @va :virtaul address
142 */
143void mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va);
144void
145mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t,
146 ARMword index);
147
148/* mmu_cache_invalidate : invalidate a cache of va
149 *
150 * @state :ARMul_State
151 * @cache_t :cache_t to invalid
152 * @va :virt_addr to invalid
153 */
154void
155mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va);
156
157void
158mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t,
159 ARMword index);
160
161void mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t);
162
163void
164mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa);
165
166cache_line_t* mmu_cache_dirty_cache(ARMul_State * state, cache_s * cache_t);
167
168#endif /*_MMU_CACHE_H_*/
diff --git a/src/core/arm/interpreter/mmu/maverick.cpp b/src/core/arm/interpreter/mmu/maverick.cpp
deleted file mode 100644
index adcc2efb5..000000000
--- a/src/core/arm/interpreter/mmu/maverick.cpp
+++ /dev/null
@@ -1,1206 +0,0 @@
1/* maverick.c -- Cirrus/DSP co-processor interface.
2 Copyright (C) 2003 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez (aldyh@redhat.com).
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19#include <assert.h>
20
21#include "core/arm/interpreter/armdefs.h"
22#include "core/arm/interpreter/armemu.h"
23
24
25/*#define CIRRUS_DEBUG 1 */
26#if CIRRUS_DEBUG
27# define printfdbg printf
28#else
29# define printfdbg printf_nothing
30#endif
31
32#define POS64(i) ( (~(i)) >> 63 )
33#define NEG64(i) ( (i) >> 63 )
34
35/* Define Co-Processor instruction handlers here. */
36
37/* Here's ARMulator's DSP definition. A few things to note:
38 1) it has 16 64-bit registers and 4 72-bit accumulators
39 2) you can only access its registers with MCR and MRC. */
40
41/* We can't define these in here because this file might not be linked
42 unless the target is arm9e-*. They are defined in wrapper.c.
43 Eventually the simulator should be made to handle any coprocessor
44 at run time. */
45struct maverick_regs
46{
47 union
48 {
49 int i;
50 float f;
51 } upper;
52
53 union
54 {
55 int i;
56 float f;
57 } lower;
58};
59
60union maverick_acc_regs
61{
62 long double ld; /* Acc registers are 72-bits. */
63};
64
65struct maverick_regs DSPregs[16];
66union maverick_acc_regs DSPacc[4];
67ARMword DSPsc;
68
69#define DEST_REG (BITS (12, 15))
70#define SRC1_REG (BITS (16, 19))
71#define SRC2_REG (BITS (0, 3))
72
73static int lsw_int_index, msw_int_index;
74static int lsw_float_index, msw_float_index;
75
76static double mv_getRegDouble (int);
77static long long mv_getReg64int (int);
78static void mv_setRegDouble (int, double val);
79static void mv_setReg64int (int, long long val);
80
81static union
82{
83 double d;
84 long long ll;
85 int ints[2];
86} reg_conv;
87
88static void
89printf_nothing (const char *foo, ...)
90{
91}
92
93static void
94cirrus_not_implemented (const char *insn)
95{
96 fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
97 fprintf (stderr, "aborting!\n");
98
99 // skyeye_exit (1);
100}
101
102static unsigned
103DSPInit (ARMul_State * state)
104{
105 NOTICE_LOG(ARM11, "ARMul_ConsolePrint: DSP present");
106 return TRUE;
107}
108
109unsigned
110DSPMRC4 (ARMul_State * state,
111 unsigned type, ARMword instr, ARMword * value)
112{
113 switch (BITS (5, 7)) {
114 case 0: /* cfmvrdl */
115 /* Move lower half of a DF stored in a DSP reg into an Arm reg. */
116 printfdbg ("cfmvrdl\n");
117 printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i);
118 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
119
120 *value = (ARMword) DSPregs[SRC1_REG].lower.i;
121 break;
122
123 case 1: /* cfmvrdh */
124 /* Move upper half of a DF stored in a DSP reg into an Arm reg. */
125 printfdbg ("cfmvrdh\n");
126 printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i);
127 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
128
129 *value = (ARMword) DSPregs[SRC1_REG].upper.i;
130 break;
131
132 case 2: /* cfmvrs */
133 /* Move SF from upper half of a DSP register to an Arm register. */
134 *value = (ARMword) DSPregs[SRC1_REG].upper.i;
135 printfdbg ("cfmvrs = mvf%d <-- %f\n",
136 SRC1_REG, DSPregs[SRC1_REG].upper.f);
137 break;
138
139#ifdef doesnt_work
140 case 4: /* cfcmps */
141 {
142 float a, b;
143 int n, z, c, v;
144
145 a = DSPregs[SRC1_REG].upper.f;
146 b = DSPregs[SRC2_REG].upper.f;
147
148 printfdbg ("cfcmps\n");
149 printfdbg ("\tcomparing %f and %f\n", a, b);
150
151 z = a == b; /* zero */
152 n = a != b; /* negative */
153 v = a > b; /* overflow */
154 c = 0; /* carry */
155 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
156 28);
157 break;
158 }
159
160 case 5: /* cfcmpd */
161 {
162 double a, b;
163 int n, z, c, v;
164
165 a = mv_getRegDouble (SRC1_REG);
166 b = mv_getRegDouble (SRC2_REG);
167
168 printfdbg ("cfcmpd\n");
169 printfdbg ("\tcomparing %g and %g\n", a, b);
170
171 z = a == b; /* zero */
172 n = a != b; /* negative */
173 v = a > b; /* overflow */
174 c = 0; /* carry */
175 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
176 28);
177 break;
178 }
179#else
180 case 4: /* cfcmps */
181 {
182 float a, b;
183 int n, z, c, v;
184
185 a = DSPregs[SRC1_REG].upper.f;
186 b = DSPregs[SRC2_REG].upper.f;
187
188 printfdbg ("cfcmps\n");
189 printfdbg ("\tcomparing %f and %f\n", a, b);
190
191 z = a == b; /* zero */
192 n = a < b; /* negative */
193 c = a > b; /* carry */
194 v = 0; /* fixme */
195 printfdbg ("\tz = %d, n = %d\n", z, n);
196 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
197 28);
198 break;
199 }
200
201 case 5: /* cfcmpd */
202 {
203 double a, b;
204 int n, z, c, v;
205
206 a = mv_getRegDouble (SRC1_REG);
207 b = mv_getRegDouble (SRC2_REG);
208
209 printfdbg ("cfcmpd\n");
210 printfdbg ("\tcomparing %g and %g\n", a, b);
211
212 z = a == b; /* zero */
213 n = a < b; /* negative */
214 c = a > b; /* carry */
215 v = 0; /* fixme */
216 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
217 28);
218 break;
219 }
220#endif
221 default:
222 fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
223 cirrus_not_implemented ("unknown");
224 break;
225 }
226
227 return ARMul_DONE;
228}
229
230unsigned
231DSPMRC5 (ARMul_State * state,
232 unsigned type, ARMword instr, ARMword * value)
233{
234 switch (BITS (5, 7)) {
235 case 0: /* cfmvr64l */
236 /* Move lower half of 64bit int from Cirrus to Arm. */
237 *value = (ARMword) DSPregs[SRC1_REG].lower.i;
238 printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
239 DEST_REG, (int) *value);
240 break;
241
242 case 1: /* cfmvr64h */
243 /* Move upper half of 64bit int from Cirrus to Arm. */
244 *value = (ARMword) DSPregs[SRC1_REG].upper.i;
245 printfdbg ("cfmvr64h <-- %d\n", (int) *value);
246 break;
247
248 case 4: /* cfcmp32 */
249 {
250 int res;
251 int n, z, c, v;
252 unsigned int a, b;
253
254 printfdbg ("cfcmp32 mvfx%d - mvfx%d\n", SRC1_REG,
255 SRC2_REG);
256
257 /* FIXME: see comment for cfcmps. */
258 a = DSPregs[SRC1_REG].lower.i;
259 b = DSPregs[SRC2_REG].lower.i;
260
261 res = DSPregs[SRC1_REG].lower.i -
262 DSPregs[SRC2_REG].lower.i;
263 /* zero */
264 z = res == 0;
265 /* negative */
266 n = res < 0;
267 /* overflow */
268 v = SubOverflow (DSPregs[SRC1_REG].lower.i,
269 DSPregs[SRC2_REG].lower.i, res);
270 /* carry */
271 c = (NEG (a) && POS (b) ||
272 (NEG (a) && POS (res)) || (POS (b)
273 && POS (res)));
274
275 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
276 28);
277 break;
278 }
279
280 case 5: /* cfcmp64 */
281 {
282 long long res;
283 int n, z, c, v;
284 unsigned long long a, b;
285
286 printfdbg ("cfcmp64 mvdx%d - mvdx%d\n", SRC1_REG,
287 SRC2_REG);
288
289 /* fixme: see comment for cfcmps. */
290
291 a = mv_getReg64int (SRC1_REG);
292 b = mv_getReg64int (SRC2_REG);
293
294 res = mv_getReg64int (SRC1_REG) -
295 mv_getReg64int (SRC2_REG);
296 /* zero */
297 z = res == 0;
298 /* negative */
299 n = res < 0;
300 /* overflow */
301 v = ((NEG64 (a) && POS64 (b) && POS64 (res))
302 || (POS64 (a) && NEG64 (b) && NEG64 (res)));
303 /* carry */
304 c = (NEG64 (a) && POS64 (b) ||
305 (NEG64 (a) && POS64 (res)) || (POS64 (b)
306 && POS64 (res)));
307
308 *value = (n << 31) | (z << 30) | (c << 29) | (v <<
309 28);
310 break;
311 }
312
313 default:
314 fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
315 cirrus_not_implemented ("unknown");
316 break;
317 }
318
319 return ARMul_DONE;
320}
321
322unsigned
323DSPMRC6 (ARMul_State * state,
324 unsigned type, ARMword instr, ARMword * value)
325{
326 switch (BITS (5, 7)) {
327 case 0: /* cfmval32 */
328 cirrus_not_implemented ("cfmval32");
329 break;
330
331 case 1: /* cfmvam32 */
332 cirrus_not_implemented ("cfmvam32");
333 break;
334
335 case 2: /* cfmvah32 */
336 cirrus_not_implemented ("cfmvah32");
337 break;
338
339 case 3: /* cfmva32 */
340 cirrus_not_implemented ("cfmva32");
341 break;
342
343 case 4: /* cfmva64 */
344 cirrus_not_implemented ("cfmva64");
345 break;
346
347 case 5: /* cfmvsc32 */
348 cirrus_not_implemented ("cfmvsc32");
349 break;
350
351 default:
352 fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
353 cirrus_not_implemented ("unknown");
354 break;
355 }
356
357 return ARMul_DONE;
358}
359
360unsigned
361DSPMCR4 (ARMul_State * state,
362 unsigned type, ARMword instr, ARMword value)
363{
364 switch (BITS (5, 7)) {
365 case 0: /* cfmvdlr */
366 /* Move the lower half of a DF value from an Arm register into
367 the lower half of a Cirrus register. */
368 printfdbg ("cfmvdlr <-- 0x%x\n", (int) value);
369 DSPregs[SRC1_REG].lower.i = (int) value;
370 break;
371
372 case 1: /* cfmvdhr */
373 /* Move the upper half of a DF value from an Arm register into
374 the upper half of a Cirrus register. */
375 printfdbg ("cfmvdhr <-- 0x%x\n", (int) value);
376 DSPregs[SRC1_REG].upper.i = (int) value;
377 break;
378
379 case 2: /* cfmvsr */
380 /* Move SF from Arm register into upper half of Cirrus register. */
381 printfdbg ("cfmvsr <-- 0x%x\n", (int) value);
382 DSPregs[SRC1_REG].upper.i = (int) value;
383 break;
384
385 default:
386 fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
387 cirrus_not_implemented ("unknown");
388 break;
389 }
390
391 return ARMul_DONE;
392}
393
394unsigned
395DSPMCR5 (ARMul_State * state,
396 unsigned type, ARMword instr, ARMword value)
397{
398 union
399 {
400 int s;
401 unsigned int us;
402 } val;
403
404 switch (BITS (5, 7)) {
405 case 0: /* cfmv64lr */
406 /* Move lower half of a 64bit int from an ARM register into the
407 lower half of a DSP register and sign extend it. */
408 printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG,
409 (int) value);
410 DSPregs[SRC1_REG].lower.i = (int) value;
411 break;
412
413 case 1: /* cfmv64hr */
414 /* Move upper half of a 64bit int from an ARM register into the
415 upper half of a DSP register. */
416 printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
417 SRC1_REG, (int) value);
418 DSPregs[SRC1_REG].upper.i = (int) value;
419 break;
420
421 case 2: /* cfrshl32 */
422 printfdbg ("cfrshl32\n");
423 val.us = value;
424 if (val.s > 0)
425 DSPregs[SRC2_REG].lower.i =
426 DSPregs[SRC1_REG].lower.i << value;
427 else
428 DSPregs[SRC2_REG].lower.i =
429 DSPregs[SRC1_REG].lower.i >> -value;
430 break;
431
432 case 3: /* cfrshl64 */
433 printfdbg ("cfrshl64\n");
434 val.us = value;
435 if (val.s > 0)
436 mv_setReg64int (SRC2_REG,
437 mv_getReg64int (SRC1_REG) << value);
438 else
439 mv_setReg64int (SRC2_REG,
440 mv_getReg64int (SRC1_REG) >> -value);
441 break;
442
443 default:
444 fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
445 cirrus_not_implemented ("unknown");
446 break;
447 }
448
449 return ARMul_DONE;
450}
451
452unsigned
453DSPMCR6 (ARMul_State * state,
454 unsigned type, ARMword instr, ARMword value)
455{
456 switch (BITS (5, 7)) {
457 case 0: /* cfmv32al */
458 cirrus_not_implemented ("cfmv32al");
459 break;
460
461 case 1: /* cfmv32am */
462 cirrus_not_implemented ("cfmv32am");
463 break;
464
465 case 2: /* cfmv32ah */
466 cirrus_not_implemented ("cfmv32ah");
467 break;
468
469 case 3: /* cfmv32a */
470 cirrus_not_implemented ("cfmv32a");
471 break;
472
473 case 4: /* cfmv64a */
474 cirrus_not_implemented ("cfmv64a");
475 break;
476
477 case 5: /* cfmv32sc */
478 cirrus_not_implemented ("cfmv32sc");
479 break;
480
481 default:
482 fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
483 cirrus_not_implemented ("unknown");
484 break;
485 }
486
487 return ARMul_DONE;
488}
489
490unsigned
491DSPLDC4 (ARMul_State * state,
492 unsigned type, ARMword instr, ARMword data)
493{
494 static unsigned words;
495
496 if (type != ARMul_DATA) {
497 words = 0;
498 return ARMul_DONE;
499 }
500
501 if (BIT (22)) { /* it's a long access, get two words */
502 /* cfldrd */
503
504 printfdbg
505 ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
506 data, words, state->bigendSig, DEST_REG);
507
508 if (words == 0) {
509 if (state->bigendSig)
510 DSPregs[DEST_REG].upper.i = (int) data;
511 else
512 DSPregs[DEST_REG].lower.i = (int) data;
513 }
514 else {
515 if (state->bigendSig)
516 DSPregs[DEST_REG].lower.i = (int) data;
517 else
518 DSPregs[DEST_REG].upper.i = (int) data;
519 }
520
521 ++words;
522
523 if (words == 2) {
524 printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
525 mv_getRegDouble (DEST_REG));
526
527 return ARMul_DONE;
528 }
529 else
530 return ARMul_INC;
531 }
532 else {
533 /* Get just one word. */
534
535 /* cfldrs */
536 printfdbg ("cfldrs\n");
537
538 DSPregs[DEST_REG].upper.i = (int) data;
539
540 printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
541 DSPregs[DEST_REG].upper.f);
542
543 return ARMul_DONE;
544 }
545}
546
547unsigned
548DSPLDC5 (ARMul_State * state,
549 unsigned type, ARMword instr, ARMword data)
550{
551 static unsigned words;
552
553 if (type != ARMul_DATA) {
554 words = 0;
555 return ARMul_DONE;
556 }
557
558 if (BIT (22)) {
559 /* It's a long access, get two words. */
560
561 /* cfldr64 */
562 printfdbg ("cfldr64: %d\n", data);
563
564 if (words == 0) {
565 if (state->bigendSig)
566 DSPregs[DEST_REG].upper.i = (int) data;
567 else
568 DSPregs[DEST_REG].lower.i = (int) data;
569 }
570 else {
571 if (state->bigendSig)
572 DSPregs[DEST_REG].lower.i = (int) data;
573 else
574 DSPregs[DEST_REG].upper.i = (int) data;
575 }
576
577 ++words;
578
579 if (words == 2) {
580 printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
581 mv_getReg64int (DEST_REG));
582
583 return ARMul_DONE;
584 }
585 else
586 return ARMul_INC;
587 }
588 else {
589 /* Get just one word. */
590
591 /* cfldr32 */
592 printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
593
594 /* 32bit ints should be sign extended to 64bits when loaded. */
595 mv_setReg64int (DEST_REG, (long long) data);
596
597 return ARMul_DONE;
598 }
599}
600
601unsigned
602DSPSTC4 (ARMul_State * state,
603 unsigned type, ARMword instr, ARMword * data)
604{
605 static unsigned words;
606
607 if (type != ARMul_DATA) {
608 words = 0;
609 return ARMul_DONE;
610 }
611
612 if (BIT (22)) {
613 /* It's a long access, get two words. */
614 /* cfstrd */
615 printfdbg ("cfstrd\n");
616
617 if (words == 0) {
618 if (state->bigendSig)
619 *data = (ARMword) DSPregs[DEST_REG].upper.i;
620 else
621 *data = (ARMword) DSPregs[DEST_REG].lower.i;
622 }
623 else {
624 if (state->bigendSig)
625 *data = (ARMword) DSPregs[DEST_REG].lower.i;
626 else
627 *data = (ARMword) DSPregs[DEST_REG].upper.i;
628 }
629
630 ++words;
631
632 if (words == 2) {
633 printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
634 mv_getRegDouble (DEST_REG));
635
636 return ARMul_DONE;
637 }
638 else
639 return ARMul_INC;
640 }
641 else {
642 /* Get just one word. */
643 /* cfstrs */
644 printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
645 DSPregs[DEST_REG].upper.f);
646
647 *data = (ARMword) DSPregs[DEST_REG].upper.i;
648
649 return ARMul_DONE;
650 }
651}
652
653unsigned
654DSPSTC5 (ARMul_State * state,
655 unsigned type, ARMword instr, ARMword * data)
656{
657 static unsigned words;
658
659 if (type != ARMul_DATA) {
660 words = 0;
661 return ARMul_DONE;
662 }
663
664 if (BIT (22)) {
665 /* It's a long access, store two words. */
666 /* cfstr64 */
667 printfdbg ("cfstr64\n");
668
669 if (words == 0) {
670 if (state->bigendSig)
671 *data = (ARMword) DSPregs[DEST_REG].upper.i;
672 else
673 *data = (ARMword) DSPregs[DEST_REG].lower.i;
674 }
675 else {
676 if (state->bigendSig)
677 *data = (ARMword) DSPregs[DEST_REG].lower.i;
678 else
679 *data = (ARMword) DSPregs[DEST_REG].upper.i;
680 }
681
682 ++words;
683
684 if (words == 2) {
685 printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
686 mv_getReg64int (DEST_REG));
687
688 return ARMul_DONE;
689 }
690 else
691 return ARMul_INC;
692 }
693 else {
694 /* Store just one word. */
695 /* cfstr32 */
696 *data = (ARMword) DSPregs[DEST_REG].lower.i;
697
698 printfdbg ("cfstr32 MEM = %d\n", (int) *data);
699
700 return ARMul_DONE;
701 }
702}
703
704unsigned
705DSPCDP4 (ARMul_State * state, unsigned type, ARMword instr)
706{
707 int opcode2;
708
709 opcode2 = BITS (5, 7);
710
711 switch (BITS (20, 21)) {
712 case 0:
713 switch (opcode2) {
714 case 0: /* cfcpys */
715 printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
716 DEST_REG, SRC1_REG,
717 DSPregs[SRC1_REG].upper.f);
718 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f;
719 break;
720
721 case 1: /* cfcpyd */
722 printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
723 DEST_REG, SRC1_REG,
724 mv_getRegDouble (SRC1_REG));
725 mv_setRegDouble (DEST_REG,
726 mv_getRegDouble (SRC1_REG));
727 break;
728
729 case 2: /* cfcvtds */
730 printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
731 DEST_REG, SRC1_REG,
732 (float) mv_getRegDouble (SRC1_REG));
733 DSPregs[DEST_REG].upper.f =
734 (float) mv_getRegDouble (SRC1_REG);
735 break;
736
737 case 3: /* cfcvtsd */
738 printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
739 DEST_REG, SRC1_REG,
740 (double) DSPregs[SRC1_REG].upper.f);
741 mv_setRegDouble (DEST_REG,
742 (double) DSPregs[SRC1_REG].upper.f);
743 break;
744
745 case 4: /* cfcvt32s */
746 printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
747 DEST_REG, SRC1_REG,
748 (float) DSPregs[SRC1_REG].lower.i);
749 DSPregs[DEST_REG].upper.f =
750 (float) DSPregs[SRC1_REG].lower.i;
751 break;
752
753 case 5: /* cfcvt32d */
754 printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
755 DEST_REG, SRC1_REG,
756 (double) DSPregs[SRC1_REG].lower.i);
757 mv_setRegDouble (DEST_REG,
758 (double) DSPregs[SRC1_REG].lower.i);
759 break;
760
761 case 6: /* cfcvt64s */
762 printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
763 DEST_REG, SRC1_REG,
764 (float) mv_getReg64int (SRC1_REG));
765 DSPregs[DEST_REG].upper.f =
766 (float) mv_getReg64int (SRC1_REG);
767 break;
768
769 case 7: /* cfcvt64d */
770 printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
771 DEST_REG, SRC1_REG,
772 (double) mv_getReg64int (SRC1_REG));
773 mv_setRegDouble (DEST_REG,
774 (double) mv_getReg64int (SRC1_REG));
775 break;
776 }
777 break;
778
779 case 1:
780 switch (opcode2) {
781 case 0: /* cfmuls */
782 printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
783 DEST_REG,
784 SRC1_REG,
785 DSPregs[SRC1_REG].upper.f *
786 DSPregs[SRC2_REG].upper.f);
787
788 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
789 * DSPregs[SRC2_REG].upper.f;
790 break;
791
792 case 1: /* cfmuld */
793 printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
794 DEST_REG,
795 SRC1_REG,
796 mv_getRegDouble (SRC1_REG) *
797 mv_getRegDouble (SRC2_REG));
798
799 mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG)
800 * mv_getRegDouble (SRC2_REG));
801 break;
802
803 default:
804 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n",
805 instr);
806 cirrus_not_implemented ("unknown");
807 break;
808 }
809 break;
810
811 case 3:
812 switch (opcode2) {
813 case 0: /* cfabss */
814 DSPregs[DEST_REG].upper.f =
815 (DSPregs[SRC1_REG].upper.f <
816 0.0F ? -DSPregs[SRC1_REG].upper.
817 f : DSPregs[SRC1_REG].upper.f);
818 printfdbg ("cfabss mvf%d = |mvf%d| = %f\n", DEST_REG,
819 SRC1_REG, DSPregs[DEST_REG].upper.f);
820 break;
821
822 case 1: /* cfabsd */
823 mv_setRegDouble (DEST_REG,
824 (mv_getRegDouble (SRC1_REG) < 0.0 ?
825 -mv_getRegDouble (SRC1_REG)
826 : mv_getRegDouble (SRC1_REG)));
827 printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
828 DEST_REG, SRC1_REG,
829 mv_getRegDouble (DEST_REG));
830 break;
831
832 case 2: /* cfnegs */
833 DSPregs[DEST_REG].upper.f =
834 -DSPregs[SRC1_REG].upper.f;
835 printfdbg ("cfnegs mvf%d = -mvf%d = %f\n", DEST_REG,
836 SRC1_REG, DSPregs[DEST_REG].upper.f);
837 break;
838
839 case 3: /* cfnegd */
840 mv_setRegDouble (DEST_REG,
841 -mv_getRegDouble (SRC1_REG));
842 printfdbg ("cfnegd mvd%d = -mvd%d = %g\n", DEST_REG,
843 mv_getRegDouble (DEST_REG));
844 break;
845
846 case 4: /* cfadds */
847 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
848 + DSPregs[SRC2_REG].upper.f;
849 printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
850 DEST_REG, SRC1_REG, SRC2_REG,
851 DSPregs[DEST_REG].upper.f);
852 break;
853
854 case 5: /* cfaddd */
855 mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG)
856 + mv_getRegDouble (SRC2_REG));
857 printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
858 DEST_REG,
859 SRC1_REG, SRC2_REG,
860 mv_getRegDouble (DEST_REG));
861 break;
862
863 case 6: /* cfsubs */
864 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
865 - DSPregs[SRC2_REG].upper.f;
866 printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
867 DEST_REG, SRC1_REG, SRC2_REG,
868 DSPregs[DEST_REG].upper.f);
869 break;
870
871 case 7: /* cfsubd */
872 mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG)
873 - mv_getRegDouble (SRC2_REG));
874 printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
875 DEST_REG,
876 SRC1_REG, SRC2_REG,
877 mv_getRegDouble (DEST_REG));
878 break;
879 }
880 break;
881
882 default:
883 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
884 cirrus_not_implemented ("unknown");
885 break;
886 }
887
888 return ARMul_DONE;
889}
890
891unsigned
892DSPCDP5 (ARMul_State * state, unsigned type, ARMword instr)
893{
894 int opcode2;
895 char shift;
896
897 opcode2 = BITS (5, 7);
898
899 /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */
900 shift = BITS (0, 3) | (BITS (5, 7)) << 4;
901 if (shift & 0x40)
902 shift |= 0xc0;
903
904 switch (BITS (20, 21)) {
905 case 0:
906 /* cfsh32 */
907 printfdbg ("cfsh32 %s amount=%d\n",
908 shift < 0 ? "right" : "left", shift);
909 if (shift < 0)
910 /* Negative shift is a right shift. */
911 DSPregs[DEST_REG].lower.i =
912 DSPregs[SRC1_REG].lower.i >> -shift;
913 else
914 /* Positive shift is a left shift. */
915 DSPregs[DEST_REG].lower.i =
916 DSPregs[SRC1_REG].lower.i << shift;
917 break;
918
919 case 1:
920 switch (opcode2) {
921 case 0: /* cfmul32 */
922 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
923 * DSPregs[SRC2_REG].lower.i;
924 printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
925 DEST_REG, SRC1_REG, SRC2_REG,
926 DSPregs[DEST_REG].lower.i);
927 break;
928
929 case 1: /* cfmul64 */
930 mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG)
931 * mv_getReg64int (SRC2_REG));
932 printfdbg
933 ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
934 DEST_REG, SRC1_REG, SRC2_REG,
935 mv_getReg64int (DEST_REG));
936 break;
937
938 case 2: /* cfmac32 */
939 DSPregs[DEST_REG].lower.i
940 +=
941 DSPregs[SRC1_REG].lower.i *
942 DSPregs[SRC2_REG].lower.i;
943 printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
944 DEST_REG, SRC1_REG, SRC2_REG,
945 DSPregs[DEST_REG].lower.i);
946 break;
947
948 case 3: /* cfmsc32 */
949 DSPregs[DEST_REG].lower.i
950 -=
951 DSPregs[SRC1_REG].lower.i *
952 DSPregs[SRC2_REG].lower.i;
953 printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
954 DEST_REG, SRC1_REG, SRC2_REG,
955 DSPregs[DEST_REG].lower.i);
956 break;
957
958 case 4: /* cfcvts32 */
959 /* fixme: this should round */
960 DSPregs[DEST_REG].lower.i =
961 (int) DSPregs[SRC1_REG].upper.f;
962 printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n", DEST_REG,
963 SRC1_REG, DSPregs[DEST_REG].lower.i);
964 break;
965
966 case 5: /* cfcvtd32 */
967 /* fixme: this should round */
968 DSPregs[DEST_REG].lower.i =
969 (int) mv_getRegDouble (SRC1_REG);
970 printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n", DEST_REG,
971 SRC1_REG, DSPregs[DEST_REG].lower.i);
972 break;
973
974 case 6: /* cftruncs32 */
975 DSPregs[DEST_REG].lower.i =
976 (int) DSPregs[SRC1_REG].upper.f;
977 printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
978 DEST_REG, SRC1_REG,
979 DSPregs[DEST_REG].lower.i);
980 break;
981
982 case 7: /* cftruncd32 */
983 DSPregs[DEST_REG].lower.i =
984 (int) mv_getRegDouble (SRC1_REG);
985 printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
986 DEST_REG, SRC1_REG,
987 DSPregs[DEST_REG].lower.i);
988 break;
989 }
990 break;
991
992 case 2:
993 /* cfsh64 */
994 printfdbg ("cfsh64\n");
995
996 if (shift < 0)
997 /* Negative shift is a right shift. */
998 mv_setReg64int (DEST_REG,
999 mv_getReg64int (SRC1_REG) >> -shift);
1000 else
1001 /* Positive shift is a left shift. */
1002 mv_setReg64int (DEST_REG,
1003 mv_getReg64int (SRC1_REG) << shift);
1004 printfdbg ("\t%llx\n", mv_getReg64int (DEST_REG));
1005 break;
1006
1007 case 3:
1008 switch (opcode2) {
1009 case 0: /* cfabs32 */
1010 DSPregs[DEST_REG].lower.i =
1011 (DSPregs[SRC1_REG].lower.i <
1012 0 ? -DSPregs[SRC1_REG].lower.
1013 i : DSPregs[SRC1_REG].lower.i);
1014 printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
1015 DEST_REG, SRC1_REG, SRC2_REG,
1016 DSPregs[DEST_REG].lower.i);
1017 break;
1018
1019 case 1: /* cfabs64 */
1020 mv_setReg64int (DEST_REG,
1021 (mv_getReg64int (SRC1_REG) < 0
1022 ? -mv_getReg64int (SRC1_REG)
1023 : mv_getReg64int (SRC1_REG)));
1024 printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
1025 DEST_REG, SRC1_REG, SRC2_REG,
1026 mv_getReg64int (DEST_REG));
1027 break;
1028
1029 case 2: /* cfneg32 */
1030 DSPregs[DEST_REG].lower.i =
1031 -DSPregs[SRC1_REG].lower.i;
1032 printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
1033 DEST_REG, SRC1_REG, SRC2_REG,
1034 DSPregs[DEST_REG].lower.i);
1035 break;
1036
1037 case 3: /* cfneg64 */
1038 mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG));
1039 printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
1040 DEST_REG, SRC1_REG, SRC2_REG,
1041 mv_getReg64int (DEST_REG));
1042 break;
1043
1044 case 4: /* cfadd32 */
1045 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
1046 + DSPregs[SRC2_REG].lower.i;
1047 printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
1048 DEST_REG, SRC1_REG, SRC2_REG,
1049 DSPregs[DEST_REG].lower.i);
1050 break;
1051
1052 case 5: /* cfadd64 */
1053 mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG)
1054 + mv_getReg64int (SRC2_REG));
1055 printfdbg
1056 ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
1057 DEST_REG, SRC1_REG, SRC2_REG,
1058 mv_getReg64int (DEST_REG));
1059 break;
1060
1061 case 6: /* cfsub32 */
1062 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
1063 - DSPregs[SRC2_REG].lower.i;
1064 printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
1065 DEST_REG, SRC1_REG, SRC2_REG,
1066 DSPregs[DEST_REG].lower.i);
1067 break;
1068
1069 case 7: /* cfsub64 */
1070 mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG)
1071 - mv_getReg64int (SRC2_REG));
1072 printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
1073 DEST_REG, SRC1_REG, SRC2_REG,
1074 mv_getReg64int (DEST_REG));
1075 break;
1076 }
1077 break;
1078
1079 default:
1080 fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
1081 cirrus_not_implemented ("unknown");
1082 break;
1083 }
1084
1085 return ARMul_DONE;
1086}
1087
1088unsigned
1089DSPCDP6 (ARMul_State * state, unsigned type, ARMword instr)
1090{
1091 int opcode2;
1092
1093 opcode2 = BITS (5, 7);
1094
1095 switch (BITS (20, 21)) {
1096 case 0:
1097 /* cfmadd32 */
1098 cirrus_not_implemented ("cfmadd32");
1099 break;
1100
1101 case 1:
1102 /* cfmsub32 */
1103 cirrus_not_implemented ("cfmsub32");
1104 break;
1105
1106 case 2:
1107 /* cfmadda32 */
1108 cirrus_not_implemented ("cfmadda32");
1109 break;
1110
1111 case 3:
1112 /* cfmsuba32 */
1113 cirrus_not_implemented ("cfmsuba32");
1114 break;
1115
1116 default:
1117 fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
1118 }
1119
1120 return ARMul_DONE;
1121}
1122
1123/* Conversion functions.
1124
1125 32-bit integers are stored in the LOWER half of a 64-bit physical
1126 register.
1127
1128 Single precision floats are stored in the UPPER half of a 64-bit
1129 physical register. */
1130
1131static double
1132mv_getRegDouble (int regnum)
1133{
1134 reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i;
1135 reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i;
1136 return reg_conv.d;
1137}
1138
1139static void
1140mv_setRegDouble (int regnum, double val)
1141{
1142 reg_conv.d = val;
1143 DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index];
1144 DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index];
1145}
1146
1147static long long
1148mv_getReg64int (int regnum)
1149{
1150 reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i;
1151 reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i;
1152 return reg_conv.ll;
1153}
1154
1155static void
1156mv_setReg64int (int regnum, long long val)
1157{
1158 reg_conv.ll = val;
1159 DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index];
1160 DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index];
1161}
1162
1163/* Compute LSW in a double and a long long. */
1164
1165void
1166mv_compute_host_endianness (ARMul_State * state)
1167{
1168 static union
1169 {
1170 long long ll;
1171 int ints[2];
1172 int i;
1173 double d;
1174 float floats[2];
1175 float f;
1176 } conv;
1177
1178 /* Calculate where's the LSW in a 64bit int. */
1179 conv.ll = 45;
1180
1181 if (conv.ints[0] == 0) {
1182 msw_int_index = 0;
1183 lsw_int_index = 1;
1184 }
1185 else {
1186 assert (conv.ints[1] == 0);
1187 msw_int_index = 1;
1188 lsw_int_index = 0;
1189 }
1190
1191 /* Calculate where's the LSW in a double. */
1192 conv.d = 3.0;
1193
1194 if (conv.ints[0] == 0) {
1195 msw_float_index = 0;
1196 lsw_float_index = 1;
1197 }
1198 else {
1199 assert (conv.ints[1] == 0);
1200 msw_float_index = 1;
1201 lsw_float_index = 0;
1202 }
1203
1204 printfdbg ("lsw_int_index %d\n", lsw_int_index);
1205 printfdbg ("lsw_float_index %d\n", lsw_float_index);
1206}
diff --git a/src/core/arm/interpreter/mmu/rb.cpp b/src/core/arm/interpreter/mmu/rb.cpp
deleted file mode 100644
index 07b11e311..000000000
--- a/src/core/arm/interpreter/mmu/rb.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
1#include "core/arm/interpreter/armdefs.h"
2
3/*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu*/
4ARMword rb_masks[] = {
5 0x0, //RB_INVALID
6 4, //RB_1
7 16, //RB_4
8 32, //RB_8
9};
10
11/*mmu_rb_init
12 * @rb_t :rb_t to init
13 * @num :number of entry
14 * */
15int
16mmu_rb_init (rb_s * rb_t, int num)
17{
18 int i;
19 rb_entry_t *entrys;
20
21 entrys = (rb_entry_t *) malloc (sizeof (*entrys) * num);
22 if (entrys == NULL) {
23 printf ("SKYEYE:mmu_rb_init malloc error\n");
24 return -1;
25 }
26 for (i = 0; i < num; i++) {
27 entrys[i].type = RB_INVALID;
28 entrys[i].fault = NO_FAULT;
29 }
30
31 rb_t->entrys = entrys;
32 rb_t->num = num;
33 return 0;
34}
35
36/*mmu_rb_exit*/
37void
38mmu_rb_exit (rb_s * rb_t)
39{
40 free (rb_t->entrys);
41};
42
43/*mmu_rb_search
44 * @rb_t :rb_t to serach
45 * @va :va address to math
46 *
47 * $ NULL :not match
48 * NO-NULL:
49 * */
50rb_entry_t *
51mmu_rb_search (rb_s * rb_t, ARMword va)
52{
53 int i;
54 rb_entry_t *rb = rb_t->entrys;
55
56 DEBUG_LOG(ARM11, "va = %x\n", va);
57 for (i = 0; i < rb_t->num; i++, rb++) {
58 //2004-06-06 lyh bug from wenye@cs.ucsb.edu
59 if (rb->type) {
60 if ((va >= rb->va)
61 && (va < (rb->va + rb_masks[rb->type])))
62 return rb;
63 }
64 }
65 return NULL;
66};
67
68void
69mmu_rb_invalidate_entry (rb_s * rb_t, int i)
70{
71 rb_t->entrys[i].type = RB_INVALID;
72}
73
74void
75mmu_rb_invalidate_all (rb_s * rb_t)
76{
77 int i;
78
79 for (i = 0; i < rb_t->num; i++)
80 mmu_rb_invalidate_entry (rb_t, i);
81};
82
83void
84mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb, int type, ARMword va)
85{
86 rb_entry_t *rb;
87 int i;
88 ARMword max_start, min_end;
89 fault_t fault;
90 tlb_entry_t *tlb;
91
92 /*align va according to type */
93 va &= ~(rb_masks[type] - 1);
94 /*invalidate all RB match [va, va + rb_masks[type]] */
95 for (rb = rb_t->entrys, i = 0; i < rb_t->num; i++, rb++) {
96 if (rb->type) {
97 max_start = max (va, rb->va);
98 min_end =
99 min (va + rb_masks[type],
100 rb->va + rb_masks[rb->type]);
101 if (max_start < min_end)
102 rb->type = RB_INVALID;
103 }
104 }
105 /*load word */
106 rb = &rb_t->entrys[i_rb];
107 rb->type = type;
108 fault = translate (state, va, D_TLB (), &tlb);
109 if (fault) {
110 rb->fault = fault;
111 return;
112 }
113 fault = check_access (state, va, tlb, 1);
114 if (fault) {
115 rb->fault = fault;
116 return;
117 }
118
119 rb->fault = NO_FAULT;
120 va = tlb_va_to_pa (tlb, va);
121 //2004-06-06 lyh bug from wenye@cs.ucsb.edu
122 for (i = 0; i < (rb_masks[type] / 4); i++, va += WORD_SIZE) {
123 //rb->data[i] = mem_read_word (state, va);
124 bus_read(32, va, &rb->data[i]);
125 };
126}
diff --git a/src/core/arm/interpreter/mmu/rb.h b/src/core/arm/interpreter/mmu/rb.h
deleted file mode 100644
index 7bf0ebb26..000000000
--- a/src/core/arm/interpreter/mmu/rb.h
+++ /dev/null
@@ -1,55 +0,0 @@
1#ifndef _MMU_RB_H
2#define _MMU_RB_H
3
4enum rb_type_t
5{
6 RB_INVALID = 0, //invalid
7 RB_1, //1 word
8 RB_4, //4 word
9 RB_8, //8 word
10};
11
12/*bytes of each rb_type*/
13extern ARMword rb_masks[];
14
15#define RB_WORD_NUM 8
16typedef struct rb_entry_s
17{
18 ARMword data[RB_WORD_NUM]; //array to store data
19 ARMword va; //first word va
20 int type; //rb type
21 fault_t fault; //fault set by rb alloc
22} rb_entry_t;
23
24typedef struct rb_s
25{
26 int num;
27 rb_entry_t *entrys;
28} rb_s;
29
30/*mmu_rb_init
31 * @rb_t :rb_t to init
32 * @num :number of entry
33 * */
34int mmu_rb_init (rb_s * rb_t, int num);
35
36/*mmu_rb_exit*/
37void mmu_rb_exit (rb_s * rb_t);
38
39
40/*mmu_rb_search
41 * @rb_t :rb_t to serach
42 * @va :va address to math
43 *
44 * $ NULL :not match
45 * NO-NULL:
46 * */
47rb_entry_t *mmu_rb_search (rb_s * rb_t, ARMword va);
48
49
50void mmu_rb_invalidate_entry (rb_s * rb_t, int i);
51void mmu_rb_invalidate_all (rb_s * rb_t);
52void mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb,
53 int type, ARMword va);
54
55#endif /*_MMU_RB_H_*/
diff --git a/src/core/arm/interpreter/mmu/sa_mmu.cpp b/src/core/arm/interpreter/mmu/sa_mmu.cpp
deleted file mode 100644
index eff5002de..000000000
--- a/src/core/arm/interpreter/mmu/sa_mmu.cpp
+++ /dev/null
@@ -1,864 +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#include <assert.h>
22#include <string.h>
23
24#include "core/arm/interpreter/armdefs.h"
25
26/**
27 * The interface of read data from bus
28 */
29int bus_read(short size, int addr, uint32_t * value) {
30 ERROR_LOG(ARM11, "unimplemented bus_read");
31 return 0;
32}
33
34/**
35 * The interface of write data from bus
36 */
37int bus_write(short size, int addr, uint32_t value) {
38 ERROR_LOG(ARM11, "unimplemented bus_write");
39 return 0;
40}
41
42
43typedef struct sa_mmu_desc_s
44{
45 int i_tlb;
46 cache_desc_t i_cache;
47
48 int d_tlb;
49 cache_desc_t main_d_cache;
50 cache_desc_t mini_d_cache;
51 int rb;
52 wb_desc_t wb;
53} sa_mmu_desc_t;
54
55static sa_mmu_desc_t sa11xx_mmu_desc = {
56 32,
57 {32, 32, 16, CACHE_WRITE_BACK},
58
59 32,
60 {32, 32, 8, CACHE_WRITE_BACK},
61 {32, 2, 8, CACHE_WRITE_BACK},
62 4,
63 //{8, 4}, for word size
64 {8, 16}, //for byte size, chy 2003-07-11
65};
66
67static fault_t sa_mmu_write (ARMul_State * state, ARMword va, ARMword data,
68 ARMword datatype);
69static fault_t sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
70 ARMword datatype);
71static fault_t update_cache (ARMul_State * state, ARMword va, ARMword data,
72 ARMword datatype, cache_line_t * cache,
73 cache_s * cache_t, ARMword real_va);
74
75void
76mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa,
77 ARMbyte * data, int n);
78int
79sa_mmu_init (ARMul_State * state)
80{
81 sa_mmu_desc_t *desc;
82 cache_desc_t *c_desc;
83
84 state->mmu.control = 0x70;
85 state->mmu.translation_table_base = 0xDEADC0DE;
86 state->mmu.domain_access_control = 0xDEADC0DE;
87 state->mmu.fault_status = 0;
88 state->mmu.fault_address = 0;
89 state->mmu.process_id = 0;
90
91 desc = &sa11xx_mmu_desc;
92 if (mmu_tlb_init (I_TLB (), desc->i_tlb)) {
93 ERROR_LOG(ARM11, "i_tlb init %d\n", -1);
94 goto i_tlb_init_error;
95 }
96
97 c_desc = &desc->i_cache;
98 if (mmu_cache_init (I_CACHE (), c_desc->width, c_desc->way,
99 c_desc->set, c_desc->w_mode)) {
100 ERROR_LOG(ARM11, "i_cache init %d\n", -1);
101 goto i_cache_init_error;
102 }
103
104 if (mmu_tlb_init (D_TLB (), desc->d_tlb)) {
105 ERROR_LOG(ARM11, "d_tlb init %d\n", -1);
106 goto d_tlb_init_error;
107 }
108
109 c_desc = &desc->main_d_cache;
110 if (mmu_cache_init (MAIN_D_CACHE (), c_desc->width, c_desc->way,
111 c_desc->set, c_desc->w_mode)) {
112 ERROR_LOG(ARM11, "main_d_cache init %d\n", -1);
113 goto main_d_cache_init_error;
114 }
115
116 c_desc = &desc->mini_d_cache;
117 if (mmu_cache_init (MINI_D_CACHE (), c_desc->width, c_desc->way,
118 c_desc->set, c_desc->w_mode)) {
119 ERROR_LOG(ARM11, "mini_d_cache init %d\n", -1);
120 goto mini_d_cache_init_error;
121 }
122
123 if (mmu_wb_init (WB (), desc->wb.num, desc->wb.nb)) {
124 ERROR_LOG(ARM11, "wb init %d\n", -1);
125 goto wb_init_error;
126 }
127
128 if (mmu_rb_init (RB (), desc->rb)) {
129 ERROR_LOG(ARM11, "rb init %d\n", -1);
130 goto rb_init_error;
131 }
132 return 0;
133
134 rb_init_error:
135 mmu_wb_exit (WB ());
136 wb_init_error:
137 mmu_cache_exit (MINI_D_CACHE ());
138 mini_d_cache_init_error:
139 mmu_cache_exit (MAIN_D_CACHE ());
140 main_d_cache_init_error:
141 mmu_tlb_exit (D_TLB ());
142 d_tlb_init_error:
143 mmu_cache_exit (I_CACHE ());
144 i_cache_init_error:
145 mmu_tlb_exit (I_TLB ());
146 i_tlb_init_error:
147 return -1;
148}
149
150void
151sa_mmu_exit (ARMul_State * state)
152{
153 mmu_rb_exit (RB ());
154 mmu_wb_exit (WB ());
155 mmu_cache_exit (MINI_D_CACHE ());
156 mmu_cache_exit (MAIN_D_CACHE ());
157 mmu_tlb_exit (D_TLB ());
158 mmu_cache_exit (I_CACHE ());
159 mmu_tlb_exit (I_TLB ());
160};
161
162
163static fault_t
164sa_mmu_load_instr (ARMul_State * state, ARMword va, ARMword * instr)
165{
166 fault_t fault;
167 tlb_entry_t *tlb;
168 cache_line_t *cache;
169 int c; //cache bit
170 ARMword pa; //physical addr
171
172 static int debug_count = 0; //used for debug
173
174 DEBUG_LOG(ARM11, "va = %x\n", va);
175
176 va = mmu_pid_va_map (va);
177 if (MMU_Enabled) {
178 /*align check */
179 if ((va & (WORD_SIZE - 1)) && MMU_Aligned) {
180 DEBUG_LOG(ARM11, "align\n");
181 return ALIGNMENT_FAULT;
182 }
183 else
184 va &= ~(WORD_SIZE - 1);
185
186 /*translate tlb */
187 fault = translate (state, va, I_TLB (), &tlb);
188 if (fault) {
189 DEBUG_LOG(ARM11, "translate\n");
190 return fault;
191 }
192
193 /*check access */
194 fault = check_access (state, va, tlb, 1);
195 if (fault) {
196 DEBUG_LOG(ARM11, "check_fault\n");
197 return fault;
198 }
199 }
200
201 /*search cache no matter MMU enabled/disabled */
202 cache = mmu_cache_search (state, I_CACHE (), va);
203 if (cache) {
204 *instr = cache->data[va_cache_index (va, I_CACHE ())];
205 return NO_FAULT;
206 }
207
208 /*if MMU disabled or C flag is set alloc cache */
209 if (MMU_Disabled) {
210 c = 1;
211 pa = va;
212 }
213 else {
214 c = tlb_c_flag (tlb);
215 pa = tlb_va_to_pa (tlb, va);
216 }
217
218 if (c) {
219 int index;
220
221 debug_count++;
222 cache = mmu_cache_alloc (state, I_CACHE (), va, pa);
223 index = va_cache_index (va, I_CACHE ());
224 *instr = cache->data[va_cache_index (va, I_CACHE ())];
225 }
226 else
227 //*instr = mem_read_word (state, pa);
228 bus_read(32, pa, instr);
229
230 return NO_FAULT;
231};
232
233
234
235static fault_t
236sa_mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data)
237{
238 //ARMword temp,offset;
239 fault_t fault;
240 fault = sa_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE);
241 return fault;
242}
243
244static fault_t
245sa_mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data)
246{
247 //ARMword temp,offset;
248 fault_t fault;
249 fault = sa_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE);
250 return fault;
251}
252
253static fault_t
254sa_mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data)
255{
256 return sa_mmu_read (state, virt_addr, data, ARM_WORD_TYPE);
257}
258
259
260
261
262static fault_t
263sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
264 ARMword datatype)
265{
266 fault_t fault;
267 rb_entry_t *rb;
268 tlb_entry_t *tlb;
269 cache_line_t *cache;
270 ARMword pa, real_va, temp, offset;
271
272 DEBUG_LOG(ARM11, "va = %x\n", va);
273
274 va = mmu_pid_va_map (va);
275 real_va = va;
276 /*if MMU disabled, memory_read */
277 if (MMU_Disabled) {
278 //*data = mem_read_word(state, va);
279 if (datatype == ARM_BYTE_TYPE)
280 //*data = mem_read_byte (state, va);
281 bus_read(8, va, data);
282 else if (datatype == ARM_HALFWORD_TYPE)
283 //*data = mem_read_halfword (state, va);
284 bus_read(16, va, data);
285 else if (datatype == ARM_WORD_TYPE)
286 //*data = mem_read_word (state, va);
287 bus_read(32, va, data);
288 else {
289 printf ("SKYEYE:1 sa_mmu_read error: unknown data type %d\n", datatype);
290 // skyeye_exit (-1);
291 }
292
293 return NO_FAULT;
294 }
295
296 /*align check */
297 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
298 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
299 DEBUG_LOG(ARM11, "align\n");
300 return ALIGNMENT_FAULT;
301 } // else
302
303 va &= ~(WORD_SIZE - 1);
304
305 /*translate va to tlb */
306 fault = translate (state, va, D_TLB (), &tlb);
307 if (fault) {
308 DEBUG_LOG(ARM11, "translate\n");
309 return fault;
310 }
311 /*check access permission */
312 fault = check_access (state, va, tlb, 1);
313 if (fault)
314 return fault;
315 /*search in read buffer */
316 rb = mmu_rb_search (RB (), va);
317 if (rb) {
318 if (rb->fault)
319 return rb->fault;
320 *data = rb->data[(va & (rb_masks[rb->type] - 1)) >> WORD_SHT];
321 goto datatrans;
322 //return 0;
323 };
324 /*search main cache */
325 cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
326 if (cache) {
327 *data = cache->data[va_cache_index (va, MAIN_D_CACHE ())];
328 goto datatrans;
329 //return 0;
330 }
331 /*search mini cache */
332 cache = mmu_cache_search (state, MINI_D_CACHE (), va);
333 if (cache) {
334 *data = cache->data[va_cache_index (va, MINI_D_CACHE ())];
335 goto datatrans;
336 //return 0;
337 }
338
339 /*get phy_addr */
340 pa = tlb_va_to_pa (tlb, va);
341 if ((pa >= 0xe0000000) && (pa < 0xe8000000)) {
342 if (tlb_c_flag (tlb)) {
343 if (tlb_b_flag (tlb)) {
344 mmu_cache_soft_flush (state, MAIN_D_CACHE (),
345 pa);
346 }
347 else {
348 mmu_cache_soft_flush (state, MINI_D_CACHE (),
349 pa);
350 }
351 }
352 return NO_FAULT;
353 }
354
355 /*if Buffer, drain Write Buffer first */
356 if (tlb_b_flag (tlb))
357 mmu_wb_drain_all (state, WB ());
358
359 /*alloc cache or mem_read */
360 if (tlb_c_flag (tlb) && MMU_DCacheEnabled) {
361 cache_s *cache_t;
362
363 if (tlb_b_flag (tlb))
364 cache_t = MAIN_D_CACHE ();
365 else
366 cache_t = MINI_D_CACHE ();
367 cache = mmu_cache_alloc (state, cache_t, va, pa);
368 *data = cache->data[va_cache_index (va, cache_t)];
369 }
370 else {
371 //*data = mem_read_word(state, pa);
372 if (datatype == ARM_BYTE_TYPE)
373 //*data = mem_read_byte (state, pa | (real_va & 3));
374 bus_read(8, pa | (real_va & 3), data);
375 else if (datatype == ARM_HALFWORD_TYPE)
376 //*data = mem_read_halfword (state, pa | (real_va & 2));
377 bus_read(16, pa | (real_va & 2), data);
378 else if (datatype == ARM_WORD_TYPE)
379 //*data = mem_read_word (state, pa);
380 bus_read(32, pa, data);
381 else {
382 printf ("SKYEYE:2 sa_mmu_read error: unknown data type %d\n", datatype);
383 // skyeye_exit (-1);
384 }
385 return NO_FAULT;
386 }
387
388
389 datatrans:
390 if (datatype == ARM_HALFWORD_TYPE) {
391 temp = *data;
392 offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
393 *data = (temp >> offset) & 0xffff;
394 }
395 else if (datatype == ARM_BYTE_TYPE) {
396 temp = *data;
397 offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
398 *data = (temp >> offset & 0xffL);
399 }
400 end:
401 return NO_FAULT;
402}
403
404
405static fault_t
406sa_mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data)
407{
408 return sa_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE);
409}
410
411static fault_t
412sa_mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data)
413{
414 return sa_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE);
415}
416
417static fault_t
418sa_mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data)
419{
420 return sa_mmu_write (state, virt_addr, data, ARM_WORD_TYPE);
421}
422
423
424
425static fault_t
426sa_mmu_write (ARMul_State * state, ARMword va, ARMword data, ARMword datatype)
427{
428 tlb_entry_t *tlb;
429 cache_line_t *cache;
430 int b;
431 ARMword pa, real_va;
432 fault_t fault;
433
434 DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data);
435 va = mmu_pid_va_map (va);
436 real_va = va;
437
438 /*search instruction cache */
439 cache = mmu_cache_search (state, I_CACHE (), va);
440 if (cache) {
441 update_cache (state, va, data, datatype, cache, I_CACHE (),
442 real_va);
443 }
444
445 if (MMU_Disabled) {
446 //mem_write_word(state, va, data);
447 if (datatype == ARM_BYTE_TYPE)
448 //mem_write_byte (state, va, data);
449 bus_write(8, va, data);
450 else if (datatype == ARM_HALFWORD_TYPE)
451 //mem_write_halfword (state, va, data);
452 bus_write(16, va, data);
453 else if (datatype == ARM_WORD_TYPE)
454 //mem_write_word (state, va, data);
455 bus_write(32, va, data);
456 else {
457 printf ("SKYEYE:1 sa_mmu_write error: unknown data type %d\n", datatype);
458 // skyeye_exit (-1);
459 }
460
461 return NO_FAULT;
462 }
463 /*align check */
464 //if ((va & (WORD_SIZE - 1)) && MMU_Aligned){
465 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
466 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
467 DEBUG_LOG(ARM11, "align\n");
468 return ALIGNMENT_FAULT;
469 } //else
470 va &= ~(WORD_SIZE - 1);
471 /*tlb translate */
472 fault = translate (state, va, D_TLB (), &tlb);
473 if (fault) {
474 DEBUG_LOG(ARM11, "translate\n");
475 return fault;
476 }
477 /*tlb check access */
478 fault = check_access (state, va, tlb, 0);
479 if (fault) {
480 DEBUG_LOG(ARM11, "check_access\n");
481 return fault;
482 }
483 /*search main cache */
484 cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
485 if (cache) {
486 update_cache (state, va, data, datatype, cache,
487 MAIN_D_CACHE (), real_va);
488 }
489 else {
490 /*search mini cache */
491 cache = mmu_cache_search (state, MINI_D_CACHE (), va);
492 if (cache) {
493 update_cache (state, va, data, datatype, cache,
494 MINI_D_CACHE (), real_va);
495 }
496 }
497
498 if (!cache) {
499 b = tlb_b_flag (tlb);
500 pa = tlb_va_to_pa (tlb, va);
501 if (b) {
502 if (MMU_WBEnabled) {
503 if (datatype == ARM_WORD_TYPE)
504 mmu_wb_write_bytes (state, WB (), pa,
505 (ARMbyte*)&data, 4);
506 else if (datatype == ARM_HALFWORD_TYPE)
507 mmu_wb_write_bytes (state, WB (),
508 (pa |
509 (real_va & 2)),
510 (ARMbyte*)&data, 2);
511 else if (datatype == ARM_BYTE_TYPE)
512 mmu_wb_write_bytes (state, WB (),
513 (pa |
514 (real_va & 3)),
515 (ARMbyte*)&data, 1);
516
517 }
518 else {
519 if (datatype == ARM_WORD_TYPE)
520 //mem_write_word (state, pa, data);
521 bus_write(32, pa, data);
522 else if (datatype == ARM_HALFWORD_TYPE)
523 /*
524 mem_write_halfword (state,
525 (pa |
526 (real_va & 2)),
527 data);
528 */
529 bus_write(16, pa | (real_va & 2), data);
530 else if (datatype == ARM_BYTE_TYPE)
531 /*
532 mem_write_byte (state,
533 (pa | (real_va & 3)),
534 data);
535 */
536 bus_write(8, pa | (real_va & 3), data);
537 }
538 }
539 else {
540 mmu_wb_drain_all (state, WB ());
541
542 if (datatype == ARM_WORD_TYPE)
543 //mem_write_word (state, pa, data);
544 bus_write(32, pa, data);
545 else if (datatype == ARM_HALFWORD_TYPE)
546 /*
547 mem_write_halfword (state,
548 (pa | (real_va & 2)),
549 data);
550 */
551 bus_write(16, pa | (real_va & 2), data);
552 else if (datatype == ARM_BYTE_TYPE)
553 /*
554 mem_write_byte (state, (pa | (real_va & 3)),
555 data);
556 */
557 bus_write(8, pa | (real_va & 3), data);
558 }
559 }
560 return NO_FAULT;
561}
562
563static fault_t
564update_cache (ARMul_State * state, ARMword va, ARMword data, ARMword datatype,
565 cache_line_t * cache, cache_s * cache_t, ARMword real_va)
566{
567 ARMword temp, offset;
568
569 ARMword index = va_cache_index (va, cache_t);
570
571 //cache->data[index] = data;
572
573 if (datatype == ARM_WORD_TYPE)
574 cache->data[index] = data;
575 else if (datatype == ARM_HALFWORD_TYPE) {
576 temp = cache->data[index];
577 offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
578 cache->data[index] =
579 (temp & ~(0xffffL << offset)) | ((data & 0xffffL) <<
580 offset);
581 }
582 else if (datatype == ARM_BYTE_TYPE) {
583 temp = cache->data[index];
584 offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
585 cache->data[index] =
586 (temp & ~(0xffL << offset)) | ((data & 0xffL) <<
587 offset);
588 }
589
590 if (index < (cache_t->width >> (WORD_SHT + 1)))
591 cache->tag |= TAG_FIRST_HALF_DIRTY;
592 else
593 cache->tag |= TAG_LAST_HALF_DIRTY;
594
595 return NO_FAULT;
596}
597
598ARMword
599sa_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
600{
601 mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15);
602 ARMword data;
603
604 switch (creg) {
605 case MMU_ID:
606// printf("mmu_mrc read ID ");
607 data = 0x41007100; /* v3 */
608 data = state->cpu->cpu_val;
609 break;
610 case MMU_CONTROL:
611// printf("mmu_mrc read CONTROL");
612 data = state->mmu.control;
613 break;
614 case MMU_TRANSLATION_TABLE_BASE:
615// printf("mmu_mrc read TTB ");
616 data = state->mmu.translation_table_base;
617 break;
618 case MMU_DOMAIN_ACCESS_CONTROL:
619// printf("mmu_mrc read DACR ");
620 data = state->mmu.domain_access_control;
621 break;
622 case MMU_FAULT_STATUS:
623// printf("mmu_mrc read FSR ");
624 data = state->mmu.fault_status;
625 break;
626 case MMU_FAULT_ADDRESS:
627// printf("mmu_mrc read FAR ");
628 data = state->mmu.fault_address;
629 break;
630 case MMU_PID:
631 data = state->mmu.process_id;
632 default:
633 printf ("mmu_mrc read UNKNOWN - reg %d\n", creg);
634 data = 0;
635 break;
636 }
637// printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]);
638 *value = data;
639 return data;
640}
641
642void
643sa_mmu_cache_ops (ARMul_State * state, ARMword instr, ARMword value)
644{
645 int CRm, OPC_2;
646
647 CRm = BITS (0, 3);
648 OPC_2 = BITS (5, 7);
649
650 if (OPC_2 == 0 && CRm == 7) {
651 mmu_cache_invalidate_all (state, I_CACHE ());
652 mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
653 mmu_cache_invalidate_all (state, MINI_D_CACHE ());
654 return;
655 }
656
657 if (OPC_2 == 0 && CRm == 5) {
658 mmu_cache_invalidate_all (state, I_CACHE ());
659 return;
660 }
661
662 if (OPC_2 == 0 && CRm == 6) {
663 mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
664 mmu_cache_invalidate_all (state, MINI_D_CACHE ());
665 return;
666 }
667
668 if (OPC_2 == 1 && CRm == 6) {
669 mmu_cache_invalidate (state, MAIN_D_CACHE (), value);
670 mmu_cache_invalidate (state, MINI_D_CACHE (), value);
671 return;
672 }
673
674 if (OPC_2 == 1 && CRm == 0xa) {
675 mmu_cache_clean (state, MAIN_D_CACHE (), value);
676 mmu_cache_clean (state, MINI_D_CACHE (), value);
677 return;
678 }
679
680 if (OPC_2 == 4 && CRm == 0xa) {
681 mmu_wb_drain_all (state, WB ());
682 return;
683 }
684 ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
685}
686
687static void
688sa_mmu_tlb_ops (ARMul_State * state, ARMword instr, ARMword value)
689{
690 int CRm, OPC_2;
691
692 CRm = BITS (0, 3);
693 OPC_2 = BITS (5, 7);
694
695
696 if (OPC_2 == 0 && CRm == 0x7) {
697 mmu_tlb_invalidate_all (state, I_TLB ());
698 mmu_tlb_invalidate_all (state, D_TLB ());
699 return;
700 }
701
702 if (OPC_2 == 0 && CRm == 0x5) {
703 mmu_tlb_invalidate_all (state, I_TLB ());
704 return;
705 }
706
707 if (OPC_2 == 0 && CRm == 0x6) {
708 mmu_tlb_invalidate_all (state, D_TLB ());
709 return;
710 }
711
712 if (OPC_2 == 1 && CRm == 0x6) {
713 mmu_tlb_invalidate_entry (state, D_TLB (), value);
714 return;
715 }
716
717 ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
718}
719
720static void
721sa_mmu_rb_ops (ARMul_State * state, ARMword instr, ARMword value)
722{
723 int CRm, OPC_2;
724
725 CRm = BITS (0, 3);
726 OPC_2 = BITS (5, 7);
727
728 if (OPC_2 == 0x0 && CRm == 0x0) {
729 mmu_rb_invalidate_all (RB ());
730 return;
731 }
732
733 if (OPC_2 == 0x2) {
734 int idx = CRm & 0x3;
735 int type = ((CRm >> 2) & 0x3) + 1;
736
737 if ((idx < 4) && (type < 4))
738 mmu_rb_load (state, RB (), idx, type, value);
739 return;
740 }
741
742 if ((OPC_2 == 1) && (CRm < 4)) {
743 mmu_rb_invalidate_entry (RB (), CRm);
744 return;
745 }
746
747 ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
748}
749
750static ARMword
751sa_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
752{
753 mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15);
754 if (!strncmp (state->cpu->cpu_arch_name, "armv4", 5)) {
755 switch (creg) {
756 case MMU_CONTROL:
757// printf("mmu_mcr wrote CONTROL ");
758 state->mmu.control = (value | 0x70) & 0xFFFD;
759 break;
760 case MMU_TRANSLATION_TABLE_BASE:
761// printf("mmu_mcr wrote TTB ");
762 state->mmu.translation_table_base =
763 value & 0xFFFFC000;
764 break;
765 case MMU_DOMAIN_ACCESS_CONTROL:
766// printf("mmu_mcr wrote DACR ");
767 state->mmu.domain_access_control = value;
768 break;
769
770 case MMU_FAULT_STATUS:
771 state->mmu.fault_status = value & 0xFF;
772 break;
773 case MMU_FAULT_ADDRESS:
774 state->mmu.fault_address = value;
775 break;
776
777 case MMU_CACHE_OPS:
778 sa_mmu_cache_ops (state, instr, value);
779 break;
780 case MMU_TLB_OPS:
781 sa_mmu_tlb_ops (state, instr, value);
782 break;
783 case MMU_SA_RB_OPS:
784 sa_mmu_rb_ops (state, instr, value);
785 break;
786 case MMU_SA_DEBUG:
787 break;
788 case MMU_SA_CP15_R15:
789 break;
790 case MMU_PID:
791 //2004-06-06 lyh, bug provided by wen ye wenye@cs.ucsb.edu
792 state->mmu.process_id = value & 0x7e000000;
793 break;
794
795 default:
796 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
797 break;
798 }
799 }
800 return 0;
801}
802
803//teawater add for arm2x86 2005.06.24-------------------------------------------
804static int
805sa_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr)
806{
807 fault_t fault;
808 tlb_entry_t *tlb;
809
810 virt_addr = mmu_pid_va_map (virt_addr);
811 if (MMU_Enabled) {
812
813 /*align check */
814 if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) {
815 DEBUG_LOG(ARM11, "align\n");
816 return ALIGNMENT_FAULT;
817 }
818 else
819 virt_addr &= ~(WORD_SIZE - 1);
820
821 /*translate tlb */
822 fault = translate (state, virt_addr, I_TLB (), &tlb);
823 if (fault) {
824 DEBUG_LOG(ARM11, "translate\n");
825 return fault;
826 }
827
828 /*check access */
829 fault = check_access (state, virt_addr, tlb, 1);
830 if (fault) {
831 DEBUG_LOG(ARM11, "check_fault\n");
832 return fault;
833 }
834 }
835
836 if (MMU_Disabled) {
837 *phys_addr = virt_addr;
838 }
839 else {
840 *phys_addr = tlb_va_to_pa (tlb, virt_addr);
841 }
842
843 return (0);
844}
845
846//AJ2D--------------------------------------------------------------------------
847
848/*sa mmu_ops_t*/
849mmu_ops_t sa_mmu_ops = {
850 sa_mmu_init,
851 sa_mmu_exit,
852 sa_mmu_read_byte,
853 sa_mmu_write_byte,
854 sa_mmu_read_halfword,
855 sa_mmu_write_halfword,
856 sa_mmu_read_word,
857 sa_mmu_write_word,
858 sa_mmu_load_instr,
859 sa_mmu_mcr,
860 sa_mmu_mrc,
861//teawater add for arm2x86 2005.06.24-------------------------------------------
862 sa_mmu_v2p_dbct,
863//AJ2D--------------------------------------------------------------------------
864};
diff --git a/src/core/arm/interpreter/mmu/sa_mmu.h b/src/core/arm/interpreter/mmu/sa_mmu.h
deleted file mode 100644
index 64b1c5470..000000000
--- a/src/core/arm/interpreter/mmu/sa_mmu.h
+++ /dev/null
@@ -1,58 +0,0 @@
1/*
2 sa_mmu.h - StrongARM Memory Management Unit emulation.
3 ARMulator extensions for SkyEye.
4 <lyhost@263.net>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21#ifndef _SA_MMU_H_
22#define _SA_MMU_H_
23
24
25/**
26 * The interface of read data from bus
27 */
28int bus_read(short size, int addr, uint32_t * value);
29
30/**
31 * The interface of write data from bus
32 */
33int bus_write(short size, int addr, uint32_t value);
34
35
36typedef struct sa_mmu_s
37{
38 tlb_s i_tlb;
39 cache_s i_cache;
40
41 tlb_s d_tlb;
42 cache_s main_d_cache;
43 cache_s mini_d_cache;
44 rb_s rb_t;
45 wb_s wb_t;
46} sa_mmu_t;
47
48#define I_TLB() (&state->mmu.u.sa_mmu.i_tlb)
49#define I_CACHE() (&state->mmu.u.sa_mmu.i_cache)
50
51#define D_TLB() (&state->mmu.u.sa_mmu.d_tlb)
52#define MAIN_D_CACHE() (&state->mmu.u.sa_mmu.main_d_cache)
53#define MINI_D_CACHE() (&state->mmu.u.sa_mmu.mini_d_cache)
54#define WB() (&state->mmu.u.sa_mmu.wb_t)
55#define RB() (&state->mmu.u.sa_mmu.rb_t)
56
57extern mmu_ops_t sa_mmu_ops;
58#endif /*_SA_MMU_H_*/
diff --git a/src/core/arm/interpreter/mmu/tlb.cpp b/src/core/arm/interpreter/mmu/tlb.cpp
deleted file mode 100644
index ca60ac1a1..000000000
--- a/src/core/arm/interpreter/mmu/tlb.cpp
+++ /dev/null
@@ -1,307 +0,0 @@
1#include <assert.h>
2
3#include "core/arm/interpreter/armdefs.h"
4
5ARMword tlb_masks[] = {
6 0x00000000, /* TLB_INVALID */
7 0xFFFFF000, /* TLB_SMALLPAGE */
8 0xFFFF0000, /* TLB_LARGEPAGE */
9 0xFFF00000, /* TLB_SECTION */
10 0xFFFFF000, /*TLB_ESMALLPAGE, have TEX attirbute, only for XScale */
11 0xFFFFFC00 /* TLB_TINYPAGE */
12};
13
14/* This function encodes table 8-2 Interpreting AP bits,
15 returning non-zero if access is allowed. */
16static int
17check_perms (ARMul_State * state, int ap, int read)
18{
19 int s, r, user;
20
21 s = state->mmu.control & CONTROL_SYSTEM;
22 r = state->mmu.control & CONTROL_ROM;
23 //chy 2006-02-15 , should consider system mode, don't conside 26bit mode
24 user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE);
25
26 switch (ap) {
27 case 0:
28 return read && ((s && !user) || r);
29 case 1:
30 return !user;
31 case 2:
32 return read || !user;
33 case 3:
34 return 1;
35 }
36 return 0;
37}
38
39fault_t
40check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,
41 int read)
42{
43 int access;
44
45 state->mmu.last_domain = tlb->domain;
46 access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3;
47 if ((access == 0) || (access == 2)) {
48 /* It's unclear from the documentation whether this
49 should always raise a section domain fault, or if
50 it should be a page domain fault in the case of an
51 L1 that describes a page table. In the ARM710T
52 datasheets, "Figure 8-9: Sequence for checking faults"
53 seems to indicate the former, while "Table 8-4: Priority
54 encoding of fault status" gives a value for FS[3210] in
55 the event of a domain fault for a page. Hmm. */
56 return SECTION_DOMAIN_FAULT;
57 }
58 if (access == 1) {
59 /* client access - check perms */
60 int subpage, ap;
61
62 switch (tlb->mapping) {
63 /*ks 2004-05-09
64 * only for XScale
65 * Extend Small Page(ESP) Format
66 * 31-12 bits the base addr of ESP
67 * 11-10 bits SBZ
68 * 9-6 bits TEX
69 * 5-4 bits AP
70 * 3 bit C
71 * 2 bit B
72 * 1-0 bits 11
73 * */
74 case TLB_ESMALLPAGE: //xj
75 subpage = 0;
76 //printf("TLB_ESMALLPAGE virt_addr=0x%x \n",virt_addr );
77 break;
78
79 case TLB_TINYPAGE:
80 subpage = 0;
81 //printf("TLB_TINYPAGE virt_addr=0x%x \n",virt_addr );
82 break;
83
84 case TLB_SMALLPAGE:
85 subpage = (virt_addr >> 10) & 3;
86 break;
87 case TLB_LARGEPAGE:
88 subpage = (virt_addr >> 14) & 3;
89 break;
90 case TLB_SECTION:
91 subpage = 3;
92 break;
93 default:
94 assert (0);
95 subpage = 0; /* cleans a warning */
96 }
97 ap = (tlb->perms >> (subpage * 2 + 4)) & 3;
98 if (!check_perms (state, ap, read)) {
99 if (tlb->mapping == TLB_SECTION) {
100 return SECTION_PERMISSION_FAULT;
101 }
102 else {
103 return SUBPAGE_PERMISSION_FAULT;
104 }
105 }
106 }
107 else { /* access == 3 */
108 /* manager access - don't check perms */
109 }
110 return NO_FAULT;
111}
112
113fault_t
114translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t,
115 tlb_entry_t ** tlb)
116{
117 *tlb = mmu_tlb_search (state, tlb_t, virt_addr);
118 if (!*tlb) {
119 /* walk the translation tables */
120 ARMword l1addr, l1desc;
121 tlb_entry_t entry;
122
123 l1addr = state->mmu.translation_table_base & 0xFFFFC000;
124 l1addr = (l1addr | (virt_addr >> 18)) & ~3;
125 //l1desc = mem_read_word (state, l1addr);
126 bus_read(32, l1addr, &l1desc);
127 switch (l1desc & 3) {
128 case 0:
129 /*
130 * according to Figure 3-9 Sequence for checking faults in arm manual,
131 * section translation fault should be returned here.
132 */
133 {
134 return SECTION_TRANSLATION_FAULT;
135 }
136 case 3:
137 /* fine page table */
138 // dcl 2006-01-08
139 {
140 ARMword l2addr, l2desc;
141
142 l2addr = l1desc & 0xFFFFF000;
143 l2addr = (l2addr |
144 ((virt_addr & 0x000FFC00) >> 8)) &
145 ~3;
146 //l2desc = mem_read_word (state, l2addr);
147 bus_read(32, l2addr, &l2desc);
148
149 entry.virt_addr = virt_addr;
150 entry.phys_addr = l2desc;
151 entry.perms = l2desc & 0x00000FFC;
152 entry.domain = (l1desc >> 5) & 0x0000000F;
153 switch (l2desc & 3) {
154 case 0:
155 state->mmu.last_domain = entry.domain;
156 return PAGE_TRANSLATION_FAULT;
157 case 3:
158 entry.mapping = TLB_TINYPAGE;
159 break;
160 case 1:
161 // this is untested
162 entry.mapping = TLB_LARGEPAGE;
163 break;
164 case 2:
165 // this is untested
166 entry.mapping = TLB_SMALLPAGE;
167 break;
168 }
169 }
170 break;
171 case 1:
172 /* coarse page table */
173 {
174 ARMword l2addr, l2desc;
175
176 l2addr = l1desc & 0xFFFFFC00;
177 l2addr = (l2addr |
178 ((virt_addr & 0x000FF000) >> 10)) &
179 ~3;
180 //l2desc = mem_read_word (state, l2addr);
181 bus_read(32, l2addr, &l2desc);
182
183 entry.virt_addr = virt_addr;
184 entry.phys_addr = l2desc;
185 entry.perms = l2desc & 0x00000FFC;
186 entry.domain = (l1desc >> 5) & 0x0000000F;
187 //printf("SKYEYE:PAGE virt_addr = %x,l1desc=%x,phys_addr=%x\n",virt_addr,l1desc,entry.phys_addr);
188 //chy 2003-09-02 for xscale
189 switch (l2desc & 3) {
190 case 0:
191 state->mmu.last_domain = entry.domain;
192 return PAGE_TRANSLATION_FAULT;
193 case 3:
194 if (!state->is_XScale) {
195 state->mmu.last_domain =
196 entry.domain;
197 return PAGE_TRANSLATION_FAULT;
198 };
199 //ks 2004-05-09 xscale shold use Extend Small Page
200 //entry.mapping = TLB_SMALLPAGE;
201 entry.mapping = TLB_ESMALLPAGE; //xj
202 break;
203 case 1:
204 entry.mapping = TLB_LARGEPAGE;
205 break;
206 case 2:
207 entry.mapping = TLB_SMALLPAGE;
208 break;
209 }
210 }
211 break;
212 case 2:
213 /* section */
214 //printf("SKYEYE:WARNING: not implement section mapping incompletely\n");
215 //printf("SKYEYE:SECTION virt_addr = %x,l1desc=%x\n",virt_addr,l1desc);
216 //return SECTION_DOMAIN_FAULT;
217 //#if 0
218 entry.virt_addr = virt_addr;
219 entry.phys_addr = l1desc;
220 entry.perms = l1desc & 0x00000C0C;
221 entry.domain = (l1desc >> 5) & 0x0000000F;
222 entry.mapping = TLB_SECTION;
223 break;
224 //#endif
225 }
226 entry.virt_addr &= tlb_masks[entry.mapping];
227 entry.phys_addr &= tlb_masks[entry.mapping];
228
229 /* place entry in the tlb */
230 *tlb = &tlb_t->entrys[tlb_t->cycle];
231 tlb_t->cycle = (tlb_t->cycle + 1) % tlb_t->num;
232 **tlb = entry;
233 }
234 state->mmu.last_domain = (*tlb)->domain;
235 return NO_FAULT;
236}
237
238int
239mmu_tlb_init (tlb_s * tlb_t, int num)
240{
241 tlb_entry_t *e;
242 int i;
243
244 e = (tlb_entry_t *) malloc (sizeof (*e) * num);
245 if (e == NULL) {
246 ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*e) * num);
247 goto tlb_malloc_error;
248 }
249 tlb_t->entrys = e;
250 for (i = 0; i < num; i++, e++)
251 e->mapping = TLB_INVALID;
252 tlb_t->cycle = 0;
253 tlb_t->num = num;
254 return 0;
255
256 tlb_malloc_error:
257 return -1;
258}
259
260void
261mmu_tlb_exit (tlb_s * tlb_t)
262{
263 free (tlb_t->entrys);
264};
265
266void
267mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t)
268{
269 int entry;
270
271 for (entry = 0; entry < tlb_t->num; entry++) {
272 tlb_t->entrys[entry].mapping = TLB_INVALID;
273 }
274 tlb_t->cycle = 0;
275}
276
277void
278mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr)
279{
280 tlb_entry_t *tlb;
281
282 tlb = mmu_tlb_search (state, tlb_t, addr);
283 if (tlb) {
284 tlb->mapping = TLB_INVALID;
285 }
286}
287
288tlb_entry_t *
289mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t, ARMword virt_addr)
290{
291 int entry;
292
293 for (entry = 0; entry < tlb_t->num; entry++) {
294 tlb_entry_t *tlb;
295 ARMword mask;
296
297 tlb = &(tlb_t->entrys[entry]);
298 if (tlb->mapping == TLB_INVALID) {
299 continue;
300 }
301 mask = tlb_masks[tlb->mapping];
302 if ((virt_addr & mask) == (tlb->virt_addr & mask)) {
303 return tlb;
304 }
305 }
306 return NULL;
307}
diff --git a/src/core/arm/interpreter/mmu/tlb.h b/src/core/arm/interpreter/mmu/tlb.h
deleted file mode 100644
index 40856567b..000000000
--- a/src/core/arm/interpreter/mmu/tlb.h
+++ /dev/null
@@ -1,87 +0,0 @@
1#ifndef _MMU_TLB_H_
2#define _MMU_TLB_H_
3
4typedef enum tlb_mapping_t
5{
6 TLB_INVALID = 0,
7 TLB_SMALLPAGE = 1,
8 TLB_LARGEPAGE = 2,
9 TLB_SECTION = 3,
10 TLB_ESMALLPAGE = 4,
11 TLB_TINYPAGE = 5
12} tlb_mapping_t;
13
14extern ARMword tlb_masks[];
15
16/* Permissions bits in a TLB entry:
17 *
18 * 31 12 11 10 9 8 7 6 5 4 3 2 1 0
19 * +-------------+-----+-----+-----+-----+---+---+-------+
20 * Page:| | ap3 | ap2 | ap1 | ap0 | C | B | |
21 * +-------------+-----+-----+-----+-----+---+---+-------+
22 *
23 * 31 12 11 10 9 4 3 2 1 0
24 * +-------------+-----+-----------------+---+---+-------+
25 * Section: | | AP | | C | B | |
26 * +-------------+-----+-----------------+---+---+-------+
27 */
28
29/*
30section:
31 section base address [31:20]
32 AP - table 8-2, page 8-8
33 domain
34 C,B
35
36page:
37 page base address [31:16] or [31:12]
38 ap[3:0]
39 domain (from L1)
40 C,B
41*/
42
43
44typedef struct tlb_entry_t
45{
46 ARMword virt_addr;
47 ARMword phys_addr;
48 ARMword perms;
49 ARMword domain;
50 tlb_mapping_t mapping;
51} tlb_entry_t;
52
53typedef struct tlb_s
54{
55 int num; /*num of tlb entry */
56 int cycle; /*current tlb cycle */
57 tlb_entry_t *entrys;
58} tlb_s;
59
60
61#define tlb_c_flag(tlb) \
62 ((tlb)->perms & 0x8)
63#define tlb_b_flag(tlb) \
64 ((tlb)->perms & 0x4)
65
66#define tlb_va_to_pa(tlb, va) ((tlb->phys_addr & tlb_masks[tlb->mapping]) | (va & ~tlb_masks[tlb->mapping]))
67fault_t
68check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,
69 int read);
70
71fault_t
72translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t,
73 tlb_entry_t ** tlb);
74
75int mmu_tlb_init (tlb_s * tlb_t, int num);
76
77void mmu_tlb_exit (tlb_s * tlb_t);
78
79void mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t);
80
81void
82mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr);
83
84tlb_entry_t *mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t,
85 ARMword virt_addr);
86
87#endif /*_MMU_TLB_H_*/
diff --git a/src/core/arm/interpreter/mmu/wb.cpp b/src/core/arm/interpreter/mmu/wb.cpp
deleted file mode 100644
index 82c0cec02..000000000
--- a/src/core/arm/interpreter/mmu/wb.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
1#include "core/arm/interpreter/armdefs.h"
2
3/* wb_init
4 * @wb_t :wb_t to init
5 * @num :num of entrys
6 * @nb :num of byte of each entry
7 *
8 * $ -1:error
9 * 0:ok
10 * */
11int
12mmu_wb_init (wb_s * wb_t, int num, int nb)
13{
14 int i;
15 wb_entry_t *entrys, *wb;
16
17 entrys = (wb_entry_t *) malloc (sizeof (*entrys) * num);
18 if (entrys == NULL) {
19 ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*entrys) * num);
20 goto entrys_malloc_error;
21 }
22
23 for (wb = entrys, i = 0; i < num; i++, wb++) {
24 /*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu */
25 //wb->data = (ARMword *)malloc(sizeof(ARMword) * nb);
26 wb->data = (ARMbyte *) malloc (nb);
27 if (wb->data == NULL) {
28 ERROR_LOG(ARM11, "malloc size of %d\n", nb);
29 goto data_malloc_error;
30 }
31
32 };
33
34 wb_t->first = wb_t->last = wb_t->used = 0;
35 wb_t->num = num;
36 wb_t->nb = nb;
37 wb_t->entrys = entrys;
38 return 0;
39
40 data_malloc_error:
41 while (--i >= 0)
42 free (entrys[i].data);
43 free (entrys);
44 entrys_malloc_error:
45 return -1;
46};
47
48/* wb_exit
49 * @wb_t :wb_t to exit
50 * */
51void
52mmu_wb_exit (wb_s * wb_t)
53{
54 int i;
55 wb_entry_t *wb;
56
57 wb = wb_t->entrys;
58 for (i = 0; i < wb_t->num; i++, wb++) {
59 free (wb->data);
60 }
61 free (wb_t->entrys);
62};
63
64/* wb_write_words :put words in Write Buffer
65 * @state: ARMul_State
66 * @wb_t: write buffer
67 * @pa: physical address
68 * @data: data ptr
69 * @n number of word to write
70 *
71 * Note: write buffer merge is not implemented, can be done late
72 * */
73void
74mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa,
75 ARMbyte * data, int n)
76{
77 int i;
78 wb_entry_t *wb;
79
80 while (n) {
81 if (wb_t->num == wb_t->used) {
82 /*clean the last wb entry */
83 ARMword t;
84
85 wb = &wb_t->entrys[wb_t->last];
86 t = wb->pa;
87 for (i = 0; i < wb->nb; i++) {
88 //mem_write_byte (state, t, wb->data[i]);
89 bus_write(8, t, wb->data[i]);
90 //t += WORD_SIZE;
91 t++;
92 }
93 wb_t->last++;
94 if (wb_t->last == wb_t->num)
95 wb_t->last = 0;
96 wb_t->used--;
97 }
98
99 wb = &wb_t->entrys[wb_t->first];
100 i = (n < wb_t->nb) ? n : wb_t->nb;
101
102 wb->pa = pa;
103 //pa += i << WORD_SHT;
104 pa += i;
105
106 wb->nb = i;
107 //memcpy(wb->data, data, i << WORD_SHT);
108 memcpy (wb->data, data, i);
109 data += i;
110 n -= i;
111 wb_t->first++;
112 if (wb_t->first == wb_t->num)
113 wb_t->first = 0;
114 wb_t->used++;
115 };
116//teawater add for set_dirty fflash cache function 2005.07.18-------------------
117#ifdef DBCT
118 if (!skyeye_config.no_dbct) {
119 tb_setdirty (state, pa, NULL);
120 }
121#endif
122//AJ2D--------------------------------------------------------------------------
123}
124
125/* wb_drain_all
126 * @wb_t wb_t to drain
127 * */
128void
129mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t)
130{
131 ARMword pa;
132 wb_entry_t *wb;
133 int i;
134
135 while (wb_t->used) {
136 wb = &wb_t->entrys[wb_t->last];
137 pa = wb->pa;
138 for (i = 0; i < wb->nb; i++) {
139 //mem_write_byte (state, pa, wb->data[i]);
140 bus_write(8, pa, wb->data[i]);
141 //pa += WORD_SIZE;
142 pa++;
143 }
144 wb_t->last++;
145 if (wb_t->last == wb_t->num)
146 wb_t->last = 0;
147 wb_t->used--;
148 };
149}
diff --git a/src/core/arm/interpreter/mmu/wb.h b/src/core/arm/interpreter/mmu/wb.h
deleted file mode 100644
index 8fb7de946..000000000
--- a/src/core/arm/interpreter/mmu/wb.h
+++ /dev/null
@@ -1,63 +0,0 @@
1#ifndef _MMU_WB_H_
2#define _MMU_WB_H_
3
4typedef struct wb_entry_s
5{
6 ARMword pa; //phy_addr
7 ARMbyte *data; //data
8 int nb; //number byte to write
9} wb_entry_t;
10
11typedef struct wb_s
12{
13 int num; //number of wb_entry
14 int nb; //number of byte of each entry
15 int first; //
16 int last; //
17 int used; //
18 wb_entry_t *entrys;
19} wb_s;
20
21typedef struct wb_desc_s
22{
23 int num;
24 int nb;
25} wb_desc_t;
26
27/* wb_init
28 * @wb_t :wb_t to init
29 * @num :num of entrys
30 * @nw :num of word of each entry
31 *
32 * $ -1:error
33 * 0:ok
34 * */
35int mmu_wb_init (wb_s * wb_t, int num, int nb);
36
37
38/* wb_exit
39 * @wb_t :wb_t to exit
40 * */
41void mmu_wb_exit (wb_s * wb);
42
43
44/* wb_write_bytes :put bytess in Write Buffer
45 * @state: ARMul_State
46 * @wb_t: write buffer
47 * @pa: physical address
48 * @data: data ptr
49 * @n number of byte to write
50 *
51 * Note: write buffer merge is not implemented, can be done late
52 * */
53void
54mmu_wb_write_bytess (ARMul_State * state, wb_s * wb_t, ARMword pa,
55 ARMbyte * data, int n);
56
57
58/* wb_drain_all
59 * @wb_t wb_t to drain
60 * */
61void mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t);
62
63#endif /*_MMU_WB_H_*/
diff --git a/src/core/arm/interpreter/mmu/xscale_copro.cpp b/src/core/arm/interpreter/mmu/xscale_copro.cpp
deleted file mode 100644
index 433ce8e02..000000000
--- a/src/core/arm/interpreter/mmu/xscale_copro.cpp
+++ /dev/null
@@ -1,1391 +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#include <assert.h>
22#include <string.h>
23
24#include "core/arm/interpreter/armdefs.h"
25#include "core/arm/interpreter/armemu.h"
26
27/*#include "pxa.h" */
28
29/* chy 2005-09-19 */
30
31/* extern pxa270_io_t pxa270_io; */
32/* chy 2005-09-19 -----end */
33
34typedef struct xscale_mmu_desc_s
35{
36 int i_tlb;
37 cache_desc_t i_cache;
38
39 int d_tlb;
40 cache_desc_t main_d_cache;
41 cache_desc_t mini_d_cache;
42 //int rb; xscale has no read buffer
43 wb_desc_t wb;
44} xscale_mmu_desc_t;
45
46static xscale_mmu_desc_t pxa_mmu_desc = {
47 32,
48 {32, 32, 32, CACHE_WRITE_BACK},
49
50 32,
51 {32, 32, 32, CACHE_WRITE_BACK},
52 {32, 2, 8, CACHE_WRITE_BACK},
53 {8, 16}, //for byte size,
54};
55
56//chy 2005-09-19 for cp6
57#define CR0_ICIP 0
58#define CR1_ICMR 1
59//chy 2005-09-19 ---end
60//----------- for cp14-----------------
61#define CCLKCFG 6
62#define PWRMODE 7
63typedef struct xscale_cp14_reg_s
64{
65 unsigned cclkcfg; //reg6
66 unsigned pwrmode; //reg7
67} xscale_cp14_reg_s;
68
69xscale_cp14_reg_s pxa_cp14_regs;
70
71//--------------------------------------
72
73static fault_t xscale_mmu_write (ARMul_State * state, ARMword va,
74 ARMword data, ARMword datatype);
75static fault_t xscale_mmu_read (ARMul_State * state, ARMword va,
76 ARMword * data, ARMword datatype);
77
78ARMword xscale_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value);
79ARMword xscale_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value);
80
81
82/* jeff add 2010.9.26 for pxa270 cp6*/
83#define PXA270_ICMR 0x40D00004
84#define PXA270_ICPR 0x40D00010
85#define PXA270_ICLR 0x40D00008
86//chy 2005-09-19 for xscale pxa27x cp6
87unsigned
88xscale_cp6_mrc (ARMul_State * state, unsigned type, ARMword instr,
89 ARMword * data)
90{
91 unsigned opcode_2 = BITS (5, 7);
92 unsigned CRm = BITS (0, 3);
93 unsigned reg = BITS (16, 19);
94 unsigned result;
95
96 //printf("SKYEYE: xscale_cp6_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,state->Reg[15], instr);
97
98 switch (reg) {
99 case CR0_ICIP: { // cp 6 reg 0
100 //printf("cp6_mrc cr0 ICIP \n");
101 /* *data = (pxa270_io.icmr & pxa270_io.icpr) & ~pxa270_io.iclr; */
102 /* use bus_read get the pxa270 machine registers 2010.9.26 jeff*/
103 int icmr, icpr, iclr;
104 bus_read(32, PXA270_ICMR, (uint32_t*)&icmr);
105 bus_read(32, PXA270_ICPR, (uint32_t*)&icpr);
106 bus_read(32, PXA270_ICLR, (uint32_t*)&iclr);
107 *data = (icmr & icpr) & ~iclr;
108 }
109 break;
110 case CR1_ICMR: { // cp 6 reg 1
111 //printf("cp6_mrc cr1 ICMR\n");
112 /* *data = pxa270_io.icmr; */
113 int icmr;
114 /* use bus_read get the pxa270 machine registers 2010.9.26 jeff*/
115 bus_read(32, PXA270_ICMR, (uint32_t*)&icmr);
116 *data = icmr;
117 }
118 break;
119 default:
120 *data = 0;
121 printf ("SKYEYE:cp6_mrc unknown cp6 regs!!!!!!\n");
122 printf ("SKYEYE: xscale_cp6_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n", opcode_2, CRm, reg, state->Reg[15], instr);
123 break;
124 }
125 return 0;
126}
127
128//chy 2005-09-19 end
129//xscale cp13 ----------------------------------------------------
130unsigned
131xscale_cp13_init (ARMul_State * state)
132{
133 //printf("SKYEYE: xscale_cp13_init: begin\n");
134 return 0;
135}
136
137unsigned
138xscale_cp13_exit (ARMul_State * state)
139{
140 //printf("SKYEYE: xscale_cp13_exit: begin\n");
141 return 0;
142}
143
144unsigned
145xscale_cp13_ldc (ARMul_State * state, unsigned type, ARMword instr,
146 ARMword data)
147{
148 printf ("SKYEYE: xscale_cp13_ldc: ERROR isn't existed,");
149 SKYEYE_OUTREGS (stderr);
150 fprintf (stderr, "\n");
151 // skyeye_exit (-1);
152 return 0; //No matter return value, only for compiler.
153}
154
155unsigned
156xscale_cp13_stc (ARMul_State * state, unsigned type, ARMword instr,
157 ARMword * data)
158{
159 printf ("SKYEYE: xscale_cp13_stc: ERROR isn't existed,");
160 SKYEYE_OUTREGS (stderr);
161 fprintf (stderr, "\n");
162 // skyeye_exit (-1);
163 return 0; //No matter return value, only for compiler.
164}
165
166unsigned
167xscale_cp13_mrc (ARMul_State * state, unsigned type, ARMword instr,
168 ARMword * data)
169{
170 printf ("SKYEYE: xscale_cp13_mrc: ERROR isn't existed,");
171 SKYEYE_OUTREGS (stderr);
172 fprintf (stderr, "\n");
173 // skyeye_exit (-1);
174 return 0; //No matter return value, only for compiler.
175}
176
177unsigned
178xscale_cp13_mcr (ARMul_State * state, unsigned type, ARMword instr,
179 ARMword data)
180{
181 printf ("SKYEYE: xscale_cp13_mcr: ERROR isn't existed,");
182 SKYEYE_OUTREGS (stderr);
183 fprintf (stderr, "\n");
184 // skyeye_exit (-1);
185 return 0; //No matter return value, only for compiler.
186}
187
188unsigned
189xscale_cp13_cdp (ARMul_State * state, unsigned type, ARMword instr)
190{
191 printf ("SKYEYE: xscale_cp13_cdp: ERROR isn't existed,");
192 SKYEYE_OUTREGS (stderr);
193 fprintf (stderr, "\n");
194 // skyeye_exit (-1);
195 return 0; //No matter return value, only for compiler.
196}
197
198unsigned
199xscale_cp13_read_reg (ARMul_State * state, unsigned reg, ARMword * data)
200{
201 printf ("SKYEYE: xscale_cp13_read_reg: ERROR isn't existed,");
202 SKYEYE_OUTREGS (stderr);
203 fprintf (stderr, "\n");
204 return 0;
205 //exit(-1);
206}
207
208unsigned
209xscale_cp13_write_reg (ARMul_State * state, unsigned reg, ARMword data)
210{
211 printf ("SKYEYE: xscale_cp13_write_reg: ERROR isn't existed,");
212 SKYEYE_OUTREGS (stderr);
213 fprintf (stderr, "\n");
214 // skyeye_exit (-1);
215 return 0; //No matter return value, only for compiler.
216}
217
218//------------------------------------------------------------------
219//xscale cp14 ----------------------------------------------------
220unsigned
221xscale_cp14_init (ARMul_State * state)
222{
223 //printf("SKYEYE: xscale_cp14_init: begin\n");
224 pxa_cp14_regs.cclkcfg = 0;
225 pxa_cp14_regs.pwrmode = 0;
226 return 0;
227}
228
229unsigned
230xscale_cp14_exit (ARMul_State * state)
231{
232 //printf("SKYEYE: xscale_cp14_exit: begin\n");
233 return 0;
234}
235
236unsigned
237xscale_cp14_ldc (ARMul_State * state, unsigned type, ARMword instr,
238 ARMword data)
239{
240 printf ("SKYEYE: xscale_cp14_ldc: ERROR isn't existed, reg15 0x%x\n",
241 state->Reg[15]);
242 SKYEYE_OUTREGS (stderr);
243 // skyeye_exit (-1);
244 return 0; //No matter return value, only for compiler.
245}
246
247unsigned
248xscale_cp14_stc (ARMul_State * state, unsigned type, ARMword instr,
249 ARMword * data)
250{
251 printf ("SKYEYE: xscale_cp14_stc: ERROR isn't existed, reg15 0x%x\n",
252 state->Reg[15]);
253 SKYEYE_OUTREGS (stderr);
254 // skyeye_exit (-1);
255 return 0; //No matter return value, only for compiler.
256}
257
258unsigned
259xscale_cp14_mrc (ARMul_State * state, unsigned type, ARMword instr,
260 ARMword * data)
261{
262 unsigned opcode_2 = BITS (5, 7);
263 unsigned CRm = BITS (0, 3);
264 unsigned reg = BITS (16, 19);
265 unsigned result;
266
267 //printf("SKYEYE: xscale_cp14_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\
268 state->Reg[15], instr);
269
270 switch (reg) {
271 case CCLKCFG: // cp 14 reg 6
272 //printf("cp14_mrc cclkcfg \n");
273 *data = pxa_cp14_regs.cclkcfg;
274 break;
275 case PWRMODE: // cp 14 reg 7
276 //printf("cp14_mrc pwrmode \n");
277 *data = pxa_cp14_regs.pwrmode;
278 break;
279 default:
280 *data = 0;
281 printf ("SKYEYE:cp14_mrc unknown cp14 regs!!!!!!\n");
282 break;
283 }
284 return 0;
285}
286unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type, ARMword instr,
287 ARMword data)
288{
289 unsigned opcode_2 = BITS (5, 7);
290 unsigned CRm = BITS (0, 3);
291 unsigned reg = BITS (16, 19);
292 unsigned result;
293
294 //printf("SKYEYE: xscale_cp14_mcr:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\
295 state->Reg[15], instr);
296
297 switch (reg) {
298 case CCLKCFG: // cp 14 reg 6
299 //printf("cp14_mcr cclkcfg \n");
300 pxa_cp14_regs.cclkcfg = data & 0xf;
301 break;
302 case PWRMODE: // cp 14 reg 7
303 //printf("cp14_mcr pwrmode \n");
304 pxa_cp14_regs.pwrmode = data & 0x3;
305 break;
306 default:printf ("SKYEYE: cp14_mcr unknown cp14 regs!!!!!!\n");
307 break;
308 }
309 return 0;
310}
311unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type, ARMword instr)
312{
313 printf ("SKYEYE: xscale_cp14_cdp: ERROR isn't existed, reg15 0x%x\n",
314 state->Reg[15]);
315 SKYEYE_OUTREGS (stderr);
316 // skyeye_exit (-1);
317 return 0; //No matter return value, only for compiler.
318}
319unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg,
320 ARMword * data)
321{
322 printf ("SKYEYE: xscale_cp14_read_reg: ERROR isn't existed, reg15 0x%x\n", state->Reg[15]);
323 SKYEYE_OUTREGS (stderr);
324 // skyeye_exit (-1);
325 return 0; //No matter return value, only for compiler.
326}
327unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg,
328 ARMword data)
329{
330 printf ("SKYEYE: xscale_cp14_write_reg: ERROR isn't existed, reg15 0x%x\n", state->Reg[15]);
331 SKYEYE_OUTREGS (stderr);
332 // skyeye_exit (-1);
333
334 return 0; //No matter return value, only for compiler.
335}
336
337//------------------------------------------------------------------
338//cp15 -------------------------------------
339unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type, ARMword instr,
340 ARMword data)
341{
342 printf ("SKYEYE: xscale_cp15_ldc: ERROR isn't existed\n");
343 SKYEYE_OUTREGS (stderr);
344 // skyeye_exit (-1);
345
346 return 0; //No matter return value, only for compiler.
347}
348unsigned xscale_cp15_stc (ARMul_State * state, unsigned type, ARMword instr,
349 ARMword * data)
350{
351 printf ("SKYEYE: xscale_cp15_stc: ERROR isn't existed\n");
352 SKYEYE_OUTREGS (stderr);
353 // skyeye_exit (-1);
354
355 return 0; //No matter return value, only for compiler.
356}
357unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type, ARMword instr)
358{
359 printf ("SKYEYE: xscale_cp15_cdp: ERROR isn't existed\n");
360 SKYEYE_OUTREGS (stderr);
361 // skyeye_exit (-1);
362
363 return 0; //No matter return value, only for compiler.
364}
365unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg,
366 ARMword * data)
367{
368//chy 2003-09-03: for xsacle_cp15_cp_access_allowed
369 if (reg == 15) {
370 *data = state->mmu.copro_access;
371 //printf("SKYEYE: xscale_cp15_read_reg: reg 0x%x,data %x\n",reg,*data);
372 return 0;
373 }
374 printf ("SKYEYE: xscale_cp15_read_reg: reg 0x%x, ERROR isn't existed\n", reg);
375 SKYEYE_OUTREGS (stderr);
376 // skyeye_exit (-1);
377
378 return 0; //No matter return value, only for compiler.
379}
380
381//chy 2003-09-03 used by macro CP_ACCESS_ALLOWED in armemu.h
382unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
383 unsigned cpnum)
384{
385 unsigned data;
386
387 xscale_cp15_read_reg (state, reg, &data);
388 //printf("SKYEYE: cp15_cp_access_allowed data %x, cpnum %x, result %x\n", data, cpnum, (data & 1<<cpnum));
389 if (data & 1 << cpnum)
390 return 1;
391 else
392 return 0;
393}
394
395unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg,
396 ARMword value)
397{
398 switch (reg) {
399 case MMU_FAULT_STATUS:
400 //printf("SKYEYE:cp15_write_reg wrote FS val 0x%x \n",value);
401 state->mmu.fault_status = value & 0x6FF;
402 break;
403 case MMU_FAULT_ADDRESS:
404 //printf("SKYEYE:cp15_write_reg wrote FA val 0x%x \n",value);
405 state->mmu.fault_address = value;
406 break;
407 default:
408 printf ("SKYEYE: xscale_cp15_write_reg: reg 0x%x R15 %x ERROR isn't existed\n", reg, state->Reg[15]);
409 SKYEYE_OUTREGS (stderr);
410 // skyeye_exit (-1);
411 }
412 return 0;
413}
414
415unsigned
416xscale_cp15_init (ARMul_State * state)
417{
418 xscale_mmu_desc_t *desc;
419 cache_desc_t *c_desc;
420
421 state->mmu.control = 0;
422 state->mmu.translation_table_base = 0xDEADC0DE;
423 state->mmu.domain_access_control = 0xDEADC0DE;
424 state->mmu.fault_status = 0;
425 state->mmu.fault_address = 0;
426 state->mmu.process_id = 0;
427 state->mmu.cache_type = 0xB1AA1AA; //0000 1011 0001 1010 1010 0001 1010 1010
428 state->mmu.aux_control = 0;
429
430 desc = &pxa_mmu_desc;
431
432 if (mmu_tlb_init (I_TLB (), desc->i_tlb)) {
433 ERROR_LOG(ARM11, "i_tlb init %d\n", -1);
434 goto i_tlb_init_error;
435 }
436
437 c_desc = &desc->i_cache;
438 if (mmu_cache_init (I_CACHE (), c_desc->width, c_desc->way,
439 c_desc->set, c_desc->w_mode)) {
440 ERROR_LOG(ARM11, "i_cache init %d\n", -1);
441 goto i_cache_init_error;
442 }
443
444 if (mmu_tlb_init (D_TLB (), desc->d_tlb)) {
445 ERROR_LOG(ARM11, "d_tlb init %d\n", -1);
446 goto d_tlb_init_error;
447 }
448
449 c_desc = &desc->main_d_cache;
450 if (mmu_cache_init (MAIN_D_CACHE (), c_desc->width, c_desc->way,
451 c_desc->set, c_desc->w_mode)) {
452 ERROR_LOG(ARM11, "main_d_cache init %d\n", -1);
453 goto main_d_cache_init_error;
454 }
455
456 c_desc = &desc->mini_d_cache;
457 if (mmu_cache_init (MINI_D_CACHE (), c_desc->width, c_desc->way,
458 c_desc->set, c_desc->w_mode)) {
459 ERROR_LOG(ARM11, "mini_d_cache init %d\n", -1);
460 goto mini_d_cache_init_error;
461 }
462
463 if (mmu_wb_init (WB (), desc->wb.num, desc->wb.nb)) {
464 ERROR_LOG(ARM11, "wb init %d\n", -1);
465 goto wb_init_error;
466 }
467#if 0
468 if (mmu_rb_init (RB (), desc->rb)) {
469 ERROR_LOG(ARM11, "rb init %d\n", -1);
470 goto rb_init_error;
471 }
472#endif
473
474 return 0;
475#if 0
476 rb_init_error:
477 mmu_wb_exit (WB ());
478#endif
479 wb_init_error:
480 mmu_cache_exit (MINI_D_CACHE ());
481 mini_d_cache_init_error:
482 mmu_cache_exit (MAIN_D_CACHE ());
483 main_d_cache_init_error:
484 mmu_tlb_exit (D_TLB ());
485 d_tlb_init_error:
486 mmu_cache_exit (I_CACHE ());
487 i_cache_init_error:
488 mmu_tlb_exit (I_TLB ());
489 i_tlb_init_error:
490 return -1;
491}
492
493unsigned
494xscale_cp15_exit (ARMul_State * state)
495{
496 //mmu_rb_exit(RB());
497 mmu_wb_exit (WB ());
498 mmu_cache_exit (MINI_D_CACHE ());
499 mmu_cache_exit (MAIN_D_CACHE ());
500 mmu_tlb_exit (D_TLB ());
501 mmu_cache_exit (I_CACHE ());
502 mmu_tlb_exit (I_TLB ());
503 return 0;
504};
505
506
507static fault_t
508 xscale_mmu_load_instr (ARMul_State * state, ARMword va,
509 ARMword * instr)
510{
511 fault_t fault;
512 tlb_entry_t *tlb;
513 cache_line_t *cache;
514 int c; //cache bit
515 ARMword pa; //physical addr
516
517 static int debug_count = 0; //used for debug
518
519 DEBUG_LOG(ARM11, "va = %x\n", va);
520
521 va = mmu_pid_va_map (va);
522 if (MMU_Enabled) {
523 /*align check */
524 if ((va & (INSN_SIZE - 1)) && MMU_Aligned) {
525 DEBUG_LOG(ARM11, "align\n");
526 return ALIGNMENT_FAULT;
527 }
528 else
529 va &= ~(INSN_SIZE - 1);
530
531 /*translate tlb */
532 fault = translate (state, va, I_TLB (), &tlb);
533 if (fault) {
534 DEBUG_LOG(ARM11, "translate\n");
535 return fault;
536 }
537
538 /*check access */
539 fault = check_access (state, va, tlb, 1);
540 if (fault) {
541 DEBUG_LOG(ARM11, "check_fault\n");
542 return fault;
543 }
544 }
545 //chy 2003-09-02 for test, don't use cache ?????
546#if 0
547 /*search cache no matter MMU enabled/disabled */
548 cache = mmu_cache_search (state, I_CACHE (), va);
549 if (cache) {
550 *instr = cache->data[va_cache_index (va, I_CACHE ())];
551 return 0;
552 }
553#endif
554 /*if MMU disabled or C flag is set alloc cache */
555 if (MMU_Disabled) {
556 c = 1;
557 pa = va;
558 }
559 else {
560 c = tlb_c_flag (tlb);
561 pa = tlb_va_to_pa (tlb, va);
562 }
563
564 //chy 2003-09-03 only read mem, don't use cache now,will change later ????
565 //*instr = mem_read_word (state, pa);
566 bus_read(32, pa, instr);
567#if 0
568//-----------------------------------------------------------
569 //chy 2003-09-02 for test????
570 if (pa >= 0xa01c8000 && pa <= 0xa01c8020) {
571 printf ("SKYEYE:load_instr: pa %x, va %x,instr %x, R15 %x\n",
572 pa, va, *instr, state->Reg[15]);
573 }
574
575//----------------------------------------------------------------------
576#endif
577 return NO_FAULT;
578
579 if (c) {
580 int index;
581
582 debug_count++;
583 cache = mmu_cache_alloc (state, I_CACHE (), va, pa);
584 index = va_cache_index (va, I_CACHE ());
585 *instr = cache->data[va_cache_index (va, I_CACHE ())];
586 }
587 else
588 //*instr = mem_read_word (state, pa);
589 bus_read(32, pa, instr);
590
591 return NO_FAULT;
592};
593
594
595
596static fault_t
597 xscale_mmu_read_byte (ARMul_State * state, ARMword virt_addr,
598 ARMword * data)
599{
600 //ARMword temp,offset;
601 fault_t fault;
602 fault = xscale_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE);
603 return fault;
604}
605
606static fault_t
607 xscale_mmu_read_halfword (ARMul_State * state, ARMword virt_addr,
608 ARMword * data)
609{
610 //ARMword temp,offset;
611 fault_t fault;
612 fault = xscale_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE);
613 return fault;
614}
615
616static fault_t
617 xscale_mmu_read_word (ARMul_State * state, ARMword virt_addr,
618 ARMword * data)
619{
620 return xscale_mmu_read (state, virt_addr, data, ARM_WORD_TYPE);
621}
622
623
624
625
626static fault_t
627 xscale_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
628 ARMword datatype)
629{
630 fault_t fault;
631// rb_entry_t *rb;
632 tlb_entry_t *tlb;
633 cache_line_t *cache;
634 ARMword pa, real_va, temp, offset;
635 //chy 2003-09-02 for test ????
636 static unsigned chyst1 = 0, chyst2 = 0;
637
638 DEBUG_LOG(ARM11, "va = %x\n", va);
639
640 va = mmu_pid_va_map (va);
641 real_va = va;
642 /*if MMU disabled, memory_read */
643 if (MMU_Disabled) {
644 //*data = mem_read_word(state, va);
645 if (datatype == ARM_BYTE_TYPE)
646 //*data = mem_read_byte (state, va);
647 bus_read(8, va, data);
648 else if (datatype == ARM_HALFWORD_TYPE)
649 //*data = mem_read_halfword (state, va);
650 bus_read(16, va, data);
651 else if (datatype == ARM_WORD_TYPE)
652 //*data = mem_read_word (state, va);
653 bus_read(32, va, data);
654 else {
655 printf ("SKYEYE:1 xscale_mmu_read error: unknown data type %d\n", datatype);
656 // skyeye_exit (-1);
657 }
658
659 return NO_FAULT;
660 }
661
662 /*align check */
663 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
664 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
665 DEBUG_LOG(ARM11, "align\n");
666 return ALIGNMENT_FAULT;
667 } // else
668
669 va &= ~(WORD_SIZE - 1);
670
671 /*translate va to tlb */
672 fault = translate (state, va, D_TLB (), &tlb);
673 if (fault) {
674 DEBUG_LOG(ARM11, "translate\n");
675 return fault;
676 }
677 /*check access permission */
678 fault = check_access (state, va, tlb, 1);
679 if (fault)
680 return fault;
681
682#if 0
683//------------------------------------------------
684//chy 2003-09-02 for test only ,should commit ????
685 if (datatype == ARM_WORD_TYPE) {
686 if (real_va >= 0xffff0000 && real_va <= 0xffff0020) {
687 pa = tlb_va_to_pa (tlb, va);
688 *data = mem_read_word (state, pa);
689 chyst1++;
690 printf ("**SKYEYE:mmu_read word %d: pa %x, va %x, data %x, R15 %x\n", chyst1, pa, real_va, *data, state->Reg[15]);
691 /*
692 cache==mmu_cache_search(state,MAIN_D_CACHE(),va);
693 if(cache){
694 *data = cache->data[va_cache_index(va, MAIN_D_CACHE())];
695 printf("cached data %x\n",*data);
696 }else printf("no cached data\n");
697 */
698 }
699 }
700//-------------------------------------------------
701#endif
702#if 0
703 /*search in read buffer */
704 rb = mmu_rb_search (RB (), va);
705 if (rb) {
706 if (rb->fault)
707 return rb->fault;
708 *data = rb->data[(va & (rb_masks[rb->type] - 1)) >> WORD_SHT];
709 goto datatrans;
710 //return 0;
711 };
712#endif
713
714 /*2004-07-19 chy: add support of xscale MMU CacheDisabled option */
715 if (MMU_CacheDisabled) {
716 //if(1){ can be used to test cache error
717 /*get phy_addr */
718 pa = tlb_va_to_pa (tlb, real_va);
719 if (datatype == ARM_BYTE_TYPE)
720 //*data = mem_read_byte (state, pa);
721 bus_read(8, pa, data);
722 else if (datatype == ARM_HALFWORD_TYPE)
723 //*data = mem_read_halfword (state, pa);
724 bus_read(16, pa, data);
725 else if (datatype == ARM_WORD_TYPE)
726 //*data = mem_read_word (state, pa);
727 bus_read(32, pa, data);
728 else {
729 printf ("SKYEYE:MMU_CacheDisabled xscale_mmu_read error: unknown data type %d\n", datatype);
730 // skyeye_exit (-1);
731 }
732 return NO_FAULT;
733 }
734
735
736 /*search main cache */
737 cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
738 if (cache) {
739 *data = cache->data[va_cache_index (va, MAIN_D_CACHE ())];
740#if 0
741//------------------------------------------------------------------------
742//chy 2003-09-02 for test only ,should commit ????
743 if (real_va >= 0xffff0000 && real_va <= 0xffff0020) {
744 pa = tlb_va_to_pa (tlb, va);
745 chyst2++;
746 printf ("**SKYEYE:mmu_read wordk:cache %d: pa %x, va %x, data %x, R15 %x\n", chyst2, pa, real_va, *data, state->Reg[15]);
747 }
748//-------------------------------------------------------------------
749#endif
750 goto datatrans;
751 //return 0;
752 }
753 //chy 2003-08-24, now maybe we don't need minidcache ????
754#if 0
755 /*search mini cache */
756 cache = mmu_cache_search (state, MINI_D_CACHE (), va);
757 if (cache) {
758 *data = cache->data[va_cache_index (va, MINI_D_CACHE ())];
759 goto datatrans;
760 //return 0;
761 }
762#endif
763 /*get phy_addr */
764 pa = tlb_va_to_pa (tlb, va);
765 //chy 2003-08-24 , in xscale it means what ?????
766#if 0
767 if ((pa >= 0xe0000000) && (pa < 0xe8000000)) {
768
769 if (tlb_c_flag (tlb)) {
770 if (tlb_b_flag (tlb)) {
771 mmu_cache_soft_flush (state, MAIN_D_CACHE (),
772 pa);
773 }
774 else {
775 mmu_cache_soft_flush (state, MINI_D_CACHE (),
776 pa);
777 }
778 }
779 return 0;
780 }
781#endif
782 //chy 2003-08-24, check phy addr
783 //ywc 2004-11-30, inactive this check because of using 0xc0000000 as the framebuffer start address
784 /*
785 if(pa >= 0xb0000000){
786 printf("SKYEYE:xscale_mmu_read: phy address 0x%x error,reg[15] 0x%x\n",pa,state->Reg[15]);
787 return 0;
788 }
789 */
790
791 //chy 2003-08-24, now maybe we don't need wb ????
792#if 0
793 /*if Buffer, drain Write Buffer first */
794 if (tlb_b_flag (tlb))
795 mmu_wb_drain_all (state, WB ());
796#endif
797 /*alloc cache or mem_read */
798 if (tlb_c_flag (tlb) && MMU_DCacheEnabled) {
799 cache_s *cache_t;
800
801 if (tlb_b_flag (tlb))
802 cache_t = MAIN_D_CACHE ();
803 else
804 cache_t = MINI_D_CACHE ();
805 cache = mmu_cache_alloc (state, cache_t, va, pa);
806 *data = cache->data[va_cache_index (va, cache_t)];
807 }
808 else {
809 //*data = mem_read_word(state, pa);
810 if (datatype == ARM_BYTE_TYPE)
811 //*data = mem_read_byte (state, pa | (real_va & 3));
812 bus_read(8, pa | (real_va & 3), data);
813 else if (datatype == ARM_HALFWORD_TYPE)
814 //*data = mem_read_halfword (state, pa | (real_va & 2));
815 bus_read(16, pa | (real_va & 2), data);
816 else if (datatype == ARM_WORD_TYPE)
817 //*data = mem_read_word (state, pa);
818 bus_read(32, pa, data);
819 else {
820 printf ("SKYEYE:2 xscale_mmu_read error: unknown data type %d\n", datatype);
821 // skyeye_exit (-1);
822 }
823 return NO_FAULT;
824 }
825
826
827 datatrans:
828 if (datatype == ARM_HALFWORD_TYPE) {
829 temp = *data;
830 offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
831 *data = (temp >> offset) & 0xffff;
832 }
833 else if (datatype == ARM_BYTE_TYPE) {
834 temp = *data;
835 offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
836 *data = (temp >> offset & 0xffL);
837 }
838 end:
839 return NO_FAULT;
840}
841
842
843static fault_t
844 xscale_mmu_write_byte (ARMul_State * state, ARMword virt_addr,
845 ARMword data)
846{
847 return xscale_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE);
848}
849
850static fault_t
851 xscale_mmu_write_halfword (ARMul_State * state, ARMword virt_addr,
852 ARMword data)
853{
854 return xscale_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE);
855}
856
857static fault_t
858 xscale_mmu_write_word (ARMul_State * state, ARMword virt_addr,
859 ARMword data)
860{
861 return xscale_mmu_write (state, virt_addr, data, ARM_WORD_TYPE);
862}
863
864
865
866static fault_t
867 xscale_mmu_write (ARMul_State * state, ARMword va, ARMword data,
868 ARMword datatype)
869{
870 tlb_entry_t *tlb;
871 cache_line_t *cache;
872 cache_s *cache_t;
873 int b;
874 ARMword pa, real_va, temp, offset;
875 fault_t fault;
876
877 ARMword index;
878//chy 2003-09-02 for test ????
879// static unsigned chyst1=0,chyst2=0;
880
881 DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data);
882 va = mmu_pid_va_map (va);
883 real_va = va;
884
885 if (MMU_Disabled) {
886 //mem_write_word(state, va, data);
887 if (datatype == ARM_BYTE_TYPE)
888 //mem_write_byte (state, va, data);
889 bus_write(8, va, data);
890 else if (datatype == ARM_HALFWORD_TYPE)
891 //mem_write_halfword (state, va, data);
892 bus_write(16, va, data);
893 else if (datatype == ARM_WORD_TYPE)
894 //mem_write_word (state, va, data);
895 bus_write(32, va, data);
896 else {
897 printf ("SKYEYE:1 xscale_mmu_write error: unknown data type %d\n", datatype);
898 // skyeye_exit (-1);
899 }
900
901 return NO_FAULT;
902 }
903 /*align check */
904 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
905 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
906 DEBUG_LOG(ARM11, "align\n");
907 return ALIGNMENT_FAULT;
908 } //else
909 va &= ~(WORD_SIZE - 1);
910 /*tlb translate */
911 fault = translate (state, va, D_TLB (), &tlb);
912 if (fault) {
913 DEBUG_LOG(ARM11, "translate\n");
914 return fault;
915 }
916 /*tlb check access */
917 fault = check_access (state, va, tlb, 0);
918 if (fault) {
919 DEBUG_LOG(ARM11, "check_access\n");
920 return fault;
921 }
922
923 /*2004-07-19 chy: add support for xscale MMU_CacheDisabled */
924 if (MMU_CacheDisabled) {
925 //if(1){ can be used to test the cache error
926 /*get phy_addr */
927 pa = tlb_va_to_pa (tlb, real_va);
928 if (datatype == ARM_BYTE_TYPE)
929 //mem_write_byte (state, pa, data);
930 bus_write(8, pa, data);
931 else if (datatype == ARM_HALFWORD_TYPE)
932 //mem_write_halfword (state, pa, data);
933 bus_write(16, pa, data);
934 else if (datatype == ARM_WORD_TYPE)
935 //mem_write_word (state, pa, data);
936 bus_write(32, pa , data);
937 else {
938 printf ("SKYEYE:MMU_CacheDisabled xscale_mmu_write error: unknown data type %d\n", datatype);
939 // skyeye_exit (-1);
940 }
941
942 return NO_FAULT;
943 }
944
945 /*search main cache */
946 b = tlb_b_flag (tlb);
947 pa = tlb_va_to_pa (tlb, va);
948 cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
949 if (cache) {
950 cache_t = MAIN_D_CACHE ();
951 goto has_cache;
952 }
953 //chy 2003-08-24, now maybe we don't need minidcache ????
954#if 0
955 /*search mini cache */
956 cache = mmu_cache_search (state, MINI_D_CACHE (), va);
957 if (cache) {
958 cache_t = MINI_D_CACHE ();
959 goto has_cache;
960 }
961#endif
962 b = tlb_b_flag (tlb);
963 pa = tlb_va_to_pa (tlb, va);
964 //chy 2003-08-24, check phy addr 0xa0000000, size 0x04000000
965 //ywc 2004-11-30, inactive this check because of using 0xc0000000 as the framebuffer start address
966 /*
967 if(pa >= 0xb0000000){
968 printf("SKYEYE:xscale_mmu_write phy address 0x%x error,reg[15] 0x%x\n",pa,state->Reg[15]);
969 return 0;
970 }
971 */
972
973 //chy 2003-08-24, now maybe we don't need WB ????
974#if 0
975 if (b) {
976 if (MMU_WBEnabled) {
977 if (datatype == ARM_WORD_TYPE)
978 mmu_wb_write_bytes (state, WB (), pa, &data,
979 4);
980 else if (datatype == ARM_HALFWORD_TYPE)
981 mmu_wb_write_bytes (state, WB (),
982 (pa | (real_va & 2)),
983 &data, 2);
984 else if (datatype == ARM_BYTE_TYPE)
985 mmu_wb_write_bytes (state, WB (),
986 (pa | (real_va & 3)),
987 &data, 1);
988
989 }
990 else {
991 if (datatype == ARM_WORD_TYPE)
992 mem_write_word (state, pa, data);
993 else if (datatype == ARM_HALFWORD_TYPE)
994 mem_write_halfword (state,
995 (pa | (real_va & 2)),
996 data);
997 else if (datatype == ARM_BYTE_TYPE)
998 mem_write_byte (state, (pa | (real_va & 3)),
999 data);
1000 }
1001 }
1002 else {
1003
1004 mmu_wb_drain_all (state, WB ());
1005
1006 if (datatype == ARM_WORD_TYPE)
1007 mem_write_word (state, pa, data);
1008 else if (datatype == ARM_HALFWORD_TYPE)
1009 mem_write_halfword (state, (pa | (real_va & 2)),
1010 data);
1011 else if (datatype == ARM_BYTE_TYPE)
1012 mem_write_byte (state, (pa | (real_va & 3)), data);
1013 }
1014#endif
1015 //chy 2003-08-24, just write phy addr
1016 if (datatype == ARM_WORD_TYPE)
1017 //mem_write_word (state, pa, data);
1018 bus_write(32, pa, data);
1019 else if (datatype == ARM_HALFWORD_TYPE)
1020 //mem_write_halfword (state, (pa | (real_va & 2)), data);
1021 bus_write(16, pa | (real_va & 2), data);
1022 else if (datatype == ARM_BYTE_TYPE)
1023 //mem_write_byte (state, (pa | (real_va & 3)), data);
1024 bus_write(8, (pa | (real_va & 3)), data);
1025#if 0
1026//-------------------------------------------------------------
1027//chy 2003-09-02 for test ????
1028 if (datatype == ARM_WORD_TYPE) {
1029 if (real_va >= 0xffff0000 && real_va <= 0xffff0020) {
1030 printf ("**SKYEYE:mmu_write word: pa %x, va %x, data %x, R15 %x \n", pa, real_va, data, state->Reg[15]);
1031 }
1032 }
1033//--------------------------------------------------------------
1034#endif
1035 return NO_FAULT;
1036
1037 has_cache:
1038 index = va_cache_index (va, cache_t);
1039 //cache->data[index] = data;
1040
1041 if (datatype == ARM_WORD_TYPE)
1042 cache->data[index] = data;
1043 else if (datatype == ARM_HALFWORD_TYPE) {
1044 temp = cache->data[index];
1045 offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
1046 cache->data[index] =
1047 (temp & ~(0xffffL << offset)) | ((data & 0xffffL) <<
1048 offset);
1049 }
1050 else if (datatype == ARM_BYTE_TYPE) {
1051 temp = cache->data[index];
1052 offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
1053 cache->data[index] =
1054 (temp & ~(0xffL << offset)) | ((data & 0xffL) <<
1055 offset);
1056 }
1057
1058 if (index < (cache_t->width >> (WORD_SHT + 1)))
1059 cache->tag |= TAG_FIRST_HALF_DIRTY;
1060 else
1061 cache->tag |= TAG_LAST_HALF_DIRTY;
1062//-------------------------------------------------------------
1063//chy 2003-09-03 be sure the changed value will be in memory as soon as possible, so I cache can get the newest value
1064#if 0
1065 {
1066 if (datatype == ARM_WORD_TYPE)
1067 mem_write_word (state, pa, data);
1068 else if (datatype == ARM_HALFWORD_TYPE)
1069 mem_write_halfword (state, (pa | (real_va & 2)),
1070 data);
1071 else if (datatype == ARM_BYTE_TYPE)
1072 mem_write_byte (state, (pa | (real_va & 3)), data);
1073 }
1074#endif
1075#if 0
1076//chy 2003-09-02 for test ????
1077 if (datatype == ARM_WORD_TYPE) {
1078 if (real_va >= 0xffff0000 && real_va <= 0xffff0020) {
1079 printf ("**SKYEYE:mmu_write word:cache: pa %x, va %x, data %x, R15 %x\n", pa, real_va, data, state->Reg[15]);
1080 }
1081 }
1082//-------------------------------------------------------------
1083#endif
1084 if (datatype == ARM_WORD_TYPE)
1085 //mem_write_word (state, pa, data);
1086 bus_write(32, pa, data);
1087 else if (datatype == ARM_HALFWORD_TYPE)
1088 //mem_write_halfword (state, (pa | (real_va & 2)), data);
1089 bus_write(16, pa | (real_va & 2), data);
1090 else if (datatype == ARM_BYTE_TYPE)
1091 //mem_write_byte (state, (pa | (real_va & 3)), data);
1092 bus_write(8, (pa | (real_va & 3)), data);
1093 return NO_FAULT;
1094}
1095
1096ARMword xscale_cp15_mrc (ARMul_State * state,
1097 unsigned type, ARMword instr, ARMword * value)
1098{
1099 return xscale_mmu_mrc (state, instr, value);
1100}
1101
1102ARMword xscale_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
1103{
1104 ARMword data;
1105 unsigned opcode_2 = BITS (5, 7);
1106 unsigned CRm = BITS (0, 3);
1107 unsigned reg = BITS (16, 19);
1108 unsigned result;
1109 mmu_regnum_t creg = (mmu_regnum_t)reg;
1110
1111/*
1112 printf("SKYEYE: xscale_cp15_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\
1113 state->Reg[15], instr);
1114*/
1115 switch (creg) {
1116 case MMU_ID: //XSCALE_CP15
1117 //printf("mmu_mrc read ID \n");
1118 data = (opcode_2 ? state->mmu.cache_type : state->cpu->
1119 cpu_val);
1120 break;
1121 case MMU_CONTROL: //XSCALE_CP15_AUX_CONTROL
1122 //printf("mmu_mrc read CONTROL \n");
1123 data = (opcode_2 ? state->mmu.aux_control : state->mmu.
1124 control);
1125 break;
1126 case MMU_TRANSLATION_TABLE_BASE:
1127 //printf("mmu_mrc read TTB \n");
1128 data = state->mmu.translation_table_base;
1129 break;
1130 case MMU_DOMAIN_ACCESS_CONTROL:
1131 //printf("mmu_mrc read DACR \n");
1132 data = state->mmu.domain_access_control;
1133 break;
1134 case MMU_FAULT_STATUS:
1135 //printf("mmu_mrc read FSR \n");
1136 data = state->mmu.fault_status;
1137 break;
1138 case MMU_FAULT_ADDRESS:
1139 //printf("mmu_mrc read FAR \n");
1140 data = state->mmu.fault_address;
1141 break;
1142 case MMU_PID:
1143 //printf("mmu_mrc read PID \n");
1144 data = state->mmu.process_id;
1145 case XSCALE_CP15_COPRO_ACCESS:
1146 //printf("xscale cp15 read coprocessor access\n");
1147 data = state->mmu.copro_access;
1148 break;
1149 default:
1150 data = 0;
1151 printf ("SKYEYE: xscale_cp15_mrc read UNKNOWN - reg %d, pc 0x%x\n", creg, state->Reg[15]);
1152 // skyeye_exit (-1);
1153 break;
1154 }
1155 *value = data;
1156 //printf("SKYEYE: xscale_cp15_mrc:end value 0x%x\n",data);
1157 return ARMul_DONE;
1158}
1159
1160void xscale_cp15_cache_ops (ARMul_State * state, ARMword instr, ARMword value)
1161{
1162//chy: 2003-08-24 now, the BTB isn't simualted ....????
1163
1164 unsigned CRm, OPC_2;
1165
1166 CRm = BITS (0, 3);
1167 OPC_2 = BITS (5, 7);
1168 //err_msg("SKYEYE: xscale cp15_cache_ops:OPC_2 = 0x%x CRm = 0x%x, Reg15 0x%x\n", OPC_2, CRm,state->Reg[15]);
1169
1170 if (OPC_2 == 0 && CRm == 7) {
1171 mmu_cache_invalidate_all (state, I_CACHE ());
1172 mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
1173 return;
1174 }
1175
1176 if (OPC_2 == 0 && CRm == 5) {
1177 mmu_cache_invalidate_all (state, I_CACHE ());
1178 return;
1179 }
1180 if (OPC_2 == 1 && CRm == 5) {
1181 mmu_cache_invalidate (state, I_CACHE (), value);
1182 return;
1183 }
1184
1185 if (OPC_2 == 0 && CRm == 6) {
1186 mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
1187 return;
1188 }
1189
1190 if (OPC_2 == 1 && CRm == 6) {
1191 mmu_cache_invalidate (state, MAIN_D_CACHE (), value);
1192 return;
1193 }
1194
1195 if (OPC_2 == 1 && CRm == 0xa) {
1196 mmu_cache_clean (state, MAIN_D_CACHE (), value);
1197 return;
1198 }
1199
1200 if (OPC_2 == 4 && CRm == 0xa) {
1201 mmu_wb_drain_all (state, WB ());
1202 return;
1203 }
1204
1205 if (OPC_2 == 6 && CRm == 5) {
1206 //chy 2004-07-19 shoud fix in the future????!!!!
1207 //printf("SKYEYE: xscale_cp15_cache_ops:invalidate BTB CANT!!!!!!!!!!\n");
1208 //exit(-1);
1209 return;
1210 }
1211
1212 if (OPC_2 == 5 && CRm == 2) {
1213 //printf("SKYEYE: cp15_c_o: A L in D C, value %x, reg15 %x\n",value, state->Reg[15]);
1214 //exit(-1);
1215 //chy 2003-09-01 for test
1216 mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
1217 return;
1218 }
1219
1220 ERROR_LOG(ARM11, "SKYEYE: xscale cp15_cache_ops:Unknown OPC_2 = 0x%x CRm = 0x%x, Reg15 0x%x\n", OPC_2, CRm, state->Reg[15]);
1221 // skyeye_exit (-1);
1222}
1223
1224static void
1225 xscale_cp15_tlb_ops (ARMul_State * state, ARMword instr,
1226 ARMword value)
1227{
1228 int CRm, OPC_2;
1229
1230 CRm = BITS (0, 3);
1231 OPC_2 = BITS (5, 7);
1232
1233
1234 //err_msg("SKYEYE:xscale_cp15_tlb_ops:OPC_2 = 0x%x CRm = 0x%x,Reg[15] 0x%x\n", OPC_2, CRm,state->Reg[15]);
1235 if (OPC_2 == 0 && CRm == 0x7) {
1236 mmu_tlb_invalidate_all (state, I_TLB ());
1237 mmu_tlb_invalidate_all (state, D_TLB ());
1238 return;
1239 }
1240
1241 if (OPC_2 == 0 && CRm == 0x5) {
1242 mmu_tlb_invalidate_all (state, I_TLB ());
1243 return;
1244 }
1245
1246 if (OPC_2 == 1 && CRm == 0x5) {
1247 mmu_tlb_invalidate_entry (state, I_TLB (), value);
1248 return;
1249 }
1250
1251 if (OPC_2 == 0 && CRm == 0x6) {
1252 mmu_tlb_invalidate_all (state, D_TLB ());
1253 return;
1254 }
1255
1256 if (OPC_2 == 1 && CRm == 0x6) {
1257 mmu_tlb_invalidate_entry (state, D_TLB (), value);
1258 return;
1259 }
1260
1261 ERROR_LOG(ARM11, "SKYEYE:xscale_cp15_tlb_ops:Unknow OPC_2 = 0x%x CRm = 0x%x,Reg[15] 0x%x\n", OPC_2, CRm, state->Reg[15]);
1262 // skyeye_exit (-1);
1263}
1264
1265
1266ARMword xscale_cp15_mcr (ARMul_State * state,
1267 unsigned type, ARMword instr, ARMword value)
1268{
1269 return xscale_mmu_mcr (state, instr, value);
1270}
1271
1272ARMword xscale_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
1273{
1274 ARMword data;
1275 unsigned opcode_2 = BITS (5, 7);
1276 unsigned CRm = BITS (0, 3);
1277 unsigned reg = BITS (16, 19);
1278 unsigned result;
1279 mmu_regnum_t creg = (mmu_regnum_t)reg;
1280
1281 //printf("SKYEYE: xscale_cp15_mcr: opcode_2 0x%x, CRm 0x%x, reg ox%x, value 0x%x, reg[15] 0x%x, instr 0x%x\n",opcode_2,CRm,reg, value, state->Reg[15], instr);
1282
1283 switch (creg) {
1284 case MMU_CONTROL:
1285 //printf("mmu_mcr wrote CONTROL val 0x%x \n",value);
1286 state->mmu.control =
1287 (opcode_2 ? (value & 0x33) : (value & 0x3FFF));
1288 break;
1289 case MMU_TRANSLATION_TABLE_BASE:
1290 //printf("mmu_mcr wrote TTB val 0x%x \n",value);
1291 state->mmu.translation_table_base = value & 0xFFFFC000;
1292 break;
1293 case MMU_DOMAIN_ACCESS_CONTROL:
1294 //printf("mmu_mcr wrote DACR val 0x%x \n",value);
1295 state->mmu.domain_access_control = value;
1296 break;
1297
1298 case MMU_FAULT_STATUS:
1299 //printf("mmu_mcr wrote FS val 0x%x \n",value);
1300 state->mmu.fault_status = value & 0x6FF;
1301 break;
1302 case MMU_FAULT_ADDRESS:
1303 //printf("mmu_mcr wrote FA val 0x%x \n",value);
1304 state->mmu.fault_address = value;
1305 break;
1306
1307 case MMU_CACHE_OPS:
1308// printf("mmu_mcr wrote CO val 0x%x \n",value);
1309 xscale_cp15_cache_ops (state, instr, value);
1310 break;
1311 case MMU_TLB_OPS:
1312 //printf("mmu_mcr wrote TO val 0x%x \n",value);
1313 xscale_cp15_tlb_ops (state, instr, value);
1314 break;
1315 case MMU_PID:
1316 //printf("mmu_mcr wrote PID val 0x%x \n",value);
1317 state->mmu.process_id = value & 0xfe000000;
1318 break;
1319 case XSCALE_CP15_COPRO_ACCESS:
1320 //printf("xscale cp15 write coprocessor access val 0x %x\n",value);
1321 state->mmu.copro_access = value & 0x3ff;
1322 break;
1323
1324 default:
1325 printf ("SKYEYE: xscale_cp15_mcr wrote UNKNOWN - reg %d, reg15 0x%x\n", creg, state->Reg[15]);
1326 break;
1327 }
1328 //printf("SKYEYE: xscale_cp15_mcr wrote val 0x%x\n", value);
1329 return 0;
1330}
1331
1332//teawater add for arm2x86 2005.06.24-------------------------------------------
1333static int xscale_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr,
1334 ARMword * phys_addr)
1335{
1336 fault_t fault;
1337 tlb_entry_t *tlb;
1338
1339 virt_addr = mmu_pid_va_map (virt_addr);
1340 if (MMU_Enabled) {
1341
1342 /*align check */
1343 if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) {
1344 DEBUG_LOG(ARM11, "align\n");
1345 return ALIGNMENT_FAULT;
1346 }
1347 else
1348 virt_addr &= ~(WORD_SIZE - 1);
1349
1350 /*translate tlb */
1351 fault = translate (state, virt_addr, I_TLB (), &tlb);
1352 if (fault) {
1353 DEBUG_LOG(ARM11, "translate\n");
1354 return fault;
1355 }
1356
1357 /*check access */
1358 fault = check_access (state, virt_addr, tlb, 1);
1359 if (fault) {
1360 DEBUG_LOG(ARM11, "check_fault\n");
1361 return fault;
1362 }
1363 }
1364
1365 if (MMU_Disabled) {
1366 *phys_addr = virt_addr;
1367 }
1368 else {
1369 *phys_addr = tlb_va_to_pa (tlb, virt_addr);
1370 }
1371
1372 return (0);
1373}
1374
1375//AJ2D--------------------------------------------------------------------------
1376
1377/*xscale mmu_ops_t*/
1378//mmu_ops_t xscale_mmu_ops = {
1379// xscale_cp15_init,
1380// xscale_cp15_exit,
1381// xscale_mmu_read_byte,
1382// xscale_mmu_write_byte,
1383// xscale_mmu_read_halfword,
1384// xscale_mmu_write_halfword,
1385// xscale_mmu_read_word,
1386// xscale_mmu_write_word,
1387// xscale_mmu_load_instr, xscale_mmu_mcr, xscale_mmu_mrc,
1388////teawater add for arm2x86 2005.06.24-------------------------------------------
1389// xscale_mmu_v2p_dbct,
1390////AJ2D--------------------------------------------------------------------------
1391//};
diff --git a/src/core/arm/interpreter/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/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h
index 0ca62780b..4dac1a8bf 100644
--- a/src/core/arm/interpreter/arm_regformat.h
+++ b/src/core/arm/skyeye_common/arm_regformat.h
@@ -99,5 +99,7 @@ enum arm_regno{
99 MAX_REG_NUM, 99 MAX_REG_NUM,
100}; 100};
101 101
102#define VFP_OFFSET(x) (x - VFP_BASE) 102#define CP15(idx) (idx - CP15_BASE)
103#define VFP_OFFSET(x) (x - VFP_BASE)
104
103#endif 105#endif
diff --git a/src/core/arm/interpreter/armcpu.h b/src/core/arm/skyeye_common/armcpu.h
index 6b5ea8566..3a029f0e7 100644
--- a/src/core/arm/interpreter/armcpu.h
+++ b/src/core/arm/skyeye_common/armcpu.h
@@ -20,16 +20,13 @@
20 20
21#ifndef __ARM_CPU_H__ 21#ifndef __ARM_CPU_H__
22#define __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 23
28#include <stddef.h> 24#include <stddef.h>
29#include <stdio.h> 25#include <stdio.h>
30 26
31#include "common/thread.h" 27#include "common/thread.h"
32 28
29#include "core/arm/skyeye_common/armdefs.h"
33 30
34typedef struct ARM_CPU_State_s { 31typedef struct ARM_CPU_State_s {
35 ARMul_State * core; 32 ARMul_State * core;
diff --git a/src/core/arm/interpreter/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index dd5983be3..8e71948c6 100644
--- a/src/core/arm/interpreter/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -31,7 +31,7 @@
31 31
32#include "arm_regformat.h" 32#include "arm_regformat.h"
33#include "common/platform.h" 33#include "common/platform.h"
34#include "skyeye_defs.h" 34#include "core/arm/skyeye_common/skyeye_defs.h"
35 35
36//AJ2D-------------------------------------------------------------------------- 36//AJ2D--------------------------------------------------------------------------
37 37
@@ -130,7 +130,7 @@ typedef unsigned long long uint64_t;
130#endif 130#endif
131*/ 131*/
132 132
133#include "armmmu.h" 133#include "core/arm/skyeye_common/armmmu.h"
134//#include "lcd/skyeye_lcd.h" 134//#include "lcd/skyeye_lcd.h"
135 135
136 136
@@ -367,7 +367,6 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
367 367
368 int verbose; /* non-zero means print various messages like the banner */ 368 int verbose; /* non-zero means print various messages like the banner */
369 369
370 mmu_state_t mmu;
371 int mmu_inited; 370 int mmu_inited;
372 //mem_state_t mem; 371 //mem_state_t mem;
373 /*remove io_state to skyeye_mach_*.c files */ 372 /*remove io_state to skyeye_mach_*.c files */
diff --git a/src/core/arm/interpreter/armemu.h b/src/core/arm/skyeye_common/armemu.h
index 36fb2d09b..c0f0270fe 100644
--- a/src/core/arm/interpreter/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -18,7 +18,7 @@
18#define __ARMEMU_H__ 18#define __ARMEMU_H__
19 19
20 20
21#include "armdefs.h" 21#include "core/arm/skyeye_common/armdefs.h"
22//#include "skyeye.h" 22//#include "skyeye.h"
23 23
24//extern ARMword isize; 24//extern ARMword isize;
diff --git a/src/core/arm/interpreter/armmmu.h b/src/core/arm/skyeye_common/armmmu.h
index 818108c9c..30858f9ba 100644
--- a/src/core/arm/interpreter/armmmu.h
+++ b/src/core/arm/skyeye_common/armmmu.h
@@ -134,121 +134,4 @@ typedef enum fault_t
134 134
135} fault_t; 135} fault_t;
136 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_ */ 137#endif /* _ARMMMU_H_ */
diff --git a/src/core/arm/interpreter/armos.h b/src/core/arm/skyeye_common/armos.h
index 4b58801ad..ffdadcd1c 100644
--- a/src/core/arm/interpreter/armos.h
+++ b/src/core/arm/skyeye_common/armos.h
@@ -15,14 +15,7 @@
15 along with this program; if not, write to the Free Software 15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17 17
18//#include "bank_defs.h" 18#include <stdint.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 19
27#if FAST_MEMORY 20#if FAST_MEMORY
28/* in user mode, mmap_base will be on initial brk, 21/* in user mode, mmap_base will be on initial brk,
diff --git a/src/core/arm/interpreter/skyeye_defs.h b/src/core/arm/skyeye_common/skyeye_defs.h
index b6713ebad..d4088383f 100644
--- a/src/core/arm/interpreter/skyeye_defs.h
+++ b/src/core/arm/skyeye_common/skyeye_defs.h
@@ -108,4 +108,6 @@ typedef struct generic_arch_s
108 align_t alignment; 108 align_t alignment;
109} generic_arch_t; 109} generic_arch_t;
110 110
111#endif \ No newline at end of file 111typedef u32 addr_t;
112
113#endif
diff --git a/src/core/arm/skyeye_common/skyeye_types.h b/src/core/arm/skyeye_common/skyeye_types.h
new file mode 100644
index 000000000..e7f022f19
--- /dev/null
+++ b/src/core/arm/skyeye_common/skyeye_types.h
@@ -0,0 +1,55 @@
1/*
2 skyeye_types.h - some data types definition for skyeye debugger
3 Copyright (C) 2003 Skyeye Develop Group
4 for help please send mail to <skyeye-developer@lists.sf.linuxforum.net>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20*/
21/*
22 * 12/16/2006 Michael.Kang <blackfin.kang@gmail.com>
23 */
24
25#ifndef __SKYEYE_TYPES_H
26#define __SKYEYE_TYPES_H
27
28#include <stdint.h>
29
30/*default machine word length */
31
32#ifndef __BEOS__
33/* To avoid the type conflict with the qemu */
34#ifndef QEMU
35typedef uint8_t uint8;
36typedef uint16_t uint16;
37typedef uint32_t uint32;
38typedef uint64_t uint64;
39
40typedef int8_t sint8;
41typedef int16_t sint16;
42typedef int32_t sint32;
43typedef int64_t sint64;
44#endif
45
46typedef uint32_t address_t;
47typedef uint32_t uinteger_t;
48typedef int32_t integer_t;
49
50typedef uint32_t physical_address_t;
51typedef uint32_t generic_address_t;
52
53#endif
54
55#endif
diff --git a/src/core/arm/interpreter/vfp/asm_vfp.h b/src/core/arm/skyeye_common/vfp/asm_vfp.h
index f4ab34fd4..f4ab34fd4 100644
--- a/src/core/arm/interpreter/vfp/asm_vfp.h
+++ b/src/core/arm/skyeye_common/vfp/asm_vfp.h
diff --git a/src/core/arm/interpreter/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index eea5e24a9..e4fa3c20a 100644
--- a/src/core/arm/interpreter/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -25,8 +25,8 @@
25 25
26#include "common/common.h" 26#include "common/common.h"
27 27
28#include "core/arm/interpreter/armdefs.h" 28#include "core/arm/skyeye_common/armdefs.h"
29#include "core/arm/interpreter/vfp/vfp.h" 29#include "core/arm/skyeye_common/vfp/vfp.h"
30 30
31//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */ 31//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */
32 32
@@ -62,7 +62,7 @@ VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value)
62 if (CoProc == 10 || CoProc == 11) 62 if (CoProc == 10 || CoProc == 11)
63 { 63 {
64 #define VFP_MRC_TRANS 64 #define VFP_MRC_TRANS
65 #include "core/arm/interpreter/vfp/vfpinstr.cpp" 65 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
66 #undef VFP_MRC_TRANS 66 #undef VFP_MRC_TRANS
67 } 67 }
68 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", 68 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
@@ -88,7 +88,7 @@ VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
88 if (CoProc == 10 || CoProc == 11) 88 if (CoProc == 10 || CoProc == 11)
89 { 89 {
90 #define VFP_MCR_TRANS 90 #define VFP_MCR_TRANS
91 #include "core/arm/interpreter/vfp/vfpinstr.cpp" 91 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
92 #undef VFP_MCR_TRANS 92 #undef VFP_MCR_TRANS
93 } 93 }
94 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", 94 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
@@ -110,7 +110,7 @@ VFPMRRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value1, AR
110 if (CoProc == 10 || CoProc == 11) 110 if (CoProc == 10 || CoProc == 11)
111 { 111 {
112 #define VFP_MRRC_TRANS 112 #define VFP_MRRC_TRANS
113 #include "core/arm/interpreter/vfp/vfpinstr.cpp" 113 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
114 #undef VFP_MRRC_TRANS 114 #undef VFP_MRRC_TRANS
115 } 115 }
116 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", 116 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
@@ -136,7 +136,7 @@ VFPMCRR (ARMul_State * state, unsigned type, ARMword instr, ARMword value1, ARMw
136 if (CoProc == 11 || CoProc == 10) 136 if (CoProc == 11 || CoProc == 10)
137 { 137 {
138 #define VFP_MCRR_TRANS 138 #define VFP_MCRR_TRANS
139 #include "core/arm/interpreter/vfp/vfpinstr.cpp" 139 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
140 #undef VFP_MCRR_TRANS 140 #undef VFP_MCRR_TRANS
141 } 141 }
142 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", 142 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
@@ -179,7 +179,7 @@ VFPSTC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value)
179 #endif 179 #endif
180 180
181 #define VFP_STC_TRANS 181 #define VFP_STC_TRANS
182 #include "core/arm/interpreter/vfp/vfpinstr.cpp" 182 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
183 #undef VFP_STC_TRANS 183 #undef VFP_STC_TRANS
184 } 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", 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",
@@ -210,7 +210,7 @@ VFPLDC (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
210 if (CoProc == 10 || CoProc == 11) 210 if (CoProc == 10 || CoProc == 11)
211 { 211 {
212 #define VFP_LDC_TRANS 212 #define VFP_LDC_TRANS
213 #include "core/arm/interpreter/vfp/vfpinstr.cpp" 213 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
214 #undef VFP_LDC_TRANS 214 #undef VFP_LDC_TRANS
215 } 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", 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",
@@ -237,7 +237,7 @@ VFPCDP (ARMul_State * state, unsigned type, ARMword instr)
237 if (CoProc == 10 || CoProc == 11) 237 if (CoProc == 10 || CoProc == 11)
238 { 238 {
239 #define VFP_CDP_TRANS 239 #define VFP_CDP_TRANS
240 #include "core/arm/interpreter/vfp/vfpinstr.cpp" 240 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
241 #undef VFP_CDP_TRANS 241 #undef VFP_CDP_TRANS
242 242
243 int exceptions = 0; 243 int exceptions = 0;
@@ -257,21 +257,21 @@ VFPCDP (ARMul_State * state, unsigned type, ARMword instr)
257 257
258/* ----------- MRC ------------ */ 258/* ----------- MRC ------------ */
259#define VFP_MRC_IMPL 259#define VFP_MRC_IMPL
260#include "core/arm/interpreter/vfp/vfpinstr.cpp" 260#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
261#undef VFP_MRC_IMPL 261#undef VFP_MRC_IMPL
262 262
263#define VFP_MRRC_IMPL 263#define VFP_MRRC_IMPL
264#include "core/arm/interpreter/vfp/vfpinstr.cpp" 264#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
265#undef VFP_MRRC_IMPL 265#undef VFP_MRRC_IMPL
266 266
267 267
268/* ----------- MCR ------------ */ 268/* ----------- MCR ------------ */
269#define VFP_MCR_IMPL 269#define VFP_MCR_IMPL
270#include "core/arm/interpreter/vfp/vfpinstr.cpp" 270#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
271#undef VFP_MCR_IMPL 271#undef VFP_MCR_IMPL
272 272
273#define VFP_MCRR_IMPL 273#define VFP_MCRR_IMPL
274#include "core/arm/interpreter/vfp/vfpinstr.cpp" 274#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
275#undef VFP_MCRR_IMPL 275#undef VFP_MCRR_IMPL
276 276
277/* Memory operation are not inlined, as old Interpreter and Fast interpreter 277/* Memory operation are not inlined, as old Interpreter and Fast interpreter
@@ -283,19 +283,19 @@ VFPCDP (ARMul_State * state, unsigned type, ARMword instr)
283 283
284/* ----------- STC ------------ */ 284/* ----------- STC ------------ */
285#define VFP_STC_IMPL 285#define VFP_STC_IMPL
286#include "core/arm/interpreter/vfp/vfpinstr.cpp" 286#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
287#undef VFP_STC_IMPL 287#undef VFP_STC_IMPL
288 288
289 289
290/* ----------- LDC ------------ */ 290/* ----------- LDC ------------ */
291#define VFP_LDC_IMPL 291#define VFP_LDC_IMPL
292#include "core/arm/interpreter/vfp/vfpinstr.cpp" 292#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
293#undef VFP_LDC_IMPL 293#undef VFP_LDC_IMPL
294 294
295 295
296/* ----------- CDP ------------ */ 296/* ----------- CDP ------------ */
297#define VFP_CDP_IMPL 297#define VFP_CDP_IMPL
298#include "core/arm/interpreter/vfp/vfpinstr.cpp" 298#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
299#undef VFP_CDP_IMPL 299#undef VFP_CDP_IMPL
300 300
301/* Miscellaneous functions */ 301/* Miscellaneous functions */
diff --git a/src/core/arm/interpreter/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index bbf4caeb0..ed627d41f 100644
--- a/src/core/arm/interpreter/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -25,7 +25,7 @@
25 25
26#define vfpdebug //printf 26#define vfpdebug //printf
27 27
28#include "core/arm/interpreter/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */ 28#include "core/arm/skyeye_common/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */
29 29
30unsigned VFPInit (ARMul_State *state); 30unsigned VFPInit (ARMul_State *state);
31unsigned VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value); 31unsigned VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value);
diff --git a/src/core/arm/interpreter/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h
index b222e79f1..5076e59f7 100644
--- a/src/core/arm/interpreter/vfp/vfp_helper.h
+++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h
@@ -38,14 +38,8 @@
38#include <stdint.h> 38#include <stdint.h>
39#include <stdio.h> 39#include <stdio.h>
40 40
41#include "core/arm/interpreter/armdefs.h" 41#include "common/common_types.h"
42 42#include "core/arm/skyeye_common/armdefs.h"
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 43
50#define pr_info //printf 44#define pr_info //printf
51#define pr_debug //printf 45#define pr_debug //printf
diff --git a/src/core/arm/interpreter/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
index 5ae99b88a..13411ad80 100644
--- a/src/core/arm/interpreter/vfp/vfpdouble.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
@@ -51,9 +51,9 @@
51 * =========================================================================== 51 * ===========================================================================
52 */ 52 */
53 53
54#include "core/arm/interpreter/vfp/vfp.h" 54#include "core/arm/skyeye_common/vfp/vfp.h"
55#include "core/arm/interpreter/vfp/vfp_helper.h" 55#include "core/arm/skyeye_common/vfp/vfp_helper.h"
56#include "core/arm/interpreter/vfp/asm_vfp.h" 56#include "core/arm/skyeye_common/vfp/asm_vfp.h"
57 57
58static struct vfp_double vfp_double_default_qnan = { 58static struct vfp_double vfp_double_default_qnan = {
59 //.exponent = 2047, 59 //.exponent = 2047,
diff --git a/src/core/arm/interpreter/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index a57047911..45208fb13 100644
--- a/src/core/arm/interpreter/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -3709,7 +3709,7 @@ VFPLABEL_INST:
3709 { 3709 {
3710 fault = check_address_validity(cpu, addr, &phys_addr, 0); 3710 fault = check_address_validity(cpu, addr, &phys_addr, 0);
3711 if (fault) goto MMU_EXCEPTION; 3711 if (fault) goto MMU_EXCEPTION;
3712 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d], 32); 3712 fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d], 32);
3713 if (fault) goto MMU_EXCEPTION; 3713 if (fault) goto MMU_EXCEPTION;
3714 DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d, cpu->ExtReg[inst_cream->d]); 3714 DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d, cpu->ExtReg[inst_cream->d]);
3715 } 3715 }
@@ -3719,13 +3719,13 @@ VFPLABEL_INST:
3719 if (fault) goto MMU_EXCEPTION; 3719 if (fault) goto MMU_EXCEPTION;
3720 3720
3721 /* Check endianness */ 3721 /* Check endianness */
3722 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d*2], 32); 3722 fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d*2], 32);
3723 if (fault) goto MMU_EXCEPTION; 3723 if (fault) goto MMU_EXCEPTION;
3724 3724
3725 fault = check_address_validity(cpu, addr + 4, &phys_addr, 0); 3725 fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
3726 if (fault) goto MMU_EXCEPTION; 3726 if (fault) goto MMU_EXCEPTION;
3727 3727
3728 fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[inst_cream->d*2+1], 32); 3728 fault = interpreter_write_memory(addr + 4, phys_addr, cpu->ExtReg[inst_cream->d*2+1], 32);
3729 if (fault) goto MMU_EXCEPTION; 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]); 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 } 3731 }
@@ -3926,7 +3926,7 @@ VFPLABEL_INST:
3926 { 3926 {
3927 fault = check_address_validity(cpu, addr, &phys_addr, 0); 3927 fault = check_address_validity(cpu, addr, &phys_addr, 0);
3928 if (fault) goto MMU_EXCEPTION; 3928 if (fault) goto MMU_EXCEPTION;
3929 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32); 3929 fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
3930 if (fault) goto MMU_EXCEPTION; 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]); 3931 DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
3932 addr += 4; 3932 addr += 4;
@@ -3936,12 +3936,12 @@ VFPLABEL_INST:
3936 /* Careful of endianness, little by default */ 3936 /* Careful of endianness, little by default */
3937 fault = check_address_validity(cpu, addr, &phys_addr, 0); 3937 fault = check_address_validity(cpu, addr, &phys_addr, 0);
3938 if (fault) goto MMU_EXCEPTION; 3938 if (fault) goto MMU_EXCEPTION;
3939 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32); 3939 fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
3940 if (fault) goto MMU_EXCEPTION; 3940 if (fault) goto MMU_EXCEPTION;
3941 3941
3942 fault = check_address_validity(cpu, addr + 4, &phys_addr, 0); 3942 fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
3943 if (fault) goto MMU_EXCEPTION; 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); 3944 fault = interpreter_write_memory(addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
3945 if (fault) goto MMU_EXCEPTION; 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]); 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; 3947 addr += 8;
@@ -4048,7 +4048,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4048 { 4048 {
4049 if (single) 4049 if (single)
4050 { 4050 {
4051 //fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32); 4051 //fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
4052 #if 0 4052 #if 0
4053 phys_addr = get_phys_addr(cpu, bb, Addr, 0); 4053 phys_addr = get_phys_addr(cpu, bb, Addr, 0);
4054 bb = cpu->dyncom_engine->bb; 4054 bb = cpu->dyncom_engine->bb;
@@ -4166,7 +4166,7 @@ VFPLABEL_INST: /* encoding 1 */
4166 fault = check_address_validity(cpu, addr, &phys_addr, 0); 4166 fault = check_address_validity(cpu, addr, &phys_addr, 0);
4167 if (fault) goto MMU_EXCEPTION; 4167 if (fault) goto MMU_EXCEPTION;
4168 4168
4169 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32); 4169 fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
4170 if (fault) goto MMU_EXCEPTION; 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]); 4171 DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
4172 addr += 4; 4172 addr += 4;
@@ -4177,13 +4177,13 @@ VFPLABEL_INST: /* encoding 1 */
4177 fault = check_address_validity(cpu, addr, &phys_addr, 0); 4177 fault = check_address_validity(cpu, addr, &phys_addr, 0);
4178 if (fault) goto MMU_EXCEPTION; 4178 if (fault) goto MMU_EXCEPTION;
4179 4179
4180 fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32); 4180 fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
4181 if (fault) goto MMU_EXCEPTION; 4181 if (fault) goto MMU_EXCEPTION;
4182 4182
4183 fault = check_address_validity(cpu, addr + 4, &phys_addr, 0); 4183 fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
4184 if (fault) goto MMU_EXCEPTION; 4184 if (fault) goto MMU_EXCEPTION;
4185 4185
4186 fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32); 4186 fault = interpreter_write_memory(addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
4187 if (fault) goto MMU_EXCEPTION; 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]); 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; 4189 addr += 8;
@@ -4304,7 +4304,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4304 if (single) 4304 if (single)
4305 { 4305 {
4306 4306
4307 //fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32); 4307 //fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
4308 /* if R(i) is R15? */ 4308 /* if R(i) is R15? */
4309 #if 0 4309 #if 0
4310 phys_addr = get_phys_addr(cpu, bb, Addr, 0); 4310 phys_addr = get_phys_addr(cpu, bb, Addr, 0);
@@ -4321,7 +4321,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4321 else 4321 else
4322 { 4322 {
4323 4323
4324 //fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32); 4324 //fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
4325 #if 0 4325 #if 0
4326 phys_addr = get_phys_addr(cpu, bb, Addr, 0); 4326 phys_addr = get_phys_addr(cpu, bb, Addr, 0);
4327 bb = cpu->dyncom_engine->bb; 4327 bb = cpu->dyncom_engine->bb;
@@ -4332,7 +4332,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4332 bb = cpu->dyncom_engine->bb; 4332 bb = cpu->dyncom_engine->bb;
4333 //if (fault) goto MMU_EXCEPTION; 4333 //if (fault) goto MMU_EXCEPTION;
4334 4334
4335 //fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32); 4335 //fault = interpreter_write_memory(addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
4336 #if 0 4336 #if 0
4337 phys_addr = get_phys_addr(cpu, bb, ADD(Addr, CONST(4)), 0); 4337 phys_addr = get_phys_addr(cpu, bb, ADD(Addr, CONST(4)), 0);
4338 bb = cpu->dyncom_engine->bb; 4338 bb = cpu->dyncom_engine->bb;
@@ -4431,7 +4431,7 @@ VFPLABEL_INST:
4431 fault = check_address_validity(cpu, addr, &phys_addr, 1); 4431 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4432 if (fault) goto MMU_EXCEPTION; 4432 if (fault) goto MMU_EXCEPTION;
4433 4433
4434 fault = interpreter_read_memory(core, addr, phys_addr, value1, 32); 4434 fault = interpreter_read_memory(addr, phys_addr, value1, 32);
4435 if (fault) goto MMU_EXCEPTION; 4435 if (fault) goto MMU_EXCEPTION;
4436 DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d+i, value1, addr); 4436 DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d+i, value1, addr);
4437 cpu->ExtReg[inst_cream->d+i] = value1; 4437 cpu->ExtReg[inst_cream->d+i] = value1;
@@ -4443,13 +4443,13 @@ VFPLABEL_INST:
4443 fault = check_address_validity(cpu, addr, &phys_addr, 1); 4443 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4444 if (fault) goto MMU_EXCEPTION; 4444 if (fault) goto MMU_EXCEPTION;
4445 4445
4446 fault = interpreter_read_memory(core, addr, phys_addr, value1, 32); 4446 fault = interpreter_read_memory(addr, phys_addr, value1, 32);
4447 if (fault) goto MMU_EXCEPTION; 4447 if (fault) goto MMU_EXCEPTION;
4448 4448
4449 fault = check_address_validity(cpu, addr + 4, &phys_addr, 1); 4449 fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
4450 if (fault) goto MMU_EXCEPTION; 4450 if (fault) goto MMU_EXCEPTION;
4451 4451
4452 fault = interpreter_read_memory(core, addr + 4, phys_addr, value2, 32); 4452 fault = interpreter_read_memory(addr + 4, phys_addr, value2, 32);
4453 if (fault) goto MMU_EXCEPTION; 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); 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; 4455 cpu->ExtReg[(inst_cream->d+i)*2] = value1;
@@ -4682,7 +4682,7 @@ VFPLABEL_INST:
4682 { 4682 {
4683 fault = check_address_validity(cpu, addr, &phys_addr, 1); 4683 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4684 if (fault) goto MMU_EXCEPTION; 4684 if (fault) goto MMU_EXCEPTION;
4685 fault = interpreter_read_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d], 32); 4685 fault = interpreter_read_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d], 32);
4686 if (fault) goto MMU_EXCEPTION; 4686 if (fault) goto MMU_EXCEPTION;
4687 DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d, cpu->ExtReg[inst_cream->d], addr); 4687 DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d, cpu->ExtReg[inst_cream->d], addr);
4688 } 4688 }
@@ -4691,12 +4691,12 @@ VFPLABEL_INST:
4691 unsigned int word1, word2; 4691 unsigned int word1, word2;
4692 fault = check_address_validity(cpu, addr, &phys_addr, 1); 4692 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4693 if (fault) goto MMU_EXCEPTION; 4693 if (fault) goto MMU_EXCEPTION;
4694 fault = interpreter_read_memory(core, addr, phys_addr, word1, 32); 4694 fault = interpreter_read_memory(addr, phys_addr, word1, 32);
4695 if (fault) goto MMU_EXCEPTION; 4695 if (fault) goto MMU_EXCEPTION;
4696 4696
4697 fault = check_address_validity(cpu, addr + 4, &phys_addr, 1); 4697 fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
4698 if (fault) goto MMU_EXCEPTION; 4698 if (fault) goto MMU_EXCEPTION;
4699 fault = interpreter_read_memory(core, addr + 4, phys_addr, word2, 32); 4699 fault = interpreter_read_memory(addr + 4, phys_addr, word2, 32);
4700 if (fault) goto MMU_EXCEPTION; 4700 if (fault) goto MMU_EXCEPTION;
4701 /* Check endianness */ 4701 /* Check endianness */
4702 cpu->ExtReg[inst_cream->d*2] = word1; 4702 cpu->ExtReg[inst_cream->d*2] = word1;
@@ -4923,7 +4923,7 @@ VFPLABEL_INST:
4923 { 4923 {
4924 fault = check_address_validity(cpu, addr, &phys_addr, 1); 4924 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4925 if (fault) goto MMU_EXCEPTION; 4925 if (fault) goto MMU_EXCEPTION;
4926 fault = interpreter_read_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32); 4926 fault = interpreter_read_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
4927 if (fault) goto MMU_EXCEPTION; 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); 4928 DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d+i, cpu->ExtReg[inst_cream->d+i], addr);
4929 addr += 4; 4929 addr += 4;
@@ -4933,12 +4933,12 @@ VFPLABEL_INST:
4933 /* Careful of endianness, little by default */ 4933 /* Careful of endianness, little by default */
4934 fault = check_address_validity(cpu, addr, &phys_addr, 1); 4934 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4935 if (fault) goto MMU_EXCEPTION; 4935 if (fault) goto MMU_EXCEPTION;
4936 fault = interpreter_read_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32); 4936 fault = interpreter_read_memory(addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
4937 if (fault) goto MMU_EXCEPTION; 4937 if (fault) goto MMU_EXCEPTION;
4938 4938
4939 fault = check_address_validity(cpu, addr + 4, &phys_addr, 1); 4939 fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
4940 if (fault) goto MMU_EXCEPTION; 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); 4941 fault = interpreter_read_memory(addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
4942 if (fault) goto MMU_EXCEPTION; 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); 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; 4944 addr += 8;
@@ -5058,7 +5058,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
5058 if (single) 5058 if (single)
5059 { 5059 {
5060 5060
5061 //fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32); 5061 //fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
5062 /* if R(i) is R15? */ 5062 /* if R(i) is R15? */
5063 #if 0 5063 #if 0
5064 phys_addr = get_phys_addr(cpu, bb, Addr, 1); 5064 phys_addr = get_phys_addr(cpu, bb, Addr, 1);
@@ -5095,7 +5095,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
5095 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb); 5095 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
5096 LETFPS((d + i) * 2 + 1, FPBITCAST32(val)); 5096 LETFPS((d + i) * 2 + 1, FPBITCAST32(val));
5097 5097
5098 //fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32); 5098 //fault = interpreter_write_memory(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]); 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; 5100 //addr += 8;
5101 Addr = ADD(Addr, CONST(8)); 5101 Addr = ADD(Addr, CONST(8));
diff --git a/src/core/arm/interpreter/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index 0fcc85266..8bcbd4fe9 100644
--- a/src/core/arm/interpreter/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -51,9 +51,9 @@
51 * =========================================================================== 51 * ===========================================================================
52 */ 52 */
53 53
54#include "core/arm/interpreter/vfp/vfp_helper.h" 54#include "core/arm/skyeye_common/vfp/vfp_helper.h"
55#include "core/arm/interpreter/vfp/asm_vfp.h" 55#include "core/arm/skyeye_common/vfp/asm_vfp.h"
56#include "core/arm/interpreter/vfp/vfp.h" 56#include "core/arm/skyeye_common/vfp/vfp.h"
57 57
58static struct vfp_single vfp_single_default_qnan = { 58static struct vfp_single vfp_single_default_qnan = {
59 //.exponent = 255, 59 //.exponent = 255,
diff --git a/src/core/core.h b/src/core/core.h
index 9c72c8b3f..87da252b8 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -5,7 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include "core/arm/arm_interface.h" 7#include "core/arm/arm_interface.h"
8#include "core/arm/interpreter/armdefs.h" 8#include "core/arm/skyeye_common/armdefs.h"
9 9
10//////////////////////////////////////////////////////////////////////////////////////////////////// 10////////////////////////////////////////////////////////////////////////////////////////////////////
11 11
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
index 213923c02..0b647f7d0 100644
--- a/src/core/file_sys/archive_sdmc.cpp
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -10,6 +10,7 @@
10#include "core/file_sys/archive_sdmc.h" 10#include "core/file_sys/archive_sdmc.h"
11#include "core/file_sys/directory_sdmc.h" 11#include "core/file_sys/directory_sdmc.h"
12#include "core/file_sys/file_sdmc.h" 12#include "core/file_sys/file_sdmc.h"
13#include "core/settings.h"
13 14
14//////////////////////////////////////////////////////////////////////////////////////////////////// 15////////////////////////////////////////////////////////////////////////////////////////////////////
15// FileSys namespace 16// FileSys namespace
@@ -29,8 +30,13 @@ Archive_SDMC::~Archive_SDMC() {
29 * @return true if it initialized successfully 30 * @return true if it initialized successfully
30 */ 31 */
31bool Archive_SDMC::Initialize() { 32bool Archive_SDMC::Initialize() {
32 if (!FileUtil::IsDirectory(mount_point)) { 33 if (!Settings::values.use_virtual_sd) {
33 WARN_LOG(FILESYS, "Directory %s not found, disabling SDMC.", mount_point.c_str()); 34 WARN_LOG(FILESYS, "SDMC disabled by config.");
35 return false;
36 }
37
38 if (!FileUtil::CreateFullPath(mount_point)) {
39 WARN_LOG(FILESYS, "Unable to create SDMC path.");
34 return false; 40 return false;
35 } 41 }
36 42
diff --git a/src/core/hle/coprocessor.h b/src/core/hle/coprocessor.h
deleted file mode 100644
index b08d6f3ee..000000000
--- a/src/core/hle/coprocessor.h
+++ /dev/null
@@ -1,20 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9namespace HLE {
10
11/// Coprocessor operations
12enum CoprocessorOperation {
13 DATA_SYNCHRONIZATION_BARRIER = 0xE0,
14 CALL_GET_THREAD_COMMAND_BUFFER = 0xE1,
15};
16
17/// Call an MRC (move to ARM register from coprocessor) instruction in HLE
18s32 CallMRC(u32 instruction);
19
20} // namespace
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 174d4cd6e..2b21657da 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -17,11 +17,11 @@ namespace Kernel {
17 17
18class AddressArbiter : public Object { 18class AddressArbiter : public Object {
19public: 19public:
20 std::string GetTypeName() const { return "Arbiter"; } 20 std::string GetTypeName() const override { return "Arbiter"; }
21 std::string GetName() const { return name; } 21 std::string GetName() const override { return name; }
22 22
23 static Kernel::HandleType GetStaticHandleType() { return HandleType::AddressArbiter; } 23 static Kernel::HandleType GetStaticHandleType() { return HandleType::AddressArbiter; }
24 Kernel::HandleType GetHandleType() const { return HandleType::AddressArbiter; } 24 Kernel::HandleType GetHandleType() const override { return HandleType::AddressArbiter; }
25 25
26 std::string name; ///< Name of address arbiter object (optional) 26 std::string name; ///< Name of address arbiter object (optional)
27 27
@@ -30,7 +30,7 @@ public:
30 * @param wait Boolean wait set if current thread should wait as a result of sync operation 30 * @param wait Boolean wait set if current thread should wait as a result of sync operation
31 * @return Result of operation, 0 on success, otherwise error code 31 * @return Result of operation, 0 on success, otherwise error code
32 */ 32 */
33 Result WaitSynchronization(bool* wait) { 33 Result WaitSynchronization(bool* wait) override {
34 // TODO(bunnei): ImplementMe 34 // TODO(bunnei): ImplementMe
35 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 35 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
36 return 0; 36 return 0;
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp
index 86aba7489..09b4e75a5 100644
--- a/src/core/hle/kernel/archive.cpp
+++ b/src/core/hle/kernel/archive.cpp
@@ -42,11 +42,11 @@ enum class DirectoryCommand : u32 {
42 42
43class Archive : public Object { 43class Archive : public Object {
44public: 44public:
45 std::string GetTypeName() const { return "Archive"; } 45 std::string GetTypeName() const override { return "Archive"; }
46 std::string GetName() const { return name; } 46 std::string GetName() const override { return name; }
47 47
48 static Kernel::HandleType GetStaticHandleType() { return HandleType::Archive; } 48 static Kernel::HandleType GetStaticHandleType() { return HandleType::Archive; }
49 Kernel::HandleType GetHandleType() const { return HandleType::Archive; } 49 Kernel::HandleType GetHandleType() const override { return HandleType::Archive; }
50 50
51 std::string name; ///< Name of archive (optional) 51 std::string name; ///< Name of archive (optional)
52 FileSys::Archive* backend; ///< Archive backend interface 52 FileSys::Archive* backend; ///< Archive backend interface
@@ -56,7 +56,7 @@ public:
56 * @param wait Boolean wait set if current thread should wait as a result of sync operation 56 * @param wait Boolean wait set if current thread should wait as a result of sync operation
57 * @return Result of operation, 0 on success, otherwise error code 57 * @return Result of operation, 0 on success, otherwise error code
58 */ 58 */
59 Result SyncRequest(bool* wait) { 59 Result SyncRequest(bool* wait) override {
60 u32* cmd_buff = Service::GetCommandBuffer(); 60 u32* cmd_buff = Service::GetCommandBuffer();
61 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 61 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
62 62
@@ -119,7 +119,7 @@ public:
119 * @param wait Boolean wait set if current thread should wait as a result of sync operation 119 * @param wait Boolean wait set if current thread should wait as a result of sync operation
120 * @return Result of operation, 0 on success, otherwise error code 120 * @return Result of operation, 0 on success, otherwise error code
121 */ 121 */
122 Result WaitSynchronization(bool* wait) { 122 Result WaitSynchronization(bool* wait) override {
123 // TODO(bunnei): ImplementMe 123 // TODO(bunnei): ImplementMe
124 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 124 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
125 return 0; 125 return 0;
@@ -128,11 +128,11 @@ public:
128 128
129class File : public Object { 129class File : public Object {
130public: 130public:
131 std::string GetTypeName() const { return "File"; } 131 std::string GetTypeName() const override { return "File"; }
132 std::string GetName() const { return path; } 132 std::string GetName() const override { return path; }
133 133
134 static Kernel::HandleType GetStaticHandleType() { return HandleType::File; } 134 static Kernel::HandleType GetStaticHandleType() { return HandleType::File; }
135 Kernel::HandleType GetHandleType() const { return HandleType::File; } 135 Kernel::HandleType GetHandleType() const override { return HandleType::File; }
136 136
137 std::string path; ///< Path of the file 137 std::string path; ///< Path of the file
138 std::unique_ptr<FileSys::File> backend; ///< File backend interface 138 std::unique_ptr<FileSys::File> backend; ///< File backend interface
@@ -142,7 +142,7 @@ public:
142 * @param wait Boolean wait set if current thread should wait as a result of sync operation 142 * @param wait Boolean wait set if current thread should wait as a result of sync operation
143 * @return Result of operation, 0 on success, otherwise error code 143 * @return Result of operation, 0 on success, otherwise error code
144 */ 144 */
145 Result SyncRequest(bool* wait) { 145 Result SyncRequest(bool* wait) override {
146 u32* cmd_buff = Service::GetCommandBuffer(); 146 u32* cmd_buff = Service::GetCommandBuffer();
147 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 147 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
148 switch (cmd) { 148 switch (cmd) {
@@ -211,7 +211,7 @@ public:
211 * @param wait Boolean wait set if current thread should wait as a result of sync operation 211 * @param wait Boolean wait set if current thread should wait as a result of sync operation
212 * @return Result of operation, 0 on success, otherwise error code 212 * @return Result of operation, 0 on success, otherwise error code
213 */ 213 */
214 Result WaitSynchronization(bool* wait) { 214 Result WaitSynchronization(bool* wait) override {
215 // TODO(bunnei): ImplementMe 215 // TODO(bunnei): ImplementMe
216 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 216 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
217 return 0; 217 return 0;
@@ -220,11 +220,11 @@ public:
220 220
221class Directory : public Object { 221class Directory : public Object {
222public: 222public:
223 std::string GetTypeName() const { return "Directory"; } 223 std::string GetTypeName() const override { return "Directory"; }
224 std::string GetName() const { return path; } 224 std::string GetName() const override { return path; }
225 225
226 static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; } 226 static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; }
227 Kernel::HandleType GetHandleType() const { return HandleType::Directory; } 227 Kernel::HandleType GetHandleType() const override { return HandleType::Directory; }
228 228
229 std::string path; ///< Path of the directory 229 std::string path; ///< Path of the directory
230 std::unique_ptr<FileSys::Directory> backend; ///< File backend interface 230 std::unique_ptr<FileSys::Directory> backend; ///< File backend interface
@@ -234,7 +234,7 @@ public:
234 * @param wait Boolean wait set if current thread should wait as a result of sync operation 234 * @param wait Boolean wait set if current thread should wait as a result of sync operation
235 * @return Result of operation, 0 on success, otherwise error code 235 * @return Result of operation, 0 on success, otherwise error code
236 */ 236 */
237 Result SyncRequest(bool* wait) { 237 Result SyncRequest(bool* wait) override {
238 u32* cmd_buff = Service::GetCommandBuffer(); 238 u32* cmd_buff = Service::GetCommandBuffer();
239 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); 239 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
240 switch (cmd) { 240 switch (cmd) {
@@ -274,7 +274,7 @@ public:
274 * @param wait Boolean wait set if current thread should wait as a result of sync operation 274 * @param wait Boolean wait set if current thread should wait as a result of sync operation
275 * @return Result of operation, 0 on success, otherwise error code 275 * @return Result of operation, 0 on success, otherwise error code
276 */ 276 */
277 Result WaitSynchronization(bool* wait) { 277 Result WaitSynchronization(bool* wait) override {
278 // TODO(bunnei): ImplementMe 278 // TODO(bunnei): ImplementMe
279 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 279 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
280 return 0; 280 return 0;
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 64f6a9649..45ed79be8 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -16,11 +16,11 @@ namespace Kernel {
16 16
17class Event : public Object { 17class Event : public Object {
18public: 18public:
19 std::string GetTypeName() const { return "Event"; } 19 std::string GetTypeName() const override { return "Event"; }
20 std::string GetName() const { return name; } 20 std::string GetName() const override { return name; }
21 21
22 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } 22 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; }
23 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } 23 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Event; }
24 24
25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization 25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization
26 ResetType reset_type; ///< Current ResetType 26 ResetType reset_type; ///< Current ResetType
@@ -35,7 +35,7 @@ public:
35 * @param wait Boolean wait set if current thread should wait as a result of sync operation 35 * @param wait Boolean wait set if current thread should wait as a result of sync operation
36 * @return Result of operation, 0 on success, otherwise error code 36 * @return Result of operation, 0 on success, otherwise error code
37 */ 37 */
38 Result WaitSynchronization(bool* wait) { 38 Result WaitSynchronization(bool* wait) override {
39 *wait = locked; 39 *wait = locked;
40 if (locked) { 40 if (locked) {
41 Handle thread = GetCurrentThreadHandle(); 41 Handle thread = GetCurrentThreadHandle();
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 5d7d65dd9..fcfd061ac 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -15,11 +15,11 @@ namespace Kernel {
15 15
16class Mutex : public Object { 16class Mutex : public Object {
17public: 17public:
18 std::string GetTypeName() const { return "Mutex"; } 18 std::string GetTypeName() const override { return "Mutex"; }
19 std::string GetName() const { return name; } 19 std::string GetName() const override { return name; }
20 20
21 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } 21 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; }
22 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Mutex; } 22 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Mutex; }
23 23
24 bool initial_locked; ///< Initial lock state when mutex was created 24 bool initial_locked; ///< Initial lock state when mutex was created
25 bool locked; ///< Current locked state 25 bool locked; ///< Current locked state
@@ -32,7 +32,7 @@ public:
32 * @param wait Boolean wait set if current thread should wait as a result of sync operation 32 * @param wait Boolean wait set if current thread should wait as a result of sync operation
33 * @return Result of operation, 0 on success, otherwise error code 33 * @return Result of operation, 0 on success, otherwise error code
34 */ 34 */
35 Result SyncRequest(bool* wait) { 35 Result SyncRequest(bool* wait) override {
36 // TODO(bunnei): ImplementMe 36 // TODO(bunnei): ImplementMe
37 locked = true; 37 locked = true;
38 return 0; 38 return 0;
@@ -43,7 +43,7 @@ public:
43 * @param wait Boolean wait set if current thread should wait as a result of sync operation 43 * @param wait Boolean wait set if current thread should wait as a result of sync operation
44 * @return Result of operation, 0 on success, otherwise error code 44 * @return Result of operation, 0 on success, otherwise error code
45 */ 45 */
46 Result WaitSynchronization(bool* wait) { 46 Result WaitSynchronization(bool* wait) override {
47 // TODO(bunnei): ImplementMe 47 // TODO(bunnei): ImplementMe
48 *wait = locked; 48 *wait = locked;
49 49
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 2a6a483a1..6bd5e2728 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -11,17 +11,17 @@ namespace Kernel {
11 11
12class SharedMemory : public Object { 12class SharedMemory : public Object {
13public: 13public:
14 std::string GetTypeName() const { return "SharedMemory"; } 14 std::string GetTypeName() const override { return "SharedMemory"; }
15 15
16 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; } 16 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; }
17 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::SharedMemory; } 17 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::SharedMemory; }
18 18
19 /** 19 /**
20 * Wait for kernel object to synchronize 20 * Wait for kernel object to synchronize
21 * @param wait Boolean wait set if current thread should wait as a result of sync operation 21 * @param wait Boolean wait set if current thread should wait as a result of sync operation
22 * @return Result of operation, 0 on success, otherwise error code 22 * @return Result of operation, 0 on success, otherwise error code
23 */ 23 */
24 Result WaitSynchronization(bool* wait) { 24 Result WaitSynchronization(bool* wait) override {
25 // TODO(bunnei): ImplementMe 25 // TODO(bunnei): ImplementMe
26 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 26 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
27 return 0; 27 return 0;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 33c0b2a47..e15590c49 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -21,11 +21,11 @@ namespace Kernel {
21class Thread : public Kernel::Object { 21class Thread : public Kernel::Object {
22public: 22public:
23 23
24 std::string GetName() const { return name; } 24 std::string GetName() const override { return name; }
25 std::string GetTypeName() const { return "Thread"; } 25 std::string GetTypeName() const override { return "Thread"; }
26 26
27 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; } 27 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; }
28 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Thread; } 28 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Thread; }
29 29
30 inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; } 30 inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; }
31 inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; } 31 inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; }
@@ -38,7 +38,7 @@ public:
38 * @param wait Boolean wait set if current thread should wait as a result of sync operation 38 * @param wait Boolean wait set if current thread should wait as a result of sync operation
39 * @return Result of operation, 0 on success, otherwise error code 39 * @return Result of operation, 0 on success, otherwise error code
40 */ 40 */
41 Result WaitSynchronization(bool* wait) { 41 Result WaitSynchronization(bool* wait) override {
42 if (status != THREADSTATUS_DORMANT) { 42 if (status != THREADSTATUS_DORMANT) {
43 Handle thread = GetCurrentThreadHandle(); 43 Handle thread = GetCurrentThreadHandle();
44 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { 44 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
diff --git a/src/core/hle/service/apt.h b/src/core/hle/service/apt.h
index 4c7dd07e7..5af39e085 100644
--- a/src/core/hle/service/apt.h
+++ b/src/core/hle/service/apt.h
@@ -29,7 +29,7 @@ public:
29 * Gets the string port name used by CTROS for the service 29 * Gets the string port name used by CTROS for the service
30 * @return Port name of service 30 * @return Port name of service
31 */ 31 */
32 std::string GetPortName() const { 32 std::string GetPortName() const override {
33 return "APT:U"; 33 return "APT:U";
34 } 34 }
35}; 35};
diff --git a/src/core/hle/service/fs.cpp b/src/core/hle/service/fs.cpp
index 8469d9840..662c4f247 100644
--- a/src/core/hle/service/fs.cpp
+++ b/src/core/hle/service/fs.cpp
@@ -83,7 +83,7 @@ void OpenFileDirectly(Service::Interface* self) {
83 auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); 83 auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]);
84 LowPathType archive_type = static_cast<LowPathType>(cmd_buff[3]); 84 LowPathType archive_type = static_cast<LowPathType>(cmd_buff[3]);
85 u32 archive_size = cmd_buff[4]; 85 u32 archive_size = cmd_buff[4];
86 LowPathType type = static_cast<LowPathType>(cmd_buff[5]); 86 LowPathType file_type = static_cast<LowPathType>(cmd_buff[5]);
87 u32 size = cmd_buff[6]; 87 u32 size = cmd_buff[6];
88 FileSys::Mode mode; mode.hex = cmd_buff[7]; 88 FileSys::Mode mode; mode.hex = cmd_buff[7];
89 u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes. 89 u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes.
@@ -96,19 +96,13 @@ void OpenFileDirectly(Service::Interface* self) {
96 return; 96 return;
97 } 97 }
98 98
99 if (type != LowPathType::Char) {
100 ERROR_LOG(KERNEL, "file LowPath type other than char is currently unsupported");
101 cmd_buff[1] = -1;
102 return;
103 }
104
105 std::string archive_name = GetStringFromCmdBuff(archive_pointer, archive_size); 99 std::string archive_name = GetStringFromCmdBuff(archive_pointer, archive_size);
106 std::string file_name = GetStringFromCmdBuff(pointer, size); 100 std::string file_name = GetStringFromCmdBuff(pointer, size);
107 101
108 DEBUG_LOG(KERNEL, "archive_type=%d archive_size=%d archive_data=%s" 102 DEBUG_LOG(KERNEL, "archive_type=%d archive_size=%d archive_data=%s"
109 "file_type=%d file_size=%d file_mode=%d file_attrs=%d file_data=%s", 103 "file_type=%d file_size=%d file_mode=%d file_attrs=%d file_data=%s",
110 archive_type, archive_size, archive_name.c_str(), 104 archive_type, archive_size, archive_name.c_str(),
111 type, size, mode, attributes, file_name.c_str()); 105 file_type, size, mode, attributes, file_name.c_str());
112 106
113 // TODO(Link Mauve): check if we should even get a handle for the archive, and don't leak it. 107 // TODO(Link Mauve): check if we should even get a handle for the archive, and don't leak it.
114 Handle archive_handle = Kernel::OpenArchive(archive_id); 108 Handle archive_handle = Kernel::OpenArchive(archive_id);
@@ -123,6 +117,11 @@ void OpenFileDirectly(Service::Interface* self) {
123 return; 117 return;
124 } 118 }
125 119
120 if (file_type != LowPathType::Char) {
121 WARN_LOG(KERNEL, "file LowPath type other than char is currently unsupported; returning archive handle instead");
122 return;
123 }
124
126 Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_name, mode); 125 Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_name, mode);
127 if (handle) { 126 if (handle) {
128 cmd_buff[1] = 0; 127 cmd_buff[1] = 0;
diff --git a/src/core/hle/service/fs.h b/src/core/hle/service/fs.h
index 36f3697d3..005382540 100644
--- a/src/core/hle/service/fs.h
+++ b/src/core/hle/service/fs.h
@@ -23,7 +23,7 @@ public:
23 * Gets the string port name used by CTROS for the service 23 * Gets the string port name used by CTROS for the service
24 * @return Port name of service 24 * @return Port name of service
25 */ 25 */
26 std::string GetPortName() const { 26 std::string GetPortName() const override {
27 return "fs:USER"; 27 return "fs:USER";
28 } 28 }
29}; 29};
diff --git a/src/core/hle/service/gsp.h b/src/core/hle/service/gsp.h
index a09d59dbb..177ce8da6 100644
--- a/src/core/hle/service/gsp.h
+++ b/src/core/hle/service/gsp.h
@@ -167,7 +167,7 @@ public:
167 * Gets the string port name used by CTROS for the service 167 * Gets the string port name used by CTROS for the service
168 * @return Port name of service 168 * @return Port name of service
169 */ 169 */
170 std::string GetPortName() const { 170 std::string GetPortName() const override {
171 return "gsp::Gpu"; 171 return "gsp::Gpu";
172 } 172 }
173 173
diff --git a/src/core/hle/service/hid.h b/src/core/hle/service/hid.h
index a077e25cd..9f6c4d5ed 100644
--- a/src/core/hle/service/hid.h
+++ b/src/core/hle/service/hid.h
@@ -111,7 +111,7 @@ public:
111 * Gets the string port name used by CTROS for the service 111 * Gets the string port name used by CTROS for the service
112 * @return Port name of service 112 * @return Port name of service
113 */ 113 */
114 std::string GetPortName() const { 114 std::string GetPortName() const override {
115 return "hid:USER"; 115 return "hid:USER";
116 } 116 }
117 117
diff --git a/src/core/hle/service/ndm.h b/src/core/hle/service/ndm.h
index d5ec28f5b..2ca9fcf22 100644
--- a/src/core/hle/service/ndm.h
+++ b/src/core/hle/service/ndm.h
@@ -24,7 +24,7 @@ public:
24 * Gets the string port name used by CTROS for the service 24 * Gets the string port name used by CTROS for the service
25 * @return Port name of service 25 * @return Port name of service
26 */ 26 */
27 std::string GetPortName() const { 27 std::string GetPortName() const override {
28 return "ndm:u"; 28 return "ndm:u";
29 } 29 }
30 30
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index c0e803bda..2f5a866c9 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -39,11 +39,11 @@ class Interface : public Kernel::Object {
39 friend class Manager; 39 friend class Manager;
40public: 40public:
41 41
42 std::string GetName() const { return GetPortName(); } 42 std::string GetName() const override { return GetPortName(); }
43 std::string GetTypeName() const { return GetPortName(); } 43 std::string GetTypeName() const override { return GetPortName(); }
44 44
45 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; } 45 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; }
46 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Service; } 46 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Service; }
47 47
48 typedef void (*Function)(Interface*); 48 typedef void (*Function)(Interface*);
49 49
@@ -80,7 +80,7 @@ public:
80 * @param wait Boolean wait set if current thread should wait as a result of sync operation 80 * @param wait Boolean wait set if current thread should wait as a result of sync operation
81 * @return Result of operation, 0 on success, otherwise error code 81 * @return Result of operation, 0 on success, otherwise error code
82 */ 82 */
83 Result SyncRequest(bool* wait) { 83 Result SyncRequest(bool* wait) override {
84 u32* cmd_buff = GetCommandBuffer(); 84 u32* cmd_buff = GetCommandBuffer();
85 auto itr = m_functions.find(cmd_buff[0]); 85 auto itr = m_functions.find(cmd_buff[0]);
86 86
@@ -113,7 +113,7 @@ public:
113 * @param wait Boolean wait set if current thread should wait as a result of sync operation 113 * @param wait Boolean wait set if current thread should wait as a result of sync operation
114 * @return Result of operation, 0 on success, otherwise error code 114 * @return Result of operation, 0 on success, otherwise error code
115 */ 115 */
116 Result WaitSynchronization(bool* wait) { 116 Result WaitSynchronization(bool* wait) override {
117 // TODO(bunnei): ImplementMe 117 // TODO(bunnei): ImplementMe
118 ERROR_LOG(OSHLE, "unimplemented function"); 118 ERROR_LOG(OSHLE, "unimplemented function");
119 return 0; 119 return 0;
diff --git a/src/core/hle/service/srv.h b/src/core/hle/service/srv.h
index 9451472de..6d5fe5048 100644
--- a/src/core/hle/service/srv.h
+++ b/src/core/hle/service/srv.h
@@ -22,7 +22,7 @@ public:
22 * Gets the string name used by CTROS for the service 22 * Gets the string name used by CTROS for the service
23 * @return Port name of service 23 * @return Port name of service
24 */ 24 */
25 std::string GetPortName() const { 25 std::string GetPortName() const override {
26 return "srv:"; 26 return "srv:";
27 } 27 }
28 28
diff --git a/src/core/settings.h b/src/core/settings.h
index a84c3d4b6..d586e2ef4 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -24,6 +24,8 @@ struct Values {
24 int pad_sdown_key; 24 int pad_sdown_key;
25 int pad_sleft_key; 25 int pad_sleft_key;
26 int pad_sright_key; 26 int pad_sright_key;
27
28 bool use_virtual_sd;
27} extern values; 29} extern values;
28 30
29} 31}
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp
index 10239c8a7..a0eb0418c 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_util.cpp
@@ -29,10 +29,9 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
29 glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &result); 29 glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &result);
30 glGetShaderiv(vertex_shader_id, GL_INFO_LOG_LENGTH, &info_log_length); 30 glGetShaderiv(vertex_shader_id, GL_INFO_LOG_LENGTH, &info_log_length);
31 31
32 std::vector<char> vertex_shader_error(info_log_length);
33 glGetShaderInfoLog(vertex_shader_id, info_log_length, NULL, &vertex_shader_error[0]);
34
35 if (info_log_length > 1) { 32 if (info_log_length > 1) {
33 std::vector<char> vertex_shader_error(info_log_length);
34 glGetShaderInfoLog(vertex_shader_id, info_log_length, NULL, &vertex_shader_error[0]);
36 DEBUG_LOG(GPU, "%s", &vertex_shader_error[0]); 35 DEBUG_LOG(GPU, "%s", &vertex_shader_error[0]);
37 } 36 }
38 37
@@ -46,10 +45,9 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
46 glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS, &result); 45 glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS, &result);
47 glGetShaderiv(fragment_shader_id, GL_INFO_LOG_LENGTH, &info_log_length); 46 glGetShaderiv(fragment_shader_id, GL_INFO_LOG_LENGTH, &info_log_length);
48 47
49 std::vector<char> fragment_shader_error(info_log_length);
50 glGetShaderInfoLog(fragment_shader_id, info_log_length, NULL, &fragment_shader_error[0]);
51
52 if (info_log_length > 1) { 48 if (info_log_length > 1) {
49 std::vector<char> fragment_shader_error(info_log_length);
50 glGetShaderInfoLog(fragment_shader_id, info_log_length, NULL, &fragment_shader_error[0]);
53 DEBUG_LOG(GPU, "%s", &fragment_shader_error[0]); 51 DEBUG_LOG(GPU, "%s", &fragment_shader_error[0]);
54 } 52 }
55 53
@@ -65,10 +63,9 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
65 glGetProgramiv(program_id, GL_LINK_STATUS, &result); 63 glGetProgramiv(program_id, GL_LINK_STATUS, &result);
66 glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &info_log_length); 64 glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &info_log_length);
67 65
68 std::vector<char> program_error(std::max(info_log_length, int(1)));
69 glGetProgramInfoLog(program_id, info_log_length, NULL, &program_error[0]);
70
71 if (info_log_length > 1) { 66 if (info_log_length > 1) {
67 std::vector<char> program_error(info_log_length);
68 glGetProgramInfoLog(program_id, info_log_length, NULL, &program_error[0]);
72 DEBUG_LOG(GPU, "%s", &program_error[0]); 69 DEBUG_LOG(GPU, "%s", &program_error[0]);
73 } 70 }
74 71
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 82ef4b14b..eed201a95 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -21,19 +21,19 @@ public:
21 ~RendererOpenGL() override; 21 ~RendererOpenGL() override;
22 22
23 /// Swap buffers (render frame) 23 /// Swap buffers (render frame)
24 void SwapBuffers(); 24 void SwapBuffers() override;
25 25
26 /** 26 /**
27 * Set the emulator window to use for renderer 27 * Set the emulator window to use for renderer
28 * @param window EmuWindow handle to emulator window to use for rendering 28 * @param window EmuWindow handle to emulator window to use for rendering
29 */ 29 */
30 void SetWindow(EmuWindow* window); 30 void SetWindow(EmuWindow* window) override;
31 31
32 /// Initialize the renderer 32 /// Initialize the renderer
33 void Init(); 33 void Init() override;
34 34
35 /// Shutdown the renderer 35 /// Shutdown the renderer
36 void ShutDown(); 36 void ShutDown() override;
37 37
38private: 38private:
39 /// Structure used for storing information about the textures for each 3DS screen 39 /// Structure used for storing information about the textures for each 3DS screen