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