Assemble.cpp revision 0c2dc522d0e120f346cf0a40c8cf0c93346131c2
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 "MipsLIR.h"
22#include "Codegen.h"
23#include <unistd.h>             /* for cacheflush */
24#include <sys/mman.h>           /* for protection change */
25
26#define MAX_ASSEMBLER_RETRIES 10
27
28/*
29 * opcode: MipsOpCode enum
30 * skeleton: pre-designated bit-pattern for this opcode
31 * k0: key to applying ds/de
32 * ds: dest start bit position
33 * de: dest end bit position
34 * k1: key to applying s1s/s1e
35 * s1s: src1 start bit position
36 * s1e: src1 end bit position
37 * k2: key to applying s2s/s2e
38 * s2s: src2 start bit position
39 * s2e: src2 end bit position
40 * operands: number of operands (for sanity check purposes)
41 * name: mnemonic name
42 * fmt: for pretty-printing
43 */
44#define ENCODING_MAP(opcode, skeleton, k0, ds, de, k1, s1s, s1e, k2, s2s, s2e, \
45                     k3, k3s, k3e, flags, name, fmt, size) \
46        {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \
47                    {k3, k3s, k3e}}, opcode, flags, name, fmt, size}
48
49/* Instruction dump string format keys: !pf, where "!" is the start
50 * of the key, "p" is which numeric operand to use and "f" is the
51 * print format.
52 *
53 * [p]ositions:
54 *     0 -> operands[0] (dest)
55 *     1 -> operands[1] (src1)
56 *     2 -> operands[2] (src2)
57 *     3 -> operands[3] (extra)
58 *
59 * [f]ormats:
60 *     h -> 4-digit hex
61 *     d -> decimal
62 *     E -> decimal*4
63 *     F -> decimal*2
64 *     c -> branch condition (beq, bne, etc.)
65 *     t -> pc-relative target
66 *     T -> pc-region target
67 *     u -> 1st half of bl[x] target
68 *     v -> 2nd half ob bl[x] target
69 *     R -> register list
70 *     s -> single precision floating point register
71 *     S -> double precision floating point register
72 *     m -> Thumb2 modified immediate
73 *     n -> complimented Thumb2 modified immediate
74 *     M -> Thumb2 16-bit zero-extended immediate
75 *     b -> 4-digit binary
76 *
77 *  [!] escape.  To insert "!", use "!!"
78 */
79/* NOTE: must be kept in sync with enum MipsOpcode from MipsLIR.h */
80MipsEncodingMap EncodingMap[kMipsLast] = {
81    ENCODING_MAP(kMips32BitData, 0x00000000,
82                 kFmtBitBlt, 31, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
83                 kFmtUnused, -1, -1, IS_UNARY_OP,
84                 "data", "0x!0h(!0d)", 2),
85    ENCODING_MAP(kMipsAddiu, 0x24000000,
86                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
87                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
88                 "addiu", "!0r,!1r,0x!2h(!2d)", 2),
89    ENCODING_MAP(kMipsAddu, 0x00000021,
90                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
91                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
92                 "addu", "!0r,!1r,!2r", 2),
93    ENCODING_MAP(kMipsAnd, 0x00000024,
94                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
95                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
96                 "and", "!0r,!1r,!2r", 2),
97    ENCODING_MAP(kMipsAndi, 0x30000000,
98                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
99                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
100                 "andi", "!0r,!1r,0x!2h(!2d)", 2),
101    ENCODING_MAP(kMipsB, 0x10000000,
102                 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
103                 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH,
104                 "b", "!0t", 2),
105    ENCODING_MAP(kMipsBal, 0x04110000,
106                 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
107                 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR,
108                 "bal", "!0t", 2),
109    ENCODING_MAP(kMipsBeq, 0x10000000,
110                 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
111                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01,
112                 "beq", "!0r,!1r,!2t", 2),
113    ENCODING_MAP(kMipsBeqz, 0x10000000, /* same as beq above with t = $zero */
114                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
115                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
116                 "beqz", "!0r,!1t", 2),
117    ENCODING_MAP(kMipsBgez, 0x04010000,
118                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
119                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
120                 "bgez", "!0r,!1t", 2),
121    ENCODING_MAP(kMipsBgtz, 0x1C000000,
122                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
123                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
124                 "bgtz", "!0r,!1t", 2),
125    ENCODING_MAP(kMipsBlez, 0x18000000,
126                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
127                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
128                 "blez", "!0r,!1t", 2),
129    ENCODING_MAP(kMipsBltz, 0x04000000,
130                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
131                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
132                 "bltz", "!0r,!1t", 2),
133    ENCODING_MAP(kMipsBnez, 0x14000000, /* same as bne below with t = $zero */
134                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
135                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
136                 "bnez", "!0r,!1t", 2),
137    ENCODING_MAP(kMipsBne, 0x14000000,
138                 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
139                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01,
140                 "bne", "!0r,!1r,!2t", 2),
141    ENCODING_MAP(kMipsDiv, 0x0000001a,
142                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtBitBlt, 25, 21,
143                 kFmtBitBlt, 20, 16, IS_QUAD_OP | REG_DEF01 | REG_USE23,
144                 "div", "!2r,!3r", 2),
145#if __mips_isa_rev>=2
146    ENCODING_MAP(kMipsExt, 0x7c000000,
147                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 10, 6,
148                 kFmtBitBlt, 15, 11, IS_QUAD_OP | REG_DEF0 | REG_USE1,
149                 "ext", "!0r,!1r,!2d,!3D", 2),
150#endif
151    ENCODING_MAP(kMipsJal, 0x0c000000,
152                 kFmtBitBlt, 25, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
153                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR,
154                 "jal", "!0T(!0E)", 2),
155    ENCODING_MAP(kMipsJalr, 0x00000009,
156                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1,
157                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_DEF0_USE1,
158                 "jalr", "!0r,!1r", 2),
159    ENCODING_MAP(kMipsJr, 0x00000008,
160                 kFmtBitBlt, 25, 21, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
161                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
162                 "jr", "!0r", 2),
163    ENCODING_MAP(kMipsLahi, 0x3C000000,
164                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
165                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
166                 "lahi/lui", "!0r,0x!1h(!1d)", 2),
167    ENCODING_MAP(kMipsLalo, 0x34000000,
168                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
169                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
170                 "lalo/ori", "!0r,!1r,0x!2h(!2d)", 2),
171    ENCODING_MAP(kMipsLui, 0x3C000000,
172                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
173                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
174                 "lui", "!0r,0x!1h(!1d)", 2),
175    ENCODING_MAP(kMipsLb, 0x80000000,
176                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
177                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
178                 "lb", "!0r,!1d(!2r)", 2),
179    ENCODING_MAP(kMipsLbu, 0x90000000,
180                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
181                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
182                 "lbu", "!0r,!1d(!2r)", 2),
183    ENCODING_MAP(kMipsLh, 0x84000000,
184                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
185                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
186                 "lh", "!0r,!1d(!2r)", 2),
187    ENCODING_MAP(kMipsLhu, 0x94000000,
188                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
189                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
190                 "lhu", "!0r,!1d(!2r)", 2),
191    ENCODING_MAP(kMipsLw, 0x8C000000,
192                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
193                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
194                 "lw", "!0r,!1d(!2r)", 2),
195    ENCODING_MAP(kMipsMfhi, 0x00000010,
196                 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
197                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
198                 "mfhi", "!0r", 2),
199    ENCODING_MAP(kMipsMflo, 0x00000012,
200                 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
201                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
202                 "mflo", "!0r", 2),
203    ENCODING_MAP(kMipsMove, 0x00000025, /* or using zero reg */
204                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1,
205                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
206                 "move", "!0r,!1r", 2),
207    ENCODING_MAP(kMipsMovz, 0x0000000a,
208                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
209                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
210                 "movz", "!0r,!1r,!2r", 2),
211    ENCODING_MAP(kMipsMul, 0x70000002,
212                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
213                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
214                 "mul", "!0r,!1r,!2r", 2),
215    ENCODING_MAP(kMipsNop, 0x00000000,
216                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
217                 kFmtUnused, -1, -1, NO_OPERAND,
218                 "nop", "", 2),
219    ENCODING_MAP(kMipsNor, 0x00000027, /* used for "not" too */
220                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
221                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
222                 "nor", "!0r,!1r,!2r", 2),
223    ENCODING_MAP(kMipsOr, 0x00000025,
224                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
225                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
226                 "or", "!0r,!1r,!2r", 2),
227    ENCODING_MAP(kMipsOri, 0x34000000,
228                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
229                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
230                 "ori", "!0r,!1r,0x!2h(!2d)", 2),
231    ENCODING_MAP(kMipsPref, 0xCC000000,
232                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
233                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE2,
234                 "pref", "!0d,!1d(!2r)", 2),
235    ENCODING_MAP(kMipsSb, 0xA0000000,
236                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
237                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
238                 "sb", "!0r,!1d(!2r)", 2),
239#if __mips_isa_rev>=2
240    ENCODING_MAP(kMipsSeb, 0x7c000420,
241                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1,
242                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
243                 "seb", "!0r,!1r", 2),
244    ENCODING_MAP(kMipsSeh, 0x7c000620,
245                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1,
246                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
247                 "seh", "!0r,!1r", 2),
248#endif
249    ENCODING_MAP(kMipsSh, 0xA4000000,
250                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
251                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
252                 "sh", "!0r,!1d(!2r)", 2),
253    ENCODING_MAP(kMipsSll, 0x00000000,
254                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
255                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
256                 "sll", "!0r,!1r,0x!2h(!2d)", 2),
257    ENCODING_MAP(kMipsSllv, 0x00000004,
258                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
259                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
260                 "sllv", "!0r,!1r,!2r", 2),
261    ENCODING_MAP(kMipsSlt, 0x0000002a,
262                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
263                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
264                 "slt", "!0r,!1r,!2r", 2),
265    ENCODING_MAP(kMipsSlti, 0x28000000,
266                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
267                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
268                 "slti", "!0r,!1r,0x!2h(!2d)", 2),
269    ENCODING_MAP(kMipsSltu, 0x0000002b,
270                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
271                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
272                 "sltu", "!0r,!1r,!2r", 2),
273    ENCODING_MAP(kMipsSra, 0x00000003,
274                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
275                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
276                 "sra", "!0r,!1r,0x!2h(!2d)", 2),
277    ENCODING_MAP(kMipsSrav, 0x00000007,
278                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
279                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
280                 "srav", "!0r,!1r,!2r", 2),
281    ENCODING_MAP(kMipsSrl, 0x00000002,
282                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
283                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
284                 "srl", "!0r,!1r,0x!2h(!2d)", 2),
285    ENCODING_MAP(kMipsSrlv, 0x00000006,
286                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
287                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
288                 "srlv", "!0r,!1r,!2r", 2),
289    ENCODING_MAP(kMipsSubu, 0x00000023, /* used for "neg" too */
290                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
291                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
292                 "subu", "!0r,!1r,!2r", 2),
293    ENCODING_MAP(kMipsSw, 0xAC000000,
294                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
295                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
296                 "sw", "!0r,!1d(!2r)", 2),
297    ENCODING_MAP(kMipsXor, 0x00000026,
298                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
299                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
300                 "xor", "!0r,!1r,!2r", 2),
301    ENCODING_MAP(kMipsXori, 0x38000000,
302                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
303                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
304                 "xori", "!0r,!1r,0x!2h(!2d)", 2),
305#ifdef __mips_hard_float
306    ENCODING_MAP(kMipsFadds, 0x46000000,
307                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
308                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
309                 "add.s", "!0s,!1s,!2s", 2),
310    ENCODING_MAP(kMipsFsubs, 0x46000001,
311                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
312                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
313                 "sub.s", "!0s,!1s,!2s", 2),
314    ENCODING_MAP(kMipsFmuls, 0x46000002,
315                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
316                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
317                 "mul.s", "!0s,!1s,!2s", 2),
318    ENCODING_MAP(kMipsFdivs, 0x46000003,
319                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
320                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
321                 "div.s", "!0s,!1s,!2s", 2),
322    ENCODING_MAP(kMipsFaddd, 0x46200000,
323                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
324                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
325                 "add.d", "!0S,!1S,!2S", 2),
326    ENCODING_MAP(kMipsFsubd, 0x46200001,
327                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
328                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
329                 "sub.d", "!0S,!1S,!2S", 2),
330    ENCODING_MAP(kMipsFmuld, 0x46200002,
331                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
332                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
333                 "mul.d", "!0S,!1S,!2S", 2),
334    ENCODING_MAP(kMipsFdivd, 0x46200003,
335                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
336                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
337                 "div.d", "!0S,!1S,!2S", 2),
338    ENCODING_MAP(kMipsFcvtsd, 0x46200020,
339                 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
340                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
341                 "cvt.s.d", "!0s,!1S", 2),
342    ENCODING_MAP(kMipsFcvtsw, 0x46800020,
343                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
344                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
345                 "cvt.s.w", "!0s,!1s", 2),
346    ENCODING_MAP(kMipsFcvtds, 0x46000021,
347                 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
348                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
349                 "cvt.d.s", "!0S,!1s", 2),
350    ENCODING_MAP(kMipsFcvtdw, 0x46800021,
351                 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
352                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
353                 "cvt.d.w", "!0S,!1s", 2),
354    ENCODING_MAP(kMipsFcvtws, 0x46000024,
355                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
356                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
357                 "cvt.w.s", "!0s,!1s", 2),
358    ENCODING_MAP(kMipsFcvtwd, 0x46200024,
359                 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
360                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
361                 "cvt.w.d", "!0s,!1S", 2),
362    ENCODING_MAP(kMipsFmovs, 0x46000006,
363                 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
364                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
365                 "mov.s", "!0s,!1s", 2),
366    ENCODING_MAP(kMipsFmovd, 0x46200006,
367                 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
368                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
369                 "mov.d", "!0S,!1S", 2),
370    ENCODING_MAP(kMipsFlwc1, 0xC4000000,
371                 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
372                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
373                 "lwc1", "!0s,!1d(!2r)", 2),
374    ENCODING_MAP(kMipsFldc1, 0xD4000000,
375                 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
376                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
377                 "ldc1", "!0S,!1d(!2r)", 2),
378    ENCODING_MAP(kMipsFswc1, 0xE4000000,
379                 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
380                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
381                 "swc1", "!0s,!1d(!2r)", 2),
382    ENCODING_MAP(kMipsFsdc1, 0xF4000000,
383                 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
384                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
385                 "sdc1", "!0S,!1d(!2r)", 2),
386    ENCODING_MAP(kMipsMfc1, 0x44000000,
387                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
388                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
389                 "mfc1", "!0r,!1s", 2),
390    ENCODING_MAP(kMipsMtc1, 0x44800000,
391                 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
392                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1,
393                 "mtc1", "!0r,!1s", 2),
394#endif
395    ENCODING_MAP(kMipsUndefined, 0x64000000,
396                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
397                 kFmtUnused, -1, -1, NO_OPERAND,
398                 "undefined", "", 2),
399};
400
401/* Track the number of times that the code cache is patched */
402#if defined(WITH_JIT_TUNING)
403#define UPDATE_CODE_CACHE_PATCHES()    (gDvmJit.codeCachePatches++)
404#else
405#define UPDATE_CODE_CACHE_PATCHES()
406#endif
407
408/* Write the numbers in the constant and class pool to the output stream */
409static void installLiteralPools(CompilationUnit *cUnit)
410{
411    int *dataPtr = (int *) ((char *) cUnit->baseAddr + cUnit->dataOffset);
412    /* Install number of class pointer literals */
413    *dataPtr++ = cUnit->numClassPointers;
414    MipsLIR *dataLIR = (MipsLIR *) cUnit->classPointerList;
415    while (dataLIR) {
416        /*
417         * Install the callsiteinfo pointers into the cells for now. They will
418         * be converted into real pointers in dvmJitInstallClassObjectPointers.
419         */
420        *dataPtr++ = dataLIR->operands[0];
421        dataLIR = NEXT_LIR(dataLIR);
422    }
423    dataLIR = (MipsLIR *) cUnit->literalList;
424    while (dataLIR) {
425        *dataPtr++ = dataLIR->operands[0];
426        dataLIR = NEXT_LIR(dataLIR);
427    }
428}
429
430/*
431 * Assemble the LIR into binary instruction format.  Note that we may
432 * discover that pc-relative displacements may not fit the selected
433 * instruction.  In those cases we will try to substitute a new code
434 * sequence or request that the trace be shortened and retried.
435 */
436static AssemblerStatus assembleInstructions(CompilationUnit *cUnit,
437                                            intptr_t startAddr)
438{
439    int *bufferAddr = (int *) cUnit->codeBuffer;
440    MipsLIR *lir;
441
442    for (lir = (MipsLIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
443        if (lir->opcode < 0) {
444            continue;
445        }
446
447
448        if (lir->flags.isNop) {
449            continue;
450        }
451
452        if (lir->opcode == kMipsB || lir->opcode == kMipsBal) {
453            MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
454            intptr_t pc = lir->generic.offset + 4;
455            intptr_t target = targetLIR->generic.offset;
456            int delta = target - pc;
457            if (delta & 0x3) {
458                LOGE("PC-rel distance is not multiple of 4: %d", delta);
459                dvmAbort();
460            }
461            if (delta > 131068 || delta < -131069) {
462                LOGE("Unconditional branch distance out of range: %d", delta);
463                dvmAbort();
464            }
465            lir->operands[0] = delta >> 2;
466        } else if (lir->opcode >= kMipsBeqz && lir->opcode <= kMipsBnez) {
467            MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
468            intptr_t pc = lir->generic.offset + 4;
469            intptr_t target = targetLIR->generic.offset;
470            int delta = target - pc;
471            if (delta & 0x3) {
472                LOGE("PC-rel distance is not multiple of 4: %d", delta);
473                dvmAbort();
474            }
475            if (delta > 131068 || delta < -131069) {
476                LOGE("Conditional branch distance out of range: %d", delta);
477                dvmAbort();
478            }
479            lir->operands[1] = delta >> 2;
480        } else if (lir->opcode == kMipsBeq || lir->opcode == kMipsBne) {
481            MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
482            intptr_t pc = lir->generic.offset + 4;
483            intptr_t target = targetLIR->generic.offset;
484            int delta = target - pc;
485            if (delta & 0x3) {
486                LOGE("PC-rel distance is not multiple of 4: %d", delta);
487                dvmAbort();
488            }
489            if (delta > 131068 || delta < -131069) {
490                LOGE("Conditional branch distance out of range: %d", delta);
491                dvmAbort();
492            }
493            lir->operands[2] = delta >> 2;
494        } else if (lir->opcode == kMipsJal) {
495            intptr_t curPC = (startAddr + lir->generic.offset + 4) & ~3;
496            intptr_t target = lir->operands[0];
497            /* ensure PC-region branch can be used */
498            assert((curPC & 0xF0000000) == (target & 0xF0000000));
499            if (target & 0x3) {
500                LOGE("Jump target is not multiple of 4: %d", target);
501                dvmAbort();
502            }
503            lir->operands[0] =  target >> 2;
504        } else if (lir->opcode == kMipsLahi) { /* load address hi (via lui) */
505            MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
506            intptr_t target = startAddr + targetLIR->generic.offset;
507            lir->operands[1] = target >> 16;
508        } else if (lir->opcode == kMipsLalo) { /* load address lo (via ori) */
509            MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
510            intptr_t target = startAddr + targetLIR->generic.offset;
511            lir->operands[2] = lir->operands[2] + target;
512        }
513
514
515        MipsEncodingMap *encoder = &EncodingMap[lir->opcode];
516        u4 bits = encoder->skeleton;
517        int i;
518        for (i = 0; i < 4; i++) {
519            u4 operand;
520            u4 value;
521            operand = lir->operands[i];
522            switch(encoder->fieldLoc[i].kind) {
523                case kFmtUnused:
524                    break;
525                case kFmtBitBlt:
526                    if (encoder->fieldLoc[i].start == 0 && encoder->fieldLoc[i].end == 31) {
527                        value = operand;
528                    } else {
529                        value = (operand << encoder->fieldLoc[i].start) &
530                                ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
531                    }
532                    bits |= value;
533                    break;
534                case kFmtDfp: {
535                    assert(DOUBLEREG(operand));
536                    assert((operand & 0x1) == 0);
537                    value = ((operand & FP_REG_MASK) << encoder->fieldLoc[i].start) &
538                            ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
539                    bits |= value;
540                    break;
541                }
542                case kFmtSfp:
543                    assert(SINGLEREG(operand));
544                    value = ((operand & FP_REG_MASK) << encoder->fieldLoc[i].start) &
545                            ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
546                    bits |= value;
547                    break;
548                default:
549                    assert(0);
550            }
551        }
552        assert(encoder->size == 2);
553        *bufferAddr++ = bits;
554    }
555    return kSuccess;
556}
557
558static int assignLiteralOffsetCommon(LIR *lir, int offset)
559{
560    for (;lir != NULL; lir = lir->next) {
561        lir->offset = offset;
562        offset += 4;
563    }
564    return offset;
565}
566
567/* Determine the offset of each literal field */
568static int assignLiteralOffset(CompilationUnit *cUnit, int offset)
569{
570    /* Reserved for the size field of class pointer pool */
571    offset += 4;
572    offset = assignLiteralOffsetCommon(cUnit->classPointerList, offset);
573    offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
574    return offset;
575}
576
577/*
578 * Translation layout in the code cache.  Note that the codeAddress pointer
579 * in JitTable will point directly to the code body (field codeAddress).  The
580 * chain cell offset codeAddress - 4, and the address of the trace profile
581 * counter is at codeAddress - 8.
582 *
583 *      +----------------------------+
584 *      | Trace Profile Counter addr |  -> 4 bytes (PROF_COUNTER_ADDR_SIZE)
585 *      +----------------------------+
586 *   +--| Offset to chain cell counts|  -> 4 bytes (CHAIN_CELL_OFFSET_SIZE)
587 *   |  +----------------------------+
588 *   |  | Trace profile code         |  <- entry point when profiling
589 *   |  .  -   -   -   -   -   -   - .
590 *   |  | Code body                  |  <- entry point when not profiling
591 *   |  .                            .
592 *   |  |                            |
593 *   |  +----------------------------+
594 *   |  | Chaining Cells             |  -> 16/20 bytes, 4 byte aligned
595 *   |  .                            .
596 *   |  .                            .
597 *   |  |                            |
598 *   |  +----------------------------+
599 *   |  | Gap for large switch stmt  |  -> # cases >= MAX_CHAINED_SWITCH_CASES
600 *   |  +----------------------------+
601 *   +->| Chaining cell counts       |  -> 8 bytes, chain cell counts by type
602 *      +----------------------------+
603 *      | Trace description          |  -> variable sized
604 *      .                            .
605 *      |                            |
606 *      +----------------------------+
607 *      | # Class pointer pool size  |  -> 4 bytes
608 *      +----------------------------+
609 *      | Class pointer pool         |  -> 4-byte aligned, variable size
610 *      .                            .
611 *      .                            .
612 *      |                            |
613 *      +----------------------------+
614 *      | Literal pool               |  -> 4-byte aligned, variable size
615 *      .                            .
616 *      .                            .
617 *      |                            |
618 *      +----------------------------+
619 *
620 */
621
622#define PROF_COUNTER_ADDR_SIZE 4
623#define CHAIN_CELL_OFFSET_SIZE 4
624
625/*
626 * Utility functions to navigate various parts in a trace. If we change the
627 * layout/offset in the future, we just modify these functions and we don't need
628 * to propagate the changes to all the use cases.
629 */
630static inline char *getTraceBase(const JitEntry *p)
631{
632    return (char*)p->codeAddress -
633        (PROF_COUNTER_ADDR_SIZE + CHAIN_CELL_OFFSET_SIZE);
634}
635
636/* Handy function to retrieve the profile count */
637static inline JitTraceCounter_t getProfileCount(const JitEntry *entry)
638{
639    if (entry->dPC == 0 || entry->codeAddress == 0 ||
640        entry->codeAddress == dvmCompilerGetInterpretTemplate())
641        return 0;
642
643    JitTraceCounter_t **p = (JitTraceCounter_t **) getTraceBase(entry);
644
645    return **p;
646}
647
648/* Handy function to reset the profile count */
649static inline void resetProfileCount(const JitEntry *entry)
650{
651    if (entry->dPC == 0 || entry->codeAddress == 0 ||
652        entry->codeAddress == dvmCompilerGetInterpretTemplate())
653        return;
654
655    JitTraceCounter_t **p = (JitTraceCounter_t **) getTraceBase(entry);
656
657    **p = 0;
658}
659
660/* Get the pointer of the chain cell count */
661static inline ChainCellCounts* getChainCellCountsPointer(const char *base)
662{
663    /* 4 is the size of the profile count */
664    u4 *chainCellOffsetP = (u4 *) (base + PROF_COUNTER_ADDR_SIZE);
665    u4 chainCellOffset = *chainCellOffsetP;
666    return (ChainCellCounts *) ((char *) chainCellOffsetP + chainCellOffset);
667}
668
669/* Get the size of all chaining cells */
670static inline u4 getChainCellSize(const ChainCellCounts* pChainCellCounts)
671{
672    int cellSize = 0;
673    int i;
674
675    /* Get total count of chain cells */
676    for (i = 0; i < kChainingCellGap; i++) {
677        if (i != kChainingCellInvokePredicted) {
678            cellSize += pChainCellCounts->u.count[i] *
679                        (CHAIN_CELL_NORMAL_SIZE >> 2);
680        } else {
681            cellSize += pChainCellCounts->u.count[i] *
682                (CHAIN_CELL_PREDICTED_SIZE >> 2);
683        }
684    }
685    return cellSize;
686}
687
688/* Get the starting pointer of the trace description section */
689static JitTraceDescription* getTraceDescriptionPointer(const char *base)
690{
691    ChainCellCounts* pCellCounts = getChainCellCountsPointer(base);
692    return (JitTraceDescription*) ((char*)pCellCounts + sizeof(*pCellCounts));
693}
694
695/* Get the size of a trace description */
696static int getTraceDescriptionSize(const JitTraceDescription *desc)
697{
698    int runCount;
699    /* Trace end is always of non-meta type (ie isCode == true) */
700    for (runCount = 0; ; runCount++) {
701        if (desc->trace[runCount].isCode &&
702            desc->trace[runCount].info.frag.runEnd)
703           break;
704    }
705    return sizeof(JitTraceDescription) + ((runCount+1) * sizeof(JitTraceRun));
706}
707
708#if defined(SIGNATURE_BREAKPOINT)
709/* Inspect the assembled instruction stream to find potential matches */
710static void matchSignatureBreakpoint(const CompilationUnit *cUnit,
711                                     unsigned int size)
712{
713    unsigned int i, j;
714    u4 *ptr = (u4 *) cUnit->codeBuffer;
715
716    for (i = 0; i < size - gDvmJit.signatureBreakpointSize + 1; i++) {
717        if (ptr[i] == gDvmJit.signatureBreakpoint[0]) {
718            for (j = 1; j < gDvmJit.signatureBreakpointSize; j++) {
719                if (ptr[i+j] != gDvmJit.signatureBreakpoint[j]) {
720                    break;
721                }
722            }
723            if (j == gDvmJit.signatureBreakpointSize) {
724                LOGD("Signature match starting from offset %#x (%d words)",
725                     i*4, gDvmJit.signatureBreakpointSize);
726                int descSize = getTraceDescriptionSize(cUnit->traceDesc);
727                JitTraceDescription *newCopy =
728                    (JitTraceDescription *) malloc(descSize);
729                memcpy(newCopy, cUnit->traceDesc, descSize);
730                dvmCompilerWorkEnqueue(NULL, kWorkOrderTraceDebug, newCopy);
731                break;
732            }
733        }
734    }
735}
736#endif
737
738/*
739 * Go over each instruction in the list and calculate the offset from the top
740 * before sending them off to the assembler. If out-of-range branch distance is
741 * seen rearrange the instructions a bit to correct it.
742 */
743void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
744{
745    MipsLIR *mipsLIR;
746    int offset = 0;
747    int i;
748    ChainCellCounts chainCellCounts;
749    int descSize = (cUnit->jitMode == kJitMethod) ?
750        0 : getTraceDescriptionSize(cUnit->traceDesc);
751    int chainingCellGap = 0;
752
753    info->instructionSet = cUnit->instructionSet;
754
755    /* Beginning offset needs to allow space for chain cell offset */
756    for (mipsLIR = (MipsLIR *) cUnit->firstLIRInsn;
757         mipsLIR;
758         mipsLIR = NEXT_LIR(mipsLIR)) {
759        mipsLIR->generic.offset = offset;
760        if (mipsLIR->opcode >= 0 && !mipsLIR->flags.isNop) {
761            mipsLIR->flags.size = EncodingMap[mipsLIR->opcode].size * 2;
762            offset += mipsLIR->flags.size;
763        }
764        /* Pseudo opcodes don't consume space */
765    }
766
767    /* Const values have to be word aligned */
768    offset = (offset + 3) & ~3;
769
770    u4 chainCellOffset = offset;
771    MipsLIR *chainCellOffsetLIR = NULL;
772
773    if (cUnit->jitMode != kJitMethod) {
774        /*
775         * Get the gap (# of u4) between the offset of chaining cell count and
776         * the bottom of real chaining cells. If the translation has chaining
777         * cells, the gap is guaranteed to be multiples of 4.
778         */
779        chainingCellGap = (offset - cUnit->chainingCellBottom->offset) >> 2;
780
781        /* Add space for chain cell counts & trace description */
782        chainCellOffsetLIR = (MipsLIR *) cUnit->chainCellOffsetLIR;
783        assert(chainCellOffsetLIR);
784        assert(chainCellOffset < 0x10000);
785        assert(chainCellOffsetLIR->opcode == kMips32BitData &&
786               chainCellOffsetLIR->operands[0] == CHAIN_CELL_OFFSET_TAG);
787
788        /*
789         * Adjust the CHAIN_CELL_OFFSET_TAG LIR's offset to remove the
790         * space occupied by the pointer to the trace profiling counter.
791         */
792        chainCellOffsetLIR->operands[0] = chainCellOffset - 4;
793
794        offset += sizeof(chainCellCounts) + descSize;
795
796        assert((offset & 0x3) == 0);  /* Should still be word aligned */
797    }
798
799    /* Set up offsets for literals */
800    cUnit->dataOffset = offset;
801
802    /*
803     * Assign each class pointer/constant an offset from the beginning of the
804     * compilation unit.
805     */
806    offset = assignLiteralOffset(cUnit, offset);
807
808    cUnit->totalSize = offset;
809
810    if (gDvmJit.codeCacheByteUsed + cUnit->totalSize > gDvmJit.codeCacheSize) {
811        gDvmJit.codeCacheFull = true;
812        info->discardResult = true;
813        return;
814    }
815
816    /* Allocate enough space for the code block */
817    cUnit->codeBuffer = (unsigned char *)dvmCompilerNew(chainCellOffset, true);
818    if (cUnit->codeBuffer == NULL) {
819        LOGE("Code buffer allocation failure");
820        info->discardResult = true;
821        return;
822    }
823
824    /*
825     * Attempt to assemble the trace.  Note that assembleInstructions
826     * may rewrite the code sequence and request a retry.
827     */
828    cUnit->assemblerStatus = assembleInstructions(cUnit,
829          (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed);
830
831    switch(cUnit->assemblerStatus) {
832        case kSuccess:
833            break;
834        case kRetryAll:
835            if (cUnit->assemblerRetries < MAX_ASSEMBLER_RETRIES) {
836                if (cUnit->jitMode != kJitMethod) {
837                    /* Restore pristine chain cell marker on retry */
838                    chainCellOffsetLIR->operands[0] = CHAIN_CELL_OFFSET_TAG;
839                }
840                return;
841            }
842            /* Too many retries - reset and try cutting the trace in half */
843            cUnit->assemblerRetries = 0;
844            cUnit->assemblerStatus = kRetryHalve;
845            return;
846        case kRetryHalve:
847            return;
848        default:
849             LOGE("Unexpected assembler status: %d", cUnit->assemblerStatus);
850             dvmAbort();
851    }
852
853#if defined(SIGNATURE_BREAKPOINT)
854    if (info->discardResult == false && gDvmJit.signatureBreakpoint != NULL &&
855        chainCellOffset/4 >= gDvmJit.signatureBreakpointSize) {
856        matchSignatureBreakpoint(cUnit, chainCellOffset/4);
857    }
858#endif
859
860    /* Don't go all the way if the goal is just to get the verbose output */
861    if (info->discardResult) return;
862
863    /*
864     * The cache might disappear - acquire lock and check version
865     * Continue holding lock until translation cache update is complete.
866     * These actions are required here in the compiler thread because
867     * it is unaffected by suspend requests and doesn't know if a
868     * translation cache flush is in progress.
869     */
870    dvmLockMutex(&gDvmJit.compilerLock);
871    if (info->cacheVersion != gDvmJit.cacheVersion) {
872        /* Cache changed - discard current translation */
873        info->discardResult = true;
874        info->codeAddress = NULL;
875        dvmUnlockMutex(&gDvmJit.compilerLock);
876        return;
877    }
878
879    cUnit->baseAddr = (char *) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed;
880    gDvmJit.codeCacheByteUsed += offset;
881
882    UNPROTECT_CODE_CACHE(cUnit->baseAddr, offset);
883
884    /* Install the code block */
885    memcpy((char*)cUnit->baseAddr, cUnit->codeBuffer, chainCellOffset);
886    gDvmJit.numCompilations++;
887
888    if (cUnit->jitMode != kJitMethod) {
889        /* Install the chaining cell counts */
890        for (i=0; i< kChainingCellGap; i++) {
891            chainCellCounts.u.count[i] = cUnit->numChainingCells[i];
892        }
893
894        /* Set the gap number in the chaining cell count structure */
895        chainCellCounts.u.count[kChainingCellGap] = chainingCellGap;
896
897        memcpy((char*)cUnit->baseAddr + chainCellOffset, &chainCellCounts,
898               sizeof(chainCellCounts));
899
900        /* Install the trace description */
901        memcpy((char*) cUnit->baseAddr + chainCellOffset +
902                       sizeof(chainCellCounts),
903               cUnit->traceDesc, descSize);
904    }
905
906    /* Write the literals directly into the code cache */
907    installLiteralPools(cUnit);
908
909    /* Flush dcache and invalidate the icache to maintain coherence */
910    dvmCompilerCacheFlush((long)cUnit->baseAddr,
911                          (long)((char *) cUnit->baseAddr + offset), 0);
912
913    UPDATE_CODE_CACHE_PATCHES();
914
915    PROTECT_CODE_CACHE(cUnit->baseAddr, offset);
916
917    /* Translation cache update complete - release lock */
918    dvmUnlockMutex(&gDvmJit.compilerLock);
919
920    /* Record code entry point and instruction set */
921    info->codeAddress = (char*)cUnit->baseAddr + cUnit->headerSize;
922    /* transfer the size of the profiling code */
923    info->profileCodeSize = cUnit->profileCodeSize;
924}
925
926/*
927 * Returns the skeleton bit pattern associated with an opcode.  All
928 * variable fields are zeroed.
929 */
930static u4 getSkeleton(MipsOpCode op)
931{
932    return EncodingMap[op].skeleton;
933}
934
935static u4 assembleChainingBranch(int branchOffset, bool thumbTarget)
936{
937    return getSkeleton(kMipsJal) | ((branchOffset & 0x0FFFFFFF) >> 2);
938}
939
940/*
941 * Perform translation chain operation.
942 * For MIPS, we'll use a JAL instruction to generate an
943 * unconditional chaining branch of up to 256M. The JAL
944 * instruction also has a restriction that the jump target
945 * must be in the same 256M page as the JAL instruction's
946 * delay slot address.
947 * If the target is out of JAL's range, don't chain.
948 * If one or more threads is suspended, don't chain.
949 */
950void* dvmJitChain(void* tgtAddr, u4* branchAddr)
951{
952    u4 newInst;
953
954    /*
955     * Only chain translations when there is no urge to ask all threads to
956     * suspend themselves via the interpreter.
957     */
958    if ((gDvmJit.pProfTable != NULL) && (gDvm.sumThreadSuspendCount == 0) &&
959        (gDvmJit.codeCacheFull == false) &&
960        ((((int) tgtAddr) & 0xF0000000) == (((int) branchAddr+4) & 0xF0000000))) {
961        gDvmJit.translationChains++;
962
963        COMPILER_TRACE_CHAINING(
964            LOGD("Jit Runtime: chaining 0x%x to 0x%x",
965                 (int) branchAddr, (int) tgtAddr & -2));
966
967        newInst = assembleChainingBranch((int) tgtAddr & -2, 0);
968
969        UNPROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr));
970
971        *branchAddr = newInst;
972        dvmCompilerCacheFlush((long)branchAddr, (long)branchAddr + 4, 0);
973        UPDATE_CODE_CACHE_PATCHES();
974
975        PROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr));
976
977        gDvmJit.hasNewChain = true;
978    }
979
980    return tgtAddr;
981}
982
983#if !defined(WITH_SELF_VERIFICATION)
984/*
985 * Attempt to enqueue a work order to patch an inline cache for a predicted
986 * chaining cell for virtual/interface calls.
987 */
988static void inlineCachePatchEnqueue(PredictedChainingCell *cellAddr,
989                                    PredictedChainingCell *newContent)
990{
991    /*
992     * Make sure only one thread gets here since updating the cell (ie fast
993     * path and queueing the request (ie the queued path) have to be done
994     * in an atomic fashion.
995     */
996    dvmLockMutex(&gDvmJit.compilerICPatchLock);
997
998    /* Fast path for uninitialized chaining cell */
999    if (cellAddr->clazz == NULL &&
1000        cellAddr->branch == PREDICTED_CHAIN_BX_PAIR_INIT) {
1001
1002        UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1003
1004        cellAddr->method = newContent->method;
1005        cellAddr->branch = newContent->branch;
1006
1007        /*
1008         * The update order matters - make sure clazz is updated last since it
1009         * will bring the uninitialized chaining cell to life.
1010         */
1011        android_atomic_release_store((int32_t)newContent->clazz,
1012            (volatile int32_t *)(void*) &cellAddr->clazz);
1013        dvmCompilerCacheFlush((long) cellAddr, (long) (cellAddr+1), 0);
1014        UPDATE_CODE_CACHE_PATCHES();
1015
1016        PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1017
1018#if defined(WITH_JIT_TUNING)
1019        gDvmJit.icPatchInit++;
1020#endif
1021    /* Check if this is a frequently missed clazz */
1022    } else if (cellAddr->stagedClazz != newContent->clazz) {
1023        /* Not proven to be frequent yet - build up the filter cache */
1024        UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1025
1026        cellAddr->stagedClazz = newContent->clazz;
1027
1028        UPDATE_CODE_CACHE_PATCHES();
1029        PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1030
1031#if defined(WITH_JIT_TUNING)
1032        gDvmJit.icPatchRejected++;
1033#endif
1034    /*
1035     * Different classes but same method implementation - it is safe to just
1036     * patch the class value without the need to stop the world.
1037     */
1038    } else if (cellAddr->method == newContent->method) {
1039        UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1040
1041        cellAddr->clazz = newContent->clazz;
1042        /* No need to flush the cache here since the branch is not patched */
1043        UPDATE_CODE_CACHE_PATCHES();
1044
1045        PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr));
1046
1047#if defined(WITH_JIT_TUNING)
1048        gDvmJit.icPatchLockFree++;
1049#endif
1050    /*
1051     * Cannot patch the chaining cell inline - queue it until the next safe
1052     * point.
1053     */
1054    } else if (gDvmJit.compilerICPatchIndex < COMPILER_IC_PATCH_QUEUE_SIZE) {
1055        int index = gDvmJit.compilerICPatchIndex++;
1056        const ClassObject *clazz = newContent->clazz;
1057
1058        gDvmJit.compilerICPatchQueue[index].cellAddr = cellAddr;
1059        gDvmJit.compilerICPatchQueue[index].cellContent = *newContent;
1060        gDvmJit.compilerICPatchQueue[index].classDescriptor = clazz->descriptor;
1061        gDvmJit.compilerICPatchQueue[index].classLoader = clazz->classLoader;
1062        /* For verification purpose only */
1063        gDvmJit.compilerICPatchQueue[index].serialNumber = clazz->serialNumber;
1064#if defined(WITH_JIT_TUNING)
1065        gDvmJit.icPatchQueued++;
1066#endif
1067    } else {
1068    /* Queue is full - just drop this patch request */
1069#if defined(WITH_JIT_TUNING)
1070        gDvmJit.icPatchDropped++;
1071#endif
1072    }
1073
1074    dvmUnlockMutex(&gDvmJit.compilerICPatchLock);
1075}
1076#endif
1077
1078/*
1079 * This method is called from the invoke templates for virtual and interface
1080 * methods to speculatively setup a chain to the callee. The templates are
1081 * written in assembly and have setup method, cell, and clazz at r0, r2, and
1082 * r3 respectively, so there is a unused argument in the list. Upon return one
1083 * of the following three results may happen:
1084 *   1) Chain is not setup because the callee is native. Reset the rechain
1085 *      count to a big number so that it will take a long time before the next
1086 *      rechain attempt to happen.
1087 *   2) Chain is not setup because the callee has not been created yet. Reset
1088 *      the rechain count to a small number and retry in the near future.
1089 *   3) Ask all other threads to stop before patching this chaining cell.
1090 *      This is required because another thread may have passed the class check
1091 *      but hasn't reached the chaining cell yet to follow the chain. If we
1092 *      patch the content before halting the other thread, there could be a
1093 *      small window for race conditions to happen that it may follow the new
1094 *      but wrong chain to invoke a different method.
1095 */
1096const Method *dvmJitToPatchPredictedChain(const Method *method,
1097                                          Thread *self,
1098                                          PredictedChainingCell *cell,
1099                                          const ClassObject *clazz)
1100{
1101    int newRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
1102#if defined(WITH_SELF_VERIFICATION)
1103    newRechainCount = PREDICTED_CHAIN_COUNTER_AVOID;
1104    goto done;
1105#else
1106    PredictedChainingCell newCell;
1107    int baseAddr, tgtAddr;
1108    if (dvmIsNativeMethod(method)) {
1109        UNPROTECT_CODE_CACHE(cell, sizeof(*cell));
1110
1111        /*
1112         * Put a non-zero/bogus value in the clazz field so that it won't
1113         * trigger immediate patching and will continue to fail to match with
1114         * a real clazz pointer.
1115         */
1116        cell->clazz = (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ;
1117
1118        UPDATE_CODE_CACHE_PATCHES();
1119        PROTECT_CODE_CACHE(cell, sizeof(*cell));
1120        goto done;
1121    }
1122
1123    tgtAddr = (int) dvmJitGetTraceAddr(method->insns);
1124    baseAddr = (int) cell + 4;   // PC is cur_addr + 4
1125
1126    if ((baseAddr & 0xF0000000) != (tgtAddr & 0xF0000000)) {
1127        COMPILER_TRACE_CHAINING(
1128            LOGD("Jit Runtime: predicted chain %p to distant target %s ignored",
1129                 cell, method->name));
1130        goto done;
1131    }
1132
1133    /*
1134     * Compilation not made yet for the callee. Reset the counter to a small
1135     * value and come back to check soon.
1136     */
1137    if ((tgtAddr == 0) ||
1138        ((void*)tgtAddr == dvmCompilerGetInterpretTemplate())) {
1139        COMPILER_TRACE_CHAINING(
1140            LOGD("Jit Runtime: predicted chain %p to method %s%s delayed",
1141                 cell, method->clazz->descriptor, method->name));
1142        goto done;
1143    }
1144
1145    if (cell->clazz == NULL) {
1146        newRechainCount = self->icRechainCount;
1147    }
1148
1149    newCell.branch = assembleChainingBranch(tgtAddr, true);
1150    newCell.delay_slot = getSkeleton(kMipsNop);
1151    newCell.clazz = clazz;
1152    newCell.method = method;
1153    newCell.stagedClazz = NULL;
1154
1155    /*
1156     * Enter the work order to the queue and the chaining cell will be patched
1157     * the next time a safe point is entered.
1158     *
1159     * If the enqueuing fails reset the rechain count to a normal value so that
1160     * it won't get indefinitely delayed.
1161     */
1162    inlineCachePatchEnqueue(cell, &newCell);
1163#endif
1164done:
1165    self->icRechainCount = newRechainCount;
1166    return method;
1167}
1168
1169/*
1170 * Patch the inline cache content based on the content passed from the work
1171 * order.
1172 */
1173void dvmCompilerPatchInlineCache(void)
1174{
1175    int i;
1176    PredictedChainingCell *minAddr, *maxAddr;
1177
1178    /* Nothing to be done */
1179    if (gDvmJit.compilerICPatchIndex == 0) return;
1180
1181    /*
1182     * Since all threads are already stopped we don't really need to acquire
1183     * the lock. But race condition can be easily introduced in the future w/o
1184     * paying attention so we still acquire the lock here.
1185     */
1186    dvmLockMutex(&gDvmJit.compilerICPatchLock);
1187
1188    UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1189
1190    //LOGD("Number of IC patch work orders: %d", gDvmJit.compilerICPatchIndex);
1191
1192    /* Initialize the min/max address range */
1193    minAddr = (PredictedChainingCell *)
1194        ((char *) gDvmJit.codeCache + gDvmJit.codeCacheSize);
1195    maxAddr = (PredictedChainingCell *) gDvmJit.codeCache;
1196
1197    for (i = 0; i < gDvmJit.compilerICPatchIndex; i++) {
1198        ICPatchWorkOrder *workOrder = &gDvmJit.compilerICPatchQueue[i];
1199        PredictedChainingCell *cellAddr = workOrder->cellAddr;
1200        PredictedChainingCell *cellContent = &workOrder->cellContent;
1201        ClassObject *clazz = dvmFindClassNoInit(workOrder->classDescriptor,
1202                                                workOrder->classLoader);
1203
1204        assert(clazz->serialNumber == workOrder->serialNumber);
1205
1206        /* Use the newly resolved clazz pointer */
1207        cellContent->clazz = clazz;
1208
1209        COMPILER_TRACE_CHAINING(
1210            LOGD("Jit Runtime: predicted chain %p from %s to %s (%s) "
1211                 "patched",
1212                 cellAddr,
1213                 cellAddr->clazz->descriptor,
1214                 cellContent->clazz->descriptor,
1215                 cellContent->method->name));
1216
1217        /* Patch the chaining cell */
1218        *cellAddr = *cellContent;
1219        minAddr = (cellAddr < minAddr) ? cellAddr : minAddr;
1220        maxAddr = (cellAddr > maxAddr) ? cellAddr : maxAddr;
1221    }
1222
1223    /* Then synchronize the I/D cache */
1224    dvmCompilerCacheFlush((long) minAddr, (long) (maxAddr+1), 0);
1225    UPDATE_CODE_CACHE_PATCHES();
1226
1227    PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1228
1229    gDvmJit.compilerICPatchIndex = 0;
1230    dvmUnlockMutex(&gDvmJit.compilerICPatchLock);
1231}
1232
1233/*
1234 * Unchain a trace given the starting address of the translation
1235 * in the code cache.  Refer to the diagram in dvmCompilerAssembleLIR.
1236 * Returns the address following the last cell unchained.  Note that
1237 * the incoming codeAddr is a thumb code address, and therefore has
1238 * the low bit set.
1239 */
1240static u4* unchainSingle(JitEntry *trace)
1241{
1242    const char *base = getTraceBase(trace);
1243    ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base);
1244    int cellSize = getChainCellSize(pChainCellCounts);
1245    u4* pChainCells;
1246    int i,j;
1247    PredictedChainingCell *predChainCell;
1248
1249    if (cellSize == 0)
1250        return (u4 *) pChainCellCounts;
1251
1252    /* Locate the beginning of the chain cell region */
1253    pChainCells = ((u4 *) pChainCellCounts) - cellSize -
1254                  pChainCellCounts->u.count[kChainingCellGap];
1255
1256    /* The cells are sorted in order - walk through them and reset */
1257    for (i = 0; i < kChainingCellGap; i++) {
1258        int elemSize = CHAIN_CELL_NORMAL_SIZE >> 2;  /* In 32-bit words */
1259        if (i == kChainingCellInvokePredicted) {
1260            elemSize = CHAIN_CELL_PREDICTED_SIZE >> 2;
1261        }
1262
1263        for (j = 0; j < pChainCellCounts->u.count[i]; j++) {
1264            int targetOffset;
1265            switch(i) {
1266                case kChainingCellNormal:
1267                    targetOffset = offsetof(Thread,
1268                          jitToInterpEntries.dvmJitToInterpNormal);
1269                    break;
1270                case kChainingCellHot:
1271                case kChainingCellInvokeSingleton:
1272                    targetOffset = offsetof(Thread,
1273                          jitToInterpEntries.dvmJitToInterpTraceSelect);
1274                    break;
1275                case kChainingCellInvokePredicted:
1276                    targetOffset = 0;
1277                    predChainCell = (PredictedChainingCell *) pChainCells;
1278                    /*
1279                     * There could be a race on another mutator thread to use
1280                     * this particular predicted cell and the check has passed
1281                     * the clazz comparison. So we cannot safely wipe the
1282                     * method and branch but it is safe to clear the clazz,
1283                     * which serves as the key.
1284                     */
1285                    predChainCell->clazz = PREDICTED_CHAIN_CLAZZ_INIT;
1286                    break;
1287#if defined(WITH_SELF_VERIFICATION)
1288                case kChainingCellBackwardBranch:
1289                    targetOffset = offsetof(Thread,
1290                          jitToInterpEntries.dvmJitToInterpBackwardBranch);
1291                    break;
1292#else
1293                case kChainingCellBackwardBranch:
1294                    targetOffset = offsetof(Thread,
1295                          jitToInterpEntries.dvmJitToInterpNormal);
1296                    break;
1297#endif
1298                default:
1299                    targetOffset = 0; // make gcc happy
1300                    LOGE("Unexpected chaining type: %d", i);
1301                    dvmAbort();  // dvmAbort OK here - can't safely recover
1302            }
1303            COMPILER_TRACE_CHAINING(
1304                LOGD("Jit Runtime: unchaining %#x", (int)pChainCells));
1305            /*
1306             * Code sequence for a chaining cell is:
1307             *     lw   a0, offset(rSELF)
1308             *     jalr ra, a0
1309             */
1310            if (i != kChainingCellInvokePredicted) {
1311                *pChainCells = getSkeleton(kMipsLw) | (r_A0 << 16) |
1312                               targetOffset | (rSELF << 21);
1313                *(pChainCells+1) = getSkeleton(kMipsJalr) | (r_RA << 11) |
1314                                   (r_A0 << 21);
1315            }
1316            pChainCells += elemSize;  /* Advance by a fixed number of words */
1317        }
1318    }
1319    return pChainCells;
1320}
1321
1322/* Unchain all translation in the cache. */
1323void dvmJitUnchainAll()
1324{
1325    u4* lowAddress = NULL;
1326    u4* highAddress = NULL;
1327    unsigned int i;
1328    if (gDvmJit.pJitEntryTable != NULL) {
1329        COMPILER_TRACE_CHAINING(LOGD("Jit Runtime: unchaining all"));
1330        dvmLockMutex(&gDvmJit.tableLock);
1331
1332        UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1333
1334        for (i = 0; i < gDvmJit.jitTableSize; i++) {
1335            if (gDvmJit.pJitEntryTable[i].dPC &&
1336                !gDvmJit.pJitEntryTable[i].u.info.isMethodEntry &&
1337                gDvmJit.pJitEntryTable[i].codeAddress &&
1338                (gDvmJit.pJitEntryTable[i].codeAddress !=
1339                 dvmCompilerGetInterpretTemplate())) {
1340                u4* lastAddress;
1341                lastAddress = unchainSingle(&gDvmJit.pJitEntryTable[i]);
1342                if (lowAddress == NULL ||
1343                      (u4*)gDvmJit.pJitEntryTable[i].codeAddress < lowAddress)
1344                    lowAddress = (u4*)gDvmJit.pJitEntryTable[i].codeAddress;
1345                if (lastAddress > highAddress)
1346                    highAddress = lastAddress;
1347            }
1348        }
1349
1350        if (lowAddress && highAddress) {
1351            dvmCompilerCacheFlush((long)lowAddress, (long)highAddress, 0);
1352        }
1353
1354        UPDATE_CODE_CACHE_PATCHES();
1355
1356        PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1357
1358        dvmUnlockMutex(&gDvmJit.tableLock);
1359        gDvmJit.translationChains = 0;
1360    }
1361    gDvmJit.hasNewChain = false;
1362}
1363
1364typedef struct jitProfileAddrToLine {
1365    u4 lineNum;
1366    u4 bytecodeOffset;
1367} jitProfileAddrToLine;
1368
1369
1370/* Callback function to track the bytecode offset/line number relationiship */
1371static int addrToLineCb (void *cnxt, u4 bytecodeOffset, u4 lineNum)
1372{
1373    jitProfileAddrToLine *addrToLine = (jitProfileAddrToLine *) cnxt;
1374
1375    /* Best match so far for this offset */
1376    if (addrToLine->bytecodeOffset >= bytecodeOffset) {
1377        addrToLine->lineNum = lineNum;
1378    }
1379    return 0;
1380}
1381
1382/* Dumps profile info for a single trace */
1383static int dumpTraceProfile(JitEntry *p, bool silent, bool reset,
1384                            unsigned long sum)
1385{
1386    int idx;
1387
1388    if (p->codeAddress == NULL) {
1389        if (!silent)
1390            LOGD("TRACEPROFILE NULL");
1391        return 0;
1392    }
1393    if (p->codeAddress == dvmCompilerGetInterpretTemplate()) {
1394        if (!silent)
1395            LOGD("TRACEPROFILE INTERPRET_ONLY");
1396        return 0;
1397    }
1398
1399    JitTraceCounter_t count = getProfileCount(p);
1400    if (reset) {
1401        resetProfileCount(p);
1402    }
1403    if (silent) {
1404        return count;
1405    }
1406    JitTraceDescription *desc = getTraceDescriptionPointer(getTraceBase(p));
1407    const Method *method = desc->method;
1408    char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype);
1409    jitProfileAddrToLine addrToLine = {0, desc->trace[0].info.frag.startOffset};
1410
1411    /*
1412     * We may end up decoding the debug information for the same method
1413     * multiple times, but the tradeoff is we don't need to allocate extra
1414     * space to store the addr/line mapping. Since this is a debugging feature
1415     * and done infrequently so the slower but simpler mechanism should work
1416     * just fine.
1417     */
1418    dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile,
1419                       dvmGetMethodCode(method),
1420                       method->clazz->descriptor,
1421                       method->prototype.protoIdx,
1422                       method->accessFlags,
1423                       addrToLineCb, NULL, &addrToLine);
1424
1425    LOGD("TRACEPROFILE 0x%08x % 10d %5.2f%% [%#x(+%d), %d] %s%s;%s",
1426         (int) getTraceBase(p),
1427         count,
1428         ((float ) count) / sum * 100.0,
1429         desc->trace[0].info.frag.startOffset,
1430         desc->trace[0].info.frag.numInsts,
1431         addrToLine.lineNum,
1432         method->clazz->descriptor, method->name, methodDesc);
1433    free(methodDesc);
1434
1435    /* Find the last fragment (ie runEnd is set) */
1436    for (idx = 0;
1437         desc->trace[idx].isCode && !desc->trace[idx].info.frag.runEnd;
1438         idx++) {
1439    }
1440
1441    /*
1442     * runEnd must comes with a JitCodeDesc frag. If isCode is false it must
1443     * be a meta info field (only used by callsite info for now).
1444     */
1445    if (!desc->trace[idx].isCode) {
1446        const Method *method = (const Method *)
1447            desc->trace[idx+JIT_TRACE_CUR_METHOD-1].info.meta;
1448        char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype);
1449        /* Print the callee info in the trace */
1450        LOGD("    -> %s%s;%s", method->clazz->descriptor, method->name,
1451             methodDesc);
1452    }
1453
1454    return count;
1455}
1456
1457/* Create a copy of the trace descriptor of an existing compilation */
1458JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
1459                                            const JitEntry *knownEntry)
1460{
1461    const JitEntry *jitEntry = knownEntry ? knownEntry
1462                                          : dvmJitFindEntry(pc, false);
1463    if ((jitEntry == NULL) || (jitEntry->codeAddress == 0))
1464        return NULL;
1465
1466    JitTraceDescription *desc =
1467        getTraceDescriptionPointer(getTraceBase(jitEntry));
1468
1469    /* Now make a copy and return */
1470    int descSize = getTraceDescriptionSize(desc);
1471    JitTraceDescription *newCopy = (JitTraceDescription *) malloc(descSize);
1472    memcpy(newCopy, desc, descSize);
1473    return newCopy;
1474}
1475
1476/* qsort callback function */
1477static int sortTraceProfileCount(const void *entry1, const void *entry2)
1478{
1479    const JitEntry *jitEntry1 = (const JitEntry *)entry1;
1480    const JitEntry *jitEntry2 = (const JitEntry *)entry2;
1481
1482    JitTraceCounter_t count1 = getProfileCount(jitEntry1);
1483    JitTraceCounter_t count2 = getProfileCount(jitEntry2);
1484    return (count1 == count2) ? 0 : ((count1 > count2) ? -1 : 1);
1485}
1486
1487/* Sort the trace profile counts and dump them */
1488void dvmCompilerSortAndPrintTraceProfiles()
1489{
1490    JitEntry *sortedEntries;
1491    int numTraces = 0;
1492    unsigned long sum = 0;
1493    unsigned int i;
1494
1495    /* Make sure that the table is not changing */
1496    dvmLockMutex(&gDvmJit.tableLock);
1497
1498    /* Sort the entries by descending order */
1499    sortedEntries = (JitEntry *)malloc(sizeof(JitEntry) * gDvmJit.jitTableSize);
1500    if (sortedEntries == NULL)
1501        goto done;
1502    memcpy(sortedEntries, gDvmJit.pJitEntryTable,
1503           sizeof(JitEntry) * gDvmJit.jitTableSize);
1504    qsort(sortedEntries, gDvmJit.jitTableSize, sizeof(JitEntry),
1505          sortTraceProfileCount);
1506
1507    /* Analyze the sorted entries */
1508    for (i=0; i < gDvmJit.jitTableSize; i++) {
1509        if (sortedEntries[i].dPC != 0) {
1510            sum += dumpTraceProfile(&sortedEntries[i],
1511                                       true /* silent */,
1512                                       false /* reset */,
1513                                       0);
1514            numTraces++;
1515        }
1516    }
1517    if (numTraces == 0)
1518        numTraces = 1;
1519    if (sum == 0) {
1520        sum = 1;
1521    }
1522
1523    LOGD("JIT: Average execution count -> %d",(int)(sum / numTraces));
1524
1525    /* Dump the sorted entries. The count of each trace will be reset to 0. */
1526    for (i=0; i < gDvmJit.jitTableSize; i++) {
1527        if (sortedEntries[i].dPC != 0) {
1528            dumpTraceProfile(&sortedEntries[i],
1529                             false /* silent */,
1530                             true /* reset */,
1531                             sum);
1532        }
1533    }
1534
1535    for (i=0; i < gDvmJit.jitTableSize && i < 10; i++) {
1536        /* Stip interpreter stubs */
1537        if (sortedEntries[i].codeAddress == dvmCompilerGetInterpretTemplate()) {
1538            continue;
1539        }
1540        JitTraceDescription* desc =
1541            dvmCopyTraceDescriptor(NULL, &sortedEntries[i]);
1542        if (desc) {
1543            dvmCompilerWorkEnqueue(sortedEntries[i].dPC,
1544                                   kWorkOrderTraceDebug, desc);
1545        }
1546    }
1547
1548    free(sortedEntries);
1549done:
1550    dvmUnlockMutex(&gDvmJit.tableLock);
1551    return;
1552}
1553
1554static void findClassPointersSingleTrace(char *base, void (*callback)(void *))
1555{
1556    unsigned int chainTypeIdx, chainIdx;
1557    ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base);
1558    int cellSize = getChainCellSize(pChainCellCounts);
1559    /* Scan the chaining cells */
1560    if (cellSize) {
1561        /* Locate the beginning of the chain cell region */
1562        u4 *pChainCells = ((u4 *) pChainCellCounts) - cellSize -
1563            pChainCellCounts->u.count[kChainingCellGap];
1564        /* The cells are sorted in order - walk through them */
1565        for (chainTypeIdx = 0; chainTypeIdx < kChainingCellGap;
1566             chainTypeIdx++) {
1567            if (chainTypeIdx != kChainingCellInvokePredicted) {
1568                /* In 32-bit words */
1569                pChainCells += (CHAIN_CELL_NORMAL_SIZE >> 2) *
1570                    pChainCellCounts->u.count[chainTypeIdx];
1571                continue;
1572            }
1573            for (chainIdx = 0;
1574                 chainIdx < pChainCellCounts->u.count[chainTypeIdx];
1575                 chainIdx++) {
1576                PredictedChainingCell *cell =
1577                    (PredictedChainingCell *) pChainCells;
1578                /*
1579                 * Report the cell if it contains a sane class
1580                 * pointer.
1581                 */
1582                if (cell->clazz != NULL &&
1583                    cell->clazz !=
1584                      (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ) {
1585                    callback(&cell->clazz);
1586                }
1587                pChainCells += CHAIN_CELL_PREDICTED_SIZE >> 2;
1588            }
1589        }
1590    }
1591
1592    /* Scan the class pointer pool */
1593    JitTraceDescription *desc = getTraceDescriptionPointer(base);
1594    int descSize = getTraceDescriptionSize(desc);
1595    int *classPointerP = (int *) ((char *) desc + descSize);
1596    int numClassPointers = *classPointerP++;
1597    for (; numClassPointers; numClassPointers--, classPointerP++) {
1598        callback(classPointerP);
1599    }
1600}
1601
1602/*
1603 * Scan class pointers in each translation and pass its address to the callback
1604 * function. Currently such a pointers can be found in the pointer pool and the
1605 * clazz field in the predicted chaining cells.
1606 */
1607void dvmJitScanAllClassPointers(void (*callback)(void *))
1608{
1609    UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1610
1611    /* Handle the inflight compilation first */
1612    if (gDvmJit.inflightBaseAddr)
1613        findClassPointersSingleTrace((char *) gDvmJit.inflightBaseAddr,
1614                                     callback);
1615
1616    if (gDvmJit.pJitEntryTable != NULL) {
1617        unsigned int traceIdx;
1618        dvmLockMutex(&gDvmJit.tableLock);
1619        for (traceIdx = 0; traceIdx < gDvmJit.jitTableSize; traceIdx++) {
1620            const JitEntry *entry = &gDvmJit.pJitEntryTable[traceIdx];
1621            if (entry->dPC &&
1622                !entry->u.info.isMethodEntry &&
1623                entry->codeAddress &&
1624                (entry->codeAddress != dvmCompilerGetInterpretTemplate())) {
1625                char *base = getTraceBase(entry);
1626                findClassPointersSingleTrace(base, callback);
1627            }
1628        }
1629        dvmUnlockMutex(&gDvmJit.tableLock);
1630    }
1631    UPDATE_CODE_CACHE_PATCHES();
1632
1633    PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1634}
1635
1636/*
1637 * Provide the final touch on the class object pointer pool to install the
1638 * actual pointers. The thread has to be in the running state.
1639 */
1640void dvmJitInstallClassObjectPointers(CompilationUnit *cUnit, char *codeAddress)
1641{
1642    char *base = codeAddress - cUnit->headerSize;
1643
1644    /* Scan the class pointer pool */
1645    JitTraceDescription *desc = getTraceDescriptionPointer(base);
1646    int descSize = getTraceDescriptionSize(desc);
1647    intptr_t *classPointerP = (int *) ((char *) desc + descSize);
1648    int numClassPointers = *(int *)classPointerP++;
1649    intptr_t *startClassPointerP = classPointerP;
1650
1651    /*
1652     * Change the thread state to VM_RUNNING so that GC won't be happening
1653     * when the assembler looks up the class pointers. May suspend the current
1654     * thread if there is a pending request before the state is actually
1655     * changed to RUNNING.
1656     */
1657    dvmChangeStatus(gDvmJit.compilerThread, THREAD_RUNNING);
1658
1659    /*
1660     * Unprotecting the code cache will need to acquire the code cache
1661     * protection lock first. Doing so after the state change may increase the
1662     * time spent in the RUNNING state (which may delay the next GC request
1663     * should there be contention on codeCacheProtectionLock). In practice
1664     * this is probably not going to happen often since a GC is just served.
1665     * More importantly, acquiring the lock before the state change will
1666     * cause deadlock (b/4192964).
1667     */
1668    UNPROTECT_CODE_CACHE(startClassPointerP,
1669                         numClassPointers * sizeof(intptr_t));
1670#if defined(WITH_JIT_TUNING)
1671    u8 startTime = dvmGetRelativeTimeUsec();
1672#endif
1673    for (;numClassPointers; numClassPointers--) {
1674        CallsiteInfo *callsiteInfo = (CallsiteInfo *) *classPointerP;
1675        ClassObject *clazz = dvmFindClassNoInit(
1676            callsiteInfo->classDescriptor, callsiteInfo->classLoader);
1677        assert(!strcmp(clazz->descriptor, callsiteInfo->classDescriptor));
1678        *classPointerP++ = (intptr_t) clazz;
1679    }
1680
1681    /*
1682     * Register the base address so that if GC kicks in after the thread state
1683     * has been changed to VMWAIT and before the compiled code is registered
1684     * in the JIT table, its content can be patched if class objects are
1685     * moved.
1686     */
1687    gDvmJit.inflightBaseAddr = base;
1688
1689#if defined(WITH_JIT_TUNING)
1690    u8 blockTime = dvmGetRelativeTimeUsec() - startTime;
1691    gDvmJit.compilerThreadBlockGCTime += blockTime;
1692    if (blockTime > gDvmJit.maxCompilerThreadBlockGCTime)
1693        gDvmJit.maxCompilerThreadBlockGCTime = blockTime;
1694    gDvmJit.numCompilerThreadBlockGC++;
1695#endif
1696    UPDATE_CODE_CACHE_PATCHES();
1697
1698    PROTECT_CODE_CACHE(startClassPointerP, numClassPointers * sizeof(intptr_t));
1699
1700    /* Change the thread state back to VMWAIT */
1701    dvmChangeStatus(gDvmJit.compilerThread, THREAD_VMWAIT);
1702}
1703
1704#if defined(WITH_SELF_VERIFICATION)
1705/*
1706 * The following are used to keep compiled loads and stores from modifying
1707 * memory during self verification mode.
1708 *
1709 * Stores do not modify memory. Instead, the address and value pair are stored
1710 * into heapSpace. Addresses within heapSpace are unique. For accesses smaller
1711 * than a word, the word containing the address is loaded first before being
1712 * updated.
1713 *
1714 * Loads check heapSpace first and return data from there if an entry exists.
1715 * Otherwise, data is loaded from memory as usual.
1716 */
1717
1718/* Used to specify sizes of memory operations */
1719enum {
1720    kSVByte,
1721    kSVSignedByte,
1722    kSVHalfword,
1723    kSVSignedHalfword,
1724    kSVWord,
1725    kSVDoubleword,
1726    kSVVariable,
1727};
1728
1729/* Load the value of a decoded register from the stack */
1730static int selfVerificationMemRegLoad(int* sp, int reg)
1731{
1732assert(0); /* MIPSTODO retarg func */
1733    return *(sp + reg);
1734}
1735
1736/* Load the value of a decoded doubleword register from the stack */
1737static s8 selfVerificationMemRegLoadDouble(int* sp, int reg)
1738{
1739assert(0); /* MIPSTODO retarg func */
1740    return *((s8*)(sp + reg));
1741}
1742
1743/* Store the value of a decoded register out to the stack */
1744static void selfVerificationMemRegStore(int* sp, int data, int reg)
1745{
1746assert(0); /* MIPSTODO retarg func */
1747    *(sp + reg) = data;
1748}
1749
1750/* Store the value of a decoded doubleword register out to the stack */
1751static void selfVerificationMemRegStoreDouble(int* sp, s8 data, int reg)
1752{
1753assert(0); /* MIPSTODO retarg func */
1754    *((s8*)(sp + reg)) = data;
1755}
1756
1757/*
1758 * Load the specified size of data from the specified address, checking
1759 * heapSpace first if Self Verification mode wrote to it previously, and
1760 * falling back to actual memory otherwise.
1761 */
1762static int selfVerificationLoad(int addr, int size)
1763{
1764assert(0); /* MIPSTODO retarg func */
1765    Thread *self = dvmThreadSelf();
1766    ShadowSpace *shadowSpace = self->shadowSpace;
1767    ShadowHeap *heapSpacePtr;
1768
1769    int data;
1770    int maskedAddr = addr & 0xFFFFFFFC;
1771    int alignment = addr & 0x3;
1772
1773    for (heapSpacePtr = shadowSpace->heapSpace;
1774         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
1775        if (heapSpacePtr->addr == maskedAddr) {
1776            addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
1777            break;
1778        }
1779    }
1780
1781    switch (size) {
1782        case kSVByte:
1783            data = *((u1*) addr);
1784            break;
1785        case kSVSignedByte:
1786            data = *((s1*) addr);
1787            break;
1788        case kSVHalfword:
1789            data = *((u2*) addr);
1790            break;
1791        case kSVSignedHalfword:
1792            data = *((s2*) addr);
1793            break;
1794        case kSVWord:
1795            data = *((u4*) addr);
1796            break;
1797        default:
1798            LOGE("*** ERROR: BAD SIZE IN selfVerificationLoad: %d", size);
1799            data = 0;
1800            dvmAbort();
1801    }
1802
1803    //LOGD("*** HEAP LOAD: Addr: %#x Data: %#x Size: %d", addr, data, size);
1804    return data;
1805}
1806
1807/* Like selfVerificationLoad, but specifically for doublewords */
1808static s8 selfVerificationLoadDoubleword(int addr)
1809{
1810assert(0); /* MIPSTODO retarg func */
1811    Thread *self = dvmThreadSelf();
1812    ShadowSpace* shadowSpace = self->shadowSpace;
1813    ShadowHeap* heapSpacePtr;
1814
1815    int addr2 = addr+4;
1816    unsigned int data = *((unsigned int*) addr);
1817    unsigned int data2 = *((unsigned int*) addr2);
1818
1819    for (heapSpacePtr = shadowSpace->heapSpace;
1820         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
1821        if (heapSpacePtr->addr == addr) {
1822            data = heapSpacePtr->data;
1823        } else if (heapSpacePtr->addr == addr2) {
1824            data2 = heapSpacePtr->data;
1825        }
1826    }
1827
1828    //LOGD("*** HEAP LOAD DOUBLEWORD: Addr: %#x Data: %#x Data2: %#x",
1829    //    addr, data, data2);
1830    return (((s8) data2) << 32) | data;
1831}
1832
1833/*
1834 * Handles a store of a specified size of data to a specified address.
1835 * This gets logged as an addr/data pair in heapSpace instead of modifying
1836 * memory.  Addresses in heapSpace are unique, and accesses smaller than a
1837 * word pull the entire word from memory first before updating.
1838 */
1839static void selfVerificationStore(int addr, int data, int size)
1840{
1841assert(0); /* MIPSTODO retarg func */
1842    Thread *self = dvmThreadSelf();
1843    ShadowSpace *shadowSpace = self->shadowSpace;
1844    ShadowHeap *heapSpacePtr;
1845
1846    int maskedAddr = addr & 0xFFFFFFFC;
1847    int alignment = addr & 0x3;
1848
1849    //LOGD("*** HEAP STORE: Addr: %#x Data: %#x Size: %d", addr, data, size);
1850
1851    for (heapSpacePtr = shadowSpace->heapSpace;
1852         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
1853        if (heapSpacePtr->addr == maskedAddr) break;
1854    }
1855
1856    if (heapSpacePtr == shadowSpace->heapSpaceTail) {
1857        heapSpacePtr->addr = maskedAddr;
1858        heapSpacePtr->data = *((unsigned int*) maskedAddr);
1859        shadowSpace->heapSpaceTail++;
1860    }
1861
1862    addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
1863    switch (size) {
1864        case kSVByte:
1865            *((u1*) addr) = data;
1866            break;
1867        case kSVSignedByte:
1868            *((s1*) addr) = data;
1869            break;
1870        case kSVHalfword:
1871            *((u2*) addr) = data;
1872            break;
1873        case kSVSignedHalfword:
1874            *((s2*) addr) = data;
1875            break;
1876        case kSVWord:
1877            *((u4*) addr) = data;
1878            break;
1879        default:
1880            LOGE("*** ERROR: BAD SIZE IN selfVerificationSave: %d", size);
1881            dvmAbort();
1882    }
1883}
1884
1885/* Like selfVerificationStore, but specifically for doublewords */
1886static void selfVerificationStoreDoubleword(int addr, s8 double_data)
1887{
1888assert(0); /* MIPSTODO retarg func */
1889    Thread *self = dvmThreadSelf();
1890    ShadowSpace *shadowSpace = self->shadowSpace;
1891    ShadowHeap *heapSpacePtr;
1892
1893    int addr2 = addr+4;
1894    int data = double_data;
1895    int data2 = double_data >> 32;
1896    bool store1 = false, store2 = false;
1897
1898    //LOGD("*** HEAP STORE DOUBLEWORD: Addr: %#x Data: %#x, Data2: %#x",
1899    //    addr, data, data2);
1900
1901    for (heapSpacePtr = shadowSpace->heapSpace;
1902         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
1903        if (heapSpacePtr->addr == addr) {
1904            heapSpacePtr->data = data;
1905            store1 = true;
1906        } else if (heapSpacePtr->addr == addr2) {
1907            heapSpacePtr->data = data2;
1908            store2 = true;
1909        }
1910    }
1911
1912    if (!store1) {
1913        shadowSpace->heapSpaceTail->addr = addr;
1914        shadowSpace->heapSpaceTail->data = data;
1915        shadowSpace->heapSpaceTail++;
1916    }
1917    if (!store2) {
1918        shadowSpace->heapSpaceTail->addr = addr2;
1919        shadowSpace->heapSpaceTail->data = data2;
1920        shadowSpace->heapSpaceTail++;
1921    }
1922}
1923
1924/*
1925 * Decodes the memory instruction at the address specified in the link
1926 * register. All registers (r0-r12,lr) and fp registers (d0-d15) are stored
1927 * consecutively on the stack beginning at the specified stack pointer.
1928 * Calls the proper Self Verification handler for the memory instruction and
1929 * updates the link register to point past the decoded memory instruction.
1930 */
1931void dvmSelfVerificationMemOpDecode(int lr, int* sp)
1932{
1933assert(0); /* MIPSTODO retarg func */
1934    enum {
1935        kMemOpLdrPcRel = 0x09, // ldr(3)  [01001] rd[10..8] imm_8[7..0]
1936        kMemOpRRR      = 0x0A, // Full opcode is 7 bits
1937        kMemOp2Single  = 0x0A, // Used for Vstrs and Vldrs
1938        kMemOpRRR2     = 0x0B, // Full opcode is 7 bits
1939        kMemOp2Double  = 0x0B, // Used for Vstrd and Vldrd
1940        kMemOpStrRRI5  = 0x0C, // str(1)  [01100] imm_5[10..6] rn[5..3] rd[2..0]
1941        kMemOpLdrRRI5  = 0x0D, // ldr(1)  [01101] imm_5[10..6] rn[5..3] rd[2..0]
1942        kMemOpStrbRRI5 = 0x0E, // strb(1) [01110] imm_5[10..6] rn[5..3] rd[2..0]
1943        kMemOpLdrbRRI5 = 0x0F, // ldrb(1) [01111] imm_5[10..6] rn[5..3] rd[2..0]
1944        kMemOpStrhRRI5 = 0x10, // strh(1) [10000] imm_5[10..6] rn[5..3] rd[2..0]
1945        kMemOpLdrhRRI5 = 0x11, // ldrh(1) [10001] imm_5[10..6] rn[5..3] rd[2..0]
1946        kMemOpLdrSpRel = 0x13, // ldr(4)  [10011] rd[10..8] imm_8[7..0]
1947        kMemOpStmia    = 0x18, // stmia   [11000] rn[10..8] reglist [7..0]
1948        kMemOpLdmia    = 0x19, // ldmia   [11001] rn[10..8] reglist [7..0]
1949        kMemOpStrRRR   = 0x28, // str(2)  [0101000] rm[8..6] rn[5..3] rd[2..0]
1950        kMemOpStrhRRR  = 0x29, // strh(2) [0101001] rm[8..6] rn[5..3] rd[2..0]
1951        kMemOpStrbRRR  = 0x2A, // strb(2) [0101010] rm[8..6] rn[5..3] rd[2..0]
1952        kMemOpLdrsbRRR = 0x2B, // ldrsb   [0101011] rm[8..6] rn[5..3] rd[2..0]
1953        kMemOpLdrRRR   = 0x2C, // ldr(2)  [0101100] rm[8..6] rn[5..3] rd[2..0]
1954        kMemOpLdrhRRR  = 0x2D, // ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0]
1955        kMemOpLdrbRRR  = 0x2E, // ldrb(2) [0101110] rm[8..6] rn[5..3] rd[2..0]
1956        kMemOpLdrshRRR = 0x2F, // ldrsh   [0101111] rm[8..6] rn[5..3] rd[2..0]
1957        kMemOp2Stmia   = 0xE88, // stmia  [111010001000[ rn[19..16] mask[15..0]
1958        kMemOp2Ldmia   = 0xE89, // ldmia  [111010001001[ rn[19..16] mask[15..0]
1959        kMemOp2Stmia2  = 0xE8A, // stmia  [111010001010[ rn[19..16] mask[15..0]
1960        kMemOp2Ldmia2  = 0xE8B, // ldmia  [111010001011[ rn[19..16] mask[15..0]
1961        kMemOp2Vstr    = 0xED8, // Used for Vstrs and Vstrd
1962        kMemOp2Vldr    = 0xED9, // Used for Vldrs and Vldrd
1963        kMemOp2Vstr2   = 0xEDC, // Used for Vstrs and Vstrd
1964        kMemOp2Vldr2   = 0xEDD, // Used for Vstrs and Vstrd
1965        kMemOp2StrbRRR = 0xF80, /* str rt,[rn,rm,LSL #imm] [111110000000]
1966                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1967        kMemOp2LdrbRRR = 0xF81, /* ldrb rt,[rn,rm,LSL #imm] [111110000001]
1968                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1969        kMemOp2StrhRRR = 0xF82, /* str rt,[rn,rm,LSL #imm] [111110000010]
1970                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1971        kMemOp2LdrhRRR = 0xF83, /* ldrh rt,[rn,rm,LSL #imm] [111110000011]
1972                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1973        kMemOp2StrRRR  = 0xF84, /* str rt,[rn,rm,LSL #imm] [111110000100]
1974                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1975        kMemOp2LdrRRR  = 0xF85, /* ldr rt,[rn,rm,LSL #imm] [111110000101]
1976                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1977        kMemOp2StrbRRI12 = 0xF88, /* strb rt,[rn,#imm12] [111110001000]
1978                                       rt[15..12] rn[19..16] imm12[11..0] */
1979        kMemOp2LdrbRRI12 = 0xF89, /* ldrb rt,[rn,#imm12] [111110001001]
1980                                       rt[15..12] rn[19..16] imm12[11..0] */
1981        kMemOp2StrhRRI12 = 0xF8A, /* strh rt,[rn,#imm12] [111110001010]
1982                                       rt[15..12] rn[19..16] imm12[11..0] */
1983        kMemOp2LdrhRRI12 = 0xF8B, /* ldrh rt,[rn,#imm12] [111110001011]
1984                                       rt[15..12] rn[19..16] imm12[11..0] */
1985        kMemOp2StrRRI12 = 0xF8C, /* str(Imm,T3) rd,[rn,#imm12] [111110001100]
1986                                       rn[19..16] rt[15..12] imm12[11..0] */
1987        kMemOp2LdrRRI12 = 0xF8D, /* ldr(Imm,T3) rd,[rn,#imm12] [111110001101]
1988                                       rn[19..16] rt[15..12] imm12[11..0] */
1989        kMemOp2LdrsbRRR = 0xF91, /* ldrsb rt,[rn,rm,LSL #imm] [111110010001]
1990                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1991        kMemOp2LdrshRRR = 0xF93, /* ldrsh rt,[rn,rm,LSL #imm] [111110010011]
1992                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1993        kMemOp2LdrsbRRI12 = 0xF99, /* ldrsb rt,[rn,#imm12] [111110011001]
1994                                       rt[15..12] rn[19..16] imm12[11..0] */
1995        kMemOp2LdrshRRI12 = 0xF9B, /* ldrsh rt,[rn,#imm12] [111110011011]
1996                                       rt[15..12] rn[19..16] imm12[11..0] */
1997        kMemOp2        = 0xE000, // top 3 bits set indicates Thumb2
1998    };
1999
2000    int addr, offset, data;
2001    long long double_data;
2002    int size = kSVWord;
2003    bool store = false;
2004    unsigned int *lr_masked = (unsigned int *) (lr & 0xFFFFFFFE);
2005    unsigned int insn = *lr_masked;
2006
2007    int old_lr;
2008    old_lr = selfVerificationMemRegLoad(sp, 13);
2009
2010    if ((insn & kMemOp2) == kMemOp2) {
2011        insn = (insn << 16) | (insn >> 16);
2012        //LOGD("*** THUMB2 - Addr: %#x Insn: %#x", lr, insn);
2013
2014        int opcode12 = (insn >> 20) & 0xFFF;
2015        int opcode6 = (insn >> 6) & 0x3F;
2016        int opcode4 = (insn >> 8) & 0xF;
2017        int imm2 = (insn >> 4) & 0x3;
2018        int imm8 = insn & 0xFF;
2019        int imm12 = insn & 0xFFF;
2020        int rd = (insn >> 12) & 0xF;
2021        int rm = insn & 0xF;
2022        int rn = (insn >> 16) & 0xF;
2023        int rt = (insn >> 12) & 0xF;
2024        bool wBack = true;
2025
2026        // Update the link register
2027        selfVerificationMemRegStore(sp, old_lr+4, 13);
2028
2029        // Determine whether the mem op is a store or load
2030        switch (opcode12) {
2031            case kMemOp2Stmia:
2032            case kMemOp2Stmia2:
2033            case kMemOp2Vstr:
2034            case kMemOp2Vstr2:
2035            case kMemOp2StrbRRR:
2036            case kMemOp2StrhRRR:
2037            case kMemOp2StrRRR:
2038            case kMemOp2StrbRRI12:
2039            case kMemOp2StrhRRI12:
2040            case kMemOp2StrRRI12:
2041                store = true;
2042        }
2043
2044        // Determine the size of the mem access
2045        switch (opcode12) {
2046            case kMemOp2StrbRRR:
2047            case kMemOp2LdrbRRR:
2048            case kMemOp2StrbRRI12:
2049            case kMemOp2LdrbRRI12:
2050                size = kSVByte;
2051                break;
2052            case kMemOp2LdrsbRRR:
2053            case kMemOp2LdrsbRRI12:
2054                size = kSVSignedByte;
2055                break;
2056            case kMemOp2StrhRRR:
2057            case kMemOp2LdrhRRR:
2058            case kMemOp2StrhRRI12:
2059            case kMemOp2LdrhRRI12:
2060                size = kSVHalfword;
2061                break;
2062            case kMemOp2LdrshRRR:
2063            case kMemOp2LdrshRRI12:
2064                size = kSVSignedHalfword;
2065                break;
2066            case kMemOp2Vstr:
2067            case kMemOp2Vstr2:
2068            case kMemOp2Vldr:
2069            case kMemOp2Vldr2:
2070                if (opcode4 == kMemOp2Double) size = kSVDoubleword;
2071                break;
2072            case kMemOp2Stmia:
2073            case kMemOp2Ldmia:
2074            case kMemOp2Stmia2:
2075            case kMemOp2Ldmia2:
2076                size = kSVVariable;
2077                break;
2078        }
2079
2080        // Load the value of the address
2081        addr = selfVerificationMemRegLoad(sp, rn);
2082
2083        // Figure out the offset
2084        switch (opcode12) {
2085            case kMemOp2Vstr:
2086            case kMemOp2Vstr2:
2087            case kMemOp2Vldr:
2088            case kMemOp2Vldr2:
2089                offset = imm8 << 2;
2090                if (opcode4 == kMemOp2Single) {
2091                    rt = rd << 1;
2092                    if (insn & 0x400000) rt |= 0x1;
2093                } else if (opcode4 == kMemOp2Double) {
2094                    if (insn & 0x400000) rt |= 0x10;
2095                    rt = rt << 1;
2096                } else {
2097                    LOGE("*** ERROR: UNRECOGNIZED VECTOR MEM OP: %x", opcode4);
2098                    dvmAbort();
2099                }
2100                rt += 14;
2101                break;
2102            case kMemOp2StrbRRR:
2103            case kMemOp2LdrbRRR:
2104            case kMemOp2StrhRRR:
2105            case kMemOp2LdrhRRR:
2106            case kMemOp2StrRRR:
2107            case kMemOp2LdrRRR:
2108            case kMemOp2LdrsbRRR:
2109            case kMemOp2LdrshRRR:
2110                offset = selfVerificationMemRegLoad(sp, rm) << imm2;
2111                break;
2112            case kMemOp2StrbRRI12:
2113            case kMemOp2LdrbRRI12:
2114            case kMemOp2StrhRRI12:
2115            case kMemOp2LdrhRRI12:
2116            case kMemOp2StrRRI12:
2117            case kMemOp2LdrRRI12:
2118            case kMemOp2LdrsbRRI12:
2119            case kMemOp2LdrshRRI12:
2120                offset = imm12;
2121                break;
2122            case kMemOp2Stmia:
2123            case kMemOp2Ldmia:
2124                wBack = false;
2125            case kMemOp2Stmia2:
2126            case kMemOp2Ldmia2:
2127                offset = 0;
2128                break;
2129            default:
2130                LOGE("*** ERROR: UNRECOGNIZED THUMB2 MEM OP: %x", opcode12);
2131                offset = 0;
2132                dvmAbort();
2133        }
2134
2135        // Handle the decoded mem op accordingly
2136        if (store) {
2137            if (size == kSVVariable) {
2138                LOGD("*** THUMB2 STMIA CURRENTLY UNUSED (AND UNTESTED)");
2139                int i;
2140                int regList = insn & 0xFFFF;
2141                for (i = 0; i < 16; i++) {
2142                    if (regList & 0x1) {
2143                        data = selfVerificationMemRegLoad(sp, i);
2144                        selfVerificationStore(addr, data, kSVWord);
2145                        addr += 4;
2146                    }
2147                    regList = regList >> 1;
2148                }
2149                if (wBack) selfVerificationMemRegStore(sp, addr, rn);
2150            } else if (size == kSVDoubleword) {
2151                double_data = selfVerificationMemRegLoadDouble(sp, rt);
2152                selfVerificationStoreDoubleword(addr+offset, double_data);
2153            } else {
2154                data = selfVerificationMemRegLoad(sp, rt);
2155                selfVerificationStore(addr+offset, data, size);
2156            }
2157        } else {
2158            if (size == kSVVariable) {
2159                LOGD("*** THUMB2 LDMIA CURRENTLY UNUSED (AND UNTESTED)");
2160                int i;
2161                int regList = insn & 0xFFFF;
2162                for (i = 0; i < 16; i++) {
2163                    if (regList & 0x1) {
2164                        data = selfVerificationLoad(addr, kSVWord);
2165                        selfVerificationMemRegStore(sp, data, i);
2166                        addr += 4;
2167                    }
2168                    regList = regList >> 1;
2169                }
2170                if (wBack) selfVerificationMemRegStore(sp, addr, rn);
2171            } else if (size == kSVDoubleword) {
2172                double_data = selfVerificationLoadDoubleword(addr+offset);
2173                selfVerificationMemRegStoreDouble(sp, double_data, rt);
2174            } else {
2175                data = selfVerificationLoad(addr+offset, size);
2176                selfVerificationMemRegStore(sp, data, rt);
2177            }
2178        }
2179    } else {
2180        //LOGD("*** THUMB - Addr: %#x Insn: %#x", lr, insn);
2181
2182        // Update the link register
2183        selfVerificationMemRegStore(sp, old_lr+2, 13);
2184
2185        int opcode5 = (insn >> 11) & 0x1F;
2186        int opcode7 = (insn >> 9) & 0x7F;
2187        int imm = (insn >> 6) & 0x1F;
2188        int rd = (insn >> 8) & 0x7;
2189        int rm = (insn >> 6) & 0x7;
2190        int rn = (insn >> 3) & 0x7;
2191        int rt = insn & 0x7;
2192
2193        // Determine whether the mem op is a store or load
2194        switch (opcode5) {
2195            case kMemOpRRR:
2196                switch (opcode7) {
2197                    case kMemOpStrRRR:
2198                    case kMemOpStrhRRR:
2199                    case kMemOpStrbRRR:
2200                        store = true;
2201                }
2202                break;
2203            case kMemOpStrRRI5:
2204            case kMemOpStrbRRI5:
2205            case kMemOpStrhRRI5:
2206            case kMemOpStmia:
2207                store = true;
2208        }
2209
2210        // Determine the size of the mem access
2211        switch (opcode5) {
2212            case kMemOpRRR:
2213            case kMemOpRRR2:
2214                switch (opcode7) {
2215                    case kMemOpStrbRRR:
2216                    case kMemOpLdrbRRR:
2217                        size = kSVByte;
2218                        break;
2219                    case kMemOpLdrsbRRR:
2220                        size = kSVSignedByte;
2221                        break;
2222                    case kMemOpStrhRRR:
2223                    case kMemOpLdrhRRR:
2224                        size = kSVHalfword;
2225                        break;
2226                    case kMemOpLdrshRRR:
2227                        size = kSVSignedHalfword;
2228                        break;
2229                }
2230                break;
2231            case kMemOpStrbRRI5:
2232            case kMemOpLdrbRRI5:
2233                size = kSVByte;
2234                break;
2235            case kMemOpStrhRRI5:
2236            case kMemOpLdrhRRI5:
2237                size = kSVHalfword;
2238                break;
2239            case kMemOpStmia:
2240            case kMemOpLdmia:
2241                size = kSVVariable;
2242                break;
2243        }
2244
2245        // Load the value of the address
2246        if (opcode5 == kMemOpLdrPcRel)
2247            addr = selfVerificationMemRegLoad(sp, 4);
2248        else if (opcode5 == kMemOpStmia || opcode5 == kMemOpLdmia)
2249            addr = selfVerificationMemRegLoad(sp, rd);
2250        else
2251            addr = selfVerificationMemRegLoad(sp, rn);
2252
2253        // Figure out the offset
2254        switch (opcode5) {
2255            case kMemOpLdrPcRel:
2256                offset = (insn & 0xFF) << 2;
2257                rt = rd;
2258                break;
2259            case kMemOpRRR:
2260            case kMemOpRRR2:
2261                offset = selfVerificationMemRegLoad(sp, rm);
2262                break;
2263            case kMemOpStrRRI5:
2264            case kMemOpLdrRRI5:
2265                offset = imm << 2;
2266                break;
2267            case kMemOpStrhRRI5:
2268            case kMemOpLdrhRRI5:
2269                offset = imm << 1;
2270                break;
2271            case kMemOpStrbRRI5:
2272            case kMemOpLdrbRRI5:
2273                offset = imm;
2274                break;
2275            case kMemOpStmia:
2276            case kMemOpLdmia:
2277                offset = 0;
2278                break;
2279            default:
2280                LOGE("*** ERROR: UNRECOGNIZED THUMB MEM OP: %x", opcode5);
2281                offset = 0;
2282                dvmAbort();
2283        }
2284
2285        // Handle the decoded mem op accordingly
2286        if (store) {
2287            if (size == kSVVariable) {
2288                int i;
2289                int regList = insn & 0xFF;
2290                for (i = 0; i < 8; i++) {
2291                    if (regList & 0x1) {
2292                        data = selfVerificationMemRegLoad(sp, i);
2293                        selfVerificationStore(addr, data, kSVWord);
2294                        addr += 4;
2295                    }
2296                    regList = regList >> 1;
2297                }
2298                selfVerificationMemRegStore(sp, addr, rd);
2299            } else {
2300                data = selfVerificationMemRegLoad(sp, rt);
2301                selfVerificationStore(addr+offset, data, size);
2302            }
2303        } else {
2304            if (size == kSVVariable) {
2305                bool wBack = true;
2306                int i;
2307                int regList = insn & 0xFF;
2308                for (i = 0; i < 8; i++) {
2309                    if (regList & 0x1) {
2310                        if (i == rd) wBack = false;
2311                        data = selfVerificationLoad(addr, kSVWord);
2312                        selfVerificationMemRegStore(sp, data, i);
2313                        addr += 4;
2314                    }
2315                    regList = regList >> 1;
2316                }
2317                if (wBack) selfVerificationMemRegStore(sp, addr, rd);
2318            } else {
2319                data = selfVerificationLoad(addr+offset, size);
2320                selfVerificationMemRegStore(sp, data, rt);
2321            }
2322        }
2323    }
2324}
2325#endif
2326