Assemble.cpp revision 0c2dc522d0e120f346cf0a40c8cf0c93346131c2
1/* 2 * Copyright (C) 2009 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 "libdex/DexOpcodes.h" 19 20#include "../../CompilerInternals.h" 21#include "MipsLIR.h" 22#include "Codegen.h" 23#include <unistd.h> /* for cacheflush */ 24#include <sys/mman.h> /* for protection change */ 25 26#define MAX_ASSEMBLER_RETRIES 10 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 * 77 * [!] escape. To insert "!", use "!!" 78 */ 79/* NOTE: must be kept in sync with enum MipsOpcode from MipsLIR.h */ 80MipsEncodingMap EncodingMap[kMipsLast] = { 81 ENCODING_MAP(kMips32BitData, 0x00000000, 82 kFmtBitBlt, 31, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 83 kFmtUnused, -1, -1, IS_UNARY_OP, 84 "data", "0x!0h(!0d)", 2), 85 ENCODING_MAP(kMipsAddiu, 0x24000000, 86 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 87 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 88 "addiu", "!0r,!1r,0x!2h(!2d)", 2), 89 ENCODING_MAP(kMipsAddu, 0x00000021, 90 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 91 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 92 "addu", "!0r,!1r,!2r", 2), 93 ENCODING_MAP(kMipsAnd, 0x00000024, 94 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 95 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 96 "and", "!0r,!1r,!2r", 2), 97 ENCODING_MAP(kMipsAndi, 0x30000000, 98 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 99 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 100 "andi", "!0r,!1r,0x!2h(!2d)", 2), 101 ENCODING_MAP(kMipsB, 0x10000000, 102 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 103 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH, 104 "b", "!0t", 2), 105 ENCODING_MAP(kMipsBal, 0x04110000, 106 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 107 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR, 108 "bal", "!0t", 2), 109 ENCODING_MAP(kMipsBeq, 0x10000000, 110 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, 111 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01, 112 "beq", "!0r,!1r,!2t", 2), 113 ENCODING_MAP(kMipsBeqz, 0x10000000, /* same as beq above with t = $zero */ 114 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 115 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0, 116 "beqz", "!0r,!1t", 2), 117 ENCODING_MAP(kMipsBgez, 0x04010000, 118 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 119 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0, 120 "bgez", "!0r,!1t", 2), 121 ENCODING_MAP(kMipsBgtz, 0x1C000000, 122 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 123 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0, 124 "bgtz", "!0r,!1t", 2), 125 ENCODING_MAP(kMipsBlez, 0x18000000, 126 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 127 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0, 128 "blez", "!0r,!1t", 2), 129 ENCODING_MAP(kMipsBltz, 0x04000000, 130 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 131 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0, 132 "bltz", "!0r,!1t", 2), 133 ENCODING_MAP(kMipsBnez, 0x14000000, /* same as bne below with t = $zero */ 134 kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 135 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0, 136 "bnez", "!0r,!1t", 2), 137 ENCODING_MAP(kMipsBne, 0x14000000, 138 kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, 139 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01, 140 "bne", "!0r,!1r,!2t", 2), 141 ENCODING_MAP(kMipsDiv, 0x0000001a, 142 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtBitBlt, 25, 21, 143 kFmtBitBlt, 20, 16, IS_QUAD_OP | REG_DEF01 | REG_USE23, 144 "div", "!2r,!3r", 2), 145#if __mips_isa_rev>=2 146 ENCODING_MAP(kMipsExt, 0x7c000000, 147 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 10, 6, 148 kFmtBitBlt, 15, 11, IS_QUAD_OP | REG_DEF0 | REG_USE1, 149 "ext", "!0r,!1r,!2d,!3D", 2), 150#endif 151 ENCODING_MAP(kMipsJal, 0x0c000000, 152 kFmtBitBlt, 25, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 153 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR, 154 "jal", "!0T(!0E)", 2), 155 ENCODING_MAP(kMipsJalr, 0x00000009, 156 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1, 157 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_DEF0_USE1, 158 "jalr", "!0r,!1r", 2), 159 ENCODING_MAP(kMipsJr, 0x00000008, 160 kFmtBitBlt, 25, 21, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 161 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0, 162 "jr", "!0r", 2), 163 ENCODING_MAP(kMipsLahi, 0x3C000000, 164 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 165 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0, 166 "lahi/lui", "!0r,0x!1h(!1d)", 2), 167 ENCODING_MAP(kMipsLalo, 0x34000000, 168 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 169 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 170 "lalo/ori", "!0r,!1r,0x!2h(!2d)", 2), 171 ENCODING_MAP(kMipsLui, 0x3C000000, 172 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 173 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0, 174 "lui", "!0r,0x!1h(!1d)", 2), 175 ENCODING_MAP(kMipsLb, 0x80000000, 176 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 177 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 178 "lb", "!0r,!1d(!2r)", 2), 179 ENCODING_MAP(kMipsLbu, 0x90000000, 180 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 181 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 182 "lbu", "!0r,!1d(!2r)", 2), 183 ENCODING_MAP(kMipsLh, 0x84000000, 184 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 185 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 186 "lh", "!0r,!1d(!2r)", 2), 187 ENCODING_MAP(kMipsLhu, 0x94000000, 188 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 189 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 190 "lhu", "!0r,!1d(!2r)", 2), 191 ENCODING_MAP(kMipsLw, 0x8C000000, 192 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 193 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 194 "lw", "!0r,!1d(!2r)", 2), 195 ENCODING_MAP(kMipsMfhi, 0x00000010, 196 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 197 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 198 "mfhi", "!0r", 2), 199 ENCODING_MAP(kMipsMflo, 0x00000012, 200 kFmtBitBlt, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 201 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 202 "mflo", "!0r", 2), 203 ENCODING_MAP(kMipsMove, 0x00000025, /* or using zero reg */ 204 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtUnused, -1, -1, 205 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 206 "move", "!0r,!1r", 2), 207 ENCODING_MAP(kMipsMovz, 0x0000000a, 208 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 209 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 210 "movz", "!0r,!1r,!2r", 2), 211 ENCODING_MAP(kMipsMul, 0x70000002, 212 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 213 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 214 "mul", "!0r,!1r,!2r", 2), 215 ENCODING_MAP(kMipsNop, 0x00000000, 216 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 217 kFmtUnused, -1, -1, NO_OPERAND, 218 "nop", "", 2), 219 ENCODING_MAP(kMipsNor, 0x00000027, /* used for "not" too */ 220 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 221 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 222 "nor", "!0r,!1r,!2r", 2), 223 ENCODING_MAP(kMipsOr, 0x00000025, 224 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 225 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 226 "or", "!0r,!1r,!2r", 2), 227 ENCODING_MAP(kMipsOri, 0x34000000, 228 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 229 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 230 "ori", "!0r,!1r,0x!2h(!2d)", 2), 231 ENCODING_MAP(kMipsPref, 0xCC000000, 232 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 233 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE2, 234 "pref", "!0d,!1d(!2r)", 2), 235 ENCODING_MAP(kMipsSb, 0xA0000000, 236 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 237 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE, 238 "sb", "!0r,!1d(!2r)", 2), 239#if __mips_isa_rev>=2 240 ENCODING_MAP(kMipsSeb, 0x7c000420, 241 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1, 242 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 243 "seb", "!0r,!1r", 2), 244 ENCODING_MAP(kMipsSeh, 0x7c000620, 245 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1, 246 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 247 "seh", "!0r,!1r", 2), 248#endif 249 ENCODING_MAP(kMipsSh, 0xA4000000, 250 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 251 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE, 252 "sh", "!0r,!1d(!2r)", 2), 253 ENCODING_MAP(kMipsSll, 0x00000000, 254 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 255 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 256 "sll", "!0r,!1r,0x!2h(!2d)", 2), 257 ENCODING_MAP(kMipsSllv, 0x00000004, 258 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, 259 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 260 "sllv", "!0r,!1r,!2r", 2), 261 ENCODING_MAP(kMipsSlt, 0x0000002a, 262 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 263 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 264 "slt", "!0r,!1r,!2r", 2), 265 ENCODING_MAP(kMipsSlti, 0x28000000, 266 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 267 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 268 "slti", "!0r,!1r,0x!2h(!2d)", 2), 269 ENCODING_MAP(kMipsSltu, 0x0000002b, 270 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 271 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 272 "sltu", "!0r,!1r,!2r", 2), 273 ENCODING_MAP(kMipsSra, 0x00000003, 274 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 275 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 276 "sra", "!0r,!1r,0x!2h(!2d)", 2), 277 ENCODING_MAP(kMipsSrav, 0x00000007, 278 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, 279 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 280 "srav", "!0r,!1r,!2r", 2), 281 ENCODING_MAP(kMipsSrl, 0x00000002, 282 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 10, 6, 283 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 284 "srl", "!0r,!1r,0x!2h(!2d)", 2), 285 ENCODING_MAP(kMipsSrlv, 0x00000006, 286 kFmtBitBlt, 15, 11, kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, 287 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 288 "srlv", "!0r,!1r,!2r", 2), 289 ENCODING_MAP(kMipsSubu, 0x00000023, /* used for "neg" too */ 290 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 291 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 292 "subu", "!0r,!1r,!2r", 2), 293 ENCODING_MAP(kMipsSw, 0xAC000000, 294 kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 295 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE, 296 "sw", "!0r,!1d(!2r)", 2), 297 ENCODING_MAP(kMipsXor, 0x00000026, 298 kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, 299 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 300 "xor", "!0r,!1r,!2r", 2), 301 ENCODING_MAP(kMipsXori, 0x38000000, 302 kFmtBitBlt, 20, 16, kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, 303 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 304 "xori", "!0r,!1r,0x!2h(!2d)", 2), 305#ifdef __mips_hard_float 306 ENCODING_MAP(kMipsFadds, 0x46000000, 307 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16, 308 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 309 "add.s", "!0s,!1s,!2s", 2), 310 ENCODING_MAP(kMipsFsubs, 0x46000001, 311 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16, 312 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 313 "sub.s", "!0s,!1s,!2s", 2), 314 ENCODING_MAP(kMipsFmuls, 0x46000002, 315 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16, 316 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 317 "mul.s", "!0s,!1s,!2s", 2), 318 ENCODING_MAP(kMipsFdivs, 0x46000003, 319 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtSfp, 20, 16, 320 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 321 "div.s", "!0s,!1s,!2s", 2), 322 ENCODING_MAP(kMipsFaddd, 0x46200000, 323 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16, 324 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 325 "add.d", "!0S,!1S,!2S", 2), 326 ENCODING_MAP(kMipsFsubd, 0x46200001, 327 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16, 328 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 329 "sub.d", "!0S,!1S,!2S", 2), 330 ENCODING_MAP(kMipsFmuld, 0x46200002, 331 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16, 332 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 333 "mul.d", "!0S,!1S,!2S", 2), 334 ENCODING_MAP(kMipsFdivd, 0x46200003, 335 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtDfp, 20, 16, 336 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 337 "div.d", "!0S,!1S,!2S", 2), 338 ENCODING_MAP(kMipsFcvtsd, 0x46200020, 339 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1, 340 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 341 "cvt.s.d", "!0s,!1S", 2), 342 ENCODING_MAP(kMipsFcvtsw, 0x46800020, 343 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 344 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 345 "cvt.s.w", "!0s,!1s", 2), 346 ENCODING_MAP(kMipsFcvtds, 0x46000021, 347 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 348 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 349 "cvt.d.s", "!0S,!1s", 2), 350 ENCODING_MAP(kMipsFcvtdw, 0x46800021, 351 kFmtDfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 352 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 353 "cvt.d.w", "!0S,!1s", 2), 354 ENCODING_MAP(kMipsFcvtws, 0x46000024, 355 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 356 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 357 "cvt.w.s", "!0s,!1s", 2), 358 ENCODING_MAP(kMipsFcvtwd, 0x46200024, 359 kFmtSfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1, 360 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 361 "cvt.w.d", "!0s,!1S", 2), 362 ENCODING_MAP(kMipsFmovs, 0x46000006, 363 kFmtSfp, 10, 6, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 364 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 365 "mov.s", "!0s,!1s", 2), 366 ENCODING_MAP(kMipsFmovd, 0x46200006, 367 kFmtDfp, 10, 6, kFmtDfp, 15, 11, kFmtUnused, -1, -1, 368 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 369 "mov.d", "!0S,!1S", 2), 370 ENCODING_MAP(kMipsFlwc1, 0xC4000000, 371 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 372 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 373 "lwc1", "!0s,!1d(!2r)", 2), 374 ENCODING_MAP(kMipsFldc1, 0xD4000000, 375 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 376 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE2 | IS_LOAD, 377 "ldc1", "!0S,!1d(!2r)", 2), 378 ENCODING_MAP(kMipsFswc1, 0xE4000000, 379 kFmtSfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 380 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE, 381 "swc1", "!0s,!1d(!2r)", 2), 382 ENCODING_MAP(kMipsFsdc1, 0xF4000000, 383 kFmtDfp, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21, 384 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE, 385 "sdc1", "!0S,!1d(!2r)", 2), 386 ENCODING_MAP(kMipsMfc1, 0x44000000, 387 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 388 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 389 "mfc1", "!0r,!1s", 2), 390 ENCODING_MAP(kMipsMtc1, 0x44800000, 391 kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1, 392 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1, 393 "mtc1", "!0r,!1s", 2), 394#endif 395 ENCODING_MAP(kMipsUndefined, 0x64000000, 396 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 397 kFmtUnused, -1, -1, NO_OPERAND, 398 "undefined", "", 2), 399}; 400 401/* Track the number of times that the code cache is patched */ 402#if defined(WITH_JIT_TUNING) 403#define UPDATE_CODE_CACHE_PATCHES() (gDvmJit.codeCachePatches++) 404#else 405#define UPDATE_CODE_CACHE_PATCHES() 406#endif 407 408/* Write the numbers in the constant and class pool to the output stream */ 409static void installLiteralPools(CompilationUnit *cUnit) 410{ 411 int *dataPtr = (int *) ((char *) cUnit->baseAddr + cUnit->dataOffset); 412 /* Install number of class pointer literals */ 413 *dataPtr++ = cUnit->numClassPointers; 414 MipsLIR *dataLIR = (MipsLIR *) cUnit->classPointerList; 415 while (dataLIR) { 416 /* 417 * Install the callsiteinfo pointers into the cells for now. They will 418 * be converted into real pointers in dvmJitInstallClassObjectPointers. 419 */ 420 *dataPtr++ = dataLIR->operands[0]; 421 dataLIR = NEXT_LIR(dataLIR); 422 } 423 dataLIR = (MipsLIR *) cUnit->literalList; 424 while (dataLIR) { 425 *dataPtr++ = dataLIR->operands[0]; 426 dataLIR = NEXT_LIR(dataLIR); 427 } 428} 429 430/* 431 * Assemble the LIR into binary instruction format. Note that we may 432 * discover that pc-relative displacements may not fit the selected 433 * instruction. In those cases we will try to substitute a new code 434 * sequence or request that the trace be shortened and retried. 435 */ 436static AssemblerStatus assembleInstructions(CompilationUnit *cUnit, 437 intptr_t startAddr) 438{ 439 int *bufferAddr = (int *) cUnit->codeBuffer; 440 MipsLIR *lir; 441 442 for (lir = (MipsLIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) { 443 if (lir->opcode < 0) { 444 continue; 445 } 446 447 448 if (lir->flags.isNop) { 449 continue; 450 } 451 452 if (lir->opcode == kMipsB || lir->opcode == kMipsBal) { 453 MipsLIR *targetLIR = (MipsLIR *) lir->generic.target; 454 intptr_t pc = lir->generic.offset + 4; 455 intptr_t target = targetLIR->generic.offset; 456 int delta = target - pc; 457 if (delta & 0x3) { 458 LOGE("PC-rel distance is not multiple of 4: %d", delta); 459 dvmAbort(); 460 } 461 if (delta > 131068 || delta < -131069) { 462 LOGE("Unconditional branch distance out of range: %d", delta); 463 dvmAbort(); 464 } 465 lir->operands[0] = delta >> 2; 466 } else if (lir->opcode >= kMipsBeqz && lir->opcode <= kMipsBnez) { 467 MipsLIR *targetLIR = (MipsLIR *) lir->generic.target; 468 intptr_t pc = lir->generic.offset + 4; 469 intptr_t target = targetLIR->generic.offset; 470 int delta = target - pc; 471 if (delta & 0x3) { 472 LOGE("PC-rel distance is not multiple of 4: %d", delta); 473 dvmAbort(); 474 } 475 if (delta > 131068 || delta < -131069) { 476 LOGE("Conditional branch distance out of range: %d", delta); 477 dvmAbort(); 478 } 479 lir->operands[1] = delta >> 2; 480 } else if (lir->opcode == kMipsBeq || lir->opcode == kMipsBne) { 481 MipsLIR *targetLIR = (MipsLIR *) lir->generic.target; 482 intptr_t pc = lir->generic.offset + 4; 483 intptr_t target = targetLIR->generic.offset; 484 int delta = target - pc; 485 if (delta & 0x3) { 486 LOGE("PC-rel distance is not multiple of 4: %d", delta); 487 dvmAbort(); 488 } 489 if (delta > 131068 || delta < -131069) { 490 LOGE("Conditional branch distance out of range: %d", delta); 491 dvmAbort(); 492 } 493 lir->operands[2] = delta >> 2; 494 } else if (lir->opcode == kMipsJal) { 495 intptr_t curPC = (startAddr + lir->generic.offset + 4) & ~3; 496 intptr_t target = lir->operands[0]; 497 /* ensure PC-region branch can be used */ 498 assert((curPC & 0xF0000000) == (target & 0xF0000000)); 499 if (target & 0x3) { 500 LOGE("Jump target is not multiple of 4: %d", target); 501 dvmAbort(); 502 } 503 lir->operands[0] = target >> 2; 504 } else if (lir->opcode == kMipsLahi) { /* load address hi (via lui) */ 505 MipsLIR *targetLIR = (MipsLIR *) lir->generic.target; 506 intptr_t target = startAddr + targetLIR->generic.offset; 507 lir->operands[1] = target >> 16; 508 } else if (lir->opcode == kMipsLalo) { /* load address lo (via ori) */ 509 MipsLIR *targetLIR = (MipsLIR *) lir->generic.target; 510 intptr_t target = startAddr + targetLIR->generic.offset; 511 lir->operands[2] = lir->operands[2] + target; 512 } 513 514 515 MipsEncodingMap *encoder = &EncodingMap[lir->opcode]; 516 u4 bits = encoder->skeleton; 517 int i; 518 for (i = 0; i < 4; i++) { 519 u4 operand; 520 u4 value; 521 operand = lir->operands[i]; 522 switch(encoder->fieldLoc[i].kind) { 523 case kFmtUnused: 524 break; 525 case kFmtBitBlt: 526 if (encoder->fieldLoc[i].start == 0 && encoder->fieldLoc[i].end == 31) { 527 value = operand; 528 } else { 529 value = (operand << encoder->fieldLoc[i].start) & 530 ((1 << (encoder->fieldLoc[i].end + 1)) - 1); 531 } 532 bits |= value; 533 break; 534 case kFmtDfp: { 535 assert(DOUBLEREG(operand)); 536 assert((operand & 0x1) == 0); 537 value = ((operand & FP_REG_MASK) << encoder->fieldLoc[i].start) & 538 ((1 << (encoder->fieldLoc[i].end + 1)) - 1); 539 bits |= value; 540 break; 541 } 542 case kFmtSfp: 543 assert(SINGLEREG(operand)); 544 value = ((operand & FP_REG_MASK) << encoder->fieldLoc[i].start) & 545 ((1 << (encoder->fieldLoc[i].end + 1)) - 1); 546 bits |= value; 547 break; 548 default: 549 assert(0); 550 } 551 } 552 assert(encoder->size == 2); 553 *bufferAddr++ = bits; 554 } 555 return kSuccess; 556} 557 558static int assignLiteralOffsetCommon(LIR *lir, int offset) 559{ 560 for (;lir != NULL; lir = lir->next) { 561 lir->offset = offset; 562 offset += 4; 563 } 564 return offset; 565} 566 567/* Determine the offset of each literal field */ 568static int assignLiteralOffset(CompilationUnit *cUnit, int offset) 569{ 570 /* Reserved for the size field of class pointer pool */ 571 offset += 4; 572 offset = assignLiteralOffsetCommon(cUnit->classPointerList, offset); 573 offset = assignLiteralOffsetCommon(cUnit->literalList, offset); 574 return offset; 575} 576 577/* 578 * Translation layout in the code cache. Note that the codeAddress pointer 579 * in JitTable will point directly to the code body (field codeAddress). The 580 * chain cell offset codeAddress - 4, and the address of the trace profile 581 * counter is at codeAddress - 8. 582 * 583 * +----------------------------+ 584 * | Trace Profile Counter addr | -> 4 bytes (PROF_COUNTER_ADDR_SIZE) 585 * +----------------------------+ 586 * +--| Offset to chain cell counts| -> 4 bytes (CHAIN_CELL_OFFSET_SIZE) 587 * | +----------------------------+ 588 * | | Trace profile code | <- entry point when profiling 589 * | . - - - - - - - . 590 * | | Code body | <- entry point when not profiling 591 * | . . 592 * | | | 593 * | +----------------------------+ 594 * | | Chaining Cells | -> 16/20 bytes, 4 byte aligned 595 * | . . 596 * | . . 597 * | | | 598 * | +----------------------------+ 599 * | | Gap for large switch stmt | -> # cases >= MAX_CHAINED_SWITCH_CASES 600 * | +----------------------------+ 601 * +->| Chaining cell counts | -> 8 bytes, chain cell counts by type 602 * +----------------------------+ 603 * | Trace description | -> variable sized 604 * . . 605 * | | 606 * +----------------------------+ 607 * | # Class pointer pool size | -> 4 bytes 608 * +----------------------------+ 609 * | Class pointer pool | -> 4-byte aligned, variable size 610 * . . 611 * . . 612 * | | 613 * +----------------------------+ 614 * | Literal pool | -> 4-byte aligned, variable size 615 * . . 616 * . . 617 * | | 618 * +----------------------------+ 619 * 620 */ 621 622#define PROF_COUNTER_ADDR_SIZE 4 623#define CHAIN_CELL_OFFSET_SIZE 4 624 625/* 626 * Utility functions to navigate various parts in a trace. If we change the 627 * layout/offset in the future, we just modify these functions and we don't need 628 * to propagate the changes to all the use cases. 629 */ 630static inline char *getTraceBase(const JitEntry *p) 631{ 632 return (char*)p->codeAddress - 633 (PROF_COUNTER_ADDR_SIZE + CHAIN_CELL_OFFSET_SIZE); 634} 635 636/* Handy function to retrieve the profile count */ 637static inline JitTraceCounter_t getProfileCount(const JitEntry *entry) 638{ 639 if (entry->dPC == 0 || entry->codeAddress == 0 || 640 entry->codeAddress == dvmCompilerGetInterpretTemplate()) 641 return 0; 642 643 JitTraceCounter_t **p = (JitTraceCounter_t **) getTraceBase(entry); 644 645 return **p; 646} 647 648/* Handy function to reset the profile count */ 649static inline void resetProfileCount(const JitEntry *entry) 650{ 651 if (entry->dPC == 0 || entry->codeAddress == 0 || 652 entry->codeAddress == dvmCompilerGetInterpretTemplate()) 653 return; 654 655 JitTraceCounter_t **p = (JitTraceCounter_t **) getTraceBase(entry); 656 657 **p = 0; 658} 659 660/* Get the pointer of the chain cell count */ 661static inline ChainCellCounts* getChainCellCountsPointer(const char *base) 662{ 663 /* 4 is the size of the profile count */ 664 u4 *chainCellOffsetP = (u4 *) (base + PROF_COUNTER_ADDR_SIZE); 665 u4 chainCellOffset = *chainCellOffsetP; 666 return (ChainCellCounts *) ((char *) chainCellOffsetP + chainCellOffset); 667} 668 669/* Get the size of all chaining cells */ 670static inline u4 getChainCellSize(const ChainCellCounts* pChainCellCounts) 671{ 672 int cellSize = 0; 673 int i; 674 675 /* Get total count of chain cells */ 676 for (i = 0; i < kChainingCellGap; i++) { 677 if (i != kChainingCellInvokePredicted) { 678 cellSize += pChainCellCounts->u.count[i] * 679 (CHAIN_CELL_NORMAL_SIZE >> 2); 680 } else { 681 cellSize += pChainCellCounts->u.count[i] * 682 (CHAIN_CELL_PREDICTED_SIZE >> 2); 683 } 684 } 685 return cellSize; 686} 687 688/* Get the starting pointer of the trace description section */ 689static JitTraceDescription* getTraceDescriptionPointer(const char *base) 690{ 691 ChainCellCounts* pCellCounts = getChainCellCountsPointer(base); 692 return (JitTraceDescription*) ((char*)pCellCounts + sizeof(*pCellCounts)); 693} 694 695/* Get the size of a trace description */ 696static int getTraceDescriptionSize(const JitTraceDescription *desc) 697{ 698 int runCount; 699 /* Trace end is always of non-meta type (ie isCode == true) */ 700 for (runCount = 0; ; runCount++) { 701 if (desc->trace[runCount].isCode && 702 desc->trace[runCount].info.frag.runEnd) 703 break; 704 } 705 return sizeof(JitTraceDescription) + ((runCount+1) * sizeof(JitTraceRun)); 706} 707 708#if defined(SIGNATURE_BREAKPOINT) 709/* Inspect the assembled instruction stream to find potential matches */ 710static void matchSignatureBreakpoint(const CompilationUnit *cUnit, 711 unsigned int size) 712{ 713 unsigned int i, j; 714 u4 *ptr = (u4 *) cUnit->codeBuffer; 715 716 for (i = 0; i < size - gDvmJit.signatureBreakpointSize + 1; i++) { 717 if (ptr[i] == gDvmJit.signatureBreakpoint[0]) { 718 for (j = 1; j < gDvmJit.signatureBreakpointSize; j++) { 719 if (ptr[i+j] != gDvmJit.signatureBreakpoint[j]) { 720 break; 721 } 722 } 723 if (j == gDvmJit.signatureBreakpointSize) { 724 LOGD("Signature match starting from offset %#x (%d words)", 725 i*4, gDvmJit.signatureBreakpointSize); 726 int descSize = getTraceDescriptionSize(cUnit->traceDesc); 727 JitTraceDescription *newCopy = 728 (JitTraceDescription *) malloc(descSize); 729 memcpy(newCopy, cUnit->traceDesc, descSize); 730 dvmCompilerWorkEnqueue(NULL, kWorkOrderTraceDebug, newCopy); 731 break; 732 } 733 } 734 } 735} 736#endif 737 738/* 739 * Go over each instruction in the list and calculate the offset from the top 740 * before sending them off to the assembler. If out-of-range branch distance is 741 * seen rearrange the instructions a bit to correct it. 742 */ 743void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info) 744{ 745 MipsLIR *mipsLIR; 746 int offset = 0; 747 int i; 748 ChainCellCounts chainCellCounts; 749 int descSize = (cUnit->jitMode == kJitMethod) ? 750 0 : getTraceDescriptionSize(cUnit->traceDesc); 751 int chainingCellGap = 0; 752 753 info->instructionSet = cUnit->instructionSet; 754 755 /* Beginning offset needs to allow space for chain cell offset */ 756 for (mipsLIR = (MipsLIR *) cUnit->firstLIRInsn; 757 mipsLIR; 758 mipsLIR = NEXT_LIR(mipsLIR)) { 759 mipsLIR->generic.offset = offset; 760 if (mipsLIR->opcode >= 0 && !mipsLIR->flags.isNop) { 761 mipsLIR->flags.size = EncodingMap[mipsLIR->opcode].size * 2; 762 offset += mipsLIR->flags.size; 763 } 764 /* Pseudo opcodes don't consume space */ 765 } 766 767 /* Const values have to be word aligned */ 768 offset = (offset + 3) & ~3; 769 770 u4 chainCellOffset = offset; 771 MipsLIR *chainCellOffsetLIR = NULL; 772 773 if (cUnit->jitMode != kJitMethod) { 774 /* 775 * Get the gap (# of u4) between the offset of chaining cell count and 776 * the bottom of real chaining cells. If the translation has chaining 777 * cells, the gap is guaranteed to be multiples of 4. 778 */ 779 chainingCellGap = (offset - cUnit->chainingCellBottom->offset) >> 2; 780 781 /* Add space for chain cell counts & trace description */ 782 chainCellOffsetLIR = (MipsLIR *) cUnit->chainCellOffsetLIR; 783 assert(chainCellOffsetLIR); 784 assert(chainCellOffset < 0x10000); 785 assert(chainCellOffsetLIR->opcode == kMips32BitData && 786 chainCellOffsetLIR->operands[0] == CHAIN_CELL_OFFSET_TAG); 787 788 /* 789 * Adjust the CHAIN_CELL_OFFSET_TAG LIR's offset to remove the 790 * space occupied by the pointer to the trace profiling counter. 791 */ 792 chainCellOffsetLIR->operands[0] = chainCellOffset - 4; 793 794 offset += sizeof(chainCellCounts) + descSize; 795 796 assert((offset & 0x3) == 0); /* Should still be word aligned */ 797 } 798 799 /* Set up offsets for literals */ 800 cUnit->dataOffset = offset; 801 802 /* 803 * Assign each class pointer/constant an offset from the beginning of the 804 * compilation unit. 805 */ 806 offset = assignLiteralOffset(cUnit, offset); 807 808 cUnit->totalSize = offset; 809 810 if (gDvmJit.codeCacheByteUsed + cUnit->totalSize > gDvmJit.codeCacheSize) { 811 gDvmJit.codeCacheFull = true; 812 info->discardResult = true; 813 return; 814 } 815 816 /* Allocate enough space for the code block */ 817 cUnit->codeBuffer = (unsigned char *)dvmCompilerNew(chainCellOffset, true); 818 if (cUnit->codeBuffer == NULL) { 819 LOGE("Code buffer allocation failure"); 820 info->discardResult = true; 821 return; 822 } 823 824 /* 825 * Attempt to assemble the trace. Note that assembleInstructions 826 * may rewrite the code sequence and request a retry. 827 */ 828 cUnit->assemblerStatus = assembleInstructions(cUnit, 829 (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed); 830 831 switch(cUnit->assemblerStatus) { 832 case kSuccess: 833 break; 834 case kRetryAll: 835 if (cUnit->assemblerRetries < MAX_ASSEMBLER_RETRIES) { 836 if (cUnit->jitMode != kJitMethod) { 837 /* Restore pristine chain cell marker on retry */ 838 chainCellOffsetLIR->operands[0] = CHAIN_CELL_OFFSET_TAG; 839 } 840 return; 841 } 842 /* Too many retries - reset and try cutting the trace in half */ 843 cUnit->assemblerRetries = 0; 844 cUnit->assemblerStatus = kRetryHalve; 845 return; 846 case kRetryHalve: 847 return; 848 default: 849 LOGE("Unexpected assembler status: %d", cUnit->assemblerStatus); 850 dvmAbort(); 851 } 852 853#if defined(SIGNATURE_BREAKPOINT) 854 if (info->discardResult == false && gDvmJit.signatureBreakpoint != NULL && 855 chainCellOffset/4 >= gDvmJit.signatureBreakpointSize) { 856 matchSignatureBreakpoint(cUnit, chainCellOffset/4); 857 } 858#endif 859 860 /* Don't go all the way if the goal is just to get the verbose output */ 861 if (info->discardResult) return; 862 863 /* 864 * The cache might disappear - acquire lock and check version 865 * Continue holding lock until translation cache update is complete. 866 * These actions are required here in the compiler thread because 867 * it is unaffected by suspend requests and doesn't know if a 868 * translation cache flush is in progress. 869 */ 870 dvmLockMutex(&gDvmJit.compilerLock); 871 if (info->cacheVersion != gDvmJit.cacheVersion) { 872 /* Cache changed - discard current translation */ 873 info->discardResult = true; 874 info->codeAddress = NULL; 875 dvmUnlockMutex(&gDvmJit.compilerLock); 876 return; 877 } 878 879 cUnit->baseAddr = (char *) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed; 880 gDvmJit.codeCacheByteUsed += offset; 881 882 UNPROTECT_CODE_CACHE(cUnit->baseAddr, offset); 883 884 /* Install the code block */ 885 memcpy((char*)cUnit->baseAddr, cUnit->codeBuffer, chainCellOffset); 886 gDvmJit.numCompilations++; 887 888 if (cUnit->jitMode != kJitMethod) { 889 /* Install the chaining cell counts */ 890 for (i=0; i< kChainingCellGap; i++) { 891 chainCellCounts.u.count[i] = cUnit->numChainingCells[i]; 892 } 893 894 /* Set the gap number in the chaining cell count structure */ 895 chainCellCounts.u.count[kChainingCellGap] = chainingCellGap; 896 897 memcpy((char*)cUnit->baseAddr + chainCellOffset, &chainCellCounts, 898 sizeof(chainCellCounts)); 899 900 /* Install the trace description */ 901 memcpy((char*) cUnit->baseAddr + chainCellOffset + 902 sizeof(chainCellCounts), 903 cUnit->traceDesc, descSize); 904 } 905 906 /* Write the literals directly into the code cache */ 907 installLiteralPools(cUnit); 908 909 /* Flush dcache and invalidate the icache to maintain coherence */ 910 dvmCompilerCacheFlush((long)cUnit->baseAddr, 911 (long)((char *) cUnit->baseAddr + offset), 0); 912 913 UPDATE_CODE_CACHE_PATCHES(); 914 915 PROTECT_CODE_CACHE(cUnit->baseAddr, offset); 916 917 /* Translation cache update complete - release lock */ 918 dvmUnlockMutex(&gDvmJit.compilerLock); 919 920 /* Record code entry point and instruction set */ 921 info->codeAddress = (char*)cUnit->baseAddr + cUnit->headerSize; 922 /* transfer the size of the profiling code */ 923 info->profileCodeSize = cUnit->profileCodeSize; 924} 925 926/* 927 * Returns the skeleton bit pattern associated with an opcode. All 928 * variable fields are zeroed. 929 */ 930static u4 getSkeleton(MipsOpCode op) 931{ 932 return EncodingMap[op].skeleton; 933} 934 935static u4 assembleChainingBranch(int branchOffset, bool thumbTarget) 936{ 937 return getSkeleton(kMipsJal) | ((branchOffset & 0x0FFFFFFF) >> 2); 938} 939 940/* 941 * Perform translation chain operation. 942 * For MIPS, we'll use a JAL instruction to generate an 943 * unconditional chaining branch of up to 256M. The JAL 944 * instruction also has a restriction that the jump target 945 * must be in the same 256M page as the JAL instruction's 946 * delay slot address. 947 * If the target is out of JAL's range, don't chain. 948 * If one or more threads is suspended, don't chain. 949 */ 950void* dvmJitChain(void* tgtAddr, u4* branchAddr) 951{ 952 u4 newInst; 953 954 /* 955 * Only chain translations when there is no urge to ask all threads to 956 * suspend themselves via the interpreter. 957 */ 958 if ((gDvmJit.pProfTable != NULL) && (gDvm.sumThreadSuspendCount == 0) && 959 (gDvmJit.codeCacheFull == false) && 960 ((((int) tgtAddr) & 0xF0000000) == (((int) branchAddr+4) & 0xF0000000))) { 961 gDvmJit.translationChains++; 962 963 COMPILER_TRACE_CHAINING( 964 LOGD("Jit Runtime: chaining 0x%x to 0x%x", 965 (int) branchAddr, (int) tgtAddr & -2)); 966 967 newInst = assembleChainingBranch((int) tgtAddr & -2, 0); 968 969 UNPROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr)); 970 971 *branchAddr = newInst; 972 dvmCompilerCacheFlush((long)branchAddr, (long)branchAddr + 4, 0); 973 UPDATE_CODE_CACHE_PATCHES(); 974 975 PROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr)); 976 977 gDvmJit.hasNewChain = true; 978 } 979 980 return tgtAddr; 981} 982 983#if !defined(WITH_SELF_VERIFICATION) 984/* 985 * Attempt to enqueue a work order to patch an inline cache for a predicted 986 * chaining cell for virtual/interface calls. 987 */ 988static void inlineCachePatchEnqueue(PredictedChainingCell *cellAddr, 989 PredictedChainingCell *newContent) 990{ 991 /* 992 * Make sure only one thread gets here since updating the cell (ie fast 993 * path and queueing the request (ie the queued path) have to be done 994 * in an atomic fashion. 995 */ 996 dvmLockMutex(&gDvmJit.compilerICPatchLock); 997 998 /* Fast path for uninitialized chaining cell */ 999 if (cellAddr->clazz == NULL && 1000 cellAddr->branch == PREDICTED_CHAIN_BX_PAIR_INIT) { 1001 1002 UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1003 1004 cellAddr->method = newContent->method; 1005 cellAddr->branch = newContent->branch; 1006 1007 /* 1008 * The update order matters - make sure clazz is updated last since it 1009 * will bring the uninitialized chaining cell to life. 1010 */ 1011 android_atomic_release_store((int32_t)newContent->clazz, 1012 (volatile int32_t *)(void*) &cellAddr->clazz); 1013 dvmCompilerCacheFlush((long) cellAddr, (long) (cellAddr+1), 0); 1014 UPDATE_CODE_CACHE_PATCHES(); 1015 1016 PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1017 1018#if defined(WITH_JIT_TUNING) 1019 gDvmJit.icPatchInit++; 1020#endif 1021 /* Check if this is a frequently missed clazz */ 1022 } else if (cellAddr->stagedClazz != newContent->clazz) { 1023 /* Not proven to be frequent yet - build up the filter cache */ 1024 UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1025 1026 cellAddr->stagedClazz = newContent->clazz; 1027 1028 UPDATE_CODE_CACHE_PATCHES(); 1029 PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1030 1031#if defined(WITH_JIT_TUNING) 1032 gDvmJit.icPatchRejected++; 1033#endif 1034 /* 1035 * Different classes but same method implementation - it is safe to just 1036 * patch the class value without the need to stop the world. 1037 */ 1038 } else if (cellAddr->method == newContent->method) { 1039 UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1040 1041 cellAddr->clazz = newContent->clazz; 1042 /* No need to flush the cache here since the branch is not patched */ 1043 UPDATE_CODE_CACHE_PATCHES(); 1044 1045 PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1046 1047#if defined(WITH_JIT_TUNING) 1048 gDvmJit.icPatchLockFree++; 1049#endif 1050 /* 1051 * Cannot patch the chaining cell inline - queue it until the next safe 1052 * point. 1053 */ 1054 } else if (gDvmJit.compilerICPatchIndex < COMPILER_IC_PATCH_QUEUE_SIZE) { 1055 int index = gDvmJit.compilerICPatchIndex++; 1056 const ClassObject *clazz = newContent->clazz; 1057 1058 gDvmJit.compilerICPatchQueue[index].cellAddr = cellAddr; 1059 gDvmJit.compilerICPatchQueue[index].cellContent = *newContent; 1060 gDvmJit.compilerICPatchQueue[index].classDescriptor = clazz->descriptor; 1061 gDvmJit.compilerICPatchQueue[index].classLoader = clazz->classLoader; 1062 /* For verification purpose only */ 1063 gDvmJit.compilerICPatchQueue[index].serialNumber = clazz->serialNumber; 1064#if defined(WITH_JIT_TUNING) 1065 gDvmJit.icPatchQueued++; 1066#endif 1067 } else { 1068 /* Queue is full - just drop this patch request */ 1069#if defined(WITH_JIT_TUNING) 1070 gDvmJit.icPatchDropped++; 1071#endif 1072 } 1073 1074 dvmUnlockMutex(&gDvmJit.compilerICPatchLock); 1075} 1076#endif 1077 1078/* 1079 * This method is called from the invoke templates for virtual and interface 1080 * methods to speculatively setup a chain to the callee. The templates are 1081 * written in assembly and have setup method, cell, and clazz at r0, r2, and 1082 * r3 respectively, so there is a unused argument in the list. Upon return one 1083 * of the following three results may happen: 1084 * 1) Chain is not setup because the callee is native. Reset the rechain 1085 * count to a big number so that it will take a long time before the next 1086 * rechain attempt to happen. 1087 * 2) Chain is not setup because the callee has not been created yet. Reset 1088 * the rechain count to a small number and retry in the near future. 1089 * 3) Ask all other threads to stop before patching this chaining cell. 1090 * This is required because another thread may have passed the class check 1091 * but hasn't reached the chaining cell yet to follow the chain. If we 1092 * patch the content before halting the other thread, there could be a 1093 * small window for race conditions to happen that it may follow the new 1094 * but wrong chain to invoke a different method. 1095 */ 1096const Method *dvmJitToPatchPredictedChain(const Method *method, 1097 Thread *self, 1098 PredictedChainingCell *cell, 1099 const ClassObject *clazz) 1100{ 1101 int newRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN; 1102#if defined(WITH_SELF_VERIFICATION) 1103 newRechainCount = PREDICTED_CHAIN_COUNTER_AVOID; 1104 goto done; 1105#else 1106 PredictedChainingCell newCell; 1107 int baseAddr, tgtAddr; 1108 if (dvmIsNativeMethod(method)) { 1109 UNPROTECT_CODE_CACHE(cell, sizeof(*cell)); 1110 1111 /* 1112 * Put a non-zero/bogus value in the clazz field so that it won't 1113 * trigger immediate patching and will continue to fail to match with 1114 * a real clazz pointer. 1115 */ 1116 cell->clazz = (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ; 1117 1118 UPDATE_CODE_CACHE_PATCHES(); 1119 PROTECT_CODE_CACHE(cell, sizeof(*cell)); 1120 goto done; 1121 } 1122 1123 tgtAddr = (int) dvmJitGetTraceAddr(method->insns); 1124 baseAddr = (int) cell + 4; // PC is cur_addr + 4 1125 1126 if ((baseAddr & 0xF0000000) != (tgtAddr & 0xF0000000)) { 1127 COMPILER_TRACE_CHAINING( 1128 LOGD("Jit Runtime: predicted chain %p to distant target %s ignored", 1129 cell, method->name)); 1130 goto done; 1131 } 1132 1133 /* 1134 * Compilation not made yet for the callee. Reset the counter to a small 1135 * value and come back to check soon. 1136 */ 1137 if ((tgtAddr == 0) || 1138 ((void*)tgtAddr == dvmCompilerGetInterpretTemplate())) { 1139 COMPILER_TRACE_CHAINING( 1140 LOGD("Jit Runtime: predicted chain %p to method %s%s delayed", 1141 cell, method->clazz->descriptor, method->name)); 1142 goto done; 1143 } 1144 1145 if (cell->clazz == NULL) { 1146 newRechainCount = self->icRechainCount; 1147 } 1148 1149 newCell.branch = assembleChainingBranch(tgtAddr, true); 1150 newCell.delay_slot = getSkeleton(kMipsNop); 1151 newCell.clazz = clazz; 1152 newCell.method = method; 1153 newCell.stagedClazz = NULL; 1154 1155 /* 1156 * Enter the work order to the queue and the chaining cell will be patched 1157 * the next time a safe point is entered. 1158 * 1159 * If the enqueuing fails reset the rechain count to a normal value so that 1160 * it won't get indefinitely delayed. 1161 */ 1162 inlineCachePatchEnqueue(cell, &newCell); 1163#endif 1164done: 1165 self->icRechainCount = newRechainCount; 1166 return method; 1167} 1168 1169/* 1170 * Patch the inline cache content based on the content passed from the work 1171 * order. 1172 */ 1173void dvmCompilerPatchInlineCache(void) 1174{ 1175 int i; 1176 PredictedChainingCell *minAddr, *maxAddr; 1177 1178 /* Nothing to be done */ 1179 if (gDvmJit.compilerICPatchIndex == 0) return; 1180 1181 /* 1182 * Since all threads are already stopped we don't really need to acquire 1183 * the lock. But race condition can be easily introduced in the future w/o 1184 * paying attention so we still acquire the lock here. 1185 */ 1186 dvmLockMutex(&gDvmJit.compilerICPatchLock); 1187 1188 UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1189 1190 //LOGD("Number of IC patch work orders: %d", gDvmJit.compilerICPatchIndex); 1191 1192 /* Initialize the min/max address range */ 1193 minAddr = (PredictedChainingCell *) 1194 ((char *) gDvmJit.codeCache + gDvmJit.codeCacheSize); 1195 maxAddr = (PredictedChainingCell *) gDvmJit.codeCache; 1196 1197 for (i = 0; i < gDvmJit.compilerICPatchIndex; i++) { 1198 ICPatchWorkOrder *workOrder = &gDvmJit.compilerICPatchQueue[i]; 1199 PredictedChainingCell *cellAddr = workOrder->cellAddr; 1200 PredictedChainingCell *cellContent = &workOrder->cellContent; 1201 ClassObject *clazz = dvmFindClassNoInit(workOrder->classDescriptor, 1202 workOrder->classLoader); 1203 1204 assert(clazz->serialNumber == workOrder->serialNumber); 1205 1206 /* Use the newly resolved clazz pointer */ 1207 cellContent->clazz = clazz; 1208 1209 COMPILER_TRACE_CHAINING( 1210 LOGD("Jit Runtime: predicted chain %p from %s to %s (%s) " 1211 "patched", 1212 cellAddr, 1213 cellAddr->clazz->descriptor, 1214 cellContent->clazz->descriptor, 1215 cellContent->method->name)); 1216 1217 /* Patch the chaining cell */ 1218 *cellAddr = *cellContent; 1219 minAddr = (cellAddr < minAddr) ? cellAddr : minAddr; 1220 maxAddr = (cellAddr > maxAddr) ? cellAddr : maxAddr; 1221 } 1222 1223 /* Then synchronize the I/D cache */ 1224 dvmCompilerCacheFlush((long) minAddr, (long) (maxAddr+1), 0); 1225 UPDATE_CODE_CACHE_PATCHES(); 1226 1227 PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1228 1229 gDvmJit.compilerICPatchIndex = 0; 1230 dvmUnlockMutex(&gDvmJit.compilerICPatchLock); 1231} 1232 1233/* 1234 * Unchain a trace given the starting address of the translation 1235 * in the code cache. Refer to the diagram in dvmCompilerAssembleLIR. 1236 * Returns the address following the last cell unchained. Note that 1237 * the incoming codeAddr is a thumb code address, and therefore has 1238 * the low bit set. 1239 */ 1240static u4* unchainSingle(JitEntry *trace) 1241{ 1242 const char *base = getTraceBase(trace); 1243 ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base); 1244 int cellSize = getChainCellSize(pChainCellCounts); 1245 u4* pChainCells; 1246 int i,j; 1247 PredictedChainingCell *predChainCell; 1248 1249 if (cellSize == 0) 1250 return (u4 *) pChainCellCounts; 1251 1252 /* Locate the beginning of the chain cell region */ 1253 pChainCells = ((u4 *) pChainCellCounts) - cellSize - 1254 pChainCellCounts->u.count[kChainingCellGap]; 1255 1256 /* The cells are sorted in order - walk through them and reset */ 1257 for (i = 0; i < kChainingCellGap; i++) { 1258 int elemSize = CHAIN_CELL_NORMAL_SIZE >> 2; /* In 32-bit words */ 1259 if (i == kChainingCellInvokePredicted) { 1260 elemSize = CHAIN_CELL_PREDICTED_SIZE >> 2; 1261 } 1262 1263 for (j = 0; j < pChainCellCounts->u.count[i]; j++) { 1264 int targetOffset; 1265 switch(i) { 1266 case kChainingCellNormal: 1267 targetOffset = offsetof(Thread, 1268 jitToInterpEntries.dvmJitToInterpNormal); 1269 break; 1270 case kChainingCellHot: 1271 case kChainingCellInvokeSingleton: 1272 targetOffset = offsetof(Thread, 1273 jitToInterpEntries.dvmJitToInterpTraceSelect); 1274 break; 1275 case kChainingCellInvokePredicted: 1276 targetOffset = 0; 1277 predChainCell = (PredictedChainingCell *) pChainCells; 1278 /* 1279 * There could be a race on another mutator thread to use 1280 * this particular predicted cell and the check has passed 1281 * the clazz comparison. So we cannot safely wipe the 1282 * method and branch but it is safe to clear the clazz, 1283 * which serves as the key. 1284 */ 1285 predChainCell->clazz = PREDICTED_CHAIN_CLAZZ_INIT; 1286 break; 1287#if defined(WITH_SELF_VERIFICATION) 1288 case kChainingCellBackwardBranch: 1289 targetOffset = offsetof(Thread, 1290 jitToInterpEntries.dvmJitToInterpBackwardBranch); 1291 break; 1292#else 1293 case kChainingCellBackwardBranch: 1294 targetOffset = offsetof(Thread, 1295 jitToInterpEntries.dvmJitToInterpNormal); 1296 break; 1297#endif 1298 default: 1299 targetOffset = 0; // make gcc happy 1300 LOGE("Unexpected chaining type: %d", i); 1301 dvmAbort(); // dvmAbort OK here - can't safely recover 1302 } 1303 COMPILER_TRACE_CHAINING( 1304 LOGD("Jit Runtime: unchaining %#x", (int)pChainCells)); 1305 /* 1306 * Code sequence for a chaining cell is: 1307 * lw a0, offset(rSELF) 1308 * jalr ra, a0 1309 */ 1310 if (i != kChainingCellInvokePredicted) { 1311 *pChainCells = getSkeleton(kMipsLw) | (r_A0 << 16) | 1312 targetOffset | (rSELF << 21); 1313 *(pChainCells+1) = getSkeleton(kMipsJalr) | (r_RA << 11) | 1314 (r_A0 << 21); 1315 } 1316 pChainCells += elemSize; /* Advance by a fixed number of words */ 1317 } 1318 } 1319 return pChainCells; 1320} 1321 1322/* Unchain all translation in the cache. */ 1323void dvmJitUnchainAll() 1324{ 1325 u4* lowAddress = NULL; 1326 u4* highAddress = NULL; 1327 unsigned int i; 1328 if (gDvmJit.pJitEntryTable != NULL) { 1329 COMPILER_TRACE_CHAINING(LOGD("Jit Runtime: unchaining all")); 1330 dvmLockMutex(&gDvmJit.tableLock); 1331 1332 UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1333 1334 for (i = 0; i < gDvmJit.jitTableSize; i++) { 1335 if (gDvmJit.pJitEntryTable[i].dPC && 1336 !gDvmJit.pJitEntryTable[i].u.info.isMethodEntry && 1337 gDvmJit.pJitEntryTable[i].codeAddress && 1338 (gDvmJit.pJitEntryTable[i].codeAddress != 1339 dvmCompilerGetInterpretTemplate())) { 1340 u4* lastAddress; 1341 lastAddress = unchainSingle(&gDvmJit.pJitEntryTable[i]); 1342 if (lowAddress == NULL || 1343 (u4*)gDvmJit.pJitEntryTable[i].codeAddress < lowAddress) 1344 lowAddress = (u4*)gDvmJit.pJitEntryTable[i].codeAddress; 1345 if (lastAddress > highAddress) 1346 highAddress = lastAddress; 1347 } 1348 } 1349 1350 if (lowAddress && highAddress) { 1351 dvmCompilerCacheFlush((long)lowAddress, (long)highAddress, 0); 1352 } 1353 1354 UPDATE_CODE_CACHE_PATCHES(); 1355 1356 PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1357 1358 dvmUnlockMutex(&gDvmJit.tableLock); 1359 gDvmJit.translationChains = 0; 1360 } 1361 gDvmJit.hasNewChain = false; 1362} 1363 1364typedef struct jitProfileAddrToLine { 1365 u4 lineNum; 1366 u4 bytecodeOffset; 1367} jitProfileAddrToLine; 1368 1369 1370/* Callback function to track the bytecode offset/line number relationiship */ 1371static int addrToLineCb (void *cnxt, u4 bytecodeOffset, u4 lineNum) 1372{ 1373 jitProfileAddrToLine *addrToLine = (jitProfileAddrToLine *) cnxt; 1374 1375 /* Best match so far for this offset */ 1376 if (addrToLine->bytecodeOffset >= bytecodeOffset) { 1377 addrToLine->lineNum = lineNum; 1378 } 1379 return 0; 1380} 1381 1382/* Dumps profile info for a single trace */ 1383static int dumpTraceProfile(JitEntry *p, bool silent, bool reset, 1384 unsigned long sum) 1385{ 1386 int idx; 1387 1388 if (p->codeAddress == NULL) { 1389 if (!silent) 1390 LOGD("TRACEPROFILE NULL"); 1391 return 0; 1392 } 1393 if (p->codeAddress == dvmCompilerGetInterpretTemplate()) { 1394 if (!silent) 1395 LOGD("TRACEPROFILE INTERPRET_ONLY"); 1396 return 0; 1397 } 1398 1399 JitTraceCounter_t count = getProfileCount(p); 1400 if (reset) { 1401 resetProfileCount(p); 1402 } 1403 if (silent) { 1404 return count; 1405 } 1406 JitTraceDescription *desc = getTraceDescriptionPointer(getTraceBase(p)); 1407 const Method *method = desc->method; 1408 char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype); 1409 jitProfileAddrToLine addrToLine = {0, desc->trace[0].info.frag.startOffset}; 1410 1411 /* 1412 * We may end up decoding the debug information for the same method 1413 * multiple times, but the tradeoff is we don't need to allocate extra 1414 * space to store the addr/line mapping. Since this is a debugging feature 1415 * and done infrequently so the slower but simpler mechanism should work 1416 * just fine. 1417 */ 1418 dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, 1419 dvmGetMethodCode(method), 1420 method->clazz->descriptor, 1421 method->prototype.protoIdx, 1422 method->accessFlags, 1423 addrToLineCb, NULL, &addrToLine); 1424 1425 LOGD("TRACEPROFILE 0x%08x % 10d %5.2f%% [%#x(+%d), %d] %s%s;%s", 1426 (int) getTraceBase(p), 1427 count, 1428 ((float ) count) / sum * 100.0, 1429 desc->trace[0].info.frag.startOffset, 1430 desc->trace[0].info.frag.numInsts, 1431 addrToLine.lineNum, 1432 method->clazz->descriptor, method->name, methodDesc); 1433 free(methodDesc); 1434 1435 /* Find the last fragment (ie runEnd is set) */ 1436 for (idx = 0; 1437 desc->trace[idx].isCode && !desc->trace[idx].info.frag.runEnd; 1438 idx++) { 1439 } 1440 1441 /* 1442 * runEnd must comes with a JitCodeDesc frag. If isCode is false it must 1443 * be a meta info field (only used by callsite info for now). 1444 */ 1445 if (!desc->trace[idx].isCode) { 1446 const Method *method = (const Method *) 1447 desc->trace[idx+JIT_TRACE_CUR_METHOD-1].info.meta; 1448 char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype); 1449 /* Print the callee info in the trace */ 1450 LOGD(" -> %s%s;%s", method->clazz->descriptor, method->name, 1451 methodDesc); 1452 } 1453 1454 return count; 1455} 1456 1457/* Create a copy of the trace descriptor of an existing compilation */ 1458JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc, 1459 const JitEntry *knownEntry) 1460{ 1461 const JitEntry *jitEntry = knownEntry ? knownEntry 1462 : dvmJitFindEntry(pc, false); 1463 if ((jitEntry == NULL) || (jitEntry->codeAddress == 0)) 1464 return NULL; 1465 1466 JitTraceDescription *desc = 1467 getTraceDescriptionPointer(getTraceBase(jitEntry)); 1468 1469 /* Now make a copy and return */ 1470 int descSize = getTraceDescriptionSize(desc); 1471 JitTraceDescription *newCopy = (JitTraceDescription *) malloc(descSize); 1472 memcpy(newCopy, desc, descSize); 1473 return newCopy; 1474} 1475 1476/* qsort callback function */ 1477static int sortTraceProfileCount(const void *entry1, const void *entry2) 1478{ 1479 const JitEntry *jitEntry1 = (const JitEntry *)entry1; 1480 const JitEntry *jitEntry2 = (const JitEntry *)entry2; 1481 1482 JitTraceCounter_t count1 = getProfileCount(jitEntry1); 1483 JitTraceCounter_t count2 = getProfileCount(jitEntry2); 1484 return (count1 == count2) ? 0 : ((count1 > count2) ? -1 : 1); 1485} 1486 1487/* Sort the trace profile counts and dump them */ 1488void dvmCompilerSortAndPrintTraceProfiles() 1489{ 1490 JitEntry *sortedEntries; 1491 int numTraces = 0; 1492 unsigned long sum = 0; 1493 unsigned int i; 1494 1495 /* Make sure that the table is not changing */ 1496 dvmLockMutex(&gDvmJit.tableLock); 1497 1498 /* Sort the entries by descending order */ 1499 sortedEntries = (JitEntry *)malloc(sizeof(JitEntry) * gDvmJit.jitTableSize); 1500 if (sortedEntries == NULL) 1501 goto done; 1502 memcpy(sortedEntries, gDvmJit.pJitEntryTable, 1503 sizeof(JitEntry) * gDvmJit.jitTableSize); 1504 qsort(sortedEntries, gDvmJit.jitTableSize, sizeof(JitEntry), 1505 sortTraceProfileCount); 1506 1507 /* Analyze the sorted entries */ 1508 for (i=0; i < gDvmJit.jitTableSize; i++) { 1509 if (sortedEntries[i].dPC != 0) { 1510 sum += dumpTraceProfile(&sortedEntries[i], 1511 true /* silent */, 1512 false /* reset */, 1513 0); 1514 numTraces++; 1515 } 1516 } 1517 if (numTraces == 0) 1518 numTraces = 1; 1519 if (sum == 0) { 1520 sum = 1; 1521 } 1522 1523 LOGD("JIT: Average execution count -> %d",(int)(sum / numTraces)); 1524 1525 /* Dump the sorted entries. The count of each trace will be reset to 0. */ 1526 for (i=0; i < gDvmJit.jitTableSize; i++) { 1527 if (sortedEntries[i].dPC != 0) { 1528 dumpTraceProfile(&sortedEntries[i], 1529 false /* silent */, 1530 true /* reset */, 1531 sum); 1532 } 1533 } 1534 1535 for (i=0; i < gDvmJit.jitTableSize && i < 10; i++) { 1536 /* Stip interpreter stubs */ 1537 if (sortedEntries[i].codeAddress == dvmCompilerGetInterpretTemplate()) { 1538 continue; 1539 } 1540 JitTraceDescription* desc = 1541 dvmCopyTraceDescriptor(NULL, &sortedEntries[i]); 1542 if (desc) { 1543 dvmCompilerWorkEnqueue(sortedEntries[i].dPC, 1544 kWorkOrderTraceDebug, desc); 1545 } 1546 } 1547 1548 free(sortedEntries); 1549done: 1550 dvmUnlockMutex(&gDvmJit.tableLock); 1551 return; 1552} 1553 1554static void findClassPointersSingleTrace(char *base, void (*callback)(void *)) 1555{ 1556 unsigned int chainTypeIdx, chainIdx; 1557 ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base); 1558 int cellSize = getChainCellSize(pChainCellCounts); 1559 /* Scan the chaining cells */ 1560 if (cellSize) { 1561 /* Locate the beginning of the chain cell region */ 1562 u4 *pChainCells = ((u4 *) pChainCellCounts) - cellSize - 1563 pChainCellCounts->u.count[kChainingCellGap]; 1564 /* The cells are sorted in order - walk through them */ 1565 for (chainTypeIdx = 0; chainTypeIdx < kChainingCellGap; 1566 chainTypeIdx++) { 1567 if (chainTypeIdx != kChainingCellInvokePredicted) { 1568 /* In 32-bit words */ 1569 pChainCells += (CHAIN_CELL_NORMAL_SIZE >> 2) * 1570 pChainCellCounts->u.count[chainTypeIdx]; 1571 continue; 1572 } 1573 for (chainIdx = 0; 1574 chainIdx < pChainCellCounts->u.count[chainTypeIdx]; 1575 chainIdx++) { 1576 PredictedChainingCell *cell = 1577 (PredictedChainingCell *) pChainCells; 1578 /* 1579 * Report the cell if it contains a sane class 1580 * pointer. 1581 */ 1582 if (cell->clazz != NULL && 1583 cell->clazz != 1584 (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ) { 1585 callback(&cell->clazz); 1586 } 1587 pChainCells += CHAIN_CELL_PREDICTED_SIZE >> 2; 1588 } 1589 } 1590 } 1591 1592 /* Scan the class pointer pool */ 1593 JitTraceDescription *desc = getTraceDescriptionPointer(base); 1594 int descSize = getTraceDescriptionSize(desc); 1595 int *classPointerP = (int *) ((char *) desc + descSize); 1596 int numClassPointers = *classPointerP++; 1597 for (; numClassPointers; numClassPointers--, classPointerP++) { 1598 callback(classPointerP); 1599 } 1600} 1601 1602/* 1603 * Scan class pointers in each translation and pass its address to the callback 1604 * function. Currently such a pointers can be found in the pointer pool and the 1605 * clazz field in the predicted chaining cells. 1606 */ 1607void dvmJitScanAllClassPointers(void (*callback)(void *)) 1608{ 1609 UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1610 1611 /* Handle the inflight compilation first */ 1612 if (gDvmJit.inflightBaseAddr) 1613 findClassPointersSingleTrace((char *) gDvmJit.inflightBaseAddr, 1614 callback); 1615 1616 if (gDvmJit.pJitEntryTable != NULL) { 1617 unsigned int traceIdx; 1618 dvmLockMutex(&gDvmJit.tableLock); 1619 for (traceIdx = 0; traceIdx < gDvmJit.jitTableSize; traceIdx++) { 1620 const JitEntry *entry = &gDvmJit.pJitEntryTable[traceIdx]; 1621 if (entry->dPC && 1622 !entry->u.info.isMethodEntry && 1623 entry->codeAddress && 1624 (entry->codeAddress != dvmCompilerGetInterpretTemplate())) { 1625 char *base = getTraceBase(entry); 1626 findClassPointersSingleTrace(base, callback); 1627 } 1628 } 1629 dvmUnlockMutex(&gDvmJit.tableLock); 1630 } 1631 UPDATE_CODE_CACHE_PATCHES(); 1632 1633 PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1634} 1635 1636/* 1637 * Provide the final touch on the class object pointer pool to install the 1638 * actual pointers. The thread has to be in the running state. 1639 */ 1640void dvmJitInstallClassObjectPointers(CompilationUnit *cUnit, char *codeAddress) 1641{ 1642 char *base = codeAddress - cUnit->headerSize; 1643 1644 /* Scan the class pointer pool */ 1645 JitTraceDescription *desc = getTraceDescriptionPointer(base); 1646 int descSize = getTraceDescriptionSize(desc); 1647 intptr_t *classPointerP = (int *) ((char *) desc + descSize); 1648 int numClassPointers = *(int *)classPointerP++; 1649 intptr_t *startClassPointerP = classPointerP; 1650 1651 /* 1652 * Change the thread state to VM_RUNNING so that GC won't be happening 1653 * when the assembler looks up the class pointers. May suspend the current 1654 * thread if there is a pending request before the state is actually 1655 * changed to RUNNING. 1656 */ 1657 dvmChangeStatus(gDvmJit.compilerThread, THREAD_RUNNING); 1658 1659 /* 1660 * Unprotecting the code cache will need to acquire the code cache 1661 * protection lock first. Doing so after the state change may increase the 1662 * time spent in the RUNNING state (which may delay the next GC request 1663 * should there be contention on codeCacheProtectionLock). In practice 1664 * this is probably not going to happen often since a GC is just served. 1665 * More importantly, acquiring the lock before the state change will 1666 * cause deadlock (b/4192964). 1667 */ 1668 UNPROTECT_CODE_CACHE(startClassPointerP, 1669 numClassPointers * sizeof(intptr_t)); 1670#if defined(WITH_JIT_TUNING) 1671 u8 startTime = dvmGetRelativeTimeUsec(); 1672#endif 1673 for (;numClassPointers; numClassPointers--) { 1674 CallsiteInfo *callsiteInfo = (CallsiteInfo *) *classPointerP; 1675 ClassObject *clazz = dvmFindClassNoInit( 1676 callsiteInfo->classDescriptor, callsiteInfo->classLoader); 1677 assert(!strcmp(clazz->descriptor, callsiteInfo->classDescriptor)); 1678 *classPointerP++ = (intptr_t) clazz; 1679 } 1680 1681 /* 1682 * Register the base address so that if GC kicks in after the thread state 1683 * has been changed to VMWAIT and before the compiled code is registered 1684 * in the JIT table, its content can be patched if class objects are 1685 * moved. 1686 */ 1687 gDvmJit.inflightBaseAddr = base; 1688 1689#if defined(WITH_JIT_TUNING) 1690 u8 blockTime = dvmGetRelativeTimeUsec() - startTime; 1691 gDvmJit.compilerThreadBlockGCTime += blockTime; 1692 if (blockTime > gDvmJit.maxCompilerThreadBlockGCTime) 1693 gDvmJit.maxCompilerThreadBlockGCTime = blockTime; 1694 gDvmJit.numCompilerThreadBlockGC++; 1695#endif 1696 UPDATE_CODE_CACHE_PATCHES(); 1697 1698 PROTECT_CODE_CACHE(startClassPointerP, numClassPointers * sizeof(intptr_t)); 1699 1700 /* Change the thread state back to VMWAIT */ 1701 dvmChangeStatus(gDvmJit.compilerThread, THREAD_VMWAIT); 1702} 1703 1704#if defined(WITH_SELF_VERIFICATION) 1705/* 1706 * The following are used to keep compiled loads and stores from modifying 1707 * memory during self verification mode. 1708 * 1709 * Stores do not modify memory. Instead, the address and value pair are stored 1710 * into heapSpace. Addresses within heapSpace are unique. For accesses smaller 1711 * than a word, the word containing the address is loaded first before being 1712 * updated. 1713 * 1714 * Loads check heapSpace first and return data from there if an entry exists. 1715 * Otherwise, data is loaded from memory as usual. 1716 */ 1717 1718/* Used to specify sizes of memory operations */ 1719enum { 1720 kSVByte, 1721 kSVSignedByte, 1722 kSVHalfword, 1723 kSVSignedHalfword, 1724 kSVWord, 1725 kSVDoubleword, 1726 kSVVariable, 1727}; 1728 1729/* Load the value of a decoded register from the stack */ 1730static int selfVerificationMemRegLoad(int* sp, int reg) 1731{ 1732assert(0); /* MIPSTODO retarg func */ 1733 return *(sp + reg); 1734} 1735 1736/* Load the value of a decoded doubleword register from the stack */ 1737static s8 selfVerificationMemRegLoadDouble(int* sp, int reg) 1738{ 1739assert(0); /* MIPSTODO retarg func */ 1740 return *((s8*)(sp + reg)); 1741} 1742 1743/* Store the value of a decoded register out to the stack */ 1744static void selfVerificationMemRegStore(int* sp, int data, int reg) 1745{ 1746assert(0); /* MIPSTODO retarg func */ 1747 *(sp + reg) = data; 1748} 1749 1750/* Store the value of a decoded doubleword register out to the stack */ 1751static void selfVerificationMemRegStoreDouble(int* sp, s8 data, int reg) 1752{ 1753assert(0); /* MIPSTODO retarg func */ 1754 *((s8*)(sp + reg)) = data; 1755} 1756 1757/* 1758 * Load the specified size of data from the specified address, checking 1759 * heapSpace first if Self Verification mode wrote to it previously, and 1760 * falling back to actual memory otherwise. 1761 */ 1762static int selfVerificationLoad(int addr, int size) 1763{ 1764assert(0); /* MIPSTODO retarg func */ 1765 Thread *self = dvmThreadSelf(); 1766 ShadowSpace *shadowSpace = self->shadowSpace; 1767 ShadowHeap *heapSpacePtr; 1768 1769 int data; 1770 int maskedAddr = addr & 0xFFFFFFFC; 1771 int alignment = addr & 0x3; 1772 1773 for (heapSpacePtr = shadowSpace->heapSpace; 1774 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 1775 if (heapSpacePtr->addr == maskedAddr) { 1776 addr = ((unsigned int) &(heapSpacePtr->data)) | alignment; 1777 break; 1778 } 1779 } 1780 1781 switch (size) { 1782 case kSVByte: 1783 data = *((u1*) addr); 1784 break; 1785 case kSVSignedByte: 1786 data = *((s1*) addr); 1787 break; 1788 case kSVHalfword: 1789 data = *((u2*) addr); 1790 break; 1791 case kSVSignedHalfword: 1792 data = *((s2*) addr); 1793 break; 1794 case kSVWord: 1795 data = *((u4*) addr); 1796 break; 1797 default: 1798 LOGE("*** ERROR: BAD SIZE IN selfVerificationLoad: %d", size); 1799 data = 0; 1800 dvmAbort(); 1801 } 1802 1803 //LOGD("*** HEAP LOAD: Addr: %#x Data: %#x Size: %d", addr, data, size); 1804 return data; 1805} 1806 1807/* Like selfVerificationLoad, but specifically for doublewords */ 1808static s8 selfVerificationLoadDoubleword(int addr) 1809{ 1810assert(0); /* MIPSTODO retarg func */ 1811 Thread *self = dvmThreadSelf(); 1812 ShadowSpace* shadowSpace = self->shadowSpace; 1813 ShadowHeap* heapSpacePtr; 1814 1815 int addr2 = addr+4; 1816 unsigned int data = *((unsigned int*) addr); 1817 unsigned int data2 = *((unsigned int*) addr2); 1818 1819 for (heapSpacePtr = shadowSpace->heapSpace; 1820 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 1821 if (heapSpacePtr->addr == addr) { 1822 data = heapSpacePtr->data; 1823 } else if (heapSpacePtr->addr == addr2) { 1824 data2 = heapSpacePtr->data; 1825 } 1826 } 1827 1828 //LOGD("*** HEAP LOAD DOUBLEWORD: Addr: %#x Data: %#x Data2: %#x", 1829 // addr, data, data2); 1830 return (((s8) data2) << 32) | data; 1831} 1832 1833/* 1834 * Handles a store of a specified size of data to a specified address. 1835 * This gets logged as an addr/data pair in heapSpace instead of modifying 1836 * memory. Addresses in heapSpace are unique, and accesses smaller than a 1837 * word pull the entire word from memory first before updating. 1838 */ 1839static void selfVerificationStore(int addr, int data, int size) 1840{ 1841assert(0); /* MIPSTODO retarg func */ 1842 Thread *self = dvmThreadSelf(); 1843 ShadowSpace *shadowSpace = self->shadowSpace; 1844 ShadowHeap *heapSpacePtr; 1845 1846 int maskedAddr = addr & 0xFFFFFFFC; 1847 int alignment = addr & 0x3; 1848 1849 //LOGD("*** HEAP STORE: Addr: %#x Data: %#x Size: %d", addr, data, size); 1850 1851 for (heapSpacePtr = shadowSpace->heapSpace; 1852 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 1853 if (heapSpacePtr->addr == maskedAddr) break; 1854 } 1855 1856 if (heapSpacePtr == shadowSpace->heapSpaceTail) { 1857 heapSpacePtr->addr = maskedAddr; 1858 heapSpacePtr->data = *((unsigned int*) maskedAddr); 1859 shadowSpace->heapSpaceTail++; 1860 } 1861 1862 addr = ((unsigned int) &(heapSpacePtr->data)) | alignment; 1863 switch (size) { 1864 case kSVByte: 1865 *((u1*) addr) = data; 1866 break; 1867 case kSVSignedByte: 1868 *((s1*) addr) = data; 1869 break; 1870 case kSVHalfword: 1871 *((u2*) addr) = data; 1872 break; 1873 case kSVSignedHalfword: 1874 *((s2*) addr) = data; 1875 break; 1876 case kSVWord: 1877 *((u4*) addr) = data; 1878 break; 1879 default: 1880 LOGE("*** ERROR: BAD SIZE IN selfVerificationSave: %d", size); 1881 dvmAbort(); 1882 } 1883} 1884 1885/* Like selfVerificationStore, but specifically for doublewords */ 1886static void selfVerificationStoreDoubleword(int addr, s8 double_data) 1887{ 1888assert(0); /* MIPSTODO retarg func */ 1889 Thread *self = dvmThreadSelf(); 1890 ShadowSpace *shadowSpace = self->shadowSpace; 1891 ShadowHeap *heapSpacePtr; 1892 1893 int addr2 = addr+4; 1894 int data = double_data; 1895 int data2 = double_data >> 32; 1896 bool store1 = false, store2 = false; 1897 1898 //LOGD("*** HEAP STORE DOUBLEWORD: Addr: %#x Data: %#x, Data2: %#x", 1899 // addr, data, data2); 1900 1901 for (heapSpacePtr = shadowSpace->heapSpace; 1902 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 1903 if (heapSpacePtr->addr == addr) { 1904 heapSpacePtr->data = data; 1905 store1 = true; 1906 } else if (heapSpacePtr->addr == addr2) { 1907 heapSpacePtr->data = data2; 1908 store2 = true; 1909 } 1910 } 1911 1912 if (!store1) { 1913 shadowSpace->heapSpaceTail->addr = addr; 1914 shadowSpace->heapSpaceTail->data = data; 1915 shadowSpace->heapSpaceTail++; 1916 } 1917 if (!store2) { 1918 shadowSpace->heapSpaceTail->addr = addr2; 1919 shadowSpace->heapSpaceTail->data = data2; 1920 shadowSpace->heapSpaceTail++; 1921 } 1922} 1923 1924/* 1925 * Decodes the memory instruction at the address specified in the link 1926 * register. All registers (r0-r12,lr) and fp registers (d0-d15) are stored 1927 * consecutively on the stack beginning at the specified stack pointer. 1928 * Calls the proper Self Verification handler for the memory instruction and 1929 * updates the link register to point past the decoded memory instruction. 1930 */ 1931void dvmSelfVerificationMemOpDecode(int lr, int* sp) 1932{ 1933assert(0); /* MIPSTODO retarg func */ 1934 enum { 1935 kMemOpLdrPcRel = 0x09, // ldr(3) [01001] rd[10..8] imm_8[7..0] 1936 kMemOpRRR = 0x0A, // Full opcode is 7 bits 1937 kMemOp2Single = 0x0A, // Used for Vstrs and Vldrs 1938 kMemOpRRR2 = 0x0B, // Full opcode is 7 bits 1939 kMemOp2Double = 0x0B, // Used for Vstrd and Vldrd 1940 kMemOpStrRRI5 = 0x0C, // str(1) [01100] imm_5[10..6] rn[5..3] rd[2..0] 1941 kMemOpLdrRRI5 = 0x0D, // ldr(1) [01101] imm_5[10..6] rn[5..3] rd[2..0] 1942 kMemOpStrbRRI5 = 0x0E, // strb(1) [01110] imm_5[10..6] rn[5..3] rd[2..0] 1943 kMemOpLdrbRRI5 = 0x0F, // ldrb(1) [01111] imm_5[10..6] rn[5..3] rd[2..0] 1944 kMemOpStrhRRI5 = 0x10, // strh(1) [10000] imm_5[10..6] rn[5..3] rd[2..0] 1945 kMemOpLdrhRRI5 = 0x11, // ldrh(1) [10001] imm_5[10..6] rn[5..3] rd[2..0] 1946 kMemOpLdrSpRel = 0x13, // ldr(4) [10011] rd[10..8] imm_8[7..0] 1947 kMemOpStmia = 0x18, // stmia [11000] rn[10..8] reglist [7..0] 1948 kMemOpLdmia = 0x19, // ldmia [11001] rn[10..8] reglist [7..0] 1949 kMemOpStrRRR = 0x28, // str(2) [0101000] rm[8..6] rn[5..3] rd[2..0] 1950 kMemOpStrhRRR = 0x29, // strh(2) [0101001] rm[8..6] rn[5..3] rd[2..0] 1951 kMemOpStrbRRR = 0x2A, // strb(2) [0101010] rm[8..6] rn[5..3] rd[2..0] 1952 kMemOpLdrsbRRR = 0x2B, // ldrsb [0101011] rm[8..6] rn[5..3] rd[2..0] 1953 kMemOpLdrRRR = 0x2C, // ldr(2) [0101100] rm[8..6] rn[5..3] rd[2..0] 1954 kMemOpLdrhRRR = 0x2D, // ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0] 1955 kMemOpLdrbRRR = 0x2E, // ldrb(2) [0101110] rm[8..6] rn[5..3] rd[2..0] 1956 kMemOpLdrshRRR = 0x2F, // ldrsh [0101111] rm[8..6] rn[5..3] rd[2..0] 1957 kMemOp2Stmia = 0xE88, // stmia [111010001000[ rn[19..16] mask[15..0] 1958 kMemOp2Ldmia = 0xE89, // ldmia [111010001001[ rn[19..16] mask[15..0] 1959 kMemOp2Stmia2 = 0xE8A, // stmia [111010001010[ rn[19..16] mask[15..0] 1960 kMemOp2Ldmia2 = 0xE8B, // ldmia [111010001011[ rn[19..16] mask[15..0] 1961 kMemOp2Vstr = 0xED8, // Used for Vstrs and Vstrd 1962 kMemOp2Vldr = 0xED9, // Used for Vldrs and Vldrd 1963 kMemOp2Vstr2 = 0xEDC, // Used for Vstrs and Vstrd 1964 kMemOp2Vldr2 = 0xEDD, // Used for Vstrs and Vstrd 1965 kMemOp2StrbRRR = 0xF80, /* str rt,[rn,rm,LSL #imm] [111110000000] 1966 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1967 kMemOp2LdrbRRR = 0xF81, /* ldrb rt,[rn,rm,LSL #imm] [111110000001] 1968 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1969 kMemOp2StrhRRR = 0xF82, /* str rt,[rn,rm,LSL #imm] [111110000010] 1970 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1971 kMemOp2LdrhRRR = 0xF83, /* ldrh rt,[rn,rm,LSL #imm] [111110000011] 1972 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1973 kMemOp2StrRRR = 0xF84, /* str rt,[rn,rm,LSL #imm] [111110000100] 1974 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1975 kMemOp2LdrRRR = 0xF85, /* ldr rt,[rn,rm,LSL #imm] [111110000101] 1976 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1977 kMemOp2StrbRRI12 = 0xF88, /* strb rt,[rn,#imm12] [111110001000] 1978 rt[15..12] rn[19..16] imm12[11..0] */ 1979 kMemOp2LdrbRRI12 = 0xF89, /* ldrb rt,[rn,#imm12] [111110001001] 1980 rt[15..12] rn[19..16] imm12[11..0] */ 1981 kMemOp2StrhRRI12 = 0xF8A, /* strh rt,[rn,#imm12] [111110001010] 1982 rt[15..12] rn[19..16] imm12[11..0] */ 1983 kMemOp2LdrhRRI12 = 0xF8B, /* ldrh rt,[rn,#imm12] [111110001011] 1984 rt[15..12] rn[19..16] imm12[11..0] */ 1985 kMemOp2StrRRI12 = 0xF8C, /* str(Imm,T3) rd,[rn,#imm12] [111110001100] 1986 rn[19..16] rt[15..12] imm12[11..0] */ 1987 kMemOp2LdrRRI12 = 0xF8D, /* ldr(Imm,T3) rd,[rn,#imm12] [111110001101] 1988 rn[19..16] rt[15..12] imm12[11..0] */ 1989 kMemOp2LdrsbRRR = 0xF91, /* ldrsb rt,[rn,rm,LSL #imm] [111110010001] 1990 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1991 kMemOp2LdrshRRR = 0xF93, /* ldrsh rt,[rn,rm,LSL #imm] [111110010011] 1992 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1993 kMemOp2LdrsbRRI12 = 0xF99, /* ldrsb rt,[rn,#imm12] [111110011001] 1994 rt[15..12] rn[19..16] imm12[11..0] */ 1995 kMemOp2LdrshRRI12 = 0xF9B, /* ldrsh rt,[rn,#imm12] [111110011011] 1996 rt[15..12] rn[19..16] imm12[11..0] */ 1997 kMemOp2 = 0xE000, // top 3 bits set indicates Thumb2 1998 }; 1999 2000 int addr, offset, data; 2001 long long double_data; 2002 int size = kSVWord; 2003 bool store = false; 2004 unsigned int *lr_masked = (unsigned int *) (lr & 0xFFFFFFFE); 2005 unsigned int insn = *lr_masked; 2006 2007 int old_lr; 2008 old_lr = selfVerificationMemRegLoad(sp, 13); 2009 2010 if ((insn & kMemOp2) == kMemOp2) { 2011 insn = (insn << 16) | (insn >> 16); 2012 //LOGD("*** THUMB2 - Addr: %#x Insn: %#x", lr, insn); 2013 2014 int opcode12 = (insn >> 20) & 0xFFF; 2015 int opcode6 = (insn >> 6) & 0x3F; 2016 int opcode4 = (insn >> 8) & 0xF; 2017 int imm2 = (insn >> 4) & 0x3; 2018 int imm8 = insn & 0xFF; 2019 int imm12 = insn & 0xFFF; 2020 int rd = (insn >> 12) & 0xF; 2021 int rm = insn & 0xF; 2022 int rn = (insn >> 16) & 0xF; 2023 int rt = (insn >> 12) & 0xF; 2024 bool wBack = true; 2025 2026 // Update the link register 2027 selfVerificationMemRegStore(sp, old_lr+4, 13); 2028 2029 // Determine whether the mem op is a store or load 2030 switch (opcode12) { 2031 case kMemOp2Stmia: 2032 case kMemOp2Stmia2: 2033 case kMemOp2Vstr: 2034 case kMemOp2Vstr2: 2035 case kMemOp2StrbRRR: 2036 case kMemOp2StrhRRR: 2037 case kMemOp2StrRRR: 2038 case kMemOp2StrbRRI12: 2039 case kMemOp2StrhRRI12: 2040 case kMemOp2StrRRI12: 2041 store = true; 2042 } 2043 2044 // Determine the size of the mem access 2045 switch (opcode12) { 2046 case kMemOp2StrbRRR: 2047 case kMemOp2LdrbRRR: 2048 case kMemOp2StrbRRI12: 2049 case kMemOp2LdrbRRI12: 2050 size = kSVByte; 2051 break; 2052 case kMemOp2LdrsbRRR: 2053 case kMemOp2LdrsbRRI12: 2054 size = kSVSignedByte; 2055 break; 2056 case kMemOp2StrhRRR: 2057 case kMemOp2LdrhRRR: 2058 case kMemOp2StrhRRI12: 2059 case kMemOp2LdrhRRI12: 2060 size = kSVHalfword; 2061 break; 2062 case kMemOp2LdrshRRR: 2063 case kMemOp2LdrshRRI12: 2064 size = kSVSignedHalfword; 2065 break; 2066 case kMemOp2Vstr: 2067 case kMemOp2Vstr2: 2068 case kMemOp2Vldr: 2069 case kMemOp2Vldr2: 2070 if (opcode4 == kMemOp2Double) size = kSVDoubleword; 2071 break; 2072 case kMemOp2Stmia: 2073 case kMemOp2Ldmia: 2074 case kMemOp2Stmia2: 2075 case kMemOp2Ldmia2: 2076 size = kSVVariable; 2077 break; 2078 } 2079 2080 // Load the value of the address 2081 addr = selfVerificationMemRegLoad(sp, rn); 2082 2083 // Figure out the offset 2084 switch (opcode12) { 2085 case kMemOp2Vstr: 2086 case kMemOp2Vstr2: 2087 case kMemOp2Vldr: 2088 case kMemOp2Vldr2: 2089 offset = imm8 << 2; 2090 if (opcode4 == kMemOp2Single) { 2091 rt = rd << 1; 2092 if (insn & 0x400000) rt |= 0x1; 2093 } else if (opcode4 == kMemOp2Double) { 2094 if (insn & 0x400000) rt |= 0x10; 2095 rt = rt << 1; 2096 } else { 2097 LOGE("*** ERROR: UNRECOGNIZED VECTOR MEM OP: %x", opcode4); 2098 dvmAbort(); 2099 } 2100 rt += 14; 2101 break; 2102 case kMemOp2StrbRRR: 2103 case kMemOp2LdrbRRR: 2104 case kMemOp2StrhRRR: 2105 case kMemOp2LdrhRRR: 2106 case kMemOp2StrRRR: 2107 case kMemOp2LdrRRR: 2108 case kMemOp2LdrsbRRR: 2109 case kMemOp2LdrshRRR: 2110 offset = selfVerificationMemRegLoad(sp, rm) << imm2; 2111 break; 2112 case kMemOp2StrbRRI12: 2113 case kMemOp2LdrbRRI12: 2114 case kMemOp2StrhRRI12: 2115 case kMemOp2LdrhRRI12: 2116 case kMemOp2StrRRI12: 2117 case kMemOp2LdrRRI12: 2118 case kMemOp2LdrsbRRI12: 2119 case kMemOp2LdrshRRI12: 2120 offset = imm12; 2121 break; 2122 case kMemOp2Stmia: 2123 case kMemOp2Ldmia: 2124 wBack = false; 2125 case kMemOp2Stmia2: 2126 case kMemOp2Ldmia2: 2127 offset = 0; 2128 break; 2129 default: 2130 LOGE("*** ERROR: UNRECOGNIZED THUMB2 MEM OP: %x", opcode12); 2131 offset = 0; 2132 dvmAbort(); 2133 } 2134 2135 // Handle the decoded mem op accordingly 2136 if (store) { 2137 if (size == kSVVariable) { 2138 LOGD("*** THUMB2 STMIA CURRENTLY UNUSED (AND UNTESTED)"); 2139 int i; 2140 int regList = insn & 0xFFFF; 2141 for (i = 0; i < 16; i++) { 2142 if (regList & 0x1) { 2143 data = selfVerificationMemRegLoad(sp, i); 2144 selfVerificationStore(addr, data, kSVWord); 2145 addr += 4; 2146 } 2147 regList = regList >> 1; 2148 } 2149 if (wBack) selfVerificationMemRegStore(sp, addr, rn); 2150 } else if (size == kSVDoubleword) { 2151 double_data = selfVerificationMemRegLoadDouble(sp, rt); 2152 selfVerificationStoreDoubleword(addr+offset, double_data); 2153 } else { 2154 data = selfVerificationMemRegLoad(sp, rt); 2155 selfVerificationStore(addr+offset, data, size); 2156 } 2157 } else { 2158 if (size == kSVVariable) { 2159 LOGD("*** THUMB2 LDMIA CURRENTLY UNUSED (AND UNTESTED)"); 2160 int i; 2161 int regList = insn & 0xFFFF; 2162 for (i = 0; i < 16; i++) { 2163 if (regList & 0x1) { 2164 data = selfVerificationLoad(addr, kSVWord); 2165 selfVerificationMemRegStore(sp, data, i); 2166 addr += 4; 2167 } 2168 regList = regList >> 1; 2169 } 2170 if (wBack) selfVerificationMemRegStore(sp, addr, rn); 2171 } else if (size == kSVDoubleword) { 2172 double_data = selfVerificationLoadDoubleword(addr+offset); 2173 selfVerificationMemRegStoreDouble(sp, double_data, rt); 2174 } else { 2175 data = selfVerificationLoad(addr+offset, size); 2176 selfVerificationMemRegStore(sp, data, rt); 2177 } 2178 } 2179 } else { 2180 //LOGD("*** THUMB - Addr: %#x Insn: %#x", lr, insn); 2181 2182 // Update the link register 2183 selfVerificationMemRegStore(sp, old_lr+2, 13); 2184 2185 int opcode5 = (insn >> 11) & 0x1F; 2186 int opcode7 = (insn >> 9) & 0x7F; 2187 int imm = (insn >> 6) & 0x1F; 2188 int rd = (insn >> 8) & 0x7; 2189 int rm = (insn >> 6) & 0x7; 2190 int rn = (insn >> 3) & 0x7; 2191 int rt = insn & 0x7; 2192 2193 // Determine whether the mem op is a store or load 2194 switch (opcode5) { 2195 case kMemOpRRR: 2196 switch (opcode7) { 2197 case kMemOpStrRRR: 2198 case kMemOpStrhRRR: 2199 case kMemOpStrbRRR: 2200 store = true; 2201 } 2202 break; 2203 case kMemOpStrRRI5: 2204 case kMemOpStrbRRI5: 2205 case kMemOpStrhRRI5: 2206 case kMemOpStmia: 2207 store = true; 2208 } 2209 2210 // Determine the size of the mem access 2211 switch (opcode5) { 2212 case kMemOpRRR: 2213 case kMemOpRRR2: 2214 switch (opcode7) { 2215 case kMemOpStrbRRR: 2216 case kMemOpLdrbRRR: 2217 size = kSVByte; 2218 break; 2219 case kMemOpLdrsbRRR: 2220 size = kSVSignedByte; 2221 break; 2222 case kMemOpStrhRRR: 2223 case kMemOpLdrhRRR: 2224 size = kSVHalfword; 2225 break; 2226 case kMemOpLdrshRRR: 2227 size = kSVSignedHalfword; 2228 break; 2229 } 2230 break; 2231 case kMemOpStrbRRI5: 2232 case kMemOpLdrbRRI5: 2233 size = kSVByte; 2234 break; 2235 case kMemOpStrhRRI5: 2236 case kMemOpLdrhRRI5: 2237 size = kSVHalfword; 2238 break; 2239 case kMemOpStmia: 2240 case kMemOpLdmia: 2241 size = kSVVariable; 2242 break; 2243 } 2244 2245 // Load the value of the address 2246 if (opcode5 == kMemOpLdrPcRel) 2247 addr = selfVerificationMemRegLoad(sp, 4); 2248 else if (opcode5 == kMemOpStmia || opcode5 == kMemOpLdmia) 2249 addr = selfVerificationMemRegLoad(sp, rd); 2250 else 2251 addr = selfVerificationMemRegLoad(sp, rn); 2252 2253 // Figure out the offset 2254 switch (opcode5) { 2255 case kMemOpLdrPcRel: 2256 offset = (insn & 0xFF) << 2; 2257 rt = rd; 2258 break; 2259 case kMemOpRRR: 2260 case kMemOpRRR2: 2261 offset = selfVerificationMemRegLoad(sp, rm); 2262 break; 2263 case kMemOpStrRRI5: 2264 case kMemOpLdrRRI5: 2265 offset = imm << 2; 2266 break; 2267 case kMemOpStrhRRI5: 2268 case kMemOpLdrhRRI5: 2269 offset = imm << 1; 2270 break; 2271 case kMemOpStrbRRI5: 2272 case kMemOpLdrbRRI5: 2273 offset = imm; 2274 break; 2275 case kMemOpStmia: 2276 case kMemOpLdmia: 2277 offset = 0; 2278 break; 2279 default: 2280 LOGE("*** ERROR: UNRECOGNIZED THUMB MEM OP: %x", opcode5); 2281 offset = 0; 2282 dvmAbort(); 2283 } 2284 2285 // Handle the decoded mem op accordingly 2286 if (store) { 2287 if (size == kSVVariable) { 2288 int i; 2289 int regList = insn & 0xFF; 2290 for (i = 0; i < 8; i++) { 2291 if (regList & 0x1) { 2292 data = selfVerificationMemRegLoad(sp, i); 2293 selfVerificationStore(addr, data, kSVWord); 2294 addr += 4; 2295 } 2296 regList = regList >> 1; 2297 } 2298 selfVerificationMemRegStore(sp, addr, rd); 2299 } else { 2300 data = selfVerificationMemRegLoad(sp, rt); 2301 selfVerificationStore(addr+offset, data, size); 2302 } 2303 } else { 2304 if (size == kSVVariable) { 2305 bool wBack = true; 2306 int i; 2307 int regList = insn & 0xFF; 2308 for (i = 0; i < 8; i++) { 2309 if (regList & 0x1) { 2310 if (i == rd) wBack = false; 2311 data = selfVerificationLoad(addr, kSVWord); 2312 selfVerificationMemRegStore(sp, data, i); 2313 addr += 4; 2314 } 2315 regList = regList >> 1; 2316 } 2317 if (wBack) selfVerificationMemRegStore(sp, addr, rd); 2318 } else { 2319 data = selfVerificationLoad(addr+offset, size); 2320 selfVerificationMemRegStore(sp, data, rt); 2321 } 2322 } 2323 } 2324} 2325#endif 2326