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