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