assemble_mips.cc revision 8d36591d93920e7b7830c3ffee3759b561f5339e
1/*
2 * Copyright (C) 2012 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 "codegen_mips.h"
18
19#include "dex/quick/mir_to_lir-inl.h"
20#include "mips_lir.h"
21
22namespace art {
23
24#define MAX_ASSEMBLER_RETRIES 50
25
26/*
27 * opcode: MipsOpCode enum
28 * skeleton: pre-designated bit-pattern for this opcode
29 * k0: key to applying ds/de
30 * ds: dest start bit position
31 * de: dest end bit position
32 * k1: key to applying s1s/s1e
33 * s1s: src1 start bit position
34 * s1e: src1 end bit position
35 * k2: key to applying s2s/s2e
36 * s2s: src2 start bit position
37 * s2e: src2 end bit position
38 * operands: number of operands (for sanity check purposes)
39 * name: mnemonic name
40 * fmt: for pretty-printing
41 */
42#define ENCODING_MAP(opcode, skeleton, k0, ds, de, k1, s1s, s1e, k2, s2s, s2e, \
43                     k3, k3s, k3e, flags, name, fmt, size) \
44        {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \
45                    {k3, k3s, k3e}}, opcode, flags, name, fmt, size}
46
47/* Instruction dump string format keys: !pf, where "!" is the start
48 * of the key, "p" is which numeric operand to use and "f" is the
49 * print format.
50 *
51 * [p]ositions:
52 *     0 -> operands[0] (dest)
53 *     1 -> operands[1] (src1)
54 *     2 -> operands[2] (src2)
55 *     3 -> operands[3] (extra)
56 *
57 * [f]ormats:
58 *     h -> 4-digit hex
59 *     d -> decimal
60 *     E -> decimal*4
61 *     F -> decimal*2
62 *     c -> branch condition (beq, bne, etc.)
63 *     t -> pc-relative target
64 *     T -> pc-region target
65 *     u -> 1st half of bl[x] target
66 *     v -> 2nd half ob bl[x] target
67 *     R -> register list
68 *     s -> single precision floating point register
69 *     S -> double precision floating point register
70 *     m -> Thumb2 modified immediate
71 *     n -> complimented Thumb2 modified immediate
72 *     M -> Thumb2 16-bit zero-extended immediate
73 *     b -> 4-digit binary
74 *     N -> append a NOP
75 *
76 *  [!] escape.  To insert "!", use "!!"
77 */
78/* NOTE: must be kept in sync with enum MipsOpcode from LIR.h */
79/*
80 * TUNING: We're currently punting on the branch delay slots.  All branch
81 * instructions in this map are given a size of 8, which during assembly
82 * is expanded to include a nop.  This scheme should be replaced with
83 * an assembler pass to fill those slots when possible.
84 */
85const MipsEncodingMap MipsMir2Lir::EncodingMap[kMipsLast] = {
86    ENCODING_MAP(kMips32BitData, 0x00000000,
87                 kFmtBitBlt, 31, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
88                 kFmtUnused, -1, -1, IS_UNARY_OP,
89                 "data", "0x!0h(!0d)", 4),
90    ENCODING_MAP(kMipsAddiu, 0x24000000,
91                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
92                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
93                 "addiu", "!0r,!1r,0x!2h(!2d)", 4),
94    ENCODING_MAP(kMipsAddu, 0x00000021,
95                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
96                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
97                 "addu", "!0r,!1r,!2r", 4),
98    ENCODING_MAP(kMipsAnd, 0x00000024,
99                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
100                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
101                 "and", "!0r,!1r,!2r", 4),
102    ENCODING_MAP(kMipsAndi, 0x30000000,
103                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
104                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
105                 "andi", "!0r,!1r,0x!2h(!2d)", 4),
106    ENCODING_MAP(kMipsB, 0x10000000,
107                 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
108                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | NEEDS_FIXUP,
109                 "b", "!0t!0N", 8),
110    ENCODING_MAP(kMipsBal, 0x04110000,
111                 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
112                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR |
113                 NEEDS_FIXUP, "bal", "!0t!0N", 8),
114    ENCODING_MAP(kMipsBeq, 0x10000000,
115                 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
116                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 |
117                 NEEDS_FIXUP, "beq", "!0r,!1r,!2t!0N", 8),
118    ENCODING_MAP(kMipsBeqz, 0x10000000, /* same as beq above with t = $zero */
119                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
120                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
121                 NEEDS_FIXUP, "beqz", "!0r,!1t!0N", 8),
122    ENCODING_MAP(kMipsBgez, 0x04010000,
123                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
124                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
125                 NEEDS_FIXUP, "bgez", "!0r,!1t!0N", 8),
126    ENCODING_MAP(kMipsBgtz, 0x1C000000,
127                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
128                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
129                 NEEDS_FIXUP, "bgtz", "!0r,!1t!0N", 8),
130    ENCODING_MAP(kMipsBlez, 0x18000000,
131                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
132                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
133                 NEEDS_FIXUP, "blez", "!0r,!1t!0N", 8),
134    ENCODING_MAP(kMipsBltz, 0x04000000,
135                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
136                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
137                 NEEDS_FIXUP, "bltz", "!0r,!1t!0N", 8),
138    ENCODING_MAP(kMipsBnez, 0x14000000, /* same as bne below with t = $zero */
139                 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
140                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
141                 NEEDS_FIXUP, "bnez", "!0r,!1t!0N", 8),
142    ENCODING_MAP(kMipsBne, 0x14000000,
143                 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
144                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 |
145                 NEEDS_FIXUP, "bne", "!0r,!1r,!2t!0N", 8),
146    ENCODING_MAP(kMipsDiv, 0x0000001a,
147                 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1,
148                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF_HI | REG_DEF_LO | REG_USE01,
149                 "div", "!0r,!1r", 4),
150    ENCODING_MAP(kMipsExt, 0x7c000000,
151                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 10, 6,
152                 kFmtBitBlt, 15, 11, IS_QUAD_OP | REG_DEF0 | REG_USE1,
153                 "ext", "!0r,!1r,!2d,!3D", 4),
154    ENCODING_MAP(kMipsJal, 0x0c000000,
155                 kFmtBitBlt, 25, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
156                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR,
157                 "jal", "!0T(!0E)!0N", 8),
158    ENCODING_MAP(kMipsJalr, 0x00000009,
159                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1,
160                 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_DEF0_USE1,
161                 "jalr", "!0r,!1r!0N", 8),
162    ENCODING_MAP(kMipsJr, 0x00000008,
163                 kFmtBitBlt, 25, 21, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
164                 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
165                 NEEDS_FIXUP, "jr", "!0r!0N", 8),
166    ENCODING_MAP(kMipsLahi, 0x3C000000,
167                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
168                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
169                 "lahi/lui", "!0r,0x!1h(!1d)", 4),
170    ENCODING_MAP(kMipsLalo, 0x34000000,
171                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
172                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
173                 "lalo/ori", "!0r,!1r,0x!2h(!2d)", 4),
174    ENCODING_MAP(kMipsLui, 0x3C000000,
175                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
176                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
177                 "lui", "!0r,0x!1h(!1d)", 4),
178    ENCODING_MAP(kMipsLb, 0x80000000,
179                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
180                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
181                 "lb", "!0r,!1d(!2r)", 4),
182    ENCODING_MAP(kMipsLbu, 0x90000000,
183                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
184                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
185                 "lbu", "!0r,!1d(!2r)", 4),
186    ENCODING_MAP(kMipsLh, 0x84000000,
187                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
188                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
189                 "lh", "!0r,!1d(!2r)", 4),
190    ENCODING_MAP(kMipsLhu, 0x94000000,
191                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
192                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
193                 "lhu", "!0r,!1d(!2r)", 4),
194    ENCODING_MAP(kMipsLw, 0x8C000000,
195                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
196                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
197                 "lw", "!0r,!1d(!2r)", 4),
198    ENCODING_MAP(kMipsMfhi, 0x00000010,
199                 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
200                 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF0 | REG_USE_HI,
201                 "mfhi", "!0r", 4),
202    ENCODING_MAP(kMipsMflo, 0x00000012,
203                 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
204                 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF0 | REG_USE_LO,
205                 "mflo", "!0r", 4),
206    ENCODING_MAP(kMipsMove, 0x00000025, /* or using zero reg */
207                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1,
208                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
209                 "move", "!0r,!1r", 4),
210    ENCODING_MAP(kMipsMovz, 0x0000000a,
211                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
212                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
213                 "movz", "!0r,!1r,!2r", 4),
214    ENCODING_MAP(kMipsMul, 0x70000002,
215                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
216                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
217                 "mul", "!0r,!1r,!2r", 4),
218    ENCODING_MAP(kMipsNop, 0x00000000,
219                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
220                 kFmtUnused, -1, -1, NO_OPERAND,
221                 "nop", ";", 4),
222    ENCODING_MAP(kMipsNor, 0x00000027, /* used for "not" too */
223                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
224                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
225                 "nor", "!0r,!1r,!2r", 4),
226    ENCODING_MAP(kMipsOr, 0x00000025,
227                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
228                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
229                 "or", "!0r,!1r,!2r", 4),
230    ENCODING_MAP(kMipsOri, 0x34000000,
231                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
232                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
233                 "ori", "!0r,!1r,0x!2h(!2d)", 4),
234    ENCODING_MAP(kMipsPref, 0xCC000000,
235                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
236                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE2,
237                 "pref", "!0d,!1d(!2r)", 4),
238    ENCODING_MAP(kMipsSb, 0xA0000000,
239                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
240                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
241                 "sb", "!0r,!1d(!2r)", 4),
242    ENCODING_MAP(kMipsSeb, 0x7c000420,
243                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1,
244                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
245                 "seb", "!0r,!1r", 4),
246    ENCODING_MAP(kMipsSeh, 0x7c000620,
247                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1,
248                 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
249                 "seh", "!0r,!1r", 4),
250    ENCODING_MAP(kMipsSh, 0xA4000000,
251                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
252                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
253                 "sh", "!0r,!1d(!2r)", 4),
254    ENCODING_MAP(kMipsSll, 0x00000000,
255                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
256                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
257                 "sll", "!0r,!1r,0x!2h(!2d)", 4),
258    ENCODING_MAP(kMipsSllv, 0x00000004,
259                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
260                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
261                 "sllv", "!0r,!1r,!2r", 4),
262    ENCODING_MAP(kMipsSlt, 0x0000002a,
263                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
264                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
265                 "slt", "!0r,!1r,!2r", 4),
266    ENCODING_MAP(kMipsSlti, 0x28000000,
267                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
268                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
269                 "slti", "!0r,!1r,0x!2h(!2d)", 4),
270    ENCODING_MAP(kMipsSltu, 0x0000002b,
271                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
272                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
273                 "sltu", "!0r,!1r,!2r", 4),
274    ENCODING_MAP(kMipsSra, 0x00000003,
275                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
276                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
277                 "sra", "!0r,!1r,0x!2h(!2d)", 4),
278    ENCODING_MAP(kMipsSrav, 0x00000007,
279                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
280                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
281                 "srav", "!0r,!1r,!2r", 4),
282    ENCODING_MAP(kMipsSrl, 0x00000002,
283                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
284                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
285                 "srl", "!0r,!1r,0x!2h(!2d)", 4),
286    ENCODING_MAP(kMipsSrlv, 0x00000006,
287                 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
288                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
289                 "srlv", "!0r,!1r,!2r", 4),
290    ENCODING_MAP(kMipsSubu, 0x00000023, /* used for "neg" too */
291                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
292                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
293                 "subu", "!0r,!1r,!2r", 4),
294    ENCODING_MAP(kMipsSw, 0xAC000000,
295                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
296                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
297                 "sw", "!0r,!1d(!2r)", 4),
298    ENCODING_MAP(kMipsXor, 0x00000026,
299                 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
300                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
301                 "xor", "!0r,!1r,!2r", 4),
302    ENCODING_MAP(kMipsXori, 0x38000000,
303                 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
304                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
305                 "xori", "!0r,!1r,0x!2h(!2d)", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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", 4),
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)", 4),
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)", 4),
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)", 4),
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)", 4),
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", 4),
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", 4),
394    ENCODING_MAP(kMipsDelta, 0x27e00000,
395                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, 15, 0,
396                 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | REG_USE_LR |
397                 NEEDS_FIXUP, "addiu", "!0r,ra,0x!1h(!1d)", 4),
398    ENCODING_MAP(kMipsDeltaHi, 0x3C000000,
399                 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
400                 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | NEEDS_FIXUP,
401                 "lui", "!0r,0x!1h(!1d)", 4),
402    ENCODING_MAP(kMipsDeltaLo, 0x34000000,
403                 kFmtBlt5_2, 16, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
404                 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0_USE0 | NEEDS_FIXUP,
405                 "ori", "!0r,!0r,0x!1h(!1d)", 4),
406    ENCODING_MAP(kMipsCurrPC, 0x04110001,
407                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
408                 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR,
409                 "addiu", "ra,pc,8", 4),
410    ENCODING_MAP(kMipsSync, 0x0000000f,
411                 kFmtBitBlt, 10, 6, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
412                 kFmtUnused, -1, -1, IS_UNARY_OP,
413                 "sync", ";", 4),
414    ENCODING_MAP(kMipsUndefined, 0x64000000,
415                 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
416                 kFmtUnused, -1, -1, NO_OPERAND,
417                 "undefined", "", 4),
418};
419
420
421/*
422 * Convert a short-form branch to long form.  Hopefully, this won't happen
423 * very often because the PIC sequence is especially unfortunate.
424 *
425 * Orig conditional branch
426 * -----------------------
427 *      beq  rs,rt,target
428 *
429 * Long conditional branch
430 * -----------------------
431 *      bne  rs,rt,hop
432 *      bal  .+8   ; rRA <- anchor
433 *      lui  rAT, ((target-anchor) >> 16)
434 * anchor:
435 *      ori  rAT, rAT, ((target-anchor) & 0xffff)
436 *      addu rAT, rAT, rRA
437 *      jalr rZERO, rAT
438 * hop:
439 *
440 * Orig unconditional branch
441 * -------------------------
442 *      b target
443 *
444 * Long unconditional branch
445 * -----------------------
446 *      bal  .+8   ; rRA <- anchor
447 *      lui  rAT, ((target-anchor) >> 16)
448 * anchor:
449 *      ori  rAT, rAT, ((target-anchor) & 0xffff)
450 *      addu rAT, rAT, rRA
451 *      jalr rZERO, rAT
452 *
453 *
454 * NOTE: An out-of-range bal isn't supported because it should
455 * never happen with the current PIC model.
456 */
457void MipsMir2Lir::ConvertShortToLongBranch(LIR* lir) {
458  // For conditional branches we'll need to reverse the sense
459  bool unconditional = false;
460  int opcode = lir->opcode;
461  int dalvik_offset = lir->dalvik_offset;
462  switch (opcode) {
463    case kMipsBal:
464      LOG(FATAL) << "long branch and link unsupported";
465      UNREACHABLE();
466    case kMipsB:
467      unconditional = true;
468      break;
469    case kMipsBeq:  opcode = kMipsBne; break;
470    case kMipsBne:  opcode = kMipsBeq; break;
471    case kMipsBeqz: opcode = kMipsBnez; break;
472    case kMipsBgez: opcode = kMipsBltz; break;
473    case kMipsBgtz: opcode = kMipsBlez; break;
474    case kMipsBlez: opcode = kMipsBgtz; break;
475    case kMipsBltz: opcode = kMipsBgez; break;
476    case kMipsBnez: opcode = kMipsBeqz; break;
477    default:
478      LOG(FATAL) << "Unexpected branch kind " << opcode;
479      UNREACHABLE();
480  }
481  LIR* hop_target = NULL;
482  if (!unconditional) {
483    hop_target = RawLIR(dalvik_offset, kPseudoTargetLabel);
484    LIR* hop_branch = RawLIR(dalvik_offset, opcode, lir->operands[0],
485                            lir->operands[1], 0, 0, 0, hop_target);
486    InsertLIRBefore(lir, hop_branch);
487  }
488  LIR* curr_pc = RawLIR(dalvik_offset, kMipsCurrPC);
489  InsertLIRBefore(lir, curr_pc);
490  LIR* anchor = RawLIR(dalvik_offset, kPseudoTargetLabel);
491  LIR* delta_hi = RawLIR(dalvik_offset, kMipsDeltaHi, rAT, 0, WrapPointer(anchor), 0, 0,
492                         lir->target);
493  InsertLIRBefore(lir, delta_hi);
494  InsertLIRBefore(lir, anchor);
495  LIR* delta_lo = RawLIR(dalvik_offset, kMipsDeltaLo, rAT, 0, WrapPointer(anchor), 0, 0,
496                         lir->target);
497  InsertLIRBefore(lir, delta_lo);
498  LIR* addu = RawLIR(dalvik_offset, kMipsAddu, rAT, rAT, rRA);
499  InsertLIRBefore(lir, addu);
500  LIR* jalr = RawLIR(dalvik_offset, kMipsJalr, rZERO, rAT);
501  InsertLIRBefore(lir, jalr);
502  if (!unconditional) {
503    InsertLIRBefore(lir, hop_target);
504  }
505  NopLIR(lir);
506}
507
508/*
509 * Assemble the LIR into binary instruction format.  Note that we may
510 * discover that pc-relative displacements may not fit the selected
511 * instruction.  In those cases we will try to substitute a new code
512 * sequence or request that the trace be shortened and retried.
513 */
514AssemblerStatus MipsMir2Lir::AssembleInstructions(CodeOffset start_addr) {
515  LIR *lir;
516  AssemblerStatus res = kSuccess;  // Assume success
517
518  for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) {
519    if (lir->opcode < 0) {
520      continue;
521    }
522
523
524    if (lir->flags.is_nop) {
525      continue;
526    }
527
528    if (lir->flags.fixup != kFixupNone) {
529      if (lir->opcode == kMipsDelta) {
530        /*
531         * The "Delta" pseudo-ops load the difference between
532         * two pc-relative locations into a the target register
533         * found in operands[0].  The delta is determined by
534         * (label2 - label1), where label1 is a standard
535         * kPseudoTargetLabel and is stored in operands[2].
536         * If operands[3] is null, then label2 is a kPseudoTargetLabel
537         * and is found in lir->target.  If operands[3] is non-NULL,
538         * then it is a Switch/Data table.
539         */
540        int offset1 = (reinterpret_cast<LIR*>(UnwrapPointer(lir->operands[2])))->offset;
541        EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(lir->operands[3]));
542        int offset2 = tab_rec ? tab_rec->offset : lir->target->offset;
543        int delta = offset2 - offset1;
544        if ((delta & 0xffff) == delta && ((delta & 0x8000) == 0)) {
545          // Fits
546          lir->operands[1] = delta;
547        } else {
548          // Doesn't fit - must expand to kMipsDelta[Hi|Lo] pair
549          LIR *new_delta_hi =
550              RawLIR(lir->dalvik_offset, kMipsDeltaHi,
551                     lir->operands[0], 0, lir->operands[2],
552                     lir->operands[3], 0, lir->target);
553          InsertLIRBefore(lir, new_delta_hi);
554          LIR *new_delta_lo =
555              RawLIR(lir->dalvik_offset, kMipsDeltaLo,
556                     lir->operands[0], 0, lir->operands[2],
557                     lir->operands[3], 0, lir->target);
558          InsertLIRBefore(lir, new_delta_lo);
559          LIR *new_addu =
560              RawLIR(lir->dalvik_offset, kMipsAddu,
561                     lir->operands[0], lir->operands[0], rRA);
562          InsertLIRBefore(lir, new_addu);
563          NopLIR(lir);
564          res = kRetryAll;
565        }
566      } else if (lir->opcode == kMipsDeltaLo) {
567        int offset1 = (reinterpret_cast<LIR*>(UnwrapPointer(lir->operands[2])))->offset;
568        EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(lir->operands[3]));
569        int offset2 = tab_rec ? tab_rec->offset : lir->target->offset;
570        int delta = offset2 - offset1;
571        lir->operands[1] = delta & 0xffff;
572      } else if (lir->opcode == kMipsDeltaHi) {
573        int offset1 = (reinterpret_cast<LIR*>(UnwrapPointer(lir->operands[2])))->offset;
574        EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(lir->operands[3]));
575        int offset2 = tab_rec ? tab_rec->offset : lir->target->offset;
576        int delta = offset2 - offset1;
577        lir->operands[1] = (delta >> 16) & 0xffff;
578      } else if (lir->opcode == kMipsB || lir->opcode == kMipsBal) {
579        LIR *target_lir = lir->target;
580        CodeOffset pc = lir->offset + 4;
581        CodeOffset target = target_lir->offset;
582        int delta = target - pc;
583        if (delta & 0x3) {
584          LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
585        }
586        if (delta > 131068 || delta < -131069) {
587          res = kRetryAll;
588          ConvertShortToLongBranch(lir);
589        } else {
590          lir->operands[0] = delta >> 2;
591        }
592      } else if (lir->opcode >= kMipsBeqz && lir->opcode <= kMipsBnez) {
593        LIR *target_lir = lir->target;
594        CodeOffset pc = lir->offset + 4;
595        CodeOffset target = target_lir->offset;
596        int delta = target - pc;
597        if (delta & 0x3) {
598          LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
599        }
600        if (delta > 131068 || delta < -131069) {
601          res = kRetryAll;
602          ConvertShortToLongBranch(lir);
603        } else {
604          lir->operands[1] = delta >> 2;
605        }
606      } else if (lir->opcode == kMipsBeq || lir->opcode == kMipsBne) {
607        LIR *target_lir = lir->target;
608        CodeOffset pc = lir->offset + 4;
609        CodeOffset target = target_lir->offset;
610        int delta = target - pc;
611        if (delta & 0x3) {
612          LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
613        }
614        if (delta > 131068 || delta < -131069) {
615          res = kRetryAll;
616          ConvertShortToLongBranch(lir);
617        } else {
618          lir->operands[2] = delta >> 2;
619        }
620      } else if (lir->opcode == kMipsJal) {
621        CodeOffset cur_pc = (start_addr + lir->offset + 4) & ~3;
622        CodeOffset target = lir->operands[0];
623        /* ensure PC-region branch can be used */
624        DCHECK_EQ((cur_pc & 0xF0000000), (target & 0xF0000000));
625        if (target & 0x3) {
626          LOG(FATAL) << "Jump target not multiple of 4: " << target;
627        }
628        lir->operands[0] =  target >> 2;
629      } else if (lir->opcode == kMipsLahi) { /* ld address hi (via lui) */
630        LIR *target_lir = lir->target;
631        CodeOffset target = start_addr + target_lir->offset;
632        lir->operands[1] = target >> 16;
633      } else if (lir->opcode == kMipsLalo) { /* ld address lo (via ori) */
634        LIR *target_lir = lir->target;
635        CodeOffset target = start_addr + target_lir->offset;
636        lir->operands[2] = lir->operands[2] + target;
637      }
638    }
639
640    /*
641     * If one of the pc-relative instructions expanded we'll have
642     * to make another pass.  Don't bother to fully assemble the
643     * instruction.
644     */
645    if (res != kSuccess) {
646      continue;
647    }
648    DCHECK(!IsPseudoLirOp(lir->opcode));
649    const MipsEncodingMap *encoder = &EncodingMap[lir->opcode];
650    uint32_t bits = encoder->skeleton;
651    int i;
652    for (i = 0; i < 4; i++) {
653      uint32_t operand;
654      uint32_t value;
655      operand = lir->operands[i];
656      switch (encoder->field_loc[i].kind) {
657        case kFmtUnused:
658          break;
659        case kFmtBitBlt:
660          if (encoder->field_loc[i].start == 0 && encoder->field_loc[i].end == 31) {
661            value = operand;
662          } else {
663            value = (operand << encoder->field_loc[i].start) &
664                ((1 << (encoder->field_loc[i].end + 1)) - 1);
665          }
666          bits |= value;
667          break;
668        case kFmtBlt5_2:
669          value = (operand & 0x1f);
670          bits |= (value << encoder->field_loc[i].start);
671          bits |= (value << encoder->field_loc[i].end);
672          break;
673        case kFmtDfp: {
674          // TODO: do we need to adjust now that we're using 64BitSolo?
675          DCHECK(RegStorage::IsDouble(operand)) << ", Operand = 0x" << std::hex << operand;
676          DCHECK_EQ((operand & 0x1), 0U);
677          value = (RegStorage::RegNum(operand) << encoder->field_loc[i].start) &
678              ((1 << (encoder->field_loc[i].end + 1)) - 1);
679          bits |= value;
680          break;
681        }
682        case kFmtSfp:
683          DCHECK(RegStorage::IsSingle(operand)) << ", Operand = 0x" << std::hex << operand;
684          value = (RegStorage::RegNum(operand) << encoder->field_loc[i].start) &
685              ((1 << (encoder->field_loc[i].end + 1)) - 1);
686          bits |= value;
687          break;
688        default:
689          LOG(FATAL) << "Bad encoder format: " << encoder->field_loc[i].kind;
690      }
691    }
692    // We only support little-endian MIPS.
693    code_buffer_.push_back(bits & 0xff);
694    code_buffer_.push_back((bits >> 8) & 0xff);
695    code_buffer_.push_back((bits >> 16) & 0xff);
696    code_buffer_.push_back((bits >> 24) & 0xff);
697    // TUNING: replace with proper delay slot handling
698    if (encoder->size == 8) {
699      DCHECK(!IsPseudoLirOp(lir->opcode));
700      const MipsEncodingMap *encoder2 = &EncodingMap[kMipsNop];
701      uint32_t bits2 = encoder2->skeleton;
702      code_buffer_.push_back(bits2 & 0xff);
703      code_buffer_.push_back((bits2 >> 8) & 0xff);
704      code_buffer_.push_back((bits2 >> 16) & 0xff);
705      code_buffer_.push_back((bits2 >> 24) & 0xff);
706    }
707  }
708  return res;
709}
710
711size_t MipsMir2Lir::GetInsnSize(LIR* lir) {
712  DCHECK(!IsPseudoLirOp(lir->opcode));
713  return EncodingMap[lir->opcode].size;
714}
715
716// LIR offset assignment.
717// TODO: consolidate w/ Arm assembly mechanism.
718int MipsMir2Lir::AssignInsnOffsets() {
719  LIR* lir;
720  int offset = 0;
721
722  for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) {
723    lir->offset = offset;
724    if (LIKELY(lir->opcode >= 0)) {
725      if (!lir->flags.is_nop) {
726        offset += lir->flags.size;
727      }
728    } else if (UNLIKELY(lir->opcode == kPseudoPseudoAlign4)) {
729      if (offset & 0x2) {
730        offset += 2;
731        lir->operands[0] = 1;
732      } else {
733        lir->operands[0] = 0;
734      }
735    }
736    /* Pseudo opcodes don't consume space */
737  }
738  return offset;
739}
740
741/*
742 * Walk the compilation unit and assign offsets to instructions
743 * and literals and compute the total size of the compiled unit.
744 * TODO: consolidate w/ Arm assembly mechanism.
745 */
746void MipsMir2Lir::AssignOffsets() {
747  int offset = AssignInsnOffsets();
748
749  /* Const values have to be word aligned */
750  offset = RoundUp(offset, 4);
751
752  /* Set up offsets for literals */
753  data_offset_ = offset;
754
755  offset = AssignLiteralOffset(offset);
756
757  offset = AssignSwitchTablesOffset(offset);
758
759  offset = AssignFillArrayDataOffset(offset);
760
761  total_size_ = offset;
762}
763
764/*
765 * Go over each instruction in the list and calculate the offset from the top
766 * before sending them off to the assembler. If out-of-range branch distance is
767 * seen rearrange the instructions a bit to correct it.
768 * TODO: consolidate w/ Arm assembly mechanism.
769 */
770void MipsMir2Lir::AssembleLIR() {
771  cu_->NewTimingSplit("Assemble");
772  AssignOffsets();
773  int assembler_retries = 0;
774  /*
775   * Assemble here.  Note that we generate code with optimistic assumptions
776   * and if found now to work, we'll have to redo the sequence and retry.
777   */
778
779  while (true) {
780    AssemblerStatus res = AssembleInstructions(0);
781    if (res == kSuccess) {
782      break;
783    } else {
784      assembler_retries++;
785      if (assembler_retries > MAX_ASSEMBLER_RETRIES) {
786        CodegenDump();
787        LOG(FATAL) << "Assembler error - too many retries";
788      }
789      // Redo offsets and try again
790      AssignOffsets();
791      code_buffer_.clear();
792    }
793  }
794
795  // Install literals
796  InstallLiteralPools();
797
798  // Install switch tables
799  InstallSwitchTables();
800
801  // Install fill array data
802  InstallFillArrayData();
803
804  // Create the mapping table and native offset to reference map.
805  cu_->NewTimingSplit("PcMappingTable");
806  CreateMappingTables();
807
808  cu_->NewTimingSplit("GcMap");
809  CreateNativeGcMap();
810}
811
812}  // namespace art
813