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 24 namespace 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 mips_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 */ 87 const MipsEncodingMap MipsMir2Lir::EncodingMap[kMipsLast] = { 88 // The following are common mips32r2, mips32r6 and mips64r6 instructions. 89 ENCODING_MAP(kMips32BitData, 0x00000000, 90 kFmtBitBlt, 31, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 91 kFmtUnused, -1, -1, IS_UNARY_OP, 92 "data", "0x!0h(!0d)", 4), 93 ENCODING_MAP(kMipsAddiu, 0x24000000, 94 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 95 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 96 "addiu", "!0r,!1r,0x!2h(!2d)", 4), 97 ENCODING_MAP(kMipsAddu, 0x00000021, 98 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 99 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 100 "addu", "!0r,!1r,!2r", 4), 101 ENCODING_MAP(kMipsAnd, 0x00000024, 102 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 103 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 104 "and", "!0r,!1r,!2r", 4), 105 ENCODING_MAP(kMipsAndi, 0x30000000, 106 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 107 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 108 "andi", "!0r,!1r,0x!2h(!2d)", 4), 109 ENCODING_MAP(kMipsB, 0x10000000, 110 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 111 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | NEEDS_FIXUP, 112 "b", "!0t!0N", 8), 113 ENCODING_MAP(kMipsBal, 0x04110000, 114 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 115 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR | 116 NEEDS_FIXUP, "bal", "!0t!0N", 8), 117 ENCODING_MAP(kMipsBeq, 0x10000000, 118 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, 119 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 | 120 NEEDS_FIXUP, "beq", "!0r,!1r,!2t!0N", 8), 121 ENCODING_MAP(kMipsBeqz, 0x10000000, // Same as beq above with t = $zero. 122 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 123 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 | 124 NEEDS_FIXUP, "beqz", "!0r,!1t!0N", 8), 125 ENCODING_MAP(kMipsBgez, 0x04010000, 126 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 127 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 | 128 NEEDS_FIXUP, "bgez", "!0r,!1t!0N", 8), 129 ENCODING_MAP(kMipsBgtz, 0x1C000000, 130 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 131 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 | 132 NEEDS_FIXUP, "bgtz", "!0r,!1t!0N", 8), 133 ENCODING_MAP(kMipsBlez, 0x18000000, 134 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 135 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 | 136 NEEDS_FIXUP, "blez", "!0r,!1t!0N", 8), 137 ENCODING_MAP(kMipsBltz, 0x04000000, 138 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 139 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 | 140 NEEDS_FIXUP, "bltz", "!0r,!1t!0N", 8), 141 ENCODING_MAP(kMipsBnez, 0x14000000, // Same as bne below with t = $zero. 142 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 143 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 | 144 NEEDS_FIXUP, "bnez", "!0r,!1t!0N", 8), 145 ENCODING_MAP(kMipsBne, 0x14000000, 146 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, 147 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 | 148 NEEDS_FIXUP, "bne", "!0r,!1r,!2t!0N", 8), 149 ENCODING_MAP(kMipsExt, 0x7c000000, 150 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 10, 6, 151 kFmtBitBlt, 15, 11, IS_QUAD_OP | REG_DEF0 | REG_USE1, 152 "ext", "!0r,!1r,!2d,!3D", 4), 153 ENCODING_MAP(kMipsFaddd, 0x46200000, 154 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16, 155 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 156 "add.d", "!0S,!1S,!2S", 4), 157 ENCODING_MAP(kMipsFadds, 0x46000000, 158 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16, 159 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 160 "add.s", "!0s,!1s,!2s", 4), 161 ENCODING_MAP(kMipsFsubd, 0x46200001, 162 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16, 163 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 164 "sub.d", "!0S,!1S,!2S", 4), 165 ENCODING_MAP(kMipsFsubs, 0x46000001, 166 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16, 167 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 168 "sub.s", "!0s,!1s,!2s", 4), 169 ENCODING_MAP(kMipsFdivd, 0x46200003, 170 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16, 171 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 172 "div.d", "!0S,!1S,!2S", 4), 173 ENCODING_MAP(kMipsFdivs, 0x46000003, 174 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16, 175 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 176 "div.s", "!0s,!1s,!2s", 4), 177 ENCODING_MAP(kMipsFmuld, 0x46200002, 178 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16, 179 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 180 "mul.d", "!0S,!1S,!2S", 4), 181 ENCODING_MAP(kMipsFmuls, 0x46000002, 182 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16, 183 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 184 "mul.s", "!0s,!1s,!2s", 4), 185 ENCODING_MAP(kMipsFcvtsd, 0x46200020, 186 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1, 187 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 188 "cvt.s.d", "!0s,!1S", 4), 189 ENCODING_MAP(kMipsFcvtsw, 0x46800020, 190 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 191 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 192 "cvt.s.w", "!0s,!1s", 4), 193 ENCODING_MAP(kMipsFcvtds, 0x46000021, 194 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 195 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 196 "cvt.d.s", "!0S,!1s", 4), 197 ENCODING_MAP(kMipsFcvtdw, 0x46800021, 198 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 199 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 200 "cvt.d.w", "!0S,!1s", 4), 201 ENCODING_MAP(kMipsFcvtwd, 0x46200024, 202 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1, 203 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 204 "cvt.w.d", "!0s,!1S", 4), 205 ENCODING_MAP(kMipsFcvtws, 0x46000024, 206 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 207 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 208 "cvt.w.s", "!0s,!1s", 4), 209 ENCODING_MAP(kMipsFmovd, 0x46200006, 210 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1, 211 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 212 "mov.d", "!0S,!1S", 4), 213 ENCODING_MAP(kMipsFmovs, 0x46000006, 214 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 215 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 216 "mov.s", "!0s,!1s", 4), 217 ENCODING_MAP(kMipsFnegd, 0x46200007, 218 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1, 219 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 220 "neg.d", "!0S,!1S", 4), 221 ENCODING_MAP(kMipsFnegs, 0x46000007, 222 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 223 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 224 "neg.s", "!0s,!1s", 4), 225 ENCODING_MAP(kMipsFldc1, 0xd4000000, 226 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 227 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 228 "ldc1", "!0S,!1d(!2r)", 4), 229 ENCODING_MAP(kMipsFlwc1, 0xc4000000, 230 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 231 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 232 "lwc1", "!0s,!1d(!2r)", 4), 233 ENCODING_MAP(kMipsFsdc1, 0xf4000000, 234 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 235 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE, 236 "sdc1", "!0S,!1d(!2r)", 4), 237 ENCODING_MAP(kMipsFswc1, 0xe4000000, 238 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 239 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE, 240 "swc1", "!0s,!1d(!2r)", 4), 241 ENCODING_MAP(kMipsJal, 0x0c000000, 242 kFmtBitBlt, 25, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 243 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR, 244 "jal", "!0T(!0E)!0N", 8), 245 ENCODING_MAP(kMipsJalr, 0x00000009, 246 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1, 247 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_DEF0_USE1, 248 "jalr", "!0r,!1r!0N", 8), 249 ENCODING_MAP(kMipsJr, 0x00000008, 250 kFmtBitBlt, 25, 21, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 251 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 | 252 NEEDS_FIXUP, "jr", "!0r!0N", 8), 253 ENCODING_MAP(kMipsLahi, 0x3C000000, 254 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 255 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0, 256 "lahi/lui", "!0r,0x!1h(!1d)", 4), 257 ENCODING_MAP(kMipsLalo, 0x34000000, 258 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 259 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 260 "lalo/ori", "!0r,!1r,0x!2h(!2d)", 4), 261 ENCODING_MAP(kMipsLui, 0x3C000000, 262 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 263 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0, 264 "lui", "!0r,0x!1h(!1d)", 4), 265 ENCODING_MAP(kMipsLb, 0x80000000, 266 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 267 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 268 "lb", "!0r,!1d(!2r)", 4), 269 ENCODING_MAP(kMipsLbu, 0x90000000, 270 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 271 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 272 "lbu", "!0r,!1d(!2r)", 4), 273 ENCODING_MAP(kMipsLh, 0x84000000, 274 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 275 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 276 "lh", "!0r,!1d(!2r)", 4), 277 ENCODING_MAP(kMipsLhu, 0x94000000, 278 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 279 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 280 "lhu", "!0r,!1d(!2r)", 4), 281 ENCODING_MAP(kMipsLw, 0x8C000000, 282 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 283 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 284 "lw", "!0r,!1d(!2r)", 4), 285 ENCODING_MAP(kMipsMove, 0x00000025, // Or using zero reg. 286 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1, 287 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 288 "move", "!0r,!1r", 4), 289 ENCODING_MAP(kMipsMfc1, 0x44000000, 290 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 291 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 292 "mfc1", "!0r,!1s", 4), 293 ENCODING_MAP(kMipsMtc1, 0x44800000, 294 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 295 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1, 296 "mtc1", "!0r,!1s", 4), 297 ENCODING_MAP(kMipsMfhc1, 0x44600000, 298 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 299 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 300 "mfhc1", "!0r,!1s", 4), 301 ENCODING_MAP(kMipsMthc1, 0x44e00000, 302 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 303 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1, 304 "mthc1", "!0r,!1s", 4), 305 ENCODING_MAP(kMipsNop, 0x00000000, 306 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 307 kFmtUnused, -1, -1, NO_OPERAND, 308 "nop", ";", 4), 309 ENCODING_MAP(kMipsNor, 0x00000027, // Used for "not" too. 310 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 311 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 312 "nor", "!0r,!1r,!2r", 4), 313 ENCODING_MAP(kMipsOr, 0x00000025, 314 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 315 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 316 "or", "!0r,!1r,!2r", 4), 317 ENCODING_MAP(kMipsOri, 0x34000000, 318 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 319 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 320 "ori", "!0r,!1r,0x!2h(!2d)", 4), 321 ENCODING_MAP(kMipsPref, 0xCC000000, 322 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 323 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE2, 324 "pref", "!0d,!1d(!2r)", 4), 325 ENCODING_MAP(kMipsSb, 0xA0000000, 326 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 327 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE, 328 "sb", "!0r,!1d(!2r)", 4), 329 ENCODING_MAP(kMipsSeb, 0x7c000420, 330 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1, 331 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 332 "seb", "!0r,!1r", 4), 333 ENCODING_MAP(kMipsSeh, 0x7c000620, 334 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1, 335 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 336 "seh", "!0r,!1r", 4), 337 ENCODING_MAP(kMipsSh, 0xA4000000, 338 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 339 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE, 340 "sh", "!0r,!1d(!2r)", 4), 341 ENCODING_MAP(kMipsSll, 0x00000000, 342 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 343 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 344 "sll", "!0r,!1r,0x!2h(!2d)", 4), 345 ENCODING_MAP(kMipsSllv, 0x00000004, 346 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, 347 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 348 "sllv", "!0r,!1r,!2r", 4), 349 ENCODING_MAP(kMipsSlt, 0x0000002a, 350 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 351 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 352 "slt", "!0r,!1r,!2r", 4), 353 ENCODING_MAP(kMipsSlti, 0x28000000, 354 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 355 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 356 "slti", "!0r,!1r,0x!2h(!2d)", 4), 357 ENCODING_MAP(kMipsSltu, 0x0000002b, 358 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 359 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 360 "sltu", "!0r,!1r,!2r", 4), 361 ENCODING_MAP(kMipsSra, 0x00000003, 362 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 363 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 364 "sra", "!0r,!1r,0x!2h(!2d)", 4), 365 ENCODING_MAP(kMipsSrav, 0x00000007, 366 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, 367 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 368 "srav", "!0r,!1r,!2r", 4), 369 ENCODING_MAP(kMipsSrl, 0x00000002, 370 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 371 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 372 "srl", "!0r,!1r,0x!2h(!2d)", 4), 373 ENCODING_MAP(kMipsSrlv, 0x00000006, 374 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, 375 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 376 "srlv", "!0r,!1r,!2r", 4), 377 ENCODING_MAP(kMipsSubu, 0x00000023, // Used for "neg" too. 378 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 379 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 380 "subu", "!0r,!1r,!2r", 4), 381 ENCODING_MAP(kMipsSw, 0xAC000000, 382 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 383 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE, 384 "sw", "!0r,!1d(!2r)", 4), 385 ENCODING_MAP(kMipsSync, 0x0000000f, 386 kFmtBitBlt, 10, 6, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 387 kFmtUnused, -1, -1, IS_UNARY_OP, 388 "sync", ";", 4), 389 ENCODING_MAP(kMipsXor, 0x00000026, 390 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 391 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 392 "xor", "!0r,!1r,!2r", 4), 393 ENCODING_MAP(kMipsXori, 0x38000000, 394 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 395 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 396 "xori", "!0r,!1r,0x!2h(!2d)", 4), 397 398 // The following are mips32r2 instructions. 399 ENCODING_MAP(kMipsR2Div, 0x0000001a, 400 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1, 401 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF_HI | REG_DEF_LO | REG_USE01, 402 "div", "!0r,!1r", 4), 403 ENCODING_MAP(kMipsR2Mul, 0x70000002, 404 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 405 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 406 "mul", "!0r,!1r,!2r", 4), 407 ENCODING_MAP(kMipsR2Mfhi, 0x00000010, 408 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 409 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF0 | REG_USE_HI, 410 "mfhi", "!0r", 4), 411 ENCODING_MAP(kMipsR2Mflo, 0x00000012, 412 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 413 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF0 | REG_USE_LO, 414 "mflo", "!0r", 4), 415 ENCODING_MAP(kMipsR2Movz, 0x0000000a, 416 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 417 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 418 "movz", "!0r,!1r,!2r", 4), 419 420 // The following are mips32r6 and mips64r6 instructions. 421 ENCODING_MAP(kMipsR6Div, 0x0000009a, 422 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 423 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 424 "div", "!0r,!1r,!2r", 4), 425 ENCODING_MAP(kMipsR6Mod, 0x000000da, 426 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 427 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 428 "mod", "!0r,!1r,!2r", 4), 429 ENCODING_MAP(kMipsR6Mul, 0x00000098, 430 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 431 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 432 "mul", "!0r,!1r,!2r", 4), 433 434 // The following are mips64r6 instructions. 435 ENCODING_MAP(kMips64Daddiu, 0x64000000, 436 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 437 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 438 "daddiu", "!0r,!1r,0x!2h(!2d)", 4), 439 ENCODING_MAP(kMips64Daddu, 0x0000002d, 440 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 441 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 442 "daddu", "!0r,!1r,!2r", 4), 443 ENCODING_MAP(kMips64Dahi, 0x04060000, 444 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 445 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE0, 446 "dahi", "!0r,0x!1h(!1d)", 4), 447 ENCODING_MAP(kMips64Dati, 0x041E0000, 448 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 449 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE0, 450 "dati", "!0r,0x!1h(!1d)", 4), 451 ENCODING_MAP(kMips64Daui, 0x74000000, 452 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 453 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 454 "daui", "!0r,!1r,0x!2h(!2d)", 4), 455 ENCODING_MAP(kMips64Ddiv, 0x0000009e, 456 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 457 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 458 "ddiv", "!0r,!1r,!2r", 4), 459 ENCODING_MAP(kMips64Dmod, 0x000000de, 460 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 461 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 462 "dmod", "!0r,!1r,!2r", 4), 463 ENCODING_MAP(kMips64Dmul, 0x0000009c, 464 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 465 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 466 "dmul", "!0r,!1r,!2r", 4), 467 ENCODING_MAP(kMips64Dmfc1, 0x44200000, 468 kFmtBitBlt, 20, 16, kFmtDfp, 15, 11, kFmtUnused, -1, -1, 469 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 470 "dmfc1", "!0r,!1s", 4), 471 ENCODING_MAP(kMips64Dmtc1, 0x44a00000, 472 kFmtBitBlt, 20, 16, kFmtDfp, 15, 11, kFmtUnused, -1, -1, 473 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1, 474 "dmtc1", "!0r,!1s", 4), 475 ENCODING_MAP(kMips64Drotr32, 0x0000003e | (1 << 21), 476 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 477 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 478 "drotr32", "!0r,!1r,0x!2h(!2d)", 4), 479 ENCODING_MAP(kMips64Dsll, 0x00000038, 480 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 481 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 482 "dsll", "!0r,!1r,0x!2h(!2d)", 4), 483 ENCODING_MAP(kMips64Dsll32, 0x0000003c, 484 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 485 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 486 "dsll32", "!0r,!1r,0x!2h(!2d)", 4), 487 ENCODING_MAP(kMips64Dsrl, 0x0000003a, 488 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 489 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 490 "dsrl", "!0r,!1r,0x!2h(!2d)", 4), 491 ENCODING_MAP(kMips64Dsrl32, 0x0000003e, 492 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 493 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 494 "dsrl32", "!0r,!1r,0x!2h(!2d)", 4), 495 ENCODING_MAP(kMips64Dsra, 0x0000003b, 496 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 497 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 498 "dsra", "!0r,!1r,0x!2h(!2d)", 4), 499 ENCODING_MAP(kMips64Dsra32, 0x0000003f, 500 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 501 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 502 "dsra32", "!0r,!1r,0x!2h(!2d)", 4), 503 ENCODING_MAP(kMips64Dsllv, 0x00000014, 504 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, 505 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 506 "dsllv", "!0r,!1r,!2r", 4), 507 ENCODING_MAP(kMips64Dsrlv, 0x00000016, 508 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, 509 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 510 "dsrlv", "!0r,!1r,!2r", 4), 511 ENCODING_MAP(kMips64Dsrav, 0x00000017, 512 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, 513 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 514 "dsrav", "!0r,!1r,!2r", 4), 515 ENCODING_MAP(kMips64Dsubu, 0x0000002f, 516 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 517 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 518 "dsubu", "!0r,!1r,!2r", 4), 519 ENCODING_MAP(kMips64Ld, 0xdc000000, 520 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 521 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 522 "ld", "!0r,!1d(!2r)", 4), 523 ENCODING_MAP(kMips64Lwu, 0x9c000000, 524 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 525 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 526 "lwu", "!0r,!1d(!2r)", 4), 527 ENCODING_MAP(kMips64Sd, 0xfc000000, 528 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 529 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE, 530 "sd", "!0r,!1d(!2r)", 4), 531 532 // The following are pseudoinstructions. 533 ENCODING_MAP(kMipsDelta, 0x27e00000, // It is implemented as daddiu for mips64. 534 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, 15, 0, 535 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | REG_USE_LR | 536 NEEDS_FIXUP, "addiu", "!0r,ra,0x!1h(!1d)", 4), 537 ENCODING_MAP(kMipsDeltaHi, 0x3C000000, 538 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 539 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | NEEDS_FIXUP, 540 "lui", "!0r,0x!1h(!1d)", 4), 541 ENCODING_MAP(kMipsDeltaLo, 0x34000000, 542 kFmtBlt5_2, 16, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 543 kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0_USE0 | NEEDS_FIXUP, 544 "ori", "!0r,!0r,0x!1h(!1d)", 4), 545 ENCODING_MAP(kMipsCurrPC, 0x04110001, 546 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 547 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR, 548 "addiu", "ra,pc,8", 4), 549 ENCODING_MAP(kMipsUndefined, 0x64000000, 550 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 551 kFmtUnused, -1, -1, NO_OPERAND, 552 "undefined", "", 4), 553 }; 554 555 556 /* 557 * Convert a short-form branch to long form. Hopefully, this won't happen 558 * very often because the PIC sequence is especially unfortunate. 559 * 560 * Orig conditional branch 561 * ----------------------- 562 * beq rs,rt,target 563 * 564 * Long conditional branch 565 * ----------------------- 566 * bne rs,rt,hop 567 * bal .+8 ; rRA <- anchor 568 * lui rAT, ((target-anchor) >> 16) 569 * anchor: 570 * ori rAT, rAT, ((target-anchor) & 0xffff) 571 * addu rAT, rAT, rRA 572 * jalr rZERO, rAT 573 * hop: 574 * 575 * Orig unconditional branch 576 * ------------------------- 577 * b target 578 * 579 * Long unconditional branch 580 * ----------------------- 581 * bal .+8 ; rRA <- anchor 582 * lui rAT, ((target-anchor) >> 16) 583 * anchor: 584 * ori rAT, rAT, ((target-anchor) & 0xffff) 585 * addu rAT, rAT, rRA 586 * jalr rZERO, rAT 587 * 588 * 589 * NOTE: An out-of-range bal isn't supported because it should 590 * never happen with the current PIC model. 591 */ 592 void MipsMir2Lir::ConvertShortToLongBranch(LIR* lir) { 593 // For conditional branches we'll need to reverse the sense 594 bool unconditional = false; 595 int opcode = lir->opcode; 596 int dalvik_offset = lir->dalvik_offset; 597 switch (opcode) { 598 case kMipsBal: 599 LOG(FATAL) << "long branch and link unsupported"; 600 UNREACHABLE(); 601 case kMipsB: 602 unconditional = true; 603 break; 604 case kMipsBeq: opcode = kMipsBne; break; 605 case kMipsBne: opcode = kMipsBeq; break; 606 case kMipsBeqz: opcode = kMipsBnez; break; 607 case kMipsBgez: opcode = kMipsBltz; break; 608 case kMipsBgtz: opcode = kMipsBlez; break; 609 case kMipsBlez: opcode = kMipsBgtz; break; 610 case kMipsBltz: opcode = kMipsBgez; break; 611 case kMipsBnez: opcode = kMipsBeqz; break; 612 default: 613 LOG(FATAL) << "Unexpected branch kind " << opcode; 614 UNREACHABLE(); 615 } 616 LIR* hop_target = nullptr; 617 if (!unconditional) { 618 hop_target = RawLIR(dalvik_offset, kPseudoTargetLabel); 619 LIR* hop_branch = RawLIR(dalvik_offset, opcode, lir->operands[0], 620 lir->operands[1], 0, 0, 0, hop_target); 621 InsertLIRBefore(lir, hop_branch); 622 } 623 LIR* curr_pc = RawLIR(dalvik_offset, kMipsCurrPC); 624 InsertLIRBefore(lir, curr_pc); 625 LIR* anchor = RawLIR(dalvik_offset, kPseudoTargetLabel); 626 LIR* delta_hi = RawLIR(dalvik_offset, kMipsDeltaHi, rAT, 0, WrapPointer(anchor), 0, 0, 627 lir->target); 628 InsertLIRBefore(lir, delta_hi); 629 InsertLIRBefore(lir, anchor); 630 LIR* delta_lo = RawLIR(dalvik_offset, kMipsDeltaLo, rAT, 0, WrapPointer(anchor), 0, 0, 631 lir->target); 632 InsertLIRBefore(lir, delta_lo); 633 LIR* addu = RawLIR(dalvik_offset, kMipsAddu, rAT, rAT, rRA); 634 InsertLIRBefore(lir, addu); 635 LIR* jalr = RawLIR(dalvik_offset, kMipsJalr, rZERO, rAT); 636 InsertLIRBefore(lir, jalr); 637 if (!unconditional) { 638 InsertLIRBefore(lir, hop_target); 639 } 640 NopLIR(lir); 641 } 642 643 /* 644 * Assemble the LIR into binary instruction format. Note that we may 645 * discover that pc-relative displacements may not fit the selected 646 * instruction. In those cases we will try to substitute a new code 647 * sequence or request that the trace be shortened and retried. 648 */ 649 AssemblerStatus MipsMir2Lir::AssembleInstructions(CodeOffset start_addr) { 650 LIR *lir; 651 AssemblerStatus res = kSuccess; // Assume success. 652 653 for (lir = first_lir_insn_; lir != nullptr; lir = NEXT_LIR(lir)) { 654 if (lir->opcode < 0) { 655 continue; 656 } 657 658 if (lir->flags.is_nop) { 659 continue; 660 } 661 662 if (lir->flags.fixup != kFixupNone) { 663 if (lir->opcode == kMipsDelta) { 664 /* 665 * The "Delta" pseudo-ops load the difference between 666 * two pc-relative locations into a the target register 667 * found in operands[0]. The delta is determined by 668 * (label2 - label1), where label1 is a standard 669 * kPseudoTargetLabel and is stored in operands[2]. 670 * If operands[3] is null, then label2 is a kPseudoTargetLabel 671 * and is found in lir->target. If operands[3] is non-nullptr, 672 * then it is a Switch/Data table. 673 */ 674 int offset1 = UnwrapPointer<LIR>(lir->operands[2])->offset; 675 const EmbeddedData* tab_rec = UnwrapPointer<EmbeddedData>(lir->operands[3]); 676 int offset2 = tab_rec ? tab_rec->offset : lir->target->offset; 677 int delta = offset2 - offset1; 678 if ((delta & 0xffff) == delta && ((delta & 0x8000) == 0)) { 679 // Fits. 680 lir->operands[1] = delta; 681 if (cu_->target64) { 682 LIR *new_addiu = RawLIR(lir->dalvik_offset, kMips64Daddiu, lir->operands[0], rRAd, 683 delta); 684 InsertLIRBefore(lir, new_addiu); 685 NopLIR(lir); 686 res = kRetryAll; 687 } 688 } else { 689 // Doesn't fit - must expand to kMipsDelta[Hi|Lo] pair. 690 LIR *new_delta_hi = RawLIR(lir->dalvik_offset, kMipsDeltaHi, lir->operands[0], 0, 691 lir->operands[2], lir->operands[3], 0, lir->target); 692 InsertLIRBefore(lir, new_delta_hi); 693 LIR *new_delta_lo = RawLIR(lir->dalvik_offset, kMipsDeltaLo, lir->operands[0], 0, 694 lir->operands[2], lir->operands[3], 0, lir->target); 695 InsertLIRBefore(lir, new_delta_lo); 696 LIR *new_addu; 697 if (cu_->target64) { 698 new_addu = RawLIR(lir->dalvik_offset, kMips64Daddu, lir->operands[0], lir->operands[0], 699 rRAd); 700 } else { 701 new_addu = RawLIR(lir->dalvik_offset, kMipsAddu, lir->operands[0], lir->operands[0], 702 rRA); 703 } 704 InsertLIRBefore(lir, new_addu); 705 NopLIR(lir); 706 res = kRetryAll; 707 } 708 } else if (lir->opcode == kMipsDeltaLo) { 709 int offset1 = UnwrapPointer<LIR>(lir->operands[2])->offset; 710 const EmbeddedData* tab_rec = UnwrapPointer<EmbeddedData>(lir->operands[3]); 711 int offset2 = tab_rec ? tab_rec->offset : lir->target->offset; 712 int delta = offset2 - offset1; 713 lir->operands[1] = delta & 0xffff; 714 } else if (lir->opcode == kMipsDeltaHi) { 715 int offset1 = UnwrapPointer<LIR>(lir->operands[2])->offset; 716 const EmbeddedData* tab_rec = UnwrapPointer<EmbeddedData>(lir->operands[3]); 717 int offset2 = tab_rec ? tab_rec->offset : lir->target->offset; 718 int delta = offset2 - offset1; 719 lir->operands[1] = (delta >> 16) & 0xffff; 720 } else if (lir->opcode == kMipsB || lir->opcode == kMipsBal) { 721 LIR *target_lir = lir->target; 722 CodeOffset pc = lir->offset + 4; 723 CodeOffset target = target_lir->offset; 724 int delta = target - pc; 725 if (delta & 0x3) { 726 LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta; 727 } 728 if (delta > 131068 || delta < -131069) { 729 res = kRetryAll; 730 ConvertShortToLongBranch(lir); 731 } else { 732 lir->operands[0] = delta >> 2; 733 } 734 } else if (lir->opcode >= kMipsBeqz && lir->opcode <= kMipsBnez) { 735 LIR *target_lir = lir->target; 736 CodeOffset pc = lir->offset + 4; 737 CodeOffset target = target_lir->offset; 738 int delta = target - pc; 739 if (delta & 0x3) { 740 LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta; 741 } 742 if (delta > 131068 || delta < -131069) { 743 res = kRetryAll; 744 ConvertShortToLongBranch(lir); 745 } else { 746 lir->operands[1] = delta >> 2; 747 } 748 } else if (lir->opcode == kMipsBeq || lir->opcode == kMipsBne) { 749 LIR *target_lir = lir->target; 750 CodeOffset pc = lir->offset + 4; 751 CodeOffset target = target_lir->offset; 752 int delta = target - pc; 753 if (delta & 0x3) { 754 LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta; 755 } 756 if (delta > 131068 || delta < -131069) { 757 res = kRetryAll; 758 ConvertShortToLongBranch(lir); 759 } else { 760 lir->operands[2] = delta >> 2; 761 } 762 } else if (lir->opcode == kMipsJal) { 763 CodeOffset cur_pc = (start_addr + lir->offset + 4) & ~3; 764 CodeOffset target = lir->operands[0]; 765 /* ensure PC-region branch can be used */ 766 DCHECK_EQ((cur_pc & 0xF0000000), (target & 0xF0000000)); 767 if (target & 0x3) { 768 LOG(FATAL) << "Jump target not multiple of 4: " << target; 769 } 770 lir->operands[0] = target >> 2; 771 } else if (lir->opcode == kMipsLahi) { /* ld address hi (via lui) */ 772 LIR *target_lir = lir->target; 773 CodeOffset target = start_addr + target_lir->offset; 774 lir->operands[1] = target >> 16; 775 } else if (lir->opcode == kMipsLalo) { /* ld address lo (via ori) */ 776 LIR *target_lir = lir->target; 777 CodeOffset target = start_addr + target_lir->offset; 778 lir->operands[2] = lir->operands[2] + target; 779 } 780 } 781 782 /* 783 * If one of the pc-relative instructions expanded we'll have 784 * to make another pass. Don't bother to fully assemble the 785 * instruction. 786 */ 787 if (res != kSuccess) { 788 continue; 789 } 790 DCHECK(!IsPseudoLirOp(lir->opcode)); 791 const MipsEncodingMap *encoder = &EncodingMap[lir->opcode]; 792 uint32_t bits = encoder->skeleton; 793 int i; 794 for (i = 0; i < 4; i++) { 795 uint32_t operand; 796 uint32_t value; 797 operand = lir->operands[i]; 798 switch (encoder->field_loc[i].kind) { 799 case kFmtUnused: 800 break; 801 case kFmtBitBlt: 802 if (encoder->field_loc[i].start == 0 && encoder->field_loc[i].end == 31) { 803 value = operand; 804 } else { 805 value = (operand << encoder->field_loc[i].start) & 806 ((1 << (encoder->field_loc[i].end + 1)) - 1); 807 } 808 bits |= value; 809 break; 810 case kFmtBlt5_2: 811 value = (operand & 0x1f); 812 bits |= (value << encoder->field_loc[i].start); 813 bits |= (value << encoder->field_loc[i].end); 814 break; 815 case kFmtDfp: { 816 // TODO: do we need to adjust now that we're using 64BitSolo? 817 DCHECK(RegStorage::IsDouble(operand)) << ", Operand = 0x" << std::hex << operand; 818 if (!cu_->target64) { 819 DCHECK_EQ((operand & 0x1), 0U); // May only use even numbered registers for mips32. 820 } 821 value = (RegStorage::RegNum(operand) << encoder->field_loc[i].start) & 822 ((1 << (encoder->field_loc[i].end + 1)) - 1); 823 bits |= value; 824 break; 825 } 826 case kFmtSfp: 827 DCHECK(RegStorage::IsSingle(operand)) << ", Operand = 0x" << std::hex << operand; 828 value = (RegStorage::RegNum(operand) << encoder->field_loc[i].start) & 829 ((1 << (encoder->field_loc[i].end + 1)) - 1); 830 bits |= value; 831 break; 832 default: 833 LOG(FATAL) << "Bad encoder format: " << encoder->field_loc[i].kind; 834 } 835 } 836 // We only support little-endian MIPS. 837 code_buffer_.push_back(bits & 0xff); 838 code_buffer_.push_back((bits >> 8) & 0xff); 839 code_buffer_.push_back((bits >> 16) & 0xff); 840 code_buffer_.push_back((bits >> 24) & 0xff); 841 // TUNING: replace with proper delay slot handling. 842 if (encoder->size == 8) { 843 DCHECK(!IsPseudoLirOp(lir->opcode)); 844 const MipsEncodingMap *encoder2 = &EncodingMap[kMipsNop]; 845 uint32_t bits2 = encoder2->skeleton; 846 code_buffer_.push_back(bits2 & 0xff); 847 code_buffer_.push_back((bits2 >> 8) & 0xff); 848 code_buffer_.push_back((bits2 >> 16) & 0xff); 849 code_buffer_.push_back((bits2 >> 24) & 0xff); 850 } 851 } 852 return res; 853 } 854 855 size_t MipsMir2Lir::GetInsnSize(LIR* lir) { 856 DCHECK(!IsPseudoLirOp(lir->opcode)); 857 return EncodingMap[lir->opcode].size; 858 } 859 860 // LIR offset assignment. 861 // TODO: consolidate w/ Arm assembly mechanism. 862 int MipsMir2Lir::AssignInsnOffsets() { 863 LIR* lir; 864 int offset = 0; 865 866 for (lir = first_lir_insn_; lir != nullptr; lir = NEXT_LIR(lir)) { 867 lir->offset = offset; 868 if (LIKELY(lir->opcode >= 0)) { 869 if (!lir->flags.is_nop) { 870 offset += lir->flags.size; 871 } 872 } else if (UNLIKELY(lir->opcode == kPseudoPseudoAlign4)) { 873 if (offset & 0x2) { 874 offset += 2; 875 lir->operands[0] = 1; 876 } else { 877 lir->operands[0] = 0; 878 } 879 } 880 // Pseudo opcodes don't consume space. 881 } 882 return offset; 883 } 884 885 /* 886 * Walk the compilation unit and assign offsets to instructions 887 * and literals and compute the total size of the compiled unit. 888 * TODO: consolidate w/ Arm assembly mechanism. 889 */ 890 void MipsMir2Lir::AssignOffsets() { 891 int offset = AssignInsnOffsets(); 892 893 // Const values have to be word aligned. 894 offset = RoundUp(offset, 4); 895 896 // Set up offsets for literals. 897 data_offset_ = offset; 898 899 offset = AssignLiteralOffset(offset); 900 901 offset = AssignSwitchTablesOffset(offset); 902 903 offset = AssignFillArrayDataOffset(offset); 904 905 total_size_ = offset; 906 } 907 908 /* 909 * Go over each instruction in the list and calculate the offset from the top 910 * before sending them off to the assembler. If out-of-range branch distance is 911 * seen rearrange the instructions a bit to correct it. 912 * TODO: consolidate w/ Arm assembly mechanism. 913 */ 914 void MipsMir2Lir::AssembleLIR() { 915 cu_->NewTimingSplit("Assemble"); 916 AssignOffsets(); 917 int assembler_retries = 0; 918 /* 919 * Assemble here. Note that we generate code with optimistic assumptions 920 * and if found now to work, we'll have to redo the sequence and retry. 921 */ 922 923 while (true) { 924 AssemblerStatus res = AssembleInstructions(0); 925 if (res == kSuccess) { 926 break; 927 } else { 928 assembler_retries++; 929 if (assembler_retries > MAX_ASSEMBLER_RETRIES) { 930 CodegenDump(); 931 LOG(FATAL) << "Assembler error - too many retries"; 932 } 933 // Redo offsets and try again. 934 AssignOffsets(); 935 code_buffer_.clear(); 936 } 937 } 938 939 // Install literals. 940 InstallLiteralPools(); 941 942 // Install switch tables. 943 InstallSwitchTables(); 944 945 // Install fill array data. 946 InstallFillArrayData(); 947 948 // Create the mapping table and native offset to reference map. 949 cu_->NewTimingSplit("PcMappingTable"); 950 CreateMappingTables(); 951 952 cu_->NewTimingSplit("GcMap"); 953 CreateNativeGcMap(); 954 } 955 956 } // namespace art 957