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