blob: a70d9dafc2ecadae645e41b0ba6dff4ee927680f [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
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 "../../Dalvik.h"
18#include "../../CompilerInternals.h"
19#include "MipsLIR.h"
20#include "Codegen.h"
21#include <sys/mman.h> /* for protection change */
22
23namespace art {
24
25#define MAX_ASSEMBLER_RETRIES 50
26
27/*
28 * opcode: MipsOpCode enum
29 * skeleton: pre-designated bit-pattern for this opcode
30 * k0: key to applying ds/de
31 * ds: dest start bit position
32 * de: dest end bit position
33 * k1: key to applying s1s/s1e
34 * s1s: src1 start bit position
35 * s1e: src1 end bit position
36 * k2: key to applying s2s/s2e
37 * s2s: src2 start bit position
38 * s2e: src2 end bit position
39 * operands: number of operands (for sanity check purposes)
40 * name: mnemonic name
41 * fmt: for pretty-printing
42 */
43#define ENCODING_MAP(opcode, skeleton, k0, ds, de, k1, s1s, s1e, k2, s2s, s2e, \
44 k3, k3s, k3e, flags, name, fmt, size) \
45 {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \
46 {k3, k3s, k3e}}, opcode, flags, name, fmt, size}
47
48/* Instruction dump string format keys: !pf, where "!" is the start
49 * of the key, "p" is which numeric operand to use and "f" is the
50 * print format.
51 *
52 * [p]ositions:
53 * 0 -> operands[0] (dest)
54 * 1 -> operands[1] (src1)
55 * 2 -> operands[2] (src2)
56 * 3 -> operands[3] (extra)
57 *
58 * [f]ormats:
59 * h -> 4-digit hex
60 * d -> decimal
61 * E -> decimal*4
62 * F -> decimal*2
63 * c -> branch condition (beq, bne, etc.)
64 * t -> pc-relative target
65 * T -> pc-region target
66 * u -> 1st half of bl[x] target
67 * v -> 2nd half ob bl[x] target
68 * R -> register list
69 * s -> single precision floating point register
70 * S -> double precision floating point register
71 * m -> Thumb2 modified immediate
72 * n -> complimented Thumb2 modified immediate
73 * M -> Thumb2 16-bit zero-extended immediate
74 * b -> 4-digit binary
buzbee82488f52012-03-02 08:20:26 -080075 * N -> append a NOP
buzbeee3acd072012-02-25 17:03:10 -080076 *
77 * [!] escape. To insert "!", use "!!"
78 */
buzbee5de34942012-03-01 14:51:57 -080079/* NOTE: must be kept in sync with enum MipsOpcode from LIR.h */
buzbee82488f52012-03-02 08:20:26 -080080/*
81 * TUNING: We're currently punting on the branch delay slots. All branch
82 * instructions in this map are given a size of 8, which during assembly
83 * is expanded to include a nop. This scheme should be replaced with
84 * an assembler pass to fill those slots when possible.
85 */
buzbeee3acd072012-02-25 17:03:10 -080086MipsEncodingMap EncodingMap[kMipsLast] = {
87 ENCODING_MAP(kMips32BitData, 0x00000000,
88 kFmtBitBlt, 31, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
89 kFmtUnused, -1, -1, IS_UNARY_OP,
buzbee71ac9942012-03-01 17:23:10 -080090 "data", "0x!0h(!0d)", 4),
buzbeee3acd072012-02-25 17:03:10 -080091 ENCODING_MAP(kMipsAddiu, 0x24000000,
92 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
93 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -080094 "addiu", "!0r,!1r,0x!2h(!2d)", 4),
buzbeee3acd072012-02-25 17:03:10 -080095 ENCODING_MAP(kMipsAddu, 0x00000021,
96 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
97 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -080098 "addu", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -080099 ENCODING_MAP(kMipsAnd, 0x00000024,
100 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
101 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800102 "and", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800103 ENCODING_MAP(kMipsAndi, 0x30000000,
104 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
105 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800106 "andi", "!0r,!1r,0x!2h(!2d)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800107 ENCODING_MAP(kMipsB, 0x10000000,
108 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
buzbeea2ebdd72012-03-04 14:57:06 -0800109 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | NEEDS_FIXUP,
buzbee82488f52012-03-02 08:20:26 -0800110 "b", "!0t!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800111 ENCODING_MAP(kMipsBal, 0x04110000,
112 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
buzbeea2ebdd72012-03-04 14:57:06 -0800113 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR |
114 NEEDS_FIXUP, "bal", "!0t!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800115 ENCODING_MAP(kMipsBeq, 0x10000000,
116 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
buzbeea2ebdd72012-03-04 14:57:06 -0800117 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 |
118 NEEDS_FIXUP, "beq", "!0r,!1r,!2t!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800119 ENCODING_MAP(kMipsBeqz, 0x10000000, /* same as beq above with t = $zero */
120 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
buzbeea2ebdd72012-03-04 14:57:06 -0800121 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
122 NEEDS_FIXUP, "beqz", "!0r,!1t!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800123 ENCODING_MAP(kMipsBgez, 0x04010000,
124 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
buzbeea2ebdd72012-03-04 14:57:06 -0800125 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
126 NEEDS_FIXUP, "bgez", "!0r,!1t!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800127 ENCODING_MAP(kMipsBgtz, 0x1C000000,
128 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
buzbeea2ebdd72012-03-04 14:57:06 -0800129 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
130 NEEDS_FIXUP, "bgtz", "!0r,!1t!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800131 ENCODING_MAP(kMipsBlez, 0x18000000,
132 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
buzbeea2ebdd72012-03-04 14:57:06 -0800133 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
134 NEEDS_FIXUP, "blez", "!0r,!1t!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800135 ENCODING_MAP(kMipsBltz, 0x04000000,
136 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
buzbeea2ebdd72012-03-04 14:57:06 -0800137 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
138 NEEDS_FIXUP, "bltz", "!0r,!1t!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800139 ENCODING_MAP(kMipsBnez, 0x14000000, /* same as bne below with t = $zero */
140 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
buzbeea2ebdd72012-03-04 14:57:06 -0800141 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
142 NEEDS_FIXUP, "bnez", "!0r,!1t!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800143 ENCODING_MAP(kMipsBne, 0x14000000,
144 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
buzbeea2ebdd72012-03-04 14:57:06 -0800145 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 |
146 NEEDS_FIXUP, "bne", "!0r,!1r,!2t!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800147 ENCODING_MAP(kMipsDiv, 0x0000001a,
148 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtBitBlt, 25, 21,
149 kFmtBitBlt, 20, 16, IS_QUAD_OP | REG_DEF01 | REG_USE23,
buzbee71ac9942012-03-01 17:23:10 -0800150 "div", "!2r,!3r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800151#if __mips_isa_rev>=2
152 ENCODING_MAP(kMipsExt, 0x7c000000,
153 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 10, 6,
154 kFmtBitBlt, 15, 11, IS_QUAD_OP | REG_DEF0 | REG_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800155 "ext", "!0r,!1r,!2d,!3D", 4),
buzbeee3acd072012-02-25 17:03:10 -0800156#endif
157 ENCODING_MAP(kMipsJal, 0x0c000000,
158 kFmtBitBlt, 25, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
159 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR,
buzbee82488f52012-03-02 08:20:26 -0800160 "jal", "!0T(!0E)!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800161 ENCODING_MAP(kMipsJalr, 0x00000009,
162 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1,
163 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_DEF0_USE1,
buzbee82488f52012-03-02 08:20:26 -0800164 "jalr", "!0r,!1r!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800165 ENCODING_MAP(kMipsJr, 0x00000008,
166 kFmtBitBlt, 25, 21, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
buzbeea2ebdd72012-03-04 14:57:06 -0800167 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
168 NEEDS_FIXUP, "jr", "!0r!0N", 8),
buzbeee3acd072012-02-25 17:03:10 -0800169 ENCODING_MAP(kMipsLahi, 0x3C000000,
170 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
171 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
buzbee71ac9942012-03-01 17:23:10 -0800172 "lahi/lui", "!0r,0x!1h(!1d)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800173 ENCODING_MAP(kMipsLalo, 0x34000000,
174 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
175 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800176 "lalo/ori", "!0r,!1r,0x!2h(!2d)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800177 ENCODING_MAP(kMipsLui, 0x3C000000,
178 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
179 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
buzbee71ac9942012-03-01 17:23:10 -0800180 "lui", "!0r,0x!1h(!1d)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800181 ENCODING_MAP(kMipsLb, 0x80000000,
182 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
183 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
buzbee71ac9942012-03-01 17:23:10 -0800184 "lb", "!0r,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800185 ENCODING_MAP(kMipsLbu, 0x90000000,
186 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
187 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
buzbee71ac9942012-03-01 17:23:10 -0800188 "lbu", "!0r,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800189 ENCODING_MAP(kMipsLh, 0x84000000,
190 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
191 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
buzbee71ac9942012-03-01 17:23:10 -0800192 "lh", "!0r,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800193 ENCODING_MAP(kMipsLhu, 0x94000000,
194 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
195 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
buzbee71ac9942012-03-01 17:23:10 -0800196 "lhu", "!0r,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800197 ENCODING_MAP(kMipsLw, 0x8C000000,
198 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
199 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
buzbee71ac9942012-03-01 17:23:10 -0800200 "lw", "!0r,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800201 ENCODING_MAP(kMipsMfhi, 0x00000010,
202 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
203 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800204 "mfhi", "!0r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800205 ENCODING_MAP(kMipsMflo, 0x00000012,
206 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
207 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800208 "mflo", "!0r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800209 ENCODING_MAP(kMipsMove, 0x00000025, /* or using zero reg */
210 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1,
211 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800212 "move", "!0r,!1r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800213 ENCODING_MAP(kMipsMovz, 0x0000000a,
214 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
215 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800216 "movz", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800217 ENCODING_MAP(kMipsMul, 0x70000002,
218 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
219 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800220 "mul", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800221 ENCODING_MAP(kMipsNop, 0x00000000,
222 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
223 kFmtUnused, -1, -1, NO_OPERAND,
buzbeec5159d52012-03-03 11:48:39 -0800224 "nop", ";", 4),
buzbeee3acd072012-02-25 17:03:10 -0800225 ENCODING_MAP(kMipsNor, 0x00000027, /* used for "not" too */
226 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
227 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800228 "nor", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800229 ENCODING_MAP(kMipsOr, 0x00000025,
230 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
231 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800232 "or", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800233 ENCODING_MAP(kMipsOri, 0x34000000,
234 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
235 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800236 "ori", "!0r,!1r,0x!2h(!2d)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800237 ENCODING_MAP(kMipsPref, 0xCC000000,
238 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
239 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE2,
buzbee71ac9942012-03-01 17:23:10 -0800240 "pref", "!0d,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800241 ENCODING_MAP(kMipsSb, 0xA0000000,
242 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
243 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
buzbee71ac9942012-03-01 17:23:10 -0800244 "sb", "!0r,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800245#if __mips_isa_rev>=2
246 ENCODING_MAP(kMipsSeb, 0x7c000420,
247 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1,
248 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800249 "seb", "!0r,!1r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800250 ENCODING_MAP(kMipsSeh, 0x7c000620,
251 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1,
252 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800253 "seh", "!0r,!1r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800254#endif
255 ENCODING_MAP(kMipsSh, 0xA4000000,
256 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
257 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
buzbee71ac9942012-03-01 17:23:10 -0800258 "sh", "!0r,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800259 ENCODING_MAP(kMipsSll, 0x00000000,
260 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
261 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800262 "sll", "!0r,!1r,0x!2h(!2d)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800263 ENCODING_MAP(kMipsSllv, 0x00000004,
264 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
265 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800266 "sllv", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800267 ENCODING_MAP(kMipsSlt, 0x0000002a,
268 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
269 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800270 "slt", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800271 ENCODING_MAP(kMipsSlti, 0x28000000,
272 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
273 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800274 "slti", "!0r,!1r,0x!2h(!2d)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800275 ENCODING_MAP(kMipsSltu, 0x0000002b,
276 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
277 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800278 "sltu", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800279 ENCODING_MAP(kMipsSra, 0x00000003,
280 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
281 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800282 "sra", "!0r,!1r,0x!2h(!2d)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800283 ENCODING_MAP(kMipsSrav, 0x00000007,
284 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
285 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800286 "srav", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800287 ENCODING_MAP(kMipsSrl, 0x00000002,
288 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6,
289 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800290 "srl", "!0r,!1r,0x!2h(!2d)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800291 ENCODING_MAP(kMipsSrlv, 0x00000006,
292 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21,
293 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800294 "srlv", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800295 ENCODING_MAP(kMipsSubu, 0x00000023, /* used for "neg" too */
296 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
297 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800298 "subu", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800299 ENCODING_MAP(kMipsSw, 0xAC000000,
300 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
301 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
buzbee71ac9942012-03-01 17:23:10 -0800302 "sw", "!0r,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800303 ENCODING_MAP(kMipsXor, 0x00000026,
304 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
305 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800306 "xor", "!0r,!1r,!2r", 4),
buzbeee3acd072012-02-25 17:03:10 -0800307 ENCODING_MAP(kMipsXori, 0x38000000,
308 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0,
309 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800310 "xori", "!0r,!1r,0x!2h(!2d)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800311#ifdef __mips_hard_float
312 ENCODING_MAP(kMipsFadds, 0x46000000,
313 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
314 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800315 "add.s", "!0s,!1s,!2s", 4),
buzbeee3acd072012-02-25 17:03:10 -0800316 ENCODING_MAP(kMipsFsubs, 0x46000001,
317 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
318 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800319 "sub.s", "!0s,!1s,!2s", 4),
buzbeee3acd072012-02-25 17:03:10 -0800320 ENCODING_MAP(kMipsFmuls, 0x46000002,
321 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
322 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800323 "mul.s", "!0s,!1s,!2s", 4),
buzbeee3acd072012-02-25 17:03:10 -0800324 ENCODING_MAP(kMipsFdivs, 0x46000003,
325 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16,
326 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800327 "div.s", "!0s,!1s,!2s", 4),
buzbeee3acd072012-02-25 17:03:10 -0800328 ENCODING_MAP(kMipsFaddd, 0x46200000,
329 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
330 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800331 "add.d", "!0S,!1S,!2S", 4),
buzbeee3acd072012-02-25 17:03:10 -0800332 ENCODING_MAP(kMipsFsubd, 0x46200001,
333 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
334 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800335 "sub.d", "!0S,!1S,!2S", 4),
buzbeee3acd072012-02-25 17:03:10 -0800336 ENCODING_MAP(kMipsFmuld, 0x46200002,
337 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
338 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800339 "mul.d", "!0S,!1S,!2S", 4),
buzbeee3acd072012-02-25 17:03:10 -0800340 ENCODING_MAP(kMipsFdivd, 0x46200003,
341 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16,
342 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
buzbee71ac9942012-03-01 17:23:10 -0800343 "div.d", "!0S,!1S,!2S", 4),
buzbeee3acd072012-02-25 17:03:10 -0800344 ENCODING_MAP(kMipsFcvtsd, 0x46200020,
345 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
346 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800347 "cvt.s.d", "!0s,!1S", 4),
buzbeee3acd072012-02-25 17:03:10 -0800348 ENCODING_MAP(kMipsFcvtsw, 0x46800020,
349 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
350 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800351 "cvt.s.w", "!0s,!1s", 4),
buzbeee3acd072012-02-25 17:03:10 -0800352 ENCODING_MAP(kMipsFcvtds, 0x46000021,
353 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
354 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800355 "cvt.d.s", "!0S,!1s", 4),
buzbeee3acd072012-02-25 17:03:10 -0800356 ENCODING_MAP(kMipsFcvtdw, 0x46800021,
357 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
358 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800359 "cvt.d.w", "!0S,!1s", 4),
buzbeee3acd072012-02-25 17:03:10 -0800360 ENCODING_MAP(kMipsFcvtws, 0x46000024,
361 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
362 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800363 "cvt.w.s", "!0s,!1s", 4),
buzbeee3acd072012-02-25 17:03:10 -0800364 ENCODING_MAP(kMipsFcvtwd, 0x46200024,
365 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
366 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800367 "cvt.w.d", "!0s,!1S", 4),
buzbeee3acd072012-02-25 17:03:10 -0800368 ENCODING_MAP(kMipsFmovs, 0x46000006,
369 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
370 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800371 "mov.s", "!0s,!1s", 4),
buzbeee3acd072012-02-25 17:03:10 -0800372 ENCODING_MAP(kMipsFmovd, 0x46200006,
373 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1,
374 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800375 "mov.d", "!0S,!1S", 4),
buzbeee3acd072012-02-25 17:03:10 -0800376 ENCODING_MAP(kMipsFlwc1, 0xC4000000,
377 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
378 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
buzbee71ac9942012-03-01 17:23:10 -0800379 "lwc1", "!0s,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800380 ENCODING_MAP(kMipsFldc1, 0xD4000000,
381 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
382 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD,
buzbee71ac9942012-03-01 17:23:10 -0800383 "ldc1", "!0S,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800384 ENCODING_MAP(kMipsFswc1, 0xE4000000,
385 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
386 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
buzbee71ac9942012-03-01 17:23:10 -0800387 "swc1", "!0s,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800388 ENCODING_MAP(kMipsFsdc1, 0xF4000000,
389 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
390 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
buzbee71ac9942012-03-01 17:23:10 -0800391 "sdc1", "!0S,!1d(!2r)", 4),
buzbeee3acd072012-02-25 17:03:10 -0800392 ENCODING_MAP(kMipsMfc1, 0x44000000,
393 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
394 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1,
buzbee71ac9942012-03-01 17:23:10 -0800395 "mfc1", "!0r,!1s", 4),
buzbeee3acd072012-02-25 17:03:10 -0800396 ENCODING_MAP(kMipsMtc1, 0x44800000,
397 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1,
398 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1,
buzbee71ac9942012-03-01 17:23:10 -0800399 "mtc1", "!0r,!1s", 4),
buzbeee3acd072012-02-25 17:03:10 -0800400#endif
buzbeec5159d52012-03-03 11:48:39 -0800401 ENCODING_MAP(kMipsDelta, 0x27e00000,
402 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, 15, 0,
buzbeea2ebdd72012-03-04 14:57:06 -0800403 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | REG_USE_LR |
404 NEEDS_FIXUP, "addiu", "!0r,r_ra,0x!1h(!1d)", 4),
buzbeec5159d52012-03-03 11:48:39 -0800405 ENCODING_MAP(kMipsDeltaHi, 0x3C000000,
406 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
buzbeea2ebdd72012-03-04 14:57:06 -0800407 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | NEEDS_FIXUP,
buzbeec5159d52012-03-03 11:48:39 -0800408 "lui", "!0r,0x!1h(!1d)", 4),
409 ENCODING_MAP(kMipsDeltaLo, 0x34000000,
410 kFmtBlt5_2, 16, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
buzbeea2ebdd72012-03-04 14:57:06 -0800411 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0_USE0 | NEEDS_FIXUP,
buzbeec5159d52012-03-03 11:48:39 -0800412 "ori", "!0r,!0r,0x!1h(!1d)", 4),
buzbeea2ebdd72012-03-04 14:57:06 -0800413 ENCODING_MAP(kMipsCurrPC, 0x04110020,
buzbeec5159d52012-03-03 11:48:39 -0800414 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
415 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR,
416 "pc2ra", "; r_ra <- .+8", 4),
buzbeea2ebdd72012-03-04 14:57:06 -0800417 ENCODING_MAP(kMipsSync, 0x0000000f,
418 kFmtBitBlt, 10, 6, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
419 kFmtUnused, -1, -1, IS_UNARY_OP,
420 "sync", ";", 4),
buzbeee3acd072012-02-25 17:03:10 -0800421 ENCODING_MAP(kMipsUndefined, 0x64000000,
422 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
423 kFmtUnused, -1, -1, NO_OPERAND,
buzbee71ac9942012-03-01 17:23:10 -0800424 "undefined", "", 4),
buzbeee3acd072012-02-25 17:03:10 -0800425};
426
buzbeea2ebdd72012-03-04 14:57:06 -0800427
428/*
429 * Convert a short-form branch to long form. Hopefully, this won't happen
430 * very often because the PIC sequence is especially unfortunate.
431 *
432 * Orig conditional branch
433 * -----------------------
434 * beq rs,rt,target
435 *
436 * Long conditional branch
437 * -----------------------
438 * bne rs,rt,hop
439 * bal .+8 ; r_RA <- anchor
440 * lui r_AT, ((target-anchor) >> 16)
441 * anchor:
442 * ori r_AT, r_AT, ((target-anchor) & 0xffff)
443 * addu r_AT, r_AT, r_RA
444 * jr r_AT
445 * hop:
446 *
447 * Orig unconditional branch
448 * -------------------------
449 * b target
450 *
451 * Long unconditional branch
452 * -----------------------
453 * bal .+8 ; r_RA <- anchor
454 * lui r_AT, ((target-anchor) >> 16)
455 * anchor:
456 * ori r_AT, r_AT, ((target-anchor) & 0xffff)
457 * addu r_AT, r_AT, r_RA
458 * jr r_AT
459 *
460 *
461 * NOTE: An out-of-range bal isn't supported because it should
462 * never happen with the current PIC model.
463 */
464void convertShortToLongBranch(CompilationUnit* cUnit, LIR* lir)
465{
466 // For conditional branches we'll need to reverse the sense
467 bool unconditional = false;
468 int opcode = lir->opcode;
469 int dalvikOffset = lir->dalvikOffset;
470 switch(opcode) {
471 case kMipsBal:
472 LOG(FATAL) << "long branch and link unsupported";
473 case kMipsB:
474 unconditional = true;
475 break;
476 case kMipsBeq: opcode = kMipsBne; break;
477 case kMipsBne: opcode = kMipsBeq; break;
478 case kMipsBeqz: opcode = kMipsBnez; break;
479 case kMipsBgez: opcode = kMipsBltz; break;
480 case kMipsBgtz: opcode = kMipsBlez; break;
481 case kMipsBlez: opcode = kMipsBgtz; break;
482 case kMipsBltz: opcode = kMipsBgez; break;
483 case kMipsBnez: opcode = kMipsBeqz; break;
484 default:
485 LOG(FATAL) << "Unexpected branch kind " << (int)opcode;
486 }
487 LIR* hopTarget = NULL;
488 if (!unconditional) {
489 hopTarget = rawLIR(cUnit, dalvikOffset, kPseudoTargetLabel);
490 LIR* hopBranch = rawLIR(cUnit, dalvikOffset, opcode, lir->operands[0],
491 lir->operands[1], 0, 0, hopTarget);
492 oatInsertLIRBefore(lir, hopBranch);
493 }
494 LIR* currPC = rawLIR(cUnit, dalvikOffset, kMipsCurrPC);
495 oatInsertLIRBefore(lir, currPC);
496 LIR* anchor = rawLIR(cUnit, dalvikOffset, kPseudoTargetLabel);
497 LIR* deltaHi = rawLIR(cUnit, dalvikOffset, kMipsDeltaHi, r_AT, 0,
498 (uintptr_t)anchor, 0, lir->target);
499 oatInsertLIRBefore(lir, deltaHi);
500 oatInsertLIRBefore(lir, anchor);
501 LIR* deltaLo = rawLIR(cUnit, dalvikOffset, kMipsDeltaLo, r_AT, 0,
502 (uintptr_t)anchor, 0, lir->target);
503 oatInsertLIRBefore(lir, deltaLo);
504 LIR* addu = rawLIR(cUnit, dalvikOffset, kMipsAddu, r_AT, r_AT, r_RA);
505 oatInsertLIRBefore(lir, addu);
506 LIR* jr = rawLIR(cUnit, dalvikOffset, kMipsJr, r_AT);
507 oatInsertLIRBefore(lir, jr);
508 if (!unconditional) {
509 oatInsertLIRBefore(lir, hopTarget);
510 }
511 lir->flags.isNop = true;
512}
513
buzbeee3acd072012-02-25 17:03:10 -0800514/*
515 * Assemble the LIR into binary instruction format. Note that we may
516 * discover that pc-relative displacements may not fit the selected
517 * instruction. In those cases we will try to substitute a new code
518 * sequence or request that the trace be shortened and retried.
519 */
520AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,
521 intptr_t startAddr)
522{
buzbee5de34942012-03-01 14:51:57 -0800523 LIR *lir;
524 AssemblerStatus res = kSuccess; // Assume success
buzbeee3acd072012-02-25 17:03:10 -0800525
buzbee5de34942012-03-01 14:51:57 -0800526 for (lir = (LIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
buzbeee3acd072012-02-25 17:03:10 -0800527 if (lir->opcode < 0) {
528 continue;
529 }
530
531
532 if (lir->flags.isNop) {
533 continue;
534 }
535
buzbeea2ebdd72012-03-04 14:57:06 -0800536 if (lir->flags.pcRelFixup) {
537 if (lir->opcode == kMipsDelta) {
538 /*
539 * The "Delta" pseudo-ops load the difference between
540 * two pc-relative locations into a the target register
541 * found in operands[0]. The delta is determined by
542 * (label2 - label1), where label1 is a standard
543 * kPseudoTargetLabel and is stored in operands[2].
544 * If operands[3] is null, then label2 is a kPseudoTargetLabel
545 * and is found in lir->target. If operands[3] is non-NULL,
546 * then it is a Switch/Data table.
547 */
548 int offset1 = ((LIR*)lir->operands[2])->offset;
549 SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
550 int offset2 = tabRec ? tabRec->offset : lir->target->offset;
551 int delta = offset2 - offset1;
552 if ((delta & 0xffff) == delta) {
553 // Fits
554 lir->operands[1] = delta;
555 } else {
556 // Doesn't fit - must expand to kMipsDelta[Hi|Lo] pair
557 LIR *newDeltaHi =
558 rawLIR(cUnit, lir->dalvikOffset, kMipsDeltaHi,
559 lir->operands[0], 0, lir->operands[2],
560 lir->operands[3], lir->target);
561 oatInsertLIRBefore((LIR*)lir, (LIR*)newDeltaHi);
562 LIR *newDeltaLo =
563 rawLIR(cUnit, lir->dalvikOffset, kMipsDeltaLo,
564 lir->operands[0], 0, lir->operands[2],
565 lir->operands[3], lir->target);
566 oatInsertLIRBefore((LIR*)lir, (LIR*)newDeltaLo);
567 lir->flags.isNop = true;
568 res = kRetryAll;
569 }
570 } else if (lir->opcode == kMipsDeltaLo) {
571 int offset1 = ((LIR*)lir->operands[2])->offset;
572 SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
573 int offset2 = tabRec ? tabRec->offset : lir->target->offset;
574 int delta = offset2 - offset1;
575 lir->operands[1] = delta & 0xffff;
576 } else if (lir->opcode == kMipsDeltaHi) {
577 int offset1 = ((LIR*)lir->operands[2])->offset;
578 SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
579 int offset2 = tabRec ? tabRec->offset : lir->target->offset;
580 int delta = offset2 - offset1;
581 lir->operands[1] = (delta >> 16) & 0xffff;
582 } else if (lir->opcode == kMipsB || lir->opcode == kMipsBal) {
583 LIR *targetLIR = (LIR *) lir->target;
584 intptr_t pc = lir->offset + 4;
585 intptr_t target = targetLIR->offset;
586 int delta = target - pc;
587 if (delta & 0x3) {
588 LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
589 }
590 if (delta > 131068 || delta < -131069) {
591 res = kRetryAll;
592 convertShortToLongBranch(cUnit, lir);
593 } else {
594 lir->operands[0] = delta >> 2;
595 }
596 } else if (lir->opcode >= kMipsBeqz && lir->opcode <= kMipsBnez) {
597 LIR *targetLIR = (LIR *) lir->target;
598 intptr_t pc = lir->offset + 4;
599 intptr_t target = targetLIR->offset;
600 int delta = target - pc;
601 if (delta & 0x3) {
602 LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
603 }
604 if (delta > 131068 || delta < -131069) {
605 res = kRetryAll;
606 convertShortToLongBranch(cUnit, lir);
607 } else {
608 lir->operands[1] = delta >> 2;
609 }
610 } else if (lir->opcode == kMipsBeq || lir->opcode == kMipsBne) {
611 LIR *targetLIR = (LIR *) lir->target;
612 intptr_t pc = lir->offset + 4;
613 intptr_t target = targetLIR->offset;
614 int delta = target - pc;
615 if (delta & 0x3) {
616 LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
617 }
618 if (delta > 131068 || delta < -131069) {
619 res = kRetryAll;
620 convertShortToLongBranch(cUnit, lir);
621 } else {
622 lir->operands[2] = delta >> 2;
623 }
624 } else if (lir->opcode == kMipsJal) {
625 intptr_t curPC = (startAddr + lir->offset + 4) & ~3;
626 intptr_t target = lir->operands[0];
627 /* ensure PC-region branch can be used */
628 DCHECK_EQ((curPC & 0xF0000000), (target & 0xF0000000));
629 if (target & 0x3) {
630 LOG(FATAL) << "Jump target not multiple of 4: " << target;
631 }
632 lir->operands[0] = target >> 2;
633 } else if (lir->opcode == kMipsLahi) { /* ld address hi (via lui) */
634 LIR *targetLIR = (LIR *) lir->target;
635 intptr_t target = startAddr + targetLIR->offset;
636 lir->operands[1] = target >> 16;
637 } else if (lir->opcode == kMipsLalo) { /* ld address lo (via ori) */
638 LIR *targetLIR = (LIR *) lir->target;
639 intptr_t target = startAddr + targetLIR->offset;
640 lir->operands[2] = lir->operands[2] + target;
buzbeec5159d52012-03-03 11:48:39 -0800641 }
buzbeee3acd072012-02-25 17:03:10 -0800642 }
643
buzbee5de34942012-03-01 14:51:57 -0800644 /*
645 * If one of the pc-relative instructions expanded we'll have
646 * to make another pass. Don't bother to fully assemble the
647 * instruction.
648 */
649 if (res != kSuccess) {
650 continue;
651 }
652 const MipsEncodingMap *encoder = &EncodingMap[lir->opcode];
buzbeee3acd072012-02-25 17:03:10 -0800653 u4 bits = encoder->skeleton;
654 int i;
655 for (i = 0; i < 4; i++) {
656 u4 operand;
657 u4 value;
658 operand = lir->operands[i];
659 switch(encoder->fieldLoc[i].kind) {
660 case kFmtUnused:
661 break;
662 case kFmtBitBlt:
663 if (encoder->fieldLoc[i].start == 0 && encoder->fieldLoc[i].end == 31) {
664 value = operand;
665 } else {
666 value = (operand << encoder->fieldLoc[i].start) &
667 ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
668 }
669 bits |= value;
670 break;
buzbeec5159d52012-03-03 11:48:39 -0800671 case kFmtBlt5_2:
672 value = (operand & 0x1f);
673 bits |= (value << encoder->fieldLoc[i].start);
674 bits |= (value << encoder->fieldLoc[i].end);
675 break;
buzbeee3acd072012-02-25 17:03:10 -0800676 case kFmtDfp: {
677 DCHECK(DOUBLEREG(operand));
buzbee5de34942012-03-01 14:51:57 -0800678 DCHECK((operand & 0x1) == 0);
buzbeee3acd072012-02-25 17:03:10 -0800679 value = ((operand & FP_REG_MASK) << encoder->fieldLoc[i].start) &
680 ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
681 bits |= value;
682 break;
683 }
684 case kFmtSfp:
685 DCHECK(SINGLEREG(operand));
686 value = ((operand & FP_REG_MASK) << encoder->fieldLoc[i].start) &
687 ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
688 bits |= value;
689 break;
690 default:
691 LOG(FATAL) << "Bad encoder format: "
buzbee5de34942012-03-01 14:51:57 -0800692 << (int)encoder->fieldLoc[i].kind;
buzbeee3acd072012-02-25 17:03:10 -0800693 }
694 }
buzbee5de34942012-03-01 14:51:57 -0800695 // FIXME: need multi-endian handling here
696 cUnit->codeBuffer.push_back((bits >> 16) & 0xffff);
697 cUnit->codeBuffer.push_back(bits & 0xffff);
buzbee82488f52012-03-02 08:20:26 -0800698 // TUNING: replace with proper delay slot handling
699 if (encoder->size == 8) {
700 const MipsEncodingMap *encoder = &EncodingMap[kMipsNop];
701 u4 bits = encoder->skeleton;
702 cUnit->codeBuffer.push_back((bits >> 16) & 0xffff);
703 cUnit->codeBuffer.push_back(bits & 0xffff);
704 }
buzbeee3acd072012-02-25 17:03:10 -0800705 }
buzbee5de34942012-03-01 14:51:57 -0800706 return res;
buzbeee3acd072012-02-25 17:03:10 -0800707}
708
709/*
710 * Target-dependent offset assignment.
711 * TODO: normalize usage of flags.size and make this target
712 * independent.
713 */
714int oatAssignInsnOffsets(CompilationUnit* cUnit)
715{
buzbee5de34942012-03-01 14:51:57 -0800716 LIR* mipsLIR;
buzbeee3acd072012-02-25 17:03:10 -0800717 int offset = 0;
718
buzbee5de34942012-03-01 14:51:57 -0800719 for (mipsLIR = (LIR *) cUnit->firstLIRInsn;
720 mipsLIR;
721 mipsLIR = NEXT_LIR(mipsLIR)) {
722 mipsLIR->offset = offset;
buzbeee3acd072012-02-25 17:03:10 -0800723 if (mipsLIR->opcode >= 0) {
724 if (!mipsLIR->flags.isNop) {
buzbee71ac9942012-03-01 17:23:10 -0800725 mipsLIR->flags.size = EncodingMap[mipsLIR->opcode].size;
buzbeee3acd072012-02-25 17:03:10 -0800726 offset += mipsLIR->flags.size;
727 }
buzbee31a4a6f2012-02-28 15:36:15 -0800728 } else if (mipsLIR->opcode == kPseudoPseudoAlign4) {
buzbeee3acd072012-02-25 17:03:10 -0800729 if (offset & 0x2) {
730 offset += 2;
731 mipsLIR->operands[0] = 1;
732 } else {
733 mipsLIR->operands[0] = 0;
734 }
735 }
736 /* Pseudo opcodes don't consume space */
737 }
738
739 return offset;
740}
741
742} // namespace art