OSDN Git Service

Dalvik fast interpreter support and JIT implementation
[android-x86/dalvik.git] / vm / compiler / codegen / mips / Assemble.cpp
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 */
80 MipsEncodingMap 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 */
409 static 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  */
436 static AssemblerStatus assembleInstructions(CompilationUnit *cUnit,
437                                             intptr_t startAddr)
438 {
439     int *bufferAddr = (int *) cUnit->codeBuffer;
440     MipsLIR *lir;
441
442     for (lir = (MipsLIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
443         if (lir->opcode < 0) {
444             continue;
445         }
446
447
448         if (lir->flags.isNop) {
449             continue;
450         }
451
452         if (lir->opcode == kMipsB || lir->opcode == kMipsBal) {
453             MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
454             intptr_t pc = lir->generic.offset + 4;
455             intptr_t target = targetLIR->generic.offset;
456             int delta = target - pc;
457             if (delta & 0x3) {
458                 LOGE("PC-rel distance is not multiple of 4: %d", delta);
459                 dvmAbort();
460             }
461             if (delta > 131068 || delta < -131069) {
462                 LOGE("Unconditional branch distance out of range: %d", delta);
463                 dvmAbort();
464             }
465             lir->operands[0] = delta >> 2;
466         } else if (lir->opcode >= kMipsBeqz && lir->opcode <= kMipsBnez) {
467             MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
468             intptr_t pc = lir->generic.offset + 4;
469             intptr_t target = targetLIR->generic.offset;
470             int delta = target - pc;
471             if (delta & 0x3) {
472                 LOGE("PC-rel distance is not multiple of 4: %d", delta);
473                 dvmAbort();
474             }
475             if (delta > 131068 || delta < -131069) {
476                 LOGE("Conditional branch distance out of range: %d", delta);
477                 dvmAbort();
478             }
479             lir->operands[1] = delta >> 2;
480         } else if (lir->opcode == kMipsBeq || lir->opcode == kMipsBne) {
481             MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
482             intptr_t pc = lir->generic.offset + 4;
483             intptr_t target = targetLIR->generic.offset;
484             int delta = target - pc;
485             if (delta & 0x3) {
486                 LOGE("PC-rel distance is not multiple of 4: %d", delta);
487                 dvmAbort();
488             }
489             if (delta > 131068 || delta < -131069) {
490                 LOGE("Conditional branch distance out of range: %d", delta);
491                 dvmAbort();
492             }
493             lir->operands[2] = delta >> 2;
494         } else if (lir->opcode == kMipsJal) {
495             intptr_t curPC = (startAddr + lir->generic.offset + 4) & ~3;
496             intptr_t target = lir->operands[0];
497             /* ensure PC-region branch can be used */
498             assert((curPC & 0xF0000000) == (target & 0xF0000000));
499             if (target & 0x3) {
500                 LOGE("Jump target is not multiple of 4: %d", target);
501                 dvmAbort();
502             }
503             lir->operands[0] =  target >> 2;
504         } else if (lir->opcode == kMipsLahi) { /* load address hi (via lui) */
505             MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
506             intptr_t target = startAddr + targetLIR->generic.offset;
507             lir->operands[1] = target >> 16;
508         } else if (lir->opcode == kMipsLalo) { /* load address lo (via ori) */
509             MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
510             intptr_t target = startAddr + targetLIR->generic.offset;
511             lir->operands[2] = lir->operands[2] + target;
512         }
513
514
515         MipsEncodingMap *encoder = &EncodingMap[lir->opcode];
516         u4 bits = encoder->skeleton;
517         int i;
518         for (i = 0; i < 4; i++) {
519             u4 operand;
520             u4 value;
521             operand = lir->operands[i];
522             switch(encoder->fieldLoc[i].kind) {
523                 case kFmtUnused:
524                     break;
525                 case kFmtBitBlt:
526                     if (encoder->fieldLoc[i].start == 0 && encoder->fieldLoc[i].end == 31) {
527                         value = operand;
528                     } else {
529                         value = (operand << encoder->fieldLoc[i].start) &
530                                 ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
531                     }
532                     bits |= value;
533                     break;
534                 case kFmtDfp: {
535                     assert(DOUBLEREG(operand));
536                     assert((operand & 0x1) == 0);
537                     value = ((operand & FP_REG_MASK) << encoder->fieldLoc[i].start) &
538                             ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
539                     bits |= value;
540                     break;
541                 }
542                 case kFmtSfp:
543                     assert(SINGLEREG(operand));
544                     value = ((operand & FP_REG_MASK) << encoder->fieldLoc[i].start) &
545                             ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
546                     bits |= value;
547                     break;
548                 default:
549                     assert(0);
550             }
551         }
552         assert(encoder->size == 2);
553         *bufferAddr++ = bits;
554     }
555     return kSuccess;
556 }
557
558 static 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 */
568 static 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  */
630 static 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 */
637 static 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 */
649 static 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 */
661 static 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 */
670 static 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 */
689 static 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 */
696 static 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 */
710 static void matchSignatureBreakpoint(const CompilationUnit *cUnit,
711                                      unsigned int size)
712 {
713     unsigned int i, j;
714     u4 *ptr = (u4 *) cUnit->codeBuffer;
715
716     for (i = 0; i < size - gDvmJit.signatureBreakpointSize + 1; i++) {
717         if (ptr[i] == gDvmJit.signatureBreakpoint[0]) {
718             for (j = 1; j < gDvmJit.signatureBreakpointSize; j++) {
719                 if (ptr[i+j] != gDvmJit.signatureBreakpoint[j]) {
720                     break;
721                 }
722             }
723             if (j == gDvmJit.signatureBreakpointSize) {
724                 LOGD("Signature match starting from offset %#x (%d words)",
725                      i*4, gDvmJit.signatureBreakpointSize);
726                 int descSize = getTraceDescriptionSize(cUnit->traceDesc);
727                 JitTraceDescription *newCopy =
728                     (JitTraceDescription *) malloc(descSize);
729                 memcpy(newCopy, cUnit->traceDesc, descSize);
730                 dvmCompilerWorkEnqueue(NULL, kWorkOrderTraceDebug, newCopy);
731                 break;
732             }
733         }
734     }
735 }
736 #endif
737
738 /*
739  * Go over each instruction in the list and calculate the offset from the top
740  * before sending them off to the assembler. If out-of-range branch distance is
741  * seen rearrange the instructions a bit to correct it.
742  */
743 void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
744 {
745     MipsLIR *mipsLIR;
746     int offset = 0;
747     int i;
748     ChainCellCounts chainCellCounts;
749     int descSize = (cUnit->jitMode == kJitMethod) ?
750         0 : getTraceDescriptionSize(cUnit->traceDesc);
751     int chainingCellGap = 0;
752
753     info->instructionSet = cUnit->instructionSet;
754
755     /* Beginning offset needs to allow space for chain cell offset */
756     for (mipsLIR = (MipsLIR *) cUnit->firstLIRInsn;
757          mipsLIR;
758          mipsLIR = NEXT_LIR(mipsLIR)) {
759         mipsLIR->generic.offset = offset;
760         if (mipsLIR->opcode >= 0 && !mipsLIR->flags.isNop) {
761             mipsLIR->flags.size = EncodingMap[mipsLIR->opcode].size * 2;
762             offset += mipsLIR->flags.size;
763         }
764         /* Pseudo opcodes don't consume space */
765     }
766
767     /* Const values have to be word aligned */
768     offset = (offset + 3) & ~3;
769
770     u4 chainCellOffset = offset;
771     MipsLIR *chainCellOffsetLIR = NULL;
772
773     if (cUnit->jitMode != kJitMethod) {
774         /*
775          * Get the gap (# of u4) between the offset of chaining cell count and
776          * the bottom of real chaining cells. If the translation has chaining
777          * cells, the gap is guaranteed to be multiples of 4.
778          */
779         chainingCellGap = (offset - cUnit->chainingCellBottom->offset) >> 2;
780
781         /* Add space for chain cell counts & trace description */
782         chainCellOffsetLIR = (MipsLIR *) cUnit->chainCellOffsetLIR;
783         assert(chainCellOffsetLIR);
784         assert(chainCellOffset < 0x10000);
785         assert(chainCellOffsetLIR->opcode == kMips32BitData &&
786                chainCellOffsetLIR->operands[0] == CHAIN_CELL_OFFSET_TAG);
787
788         /*
789          * Adjust the CHAIN_CELL_OFFSET_TAG LIR's offset to remove the
790          * space occupied by the pointer to the trace profiling counter.
791          */
792         chainCellOffsetLIR->operands[0] = chainCellOffset - 4;
793
794         offset += sizeof(chainCellCounts) + descSize;
795
796         assert((offset & 0x3) == 0);  /* Should still be word aligned */
797     }
798
799     /* Set up offsets for literals */
800     cUnit->dataOffset = offset;
801
802     /*
803      * Assign each class pointer/constant an offset from the beginning of the
804      * compilation unit.
805      */
806     offset = assignLiteralOffset(cUnit, offset);
807
808     cUnit->totalSize = offset;
809
810     if (gDvmJit.codeCacheByteUsed + cUnit->totalSize > gDvmJit.codeCacheSize) {
811         gDvmJit.codeCacheFull = true;
812         info->discardResult = true;
813         return;
814     }
815
816     /* Allocate enough space for the code block */
817     cUnit->codeBuffer = (unsigned char *)dvmCompilerNew(chainCellOffset, true);
818     if (cUnit->codeBuffer == NULL) {
819         LOGE("Code buffer allocation failure");
820         info->discardResult = true;
821         return;
822     }
823
824     /*
825      * Attempt to assemble the trace.  Note that assembleInstructions
826      * may rewrite the code sequence and request a retry.
827      */
828     cUnit->assemblerStatus = assembleInstructions(cUnit,
829           (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed);
830
831     switch(cUnit->assemblerStatus) {
832         case kSuccess:
833             break;
834         case kRetryAll:
835             if (cUnit->assemblerRetries < MAX_ASSEMBLER_RETRIES) {
836                 if (cUnit->jitMode != kJitMethod) {
837                     /* Restore pristine chain cell marker on retry */
838                     chainCellOffsetLIR->operands[0] = CHAIN_CELL_OFFSET_TAG;
839                 }
840                 return;
841             }
842             /* Too many retries - reset and try cutting the trace in half */
843             cUnit->assemblerRetries = 0;
844             cUnit->assemblerStatus = kRetryHalve;
845             return;
846         case kRetryHalve:
847             return;
848         default:
849              LOGE("Unexpected assembler status: %d", cUnit->assemblerStatus);
850              dvmAbort();
851     }
852
853 #if defined(SIGNATURE_BREAKPOINT)
854     if (info->discardResult == false && gDvmJit.signatureBreakpoint != NULL &&
855         chainCellOffset/4 >= gDvmJit.signatureBreakpointSize) {
856         matchSignatureBreakpoint(cUnit, chainCellOffset/4);
857     }
858 #endif
859
860     /* Don't go all the way if the goal is just to get the verbose output */
861     if (info->discardResult) return;
862
863     /*
864      * The cache might disappear - acquire lock and check version
865      * Continue holding lock until translation cache update is complete.
866      * These actions are required here in the compiler thread because
867      * it is unaffected by suspend requests and doesn't know if a
868      * translation cache flush is in progress.
869      */
870     dvmLockMutex(&gDvmJit.compilerLock);
871     if (info->cacheVersion != gDvmJit.cacheVersion) {
872         /* Cache changed - discard current translation */
873         info->discardResult = true;
874         info->codeAddress = NULL;
875         dvmUnlockMutex(&gDvmJit.compilerLock);
876         return;
877     }
878
879     cUnit->baseAddr = (char *) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed;
880     gDvmJit.codeCacheByteUsed += offset;
881
882     UNPROTECT_CODE_CACHE(cUnit->baseAddr, offset);
883
884     /* Install the code block */
885     memcpy((char*)cUnit->baseAddr, cUnit->codeBuffer, chainCellOffset);
886     gDvmJit.numCompilations++;
887
888     if (cUnit->jitMode != kJitMethod) {
889         /* Install the chaining cell counts */
890         for (i=0; i< kChainingCellGap; i++) {
891             chainCellCounts.u.count[i] = cUnit->numChainingCells[i];
892         }
893
894         /* Set the gap number in the chaining cell count structure */
895         chainCellCounts.u.count[kChainingCellGap] = chainingCellGap;
896
897         memcpy((char*)cUnit->baseAddr + chainCellOffset, &chainCellCounts,
898                sizeof(chainCellCounts));
899
900         /* Install the trace description */
901         memcpy((char*) cUnit->baseAddr + chainCellOffset +
902                        sizeof(chainCellCounts),
903                cUnit->traceDesc, descSize);
904     }
905
906     /* Write the literals directly into the code cache */
907     installLiteralPools(cUnit);
908
909     /* Flush dcache and invalidate the icache to maintain coherence */
910     dvmCompilerCacheFlush((long)cUnit->baseAddr,
911                           (long)((char *) cUnit->baseAddr + offset), 0);
912
913     UPDATE_CODE_CACHE_PATCHES();
914
915     PROTECT_CODE_CACHE(cUnit->baseAddr, offset);
916
917     /* Translation cache update complete - release lock */
918     dvmUnlockMutex(&gDvmJit.compilerLock);
919
920     /* Record code entry point and instruction set */
921     info->codeAddress = (char*)cUnit->baseAddr + cUnit->headerSize;
922     /* transfer the size of the profiling code */
923     info->profileCodeSize = cUnit->profileCodeSize;
924 }
925
926 /*
927  * Returns the skeleton bit pattern associated with an opcode.  All
928  * variable fields are zeroed.
929  */
930 static u4 getSkeleton(MipsOpCode op)
931 {
932     return EncodingMap[op].skeleton;
933 }
934
935 static 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  */
950 void* dvmJitChain(void* tgtAddr, u4* branchAddr)
951 {
952     u4 newInst;
953
954     /*
955      * Only chain translations when there is no urge to ask all threads to
956      * suspend themselves via the interpreter.
957      */
958     if ((gDvmJit.pProfTable != NULL) && (gDvm.sumThreadSuspendCount == 0) &&
959         (gDvmJit.codeCacheFull == false) &&
960         ((((int) tgtAddr) & 0xF0000000) == (((int) branchAddr+4) & 0xF0000000))) {
961         gDvmJit.translationChains++;
962
963         COMPILER_TRACE_CHAINING(
964             LOGD("Jit Runtime: chaining 0x%x to 0x%x",
965                  (int) branchAddr, (int) tgtAddr & -2));
966
967         newInst = assembleChainingBranch((int) tgtAddr & -2, 0);
968
969         UNPROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr));
970
971         *branchAddr = newInst;
972         dvmCompilerCacheFlush((long)branchAddr, (long)branchAddr + 4, 0);
973         UPDATE_CODE_CACHE_PATCHES();
974
975         PROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr));
976
977         gDvmJit.hasNewChain = true;
978     }
979
980     return tgtAddr;
981 }
982
983 #if !defined(WITH_SELF_VERIFICATION)
984 /*
985  * Attempt to enqueue a work order to patch an inline cache for a predicted
986  * chaining cell for virtual/interface calls.
987  */
988 static 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  */
1096 const Method *dvmJitToPatchPredictedChain(const Method *method,
1097                                           Thread *self,
1098                                           PredictedChainingCell *cell,
1099                                           const ClassObject *clazz)
1100 {
1101     int newRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
1102 #if defined(WITH_SELF_VERIFICATION)
1103     newRechainCount = PREDICTED_CHAIN_COUNTER_AVOID;
1104     goto done;
1105 #else
1106     PredictedChainingCell newCell;
1107     int baseAddr, tgtAddr;
1108     if (dvmIsNativeMethod(method)) {
1109         UNPROTECT_CODE_CACHE(cell, sizeof(*cell));
1110
1111         /*
1112          * Put a non-zero/bogus value in the clazz field so that it won't
1113          * trigger immediate patching and will continue to fail to match with
1114          * a real clazz pointer.
1115          */
1116         cell->clazz = (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ;
1117
1118         UPDATE_CODE_CACHE_PATCHES();
1119         PROTECT_CODE_CACHE(cell, sizeof(*cell));
1120         goto done;
1121     }
1122
1123     tgtAddr = (int) dvmJitGetTraceAddr(method->insns);
1124     baseAddr = (int) cell + 4;   // PC is cur_addr + 4
1125
1126     if ((baseAddr & 0xF0000000) != (tgtAddr & 0xF0000000)) {
1127         COMPILER_TRACE_CHAINING(
1128             LOGD("Jit Runtime: predicted chain %p to distant target %s ignored",
1129                  cell, method->name));
1130         goto done;
1131     }
1132
1133     /*
1134      * Compilation not made yet for the callee. Reset the counter to a small
1135      * value and come back to check soon.
1136      */
1137     if ((tgtAddr == 0) ||
1138         ((void*)tgtAddr == dvmCompilerGetInterpretTemplate())) {
1139         COMPILER_TRACE_CHAINING(
1140             LOGD("Jit Runtime: predicted chain %p to method %s%s delayed",
1141                  cell, method->clazz->descriptor, method->name));
1142         goto done;
1143     }
1144
1145     if (cell->clazz == NULL) {
1146         newRechainCount = self->icRechainCount;
1147     }
1148
1149     newCell.branch = assembleChainingBranch(tgtAddr, true);
1150     newCell.delay_slot = getSkeleton(kMipsNop);
1151     newCell.clazz = clazz;
1152     newCell.method = method;
1153     newCell.stagedClazz = NULL;
1154
1155     /*
1156      * Enter the work order to the queue and the chaining cell will be patched
1157      * the next time a safe point is entered.
1158      *
1159      * If the enqueuing fails reset the rechain count to a normal value so that
1160      * it won't get indefinitely delayed.
1161      */
1162     inlineCachePatchEnqueue(cell, &newCell);
1163 #endif
1164 done:
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  */
1173 void dvmCompilerPatchInlineCache(void)
1174 {
1175     int i;
1176     PredictedChainingCell *minAddr, *maxAddr;
1177
1178     /* Nothing to be done */
1179     if (gDvmJit.compilerICPatchIndex == 0) return;
1180
1181     /*
1182      * Since all threads are already stopped we don't really need to acquire
1183      * the lock. But race condition can be easily introduced in the future w/o
1184      * paying attention so we still acquire the lock here.
1185      */
1186     dvmLockMutex(&gDvmJit.compilerICPatchLock);
1187
1188     UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1189
1190     //LOGD("Number of IC patch work orders: %d", gDvmJit.compilerICPatchIndex);
1191
1192     /* Initialize the min/max address range */
1193     minAddr = (PredictedChainingCell *)
1194         ((char *) gDvmJit.codeCache + gDvmJit.codeCacheSize);
1195     maxAddr = (PredictedChainingCell *) gDvmJit.codeCache;
1196
1197     for (i = 0; i < gDvmJit.compilerICPatchIndex; i++) {
1198         ICPatchWorkOrder *workOrder = &gDvmJit.compilerICPatchQueue[i];
1199         PredictedChainingCell *cellAddr = workOrder->cellAddr;
1200         PredictedChainingCell *cellContent = &workOrder->cellContent;
1201         ClassObject *clazz = dvmFindClassNoInit(workOrder->classDescriptor,
1202                                                 workOrder->classLoader);
1203
1204         assert(clazz->serialNumber == workOrder->serialNumber);
1205
1206         /* Use the newly resolved clazz pointer */
1207         cellContent->clazz = clazz;
1208
1209         COMPILER_TRACE_CHAINING(
1210             LOGD("Jit Runtime: predicted chain %p from %s to %s (%s) "
1211                  "patched",
1212                  cellAddr,
1213                  cellAddr->clazz->descriptor,
1214                  cellContent->clazz->descriptor,
1215                  cellContent->method->name));
1216
1217         /* Patch the chaining cell */
1218         *cellAddr = *cellContent;
1219         minAddr = (cellAddr < minAddr) ? cellAddr : minAddr;
1220         maxAddr = (cellAddr > maxAddr) ? cellAddr : maxAddr;
1221     }
1222
1223     /* Then synchronize the I/D cache */
1224     dvmCompilerCacheFlush((long) minAddr, (long) (maxAddr+1), 0);
1225     UPDATE_CODE_CACHE_PATCHES();
1226
1227     PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1228
1229     gDvmJit.compilerICPatchIndex = 0;
1230     dvmUnlockMutex(&gDvmJit.compilerICPatchLock);
1231 }
1232
1233 /*
1234  * Unchain a trace given the starting address of the translation
1235  * in the code cache.  Refer to the diagram in dvmCompilerAssembleLIR.
1236  * Returns the address following the last cell unchained.  Note that
1237  * the incoming codeAddr is a thumb code address, and therefore has
1238  * the low bit set.
1239  */
1240 static u4* unchainSingle(JitEntry *trace)
1241 {
1242     const char *base = getTraceBase(trace);
1243     ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base);
1244     int cellSize = getChainCellSize(pChainCellCounts);
1245     u4* pChainCells;
1246     int i,j;
1247     PredictedChainingCell *predChainCell;
1248
1249     if (cellSize == 0)
1250         return (u4 *) pChainCellCounts;
1251
1252     /* Locate the beginning of the chain cell region */
1253     pChainCells = ((u4 *) pChainCellCounts) - cellSize -
1254                   pChainCellCounts->u.count[kChainingCellGap];
1255
1256     /* The cells are sorted in order - walk through them and reset */
1257     for (i = 0; i < kChainingCellGap; i++) {
1258         int elemSize = CHAIN_CELL_NORMAL_SIZE >> 2;  /* In 32-bit words */
1259         if (i == kChainingCellInvokePredicted) {
1260             elemSize = CHAIN_CELL_PREDICTED_SIZE >> 2;
1261         }
1262
1263         for (j = 0; j < pChainCellCounts->u.count[i]; j++) {
1264             int targetOffset;
1265             switch(i) {
1266                 case kChainingCellNormal:
1267                     targetOffset = offsetof(Thread,
1268                           jitToInterpEntries.dvmJitToInterpNormal);
1269                     break;
1270                 case kChainingCellHot:
1271                 case kChainingCellInvokeSingleton:
1272                     targetOffset = offsetof(Thread,
1273                           jitToInterpEntries.dvmJitToInterpTraceSelect);
1274                     break;
1275                 case kChainingCellInvokePredicted:
1276                     targetOffset = 0;
1277                     predChainCell = (PredictedChainingCell *) pChainCells;
1278                     /*
1279                      * There could be a race on another mutator thread to use
1280                      * this particular predicted cell and the check has passed
1281                      * the clazz comparison. So we cannot safely wipe the
1282                      * method and branch but it is safe to clear the clazz,
1283                      * which serves as the key.
1284                      */
1285                     predChainCell->clazz = PREDICTED_CHAIN_CLAZZ_INIT;
1286                     break;
1287 #if defined(WITH_SELF_VERIFICATION)
1288                 case kChainingCellBackwardBranch:
1289                     targetOffset = offsetof(Thread,
1290                           jitToInterpEntries.dvmJitToInterpBackwardBranch);
1291                     break;
1292 #else
1293                 case kChainingCellBackwardBranch:
1294                     targetOffset = offsetof(Thread,
1295                           jitToInterpEntries.dvmJitToInterpNormal);
1296                     break;
1297 #endif
1298                 default:
1299                     targetOffset = 0; // make gcc happy
1300                     LOGE("Unexpected chaining type: %d", i);
1301                     dvmAbort();  // dvmAbort OK here - can't safely recover
1302             }
1303             COMPILER_TRACE_CHAINING(
1304                 LOGD("Jit Runtime: unchaining %#x", (int)pChainCells));
1305             /*
1306              * Code sequence for a chaining cell is:
1307              *     lw   a0, offset(rSELF)
1308              *     jalr ra, a0
1309              */
1310             if (i != kChainingCellInvokePredicted) {
1311                 *pChainCells = getSkeleton(kMipsLw) | (r_A0 << 16) |
1312                                targetOffset | (rSELF << 21);
1313                 *(pChainCells+1) = getSkeleton(kMipsJalr) | (r_RA << 11) |
1314                                    (r_A0 << 21);
1315             }
1316             pChainCells += elemSize;  /* Advance by a fixed number of words */
1317         }
1318     }
1319     return pChainCells;
1320 }
1321
1322 /* Unchain all translation in the cache. */
1323 void dvmJitUnchainAll()
1324 {
1325     u4* lowAddress = NULL;
1326     u4* highAddress = NULL;
1327     unsigned int i;
1328     if (gDvmJit.pJitEntryTable != NULL) {
1329         COMPILER_TRACE_CHAINING(LOGD("Jit Runtime: unchaining all"));
1330         dvmLockMutex(&gDvmJit.tableLock);
1331
1332         UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
1333
1334         for (i = 0; i < gDvmJit.jitTableSize; i++) {
1335             if (gDvmJit.pJitEntryTable[i].dPC &&
1336                 !gDvmJit.pJitEntryTable[i].u.info.isMethodEntry &&
1337                 gDvmJit.pJitEntryTable[i].codeAddress &&
1338                 (gDvmJit.pJitEntryTable[i].codeAddress !=
1339                  dvmCompilerGetInterpretTemplate())) {
1340                 u4* lastAddress;
1341                 lastAddress = unchainSingle(&gDvmJit.pJitEntryTable[i]);
1342                 if (lowAddress == NULL ||
1343                       (u4*)gDvmJit.pJitEntryTable[i].codeAddress < lowAddress)
1344                     lowAddress = (u4*)gDvmJit.pJitEntryTable[i].codeAddress;
1345                 if (lastAddress > highAddress)
1346                     highAddress = lastAddress;
1347             }
1348         }
1349
1350         if (lowAddress && highAddress)
1351                 dvmCompilerCacheFlush((long)lowAddress, (long)highAddress, 0);
1352
1353         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
1363 typedef struct jitProfileAddrToLine {
1364     u4 lineNum;
1365     u4 bytecodeOffset;
1366 } jitProfileAddrToLine;
1367
1368
1369 /* Callback function to track the bytecode offset/line number relationiship */
1370 static 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 */
1382 static 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             LOGD("TRACEPROFILE NULL");
1390         return 0;
1391     }
1392     if (p->codeAddress == dvmCompilerGetInterpretTemplate()) {
1393         if (!silent)
1394             LOGD("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     LOGD("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         LOGD("    -> %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 */
1457 JitTraceDescription *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 */
1476 static 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 */
1487 void 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     LOGD("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);
1548 done:
1549     dvmUnlockMutex(&gDvmJit.tableLock);
1550     return;
1551 }
1552
1553 static 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  */
1606 void 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  */
1639 void 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 */
1718 enum {
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 */
1729 static int selfVerificationMemRegLoad(int* sp, int reg)
1730 {
1731 assert(0); /* MIPSTODO retarg func */
1732     return *(sp + reg);
1733 }
1734
1735 /* Load the value of a decoded doubleword register from the stack */
1736 static s8 selfVerificationMemRegLoadDouble(int* sp, int reg)
1737 {
1738 assert(0); /* MIPSTODO retarg func */
1739     return *((s8*)(sp + reg));
1740 }
1741
1742 /* Store the value of a decoded register out to the stack */
1743 static void selfVerificationMemRegStore(int* sp, int data, int reg)
1744 {
1745 assert(0); /* MIPSTODO retarg func */
1746     *(sp + reg) = data;
1747 }
1748
1749 /* Store the value of a decoded doubleword register out to the stack */
1750 static void selfVerificationMemRegStoreDouble(int* sp, s8 data, int reg)
1751 {
1752 assert(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  */
1761 static int selfVerificationLoad(int addr, int size)
1762 {
1763 assert(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             LOGE("*** ERROR: BAD SIZE IN selfVerificationLoad: %d", size);
1798             data = 0;
1799             dvmAbort();
1800     }
1801
1802     //LOGD("*** HEAP LOAD: Addr: %#x Data: %#x Size: %d", addr, data, size);
1803     return data;
1804 }
1805
1806 /* Like selfVerificationLoad, but specifically for doublewords */
1807 static s8 selfVerificationLoadDoubleword(int addr)
1808 {
1809 assert(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     //LOGD("*** 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  */
1838 static void selfVerificationStore(int addr, int data, int size)
1839 {
1840 assert(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     //LOGD("*** 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             LOGE("*** ERROR: BAD SIZE IN selfVerificationSave: %d", size);
1880             dvmAbort();
1881     }
1882 }
1883
1884 /* Like selfVerificationStore, but specifically for doublewords */
1885 static void selfVerificationStoreDoubleword(int addr, s8 double_data)
1886 {
1887 assert(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     //LOGD("*** 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  */
1930 void dvmSelfVerificationMemOpDecode(int lr, int* sp)
1931 {
1932 assert(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         //LOGD("*** 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                     LOGE("*** 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                 LOGE("*** 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                 LOGD("*** 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                 LOGD("*** 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         //LOGD("*** 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                 LOGE("*** 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