assemble_mips.cc revision 027f0ff64c2512b9a5f1f54f3fea1bec481eb0f5
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "codegen_mips.h" 18 19#include "base/logging.h" 20#include "dex/compiler_ir.h" 21#include "dex/quick/mir_to_lir-inl.h" 22#include "mips_lir.h" 23 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, 149 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), 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, 155 "ext", "!0r,!1r,!2d,!3D", 4), 156 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, 202 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF0 | REG_USE_HI, 203 "mfhi", "!0r", 4), 204 ENCODING_MAP(kMipsMflo, 0x00000012, 205 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 206 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF0 | REG_USE_LO, 207 "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), 244 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), 252 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), 396 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), 404 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), 424 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 439 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 457 * bal .+8 ; rRA <- anchor 458 * lui rAT, ((target-anchor) >> 16) 459 * anchor: 460 * ori rAT, rAT, ((target-anchor) & 0xffff) 461 * addu rAT, rAT, rRA 462 * jalr rZERO, rAT 463 * hop: 464 * 465 * Orig unconditional branch 466 * ------------------------- 467 * b target 468 * 469 * Long unconditional branch 470 * ----------------------- 471 * bal .+8 ; rRA <- anchor 472 * lui rAT, ((target-anchor) >> 16) 473 * anchor: 474 * ori rAT, rAT, ((target-anchor) & 0xffff) 475 * addu rAT, rAT, rRA 476 * jalr rZERO, rAT 477 * 478 * 479 * NOTE: An out-of-range bal isn't supported because it should 480 * never happen with the current PIC model. 481 */ 482void MipsMir2Lir::ConvertShortToLongBranch(LIR* lir) { 483 // 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"; 490 UNREACHABLE(); 491 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; 504 UNREACHABLE(); 505 } 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], 510 lir->operands[1], 0, 0, 0, hop_target); 511 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); 516 LIR* delta_hi = RawLIR(dalvik_offset, kMipsDeltaHi, rAT, 0, WrapPointer(anchor), 0, 0, 517 lir->target); 518 InsertLIRBefore(lir, delta_hi); 519 InsertLIRBefore(lir, anchor); 520 LIR* delta_lo = RawLIR(dalvik_offset, kMipsDeltaLo, rAT, 0, WrapPointer(anchor), 0, 0, 521 lir->target); 522 InsertLIRBefore(lir, delta_lo); 523 LIR* addu = RawLIR(dalvik_offset, kMipsAddu, rAT, rAT, rRA); 524 InsertLIRBefore(lir, addu); 525 LIR* jalr = RawLIR(dalvik_offset, kMipsJalr, rZERO, rAT); 526 InsertLIRBefore(lir, jalr); 527 if (!unconditional) { 528 InsertLIRBefore(lir, hop_target); 529 } 530 NopLIR(lir); 531} 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 */ 539AssemblerStatus MipsMir2Lir::AssembleInstructions(CodeOffset start_addr) { 540 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 553 if (lir->flags.fixup != kFixupNone) { 554 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 */ 565 int offset1 = (reinterpret_cast<LIR*>(UnwrapPointer(lir->operands[2])))->offset; 566 EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(lir->operands[3])); 567 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, 586 lir->operands[0], lir->operands[0], rRA); 587 InsertLIRBefore(lir, new_addu); 588 NopLIR(lir); 589 res = kRetryAll; 590 } 591 } else if (lir->opcode == kMipsDeltaLo) { 592 int offset1 = (reinterpret_cast<LIR*>(UnwrapPointer(lir->operands[2])))->offset; 593 EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(lir->operands[3])); 594 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) { 598 int offset1 = (reinterpret_cast<LIR*>(UnwrapPointer(lir->operands[2])))->offset; 599 EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(lir->operands[3])); 600 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; 605 CodeOffset pc = lir->offset + 4; 606 CodeOffset target = target_lir->offset; 607 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; 619 CodeOffset pc = lir->offset + 4; 620 CodeOffset target = target_lir->offset; 621 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; 633 CodeOffset pc = lir->offset + 4; 634 CodeOffset target = target_lir->offset; 635 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) { 646 CodeOffset cur_pc = (start_addr + lir->offset + 4) & ~3; 647 CodeOffset target = lir->operands[0]; 648 /* 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; 656 CodeOffset target = start_addr + target_lir->offset; 657 lir->operands[1] = target >> 16; 658 } else if (lir->opcode == kMipsLalo) { /* ld address lo (via ori) */ 659 LIR *target_lir = lir->target; 660 CodeOffset target = start_addr + target_lir->offset; 661 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 } 673 DCHECK(!IsPseudoLirOp(lir->opcode)); 674 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: { 699 // TODO: do we need to adjust now that we're using 64BitSolo? 700 DCHECK(RegStorage::IsDouble(operand)) << ", Operand = 0x" << std::hex << operand; 701 DCHECK_EQ((operand & 0x1), 0U); 702 value = (RegStorage::RegNum(operand) << encoder->field_loc[i].start) & 703 ((1 << (encoder->field_loc[i].end + 1)) - 1); 704 bits |= value; 705 break; 706 } 707 case kFmtSfp: 708 DCHECK(RegStorage::IsSingle(operand)) << ", Operand = 0x" << std::hex << operand; 709 value = (RegStorage::RegNum(operand) << encoder->field_loc[i].start) & 710 ((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) { 724 DCHECK(!IsPseudoLirOp(lir->opcode)); 725 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); 731 } 732 } 733 return res; 734} 735 736size_t MipsMir2Lir::GetInsnSize(LIR* lir) { 737 DCHECK(!IsPseudoLirOp(lir->opcode)); 738 return EncodingMap[lir->opcode].size; 739} 740 741// 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 */ 775 offset = RoundUp(offset, 4); 776 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() { 796 cu_->NewTimingSplit("Assemble"); 797 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. 830 cu_->NewTimingSplit("PcMappingTable"); 831 CreateMappingTables(); 832 833 cu_->NewTimingSplit("GcMap"); 834 CreateNativeGcMap(); 835} 836 837} // namespace art 838