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                ALOGE("PC-rel distance is not multiple of 4: %d", delta);
459                dvmAbort();
460            }
461            if (delta > 131068 || delta < -131069) {
462                ALOGE("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                ALOGE("PC-rel distance is not multiple of 4: %d", delta);
473                dvmAbort();
474            }
475            if (delta > 131068 || delta < -131069) {
476                ALOGE("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                ALOGE("PC-rel distance is not multiple of 4: %d", delta);
487                dvmAbort();
488            }
489            if (delta > 131068 || delta < -131069) {
490                ALOGE("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                ALOGE("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                ALOGD("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        ALOGE("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             ALOGE("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            ALOGD("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            ALOGD("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            ALOGD("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    //ALOGD("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            ALOGD("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                    ALOGE("Unexpected chaining type: %d", i);
1301                    dvmAbort();  // dvmAbort OK here - can't safely recover
1302            }
1303            COMPILER_TRACE_CHAINING(
1304                ALOGD("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(ALOGD("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        UPDATE_CODE_CACHE_PATCHES();
1354
1355        PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1356
1357        dvmUnlockMutex(&gDvmJit.tableLock);
1358        gDvmJit.translationChains = 0;
1359    }
1360    gDvmJit.hasNewChain = false;
1361}
1362
1363typedef struct jitProfileAddrToLine {
1364    u4 lineNum;
1365    u4 bytecodeOffset;
1366} jitProfileAddrToLine;
1367
1368
1369/* Callback function to track the bytecode offset/line number relationiship */
1370static int addrToLineCb (void *cnxt, u4 bytecodeOffset, u4 lineNum)
1371{
1372    jitProfileAddrToLine *addrToLine = (jitProfileAddrToLine *) cnxt;
1373
1374    /* Best match so far for this offset */
1375    if (addrToLine->bytecodeOffset >= bytecodeOffset) {
1376        addrToLine->lineNum = lineNum;
1377    }
1378    return 0;
1379}
1380
1381/* Dumps profile info for a single trace */
1382static int dumpTraceProfile(JitEntry *p, bool silent, bool reset,
1383                            unsigned long sum)
1384{
1385    int idx;
1386
1387    if (p->codeAddress == NULL) {
1388        if (!silent)
1389            ALOGD("TRACEPROFILE NULL");
1390        return 0;
1391    }
1392    if (p->codeAddress == dvmCompilerGetInterpretTemplate()) {
1393        if (!silent)
1394            ALOGD("TRACEPROFILE INTERPRET_ONLY");
1395        return 0;
1396    }
1397
1398    JitTraceCounter_t count = getProfileCount(p);
1399    if (reset) {
1400        resetProfileCount(p);
1401    }
1402    if (silent) {
1403        return count;
1404    }
1405    JitTraceDescription *desc = getTraceDescriptionPointer(getTraceBase(p));
1406    const Method *method = desc->method;
1407    char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype);
1408    jitProfileAddrToLine addrToLine = {0, desc->trace[0].info.frag.startOffset};
1409
1410    /*
1411     * We may end up decoding the debug information for the same method
1412     * multiple times, but the tradeoff is we don't need to allocate extra
1413     * space to store the addr/line mapping. Since this is a debugging feature
1414     * and done infrequently so the slower but simpler mechanism should work
1415     * just fine.
1416     */
1417    dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile,
1418                       dvmGetMethodCode(method),
1419                       method->clazz->descriptor,
1420                       method->prototype.protoIdx,
1421                       method->accessFlags,
1422                       addrToLineCb, NULL, &addrToLine);
1423
1424    ALOGD("TRACEPROFILE 0x%08x % 10d %5.2f%% [%#x(+%d), %d] %s%s;%s",
1425         (int) getTraceBase(p),
1426         count,
1427         ((float ) count) / sum * 100.0,
1428         desc->trace[0].info.frag.startOffset,
1429         desc->trace[0].info.frag.numInsts,
1430         addrToLine.lineNum,
1431         method->clazz->descriptor, method->name, methodDesc);
1432    free(methodDesc);
1433
1434    /* Find the last fragment (ie runEnd is set) */
1435    for (idx = 0;
1436         desc->trace[idx].isCode && !desc->trace[idx].info.frag.runEnd;
1437         idx++) {
1438    }
1439
1440    /*
1441     * runEnd must comes with a JitCodeDesc frag. If isCode is false it must
1442     * be a meta info field (only used by callsite info for now).
1443     */
1444    if (!desc->trace[idx].isCode) {
1445        const Method *method = (const Method *)
1446            desc->trace[idx+JIT_TRACE_CUR_METHOD-1].info.meta;
1447        char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype);
1448        /* Print the callee info in the trace */
1449        ALOGD("    -> %s%s;%s", method->clazz->descriptor, method->name,
1450             methodDesc);
1451    }
1452
1453    return count;
1454}
1455
1456/* Create a copy of the trace descriptor of an existing compilation */
1457JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
1458                                            const JitEntry *knownEntry)
1459{
1460    const JitEntry *jitEntry = knownEntry ? knownEntry
1461                                          : dvmJitFindEntry(pc, false);
1462    if ((jitEntry == NULL) || (jitEntry->codeAddress == 0))
1463        return NULL;
1464
1465    JitTraceDescription *desc =
1466        getTraceDescriptionPointer(getTraceBase(jitEntry));
1467
1468    /* Now make a copy and return */
1469    int descSize = getTraceDescriptionSize(desc);
1470    JitTraceDescription *newCopy = (JitTraceDescription *) malloc(descSize);
1471    memcpy(newCopy, desc, descSize);
1472    return newCopy;
1473}
1474
1475/* qsort callback function */
1476static int sortTraceProfileCount(const void *entry1, const void *entry2)
1477{
1478    const JitEntry *jitEntry1 = (const JitEntry *)entry1;
1479    const JitEntry *jitEntry2 = (const JitEntry *)entry2;
1480
1481    JitTraceCounter_t count1 = getProfileCount(jitEntry1);
1482    JitTraceCounter_t count2 = getProfileCount(jitEntry2);
1483    return (count1 == count2) ? 0 : ((count1 > count2) ? -1 : 1);
1484}
1485
1486/* Sort the trace profile counts and dump them */
1487void dvmCompilerSortAndPrintTraceProfiles()
1488{
1489    JitEntry *sortedEntries;
1490    int numTraces = 0;
1491    unsigned long sum = 0;
1492    unsigned int i;
1493
1494    /* Make sure that the table is not changing */
1495    dvmLockMutex(&gDvmJit.tableLock);
1496
1497    /* Sort the entries by descending order */
1498    sortedEntries = (JitEntry *)malloc(sizeof(JitEntry) * gDvmJit.jitTableSize);
1499    if (sortedEntries == NULL)
1500        goto done;
1501    memcpy(sortedEntries, gDvmJit.pJitEntryTable,
1502           sizeof(JitEntry) * gDvmJit.jitTableSize);
1503    qsort(sortedEntries, gDvmJit.jitTableSize, sizeof(JitEntry),
1504          sortTraceProfileCount);
1505
1506    /* Analyze the sorted entries */
1507    for (i=0; i < gDvmJit.jitTableSize; i++) {
1508        if (sortedEntries[i].dPC != 0) {
1509            sum += dumpTraceProfile(&sortedEntries[i],
1510                                       true /* silent */,
1511                                       false /* reset */,
1512                                       0);
1513            numTraces++;
1514        }
1515    }
1516    if (numTraces == 0)
1517        numTraces = 1;
1518    if (sum == 0) {
1519        sum = 1;
1520    }
1521
1522    ALOGD("JIT: Average execution count -> %d",(int)(sum / numTraces));
1523
1524    /* Dump the sorted entries. The count of each trace will be reset to 0. */
1525    for (i=0; i < gDvmJit.jitTableSize; i++) {
1526        if (sortedEntries[i].dPC != 0) {
1527            dumpTraceProfile(&sortedEntries[i],
1528                             false /* silent */,
1529                             true /* reset */,
1530                             sum);
1531        }
1532    }
1533
1534    for (i=0; i < gDvmJit.jitTableSize && i < 10; i++) {
1535        /* Stip interpreter stubs */
1536        if (sortedEntries[i].codeAddress == dvmCompilerGetInterpretTemplate()) {
1537            continue;
1538        }
1539        JitTraceDescription* desc =
1540            dvmCopyTraceDescriptor(NULL, &sortedEntries[i]);
1541        if (desc) {
1542            dvmCompilerWorkEnqueue(sortedEntries[i].dPC,
1543                                   kWorkOrderTraceDebug, desc);
1544        }
1545    }
1546
1547    free(sortedEntries);
1548done:
1549    dvmUnlockMutex(&gDvmJit.tableLock);
1550    return;
1551}
1552
1553static void findClassPointersSingleTrace(char *base, void (*callback)(void *))
1554{
1555    unsigned int chainTypeIdx, chainIdx;
1556    ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base);
1557    int cellSize = getChainCellSize(pChainCellCounts);
1558    /* Scan the chaining cells */
1559    if (cellSize) {
1560        /* Locate the beginning of the chain cell region */
1561        u4 *pChainCells = ((u4 *) pChainCellCounts) - cellSize -
1562            pChainCellCounts->u.count[kChainingCellGap];
1563        /* The cells are sorted in order - walk through them */
1564        for (chainTypeIdx = 0; chainTypeIdx < kChainingCellGap;
1565             chainTypeIdx++) {
1566            if (chainTypeIdx != kChainingCellInvokePredicted) {
1567                /* In 32-bit words */
1568                pChainCells += (CHAIN_CELL_NORMAL_SIZE >> 2) *
1569                    pChainCellCounts->u.count[chainTypeIdx];
1570                continue;
1571            }
1572            for (chainIdx = 0;
1573                 chainIdx < pChainCellCounts->u.count[chainTypeIdx];
1574                 chainIdx++) {
1575                PredictedChainingCell *cell =
1576                    (PredictedChainingCell *) pChainCells;
1577                /*
1578                 * Report the cell if it contains a sane class
1579                 * pointer.
1580                 */
1581                if (cell->clazz != NULL &&
1582                    cell->clazz !=
1583                      (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ) {
1584                    callback(&cell->clazz);
1585                }
1586                pChainCells += CHAIN_CELL_PREDICTED_SIZE >> 2;
1587            }
1588        }
1589    }
1590
1591    /* Scan the class pointer pool */
1592    JitTraceDescription *desc = getTraceDescriptionPointer(base);
1593    int descSize = getTraceDescriptionSize(desc);
1594    int *classPointerP = (int *) ((char *) desc + descSize);
1595    int numClassPointers = *classPointerP++;
1596    for (; numClassPointers; numClassPointers--, classPointerP++) {
1597        callback(classPointerP);
1598    }
1599}
1600
1601/*
1602 * Scan class pointers in each translation and pass its address to the callback
1603 * function. Currently such a pointers can be found in the pointer pool and the
1604 * clazz field in the predicted chaining cells.
1605 */
1606void dvmJitScanAllClassPointers(void (*callback)(void *))
1607{
1608    UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1609
1610    /* Handle the inflight compilation first */
1611    if (gDvmJit.inflightBaseAddr)
1612        findClassPointersSingleTrace((char *) gDvmJit.inflightBaseAddr,
1613                                     callback);
1614
1615    if (gDvmJit.pJitEntryTable != NULL) {
1616        unsigned int traceIdx;
1617        dvmLockMutex(&gDvmJit.tableLock);
1618        for (traceIdx = 0; traceIdx < gDvmJit.jitTableSize; traceIdx++) {
1619            const JitEntry *entry = &gDvmJit.pJitEntryTable[traceIdx];
1620            if (entry->dPC &&
1621                !entry->u.info.isMethodEntry &&
1622                entry->codeAddress &&
1623                (entry->codeAddress != dvmCompilerGetInterpretTemplate())) {
1624                char *base = getTraceBase(entry);
1625                findClassPointersSingleTrace(base, callback);
1626            }
1627        }
1628        dvmUnlockMutex(&gDvmJit.tableLock);
1629    }
1630    UPDATE_CODE_CACHE_PATCHES();
1631
1632    PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1633}
1634
1635/*
1636 * Provide the final touch on the class object pointer pool to install the
1637 * actual pointers. The thread has to be in the running state.
1638 */
1639void dvmJitInstallClassObjectPointers(CompilationUnit *cUnit, char *codeAddress)
1640{
1641    char *base = codeAddress - cUnit->headerSize;
1642
1643    /* Scan the class pointer pool */
1644    JitTraceDescription *desc = getTraceDescriptionPointer(base);
1645    int descSize = getTraceDescriptionSize(desc);
1646    intptr_t *classPointerP = (int *) ((char *) desc + descSize);
1647    int numClassPointers = *(int *)classPointerP++;
1648    intptr_t *startClassPointerP = classPointerP;
1649
1650    /*
1651     * Change the thread state to VM_RUNNING so that GC won't be happening
1652     * when the assembler looks up the class pointers. May suspend the current
1653     * thread if there is a pending request before the state is actually
1654     * changed to RUNNING.
1655     */
1656    dvmChangeStatus(gDvmJit.compilerThread, THREAD_RUNNING);
1657
1658    /*
1659     * Unprotecting the code cache will need to acquire the code cache
1660     * protection lock first. Doing so after the state change may increase the
1661     * time spent in the RUNNING state (which may delay the next GC request
1662     * should there be contention on codeCacheProtectionLock). In practice
1663     * this is probably not going to happen often since a GC is just served.
1664     * More importantly, acquiring the lock before the state change will
1665     * cause deadlock (b/4192964).
1666     */
1667    UNPROTECT_CODE_CACHE(startClassPointerP,
1668                         numClassPointers * sizeof(intptr_t));
1669#if defined(WITH_JIT_TUNING)
1670    u8 startTime = dvmGetRelativeTimeUsec();
1671#endif
1672    for (;numClassPointers; numClassPointers--) {
1673        CallsiteInfo *callsiteInfo = (CallsiteInfo *) *classPointerP;
1674        ClassObject *clazz = dvmFindClassNoInit(
1675            callsiteInfo->classDescriptor, callsiteInfo->classLoader);
1676        assert(!strcmp(clazz->descriptor, callsiteInfo->classDescriptor));
1677        *classPointerP++ = (intptr_t) clazz;
1678    }
1679
1680    /*
1681     * Register the base address so that if GC kicks in after the thread state
1682     * has been changed to VMWAIT and before the compiled code is registered
1683     * in the JIT table, its content can be patched if class objects are
1684     * moved.
1685     */
1686    gDvmJit.inflightBaseAddr = base;
1687
1688#if defined(WITH_JIT_TUNING)
1689    u8 blockTime = dvmGetRelativeTimeUsec() - startTime;
1690    gDvmJit.compilerThreadBlockGCTime += blockTime;
1691    if (blockTime > gDvmJit.maxCompilerThreadBlockGCTime)
1692        gDvmJit.maxCompilerThreadBlockGCTime = blockTime;
1693    gDvmJit.numCompilerThreadBlockGC++;
1694#endif
1695    UPDATE_CODE_CACHE_PATCHES();
1696
1697    PROTECT_CODE_CACHE(startClassPointerP, numClassPointers * sizeof(intptr_t));
1698
1699    /* Change the thread state back to VMWAIT */
1700    dvmChangeStatus(gDvmJit.compilerThread, THREAD_VMWAIT);
1701}
1702
1703#if defined(WITH_SELF_VERIFICATION)
1704/*
1705 * The following are used to keep compiled loads and stores from modifying
1706 * memory during self verification mode.
1707 *
1708 * Stores do not modify memory. Instead, the address and value pair are stored
1709 * into heapSpace. Addresses within heapSpace are unique. For accesses smaller
1710 * than a word, the word containing the address is loaded first before being
1711 * updated.
1712 *
1713 * Loads check heapSpace first and return data from there if an entry exists.
1714 * Otherwise, data is loaded from memory as usual.
1715 */
1716
1717/* Used to specify sizes of memory operations */
1718enum {
1719    kSVByte,
1720    kSVSignedByte,
1721    kSVHalfword,
1722    kSVSignedHalfword,
1723    kSVWord,
1724    kSVDoubleword,
1725    kSVVariable,
1726};
1727
1728/* Load the value of a decoded register from the stack */
1729static int selfVerificationMemRegLoad(int* sp, int reg)
1730{
1731assert(0); /* MIPSTODO retarg func */
1732    return *(sp + reg);
1733}
1734
1735/* Load the value of a decoded doubleword register from the stack */
1736static s8 selfVerificationMemRegLoadDouble(int* sp, int reg)
1737{
1738assert(0); /* MIPSTODO retarg func */
1739    return *((s8*)(sp + reg));
1740}
1741
1742/* Store the value of a decoded register out to the stack */
1743static void selfVerificationMemRegStore(int* sp, int data, int reg)
1744{
1745assert(0); /* MIPSTODO retarg func */
1746    *(sp + reg) = data;
1747}
1748
1749/* Store the value of a decoded doubleword register out to the stack */
1750static void selfVerificationMemRegStoreDouble(int* sp, s8 data, int reg)
1751{
1752assert(0); /* MIPSTODO retarg func */
1753    *((s8*)(sp + reg)) = data;
1754}
1755
1756/*
1757 * Load the specified size of data from the specified address, checking
1758 * heapSpace first if Self Verification mode wrote to it previously, and
1759 * falling back to actual memory otherwise.
1760 */
1761static int selfVerificationLoad(int addr, int size)
1762{
1763assert(0); /* MIPSTODO retarg func */
1764    Thread *self = dvmThreadSelf();
1765    ShadowSpace *shadowSpace = self->shadowSpace;
1766    ShadowHeap *heapSpacePtr;
1767
1768    int data;
1769    int maskedAddr = addr & 0xFFFFFFFC;
1770    int alignment = addr & 0x3;
1771
1772    for (heapSpacePtr = shadowSpace->heapSpace;
1773         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
1774        if (heapSpacePtr->addr == maskedAddr) {
1775            addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
1776            break;
1777        }
1778    }
1779
1780    switch (size) {
1781        case kSVByte:
1782            data = *((u1*) addr);
1783            break;
1784        case kSVSignedByte:
1785            data = *((s1*) addr);
1786            break;
1787        case kSVHalfword:
1788            data = *((u2*) addr);
1789            break;
1790        case kSVSignedHalfword:
1791            data = *((s2*) addr);
1792            break;
1793        case kSVWord:
1794            data = *((u4*) addr);
1795            break;
1796        default:
1797            ALOGE("*** ERROR: BAD SIZE IN selfVerificationLoad: %d", size);
1798            data = 0;
1799            dvmAbort();
1800    }
1801
1802    //ALOGD("*** HEAP LOAD: Addr: %#x Data: %#x Size: %d", addr, data, size);
1803    return data;
1804}
1805
1806/* Like selfVerificationLoad, but specifically for doublewords */
1807static s8 selfVerificationLoadDoubleword(int addr)
1808{
1809assert(0); /* MIPSTODO retarg func */
1810    Thread *self = dvmThreadSelf();
1811    ShadowSpace* shadowSpace = self->shadowSpace;
1812    ShadowHeap* heapSpacePtr;
1813
1814    int addr2 = addr+4;
1815    unsigned int data = *((unsigned int*) addr);
1816    unsigned int data2 = *((unsigned int*) addr2);
1817
1818    for (heapSpacePtr = shadowSpace->heapSpace;
1819         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
1820        if (heapSpacePtr->addr == addr) {
1821            data = heapSpacePtr->data;
1822        } else if (heapSpacePtr->addr == addr2) {
1823            data2 = heapSpacePtr->data;
1824        }
1825    }
1826
1827    //ALOGD("*** HEAP LOAD DOUBLEWORD: Addr: %#x Data: %#x Data2: %#x",
1828    //    addr, data, data2);
1829    return (((s8) data2) << 32) | data;
1830}
1831
1832/*
1833 * Handles a store of a specified size of data to a specified address.
1834 * This gets logged as an addr/data pair in heapSpace instead of modifying
1835 * memory.  Addresses in heapSpace are unique, and accesses smaller than a
1836 * word pull the entire word from memory first before updating.
1837 */
1838static void selfVerificationStore(int addr, int data, int size)
1839{
1840assert(0); /* MIPSTODO retarg func */
1841    Thread *self = dvmThreadSelf();
1842    ShadowSpace *shadowSpace = self->shadowSpace;
1843    ShadowHeap *heapSpacePtr;
1844
1845    int maskedAddr = addr & 0xFFFFFFFC;
1846    int alignment = addr & 0x3;
1847
1848    //ALOGD("*** HEAP STORE: Addr: %#x Data: %#x Size: %d", addr, data, size);
1849
1850    for (heapSpacePtr = shadowSpace->heapSpace;
1851         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
1852        if (heapSpacePtr->addr == maskedAddr) break;
1853    }
1854
1855    if (heapSpacePtr == shadowSpace->heapSpaceTail) {
1856        heapSpacePtr->addr = maskedAddr;
1857        heapSpacePtr->data = *((unsigned int*) maskedAddr);
1858        shadowSpace->heapSpaceTail++;
1859    }
1860
1861    addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
1862    switch (size) {
1863        case kSVByte:
1864            *((u1*) addr) = data;
1865            break;
1866        case kSVSignedByte:
1867            *((s1*) addr) = data;
1868            break;
1869        case kSVHalfword:
1870            *((u2*) addr) = data;
1871            break;
1872        case kSVSignedHalfword:
1873            *((s2*) addr) = data;
1874            break;
1875        case kSVWord:
1876            *((u4*) addr) = data;
1877            break;
1878        default:
1879            ALOGE("*** ERROR: BAD SIZE IN selfVerificationSave: %d", size);
1880            dvmAbort();
1881    }
1882}
1883
1884/* Like selfVerificationStore, but specifically for doublewords */
1885static void selfVerificationStoreDoubleword(int addr, s8 double_data)
1886{
1887assert(0); /* MIPSTODO retarg func */
1888    Thread *self = dvmThreadSelf();
1889    ShadowSpace *shadowSpace = self->shadowSpace;
1890    ShadowHeap *heapSpacePtr;
1891
1892    int addr2 = addr+4;
1893    int data = double_data;
1894    int data2 = double_data >> 32;
1895    bool store1 = false, store2 = false;
1896
1897    //ALOGD("*** HEAP STORE DOUBLEWORD: Addr: %#x Data: %#x, Data2: %#x",
1898    //    addr, data, data2);
1899
1900    for (heapSpacePtr = shadowSpace->heapSpace;
1901         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
1902        if (heapSpacePtr->addr == addr) {
1903            heapSpacePtr->data = data;
1904            store1 = true;
1905        } else if (heapSpacePtr->addr == addr2) {
1906            heapSpacePtr->data = data2;
1907            store2 = true;
1908        }
1909    }
1910
1911    if (!store1) {
1912        shadowSpace->heapSpaceTail->addr = addr;
1913        shadowSpace->heapSpaceTail->data = data;
1914        shadowSpace->heapSpaceTail++;
1915    }
1916    if (!store2) {
1917        shadowSpace->heapSpaceTail->addr = addr2;
1918        shadowSpace->heapSpaceTail->data = data2;
1919        shadowSpace->heapSpaceTail++;
1920    }
1921}
1922
1923/*
1924 * Decodes the memory instruction at the address specified in the link
1925 * register. All registers (r0-r12,lr) and fp registers (d0-d15) are stored
1926 * consecutively on the stack beginning at the specified stack pointer.
1927 * Calls the proper Self Verification handler for the memory instruction and
1928 * updates the link register to point past the decoded memory instruction.
1929 */
1930void dvmSelfVerificationMemOpDecode(int lr, int* sp)
1931{
1932assert(0); /* MIPSTODO retarg func */
1933    enum {
1934        kMemOpLdrPcRel = 0x09, // ldr(3)  [01001] rd[10..8] imm_8[7..0]
1935        kMemOpRRR      = 0x0A, // Full opcode is 7 bits
1936        kMemOp2Single  = 0x0A, // Used for Vstrs and Vldrs
1937        kMemOpRRR2     = 0x0B, // Full opcode is 7 bits
1938        kMemOp2Double  = 0x0B, // Used for Vstrd and Vldrd
1939        kMemOpStrRRI5  = 0x0C, // str(1)  [01100] imm_5[10..6] rn[5..3] rd[2..0]
1940        kMemOpLdrRRI5  = 0x0D, // ldr(1)  [01101] imm_5[10..6] rn[5..3] rd[2..0]
1941        kMemOpStrbRRI5 = 0x0E, // strb(1) [01110] imm_5[10..6] rn[5..3] rd[2..0]
1942        kMemOpLdrbRRI5 = 0x0F, // ldrb(1) [01111] imm_5[10..6] rn[5..3] rd[2..0]
1943        kMemOpStrhRRI5 = 0x10, // strh(1) [10000] imm_5[10..6] rn[5..3] rd[2..0]
1944        kMemOpLdrhRRI5 = 0x11, // ldrh(1) [10001] imm_5[10..6] rn[5..3] rd[2..0]
1945        kMemOpLdrSpRel = 0x13, // ldr(4)  [10011] rd[10..8] imm_8[7..0]
1946        kMemOpStmia    = 0x18, // stmia   [11000] rn[10..8] reglist [7..0]
1947        kMemOpLdmia    = 0x19, // ldmia   [11001] rn[10..8] reglist [7..0]
1948        kMemOpStrRRR   = 0x28, // str(2)  [0101000] rm[8..6] rn[5..3] rd[2..0]
1949        kMemOpStrhRRR  = 0x29, // strh(2) [0101001] rm[8..6] rn[5..3] rd[2..0]
1950        kMemOpStrbRRR  = 0x2A, // strb(2) [0101010] rm[8..6] rn[5..3] rd[2..0]
1951        kMemOpLdrsbRRR = 0x2B, // ldrsb   [0101011] rm[8..6] rn[5..3] rd[2..0]
1952        kMemOpLdrRRR   = 0x2C, // ldr(2)  [0101100] rm[8..6] rn[5..3] rd[2..0]
1953        kMemOpLdrhRRR  = 0x2D, // ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0]
1954        kMemOpLdrbRRR  = 0x2E, // ldrb(2) [0101110] rm[8..6] rn[5..3] rd[2..0]
1955        kMemOpLdrshRRR = 0x2F, // ldrsh   [0101111] rm[8..6] rn[5..3] rd[2..0]
1956        kMemOp2Stmia   = 0xE88, // stmia  [111010001000[ rn[19..16] mask[15..0]
1957        kMemOp2Ldmia   = 0xE89, // ldmia  [111010001001[ rn[19..16] mask[15..0]
1958        kMemOp2Stmia2  = 0xE8A, // stmia  [111010001010[ rn[19..16] mask[15..0]
1959        kMemOp2Ldmia2  = 0xE8B, // ldmia  [111010001011[ rn[19..16] mask[15..0]
1960        kMemOp2Vstr    = 0xED8, // Used for Vstrs and Vstrd
1961        kMemOp2Vldr    = 0xED9, // Used for Vldrs and Vldrd
1962        kMemOp2Vstr2   = 0xEDC, // Used for Vstrs and Vstrd
1963        kMemOp2Vldr2   = 0xEDD, // Used for Vstrs and Vstrd
1964        kMemOp2StrbRRR = 0xF80, /* str rt,[rn,rm,LSL #imm] [111110000000]
1965                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1966        kMemOp2LdrbRRR = 0xF81, /* ldrb rt,[rn,rm,LSL #imm] [111110000001]
1967                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1968        kMemOp2StrhRRR = 0xF82, /* str rt,[rn,rm,LSL #imm] [111110000010]
1969                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1970        kMemOp2LdrhRRR = 0xF83, /* ldrh rt,[rn,rm,LSL #imm] [111110000011]
1971                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1972        kMemOp2StrRRR  = 0xF84, /* str rt,[rn,rm,LSL #imm] [111110000100]
1973                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1974        kMemOp2LdrRRR  = 0xF85, /* ldr rt,[rn,rm,LSL #imm] [111110000101]
1975                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1976        kMemOp2StrbRRI12 = 0xF88, /* strb rt,[rn,#imm12] [111110001000]
1977                                       rt[15..12] rn[19..16] imm12[11..0] */
1978        kMemOp2LdrbRRI12 = 0xF89, /* ldrb rt,[rn,#imm12] [111110001001]
1979                                       rt[15..12] rn[19..16] imm12[11..0] */
1980        kMemOp2StrhRRI12 = 0xF8A, /* strh rt,[rn,#imm12] [111110001010]
1981                                       rt[15..12] rn[19..16] imm12[11..0] */
1982        kMemOp2LdrhRRI12 = 0xF8B, /* ldrh rt,[rn,#imm12] [111110001011]
1983                                       rt[15..12] rn[19..16] imm12[11..0] */
1984        kMemOp2StrRRI12 = 0xF8C, /* str(Imm,T3) rd,[rn,#imm12] [111110001100]
1985                                       rn[19..16] rt[15..12] imm12[11..0] */
1986        kMemOp2LdrRRI12 = 0xF8D, /* ldr(Imm,T3) rd,[rn,#imm12] [111110001101]
1987                                       rn[19..16] rt[15..12] imm12[11..0] */
1988        kMemOp2LdrsbRRR = 0xF91, /* ldrsb rt,[rn,rm,LSL #imm] [111110010001]
1989                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1990        kMemOp2LdrshRRR = 0xF93, /* ldrsh rt,[rn,rm,LSL #imm] [111110010011]
1991                                rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
1992        kMemOp2LdrsbRRI12 = 0xF99, /* ldrsb rt,[rn,#imm12] [111110011001]
1993                                       rt[15..12] rn[19..16] imm12[11..0] */
1994        kMemOp2LdrshRRI12 = 0xF9B, /* ldrsh rt,[rn,#imm12] [111110011011]
1995                                       rt[15..12] rn[19..16] imm12[11..0] */
1996        kMemOp2        = 0xE000, // top 3 bits set indicates Thumb2
1997    };
1998
1999    int addr, offset, data;
2000    long long double_data;
2001    int size = kSVWord;
2002    bool store = false;
2003    unsigned int *lr_masked = (unsigned int *) (lr & 0xFFFFFFFE);
2004    unsigned int insn = *lr_masked;
2005
2006    int old_lr;
2007    old_lr = selfVerificationMemRegLoad(sp, 13);
2008
2009    if ((insn & kMemOp2) == kMemOp2) {
2010        insn = (insn << 16) | (insn >> 16);
2011        //ALOGD("*** THUMB2 - Addr: %#x Insn: %#x", lr, insn);
2012
2013        int opcode12 = (insn >> 20) & 0xFFF;
2014        int opcode6 = (insn >> 6) & 0x3F;
2015        int opcode4 = (insn >> 8) & 0xF;
2016        int imm2 = (insn >> 4) & 0x3;
2017        int imm8 = insn & 0xFF;
2018        int imm12 = insn & 0xFFF;
2019        int rd = (insn >> 12) & 0xF;
2020        int rm = insn & 0xF;
2021        int rn = (insn >> 16) & 0xF;
2022        int rt = (insn >> 12) & 0xF;
2023        bool wBack = true;
2024
2025        // Update the link register
2026        selfVerificationMemRegStore(sp, old_lr+4, 13);
2027
2028        // Determine whether the mem op is a store or load
2029        switch (opcode12) {
2030            case kMemOp2Stmia:
2031            case kMemOp2Stmia2:
2032            case kMemOp2Vstr:
2033            case kMemOp2Vstr2:
2034            case kMemOp2StrbRRR:
2035            case kMemOp2StrhRRR:
2036            case kMemOp2StrRRR:
2037            case kMemOp2StrbRRI12:
2038            case kMemOp2StrhRRI12:
2039            case kMemOp2StrRRI12:
2040                store = true;
2041        }
2042
2043        // Determine the size of the mem access
2044        switch (opcode12) {
2045            case kMemOp2StrbRRR:
2046            case kMemOp2LdrbRRR:
2047            case kMemOp2StrbRRI12:
2048            case kMemOp2LdrbRRI12:
2049                size = kSVByte;
2050                break;
2051            case kMemOp2LdrsbRRR:
2052            case kMemOp2LdrsbRRI12:
2053                size = kSVSignedByte;
2054                break;
2055            case kMemOp2StrhRRR:
2056            case kMemOp2LdrhRRR:
2057            case kMemOp2StrhRRI12:
2058            case kMemOp2LdrhRRI12:
2059                size = kSVHalfword;
2060                break;
2061            case kMemOp2LdrshRRR:
2062            case kMemOp2LdrshRRI12:
2063                size = kSVSignedHalfword;
2064                break;
2065            case kMemOp2Vstr:
2066            case kMemOp2Vstr2:
2067            case kMemOp2Vldr:
2068            case kMemOp2Vldr2:
2069                if (opcode4 == kMemOp2Double) size = kSVDoubleword;
2070                break;
2071            case kMemOp2Stmia:
2072            case kMemOp2Ldmia:
2073            case kMemOp2Stmia2:
2074            case kMemOp2Ldmia2:
2075                size = kSVVariable;
2076                break;
2077        }
2078
2079        // Load the value of the address
2080        addr = selfVerificationMemRegLoad(sp, rn);
2081
2082        // Figure out the offset
2083        switch (opcode12) {
2084            case kMemOp2Vstr:
2085            case kMemOp2Vstr2:
2086            case kMemOp2Vldr:
2087            case kMemOp2Vldr2:
2088                offset = imm8 << 2;
2089                if (opcode4 == kMemOp2Single) {
2090                    rt = rd << 1;
2091                    if (insn & 0x400000) rt |= 0x1;
2092                } else if (opcode4 == kMemOp2Double) {
2093                    if (insn & 0x400000) rt |= 0x10;
2094                    rt = rt << 1;
2095                } else {
2096                    ALOGE("*** ERROR: UNRECOGNIZED VECTOR MEM OP: %x", opcode4);
2097                    dvmAbort();
2098                }
2099                rt += 14;
2100                break;
2101            case kMemOp2StrbRRR:
2102            case kMemOp2LdrbRRR:
2103            case kMemOp2StrhRRR:
2104            case kMemOp2LdrhRRR:
2105            case kMemOp2StrRRR:
2106            case kMemOp2LdrRRR:
2107            case kMemOp2LdrsbRRR:
2108            case kMemOp2LdrshRRR:
2109                offset = selfVerificationMemRegLoad(sp, rm) << imm2;
2110                break;
2111            case kMemOp2StrbRRI12:
2112            case kMemOp2LdrbRRI12:
2113            case kMemOp2StrhRRI12:
2114            case kMemOp2LdrhRRI12:
2115            case kMemOp2StrRRI12:
2116            case kMemOp2LdrRRI12:
2117            case kMemOp2LdrsbRRI12:
2118            case kMemOp2LdrshRRI12:
2119                offset = imm12;
2120                break;
2121            case kMemOp2Stmia:
2122            case kMemOp2Ldmia:
2123                wBack = false;
2124            case kMemOp2Stmia2:
2125            case kMemOp2Ldmia2:
2126                offset = 0;
2127                break;
2128            default:
2129                ALOGE("*** ERROR: UNRECOGNIZED THUMB2 MEM OP: %x", opcode12);
2130                offset = 0;
2131                dvmAbort();
2132        }
2133
2134        // Handle the decoded mem op accordingly
2135        if (store) {
2136            if (size == kSVVariable) {
2137                ALOGD("*** THUMB2 STMIA CURRENTLY UNUSED (AND UNTESTED)");
2138                int i;
2139                int regList = insn & 0xFFFF;
2140                for (i = 0; i < 16; i++) {
2141                    if (regList & 0x1) {
2142                        data = selfVerificationMemRegLoad(sp, i);
2143                        selfVerificationStore(addr, data, kSVWord);
2144                        addr += 4;
2145                    }
2146                    regList = regList >> 1;
2147                }
2148                if (wBack) selfVerificationMemRegStore(sp, addr, rn);
2149            } else if (size == kSVDoubleword) {
2150                double_data = selfVerificationMemRegLoadDouble(sp, rt);
2151                selfVerificationStoreDoubleword(addr+offset, double_data);
2152            } else {
2153                data = selfVerificationMemRegLoad(sp, rt);
2154                selfVerificationStore(addr+offset, data, size);
2155            }
2156        } else {
2157            if (size == kSVVariable) {
2158                ALOGD("*** THUMB2 LDMIA CURRENTLY UNUSED (AND UNTESTED)");
2159                int i;
2160                int regList = insn & 0xFFFF;
2161                for (i = 0; i < 16; i++) {
2162                    if (regList & 0x1) {
2163                        data = selfVerificationLoad(addr, kSVWord);
2164                        selfVerificationMemRegStore(sp, data, i);
2165                        addr += 4;
2166                    }
2167                    regList = regList >> 1;
2168                }
2169                if (wBack) selfVerificationMemRegStore(sp, addr, rn);
2170            } else if (size == kSVDoubleword) {
2171                double_data = selfVerificationLoadDoubleword(addr+offset);
2172                selfVerificationMemRegStoreDouble(sp, double_data, rt);
2173            } else {
2174                data = selfVerificationLoad(addr+offset, size);
2175                selfVerificationMemRegStore(sp, data, rt);
2176            }
2177        }
2178    } else {
2179        //ALOGD("*** THUMB - Addr: %#x Insn: %#x", lr, insn);
2180
2181        // Update the link register
2182        selfVerificationMemRegStore(sp, old_lr+2, 13);
2183
2184        int opcode5 = (insn >> 11) & 0x1F;
2185        int opcode7 = (insn >> 9) & 0x7F;
2186        int imm = (insn >> 6) & 0x1F;
2187        int rd = (insn >> 8) & 0x7;
2188        int rm = (insn >> 6) & 0x7;
2189        int rn = (insn >> 3) & 0x7;
2190        int rt = insn & 0x7;
2191
2192        // Determine whether the mem op is a store or load
2193        switch (opcode5) {
2194            case kMemOpRRR:
2195                switch (opcode7) {
2196                    case kMemOpStrRRR:
2197                    case kMemOpStrhRRR:
2198                    case kMemOpStrbRRR:
2199                        store = true;
2200                }
2201                break;
2202            case kMemOpStrRRI5:
2203            case kMemOpStrbRRI5:
2204            case kMemOpStrhRRI5:
2205            case kMemOpStmia:
2206                store = true;
2207        }
2208
2209        // Determine the size of the mem access
2210        switch (opcode5) {
2211            case kMemOpRRR:
2212            case kMemOpRRR2:
2213                switch (opcode7) {
2214                    case kMemOpStrbRRR:
2215                    case kMemOpLdrbRRR:
2216                        size = kSVByte;
2217                        break;
2218                    case kMemOpLdrsbRRR:
2219                        size = kSVSignedByte;
2220                        break;
2221                    case kMemOpStrhRRR:
2222                    case kMemOpLdrhRRR:
2223                        size = kSVHalfword;
2224                        break;
2225                    case kMemOpLdrshRRR:
2226                        size = kSVSignedHalfword;
2227                        break;
2228                }
2229                break;
2230            case kMemOpStrbRRI5:
2231            case kMemOpLdrbRRI5:
2232                size = kSVByte;
2233                break;
2234            case kMemOpStrhRRI5:
2235            case kMemOpLdrhRRI5:
2236                size = kSVHalfword;
2237                break;
2238            case kMemOpStmia:
2239            case kMemOpLdmia:
2240                size = kSVVariable;
2241                break;
2242        }
2243
2244        // Load the value of the address
2245        if (opcode5 == kMemOpLdrPcRel)
2246            addr = selfVerificationMemRegLoad(sp, 4);
2247        else if (opcode5 == kMemOpStmia || opcode5 == kMemOpLdmia)
2248            addr = selfVerificationMemRegLoad(sp, rd);
2249        else
2250            addr = selfVerificationMemRegLoad(sp, rn);
2251
2252        // Figure out the offset
2253        switch (opcode5) {
2254            case kMemOpLdrPcRel:
2255                offset = (insn & 0xFF) << 2;
2256                rt = rd;
2257                break;
2258            case kMemOpRRR:
2259            case kMemOpRRR2:
2260                offset = selfVerificationMemRegLoad(sp, rm);
2261                break;
2262            case kMemOpStrRRI5:
2263            case kMemOpLdrRRI5:
2264                offset = imm << 2;
2265                break;
2266            case kMemOpStrhRRI5:
2267            case kMemOpLdrhRRI5:
2268                offset = imm << 1;
2269                break;
2270            case kMemOpStrbRRI5:
2271            case kMemOpLdrbRRI5:
2272                offset = imm;
2273                break;
2274            case kMemOpStmia:
2275            case kMemOpLdmia:
2276                offset = 0;
2277                break;
2278            default:
2279                ALOGE("*** ERROR: UNRECOGNIZED THUMB MEM OP: %x", opcode5);
2280                offset = 0;
2281                dvmAbort();
2282        }
2283
2284        // Handle the decoded mem op accordingly
2285        if (store) {
2286            if (size == kSVVariable) {
2287                int i;
2288                int regList = insn & 0xFF;
2289                for (i = 0; i < 8; i++) {
2290                    if (regList & 0x1) {
2291                        data = selfVerificationMemRegLoad(sp, i);
2292                        selfVerificationStore(addr, data, kSVWord);
2293                        addr += 4;
2294                    }
2295                    regList = regList >> 1;
2296                }
2297                selfVerificationMemRegStore(sp, addr, rd);
2298            } else {
2299                data = selfVerificationMemRegLoad(sp, rt);
2300                selfVerificationStore(addr+offset, data, size);
2301            }
2302        } else {
2303            if (size == kSVVariable) {
2304                bool wBack = true;
2305                int i;
2306                int regList = insn & 0xFF;
2307                for (i = 0; i < 8; i++) {
2308                    if (regList & 0x1) {
2309                        if (i == rd) wBack = false;
2310                        data = selfVerificationLoad(addr, kSVWord);
2311                        selfVerificationMemRegStore(sp, data, i);
2312                        addr += 4;
2313                    }
2314                    regList = regList >> 1;
2315                }
2316                if (wBack) selfVerificationMemRegStore(sp, addr, rd);
2317            } else {
2318                data = selfVerificationLoad(addr+offset, size);
2319                selfVerificationMemRegStore(sp, data, rt);
2320            }
2321        }
2322    }
2323}
2324#endif
2325