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 */ 80 MipsEncodingMap 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 */ 409 static 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 */ 436 static 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 ALOGE("PC-rel distance is not multiple of 4: %d", delta); 459 dvmAbort(); 460 } 461 if (delta > 131068 || delta < -131069) { 462 ALOGE("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 ALOGE("PC-rel distance is not multiple of 4: %d", delta); 473 dvmAbort(); 474 } 475 if (delta > 131068 || delta < -131069) { 476 ALOGE("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 ALOGE("PC-rel distance is not multiple of 4: %d", delta); 487 dvmAbort(); 488 } 489 if (delta > 131068 || delta < -131069) { 490 ALOGE("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 ALOGE("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 558 static 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 */ 568 static 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 */ 630 static 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 */ 637 static 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 */ 649 static 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 */ 661 static 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 */ 670 static 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 */ 689 static 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 */ 696 static 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 */ 710 static 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 ALOGD("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 */ 743 void 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 ALOGE("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 ALOGE("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 */ 930 static u4 getSkeleton(MipsOpCode op) 931 { 932 return EncodingMap[op].skeleton; 933 } 934 935 static 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 */ 950 void* 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 ALOGD("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 */ 988 static 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 */ 1096 const 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 ALOGD("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 ALOGD("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 1164 done: 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 */ 1173 void 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 //ALOGD("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 ALOGD("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 */ 1240 static 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 ALOGE("Unexpected chaining type: %d", i); 1301 dvmAbort(); // dvmAbort OK here - can't safely recover 1302 } 1303 COMPILER_TRACE_CHAINING( 1304 ALOGD("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. */ 1323 void dvmJitUnchainAll() 1324 { 1325 u4* lowAddress = NULL; 1326 u4* highAddress = NULL; 1327 unsigned int i; 1328 if (gDvmJit.pJitEntryTable != NULL) { 1329 COMPILER_TRACE_CHAINING(ALOGD("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 UPDATE_CODE_CACHE_PATCHES(); 1354 1355 PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1356 1357 dvmUnlockMutex(&gDvmJit.tableLock); 1358 gDvmJit.translationChains = 0; 1359 } 1360 gDvmJit.hasNewChain = false; 1361 } 1362 1363 typedef struct jitProfileAddrToLine { 1364 u4 lineNum; 1365 u4 bytecodeOffset; 1366 } jitProfileAddrToLine; 1367 1368 1369 /* Callback function to track the bytecode offset/line number relationiship */ 1370 static int addrToLineCb (void *cnxt, u4 bytecodeOffset, u4 lineNum) 1371 { 1372 jitProfileAddrToLine *addrToLine = (jitProfileAddrToLine *) cnxt; 1373 1374 /* Best match so far for this offset */ 1375 if (addrToLine->bytecodeOffset >= bytecodeOffset) { 1376 addrToLine->lineNum = lineNum; 1377 } 1378 return 0; 1379 } 1380 1381 /* Dumps profile info for a single trace */ 1382 static int dumpTraceProfile(JitEntry *p, bool silent, bool reset, 1383 unsigned long sum) 1384 { 1385 int idx; 1386 1387 if (p->codeAddress == NULL) { 1388 if (!silent) 1389 ALOGD("TRACEPROFILE NULL"); 1390 return 0; 1391 } 1392 if (p->codeAddress == dvmCompilerGetInterpretTemplate()) { 1393 if (!silent) 1394 ALOGD("TRACEPROFILE INTERPRET_ONLY"); 1395 return 0; 1396 } 1397 1398 JitTraceCounter_t count = getProfileCount(p); 1399 if (reset) { 1400 resetProfileCount(p); 1401 } 1402 if (silent) { 1403 return count; 1404 } 1405 JitTraceDescription *desc = getTraceDescriptionPointer(getTraceBase(p)); 1406 const Method *method = desc->method; 1407 char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype); 1408 jitProfileAddrToLine addrToLine = {0, desc->trace[0].info.frag.startOffset}; 1409 1410 /* 1411 * We may end up decoding the debug information for the same method 1412 * multiple times, but the tradeoff is we don't need to allocate extra 1413 * space to store the addr/line mapping. Since this is a debugging feature 1414 * and done infrequently so the slower but simpler mechanism should work 1415 * just fine. 1416 */ 1417 dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, 1418 dvmGetMethodCode(method), 1419 method->clazz->descriptor, 1420 method->prototype.protoIdx, 1421 method->accessFlags, 1422 addrToLineCb, NULL, &addrToLine); 1423 1424 ALOGD("TRACEPROFILE 0x%08x % 10d %5.2f%% [%#x(+%d), %d] %s%s;%s", 1425 (int) getTraceBase(p), 1426 count, 1427 ((float ) count) / sum * 100.0, 1428 desc->trace[0].info.frag.startOffset, 1429 desc->trace[0].info.frag.numInsts, 1430 addrToLine.lineNum, 1431 method->clazz->descriptor, method->name, methodDesc); 1432 free(methodDesc); 1433 1434 /* Find the last fragment (ie runEnd is set) */ 1435 for (idx = 0; 1436 desc->trace[idx].isCode && !desc->trace[idx].info.frag.runEnd; 1437 idx++) { 1438 } 1439 1440 /* 1441 * runEnd must comes with a JitCodeDesc frag. If isCode is false it must 1442 * be a meta info field (only used by callsite info for now). 1443 */ 1444 if (!desc->trace[idx].isCode) { 1445 const Method *method = (const Method *) 1446 desc->trace[idx+JIT_TRACE_CUR_METHOD-1].info.meta; 1447 char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype); 1448 /* Print the callee info in the trace */ 1449 ALOGD(" -> %s%s;%s", method->clazz->descriptor, method->name, 1450 methodDesc); 1451 } 1452 1453 return count; 1454 } 1455 1456 /* Create a copy of the trace descriptor of an existing compilation */ 1457 JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc, 1458 const JitEntry *knownEntry) 1459 { 1460 const JitEntry *jitEntry = knownEntry ? knownEntry 1461 : dvmJitFindEntry(pc, false); 1462 if ((jitEntry == NULL) || (jitEntry->codeAddress == 0)) 1463 return NULL; 1464 1465 JitTraceDescription *desc = 1466 getTraceDescriptionPointer(getTraceBase(jitEntry)); 1467 1468 /* Now make a copy and return */ 1469 int descSize = getTraceDescriptionSize(desc); 1470 JitTraceDescription *newCopy = (JitTraceDescription *) malloc(descSize); 1471 memcpy(newCopy, desc, descSize); 1472 return newCopy; 1473 } 1474 1475 /* qsort callback function */ 1476 static int sortTraceProfileCount(const void *entry1, const void *entry2) 1477 { 1478 const JitEntry *jitEntry1 = (const JitEntry *)entry1; 1479 const JitEntry *jitEntry2 = (const JitEntry *)entry2; 1480 1481 JitTraceCounter_t count1 = getProfileCount(jitEntry1); 1482 JitTraceCounter_t count2 = getProfileCount(jitEntry2); 1483 return (count1 == count2) ? 0 : ((count1 > count2) ? -1 : 1); 1484 } 1485 1486 /* Sort the trace profile counts and dump them */ 1487 void dvmCompilerSortAndPrintTraceProfiles() 1488 { 1489 JitEntry *sortedEntries; 1490 int numTraces = 0; 1491 unsigned long sum = 0; 1492 unsigned int i; 1493 1494 /* Make sure that the table is not changing */ 1495 dvmLockMutex(&gDvmJit.tableLock); 1496 1497 /* Sort the entries by descending order */ 1498 sortedEntries = (JitEntry *)malloc(sizeof(JitEntry) * gDvmJit.jitTableSize); 1499 if (sortedEntries == NULL) 1500 goto done; 1501 memcpy(sortedEntries, gDvmJit.pJitEntryTable, 1502 sizeof(JitEntry) * gDvmJit.jitTableSize); 1503 qsort(sortedEntries, gDvmJit.jitTableSize, sizeof(JitEntry), 1504 sortTraceProfileCount); 1505 1506 /* Analyze the sorted entries */ 1507 for (i=0; i < gDvmJit.jitTableSize; i++) { 1508 if (sortedEntries[i].dPC != 0) { 1509 sum += dumpTraceProfile(&sortedEntries[i], 1510 true /* silent */, 1511 false /* reset */, 1512 0); 1513 numTraces++; 1514 } 1515 } 1516 if (numTraces == 0) 1517 numTraces = 1; 1518 if (sum == 0) { 1519 sum = 1; 1520 } 1521 1522 ALOGD("JIT: Average execution count -> %d",(int)(sum / numTraces)); 1523 1524 /* Dump the sorted entries. The count of each trace will be reset to 0. */ 1525 for (i=0; i < gDvmJit.jitTableSize; i++) { 1526 if (sortedEntries[i].dPC != 0) { 1527 dumpTraceProfile(&sortedEntries[i], 1528 false /* silent */, 1529 true /* reset */, 1530 sum); 1531 } 1532 } 1533 1534 for (i=0; i < gDvmJit.jitTableSize && i < 10; i++) { 1535 /* Stip interpreter stubs */ 1536 if (sortedEntries[i].codeAddress == dvmCompilerGetInterpretTemplate()) { 1537 continue; 1538 } 1539 JitTraceDescription* desc = 1540 dvmCopyTraceDescriptor(NULL, &sortedEntries[i]); 1541 if (desc) { 1542 dvmCompilerWorkEnqueue(sortedEntries[i].dPC, 1543 kWorkOrderTraceDebug, desc); 1544 } 1545 } 1546 1547 free(sortedEntries); 1548 done: 1549 dvmUnlockMutex(&gDvmJit.tableLock); 1550 return; 1551 } 1552 1553 static void findClassPointersSingleTrace(char *base, void (*callback)(void *)) 1554 { 1555 unsigned int chainTypeIdx, chainIdx; 1556 ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base); 1557 int cellSize = getChainCellSize(pChainCellCounts); 1558 /* Scan the chaining cells */ 1559 if (cellSize) { 1560 /* Locate the beginning of the chain cell region */ 1561 u4 *pChainCells = ((u4 *) pChainCellCounts) - cellSize - 1562 pChainCellCounts->u.count[kChainingCellGap]; 1563 /* The cells are sorted in order - walk through them */ 1564 for (chainTypeIdx = 0; chainTypeIdx < kChainingCellGap; 1565 chainTypeIdx++) { 1566 if (chainTypeIdx != kChainingCellInvokePredicted) { 1567 /* In 32-bit words */ 1568 pChainCells += (CHAIN_CELL_NORMAL_SIZE >> 2) * 1569 pChainCellCounts->u.count[chainTypeIdx]; 1570 continue; 1571 } 1572 for (chainIdx = 0; 1573 chainIdx < pChainCellCounts->u.count[chainTypeIdx]; 1574 chainIdx++) { 1575 PredictedChainingCell *cell = 1576 (PredictedChainingCell *) pChainCells; 1577 /* 1578 * Report the cell if it contains a sane class 1579 * pointer. 1580 */ 1581 if (cell->clazz != NULL && 1582 cell->clazz != 1583 (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ) { 1584 callback(&cell->clazz); 1585 } 1586 pChainCells += CHAIN_CELL_PREDICTED_SIZE >> 2; 1587 } 1588 } 1589 } 1590 1591 /* Scan the class pointer pool */ 1592 JitTraceDescription *desc = getTraceDescriptionPointer(base); 1593 int descSize = getTraceDescriptionSize(desc); 1594 int *classPointerP = (int *) ((char *) desc + descSize); 1595 int numClassPointers = *classPointerP++; 1596 for (; numClassPointers; numClassPointers--, classPointerP++) { 1597 callback(classPointerP); 1598 } 1599 } 1600 1601 /* 1602 * Scan class pointers in each translation and pass its address to the callback 1603 * function. Currently such a pointers can be found in the pointer pool and the 1604 * clazz field in the predicted chaining cells. 1605 */ 1606 void dvmJitScanAllClassPointers(void (*callback)(void *)) 1607 { 1608 UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1609 1610 /* Handle the inflight compilation first */ 1611 if (gDvmJit.inflightBaseAddr) 1612 findClassPointersSingleTrace((char *) gDvmJit.inflightBaseAddr, 1613 callback); 1614 1615 if (gDvmJit.pJitEntryTable != NULL) { 1616 unsigned int traceIdx; 1617 dvmLockMutex(&gDvmJit.tableLock); 1618 for (traceIdx = 0; traceIdx < gDvmJit.jitTableSize; traceIdx++) { 1619 const JitEntry *entry = &gDvmJit.pJitEntryTable[traceIdx]; 1620 if (entry->dPC && 1621 !entry->u.info.isMethodEntry && 1622 entry->codeAddress && 1623 (entry->codeAddress != dvmCompilerGetInterpretTemplate())) { 1624 char *base = getTraceBase(entry); 1625 findClassPointersSingleTrace(base, callback); 1626 } 1627 } 1628 dvmUnlockMutex(&gDvmJit.tableLock); 1629 } 1630 UPDATE_CODE_CACHE_PATCHES(); 1631 1632 PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1633 } 1634 1635 /* 1636 * Provide the final touch on the class object pointer pool to install the 1637 * actual pointers. The thread has to be in the running state. 1638 */ 1639 void dvmJitInstallClassObjectPointers(CompilationUnit *cUnit, char *codeAddress) 1640 { 1641 char *base = codeAddress - cUnit->headerSize; 1642 1643 /* Scan the class pointer pool */ 1644 JitTraceDescription *desc = getTraceDescriptionPointer(base); 1645 int descSize = getTraceDescriptionSize(desc); 1646 intptr_t *classPointerP = (int *) ((char *) desc + descSize); 1647 int numClassPointers = *(int *)classPointerP++; 1648 intptr_t *startClassPointerP = classPointerP; 1649 1650 /* 1651 * Change the thread state to VM_RUNNING so that GC won't be happening 1652 * when the assembler looks up the class pointers. May suspend the current 1653 * thread if there is a pending request before the state is actually 1654 * changed to RUNNING. 1655 */ 1656 dvmChangeStatus(gDvmJit.compilerThread, THREAD_RUNNING); 1657 1658 /* 1659 * Unprotecting the code cache will need to acquire the code cache 1660 * protection lock first. Doing so after the state change may increase the 1661 * time spent in the RUNNING state (which may delay the next GC request 1662 * should there be contention on codeCacheProtectionLock). In practice 1663 * this is probably not going to happen often since a GC is just served. 1664 * More importantly, acquiring the lock before the state change will 1665 * cause deadlock (b/4192964). 1666 */ 1667 UNPROTECT_CODE_CACHE(startClassPointerP, 1668 numClassPointers * sizeof(intptr_t)); 1669 #if defined(WITH_JIT_TUNING) 1670 u8 startTime = dvmGetRelativeTimeUsec(); 1671 #endif 1672 for (;numClassPointers; numClassPointers--) { 1673 CallsiteInfo *callsiteInfo = (CallsiteInfo *) *classPointerP; 1674 ClassObject *clazz = dvmFindClassNoInit( 1675 callsiteInfo->classDescriptor, callsiteInfo->classLoader); 1676 assert(!strcmp(clazz->descriptor, callsiteInfo->classDescriptor)); 1677 *classPointerP++ = (intptr_t) clazz; 1678 } 1679 1680 /* 1681 * Register the base address so that if GC kicks in after the thread state 1682 * has been changed to VMWAIT and before the compiled code is registered 1683 * in the JIT table, its content can be patched if class objects are 1684 * moved. 1685 */ 1686 gDvmJit.inflightBaseAddr = base; 1687 1688 #if defined(WITH_JIT_TUNING) 1689 u8 blockTime = dvmGetRelativeTimeUsec() - startTime; 1690 gDvmJit.compilerThreadBlockGCTime += blockTime; 1691 if (blockTime > gDvmJit.maxCompilerThreadBlockGCTime) 1692 gDvmJit.maxCompilerThreadBlockGCTime = blockTime; 1693 gDvmJit.numCompilerThreadBlockGC++; 1694 #endif 1695 UPDATE_CODE_CACHE_PATCHES(); 1696 1697 PROTECT_CODE_CACHE(startClassPointerP, numClassPointers * sizeof(intptr_t)); 1698 1699 /* Change the thread state back to VMWAIT */ 1700 dvmChangeStatus(gDvmJit.compilerThread, THREAD_VMWAIT); 1701 } 1702 1703 #if defined(WITH_SELF_VERIFICATION) 1704 /* 1705 * The following are used to keep compiled loads and stores from modifying 1706 * memory during self verification mode. 1707 * 1708 * Stores do not modify memory. Instead, the address and value pair are stored 1709 * into heapSpace. Addresses within heapSpace are unique. For accesses smaller 1710 * than a word, the word containing the address is loaded first before being 1711 * updated. 1712 * 1713 * Loads check heapSpace first and return data from there if an entry exists. 1714 * Otherwise, data is loaded from memory as usual. 1715 */ 1716 1717 /* Used to specify sizes of memory operations */ 1718 enum { 1719 kSVByte, 1720 kSVSignedByte, 1721 kSVHalfword, 1722 kSVSignedHalfword, 1723 kSVWord, 1724 kSVDoubleword, 1725 kSVVariable, 1726 }; 1727 1728 /* Load the value of a decoded register from the stack */ 1729 static int selfVerificationMemRegLoad(int* sp, int reg) 1730 { 1731 assert(0); /* MIPSTODO retarg func */ 1732 return *(sp + reg); 1733 } 1734 1735 /* Load the value of a decoded doubleword register from the stack */ 1736 static s8 selfVerificationMemRegLoadDouble(int* sp, int reg) 1737 { 1738 assert(0); /* MIPSTODO retarg func */ 1739 return *((s8*)(sp + reg)); 1740 } 1741 1742 /* Store the value of a decoded register out to the stack */ 1743 static void selfVerificationMemRegStore(int* sp, int data, int reg) 1744 { 1745 assert(0); /* MIPSTODO retarg func */ 1746 *(sp + reg) = data; 1747 } 1748 1749 /* Store the value of a decoded doubleword register out to the stack */ 1750 static void selfVerificationMemRegStoreDouble(int* sp, s8 data, int reg) 1751 { 1752 assert(0); /* MIPSTODO retarg func */ 1753 *((s8*)(sp + reg)) = data; 1754 } 1755 1756 /* 1757 * Load the specified size of data from the specified address, checking 1758 * heapSpace first if Self Verification mode wrote to it previously, and 1759 * falling back to actual memory otherwise. 1760 */ 1761 static int selfVerificationLoad(int addr, int size) 1762 { 1763 assert(0); /* MIPSTODO retarg func */ 1764 Thread *self = dvmThreadSelf(); 1765 ShadowSpace *shadowSpace = self->shadowSpace; 1766 ShadowHeap *heapSpacePtr; 1767 1768 int data; 1769 int maskedAddr = addr & 0xFFFFFFFC; 1770 int alignment = addr & 0x3; 1771 1772 for (heapSpacePtr = shadowSpace->heapSpace; 1773 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 1774 if (heapSpacePtr->addr == maskedAddr) { 1775 addr = ((unsigned int) &(heapSpacePtr->data)) | alignment; 1776 break; 1777 } 1778 } 1779 1780 switch (size) { 1781 case kSVByte: 1782 data = *((u1*) addr); 1783 break; 1784 case kSVSignedByte: 1785 data = *((s1*) addr); 1786 break; 1787 case kSVHalfword: 1788 data = *((u2*) addr); 1789 break; 1790 case kSVSignedHalfword: 1791 data = *((s2*) addr); 1792 break; 1793 case kSVWord: 1794 data = *((u4*) addr); 1795 break; 1796 default: 1797 ALOGE("*** ERROR: BAD SIZE IN selfVerificationLoad: %d", size); 1798 data = 0; 1799 dvmAbort(); 1800 } 1801 1802 //ALOGD("*** HEAP LOAD: Addr: %#x Data: %#x Size: %d", addr, data, size); 1803 return data; 1804 } 1805 1806 /* Like selfVerificationLoad, but specifically for doublewords */ 1807 static s8 selfVerificationLoadDoubleword(int addr) 1808 { 1809 assert(0); /* MIPSTODO retarg func */ 1810 Thread *self = dvmThreadSelf(); 1811 ShadowSpace* shadowSpace = self->shadowSpace; 1812 ShadowHeap* heapSpacePtr; 1813 1814 int addr2 = addr+4; 1815 unsigned int data = *((unsigned int*) addr); 1816 unsigned int data2 = *((unsigned int*) addr2); 1817 1818 for (heapSpacePtr = shadowSpace->heapSpace; 1819 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 1820 if (heapSpacePtr->addr == addr) { 1821 data = heapSpacePtr->data; 1822 } else if (heapSpacePtr->addr == addr2) { 1823 data2 = heapSpacePtr->data; 1824 } 1825 } 1826 1827 //ALOGD("*** HEAP LOAD DOUBLEWORD: Addr: %#x Data: %#x Data2: %#x", 1828 // addr, data, data2); 1829 return (((s8) data2) << 32) | data; 1830 } 1831 1832 /* 1833 * Handles a store of a specified size of data to a specified address. 1834 * This gets logged as an addr/data pair in heapSpace instead of modifying 1835 * memory. Addresses in heapSpace are unique, and accesses smaller than a 1836 * word pull the entire word from memory first before updating. 1837 */ 1838 static void selfVerificationStore(int addr, int data, int size) 1839 { 1840 assert(0); /* MIPSTODO retarg func */ 1841 Thread *self = dvmThreadSelf(); 1842 ShadowSpace *shadowSpace = self->shadowSpace; 1843 ShadowHeap *heapSpacePtr; 1844 1845 int maskedAddr = addr & 0xFFFFFFFC; 1846 int alignment = addr & 0x3; 1847 1848 //ALOGD("*** HEAP STORE: Addr: %#x Data: %#x Size: %d", addr, data, size); 1849 1850 for (heapSpacePtr = shadowSpace->heapSpace; 1851 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 1852 if (heapSpacePtr->addr == maskedAddr) break; 1853 } 1854 1855 if (heapSpacePtr == shadowSpace->heapSpaceTail) { 1856 heapSpacePtr->addr = maskedAddr; 1857 heapSpacePtr->data = *((unsigned int*) maskedAddr); 1858 shadowSpace->heapSpaceTail++; 1859 } 1860 1861 addr = ((unsigned int) &(heapSpacePtr->data)) | alignment; 1862 switch (size) { 1863 case kSVByte: 1864 *((u1*) addr) = data; 1865 break; 1866 case kSVSignedByte: 1867 *((s1*) addr) = data; 1868 break; 1869 case kSVHalfword: 1870 *((u2*) addr) = data; 1871 break; 1872 case kSVSignedHalfword: 1873 *((s2*) addr) = data; 1874 break; 1875 case kSVWord: 1876 *((u4*) addr) = data; 1877 break; 1878 default: 1879 ALOGE("*** ERROR: BAD SIZE IN selfVerificationSave: %d", size); 1880 dvmAbort(); 1881 } 1882 } 1883 1884 /* Like selfVerificationStore, but specifically for doublewords */ 1885 static void selfVerificationStoreDoubleword(int addr, s8 double_data) 1886 { 1887 assert(0); /* MIPSTODO retarg func */ 1888 Thread *self = dvmThreadSelf(); 1889 ShadowSpace *shadowSpace = self->shadowSpace; 1890 ShadowHeap *heapSpacePtr; 1891 1892 int addr2 = addr+4; 1893 int data = double_data; 1894 int data2 = double_data >> 32; 1895 bool store1 = false, store2 = false; 1896 1897 //ALOGD("*** HEAP STORE DOUBLEWORD: Addr: %#x Data: %#x, Data2: %#x", 1898 // addr, data, data2); 1899 1900 for (heapSpacePtr = shadowSpace->heapSpace; 1901 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 1902 if (heapSpacePtr->addr == addr) { 1903 heapSpacePtr->data = data; 1904 store1 = true; 1905 } else if (heapSpacePtr->addr == addr2) { 1906 heapSpacePtr->data = data2; 1907 store2 = true; 1908 } 1909 } 1910 1911 if (!store1) { 1912 shadowSpace->heapSpaceTail->addr = addr; 1913 shadowSpace->heapSpaceTail->data = data; 1914 shadowSpace->heapSpaceTail++; 1915 } 1916 if (!store2) { 1917 shadowSpace->heapSpaceTail->addr = addr2; 1918 shadowSpace->heapSpaceTail->data = data2; 1919 shadowSpace->heapSpaceTail++; 1920 } 1921 } 1922 1923 /* 1924 * Decodes the memory instruction at the address specified in the link 1925 * register. All registers (r0-r12,lr) and fp registers (d0-d15) are stored 1926 * consecutively on the stack beginning at the specified stack pointer. 1927 * Calls the proper Self Verification handler for the memory instruction and 1928 * updates the link register to point past the decoded memory instruction. 1929 */ 1930 void dvmSelfVerificationMemOpDecode(int lr, int* sp) 1931 { 1932 assert(0); /* MIPSTODO retarg func */ 1933 enum { 1934 kMemOpLdrPcRel = 0x09, // ldr(3) [01001] rd[10..8] imm_8[7..0] 1935 kMemOpRRR = 0x0A, // Full opcode is 7 bits 1936 kMemOp2Single = 0x0A, // Used for Vstrs and Vldrs 1937 kMemOpRRR2 = 0x0B, // Full opcode is 7 bits 1938 kMemOp2Double = 0x0B, // Used for Vstrd and Vldrd 1939 kMemOpStrRRI5 = 0x0C, // str(1) [01100] imm_5[10..6] rn[5..3] rd[2..0] 1940 kMemOpLdrRRI5 = 0x0D, // ldr(1) [01101] imm_5[10..6] rn[5..3] rd[2..0] 1941 kMemOpStrbRRI5 = 0x0E, // strb(1) [01110] imm_5[10..6] rn[5..3] rd[2..0] 1942 kMemOpLdrbRRI5 = 0x0F, // ldrb(1) [01111] imm_5[10..6] rn[5..3] rd[2..0] 1943 kMemOpStrhRRI5 = 0x10, // strh(1) [10000] imm_5[10..6] rn[5..3] rd[2..0] 1944 kMemOpLdrhRRI5 = 0x11, // ldrh(1) [10001] imm_5[10..6] rn[5..3] rd[2..0] 1945 kMemOpLdrSpRel = 0x13, // ldr(4) [10011] rd[10..8] imm_8[7..0] 1946 kMemOpStmia = 0x18, // stmia [11000] rn[10..8] reglist [7..0] 1947 kMemOpLdmia = 0x19, // ldmia [11001] rn[10..8] reglist [7..0] 1948 kMemOpStrRRR = 0x28, // str(2) [0101000] rm[8..6] rn[5..3] rd[2..0] 1949 kMemOpStrhRRR = 0x29, // strh(2) [0101001] rm[8..6] rn[5..3] rd[2..0] 1950 kMemOpStrbRRR = 0x2A, // strb(2) [0101010] rm[8..6] rn[5..3] rd[2..0] 1951 kMemOpLdrsbRRR = 0x2B, // ldrsb [0101011] rm[8..6] rn[5..3] rd[2..0] 1952 kMemOpLdrRRR = 0x2C, // ldr(2) [0101100] rm[8..6] rn[5..3] rd[2..0] 1953 kMemOpLdrhRRR = 0x2D, // ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0] 1954 kMemOpLdrbRRR = 0x2E, // ldrb(2) [0101110] rm[8..6] rn[5..3] rd[2..0] 1955 kMemOpLdrshRRR = 0x2F, // ldrsh [0101111] rm[8..6] rn[5..3] rd[2..0] 1956 kMemOp2Stmia = 0xE88, // stmia [111010001000[ rn[19..16] mask[15..0] 1957 kMemOp2Ldmia = 0xE89, // ldmia [111010001001[ rn[19..16] mask[15..0] 1958 kMemOp2Stmia2 = 0xE8A, // stmia [111010001010[ rn[19..16] mask[15..0] 1959 kMemOp2Ldmia2 = 0xE8B, // ldmia [111010001011[ rn[19..16] mask[15..0] 1960 kMemOp2Vstr = 0xED8, // Used for Vstrs and Vstrd 1961 kMemOp2Vldr = 0xED9, // Used for Vldrs and Vldrd 1962 kMemOp2Vstr2 = 0xEDC, // Used for Vstrs and Vstrd 1963 kMemOp2Vldr2 = 0xEDD, // Used for Vstrs and Vstrd 1964 kMemOp2StrbRRR = 0xF80, /* str rt,[rn,rm,LSL #imm] [111110000000] 1965 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1966 kMemOp2LdrbRRR = 0xF81, /* ldrb rt,[rn,rm,LSL #imm] [111110000001] 1967 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1968 kMemOp2StrhRRR = 0xF82, /* str rt,[rn,rm,LSL #imm] [111110000010] 1969 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1970 kMemOp2LdrhRRR = 0xF83, /* ldrh rt,[rn,rm,LSL #imm] [111110000011] 1971 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1972 kMemOp2StrRRR = 0xF84, /* str rt,[rn,rm,LSL #imm] [111110000100] 1973 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1974 kMemOp2LdrRRR = 0xF85, /* ldr rt,[rn,rm,LSL #imm] [111110000101] 1975 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1976 kMemOp2StrbRRI12 = 0xF88, /* strb rt,[rn,#imm12] [111110001000] 1977 rt[15..12] rn[19..16] imm12[11..0] */ 1978 kMemOp2LdrbRRI12 = 0xF89, /* ldrb rt,[rn,#imm12] [111110001001] 1979 rt[15..12] rn[19..16] imm12[11..0] */ 1980 kMemOp2StrhRRI12 = 0xF8A, /* strh rt,[rn,#imm12] [111110001010] 1981 rt[15..12] rn[19..16] imm12[11..0] */ 1982 kMemOp2LdrhRRI12 = 0xF8B, /* ldrh rt,[rn,#imm12] [111110001011] 1983 rt[15..12] rn[19..16] imm12[11..0] */ 1984 kMemOp2StrRRI12 = 0xF8C, /* str(Imm,T3) rd,[rn,#imm12] [111110001100] 1985 rn[19..16] rt[15..12] imm12[11..0] */ 1986 kMemOp2LdrRRI12 = 0xF8D, /* ldr(Imm,T3) rd,[rn,#imm12] [111110001101] 1987 rn[19..16] rt[15..12] imm12[11..0] */ 1988 kMemOp2LdrsbRRR = 0xF91, /* ldrsb rt,[rn,rm,LSL #imm] [111110010001] 1989 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1990 kMemOp2LdrshRRR = 0xF93, /* ldrsh rt,[rn,rm,LSL #imm] [111110010011] 1991 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 1992 kMemOp2LdrsbRRI12 = 0xF99, /* ldrsb rt,[rn,#imm12] [111110011001] 1993 rt[15..12] rn[19..16] imm12[11..0] */ 1994 kMemOp2LdrshRRI12 = 0xF9B, /* ldrsh rt,[rn,#imm12] [111110011011] 1995 rt[15..12] rn[19..16] imm12[11..0] */ 1996 kMemOp2 = 0xE000, // top 3 bits set indicates Thumb2 1997 }; 1998 1999 int addr, offset, data; 2000 long long double_data; 2001 int size = kSVWord; 2002 bool store = false; 2003 unsigned int *lr_masked = (unsigned int *) (lr & 0xFFFFFFFE); 2004 unsigned int insn = *lr_masked; 2005 2006 int old_lr; 2007 old_lr = selfVerificationMemRegLoad(sp, 13); 2008 2009 if ((insn & kMemOp2) == kMemOp2) { 2010 insn = (insn << 16) | (insn >> 16); 2011 //ALOGD("*** THUMB2 - Addr: %#x Insn: %#x", lr, insn); 2012 2013 int opcode12 = (insn >> 20) & 0xFFF; 2014 int opcode6 = (insn >> 6) & 0x3F; 2015 int opcode4 = (insn >> 8) & 0xF; 2016 int imm2 = (insn >> 4) & 0x3; 2017 int imm8 = insn & 0xFF; 2018 int imm12 = insn & 0xFFF; 2019 int rd = (insn >> 12) & 0xF; 2020 int rm = insn & 0xF; 2021 int rn = (insn >> 16) & 0xF; 2022 int rt = (insn >> 12) & 0xF; 2023 bool wBack = true; 2024 2025 // Update the link register 2026 selfVerificationMemRegStore(sp, old_lr+4, 13); 2027 2028 // Determine whether the mem op is a store or load 2029 switch (opcode12) { 2030 case kMemOp2Stmia: 2031 case kMemOp2Stmia2: 2032 case kMemOp2Vstr: 2033 case kMemOp2Vstr2: 2034 case kMemOp2StrbRRR: 2035 case kMemOp2StrhRRR: 2036 case kMemOp2StrRRR: 2037 case kMemOp2StrbRRI12: 2038 case kMemOp2StrhRRI12: 2039 case kMemOp2StrRRI12: 2040 store = true; 2041 } 2042 2043 // Determine the size of the mem access 2044 switch (opcode12) { 2045 case kMemOp2StrbRRR: 2046 case kMemOp2LdrbRRR: 2047 case kMemOp2StrbRRI12: 2048 case kMemOp2LdrbRRI12: 2049 size = kSVByte; 2050 break; 2051 case kMemOp2LdrsbRRR: 2052 case kMemOp2LdrsbRRI12: 2053 size = kSVSignedByte; 2054 break; 2055 case kMemOp2StrhRRR: 2056 case kMemOp2LdrhRRR: 2057 case kMemOp2StrhRRI12: 2058 case kMemOp2LdrhRRI12: 2059 size = kSVHalfword; 2060 break; 2061 case kMemOp2LdrshRRR: 2062 case kMemOp2LdrshRRI12: 2063 size = kSVSignedHalfword; 2064 break; 2065 case kMemOp2Vstr: 2066 case kMemOp2Vstr2: 2067 case kMemOp2Vldr: 2068 case kMemOp2Vldr2: 2069 if (opcode4 == kMemOp2Double) size = kSVDoubleword; 2070 break; 2071 case kMemOp2Stmia: 2072 case kMemOp2Ldmia: 2073 case kMemOp2Stmia2: 2074 case kMemOp2Ldmia2: 2075 size = kSVVariable; 2076 break; 2077 } 2078 2079 // Load the value of the address 2080 addr = selfVerificationMemRegLoad(sp, rn); 2081 2082 // Figure out the offset 2083 switch (opcode12) { 2084 case kMemOp2Vstr: 2085 case kMemOp2Vstr2: 2086 case kMemOp2Vldr: 2087 case kMemOp2Vldr2: 2088 offset = imm8 << 2; 2089 if (opcode4 == kMemOp2Single) { 2090 rt = rd << 1; 2091 if (insn & 0x400000) rt |= 0x1; 2092 } else if (opcode4 == kMemOp2Double) { 2093 if (insn & 0x400000) rt |= 0x10; 2094 rt = rt << 1; 2095 } else { 2096 ALOGE("*** ERROR: UNRECOGNIZED VECTOR MEM OP: %x", opcode4); 2097 dvmAbort(); 2098 } 2099 rt += 14; 2100 break; 2101 case kMemOp2StrbRRR: 2102 case kMemOp2LdrbRRR: 2103 case kMemOp2StrhRRR: 2104 case kMemOp2LdrhRRR: 2105 case kMemOp2StrRRR: 2106 case kMemOp2LdrRRR: 2107 case kMemOp2LdrsbRRR: 2108 case kMemOp2LdrshRRR: 2109 offset = selfVerificationMemRegLoad(sp, rm) << imm2; 2110 break; 2111 case kMemOp2StrbRRI12: 2112 case kMemOp2LdrbRRI12: 2113 case kMemOp2StrhRRI12: 2114 case kMemOp2LdrhRRI12: 2115 case kMemOp2StrRRI12: 2116 case kMemOp2LdrRRI12: 2117 case kMemOp2LdrsbRRI12: 2118 case kMemOp2LdrshRRI12: 2119 offset = imm12; 2120 break; 2121 case kMemOp2Stmia: 2122 case kMemOp2Ldmia: 2123 wBack = false; 2124 case kMemOp2Stmia2: 2125 case kMemOp2Ldmia2: 2126 offset = 0; 2127 break; 2128 default: 2129 ALOGE("*** ERROR: UNRECOGNIZED THUMB2 MEM OP: %x", opcode12); 2130 offset = 0; 2131 dvmAbort(); 2132 } 2133 2134 // Handle the decoded mem op accordingly 2135 if (store) { 2136 if (size == kSVVariable) { 2137 ALOGD("*** THUMB2 STMIA CURRENTLY UNUSED (AND UNTESTED)"); 2138 int i; 2139 int regList = insn & 0xFFFF; 2140 for (i = 0; i < 16; i++) { 2141 if (regList & 0x1) { 2142 data = selfVerificationMemRegLoad(sp, i); 2143 selfVerificationStore(addr, data, kSVWord); 2144 addr += 4; 2145 } 2146 regList = regList >> 1; 2147 } 2148 if (wBack) selfVerificationMemRegStore(sp, addr, rn); 2149 } else if (size == kSVDoubleword) { 2150 double_data = selfVerificationMemRegLoadDouble(sp, rt); 2151 selfVerificationStoreDoubleword(addr+offset, double_data); 2152 } else { 2153 data = selfVerificationMemRegLoad(sp, rt); 2154 selfVerificationStore(addr+offset, data, size); 2155 } 2156 } else { 2157 if (size == kSVVariable) { 2158 ALOGD("*** THUMB2 LDMIA CURRENTLY UNUSED (AND UNTESTED)"); 2159 int i; 2160 int regList = insn & 0xFFFF; 2161 for (i = 0; i < 16; i++) { 2162 if (regList & 0x1) { 2163 data = selfVerificationLoad(addr, kSVWord); 2164 selfVerificationMemRegStore(sp, data, i); 2165 addr += 4; 2166 } 2167 regList = regList >> 1; 2168 } 2169 if (wBack) selfVerificationMemRegStore(sp, addr, rn); 2170 } else if (size == kSVDoubleword) { 2171 double_data = selfVerificationLoadDoubleword(addr+offset); 2172 selfVerificationMemRegStoreDouble(sp, double_data, rt); 2173 } else { 2174 data = selfVerificationLoad(addr+offset, size); 2175 selfVerificationMemRegStore(sp, data, rt); 2176 } 2177 } 2178 } else { 2179 //ALOGD("*** THUMB - Addr: %#x Insn: %#x", lr, insn); 2180 2181 // Update the link register 2182 selfVerificationMemRegStore(sp, old_lr+2, 13); 2183 2184 int opcode5 = (insn >> 11) & 0x1F; 2185 int opcode7 = (insn >> 9) & 0x7F; 2186 int imm = (insn >> 6) & 0x1F; 2187 int rd = (insn >> 8) & 0x7; 2188 int rm = (insn >> 6) & 0x7; 2189 int rn = (insn >> 3) & 0x7; 2190 int rt = insn & 0x7; 2191 2192 // Determine whether the mem op is a store or load 2193 switch (opcode5) { 2194 case kMemOpRRR: 2195 switch (opcode7) { 2196 case kMemOpStrRRR: 2197 case kMemOpStrhRRR: 2198 case kMemOpStrbRRR: 2199 store = true; 2200 } 2201 break; 2202 case kMemOpStrRRI5: 2203 case kMemOpStrbRRI5: 2204 case kMemOpStrhRRI5: 2205 case kMemOpStmia: 2206 store = true; 2207 } 2208 2209 // Determine the size of the mem access 2210 switch (opcode5) { 2211 case kMemOpRRR: 2212 case kMemOpRRR2: 2213 switch (opcode7) { 2214 case kMemOpStrbRRR: 2215 case kMemOpLdrbRRR: 2216 size = kSVByte; 2217 break; 2218 case kMemOpLdrsbRRR: 2219 size = kSVSignedByte; 2220 break; 2221 case kMemOpStrhRRR: 2222 case kMemOpLdrhRRR: 2223 size = kSVHalfword; 2224 break; 2225 case kMemOpLdrshRRR: 2226 size = kSVSignedHalfword; 2227 break; 2228 } 2229 break; 2230 case kMemOpStrbRRI5: 2231 case kMemOpLdrbRRI5: 2232 size = kSVByte; 2233 break; 2234 case kMemOpStrhRRI5: 2235 case kMemOpLdrhRRI5: 2236 size = kSVHalfword; 2237 break; 2238 case kMemOpStmia: 2239 case kMemOpLdmia: 2240 size = kSVVariable; 2241 break; 2242 } 2243 2244 // Load the value of the address 2245 if (opcode5 == kMemOpLdrPcRel) 2246 addr = selfVerificationMemRegLoad(sp, 4); 2247 else if (opcode5 == kMemOpStmia || opcode5 == kMemOpLdmia) 2248 addr = selfVerificationMemRegLoad(sp, rd); 2249 else 2250 addr = selfVerificationMemRegLoad(sp, rn); 2251 2252 // Figure out the offset 2253 switch (opcode5) { 2254 case kMemOpLdrPcRel: 2255 offset = (insn & 0xFF) << 2; 2256 rt = rd; 2257 break; 2258 case kMemOpRRR: 2259 case kMemOpRRR2: 2260 offset = selfVerificationMemRegLoad(sp, rm); 2261 break; 2262 case kMemOpStrRRI5: 2263 case kMemOpLdrRRI5: 2264 offset = imm << 2; 2265 break; 2266 case kMemOpStrhRRI5: 2267 case kMemOpLdrhRRI5: 2268 offset = imm << 1; 2269 break; 2270 case kMemOpStrbRRI5: 2271 case kMemOpLdrbRRI5: 2272 offset = imm; 2273 break; 2274 case kMemOpStmia: 2275 case kMemOpLdmia: 2276 offset = 0; 2277 break; 2278 default: 2279 ALOGE("*** ERROR: UNRECOGNIZED THUMB MEM OP: %x", opcode5); 2280 offset = 0; 2281 dvmAbort(); 2282 } 2283 2284 // Handle the decoded mem op accordingly 2285 if (store) { 2286 if (size == kSVVariable) { 2287 int i; 2288 int regList = insn & 0xFF; 2289 for (i = 0; i < 8; i++) { 2290 if (regList & 0x1) { 2291 data = selfVerificationMemRegLoad(sp, i); 2292 selfVerificationStore(addr, data, kSVWord); 2293 addr += 4; 2294 } 2295 regList = regList >> 1; 2296 } 2297 selfVerificationMemRegStore(sp, addr, rd); 2298 } else { 2299 data = selfVerificationMemRegLoad(sp, rt); 2300 selfVerificationStore(addr+offset, data, size); 2301 } 2302 } else { 2303 if (size == kSVVariable) { 2304 bool wBack = true; 2305 int i; 2306 int regList = insn & 0xFF; 2307 for (i = 0; i < 8; i++) { 2308 if (regList & 0x1) { 2309 if (i == rd) wBack = false; 2310 data = selfVerificationLoad(addr, kSVWord); 2311 selfVerificationMemRegStore(sp, data, i); 2312 addr += 4; 2313 } 2314 regList = regList >> 1; 2315 } 2316 if (wBack) selfVerificationMemRegStore(sp, addr, rd); 2317 } else { 2318 data = selfVerificationLoad(addr+offset, size); 2319 selfVerificationMemRegStore(sp, data, rt); 2320 } 2321 } 2322 } 2323 } 2324 #endif 2325