Assemble.cpp revision 291c84f60853d30e1c0d79dd08c5e5164f588e26
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Dalvik.h"
18#include "libdex/DexOpcodes.h"
19
20#include "../../CompilerInternals.h"
21#include "ArmLIR.h"
22#include "Codegen.h"
23#include <sys/mman.h>           /* for protection change */
24
25#define MAX_ASSEMBLER_RETRIES 10
26
27/*
28 * opcode: ArmOpcode enum
29 * skeleton: pre-designated bit-pattern for this opcode
30 * k0: key to applying ds/de
31 * ds: dest start bit position
32 * de: dest end bit position
33 * k1: key to applying s1s/s1e
34 * s1s: src1 start bit position
35 * s1e: src1 end bit position
36 * k2: key to applying s2s/s2e
37 * s2s: src2 start bit position
38 * s2e: src2 end bit position
39 * operands: number of operands (for sanity check purposes)
40 * name: mnemonic name
41 * fmt: for pretty-printing
42 */
43#define ENCODING_MAP(opcode, skeleton, k0, ds, de, k1, s1s, s1e, k2, s2s, s2e, \
44                     k3, k3s, k3e, flags, name, fmt, size) \
45        {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \
46                    {k3, k3s, k3e}}, opcode, flags, name, fmt, size}
47
48/* Instruction dump string format keys: !pf, where "!" is the start
49 * of the key, "p" is which numeric operand to use and "f" is the
50 * print format.
51 *
52 * [p]ositions:
53 *     0 -> operands[0] (dest)
54 *     1 -> operands[1] (src1)
55 *     2 -> operands[2] (src2)
56 *     3 -> operands[3] (extra)
57 *
58 * [f]ormats:
59 *     h -> 4-digit hex
60 *     d -> decimal
61 *     E -> decimal*4
62 *     F -> decimal*2
63 *     c -> branch condition (beq, bne, etc.)
64 *     t -> pc-relative target
65 *     u -> 1st half of bl[x] target
66 *     v -> 2nd half ob bl[x] target
67 *     R -> register list
68 *     s -> single precision floating point register
69 *     S -> double precision floating point register
70 *     m -> Thumb2 modified immediate
71 *     n -> complimented Thumb2 modified immediate
72 *     M -> Thumb2 16-bit zero-extended immediate
73 *     b -> 4-digit binary
74 *     B -> dmb option string (sy, st, ish, ishst, nsh, hshst)
75 *     H -> operand shift
76 *
77 *  [!] escape.  To insert "!", use "!!"
78 */
79/* NOTE: must be kept in sync with enum ArmOpcode from ArmLIR.h */
80ArmEncodingMap EncodingMap[kArmLast] = {
81    ENCODING_MAP(kArm16BitData,    0x0000,
82                 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
83                 kFmtUnused, -1, -1, IS_UNARY_OP, "data", "0x!0h(!0d)", 1),
84    ENCODING_MAP(kThumbAdcRR,        0x4140,
85                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
86                 kFmtUnused, -1, -1,
87                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES | USES_CCODES,
88                 "adcs", "r!0d, r!1d", 1),
89    ENCODING_MAP(kThumbAddRRI3,      0x1c00,
90                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
91                 kFmtUnused, -1, -1,
92                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
93                 "adds", "r!0d, r!1d, #!2d", 1),
94    ENCODING_MAP(kThumbAddRI8,       0x3000,
95                 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1,
96                 kFmtUnused, -1, -1,
97                 IS_BINARY_OP | REG_DEF0_USE0 | SETS_CCODES,
98                 "adds", "r!0d, r!0d, #!1d", 1),
99    ENCODING_MAP(kThumbAddRRR,       0x1800,
100                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
101                 kFmtUnused, -1, -1,
102                 IS_TERTIARY_OP | REG_DEF0_USE12 | SETS_CCODES,
103                 "adds", "r!0d, r!1d, r!2d", 1),
104    ENCODING_MAP(kThumbAddRRLH,     0x4440,
105                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
106                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE01,
107                 "add", "r!0d, r!1d", 1),
108    ENCODING_MAP(kThumbAddRRHL,     0x4480,
109                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
110                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE01,
111                 "add", "r!0d, r!1d", 1),
112    ENCODING_MAP(kThumbAddRRHH,     0x44c0,
113                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
114                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE01,
115                 "add", "r!0d, r!1d", 1),
116    ENCODING_MAP(kThumbAddPcRel,    0xa000,
117                 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1,
118                 kFmtUnused, -1, -1, IS_TERTIARY_OP | IS_BRANCH,
119                 "add", "r!0d, pc, #!1E", 1),
120    ENCODING_MAP(kThumbAddSpRel,    0xa800,
121                 kFmtBitBlt, 10, 8, kFmtUnused, -1, -1, kFmtBitBlt, 7, 0,
122                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF_SP | REG_USE_SP,
123                 "add", "r!0d, sp, #!2E", 1),
124    ENCODING_MAP(kThumbAddSpI7,      0xb000,
125                 kFmtBitBlt, 6, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
126                 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF_SP | REG_USE_SP,
127                 "add", "sp, #!0d*4", 1),
128    ENCODING_MAP(kThumbAndRR,        0x4000,
129                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
130                 kFmtUnused, -1, -1,
131                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
132                 "ands", "r!0d, r!1d", 1),
133    ENCODING_MAP(kThumbAsrRRI5,      0x1000,
134                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6,
135                 kFmtUnused, -1, -1,
136                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
137                 "asrs", "r!0d, r!1d, #!2d", 1),
138    ENCODING_MAP(kThumbAsrRR,        0x4100,
139                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
140                 kFmtUnused, -1, -1,
141                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
142                 "asrs", "r!0d, r!1d", 1),
143    ENCODING_MAP(kThumbBCond,        0xd000,
144                 kFmtBitBlt, 7, 0, kFmtBitBlt, 11, 8, kFmtUnused, -1, -1,
145                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | USES_CCODES,
146                 "b!1c", "!0t", 1),
147    ENCODING_MAP(kThumbBUncond,      0xe000,
148                 kFmtBitBlt, 10, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
149                 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH,
150                 "b", "!0t", 1),
151    ENCODING_MAP(kThumbBicRR,        0x4380,
152                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
153                 kFmtUnused, -1, -1,
154                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
155                 "bics", "r!0d, r!1d", 1),
156    ENCODING_MAP(kThumbBkpt,          0xbe00,
157                 kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
158                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH,
159                 "bkpt", "!0d", 1),
160    ENCODING_MAP(kThumbBlx1,         0xf000,
161                 kFmtBitBlt, 10, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
162                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_DEF_LR,
163                 "blx_1", "!0u", 1),
164    ENCODING_MAP(kThumbBlx2,         0xe800,
165                 kFmtBitBlt, 10, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
166                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_DEF_LR,
167                 "blx_2", "!0v", 1),
168    ENCODING_MAP(kThumbBl1,          0xf000,
169                 kFmtBitBlt, 10, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
170                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR,
171                 "bl_1", "!0u", 1),
172    ENCODING_MAP(kThumbBl2,          0xf800,
173                 kFmtBitBlt, 10, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
174                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR,
175                 "bl_2", "!0v", 1),
176    ENCODING_MAP(kThumbBlxR,         0x4780,
177                 kFmtBitBlt, 6, 3, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
178                 kFmtUnused, -1, -1,
179                 IS_UNARY_OP | REG_USE0 | IS_BRANCH | REG_DEF_LR,
180                 "blx", "r!0d", 1),
181    ENCODING_MAP(kThumbBx,            0x4700,
182                 kFmtBitBlt, 6, 3, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
183                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH,
184                 "bx", "r!0d", 1),
185    ENCODING_MAP(kThumbCmnRR,        0x42c0,
186                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
187                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01 | SETS_CCODES,
188                 "cmn", "r!0d, r!1d", 1),
189    ENCODING_MAP(kThumbCmpRI8,       0x2800,
190                 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1,
191                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | SETS_CCODES,
192                 "cmp", "r!0d, #!1d", 1),
193    ENCODING_MAP(kThumbCmpRR,        0x4280,
194                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
195                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01 | SETS_CCODES,
196                 "cmp", "r!0d, r!1d", 1),
197    ENCODING_MAP(kThumbCmpLH,        0x4540,
198                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
199                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01 | SETS_CCODES,
200                 "cmp", "r!0d, r!1d", 1),
201    ENCODING_MAP(kThumbCmpHL,        0x4580,
202                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
203                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01 | SETS_CCODES,
204                 "cmp", "r!0d, r!1d", 1),
205    ENCODING_MAP(kThumbCmpHH,        0x45c0,
206                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
207                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01 | SETS_CCODES,
208                 "cmp", "r!0d, r!1d", 1),
209    ENCODING_MAP(kThumbEorRR,        0x4040,
210                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
211                 kFmtUnused, -1, -1,
212                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
213                 "eors", "r!0d, r!1d", 1),
214    ENCODING_MAP(kThumbLdmia,         0xc800,
215                 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1,
216                 kFmtUnused, -1, -1,
217                 IS_BINARY_OP | REG_DEF0_USE0 | REG_DEF_LIST1 | IS_LOAD,
218                 "ldmia", "r!0d!!, <!1R>", 1),
219    ENCODING_MAP(kThumbLdrRRI5,      0x6800,
220                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6,
221                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
222                 "ldr", "r!0d, [r!1d, #!2E]", 1),
223    ENCODING_MAP(kThumbLdrRRR,       0x5800,
224                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
225                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12 | IS_LOAD,
226                 "ldr", "r!0d, [r!1d, r!2d]", 1),
227    ENCODING_MAP(kThumbLdrPcRel,    0x4800,
228                 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1,
229                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0 | REG_USE_PC
230                 | IS_LOAD, "ldr", "r!0d, [pc, #!1E]", 1),
231    ENCODING_MAP(kThumbLdrSpRel,    0x9800,
232                 kFmtBitBlt, 10, 8, kFmtUnused, -1, -1, kFmtBitBlt, 7, 0,
233                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0 | REG_USE_SP
234                 | IS_LOAD, "ldr", "r!0d, [sp, #!2E]", 1),
235    ENCODING_MAP(kThumbLdrbRRI5,     0x7800,
236                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6,
237                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
238                 "ldrb", "r!0d, [r!1d, #2d]", 1),
239    ENCODING_MAP(kThumbLdrbRRR,      0x5c00,
240                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
241                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12 | IS_LOAD,
242                 "ldrb", "r!0d, [r!1d, r!2d]", 1),
243    ENCODING_MAP(kThumbLdrhRRI5,     0x8800,
244                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6,
245                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
246                 "ldrh", "r!0d, [r!1d, #!2F]", 1),
247    ENCODING_MAP(kThumbLdrhRRR,      0x5a00,
248                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
249                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12 | IS_LOAD,
250                 "ldrh", "r!0d, [r!1d, r!2d]", 1),
251    ENCODING_MAP(kThumbLdrsbRRR,     0x5600,
252                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
253                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12 | IS_LOAD,
254                 "ldrsb", "r!0d, [r!1d, r!2d]", 1),
255    ENCODING_MAP(kThumbLdrshRRR,     0x5e00,
256                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
257                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12 | IS_LOAD,
258                 "ldrsh", "r!0d, [r!1d, r!2d]", 1),
259    ENCODING_MAP(kThumbLslRRI5,      0x0000,
260                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6,
261                 kFmtUnused, -1, -1,
262                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
263                 "lsls", "r!0d, r!1d, #!2d", 1),
264    ENCODING_MAP(kThumbLslRR,        0x4080,
265                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
266                 kFmtUnused, -1, -1,
267                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
268                 "lsls", "r!0d, r!1d", 1),
269    ENCODING_MAP(kThumbLsrRRI5,      0x0800,
270                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6,
271                 kFmtUnused, -1, -1,
272                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
273                 "lsrs", "r!0d, r!1d, #!2d", 1),
274    ENCODING_MAP(kThumbLsrRR,        0x40c0,
275                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
276                 kFmtUnused, -1, -1,
277                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
278                 "lsrs", "r!0d, r!1d", 1),
279    ENCODING_MAP(kThumbMovImm,       0x2000,
280                 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1,
281                 kFmtUnused, -1, -1,
282                 IS_BINARY_OP | REG_DEF0 | SETS_CCODES,
283                 "movs", "r!0d, #!1d", 1),
284    ENCODING_MAP(kThumbMovRR,        0x1c00,
285                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
286                 kFmtUnused, -1, -1,
287                 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
288                 "movs", "r!0d, r!1d", 1),
289    ENCODING_MAP(kThumbMovRR_H2H,    0x46c0,
290                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
291                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
292                 "mov", "r!0d, r!1d", 1),
293    ENCODING_MAP(kThumbMovRR_H2L,    0x4640,
294                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
295                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
296                 "mov", "r!0d, r!1d", 1),
297    ENCODING_MAP(kThumbMovRR_L2H,    0x4680,
298                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
299                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
300                 "mov", "r!0d, r!1d", 1),
301    ENCODING_MAP(kThumbMul,           0x4340,
302                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
303                 kFmtUnused, -1, -1,
304                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
305                 "muls", "r!0d, r!1d", 1),
306    ENCODING_MAP(kThumbMvn,           0x43c0,
307                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
308                 kFmtUnused, -1, -1,
309                 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
310                 "mvns", "r!0d, r!1d", 1),
311    ENCODING_MAP(kThumbNeg,           0x4240,
312                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
313                 kFmtUnused, -1, -1,
314                 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
315                 "negs", "r!0d, r!1d", 1),
316    ENCODING_MAP(kThumbOrr,           0x4300,
317                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
318                 kFmtUnused, -1, -1,
319                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
320                 "orrs", "r!0d, r!1d", 1),
321    ENCODING_MAP(kThumbPop,           0xbc00,
322                 kFmtBitBlt, 8, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
323                 kFmtUnused, -1, -1,
324                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0
325                 | IS_LOAD, "pop", "<!0R>", 1),
326    ENCODING_MAP(kThumbPush,          0xb400,
327                 kFmtBitBlt, 8, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
328                 kFmtUnused, -1, -1,
329                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE_LIST0
330                 | IS_STORE, "push", "<!0R>", 1),
331    ENCODING_MAP(kThumbRorRR,        0x41c0,
332                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
333                 kFmtUnused, -1, -1,
334                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
335                 "rors", "r!0d, r!1d", 1),
336    ENCODING_MAP(kThumbSbc,           0x4180,
337                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
338                 kFmtUnused, -1, -1,
339                 IS_BINARY_OP | REG_DEF0_USE01 | USES_CCODES | SETS_CCODES,
340                 "sbcs", "r!0d, r!1d", 1),
341    ENCODING_MAP(kThumbStmia,         0xc000,
342                 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1,
343                 kFmtUnused, -1, -1,
344                 IS_BINARY_OP | REG_DEF0 | REG_USE0 | REG_USE_LIST1 | IS_STORE,
345                 "stmia", "r!0d!!, <!1R>", 1),
346    ENCODING_MAP(kThumbStrRRI5,      0x6000,
347                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6,
348                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE,
349                 "str", "r!0d, [r!1d, #!2E]", 1),
350    ENCODING_MAP(kThumbStrRRR,       0x5000,
351                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
352                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE012 | IS_STORE,
353                 "str", "r!0d, [r!1d, r!2d]", 1),
354    ENCODING_MAP(kThumbStrSpRel,    0x9000,
355                 kFmtBitBlt, 10, 8, kFmtUnused, -1, -1, kFmtBitBlt, 7, 0,
356                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE0 | REG_USE_SP
357                 | IS_STORE, "str", "r!0d, [sp, #!2E]", 1),
358    ENCODING_MAP(kThumbStrbRRI5,     0x7000,
359                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6,
360                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE,
361                 "strb", "r!0d, [r!1d, #!2d]", 1),
362    ENCODING_MAP(kThumbStrbRRR,      0x5400,
363                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
364                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE012 | IS_STORE,
365                 "strb", "r!0d, [r!1d, r!2d]", 1),
366    ENCODING_MAP(kThumbStrhRRI5,     0x8000,
367                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6,
368                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE,
369                 "strh", "r!0d, [r!1d, #!2F]", 1),
370    ENCODING_MAP(kThumbStrhRRR,      0x5200,
371                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
372                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE012 | IS_STORE,
373                 "strh", "r!0d, [r!1d, r!2d]", 1),
374    ENCODING_MAP(kThumbSubRRI3,      0x1e00,
375                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
376                 kFmtUnused, -1, -1,
377                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
378                 "subs", "r!0d, r!1d, #!2d]", 1),
379    ENCODING_MAP(kThumbSubRI8,       0x3800,
380                 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1,
381                 kFmtUnused, -1, -1,
382                 IS_BINARY_OP | REG_DEF0_USE0 | SETS_CCODES,
383                 "subs", "r!0d, #!1d", 1),
384    ENCODING_MAP(kThumbSubRRR,       0x1a00,
385                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6,
386                 kFmtUnused, -1, -1,
387                 IS_TERTIARY_OP | REG_DEF0_USE12 | SETS_CCODES,
388                 "subs", "r!0d, r!1d, r!2d", 1),
389    ENCODING_MAP(kThumbSubSpI7,      0xb080,
390                 kFmtBitBlt, 6, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
391                 kFmtUnused, -1, -1,
392                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP,
393                 "sub", "sp, #!0d", 1),
394    ENCODING_MAP(kThumbSwi,           0xdf00,
395                 kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,                       kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH,
396                 "swi", "!0d", 1),
397    ENCODING_MAP(kThumbTst,           0x4200,
398                 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1,
399                 kFmtUnused, -1, -1, IS_UNARY_OP | REG_USE01 | SETS_CCODES,
400                 "tst", "r!0d, r!1d", 1),
401    ENCODING_MAP(kThumb2Vldrs,       0xed900a00,
402                 kFmtSfp, 22, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0,
403                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
404                 "vldr", "!0s, [r!1d, #!2E]", 2),
405    ENCODING_MAP(kThumb2Vldrd,       0xed900b00,
406                 kFmtDfp, 22, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0,
407                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
408                 "vldr", "!0S, [r!1d, #!2E]", 2),
409    ENCODING_MAP(kThumb2Vmuls,        0xee200a00,
410                 kFmtSfp, 22, 12, kFmtSfp, 7, 16, kFmtSfp, 5, 0,
411                 kFmtUnused, -1, -1,
412                 IS_TERTIARY_OP | REG_DEF0_USE12,
413                 "vmuls", "!0s, !1s, !2s", 2),
414    ENCODING_MAP(kThumb2Vmuld,        0xee200b00,
415                 kFmtDfp, 22, 12, kFmtDfp, 7, 16, kFmtDfp, 5, 0,
416                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
417                 "vmuld", "!0S, !1S, !2S", 2),
418    ENCODING_MAP(kThumb2Vstrs,       0xed800a00,
419                 kFmtSfp, 22, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0,
420                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE,
421                 "vstr", "!0s, [r!1d, #!2E]", 2),
422    ENCODING_MAP(kThumb2Vstrd,       0xed800b00,
423                 kFmtDfp, 22, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0,
424                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE,
425                 "vstr", "!0S, [r!1d, #!2E]", 2),
426    ENCODING_MAP(kThumb2Vsubs,        0xee300a40,
427                 kFmtSfp, 22, 12, kFmtSfp, 7, 16, kFmtSfp, 5, 0,
428                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
429                 "vsub", "!0s, !1s, !2s", 2),
430    ENCODING_MAP(kThumb2Vsubd,        0xee300b40,
431                 kFmtDfp, 22, 12, kFmtDfp, 7, 16, kFmtDfp, 5, 0,
432                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
433                 "vsub", "!0S, !1S, !2S", 2),
434    ENCODING_MAP(kThumb2Vadds,        0xee300a00,
435                 kFmtSfp, 22, 12, kFmtSfp, 7, 16, kFmtSfp, 5, 0,
436                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
437                 "vadd", "!0s, !1s, !2s", 2),
438    ENCODING_MAP(kThumb2Vaddd,        0xee300b00,
439                 kFmtDfp, 22, 12, kFmtDfp, 7, 16, kFmtDfp, 5, 0,
440                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
441                 "vadd", "!0S, !1S, !2S", 2),
442    ENCODING_MAP(kThumb2Vdivs,        0xee800a00,
443                 kFmtSfp, 22, 12, kFmtSfp, 7, 16, kFmtSfp, 5, 0,
444                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
445                 "vdivs", "!0s, !1s, !2s", 2),
446    ENCODING_MAP(kThumb2Vdivd,        0xee800b00,
447                 kFmtDfp, 22, 12, kFmtDfp, 7, 16, kFmtDfp, 5, 0,
448                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
449                 "vdivd", "!0S, !1S, !2S", 2),
450    ENCODING_MAP(kThumb2VcvtIF,       0xeeb80ac0,
451                 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1,
452                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
453                 "vcvt.f32", "!0s, !1s", 2),
454    ENCODING_MAP(kThumb2VcvtID,       0xeeb80bc0,
455                 kFmtDfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1,
456                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
457                 "vcvt.f64", "!0S, !1s", 2),
458    ENCODING_MAP(kThumb2VcvtFI,       0xeebd0ac0,
459                 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1,
460                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
461                 "vcvt.s32.f32 ", "!0s, !1s", 2),
462    ENCODING_MAP(kThumb2VcvtDI,       0xeebd0bc0,
463                 kFmtSfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1,
464                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
465                 "vcvt.s32.f64 ", "!0s, !1S", 2),
466    ENCODING_MAP(kThumb2VcvtFd,       0xeeb70ac0,
467                 kFmtDfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1,
468                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
469                 "vcvt.f64.f32 ", "!0S, !1s", 2),
470    ENCODING_MAP(kThumb2VcvtDF,       0xeeb70bc0,
471                 kFmtSfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1,
472                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
473                 "vcvt.f32.f64 ", "!0s, !1S", 2),
474    ENCODING_MAP(kThumb2Vsqrts,       0xeeb10ac0,
475                 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1,
476                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
477                 "vsqrt.f32 ", "!0s, !1s", 2),
478    ENCODING_MAP(kThumb2Vsqrtd,       0xeeb10bc0,
479                 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1,
480                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
481                 "vsqrt.f64 ", "!0S, !1S", 2),
482    ENCODING_MAP(kThumb2MovImmShift, 0xf04f0000, /* no setflags encoding */
483                 kFmtBitBlt, 11, 8, kFmtModImm, -1, -1, kFmtUnused, -1, -1,
484                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
485                 "mov", "r!0d, #!1m", 2),
486    ENCODING_MAP(kThumb2MovImm16,       0xf2400000,
487                 kFmtBitBlt, 11, 8, kFmtImm16, -1, -1, kFmtUnused, -1, -1,
488                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
489                 "mov", "r!0d, #!1M", 2),
490    ENCODING_MAP(kThumb2StrRRI12,       0xf8c00000,
491                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0,
492                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE,
493                 "str", "r!0d, [r!1d, #!2d]", 2),
494    ENCODING_MAP(kThumb2LdrRRI12,       0xf8d00000,
495                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0,
496                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
497                 "ldr", "r!0d, [r!1d, #!2d]", 2),
498    ENCODING_MAP(kThumb2StrRRI8Predec,       0xf8400c00,
499                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 8, 0,
500                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE,
501                 "str", "r!0d, [r!1d, #-!2d]", 2),
502    ENCODING_MAP(kThumb2LdrRRI8Predec,       0xf8500c00,
503                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 8, 0,
504                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
505                 "ldr", "r!0d, [r!1d, #-!2d]", 2),
506    ENCODING_MAP(kThumb2Cbnz,       0xb900, /* Note: does not affect flags */
507                 kFmtBitBlt, 2, 0, kFmtImm6, -1, -1, kFmtUnused, -1, -1,
508                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | IS_BRANCH,
509                 "cbnz", "r!0d,!1t", 1),
510    ENCODING_MAP(kThumb2Cbz,       0xb100, /* Note: does not affect flags */
511                 kFmtBitBlt, 2, 0, kFmtImm6, -1, -1, kFmtUnused, -1, -1,
512                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | IS_BRANCH,
513                 "cbz", "r!0d,!1t", 1),
514    ENCODING_MAP(kThumb2AddRRI12,       0xf2000000,
515                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtImm12, -1, -1,
516                 kFmtUnused, -1, -1,
517                 IS_TERTIARY_OP | REG_DEF0_USE1,/* Note: doesn't affect flags */
518                 "add", "r!0d,r!1d,#!2d", 2),
519    ENCODING_MAP(kThumb2MovRR,       0xea4f0000, /* no setflags encoding */
520                 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtUnused, -1, -1,
521                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
522                 "mov", "r!0d, r!1d", 2),
523    ENCODING_MAP(kThumb2Vmovs,       0xeeb00a40,
524                 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1,
525                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
526                 "vmov.f32 ", " !0s, !1s", 2),
527    ENCODING_MAP(kThumb2Vmovd,       0xeeb00b40,
528                 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1,
529                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
530                 "vmov.f64 ", " !0S, !1S", 2),
531    ENCODING_MAP(kThumb2Ldmia,         0xe8900000,
532                 kFmtBitBlt, 19, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
533                 kFmtUnused, -1, -1,
534                 IS_BINARY_OP | REG_DEF0_USE0 | REG_DEF_LIST1 | IS_LOAD,
535                 "ldmia", "r!0d!!, <!1R>", 2),
536    ENCODING_MAP(kThumb2Stmia,         0xe8800000,
537                 kFmtBitBlt, 19, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
538                 kFmtUnused, -1, -1,
539                 IS_BINARY_OP | REG_DEF0_USE0 | REG_USE_LIST1 | IS_STORE,
540                 "stmia", "r!0d!!, <!1R>", 2),
541    ENCODING_MAP(kThumb2AddRRR,  0xeb100000, /* setflags encoding */
542                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
543                 kFmtShift, -1, -1,
544                 IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES,
545                 "adds", "r!0d, r!1d, r!2d!3H", 2),
546    ENCODING_MAP(kThumb2SubRRR,       0xebb00000, /* setflags enconding */
547                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
548                 kFmtShift, -1, -1,
549                 IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES,
550                 "subs", "r!0d, r!1d, r!2d!3H", 2),
551    ENCODING_MAP(kThumb2SbcRRR,       0xeb700000, /* setflags encoding */
552                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
553                 kFmtShift, -1, -1,
554                 IS_QUAD_OP | REG_DEF0_USE12 | USES_CCODES | SETS_CCODES,
555                 "sbcs", "r!0d, r!1d, r!2d!3H", 2),
556    ENCODING_MAP(kThumb2CmpRR,       0xebb00f00,
557                 kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, kFmtShift, -1, -1,
558                 kFmtUnused, -1, -1,
559                 IS_TERTIARY_OP | REG_USE01 | SETS_CCODES,
560                 "cmp", "r!0d, r!1d", 2),
561    ENCODING_MAP(kThumb2SubRRI12,       0xf2a00000,
562                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtImm12, -1, -1,
563                 kFmtUnused, -1, -1,
564                 IS_TERTIARY_OP | REG_DEF0_USE1,/* Note: doesn't affect flags */
565                 "sub", "r!0d,r!1d,#!2d", 2),
566    ENCODING_MAP(kThumb2MvnImmShift,  0xf06f0000, /* no setflags encoding */
567                 kFmtBitBlt, 11, 8, kFmtModImm, -1, -1, kFmtUnused, -1, -1,
568                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
569                 "mvn", "r!0d, #!1n", 2),
570    ENCODING_MAP(kThumb2Sel,       0xfaa0f080,
571                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
572                 kFmtUnused, -1, -1,
573                 IS_TERTIARY_OP | REG_DEF0_USE12 | USES_CCODES,
574                 "sel", "r!0d, r!1d, r!2d", 2),
575    ENCODING_MAP(kThumb2Ubfx,       0xf3c00000,
576                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtLsb, -1, -1,
577                 kFmtBWidth, 4, 0, IS_QUAD_OP | REG_DEF0_USE1,
578                 "ubfx", "r!0d, r!1d, #!2d, #!3d", 2),
579    ENCODING_MAP(kThumb2Sbfx,       0xf3400000,
580                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtLsb, -1, -1,
581                 kFmtBWidth, 4, 0, IS_QUAD_OP | REG_DEF0_USE1,
582                 "sbfx", "r!0d, r!1d, #!2d, #!3d", 2),
583    ENCODING_MAP(kThumb2LdrRRR,    0xf8500000,
584                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
585                 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_DEF0_USE12 | IS_LOAD,
586                 "ldr", "r!0d, [r!1d, r!2d, LSL #!3d]", 2),
587    ENCODING_MAP(kThumb2LdrhRRR,    0xf8300000,
588                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
589                 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_DEF0_USE12 | IS_LOAD,
590                 "ldrh", "r!0d, [r!1d, r!2d, LSL #!3d]", 2),
591    ENCODING_MAP(kThumb2LdrshRRR,    0xf9300000,
592                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
593                 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_DEF0_USE12 | IS_LOAD,
594                 "ldrsh", "r!0d, [r!1d, r!2d, LSL #!3d]", 2),
595    ENCODING_MAP(kThumb2LdrbRRR,    0xf8100000,
596                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
597                 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_DEF0_USE12 | IS_LOAD,
598                 "ldrb", "r!0d, [r!1d, r!2d, LSL #!3d]", 2),
599    ENCODING_MAP(kThumb2LdrsbRRR,    0xf9100000,
600                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
601                 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_DEF0_USE12 | IS_LOAD,
602                 "ldrsb", "r!0d, [r!1d, r!2d, LSL #!3d]", 2),
603    ENCODING_MAP(kThumb2StrRRR,    0xf8400000,
604                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
605                 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_USE012 | IS_STORE,
606                 "str", "r!0d, [r!1d, r!2d, LSL #!3d]", 2),
607    ENCODING_MAP(kThumb2StrhRRR,    0xf8200000,
608                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
609                 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_USE012 | IS_STORE,
610                 "strh", "r!0d, [r!1d, r!2d, LSL #!3d]", 2),
611    ENCODING_MAP(kThumb2StrbRRR,    0xf8000000,
612                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
613                 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_USE012 | IS_STORE,
614                 "strb", "r!0d, [r!1d, r!2d, LSL #!3d]", 2),
615    ENCODING_MAP(kThumb2LdrhRRI12,       0xf8b00000,
616                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0,
617                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
618                 "ldrh", "r!0d, [r!1d, #!2d]", 2),
619    ENCODING_MAP(kThumb2LdrshRRI12,       0xf9b00000,
620                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0,
621                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
622                 "ldrsh", "r!0d, [r!1d, #!2d]", 2),
623    ENCODING_MAP(kThumb2LdrbRRI12,       0xf8900000,
624                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0,
625                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
626                 "ldrb", "r!0d, [r!1d, #!2d]", 2),
627    ENCODING_MAP(kThumb2LdrsbRRI12,       0xf9900000,
628                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0,
629                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
630                 "ldrsb", "r!0d, [r!1d, #!2d]", 2),
631    ENCODING_MAP(kThumb2StrhRRI12,       0xf8a00000,
632                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0,
633                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE,
634                 "strh", "r!0d, [r!1d, #!2d]", 2),
635    ENCODING_MAP(kThumb2StrbRRI12,       0xf8800000,
636                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0,
637                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE,
638                 "strb", "r!0d, [r!1d, #!2d]", 2),
639    ENCODING_MAP(kThumb2Pop,           0xe8bd0000,
640                 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
641                 kFmtUnused, -1, -1,
642                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0
643                 | IS_LOAD, "pop", "<!0R>", 2),
644    ENCODING_MAP(kThumb2Push,          0xe92d0000,
645                 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
646                 kFmtUnused, -1, -1,
647                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE_LIST0
648                 | IS_STORE, "push", "<!0R>", 2),
649    ENCODING_MAP(kThumb2CmpRI8, 0xf1b00f00,
650                 kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, kFmtUnused, -1, -1,
651                 kFmtUnused, -1, -1,
652                 IS_BINARY_OP | REG_USE0 | SETS_CCODES,
653                 "cmp", "r!0d, #!1m", 2),
654    ENCODING_MAP(kThumb2AdcRRR,  0xeb500000, /* setflags encoding */
655                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
656                 kFmtShift, -1, -1,
657                 IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES,
658                 "adcs", "r!0d, r!1d, r!2d!3H", 2),
659    ENCODING_MAP(kThumb2AndRRR,  0xea000000,
660                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
661                 kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12,
662                 "and", "r!0d, r!1d, r!2d!3H", 2),
663    ENCODING_MAP(kThumb2BicRRR,  0xea200000,
664                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
665                 kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12,
666                 "bic", "r!0d, r!1d, r!2d!3H", 2),
667    ENCODING_MAP(kThumb2CmnRR,  0xeb000000,
668                 kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, kFmtShift, -1, -1,
669                 kFmtUnused, -1, -1,
670                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
671                 "cmn", "r!0d, r!1d, shift !2d", 2),
672    ENCODING_MAP(kThumb2EorRRR,  0xea800000,
673                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
674                 kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12,
675                 "eor", "r!0d, r!1d, r!2d!3H", 2),
676    ENCODING_MAP(kThumb2MulRRR,  0xfb00f000,
677                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
678                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
679                 "mul", "r!0d, r!1d, r!2d", 2),
680    ENCODING_MAP(kThumb2MnvRR,  0xea6f0000,
681                 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtShift, -1, -1,
682                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
683                 "mvn", "r!0d, r!1d, shift !2d", 2),
684    ENCODING_MAP(kThumb2RsubRRI8,       0xf1d00000,
685                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1,
686                 kFmtUnused, -1, -1,
687                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
688                 "rsb", "r!0d,r!1d,#!2m", 2),
689    ENCODING_MAP(kThumb2NegRR,       0xf1d00000, /* instance of rsub */
690                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtUnused, -1, -1,
691                 kFmtUnused, -1, -1,
692                 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
693                 "neg", "r!0d,r!1d", 2),
694    ENCODING_MAP(kThumb2OrrRRR,  0xea400000,
695                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
696                 kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12,
697                 "orr", "r!0d, r!1d, r!2d!3H", 2),
698    ENCODING_MAP(kThumb2TstRR,       0xea100f00,
699                 kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, kFmtShift, -1, -1,
700                 kFmtUnused, -1, -1,
701                 IS_TERTIARY_OP | REG_USE01 | SETS_CCODES,
702                 "tst", "r!0d, r!1d, shift !2d", 2),
703    ENCODING_MAP(kThumb2LslRRR,  0xfa00f000,
704                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
705                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
706                 "lsl", "r!0d, r!1d, r!2d", 2),
707    ENCODING_MAP(kThumb2LsrRRR,  0xfa20f000,
708                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
709                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
710                 "lsr", "r!0d, r!1d, r!2d", 2),
711    ENCODING_MAP(kThumb2AsrRRR,  0xfa40f000,
712                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
713                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
714                 "asr", "r!0d, r!1d, r!2d", 2),
715    ENCODING_MAP(kThumb2RorRRR,  0xfa60f000,
716                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
717                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
718                 "ror", "r!0d, r!1d, r!2d", 2),
719    ENCODING_MAP(kThumb2LslRRI5,  0xea4f0000,
720                 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtShift5, -1, -1,
721                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
722                 "lsl", "r!0d, r!1d, #!2d", 2),
723    ENCODING_MAP(kThumb2LsrRRI5,  0xea4f0010,
724                 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtShift5, -1, -1,
725                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
726                 "lsr", "r!0d, r!1d, #!2d", 2),
727    ENCODING_MAP(kThumb2AsrRRI5,  0xea4f0020,
728                 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtShift5, -1, -1,
729                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
730                 "asr", "r!0d, r!1d, #!2d", 2),
731    ENCODING_MAP(kThumb2RorRRI5,  0xea4f0030,
732                 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtShift5, -1, -1,
733                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
734                 "ror", "r!0d, r!1d, #!2d", 2),
735    ENCODING_MAP(kThumb2BicRRI8,  0xf0200000,
736                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1,
737                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
738                 "bic", "r!0d, r!1d, #!2m", 2),
739    ENCODING_MAP(kThumb2AndRRI8,  0xf0000000,
740                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1,
741                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
742                 "and", "r!0d, r!1d, #!2m", 2),
743    ENCODING_MAP(kThumb2OrrRRI8,  0xf0400000,
744                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1,
745                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
746                 "orr", "r!0d, r!1d, #!2m", 2),
747    ENCODING_MAP(kThumb2EorRRI8,  0xf0800000,
748                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1,
749                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
750                 "eor", "r!0d, r!1d, #!2m", 2),
751    ENCODING_MAP(kThumb2AddRRI8,  0xf1100000,
752                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1,
753                 kFmtUnused, -1, -1,
754                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
755                 "adds", "r!0d, r!1d, #!2m", 2),
756    ENCODING_MAP(kThumb2AdcRRI8,  0xf1500000,
757                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1,
758                 kFmtUnused, -1, -1,
759                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES | USES_CCODES,
760                 "adcs", "r!0d, r!1d, #!2m", 2),
761    ENCODING_MAP(kThumb2SubRRI8,  0xf1b00000,
762                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1,
763                 kFmtUnused, -1, -1,
764                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
765                 "subs", "r!0d, r!1d, #!2m", 2),
766    ENCODING_MAP(kThumb2SbcRRI8,  0xf1700000,
767                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1,
768                 kFmtUnused, -1, -1,
769                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES | USES_CCODES,
770                 "sbcs", "r!0d, r!1d, #!2m", 2),
771    ENCODING_MAP(kThumb2It,  0xbf00,
772                 kFmtBitBlt, 7, 4, kFmtBitBlt, 3, 0, kFmtModImm, -1, -1,
773                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_IT | USES_CCODES,
774                 "it:!1b", "!0c", 1),
775    ENCODING_MAP(kThumb2Fmstat,  0xeef1fa10,
776                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
777                 kFmtUnused, -1, -1, NO_OPERAND | SETS_CCODES,
778                 "fmstat", "", 2),
779    ENCODING_MAP(kThumb2Vcmpd,        0xeeb40b40,
780                 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1,
781                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01,
782                 "vcmp.f64", "!0S, !1S", 2),
783    ENCODING_MAP(kThumb2Vcmps,        0xeeb40a40,
784                 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1,
785                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01,
786                 "vcmp.f32", "!0s, !1s", 2),
787    ENCODING_MAP(kThumb2LdrPcRel12,       0xf8df0000,
788                 kFmtBitBlt, 15, 12, kFmtBitBlt, 11, 0, kFmtUnused, -1, -1,
789                 kFmtUnused, -1, -1,
790                 IS_TERTIARY_OP | REG_DEF0 | REG_USE_PC | IS_LOAD,
791                 "ldr", "r!0d, [r15pc, #!1d]", 2),
792    ENCODING_MAP(kThumb2BCond,        0xf0008000,
793                 kFmtBrOffset, -1, -1, kFmtBitBlt, 25, 22, kFmtUnused, -1, -1,
794                 kFmtUnused, -1, -1,
795                 IS_BINARY_OP | IS_BRANCH | USES_CCODES,
796                 "b!1c", "!0t", 2),
797    ENCODING_MAP(kThumb2Vmovd_RR,       0xeeb00b40,
798                 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1,
799                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
800                 "vmov.f64", "!0S, !1S", 2),
801    ENCODING_MAP(kThumb2Vmovs_RR,       0xeeb00a40,
802                 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1,
803                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
804                 "vmov.f32", "!0s, !1s", 2),
805    ENCODING_MAP(kThumb2Fmrs,       0xee100a10,
806                 kFmtBitBlt, 15, 12, kFmtSfp, 7, 16, kFmtUnused, -1, -1,
807                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
808                 "fmrs", "r!0d, !1s", 2),
809    ENCODING_MAP(kThumb2Fmsr,       0xee000a10,
810                 kFmtSfp, 7, 16, kFmtBitBlt, 15, 12, kFmtUnused, -1, -1,
811                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
812                 "fmsr", "!0s, r!1d", 2),
813    ENCODING_MAP(kThumb2Fmrrd,       0xec500b10,
814                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtDfp, 5, 0,
815                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF01_USE2,
816                 "fmrrd", "r!0d, r!1d, !2S", 2),
817    ENCODING_MAP(kThumb2Fmdrr,       0xec400b10,
818                 kFmtDfp, 5, 0, kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16,
819                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
820                 "fmdrr", "!0S, r!1d, r!2d", 2),
821    ENCODING_MAP(kThumb2Vabsd,       0xeeb00bc0,
822                 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1,
823                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
824                 "vabs.f64", "!0S, !1S", 2),
825    ENCODING_MAP(kThumb2Vabss,       0xeeb00ac0,
826                 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1,
827                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
828                 "vabs.f32", "!0s, !1s", 2),
829    ENCODING_MAP(kThumb2Vnegd,       0xeeb10b40,
830                 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1,
831                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
832                 "vneg.f64", "!0S, !1S", 2),
833    ENCODING_MAP(kThumb2Vnegs,       0xeeb10a40,
834                 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1,
835                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
836                 "vneg.f32", "!0s, !1s", 2),
837    ENCODING_MAP(kThumb2Vmovs_IMM8,       0xeeb00a00,
838                 kFmtSfp, 22, 12, kFmtFPImm, 16, 0, kFmtUnused, -1, -1,
839                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
840                 "vmov.f32", "!0s, #0x!1h", 2),
841    ENCODING_MAP(kThumb2Vmovd_IMM8,       0xeeb00b00,
842                 kFmtDfp, 22, 12, kFmtFPImm, 16, 0, kFmtUnused, -1, -1,
843                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
844                 "vmov.f64", "!0S, #0x!1h", 2),
845    ENCODING_MAP(kThumb2Mla,  0xfb000000,
846                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
847                 kFmtBitBlt, 15, 12,
848                 IS_QUAD_OP | REG_DEF0 | REG_USE1 | REG_USE2 | REG_USE3,
849                 "mla", "r!0d, r!1d, r!2d, r!3d", 2),
850    ENCODING_MAP(kThumb2Umull,  0xfba00000,
851                 kFmtBitBlt, 15, 12, kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16,
852                 kFmtBitBlt, 3, 0,
853                 IS_QUAD_OP | REG_DEF0 | REG_DEF1 | REG_USE2 | REG_USE3,
854                 "umull", "r!0d, r!1d, r!2d, r!3d", 2),
855    ENCODING_MAP(kThumb2Ldrex,       0xe8500f00,
856                 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0,
857                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
858                 "ldrex", "r!0d, [r!1d, #!2E]", 2),
859    ENCODING_MAP(kThumb2Strex,       0xe8400000,
860                 kFmtBitBlt, 11, 8, kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16,
861                 kFmtBitBlt, 7, 0, IS_QUAD_OP | REG_DEF0_USE12 | IS_STORE,
862                 "strex", "r!0d,r!1d, [r!2d, #!2E]", 2),
863    ENCODING_MAP(kThumb2Clrex,       0xf3bf8f2f,
864                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
865                 kFmtUnused, -1, -1, NO_OPERAND,
866                 "clrex", "", 2),
867    ENCODING_MAP(kThumb2Bfi,         0xf3600000,
868                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtShift5, -1, -1,
869                 kFmtBitBlt, 4, 0, IS_QUAD_OP | REG_DEF0_USE1,
870                 "bfi", "r!0d,r!1d,#!2d,#!3d", 2),
871    ENCODING_MAP(kThumb2Bfc,         0xf36f0000,
872                 kFmtBitBlt, 11, 8, kFmtShift5, -1, -1, kFmtBitBlt, 4, 0,
873                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0,
874                 "bfc", "r!0d,#!1d,#!2d", 2),
875    ENCODING_MAP(kThumb2Dmb,         0xf3bf8f50,
876                 kFmtBitBlt, 3, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
877                 kFmtUnused, -1, -1, IS_UNARY_OP,
878                 "dmb","#!0B",2),
879    ENCODING_MAP(kThumb2LdrPcReln12,       0xf85f0000,
880                 kFmtBitBlt, 15, 12, kFmtBitBlt, 11, 0, kFmtUnused, -1, -1,
881                 kFmtUnused, -1, -1,
882                 IS_BINARY_OP | REG_DEF0 | REG_USE_PC | IS_LOAD,
883                 "ldr", "r!0d, [r15pc, -#!1d]", 2),
884    ENCODING_MAP(kThumbUndefined,       0xde00,
885                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
886                 kFmtUnused, -1, -1, NO_OPERAND,
887                 "undefined", "", 1),
888};
889
890/*
891 * The fake NOP of moving r0 to r0 actually will incur data stalls if r0 is
892 * not ready. Since r5FP is not updated often, it is less likely to
893 * generate unnecessary stall cycles.
894 */
895#define PADDING_MOV_R5_R5               0x1C2D
896
897/* Track the number of times that the code cache is patched */
898#if defined(WITH_JIT_TUNING)
899#define UPDATE_CODE_CACHE_PATCHES()    (gDvmJit.codeCachePatches++)
900#else
901#define UPDATE_CODE_CACHE_PATCHES()
902#endif
903
904/* Write the numbers in the constant and class pool to the output stream */
905static void installLiteralPools(CompilationUnit *cUnit)
906{
907    int *dataPtr = (int *) ((char *) cUnit->baseAddr + cUnit->dataOffset);
908    /* Install number of class pointer literals */
909    *dataPtr++ = cUnit->numClassPointers;
910    ArmLIR *dataLIR = (ArmLIR *) cUnit->classPointerList;
911    while (dataLIR) {
912        /*
913         * Install the callsiteinfo pointers into the cells for now. They will
914         * be converted into real pointers in dvmJitInstallClassObjectPointers.
915         */
916        *dataPtr++ = dataLIR->operands[0];
917        dataLIR = NEXT_LIR(dataLIR);
918    }
919    dataLIR = (ArmLIR *) cUnit->literalList;
920    while (dataLIR) {
921        *dataPtr++ = dataLIR->operands[0];
922        dataLIR = NEXT_LIR(dataLIR);
923    }
924}
925
926/*
927 * Assemble the LIR into binary instruction format.  Note that we may
928 * discover that pc-relative displacements may not fit the selected
929 * instruction.  In those cases we will try to substitute a new code
930 * sequence or request that the trace be shortened and retried.
931 */
932static AssemblerStatus assembleInstructions(CompilationUnit *cUnit,
933                                            intptr_t startAddr)
934{
935    short *bufferAddr = (short *) cUnit->codeBuffer;
936    ArmLIR *lir;
937
938    for (lir = (ArmLIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
939        if (lir->opcode < 0) {
940            if ((lir->opcode == kArmPseudoPseudoAlign4) &&
941                /* 1 means padding is needed */
942                (lir->operands[0] == 1)) {
943                *bufferAddr++ = PADDING_MOV_R5_R5;
944            }
945            continue;
946        }
947
948        if (lir->flags.isNop) {
949            continue;
950        }
951
952        if (lir->opcode == kThumbLdrPcRel ||
953            lir->opcode == kThumb2LdrPcRel12 ||
954            lir->opcode == kThumbAddPcRel ||
955            ((lir->opcode == kThumb2Vldrs) && (lir->operands[1] == r15pc))) {
956            ArmLIR *lirTarget = (ArmLIR *) lir->generic.target;
957            intptr_t pc = (lir->generic.offset + 4) & ~3;
958            intptr_t target = lirTarget->generic.offset;
959            int delta = target - pc;
960            if (delta & 0x3) {
961                LOGE("PC-rel distance is not multiples of 4: %d", delta);
962                dvmCompilerAbort(cUnit);
963            }
964            if ((lir->opcode == kThumb2LdrPcRel12) && (delta > 4091)) {
965                if (cUnit->printMe) {
966                    LOGD("kThumb2LdrPcRel12@%x: delta=%d", lir->generic.offset,
967                         delta);
968                    dvmCompilerCodegenDump(cUnit);
969                }
970                return kRetryHalve;
971            } else if (delta > 1020) {
972                if (cUnit->printMe) {
973                    LOGD("kThumbLdrPcRel@%x: delta=%d", lir->generic.offset,
974                         delta);
975                    dvmCompilerCodegenDump(cUnit);
976                }
977                return kRetryHalve;
978            }
979            if (lir->opcode == kThumb2Vldrs) {
980                lir->operands[2] = delta >> 2;
981            } else {
982                lir->operands[1] = (lir->opcode == kThumb2LdrPcRel12) ?
983                                    delta : delta >> 2;
984            }
985        } else if (lir->opcode == kThumb2Cbnz || lir->opcode == kThumb2Cbz) {
986            ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;
987            intptr_t pc = lir->generic.offset + 4;
988            intptr_t target = targetLIR->generic.offset;
989            int delta = target - pc;
990            if (delta > 126 || delta < 0) {
991                /* Convert to cmp rx,#0 / b[eq/ne] tgt pair */
992                ArmLIR *newInst =
993                    (ArmLIR *)dvmCompilerNew(sizeof(ArmLIR), true);
994                /* Make new branch instruction and insert after */
995                newInst->opcode = kThumbBCond;
996                newInst->operands[0] = 0;
997                newInst->operands[1] = (lir->opcode == kThumb2Cbz) ?
998                                        kArmCondEq : kArmCondNe;
999                newInst->generic.target = lir->generic.target;
1000                dvmCompilerSetupResourceMasks(newInst);
1001                dvmCompilerInsertLIRAfter((LIR *)lir, (LIR *)newInst);
1002                /* Convert the cb[n]z to a cmp rx, #0 ] */
1003                lir->opcode = kThumbCmpRI8;
1004                /* operand[0] is src1 in both cb[n]z & CmpRI8 */
1005                lir->operands[1] = 0;
1006                lir->generic.target = 0;
1007                dvmCompilerSetupResourceMasks(lir);
1008                if (cUnit->printMe) {
1009                    LOGD("kThumb2Cbnz/kThumb2Cbz@%x: delta=%d",
1010                         lir->generic.offset, delta);
1011                    dvmCompilerCodegenDump(cUnit);
1012                }
1013                return kRetryAll;
1014            } else {
1015                lir->operands[1] = delta >> 1;
1016            }
1017        } else if (lir->opcode == kThumbBCond ||
1018                   lir->opcode == kThumb2BCond) {
1019            ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;
1020            intptr_t pc = lir->generic.offset + 4;
1021            intptr_t target = targetLIR->generic.offset;
1022            int delta = target - pc;
1023            if ((lir->opcode == kThumbBCond) && (delta > 254 || delta < -256)) {
1024                if (cUnit->printMe) {
1025                    LOGD("kThumbBCond@%x: delta=%d", lir->generic.offset,
1026                         delta);
1027                    dvmCompilerCodegenDump(cUnit);
1028                }
1029                return kRetryHalve;
1030            }
1031            lir->operands[0] = delta >> 1;
1032        } else if (lir->opcode == kThumbBUncond) {
1033            ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;
1034            intptr_t pc = lir->generic.offset + 4;
1035            intptr_t target = targetLIR->generic.offset;
1036            int delta = target - pc;
1037            if (delta > 2046 || delta < -2048) {
1038                LOGE("Unconditional branch distance out of range: %d", delta);
1039                dvmCompilerAbort(cUnit);
1040            }
1041            lir->operands[0] = delta >> 1;
1042        } else if (lir->opcode == kThumbBlx1) {
1043            assert(NEXT_LIR(lir)->opcode == kThumbBlx2);
1044            /* curPC is Thumb */
1045            intptr_t curPC = (startAddr + lir->generic.offset + 4) & ~3;
1046            intptr_t target = lir->operands[1];
1047
1048            /* Match bit[1] in target with base */
1049            if (curPC & 0x2) {
1050                target |= 0x2;
1051            }
1052            int delta = target - curPC;
1053            assert((delta >= -(1<<22)) && (delta <= ((1<<22)-2)));
1054
1055            lir->operands[0] = (delta >> 12) & 0x7ff;
1056            NEXT_LIR(lir)->operands[0] = (delta>> 1) & 0x7ff;
1057        } else if (lir->opcode == kThumbBl1) {
1058            assert(NEXT_LIR(lir)->opcode == kThumbBl2);
1059            /* Both curPC and target are Thumb */
1060            intptr_t curPC = startAddr + lir->generic.offset + 4;
1061            intptr_t target = lir->operands[1];
1062
1063            int delta = target - curPC;
1064            assert((delta >= -(1<<22)) && (delta <= ((1<<22)-2)));
1065
1066            lir->operands[0] = (delta >> 12) & 0x7ff;
1067            NEXT_LIR(lir)->operands[0] = (delta>> 1) & 0x7ff;
1068        }
1069
1070        ArmEncodingMap *encoder = &EncodingMap[lir->opcode];
1071        u4 bits = encoder->skeleton;
1072        int i;
1073        for (i = 0; i < 4; i++) {
1074            u4 operand;
1075            u4 value;
1076            operand = lir->operands[i];
1077            switch(encoder->fieldLoc[i].kind) {
1078                case kFmtUnused:
1079                    break;
1080                case kFmtFPImm:
1081                    value = ((operand & 0xF0) >> 4) << encoder->fieldLoc[i].end;
1082                    value |= (operand & 0x0F) << encoder->fieldLoc[i].start;
1083                    bits |= value;
1084                    break;
1085                case kFmtBrOffset:
1086                    value = ((operand  & 0x80000) >> 19) << 26;
1087                    value |= ((operand & 0x40000) >> 18) << 11;
1088                    value |= ((operand & 0x20000) >> 17) << 13;
1089                    value |= ((operand & 0x1f800) >> 11) << 16;
1090                    value |= (operand  & 0x007ff);
1091                    bits |= value;
1092                    break;
1093                case kFmtShift5:
1094                    value = ((operand & 0x1c) >> 2) << 12;
1095                    value |= (operand & 0x03) << 6;
1096                    bits |= value;
1097                    break;
1098                case kFmtShift:
1099                    value = ((operand & 0x70) >> 4) << 12;
1100                    value |= (operand & 0x0f) << 4;
1101                    bits |= value;
1102                    break;
1103                case kFmtBWidth:
1104                    value = operand - 1;
1105                    bits |= value;
1106                    break;
1107                case kFmtLsb:
1108                    value = ((operand & 0x1c) >> 2) << 12;
1109                    value |= (operand & 0x03) << 6;
1110                    bits |= value;
1111                    break;
1112                case kFmtImm6:
1113                    value = ((operand & 0x20) >> 5) << 9;
1114                    value |= (operand & 0x1f) << 3;
1115                    bits |= value;
1116                    break;
1117                case kFmtBitBlt:
1118                    value = (operand << encoder->fieldLoc[i].start) &
1119                            ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
1120                    bits |= value;
1121                    break;
1122                case kFmtDfp: {
1123                    assert(DOUBLEREG(operand));
1124                    assert((operand & 0x1) == 0);
1125                    int regName = (operand & FP_REG_MASK) >> 1;
1126                    /* Snag the 1-bit slice and position it */
1127                    value = ((regName & 0x10) >> 4) <<
1128                            encoder->fieldLoc[i].end;
1129                    /* Extract and position the 4-bit slice */
1130                    value |= (regName & 0x0f) <<
1131                            encoder->fieldLoc[i].start;
1132                    bits |= value;
1133                    break;
1134                }
1135                case kFmtSfp:
1136                    assert(SINGLEREG(operand));
1137                    /* Snag the 1-bit slice and position it */
1138                    value = (operand & 0x1) <<
1139                            encoder->fieldLoc[i].end;
1140                    /* Extract and position the 4-bit slice */
1141                    value |= ((operand & 0x1e) >> 1) <<
1142                            encoder->fieldLoc[i].start;
1143                    bits |= value;
1144                    break;
1145                case kFmtImm12:
1146                case kFmtModImm:
1147                    value = ((operand & 0x800) >> 11) << 26;
1148                    value |= ((operand & 0x700) >> 8) << 12;
1149                    value |= operand & 0x0ff;
1150                    bits |= value;
1151                    break;
1152                case kFmtImm16:
1153                    value = ((operand & 0x0800) >> 11) << 26;
1154                    value |= ((operand & 0xf000) >> 12) << 16;
1155                    value |= ((operand & 0x0700) >> 8) << 12;
1156                    value |= operand & 0x0ff;
1157                    bits |= value;
1158                    break;
1159                default:
1160                    assert(0);
1161            }
1162        }
1163        if (encoder->size == 2) {
1164            *bufferAddr++ = (bits >> 16) & 0xffff;
1165        }
1166        *bufferAddr++ = bits & 0xffff;
1167    }
1168    return kSuccess;
1169}
1170
1171static int assignLiteralOffsetCommon(LIR *lir, int offset)
1172{
1173    for (;lir != NULL; lir = lir->next) {
1174        lir->offset = offset;
1175        offset += 4;
1176    }
1177    return offset;
1178}
1179
1180/* Determine the offset of each literal field */
1181static int assignLiteralOffset(CompilationUnit *cUnit, int offset)
1182{
1183    /* Reserved for the size field of class pointer pool */
1184    offset += 4;
1185    offset = assignLiteralOffsetCommon(cUnit->classPointerList, offset);
1186    offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
1187    return offset;
1188}
1189
1190/*
1191 * Translation layout in the code cache.  Note that the codeAddress pointer
1192 * in JitTable will point directly to the code body (field codeAddress).  The
1193 * chain cell offset codeAddress - 2, and the address of the trace profile
1194 * counter is at codeAddress - 6.
1195 *
1196 *      +----------------------------+
1197 *      | Trace Profile Counter addr |  -> 4 bytes (PROF_COUNTER_ADDR_SIZE)
1198 *      +----------------------------+
1199 *   +--| Offset to chain cell counts|  -> 2 bytes (CHAIN_CELL_OFFSET_SIZE)
1200 *   |  +----------------------------+
1201 *   |  | Trace profile code         |  <- entry point when profiling
1202 *   |  .  -   -   -   -   -   -   - .
1203 *   |  | Code body                  |  <- entry point when not profiling
1204 *   |  .                            .
1205 *   |  |                            |
1206 *   |  +----------------------------+
1207 *   |  | Chaining Cells             |  -> 12/16 bytes, 4 byte aligned
1208 *   |  .                            .
1209 *   |  .                            .
1210 *   |  |                            |
1211 *   |  +----------------------------+
1212 *   |  | Gap for large switch stmt  |  -> # cases >= MAX_CHAINED_SWITCH_CASES
1213 *   |  +----------------------------+
1214 *   +->| Chaining cell counts       |  -> 8 bytes, chain cell counts by type
1215 *      +----------------------------+
1216 *      | Trace description          |  -> variable sized
1217 *      .                            .
1218 *      |                            |
1219 *      +----------------------------+
1220 *      | # Class pointer pool size  |  -> 4 bytes
1221 *      +----------------------------+
1222 *      | Class pointer pool         |  -> 4-byte aligned, variable size
1223 *      .                            .
1224 *      .                            .
1225 *      |                            |
1226 *      +----------------------------+
1227 *      | Literal pool               |  -> 4-byte aligned, variable size
1228 *      .                            .
1229 *      .                            .
1230 *      |                            |
1231 *      +----------------------------+
1232 *
1233 */
1234
1235#define PROF_COUNTER_ADDR_SIZE 4
1236#define CHAIN_CELL_OFFSET_SIZE 2
1237
1238/*
1239 * Utility functions to navigate various parts in a trace. If we change the
1240 * layout/offset in the future, we just modify these functions and we don't need
1241 * to propagate the changes to all the use cases.
1242 */
1243static inline char *getTraceBase(const JitEntry *p)
1244{
1245    return (char*)p->codeAddress -
1246        (PROF_COUNTER_ADDR_SIZE + CHAIN_CELL_OFFSET_SIZE +
1247         (p->u.info.instructionSet == DALVIK_JIT_ARM ? 0 : 1));
1248}
1249
1250/* Handy function to retrieve the profile count */
1251static inline JitTraceCounter_t getProfileCount(const JitEntry *entry)
1252{
1253    if (entry->dPC == 0 || entry->codeAddress == 0 ||
1254        entry->codeAddress == dvmCompilerGetInterpretTemplate())
1255        return 0;
1256
1257    JitTraceCounter_t **p = (JitTraceCounter_t **) getTraceBase(entry);
1258
1259    return **p;
1260}
1261
1262/* Handy function to reset the profile count */
1263static inline void resetProfileCount(const JitEntry *entry)
1264{
1265    if (entry->dPC == 0 || entry->codeAddress == 0 ||
1266        entry->codeAddress == dvmCompilerGetInterpretTemplate())
1267        return;
1268
1269    JitTraceCounter_t **p = (JitTraceCounter_t **) getTraceBase(entry);
1270
1271    **p = 0;
1272}
1273
1274/* Get the pointer of the chain cell count */
1275static inline ChainCellCounts* getChainCellCountsPointer(const char *base)
1276{
1277    /* 4 is the size of the profile count */
1278    u2 *chainCellOffsetP = (u2 *) (base + PROF_COUNTER_ADDR_SIZE);
1279    u2 chainCellOffset = *chainCellOffsetP;
1280    return (ChainCellCounts *) ((char *) chainCellOffsetP + chainCellOffset);
1281}
1282
1283/* Get the size of all chaining cells */
1284static inline u4 getChainCellSize(const ChainCellCounts* pChainCellCounts)
1285{
1286    int cellSize = 0;
1287    int i;
1288
1289    /* Get total count of chain cells */
1290    for (i = 0; i < kChainingCellGap; i++) {
1291        if (i != kChainingCellInvokePredicted) {
1292            cellSize += pChainCellCounts->u.count[i] *
1293                        (CHAIN_CELL_NORMAL_SIZE >> 2);
1294        } else {
1295            cellSize += pChainCellCounts->u.count[i] *
1296                (CHAIN_CELL_PREDICTED_SIZE >> 2);
1297        }
1298    }
1299    return cellSize;
1300}
1301
1302/* Get the starting pointer of the trace description section */
1303static JitTraceDescription* getTraceDescriptionPointer(const char *base)
1304{
1305    ChainCellCounts* pCellCounts = getChainCellCountsPointer(base);
1306    return (JitTraceDescription*) ((char*)pCellCounts + sizeof(*pCellCounts));
1307}
1308
1309/* Get the size of a trace description */
1310static int getTraceDescriptionSize(const JitTraceDescription *desc)
1311{
1312    int runCount;
1313    /* Trace end is always of non-meta type (ie isCode == true) */
1314    for (runCount = 0; ; runCount++) {
1315        if (desc->trace[runCount].isCode &&
1316            desc->trace[runCount].info.frag.runEnd)
1317           break;
1318    }
1319    return sizeof(JitTraceDescription) + ((runCount+1) * sizeof(JitTraceRun));
1320}
1321
1322#if defined(SIGNATURE_BREAKPOINT)
1323/* Inspect the assembled instruction stream to find potential matches */
1324static void matchSignatureBreakpoint(const CompilationUnit *cUnit,
1325                                     unsigned int size)
1326{
1327    unsigned int i, j;
1328    u4 *ptr = (u4 *) cUnit->codeBuffer;
1329
1330    for (i = 0; i < size - gDvmJit.signatureBreakpointSize + 1; i++) {
1331        if (ptr[i] == gDvmJit.signatureBreakpoint[0]) {
1332            for (j = 1; j < gDvmJit.signatureBreakpointSize; j++) {
1333                if (ptr[i+j] != gDvmJit.signatureBreakpoint[j]) {
1334                    break;
1335                }
1336            }
1337            if (j == gDvmJit.signatureBreakpointSize) {
1338                LOGD("Signature match starting from offset %#x (%d words)",
1339                     i*4, gDvmJit.signatureBreakpointSize);
1340                int descSize = getTraceDescriptionSize(cUnit->traceDesc);
1341                JitTraceDescription *newCopy =
1342                    (JitTraceDescription *) malloc(descSize);
1343                memcpy(newCopy, cUnit->traceDesc, descSize);
1344                dvmCompilerWorkEnqueue(NULL, kWorkOrderTraceDebug, newCopy);
1345                break;
1346            }
1347        }
1348    }
1349}
1350#endif
1351
1352/*
1353 * Go over each instruction in the list and calculate the offset from the top
1354 * before sending them off to the assembler. If out-of-range branch distance is
1355 * seen rearrange the instructions a bit to correct it.
1356 */
1357void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
1358{
1359    ArmLIR *armLIR;
1360    int offset = 0;
1361    int i;
1362    ChainCellCounts chainCellCounts;
1363    int descSize = (cUnit->jitMode == kJitMethod) ?
1364        0 : getTraceDescriptionSize(cUnit->traceDesc);
1365    int chainingCellGap = 0;
1366
1367    info->instructionSet = cUnit->instructionSet;
1368
1369    /* Beginning offset needs to allow space for chain cell offset */
1370    for (armLIR = (ArmLIR *) cUnit->firstLIRInsn;
1371         armLIR;
1372         armLIR = NEXT_LIR(armLIR)) {
1373        armLIR->generic.offset = offset;
1374        if (armLIR->opcode >= 0 && !armLIR->flags.isNop) {
1375            armLIR->flags.size = EncodingMap[armLIR->opcode].size * 2;
1376            offset += armLIR->flags.size;
1377        } else if (armLIR->opcode == kArmPseudoPseudoAlign4) {
1378            if (offset & 0x2) {
1379                offset += 2;
1380                armLIR->operands[0] = 1;
1381            } else {
1382                armLIR->operands[0] = 0;
1383            }
1384        }
1385        /* Pseudo opcodes don't consume space */
1386    }
1387
1388    /* Const values have to be word aligned */
1389    offset = (offset + 3) & ~3;
1390
1391    u4 chainCellOffset = offset;
1392    ArmLIR *chainCellOffsetLIR = NULL;
1393
1394    if (cUnit->jitMode != kJitMethod) {
1395        /*
1396         * Get the gap (# of u4) between the offset of chaining cell count and
1397         * the bottom of real chaining cells. If the translation has chaining
1398         * cells, the gap is guaranteed to be multiples of 4.
1399         */
1400        chainingCellGap = (offset - cUnit->chainingCellBottom->offset) >> 2;
1401
1402        /* Add space for chain cell counts & trace description */
1403        chainCellOffsetLIR = (ArmLIR *) cUnit->chainCellOffsetLIR;
1404        assert(chainCellOffsetLIR);
1405        assert(chainCellOffset < 0x10000);
1406        assert(chainCellOffsetLIR->opcode == kArm16BitData &&
1407               chainCellOffsetLIR->operands[0] == CHAIN_CELL_OFFSET_TAG);
1408
1409        /*
1410         * Adjust the CHAIN_CELL_OFFSET_TAG LIR's offset to remove the
1411         * space occupied by the pointer to the trace profiling counter.
1412         */
1413        chainCellOffsetLIR->operands[0] = chainCellOffset - 4;
1414
1415        offset += sizeof(chainCellCounts) + descSize;
1416
1417        assert((offset & 0x3) == 0);  /* Should still be word aligned */
1418    }
1419
1420    /* Set up offsets for literals */
1421    cUnit->dataOffset = offset;
1422
1423    /*
1424     * Assign each class pointer/constant an offset from the beginning of the
1425     * compilation unit.
1426     */
1427    offset = assignLiteralOffset(cUnit, offset);
1428
1429    cUnit->totalSize = offset;
1430
1431    if (gDvmJit.codeCacheByteUsed + cUnit->totalSize > gDvmJit.codeCacheSize) {
1432        gDvmJit.codeCacheFull = true;
1433        info->discardResult = true;
1434        return;
1435    }
1436
1437    /* Allocate enough space for the code block */
1438    cUnit->codeBuffer = (unsigned char *)dvmCompilerNew(chainCellOffset, true);
1439    if (cUnit->codeBuffer == NULL) {
1440        LOGE("Code buffer allocation failure");
1441        info->discardResult = true;
1442        return;
1443    }
1444
1445    /*
1446     * Attempt to assemble the trace.  Note that assembleInstructions
1447     * may rewrite the code sequence and request a retry.
1448     */
1449    cUnit->assemblerStatus = assembleInstructions(cUnit,
1450          (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed);
1451
1452    switch(cUnit->assemblerStatus) {
1453        case kSuccess:
1454            break;
1455        case kRetryAll:
1456            if (cUnit->assemblerRetries < MAX_ASSEMBLER_RETRIES) {
1457                if (cUnit->jitMode != kJitMethod) {
1458                    /* Restore pristine chain cell marker on retry */
1459                    chainCellOffsetLIR->operands[0] = CHAIN_CELL_OFFSET_TAG;
1460                }
1461                return;
1462            }
1463            /* Too many retries - reset and try cutting the trace in half */
1464            cUnit->assemblerRetries = 0;
1465            cUnit->assemblerStatus = kRetryHalve;
1466            return;
1467        case kRetryHalve:
1468            return;
1469        default:
1470             LOGE("Unexpected assembler status: %d", cUnit->assemblerStatus);
1471             dvmAbort();
1472    }
1473
1474#if defined(SIGNATURE_BREAKPOINT)
1475    if (info->discardResult == false && gDvmJit.signatureBreakpoint != NULL &&
1476        chainCellOffset/4 >= gDvmJit.signatureBreakpointSize) {
1477        matchSignatureBreakpoint(cUnit, chainCellOffset/4);
1478    }
1479#endif
1480
1481    /* Don't go all the way if the goal is just to get the verbose output */
1482    if (info->discardResult) return;
1483
1484    /*
1485     * The cache might disappear - acquire lock and check version
1486     * Continue holding lock until translation cache update is complete.
1487     * These actions are required here in the compiler thread because
1488     * it is unaffected by suspend requests and doesn't know if a
1489     * translation cache flush is in progress.
1490     */
1491    dvmLockMutex(&gDvmJit.compilerLock);
1492    if (info->cacheVersion != gDvmJit.cacheVersion) {
1493        /* Cache changed - discard current translation */
1494        info->discardResult = true;
1495        info->codeAddress = NULL;
1496        dvmUnlockMutex(&gDvmJit.compilerLock);
1497        return;
1498    }
1499
1500    cUnit->baseAddr = (char *) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed;
1501    gDvmJit.codeCacheByteUsed += offset;
1502
1503    UNPROTECT_CODE_CACHE(cUnit->baseAddr, offset);
1504
1505    /* Install the code block */
1506    memcpy((char*)cUnit->baseAddr, cUnit->codeBuffer, chainCellOffset);
1507    gDvmJit.numCompilations++;
1508
1509    if (cUnit->jitMode != kJitMethod) {
1510        /* Install the chaining cell counts */
1511        for (i=0; i< kChainingCellGap; i++) {
1512            chainCellCounts.u.count[i] = cUnit->numChainingCells[i];
1513        }
1514
1515        /* Set the gap number in the chaining cell count structure */
1516        chainCellCounts.u.count[kChainingCellGap] = chainingCellGap;
1517
1518        memcpy((char*)cUnit->baseAddr + chainCellOffset, &chainCellCounts,
1519               sizeof(chainCellCounts));
1520
1521        /* Install the trace description */
1522        memcpy((char*) cUnit->baseAddr + chainCellOffset +
1523                       sizeof(chainCellCounts),
1524               cUnit->traceDesc, descSize);
1525    }
1526
1527    /* Write the literals directly into the code cache */
1528    installLiteralPools(cUnit);
1529
1530    /* Flush dcache and invalidate the icache to maintain coherence */
1531    dvmCompilerCacheFlush((long)cUnit->baseAddr,
1532                          (long)((char *) cUnit->baseAddr + offset), 0);
1533    UPDATE_CODE_CACHE_PATCHES();
1534
1535    PROTECT_CODE_CACHE(cUnit->baseAddr, offset);
1536
1537    /* Translation cache update complete - release lock */
1538    dvmUnlockMutex(&gDvmJit.compilerLock);
1539
1540    /* Record code entry point and instruction set */
1541    info->codeAddress = (char*)cUnit->baseAddr + cUnit->headerSize;
1542    /* If applicable, mark low bit to denote thumb */
1543    if (info->instructionSet != DALVIK_JIT_ARM)
1544        info->codeAddress = (char*)info->codeAddress + 1;
1545    /* transfer the size of the profiling code */
1546    info->profileCodeSize = cUnit->profileCodeSize;
1547}
1548
1549/*
1550 * Returns the skeleton bit pattern associated with an opcode.  All
1551 * variable fields are zeroed.
1552 */
1553static u4 getSkeleton(ArmOpcode op)
1554{
1555    return EncodingMap[op].skeleton;
1556}
1557
1558static u4 assembleChainingBranch(int branchOffset, bool thumbTarget)
1559{
1560    u4 thumb1, thumb2;
1561
1562    if (!thumbTarget) {
1563        thumb1 =  (getSkeleton(kThumbBlx1) | ((branchOffset>>12) & 0x7ff));
1564        thumb2 =  (getSkeleton(kThumbBlx2) | ((branchOffset>> 1) & 0x7ff));
1565    } else if ((branchOffset < -2048) | (branchOffset > 2046)) {
1566        thumb1 =  (getSkeleton(kThumbBl1) | ((branchOffset>>12) & 0x7ff));
1567        thumb2 =  (getSkeleton(kThumbBl2) | ((branchOffset>> 1) & 0x7ff));
1568    } else {
1569        thumb1 =  (getSkeleton(kThumbBUncond) | ((branchOffset>> 1) & 0x7ff));
1570        thumb2 =  getSkeleton(kThumbOrr);  /* nop -> or r0, r0 */
1571    }
1572
1573    return thumb2<<16 | thumb1;
1574}
1575
1576/*
1577 * Perform translation chain operation.
1578 * For ARM, we'll use a pair of thumb instructions to generate
1579 * an unconditional chaining branch of up to 4MB in distance.
1580 * Use a BL, because the generic "interpret" translation needs
1581 * the link register to find the dalvik pc of teh target.
1582 *     111HHooooooooooo
1583 * Where HH is 10 for the 1st inst, and 11 for the second and
1584 * the "o" field is each instruction's 11-bit contribution to the
1585 * 22-bit branch offset.
1586 * If the target is nearby, use a single-instruction bl.
1587 * If one or more threads is suspended, don't chain.
1588 */
1589void* dvmJitChain(void* tgtAddr, u4* branchAddr)
1590{
1591    int baseAddr = (u4) branchAddr + 4;
1592    int branchOffset = (int) tgtAddr - baseAddr;
1593    u4 newInst;
1594    bool thumbTarget;
1595
1596    /*
1597     * Only chain translations when there is no urge to ask all threads to
1598     * suspend themselves via the interpreter.
1599     */
1600    if ((gDvmJit.pProfTable != NULL) && (gDvm.sumThreadSuspendCount == 0) &&
1601        (gDvmJit.codeCacheFull == false)) {
1602        assert((branchOffset >= -(1<<22)) && (branchOffset <= ((1<<22)-2)));
1603
1604        gDvmJit.translationChains++;
1605
1606        COMPILER_TRACE_CHAINING(
1607            LOGD("Jit Runtime: chaining %#x to %#x",
1608                 (int) branchAddr, (int) tgtAddr & -2));
1609
1610        /*
1611         * NOTE: normally, all translations are Thumb[2] mode, with
1612         * a single exception: the default TEMPLATE_INTERPRET
1613         * pseudo-translation.  If the need ever arises to
1614         * mix Arm & Thumb[2] translations, the following code should be
1615         * generalized.
1616         */
1617        thumbTarget = (tgtAddr != dvmCompilerGetInterpretTemplate());
1618
1619        newInst = assembleChainingBranch(branchOffset, thumbTarget);
1620
1621        /*
1622         * The second half-word instruction of the chaining cell must
1623         * either be a nop (which represents initial state), or is the
1624         * same exact branch halfword that we are trying to install.
1625         */
1626        assert( ((*branchAddr >> 16) == getSkeleton(kThumbOrr)) ||
1627                ((*branchAddr >> 16) == (newInst >> 16)));
1628
1629        UNPROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr));
1630
1631        *branchAddr = newInst;
1632        dvmCompilerCacheFlush((long)branchAddr, (long)branchAddr + 4, 0);
1633        UPDATE_CODE_CACHE_PATCHES();
1634
1635        PROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr));
1636
1637        gDvmJit.hasNewChain = true;
1638    }
1639
1640    return tgtAddr;
1641}
1642
1643#if !defined(WITH_SELF_VERIFICATION)
1644/*
1645 * Attempt to enqueue a work order to patch an inline cache for a predicted
1646 * chaining cell for virtual/interface calls.
1647 */
1648static void inlineCachePatchEnqueue(PredictedChainingCell *cellAddr,
1649                                    PredictedChainingCell *newContent)
1650{
1651    /*
1652     * Make sure only one thread gets here since updating the cell (ie fast
1653     * path and queueing the request (ie the queued path) have to be done
1654     * in an atomic fashion.
1655     */
1656    dvmLockMutex(&gDvmJit.compilerICPatchLock);
1657
1658    /* Fast path for uninitialized chaining cell */
1659    if (cellAddr->clazz == NULL &&
1660        cellAddr->branch == PREDICTED_CHAIN_BX_PAIR_INIT) {
1661
1662        UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1663
1664        cellAddr->method = newContent->method;
1665        cellAddr->branch = newContent->branch;
1666        /*
1667         * The update order matters - make sure clazz is updated last since it
1668         * will bring the uninitialized chaining cell to life.
1669         */
1670        android_atomic_release_store((int32_t)newContent->clazz,
1671            (volatile int32_t *)(void *)&cellAddr->clazz);
1672        dvmCompilerCacheFlush((intptr_t) cellAddr, (intptr_t) (cellAddr+1), 0);
1673        UPDATE_CODE_CACHE_PATCHES();
1674
1675        PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1676
1677#if defined(WITH_JIT_TUNING)
1678        gDvmJit.icPatchInit++;
1679#endif
1680    /* Check if this is a frequently missed clazz */
1681    } else if (cellAddr->stagedClazz != newContent->clazz) {
1682        /* Not proven to be frequent yet - build up the filter cache */
1683        UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1684
1685        cellAddr->stagedClazz = newContent->clazz;
1686
1687        UPDATE_CODE_CACHE_PATCHES();
1688        PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1689
1690#if defined(WITH_JIT_TUNING)
1691        gDvmJit.icPatchRejected++;
1692#endif
1693    /*
1694     * Different classes but same method implementation - it is safe to just
1695     * patch the class value without the need to stop the world.
1696     */
1697    } else if (cellAddr->method == newContent->method) {
1698        UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1699
1700        cellAddr->clazz = newContent->clazz;
1701        /* No need to flush the cache here since the branch is not patched */
1702        UPDATE_CODE_CACHE_PATCHES();
1703
1704        PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1705
1706#if defined(WITH_JIT_TUNING)
1707        gDvmJit.icPatchLockFree++;
1708#endif
1709    /*
1710     * Cannot patch the chaining cell inline - queue it until the next safe
1711     * point.
1712     */
1713    } else if (gDvmJit.compilerICPatchIndex < COMPILER_IC_PATCH_QUEUE_SIZE) {
1714        int index = gDvmJit.compilerICPatchIndex++;
1715        const ClassObject *clazz = newContent->clazz;
1716
1717        gDvmJit.compilerICPatchQueue[index].cellAddr = cellAddr;
1718        gDvmJit.compilerICPatchQueue[index].cellContent = *newContent;
1719        gDvmJit.compilerICPatchQueue[index].classDescriptor = clazz->descriptor;
1720        gDvmJit.compilerICPatchQueue[index].classLoader = clazz->classLoader;
1721        /* For verification purpose only */
1722        gDvmJit.compilerICPatchQueue[index].serialNumber = clazz->serialNumber;
1723#if defined(WITH_JIT_TUNING)
1724        gDvmJit.icPatchQueued++;
1725#endif
1726    } else {
1727    /* Queue is full - just drop this patch request */
1728#if defined(WITH_JIT_TUNING)
1729        gDvmJit.icPatchDropped++;
1730#endif
1731    }
1732
1733    dvmUnlockMutex(&gDvmJit.compilerICPatchLock);
1734}
1735#endif
1736
1737/*
1738 * This method is called from the invoke templates for virtual and interface
1739 * methods to speculatively setup a chain to the callee. The templates are
1740 * written in assembly and have setup method, cell, and clazz at r0, r2, and
1741 * r3 respectively, so there is a unused argument in the list. Upon return one
1742 * of the following three results may happen:
1743 *   1) Chain is not setup because the callee is native. Reset the rechain
1744 *      count to a big number so that it will take a long time before the next
1745 *      rechain attempt to happen.
1746 *   2) Chain is not setup because the callee has not been created yet. Reset
1747 *      the rechain count to a small number and retry in the near future.
1748 *   3) Enqueue the new content for the chaining cell which will be appled in
1749 *      next safe point.
1750 */
1751const Method *dvmJitToPatchPredictedChain(const Method *method,
1752                                          Thread *self,
1753                                          PredictedChainingCell *cell,
1754                                          const ClassObject *clazz)
1755{
1756    int newRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
1757#if defined(WITH_SELF_VERIFICATION)
1758    newRechainCount = PREDICTED_CHAIN_COUNTER_AVOID;
1759    goto done;
1760#else
1761    PredictedChainingCell newCell;
1762    int baseAddr, branchOffset, tgtAddr;
1763    if (dvmIsNativeMethod(method)) {
1764        UNPROTECT_CODE_CACHE(cell, sizeof(*cell));
1765
1766        /*
1767         * Put a non-zero/bogus value in the clazz field so that it won't
1768         * trigger immediate patching and will continue to fail to match with
1769         * a real clazz pointer.
1770         */
1771        cell->clazz = (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ;
1772
1773        UPDATE_CODE_CACHE_PATCHES();
1774        PROTECT_CODE_CACHE(cell, sizeof(*cell));
1775        goto done;
1776    }
1777    tgtAddr = (int) dvmJitGetTraceAddr(method->insns);
1778
1779    /*
1780     * Compilation not made yet for the callee. Reset the counter to a small
1781     * value and come back to check soon.
1782     */
1783    if ((tgtAddr == 0) ||
1784        ((void*)tgtAddr == dvmCompilerGetInterpretTemplate())) {
1785        COMPILER_TRACE_CHAINING(
1786            LOGD("Jit Runtime: predicted chain %p to method %s%s delayed",
1787                 cell, method->clazz->descriptor, method->name));
1788        goto done;
1789    }
1790
1791    if (cell->clazz == NULL) {
1792        newRechainCount = self->icRechainCount;
1793    }
1794
1795    baseAddr = (int) cell + 4;   // PC is cur_addr + 4
1796    branchOffset = tgtAddr - baseAddr;
1797
1798    newCell.branch = assembleChainingBranch(branchOffset, true);
1799    newCell.clazz = clazz;
1800    newCell.method = method;
1801    newCell.stagedClazz = NULL;
1802
1803    /*
1804     * Enter the work order to the queue and the chaining cell will be patched
1805     * the next time a safe point is entered.
1806     *
1807     * If the enqueuing fails reset the rechain count to a normal value so that
1808     * it won't get indefinitely delayed.
1809     */
1810    inlineCachePatchEnqueue(cell, &newCell);
1811#endif
1812done:
1813    self->icRechainCount = newRechainCount;
1814    return method;
1815}
1816
1817/*
1818 * Patch the inline cache content based on the content passed from the work
1819 * order.
1820 */
1821void dvmCompilerPatchInlineCache(void)
1822{
1823    int i;
1824    PredictedChainingCell *minAddr, *maxAddr;
1825
1826    /* Nothing to be done */
1827    if (gDvmJit.compilerICPatchIndex == 0) return;
1828
1829    /*
1830     * Since all threads are already stopped we don't really need to acquire
1831     * the lock. But race condition can be easily introduced in the future w/o
1832     * paying attention so we still acquire the lock here.
1833     */
1834    dvmLockMutex(&gDvmJit.compilerICPatchLock);
1835
1836    UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1837
1838    //LOGD("Number of IC patch work orders: %d", gDvmJit.compilerICPatchIndex);
1839
1840    /* Initialize the min/max address range */
1841    minAddr = (PredictedChainingCell *)
1842        ((char *) gDvmJit.codeCache + gDvmJit.codeCacheSize);
1843    maxAddr = (PredictedChainingCell *) gDvmJit.codeCache;
1844
1845    for (i = 0; i < gDvmJit.compilerICPatchIndex; i++) {
1846        ICPatchWorkOrder *workOrder = &gDvmJit.compilerICPatchQueue[i];
1847        PredictedChainingCell *cellAddr = workOrder->cellAddr;
1848        PredictedChainingCell *cellContent = &workOrder->cellContent;
1849        ClassObject *clazz = dvmFindClassNoInit(workOrder->classDescriptor,
1850                                                workOrder->classLoader);
1851
1852        assert(clazz->serialNumber == workOrder->serialNumber);
1853
1854        /* Use the newly resolved clazz pointer */
1855        cellContent->clazz = clazz;
1856
1857        COMPILER_TRACE_CHAINING(
1858            LOGD("Jit Runtime: predicted chain %p from %s to %s (%s) "
1859                 "patched",
1860                 cellAddr,
1861                 cellAddr->clazz->descriptor,
1862                 cellContent->clazz->descriptor,
1863                 cellContent->method->name));
1864
1865        /* Patch the chaining cell */
1866        *cellAddr = *cellContent;
1867        minAddr = (cellAddr < minAddr) ? cellAddr : minAddr;
1868        maxAddr = (cellAddr > maxAddr) ? cellAddr : maxAddr;
1869    }
1870
1871    /* Then synchronize the I/D cache */
1872    dvmCompilerCacheFlush((long) minAddr, (long) (maxAddr+1), 0);
1873    UPDATE_CODE_CACHE_PATCHES();
1874
1875    PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1876
1877    gDvmJit.compilerICPatchIndex = 0;
1878    dvmUnlockMutex(&gDvmJit.compilerICPatchLock);
1879}
1880
1881/*
1882 * Unchain a trace given the starting address of the translation
1883 * in the code cache.  Refer to the diagram in dvmCompilerAssembleLIR.
1884 * Returns the address following the last cell unchained.  Note that
1885 * the incoming codeAddr is a thumb code address, and therefore has
1886 * the low bit set.
1887 */
1888static u4* unchainSingle(JitEntry *trace)
1889{
1890    const char *base = getTraceBase(trace);
1891    ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base);
1892    int cellSize = getChainCellSize(pChainCellCounts);
1893    u4* pChainCells;
1894    u4 newInst;
1895    int i,j;
1896    PredictedChainingCell *predChainCell;
1897
1898    if (cellSize == 0)
1899        return (u4 *) pChainCellCounts;
1900
1901    /* Locate the beginning of the chain cell region */
1902    pChainCells = ((u4 *) pChainCellCounts) - cellSize -
1903                  pChainCellCounts->u.count[kChainingCellGap];
1904
1905    /* The cells are sorted in order - walk through them and reset */
1906    for (i = 0; i < kChainingCellGap; i++) {
1907        int elemSize = CHAIN_CELL_NORMAL_SIZE >> 2;  /* In 32-bit words */
1908        if (i == kChainingCellInvokePredicted) {
1909            elemSize = CHAIN_CELL_PREDICTED_SIZE >> 2;
1910        }
1911
1912        for (j = 0; j < pChainCellCounts->u.count[i]; j++) {
1913            switch(i) {
1914                case kChainingCellNormal:
1915                case kChainingCellHot:
1916                case kChainingCellInvokeSingleton:
1917                case kChainingCellBackwardBranch:
1918                    /*
1919                     * Replace the 1st half-word of the cell with an
1920                     * unconditional branch, leaving the 2nd half-word
1921                     * untouched.  This avoids problems with a thread
1922                     * that is suspended between the two halves when
1923                     * this unchaining takes place.
1924                     */
1925                    newInst = *pChainCells;
1926                    newInst &= 0xFFFF0000;
1927                    newInst |= getSkeleton(kThumbBUncond); /* b offset is 0 */
1928                    *pChainCells = newInst;
1929                    break;
1930                case kChainingCellInvokePredicted:
1931                    predChainCell = (PredictedChainingCell *) pChainCells;
1932                    /*
1933                     * There could be a race on another mutator thread to use
1934                     * this particular predicted cell and the check has passed
1935                     * the clazz comparison. So we cannot safely wipe the
1936                     * method and branch but it is safe to clear the clazz,
1937                     * which serves as the key.
1938                     */
1939                    predChainCell->clazz = PREDICTED_CHAIN_CLAZZ_INIT;
1940                    break;
1941                default:
1942                    LOGE("Unexpected chaining type: %d", i);
1943                    dvmAbort();  // dvmAbort OK here - can't safely recover
1944            }
1945            COMPILER_TRACE_CHAINING(
1946                LOGD("Jit Runtime: unchaining %#x", (int)pChainCells));
1947            pChainCells += elemSize;  /* Advance by a fixed number of words */
1948        }
1949    }
1950    return pChainCells;
1951}
1952
1953/* Unchain all translation in the cache. */
1954void dvmJitUnchainAll()
1955{
1956    u4* lowAddress = NULL;
1957    u4* highAddress = NULL;
1958    unsigned int i;
1959    if (gDvmJit.pJitEntryTable != NULL) {
1960        COMPILER_TRACE_CHAINING(LOGD("Jit Runtime: unchaining all"));
1961        dvmLockMutex(&gDvmJit.tableLock);
1962
1963        UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1964
1965        for (i = 0; i < gDvmJit.jitTableSize; i++) {
1966            if (gDvmJit.pJitEntryTable[i].dPC &&
1967                !gDvmJit.pJitEntryTable[i].u.info.isMethodEntry &&
1968                gDvmJit.pJitEntryTable[i].codeAddress &&
1969                (gDvmJit.pJitEntryTable[i].codeAddress !=
1970                 dvmCompilerGetInterpretTemplate())) {
1971                u4* lastAddress;
1972                lastAddress = unchainSingle(&gDvmJit.pJitEntryTable[i]);
1973                if (lowAddress == NULL ||
1974                      (u4*)gDvmJit.pJitEntryTable[i].codeAddress <
1975                      lowAddress)
1976                    lowAddress = lastAddress;
1977                if (lastAddress > highAddress)
1978                    highAddress = lastAddress;
1979            }
1980        }
1981        dvmCompilerCacheFlush((long)lowAddress, (long)highAddress, 0);
1982        UPDATE_CODE_CACHE_PATCHES();
1983
1984        PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1985
1986        dvmUnlockMutex(&gDvmJit.tableLock);
1987        gDvmJit.translationChains = 0;
1988    }
1989    gDvmJit.hasNewChain = false;
1990}
1991
1992typedef struct jitProfileAddrToLine {
1993    u4 lineNum;
1994    u4 bytecodeOffset;
1995} jitProfileAddrToLine;
1996
1997
1998/* Callback function to track the bytecode offset/line number relationiship */
1999static int addrToLineCb (void *cnxt, u4 bytecodeOffset, u4 lineNum)
2000{
2001    jitProfileAddrToLine *addrToLine = (jitProfileAddrToLine *) cnxt;
2002
2003    /* Best match so far for this offset */
2004    if (addrToLine->bytecodeOffset >= bytecodeOffset) {
2005        addrToLine->lineNum = lineNum;
2006    }
2007    return 0;
2008}
2009
2010/* Dumps profile info for a single trace */
2011static int dumpTraceProfile(JitEntry *p, bool silent, bool reset,
2012                            unsigned long sum)
2013{
2014    int idx;
2015
2016    if (p->codeAddress == NULL) {
2017        if (!silent)
2018            LOGD("TRACEPROFILE NULL");
2019        return 0;
2020    }
2021    if (p->codeAddress == dvmCompilerGetInterpretTemplate()) {
2022        if (!silent)
2023            LOGD("TRACEPROFILE INTERPRET_ONLY");
2024        return 0;
2025    }
2026    JitTraceCounter_t count = getProfileCount(p);
2027    if (reset) {
2028        resetProfileCount(p);
2029    }
2030    if (silent) {
2031        return count;
2032    }
2033    JitTraceDescription *desc = getTraceDescriptionPointer(getTraceBase(p));
2034    const Method *method = desc->method;
2035    char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype);
2036    jitProfileAddrToLine addrToLine = {0, desc->trace[0].info.frag.startOffset};
2037
2038    /*
2039     * We may end up decoding the debug information for the same method
2040     * multiple times, but the tradeoff is we don't need to allocate extra
2041     * space to store the addr/line mapping. Since this is a debugging feature
2042     * and done infrequently so the slower but simpler mechanism should work
2043     * just fine.
2044     */
2045    dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile,
2046                       dvmGetMethodCode(method),
2047                       method->clazz->descriptor,
2048                       method->prototype.protoIdx,
2049                       method->accessFlags,
2050                       addrToLineCb, NULL, &addrToLine);
2051
2052    LOGD("TRACEPROFILE 0x%08x % 10d %5.2f%% [%#x(+%d), %d] %s%s;%s",
2053         (int) getTraceBase(p),
2054         count,
2055         ((float ) count) / sum * 100.0,
2056         desc->trace[0].info.frag.startOffset,
2057         desc->trace[0].info.frag.numInsts,
2058         addrToLine.lineNum,
2059         method->clazz->descriptor, method->name, methodDesc);
2060    free(methodDesc);
2061
2062    /* Find the last fragment (ie runEnd is set) */
2063    for (idx = 0;
2064         desc->trace[idx].isCode && !desc->trace[idx].info.frag.runEnd;
2065         idx++) {
2066    }
2067
2068    /*
2069     * runEnd must comes with a JitCodeDesc frag. If isCode is false it must
2070     * be a meta info field (only used by callsite info for now).
2071     */
2072    if (!desc->trace[idx].isCode) {
2073        const Method *method = (const Method *)
2074            desc->trace[idx+JIT_TRACE_CUR_METHOD-1].info.meta;
2075        char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype);
2076        /* Print the callee info in the trace */
2077        LOGD("    -> %s%s;%s", method->clazz->descriptor, method->name,
2078             methodDesc);
2079    }
2080
2081    return count;
2082}
2083
2084/* Create a copy of the trace descriptor of an existing compilation */
2085JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
2086                                            const JitEntry *knownEntry)
2087{
2088    const JitEntry *jitEntry = knownEntry ? knownEntry
2089                                          : dvmJitFindEntry(pc, false);
2090    if ((jitEntry == NULL) || (jitEntry->codeAddress == 0))
2091        return NULL;
2092
2093    JitTraceDescription *desc =
2094        getTraceDescriptionPointer(getTraceBase(jitEntry));
2095
2096    /* Now make a copy and return */
2097    int descSize = getTraceDescriptionSize(desc);
2098    JitTraceDescription *newCopy = (JitTraceDescription *) malloc(descSize);
2099    memcpy(newCopy, desc, descSize);
2100    return newCopy;
2101}
2102
2103/* qsort callback function */
2104static int sortTraceProfileCount(const void *entry1, const void *entry2)
2105{
2106    const JitEntry *jitEntry1 = (const JitEntry *)entry1;
2107    const JitEntry *jitEntry2 = (const JitEntry *)entry2;
2108
2109    JitTraceCounter_t count1 = getProfileCount(jitEntry1);
2110    JitTraceCounter_t count2 = getProfileCount(jitEntry2);
2111    return (count1 == count2) ? 0 : ((count1 > count2) ? -1 : 1);
2112}
2113
2114/* Sort the trace profile counts and dump them */
2115void dvmCompilerSortAndPrintTraceProfiles()
2116{
2117    JitEntry *sortedEntries;
2118    int numTraces = 0;
2119    unsigned long sum = 0;
2120    unsigned int i;
2121
2122    /* Make sure that the table is not changing */
2123    dvmLockMutex(&gDvmJit.tableLock);
2124
2125    /* Sort the entries by descending order */
2126    sortedEntries = (JitEntry *)malloc(sizeof(JitEntry) * gDvmJit.jitTableSize);
2127    if (sortedEntries == NULL)
2128        goto done;
2129    memcpy(sortedEntries, gDvmJit.pJitEntryTable,
2130           sizeof(JitEntry) * gDvmJit.jitTableSize);
2131    qsort(sortedEntries, gDvmJit.jitTableSize, sizeof(JitEntry),
2132          sortTraceProfileCount);
2133
2134    /* Analyze the sorted entries */
2135    for (i=0; i < gDvmJit.jitTableSize; i++) {
2136        if (sortedEntries[i].dPC != 0) {
2137            sum += dumpTraceProfile(&sortedEntries[i],
2138                                       true /* silent */,
2139                                       false /* reset */,
2140                                       0);
2141            numTraces++;
2142        }
2143    }
2144    if (numTraces == 0)
2145        numTraces = 1;
2146    if (sum == 0) {
2147        sum = 1;
2148    }
2149
2150    LOGD("JIT: Average execution count -> %d",(int)(sum / numTraces));
2151
2152    /* Dump the sorted entries. The count of each trace will be reset to 0. */
2153    for (i=0; i < gDvmJit.jitTableSize; i++) {
2154        if (sortedEntries[i].dPC != 0) {
2155            dumpTraceProfile(&sortedEntries[i],
2156                             false /* silent */,
2157                             true /* reset */,
2158                             sum);
2159        }
2160    }
2161
2162    for (i=0; i < gDvmJit.jitTableSize && i < 10; i++) {
2163        /* Stip interpreter stubs */
2164        if (sortedEntries[i].codeAddress == dvmCompilerGetInterpretTemplate()) {
2165            continue;
2166        }
2167        JitTraceDescription* desc =
2168            dvmCopyTraceDescriptor(NULL, &sortedEntries[i]);
2169        if (desc) {
2170            dvmCompilerWorkEnqueue(sortedEntries[i].dPC,
2171                                   kWorkOrderTraceDebug, desc);
2172        }
2173    }
2174
2175    free(sortedEntries);
2176done:
2177    dvmUnlockMutex(&gDvmJit.tableLock);
2178    return;
2179}
2180
2181static void findClassPointersSingleTrace(char *base, void (*callback)(void *))
2182{
2183    unsigned int chainTypeIdx, chainIdx;
2184    ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base);
2185    int cellSize = getChainCellSize(pChainCellCounts);
2186    /* Scan the chaining cells */
2187    if (cellSize) {
2188        /* Locate the beginning of the chain cell region */
2189        u4 *pChainCells = ((u4 *) pChainCellCounts) - cellSize -
2190            pChainCellCounts->u.count[kChainingCellGap];
2191        /* The cells are sorted in order - walk through them */
2192        for (chainTypeIdx = 0; chainTypeIdx < kChainingCellGap;
2193             chainTypeIdx++) {
2194            if (chainTypeIdx != kChainingCellInvokePredicted) {
2195                /* In 32-bit words */
2196                pChainCells += (CHAIN_CELL_NORMAL_SIZE >> 2) *
2197                    pChainCellCounts->u.count[chainTypeIdx];
2198                continue;
2199            }
2200            for (chainIdx = 0;
2201                 chainIdx < pChainCellCounts->u.count[chainTypeIdx];
2202                 chainIdx++) {
2203                PredictedChainingCell *cell =
2204                    (PredictedChainingCell *) pChainCells;
2205                /*
2206                 * Report the cell if it contains a sane class
2207                 * pointer.
2208                 */
2209                if (cell->clazz != NULL &&
2210                    cell->clazz !=
2211                      (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ) {
2212                    callback(&cell->clazz);
2213                }
2214                pChainCells += CHAIN_CELL_PREDICTED_SIZE >> 2;
2215            }
2216        }
2217    }
2218
2219    /* Scan the class pointer pool */
2220    JitTraceDescription *desc = getTraceDescriptionPointer(base);
2221    int descSize = getTraceDescriptionSize(desc);
2222    int *classPointerP = (int *) ((char *) desc + descSize);
2223    int numClassPointers = *classPointerP++;
2224    for (; numClassPointers; numClassPointers--, classPointerP++) {
2225        callback(classPointerP);
2226    }
2227}
2228
2229/*
2230 * Scan class pointers in each translation and pass its address to the callback
2231 * function. Currently such a pointers can be found in the pointer pool and the
2232 * clazz field in the predicted chaining cells.
2233 */
2234void dvmJitScanAllClassPointers(void (*callback)(void *))
2235{
2236    UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
2237
2238    /* Handle the inflight compilation first */
2239    if (gDvmJit.inflightBaseAddr)
2240        findClassPointersSingleTrace((char *) gDvmJit.inflightBaseAddr,
2241                                     callback);
2242
2243    if (gDvmJit.pJitEntryTable != NULL) {
2244        unsigned int traceIdx;
2245        dvmLockMutex(&gDvmJit.tableLock);
2246        for (traceIdx = 0; traceIdx < gDvmJit.jitTableSize; traceIdx++) {
2247            const JitEntry *entry = &gDvmJit.pJitEntryTable[traceIdx];
2248            if (entry->dPC &&
2249                !entry->u.info.isMethodEntry &&
2250                entry->codeAddress &&
2251                (entry->codeAddress != dvmCompilerGetInterpretTemplate())) {
2252                char *base = getTraceBase(entry);
2253                findClassPointersSingleTrace(base, callback);
2254            }
2255        }
2256        dvmUnlockMutex(&gDvmJit.tableLock);
2257    }
2258    UPDATE_CODE_CACHE_PATCHES();
2259
2260    PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
2261}
2262
2263/*
2264 * Provide the final touch on the class object pointer pool to install the
2265 * actual pointers. The thread has to be in the running state.
2266 */
2267void dvmJitInstallClassObjectPointers(CompilationUnit *cUnit, char *codeAddress)
2268{
2269    char *base = codeAddress - cUnit->headerSize -
2270                 (cUnit->instructionSet == DALVIK_JIT_ARM ? 0 : 1);
2271
2272    /* Scan the class pointer pool */
2273    JitTraceDescription *desc = getTraceDescriptionPointer(base);
2274    int descSize = getTraceDescriptionSize(desc);
2275    intptr_t *classPointerP = (int *) ((char *) desc + descSize);
2276    int numClassPointers = *(int *)classPointerP++;
2277    intptr_t *startClassPointerP = classPointerP;
2278
2279    /*
2280     * Change the thread state to VM_RUNNING so that GC won't be happening
2281     * when the assembler looks up the class pointers. May suspend the current
2282     * thread if there is a pending request before the state is actually
2283     * changed to RUNNING.
2284     */
2285    dvmChangeStatus(gDvmJit.compilerThread, THREAD_RUNNING);
2286
2287    /*
2288     * Unprotecting the code cache will need to acquire the code cache
2289     * protection lock first. Doing so after the state change may increase the
2290     * time spent in the RUNNING state (which may delay the next GC request
2291     * should there be contention on codeCacheProtectionLock). In practice
2292     * this is probably not going to happen often since a GC is just served.
2293     * More importantly, acquiring the lock before the state change will
2294     * cause deadlock (b/4192964).
2295     */
2296    UNPROTECT_CODE_CACHE(startClassPointerP,
2297                         numClassPointers * sizeof(intptr_t));
2298#if defined(WITH_JIT_TUNING)
2299    u8 startTime = dvmGetRelativeTimeUsec();
2300#endif
2301    for (;numClassPointers; numClassPointers--) {
2302        CallsiteInfo *callsiteInfo = (CallsiteInfo *) *classPointerP;
2303        ClassObject *clazz = dvmFindClassNoInit(
2304            callsiteInfo->classDescriptor, callsiteInfo->classLoader);
2305        assert(!strcmp(clazz->descriptor, callsiteInfo->classDescriptor));
2306        *classPointerP++ = (intptr_t) clazz;
2307    }
2308
2309    /*
2310     * Register the base address so that if GC kicks in after the thread state
2311     * has been changed to VMWAIT and before the compiled code is registered
2312     * in the JIT table, its content can be patched if class objects are
2313     * moved.
2314     */
2315    gDvmJit.inflightBaseAddr = base;
2316
2317#if defined(WITH_JIT_TUNING)
2318    u8 blockTime = dvmGetRelativeTimeUsec() - startTime;
2319    gDvmJit.compilerThreadBlockGCTime += blockTime;
2320    if (blockTime > gDvmJit.maxCompilerThreadBlockGCTime)
2321        gDvmJit.maxCompilerThreadBlockGCTime = blockTime;
2322    gDvmJit.numCompilerThreadBlockGC++;
2323#endif
2324    UPDATE_CODE_CACHE_PATCHES();
2325
2326    PROTECT_CODE_CACHE(startClassPointerP, numClassPointers * sizeof(intptr_t));
2327
2328    /* Change the thread state back to VMWAIT */
2329    dvmChangeStatus(gDvmJit.compilerThread, THREAD_VMWAIT);
2330}
2331
2332#if defined(WITH_SELF_VERIFICATION)
2333/*
2334 * The following are used to keep compiled loads and stores from modifying
2335 * memory during self verification mode.
2336 *
2337 * Stores do not modify memory. Instead, the address and value pair are stored
2338 * into heapSpace. Addresses within heapSpace are unique. For accesses smaller
2339 * than a word, the word containing the address is loaded first before being
2340 * updated.
2341 *
2342 * Loads check heapSpace first and return data from there if an entry exists.
2343 * Otherwise, data is loaded from memory as usual.
2344 */
2345
2346/* Used to specify sizes of memory operations */
2347enum {
2348    kSVByte,
2349    kSVSignedByte,
2350    kSVHalfword,
2351    kSVSignedHalfword,
2352    kSVWord,
2353    kSVDoubleword,
2354    kSVVariable,
2355};
2356
2357/* Load the value of a decoded register from the stack */
2358static int selfVerificationMemRegLoad(int* sp, int reg)
2359{
2360    return *(sp + reg);
2361}
2362
2363/* Load the value of a decoded doubleword register from the stack */
2364static s8 selfVerificationMemRegLoadDouble(int* sp, int reg)
2365{
2366    return *((s8*)(sp + reg));
2367}
2368
2369/* Store the value of a decoded register out to the stack */
2370static void selfVerificationMemRegStore(int* sp, int data, int reg)
2371{
2372    *(sp + reg) = data;
2373}
2374
2375/* Store the value of a decoded doubleword register out to the stack */
2376static void selfVerificationMemRegStoreDouble(int* sp, s8 data, int reg)
2377{
2378    *((s8*)(sp + reg)) = data;
2379}
2380
2381/*
2382 * Load the specified size of data from the specified address, checking
2383 * heapSpace first if Self Verification mode wrote to it previously, and
2384 * falling back to actual memory otherwise.
2385 */
2386static int selfVerificationLoad(int addr, int size)
2387{
2388    Thread *self = dvmThreadSelf();
2389    ShadowSpace *shadowSpace = self->shadowSpace;
2390    ShadowHeap *heapSpacePtr;
2391
2392    int data;
2393    int maskedAddr = addr & 0xFFFFFFFC;
2394    int alignment = addr & 0x3;
2395
2396    for (heapSpacePtr = shadowSpace->heapSpace;
2397         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
2398        if (heapSpacePtr->addr == maskedAddr) {
2399            addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
2400            break;
2401        }
2402    }
2403
2404    switch (size) {
2405        case kSVByte:
2406            data = *((u1*) addr);
2407            break;
2408        case kSVSignedByte:
2409            data = *((s1*) addr);
2410            break;
2411        case kSVHalfword:
2412            data = *((u2*) addr);
2413            break;
2414        case kSVSignedHalfword:
2415            data = *((s2*) addr);
2416            break;
2417        case kSVWord:
2418            data = *((u4*) addr);
2419            break;
2420        default:
2421            LOGE("*** ERROR: BAD SIZE IN selfVerificationLoad: %d", size);
2422            data = 0;
2423            dvmAbort();
2424    }
2425
2426    //LOGD("*** HEAP LOAD: Addr: %#x Data: %#x Size: %d", addr, data, size);
2427    return data;
2428}
2429
2430/* Like selfVerificationLoad, but specifically for doublewords */
2431static s8 selfVerificationLoadDoubleword(int addr)
2432{
2433    Thread *self = dvmThreadSelf();
2434    ShadowSpace* shadowSpace = self->shadowSpace;
2435    ShadowHeap* heapSpacePtr;
2436
2437    int addr2 = addr+4;
2438    unsigned int data = *((unsigned int*) addr);
2439    unsigned int data2 = *((unsigned int*) addr2);
2440
2441    for (heapSpacePtr = shadowSpace->heapSpace;
2442         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
2443        if (heapSpacePtr->addr == addr) {
2444            data = heapSpacePtr->data;
2445        } else if (heapSpacePtr->addr == addr2) {
2446            data2 = heapSpacePtr->data;
2447        }
2448    }
2449
2450    //LOGD("*** HEAP LOAD DOUBLEWORD: Addr: %#x Data: %#x Data2: %#x",
2451    //    addr, data, data2);
2452    return (((s8) data2) << 32) | data;
2453}
2454
2455/*
2456 * Handles a store of a specified size of data to a specified address.
2457 * This gets logged as an addr/data pair in heapSpace instead of modifying
2458 * memory.  Addresses in heapSpace are unique, and accesses smaller than a
2459 * word pull the entire word from memory first before updating.
2460 */
2461static void selfVerificationStore(int addr, int data, int size)
2462{
2463    Thread *self = dvmThreadSelf();
2464    ShadowSpace *shadowSpace = self->shadowSpace;
2465    ShadowHeap *heapSpacePtr;
2466
2467    int maskedAddr = addr & 0xFFFFFFFC;
2468    int alignment = addr & 0x3;
2469
2470    //LOGD("*** HEAP STORE: Addr: %#x Data: %#x Size: %d", addr, data, size);
2471
2472    for (heapSpacePtr = shadowSpace->heapSpace;
2473         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
2474        if (heapSpacePtr->addr == maskedAddr) break;
2475    }
2476
2477    if (heapSpacePtr == shadowSpace->heapSpaceTail) {
2478        heapSpacePtr->addr = maskedAddr;
2479        heapSpacePtr->data = *((unsigned int*) maskedAddr);
2480        shadowSpace->heapSpaceTail++;
2481    }
2482
2483    addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
2484    switch (size) {
2485        case kSVByte:
2486            *((u1*) addr) = data;
2487            break;
2488        case kSVSignedByte:
2489            *((s1*) addr) = data;
2490            break;
2491        case kSVHalfword:
2492            *((u2*) addr) = data;
2493            break;
2494        case kSVSignedHalfword:
2495            *((s2*) addr) = data;
2496            break;
2497        case kSVWord:
2498            *((u4*) addr) = data;
2499            break;
2500        default:
2501            LOGE("*** ERROR: BAD SIZE IN selfVerificationSave: %d", size);
2502            dvmAbort();
2503    }
2504}
2505
2506/* Like selfVerificationStore, but specifically for doublewords */
2507static void selfVerificationStoreDoubleword(int addr, s8 double_data)
2508{
2509    Thread *self = dvmThreadSelf();
2510    ShadowSpace *shadowSpace = self->shadowSpace;
2511    ShadowHeap *heapSpacePtr;
2512
2513    int addr2 = addr+4;
2514    int data = double_data;
2515    int data2 = double_data >> 32;
2516    bool store1 = false, store2 = false;
2517
2518    //LOGD("*** HEAP STORE DOUBLEWORD: Addr: %#x Data: %#x, Data2: %#x",
2519    //    addr, data, data2);
2520
2521    for (heapSpacePtr = shadowSpace->heapSpace;
2522         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
2523        if (heapSpacePtr->addr == addr) {
2524            heapSpacePtr->data = data;
2525            store1 = true;
2526        } else if (heapSpacePtr->addr == addr2) {
2527            heapSpacePtr->data = data2;
2528            store2 = true;
2529        }
2530    }
2531
2532    if (!store1) {
2533        shadowSpace->heapSpaceTail->addr = addr;
2534        shadowSpace->heapSpaceTail->data = data;
2535        shadowSpace->heapSpaceTail++;
2536    }
2537    if (!store2) {
2538        shadowSpace->heapSpaceTail->addr = addr2;
2539        shadowSpace->heapSpaceTail->data = data2;
2540        shadowSpace->heapSpaceTail++;
2541    }
2542}
2543
2544/*
2545 * Decodes the memory instruction at the address specified in the link
2546 * register. All registers (r0-r12,lr) and fp registers (d0-d15) are stored
2547 * consecutively on the stack beginning at the specified stack pointer.
2548 * Calls the proper Self Verification handler for the memory instruction and
2549 * updates the link register to point past the decoded memory instruction.
2550 */
2551void dvmSelfVerificationMemOpDecode(int lr, int* sp)
2552{
2553    enum {
2554        kMemOpLdrPcRel = 0x09, // ldr(3)  [01001] rd[10..8] imm_8[7..0]
2555        kMemOpRRR      = 0x0A, // Full opcode is 7 bits
2556        kMemOp2Single  = 0x0A, // Used for Vstrs and Vldrs
2557        kMemOpRRR2     = 0x0B, // Full opcode is 7 bits
2558        kMemOp2Double  = 0x0B, // Used for Vstrd and Vldrd
2559        kMemOpStrRRI5  = 0x0C, // str(1)  [01100] imm_5[10..6] rn[5..3] rd[2..0]
2560        kMemOpLdrRRI5  = 0x0D, // ldr(1)  [01101] imm_5[10..6] rn[5..3] rd[2..0]
2561        kMemOpStrbRRI5 = 0x0E, // strb(1) [01110] imm_5[10..6] rn[5..3] rd[2..0]
2562        kMemOpLdrbRRI5 = 0x0F, // ldrb(1) [01111] imm_5[10..6] rn[5..3] rd[2..0]
2563        kMemOpStrhRRI5 = 0x10, // strh(1) [10000] imm_5[10..6] rn[5..3] rd[2..0]
2564        kMemOpLdrhRRI5 = 0x11, // ldrh(1) [10001] imm_5[10..6] rn[5..3] rd[2..0]
2565        kMemOpLdrSpRel = 0x13, // ldr(4)  [10011] rd[10..8] imm_8[7..0]
2566        kMemOpStmia    = 0x18, // stmia   [11000] rn[10..8] reglist [7..0]
2567        kMemOpLdmia    = 0x19, // ldmia   [11001] rn[10..8] reglist [7..0]
2568        kMemOpStrRRR   = 0x28, // str(2)  [0101000] rm[8..6] rn[5..3] rd[2..0]
2569        kMemOpStrhRRR  = 0x29, // strh(2) [0101001] rm[8..6] rn[5..3] rd[2..0]
2570        kMemOpStrbRRR  = 0x2A, // strb(2) [0101010] rm[8..6] rn[5..3] rd[2..0]
2571        kMemOpLdrsbRRR = 0x2B, // ldrsb   [0101011] rm[8..6] rn[5..3] rd[2..0]
2572        kMemOpLdrRRR   = 0x2C, // ldr(2)  [0101100] rm[8..6] rn[5..3] rd[2..0]
2573        kMemOpLdrhRRR  = 0x2D, // ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0]
2574        kMemOpLdrbRRR  = 0x2E, // ldrb(2) [0101110] rm[8..6] rn[5..3] rd[2..0]
2575        kMemOpLdrshRRR = 0x2F, // ldrsh   [0101111] rm[8..6] rn[5..3] rd[2..0]
2576        kMemOp2Stmia   = 0xE88, // stmia  [111010001000[ rn[19..16] mask[15..0]
2577        kMemOp2Ldmia   = 0xE89, // ldmia  [111010001001[ rn[19..16] mask[15..0]
2578        kMemOp2Stmia2  = 0xE8A, // stmia  [111010001010[ rn[19..16] mask[15..0]
2579        kMemOp2Ldmia2  = 0xE8B, // ldmia  [111010001011[ rn[19..16] mask[15..0]
2580        kMemOp2Vstr    = 0xED8, // Used for Vstrs and Vstrd
2581        kMemOp2Vldr    = 0xED9, // Used for Vldrs and Vldrd
2582        kMemOp2Vstr2   = 0xEDC, // Used for Vstrs and Vstrd
2583        kMemOp2Vldr2   = 0xEDD, // Used for Vstrs and Vstrd
2584        kMemOp2StrbRRR = 0xF80, /* str rt,[rn,rm,LSL #imm] [111110000000]
2585                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
2586        kMemOp2LdrbRRR = 0xF81, /* ldrb rt,[rn,rm,LSL #imm] [111110000001]
2587                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
2588        kMemOp2StrhRRR = 0xF82, /* str rt,[rn,rm,LSL #imm] [111110000010]
2589                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
2590        kMemOp2LdrhRRR = 0xF83, /* ldrh rt,[rn,rm,LSL #imm] [111110000011]
2591                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
2592        kMemOp2StrRRR  = 0xF84, /* str rt,[rn,rm,LSL #imm] [111110000100]
2593                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
2594        kMemOp2LdrRRR  = 0xF85, /* ldr rt,[rn,rm,LSL #imm] [111110000101]
2595                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
2596        kMemOp2StrbRRI12 = 0xF88, /* strb rt,[rn,#imm12] [111110001000]
2597                                       rt[15..12] rn[19..16] imm12[11..0] */
2598        kMemOp2LdrbRRI12 = 0xF89, /* ldrb rt,[rn,#imm12] [111110001001]
2599                                       rt[15..12] rn[19..16] imm12[11..0] */
2600        kMemOp2StrhRRI12 = 0xF8A, /* strh rt,[rn,#imm12] [111110001010]
2601                                       rt[15..12] rn[19..16] imm12[11..0] */
2602        kMemOp2LdrhRRI12 = 0xF8B, /* ldrh rt,[rn,#imm12] [111110001011]
2603                                       rt[15..12] rn[19..16] imm12[11..0] */
2604        kMemOp2StrRRI12 = 0xF8C, /* str(Imm,T3) rd,[rn,#imm12] [111110001100]
2605                                       rn[19..16] rt[15..12] imm12[11..0] */
2606        kMemOp2LdrRRI12 = 0xF8D, /* ldr(Imm,T3) rd,[rn,#imm12] [111110001101]
2607                                       rn[19..16] rt[15..12] imm12[11..0] */
2608        kMemOp2LdrsbRRR = 0xF91, /* ldrsb rt,[rn,rm,LSL #imm] [111110010001]
2609                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
2610        kMemOp2LdrshRRR = 0xF93, /* ldrsh rt,[rn,rm,LSL #imm] [111110010011]
2611                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
2612        kMemOp2LdrsbRRI12 = 0xF99, /* ldrsb rt,[rn,#imm12] [111110011001]
2613                                       rt[15..12] rn[19..16] imm12[11..0] */
2614        kMemOp2LdrshRRI12 = 0xF9B, /* ldrsh rt,[rn,#imm12] [111110011011]
2615                                       rt[15..12] rn[19..16] imm12[11..0] */
2616        kMemOp2        = 0xE000, // top 3 bits set indicates Thumb2
2617    };
2618
2619    int addr, offset, data;
2620    long long double_data;
2621    int size = kSVWord;
2622    bool store = false;
2623    unsigned int *lr_masked = (unsigned int *) (lr & 0xFFFFFFFE);
2624    unsigned int insn = *lr_masked;
2625
2626    int old_lr;
2627    old_lr = selfVerificationMemRegLoad(sp, 13);
2628
2629    if ((insn & kMemOp2) == kMemOp2) {
2630        insn = (insn << 16) | (insn >> 16);
2631        //LOGD("*** THUMB2 - Addr: %#x Insn: %#x", lr, insn);
2632
2633        int opcode12 = (insn >> 20) & 0xFFF;
2634        int opcode4 = (insn >> 8) & 0xF;
2635        int imm2 = (insn >> 4) & 0x3;
2636        int imm8 = insn & 0xFF;
2637        int imm12 = insn & 0xFFF;
2638        int rd = (insn >> 12) & 0xF;
2639        int rm = insn & 0xF;
2640        int rn = (insn >> 16) & 0xF;
2641        int rt = (insn >> 12) & 0xF;
2642        bool wBack = true;
2643
2644        // Update the link register
2645        selfVerificationMemRegStore(sp, old_lr+4, 13);
2646
2647        // Determine whether the mem op is a store or load
2648        switch (opcode12) {
2649            case kMemOp2Stmia:
2650            case kMemOp2Stmia2:
2651            case kMemOp2Vstr:
2652            case kMemOp2Vstr2:
2653            case kMemOp2StrbRRR:
2654            case kMemOp2StrhRRR:
2655            case kMemOp2StrRRR:
2656            case kMemOp2StrbRRI12:
2657            case kMemOp2StrhRRI12:
2658            case kMemOp2StrRRI12:
2659                store = true;
2660        }
2661
2662        // Determine the size of the mem access
2663        switch (opcode12) {
2664            case kMemOp2StrbRRR:
2665            case kMemOp2LdrbRRR:
2666            case kMemOp2StrbRRI12:
2667            case kMemOp2LdrbRRI12:
2668                size = kSVByte;
2669                break;
2670            case kMemOp2LdrsbRRR:
2671            case kMemOp2LdrsbRRI12:
2672                size = kSVSignedByte;
2673                break;
2674            case kMemOp2StrhRRR:
2675            case kMemOp2LdrhRRR:
2676            case kMemOp2StrhRRI12:
2677            case kMemOp2LdrhRRI12:
2678                size = kSVHalfword;
2679                break;
2680            case kMemOp2LdrshRRR:
2681            case kMemOp2LdrshRRI12:
2682                size = kSVSignedHalfword;
2683                break;
2684            case kMemOp2Vstr:
2685            case kMemOp2Vstr2:
2686            case kMemOp2Vldr:
2687            case kMemOp2Vldr2:
2688                if (opcode4 == kMemOp2Double) size = kSVDoubleword;
2689                break;
2690            case kMemOp2Stmia:
2691            case kMemOp2Ldmia:
2692            case kMemOp2Stmia2:
2693            case kMemOp2Ldmia2:
2694                size = kSVVariable;
2695                break;
2696        }
2697
2698        // Load the value of the address
2699        addr = selfVerificationMemRegLoad(sp, rn);
2700
2701        // Figure out the offset
2702        switch (opcode12) {
2703            case kMemOp2Vstr:
2704            case kMemOp2Vstr2:
2705            case kMemOp2Vldr:
2706            case kMemOp2Vldr2:
2707                offset = imm8 << 2;
2708                if (opcode4 == kMemOp2Single) {
2709                    rt = rd << 1;
2710                    if (insn & 0x400000) rt |= 0x1;
2711                } else if (opcode4 == kMemOp2Double) {
2712                    if (insn & 0x400000) rt |= 0x10;
2713                    rt = rt << 1;
2714                } else {
2715                    LOGE("*** ERROR: UNRECOGNIZED VECTOR MEM OP: %x", opcode4);
2716                    dvmAbort();
2717                }
2718                rt += 14;
2719                break;
2720            case kMemOp2StrbRRR:
2721            case kMemOp2LdrbRRR:
2722            case kMemOp2StrhRRR:
2723            case kMemOp2LdrhRRR:
2724            case kMemOp2StrRRR:
2725            case kMemOp2LdrRRR:
2726            case kMemOp2LdrsbRRR:
2727            case kMemOp2LdrshRRR:
2728                offset = selfVerificationMemRegLoad(sp, rm) << imm2;
2729                break;
2730            case kMemOp2StrbRRI12:
2731            case kMemOp2LdrbRRI12:
2732            case kMemOp2StrhRRI12:
2733            case kMemOp2LdrhRRI12:
2734            case kMemOp2StrRRI12:
2735            case kMemOp2LdrRRI12:
2736            case kMemOp2LdrsbRRI12:
2737            case kMemOp2LdrshRRI12:
2738                offset = imm12;
2739                break;
2740            case kMemOp2Stmia:
2741            case kMemOp2Ldmia:
2742                wBack = false;
2743            case kMemOp2Stmia2:
2744            case kMemOp2Ldmia2:
2745                offset = 0;
2746                break;
2747            default:
2748                LOGE("*** ERROR: UNRECOGNIZED THUMB2 MEM OP: %x", opcode12);
2749                offset = 0;
2750                dvmAbort();
2751        }
2752
2753        // Handle the decoded mem op accordingly
2754        if (store) {
2755            if (size == kSVVariable) {
2756                LOGD("*** THUMB2 STMIA CURRENTLY UNUSED (AND UNTESTED)");
2757                int i;
2758                int regList = insn & 0xFFFF;
2759                for (i = 0; i < 16; i++) {
2760                    if (regList & 0x1) {
2761                        data = selfVerificationMemRegLoad(sp, i);
2762                        selfVerificationStore(addr, data, kSVWord);
2763                        addr += 4;
2764                    }
2765                    regList = regList >> 1;
2766                }
2767                if (wBack) selfVerificationMemRegStore(sp, addr, rn);
2768            } else if (size == kSVDoubleword) {
2769                double_data = selfVerificationMemRegLoadDouble(sp, rt);
2770                selfVerificationStoreDoubleword(addr+offset, double_data);
2771            } else {
2772                data = selfVerificationMemRegLoad(sp, rt);
2773                selfVerificationStore(addr+offset, data, size);
2774            }
2775        } else {
2776            if (size == kSVVariable) {
2777                LOGD("*** THUMB2 LDMIA CURRENTLY UNUSED (AND UNTESTED)");
2778                int i;
2779                int regList = insn & 0xFFFF;
2780                for (i = 0; i < 16; i++) {
2781                    if (regList & 0x1) {
2782                        data = selfVerificationLoad(addr, kSVWord);
2783                        selfVerificationMemRegStore(sp, data, i);
2784                        addr += 4;
2785                    }
2786                    regList = regList >> 1;
2787                }
2788                if (wBack) selfVerificationMemRegStore(sp, addr, rn);
2789            } else if (size == kSVDoubleword) {
2790                double_data = selfVerificationLoadDoubleword(addr+offset);
2791                selfVerificationMemRegStoreDouble(sp, double_data, rt);
2792            } else {
2793                data = selfVerificationLoad(addr+offset, size);
2794                selfVerificationMemRegStore(sp, data, rt);
2795            }
2796        }
2797    } else {
2798        //LOGD("*** THUMB - Addr: %#x Insn: %#x", lr, insn);
2799
2800        // Update the link register
2801        selfVerificationMemRegStore(sp, old_lr+2, 13);
2802
2803        int opcode5 = (insn >> 11) & 0x1F;
2804        int opcode7 = (insn >> 9) & 0x7F;
2805        int imm = (insn >> 6) & 0x1F;
2806        int rd = (insn >> 8) & 0x7;
2807        int rm = (insn >> 6) & 0x7;
2808        int rn = (insn >> 3) & 0x7;
2809        int rt = insn & 0x7;
2810
2811        // Determine whether the mem op is a store or load
2812        switch (opcode5) {
2813            case kMemOpRRR:
2814                switch (opcode7) {
2815                    case kMemOpStrRRR:
2816                    case kMemOpStrhRRR:
2817                    case kMemOpStrbRRR:
2818                        store = true;
2819                }
2820                break;
2821            case kMemOpStrRRI5:
2822            case kMemOpStrbRRI5:
2823            case kMemOpStrhRRI5:
2824            case kMemOpStmia:
2825                store = true;
2826        }
2827
2828        // Determine the size of the mem access
2829        switch (opcode5) {
2830            case kMemOpRRR:
2831            case kMemOpRRR2:
2832                switch (opcode7) {
2833                    case kMemOpStrbRRR:
2834                    case kMemOpLdrbRRR:
2835                        size = kSVByte;
2836                        break;
2837                    case kMemOpLdrsbRRR:
2838                        size = kSVSignedByte;
2839                        break;
2840                    case kMemOpStrhRRR:
2841                    case kMemOpLdrhRRR:
2842                        size = kSVHalfword;
2843                        break;
2844                    case kMemOpLdrshRRR:
2845                        size = kSVSignedHalfword;
2846                        break;
2847                }
2848                break;
2849            case kMemOpStrbRRI5:
2850            case kMemOpLdrbRRI5:
2851                size = kSVByte;
2852                break;
2853            case kMemOpStrhRRI5:
2854            case kMemOpLdrhRRI5:
2855                size = kSVHalfword;
2856                break;
2857            case kMemOpStmia:
2858            case kMemOpLdmia:
2859                size = kSVVariable;
2860                break;
2861        }
2862
2863        // Load the value of the address
2864        if (opcode5 == kMemOpLdrPcRel)
2865            addr = selfVerificationMemRegLoad(sp, 4);
2866        else if (opcode5 == kMemOpStmia || opcode5 == kMemOpLdmia)
2867            addr = selfVerificationMemRegLoad(sp, rd);
2868        else
2869            addr = selfVerificationMemRegLoad(sp, rn);
2870
2871        // Figure out the offset
2872        switch (opcode5) {
2873            case kMemOpLdrPcRel:
2874                offset = (insn & 0xFF) << 2;
2875                rt = rd;
2876                break;
2877            case kMemOpRRR:
2878            case kMemOpRRR2:
2879                offset = selfVerificationMemRegLoad(sp, rm);
2880                break;
2881            case kMemOpStrRRI5:
2882            case kMemOpLdrRRI5:
2883                offset = imm << 2;
2884                break;
2885            case kMemOpStrhRRI5:
2886            case kMemOpLdrhRRI5:
2887                offset = imm << 1;
2888                break;
2889            case kMemOpStrbRRI5:
2890            case kMemOpLdrbRRI5:
2891                offset = imm;
2892                break;
2893            case kMemOpStmia:
2894            case kMemOpLdmia:
2895                offset = 0;
2896                break;
2897            default:
2898                LOGE("*** ERROR: UNRECOGNIZED THUMB MEM OP: %x", opcode5);
2899                offset = 0;
2900                dvmAbort();
2901        }
2902
2903        // Handle the decoded mem op accordingly
2904        if (store) {
2905            if (size == kSVVariable) {
2906                int i;
2907                int regList = insn & 0xFF;
2908                for (i = 0; i < 8; i++) {
2909                    if (regList & 0x1) {
2910                        data = selfVerificationMemRegLoad(sp, i);
2911                        selfVerificationStore(addr, data, kSVWord);
2912                        addr += 4;
2913                    }
2914                    regList = regList >> 1;
2915                }
2916                selfVerificationMemRegStore(sp, addr, rd);
2917            } else {
2918                data = selfVerificationMemRegLoad(sp, rt);
2919                selfVerificationStore(addr+offset, data, size);
2920            }
2921        } else {
2922            if (size == kSVVariable) {
2923                bool wBack = true;
2924                int i;
2925                int regList = insn & 0xFF;
2926                for (i = 0; i < 8; i++) {
2927                    if (regList & 0x1) {
2928                        if (i == rd) wBack = false;
2929                        data = selfVerificationLoad(addr, kSVWord);
2930                        selfVerificationMemRegStore(sp, data, i);
2931                        addr += 4;
2932                    }
2933                    regList = regList >> 1;
2934                }
2935                if (wBack) selfVerificationMemRegStore(sp, addr, rd);
2936            } else {
2937                data = selfVerificationLoad(addr+offset, size);
2938                selfVerificationMemRegStore(sp, data, rt);
2939            }
2940        }
2941    }
2942}
2943#endif
2944