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