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