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 "ArmLIR.h" 22 #include "Codegen.h" 23 #include <sys/mman.h> /* for protection change */ 24 25 #define MAX_ASSEMBLER_RETRIES 10 26 27 /* 28 * opcode: ArmOpcode enum 29 * skeleton: pre-designated bit-pattern for this opcode 30 * k0: key to applying ds/de 31 * ds: dest start bit position 32 * de: dest end bit position 33 * k1: key to applying s1s/s1e 34 * s1s: src1 start bit position 35 * s1e: src1 end bit position 36 * k2: key to applying s2s/s2e 37 * s2s: src2 start bit position 38 * s2e: src2 end bit position 39 * operands: number of operands (for sanity check purposes) 40 * name: mnemonic name 41 * fmt: for pretty-printing 42 */ 43 #define ENCODING_MAP(opcode, skeleton, k0, ds, de, k1, s1s, s1e, k2, s2s, s2e, \ 44 k3, k3s, k3e, flags, name, fmt, size) \ 45 {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \ 46 {k3, k3s, k3e}}, opcode, flags, name, fmt, size} 47 48 /* Instruction dump string format keys: !pf, where "!" is the start 49 * of the key, "p" is which numeric operand to use and "f" is the 50 * print format. 51 * 52 * [p]ositions: 53 * 0 -> operands[0] (dest) 54 * 1 -> operands[1] (src1) 55 * 2 -> operands[2] (src2) 56 * 3 -> operands[3] (extra) 57 * 58 * [f]ormats: 59 * h -> 4-digit hex 60 * d -> decimal 61 * E -> decimal*4 62 * F -> decimal*2 63 * c -> branch condition (beq, bne, etc.) 64 * t -> pc-relative target 65 * u -> 1st half of bl[x] target 66 * v -> 2nd half ob bl[x] target 67 * R -> register list 68 * s -> single precision floating point register 69 * S -> double precision floating point register 70 * m -> Thumb2 modified immediate 71 * n -> complimented Thumb2 modified immediate 72 * M -> Thumb2 16-bit zero-extended immediate 73 * b -> 4-digit binary 74 * B -> dmb option string (sy, st, ish, ishst, nsh, hshst) 75 * H -> operand shift 76 * 77 * [!] escape. To insert "!", use "!!" 78 */ 79 /* NOTE: must be kept in sync with enum ArmOpcode from ArmLIR.h */ 80 ArmEncodingMap EncodingMap[kArmLast] = { 81 ENCODING_MAP(kArm16BitData, 0x0000, 82 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 83 kFmtUnused, -1, -1, IS_UNARY_OP, "data", "0x!0h(!0d)", 1), 84 ENCODING_MAP(kThumbAdcRR, 0x4140, 85 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 86 kFmtUnused, -1, -1, 87 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES | USES_CCODES, 88 "adcs", "r!0d, r!1d", 1), 89 ENCODING_MAP(kThumbAddRRI3, 0x1c00, 90 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 91 kFmtUnused, -1, -1, 92 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, 93 "adds", "r!0d, r!1d, #!2d", 1), 94 ENCODING_MAP(kThumbAddRI8, 0x3000, 95 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, 96 kFmtUnused, -1, -1, 97 IS_BINARY_OP | REG_DEF0_USE0 | SETS_CCODES, 98 "adds", "r!0d, r!0d, #!1d", 1), 99 ENCODING_MAP(kThumbAddRRR, 0x1800, 100 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 101 kFmtUnused, -1, -1, 102 IS_TERTIARY_OP | REG_DEF0_USE12 | SETS_CCODES, 103 "adds", "r!0d, r!1d, r!2d", 1), 104 ENCODING_MAP(kThumbAddRRLH, 0x4440, 105 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 106 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE01, 107 "add", "r!0d, r!1d", 1), 108 ENCODING_MAP(kThumbAddRRHL, 0x4480, 109 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 110 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE01, 111 "add", "r!0d, r!1d", 1), 112 ENCODING_MAP(kThumbAddRRHH, 0x44c0, 113 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 114 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE01, 115 "add", "r!0d, r!1d", 1), 116 ENCODING_MAP(kThumbAddPcRel, 0xa000, 117 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, 118 kFmtUnused, -1, -1, IS_TERTIARY_OP | IS_BRANCH, 119 "add", "r!0d, pc, #!1E", 1), 120 ENCODING_MAP(kThumbAddSpRel, 0xa800, 121 kFmtBitBlt, 10, 8, kFmtUnused, -1, -1, kFmtBitBlt, 7, 0, 122 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF_SP | REG_USE_SP, 123 "add", "r!0d, sp, #!2E", 1), 124 ENCODING_MAP(kThumbAddSpI7, 0xb000, 125 kFmtBitBlt, 6, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 126 kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF_SP | REG_USE_SP, 127 "add", "sp, #!0d*4", 1), 128 ENCODING_MAP(kThumbAndRR, 0x4000, 129 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 130 kFmtUnused, -1, -1, 131 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES, 132 "ands", "r!0d, r!1d", 1), 133 ENCODING_MAP(kThumbAsrRRI5, 0x1000, 134 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6, 135 kFmtUnused, -1, -1, 136 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, 137 "asrs", "r!0d, r!1d, #!2d", 1), 138 ENCODING_MAP(kThumbAsrRR, 0x4100, 139 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 140 kFmtUnused, -1, -1, 141 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES, 142 "asrs", "r!0d, r!1d", 1), 143 ENCODING_MAP(kThumbBCond, 0xd000, 144 kFmtBitBlt, 7, 0, kFmtBitBlt, 11, 8, kFmtUnused, -1, -1, 145 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | USES_CCODES, 146 "b!1c", "!0t", 1), 147 ENCODING_MAP(kThumbBUncond, 0xe000, 148 kFmtBitBlt, 10, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 149 kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH, 150 "b", "!0t", 1), 151 ENCODING_MAP(kThumbBicRR, 0x4380, 152 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 153 kFmtUnused, -1, -1, 154 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES, 155 "bics", "r!0d, r!1d", 1), 156 ENCODING_MAP(kThumbBkpt, 0xbe00, 157 kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 158 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH, 159 "bkpt", "!0d", 1), 160 ENCODING_MAP(kThumbBlx1, 0xf000, 161 kFmtBitBlt, 10, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 162 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_DEF_LR, 163 "blx_1", "!0u", 1), 164 ENCODING_MAP(kThumbBlx2, 0xe800, 165 kFmtBitBlt, 10, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 166 kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_DEF_LR, 167 "blx_2", "!0v", 1), 168 ENCODING_MAP(kThumbBl1, 0xf000, 169 kFmtBitBlt, 10, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 170 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR, 171 "bl_1", "!0u", 1), 172 ENCODING_MAP(kThumbBl2, 0xf800, 173 kFmtBitBlt, 10, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 174 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_DEF_LR, 175 "bl_2", "!0v", 1), 176 ENCODING_MAP(kThumbBlxR, 0x4780, 177 kFmtBitBlt, 6, 3, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 178 kFmtUnused, -1, -1, 179 IS_UNARY_OP | REG_USE0 | IS_BRANCH | REG_DEF_LR, 180 "blx", "r!0d", 1), 181 ENCODING_MAP(kThumbBx, 0x4700, 182 kFmtBitBlt, 6, 3, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 183 kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH, 184 "bx", "r!0d", 1), 185 ENCODING_MAP(kThumbCmnRR, 0x42c0, 186 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 187 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01 | SETS_CCODES, 188 "cmn", "r!0d, r!1d", 1), 189 ENCODING_MAP(kThumbCmpRI8, 0x2800, 190 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, 191 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | SETS_CCODES, 192 "cmp", "r!0d, #!1d", 1), 193 ENCODING_MAP(kThumbCmpRR, 0x4280, 194 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 195 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01 | SETS_CCODES, 196 "cmp", "r!0d, r!1d", 1), 197 ENCODING_MAP(kThumbCmpLH, 0x4540, 198 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 199 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01 | SETS_CCODES, 200 "cmp", "r!0d, r!1d", 1), 201 ENCODING_MAP(kThumbCmpHL, 0x4580, 202 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 203 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01 | SETS_CCODES, 204 "cmp", "r!0d, r!1d", 1), 205 ENCODING_MAP(kThumbCmpHH, 0x45c0, 206 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 207 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01 | SETS_CCODES, 208 "cmp", "r!0d, r!1d", 1), 209 ENCODING_MAP(kThumbEorRR, 0x4040, 210 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 211 kFmtUnused, -1, -1, 212 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES, 213 "eors", "r!0d, r!1d", 1), 214 ENCODING_MAP(kThumbLdmia, 0xc800, 215 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, 216 kFmtUnused, -1, -1, 217 IS_BINARY_OP | REG_DEF0_USE0 | REG_DEF_LIST1 | IS_LOAD, 218 "ldmia", "r!0d!!, <!1R>", 1), 219 ENCODING_MAP(kThumbLdrRRI5, 0x6800, 220 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6, 221 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 222 "ldr", "r!0d, [r!1d, #!2E]", 1), 223 ENCODING_MAP(kThumbLdrRRR, 0x5800, 224 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 225 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12 | IS_LOAD, 226 "ldr", "r!0d, [r!1d, r!2d]", 1), 227 ENCODING_MAP(kThumbLdrPcRel, 0x4800, 228 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, 229 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0 | REG_USE_PC 230 | IS_LOAD, "ldr", "r!0d, [pc, #!1E]", 1), 231 ENCODING_MAP(kThumbLdrSpRel, 0x9800, 232 kFmtBitBlt, 10, 8, kFmtUnused, -1, -1, kFmtBitBlt, 7, 0, 233 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0 | REG_USE_SP 234 | IS_LOAD, "ldr", "r!0d, [sp, #!2E]", 1), 235 ENCODING_MAP(kThumbLdrbRRI5, 0x7800, 236 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6, 237 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 238 "ldrb", "r!0d, [r!1d, #2d]", 1), 239 ENCODING_MAP(kThumbLdrbRRR, 0x5c00, 240 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 241 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12 | IS_LOAD, 242 "ldrb", "r!0d, [r!1d, r!2d]", 1), 243 ENCODING_MAP(kThumbLdrhRRI5, 0x8800, 244 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6, 245 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 246 "ldrh", "r!0d, [r!1d, #!2F]", 1), 247 ENCODING_MAP(kThumbLdrhRRR, 0x5a00, 248 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 249 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12 | IS_LOAD, 250 "ldrh", "r!0d, [r!1d, r!2d]", 1), 251 ENCODING_MAP(kThumbLdrsbRRR, 0x5600, 252 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 253 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12 | IS_LOAD, 254 "ldrsb", "r!0d, [r!1d, r!2d]", 1), 255 ENCODING_MAP(kThumbLdrshRRR, 0x5e00, 256 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 257 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12 | IS_LOAD, 258 "ldrsh", "r!0d, [r!1d, r!2d]", 1), 259 ENCODING_MAP(kThumbLslRRI5, 0x0000, 260 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6, 261 kFmtUnused, -1, -1, 262 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, 263 "lsls", "r!0d, r!1d, #!2d", 1), 264 ENCODING_MAP(kThumbLslRR, 0x4080, 265 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 266 kFmtUnused, -1, -1, 267 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES, 268 "lsls", "r!0d, r!1d", 1), 269 ENCODING_MAP(kThumbLsrRRI5, 0x0800, 270 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6, 271 kFmtUnused, -1, -1, 272 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, 273 "lsrs", "r!0d, r!1d, #!2d", 1), 274 ENCODING_MAP(kThumbLsrRR, 0x40c0, 275 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 276 kFmtUnused, -1, -1, 277 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES, 278 "lsrs", "r!0d, r!1d", 1), 279 ENCODING_MAP(kThumbMovImm, 0x2000, 280 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, 281 kFmtUnused, -1, -1, 282 IS_BINARY_OP | REG_DEF0 | SETS_CCODES, 283 "movs", "r!0d, #!1d", 1), 284 ENCODING_MAP(kThumbMovRR, 0x1c00, 285 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 286 kFmtUnused, -1, -1, 287 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES, 288 "movs", "r!0d, r!1d", 1), 289 ENCODING_MAP(kThumbMovRR_H2H, 0x46c0, 290 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 291 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 292 "mov", "r!0d, r!1d", 1), 293 ENCODING_MAP(kThumbMovRR_H2L, 0x4640, 294 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 295 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 296 "mov", "r!0d, r!1d", 1), 297 ENCODING_MAP(kThumbMovRR_L2H, 0x4680, 298 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 299 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 300 "mov", "r!0d, r!1d", 1), 301 ENCODING_MAP(kThumbMul, 0x4340, 302 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 303 kFmtUnused, -1, -1, 304 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES, 305 "muls", "r!0d, r!1d", 1), 306 ENCODING_MAP(kThumbMvn, 0x43c0, 307 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 308 kFmtUnused, -1, -1, 309 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES, 310 "mvns", "r!0d, r!1d", 1), 311 ENCODING_MAP(kThumbNeg, 0x4240, 312 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 313 kFmtUnused, -1, -1, 314 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES, 315 "negs", "r!0d, r!1d", 1), 316 ENCODING_MAP(kThumbOrr, 0x4300, 317 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 318 kFmtUnused, -1, -1, 319 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES, 320 "orrs", "r!0d, r!1d", 1), 321 ENCODING_MAP(kThumbPop, 0xbc00, 322 kFmtBitBlt, 8, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 323 kFmtUnused, -1, -1, 324 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0 325 | IS_LOAD, "pop", "<!0R>", 1), 326 ENCODING_MAP(kThumbPush, 0xb400, 327 kFmtBitBlt, 8, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 328 kFmtUnused, -1, -1, 329 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE_LIST0 330 | IS_STORE, "push", "<!0R>", 1), 331 ENCODING_MAP(kThumbRorRR, 0x41c0, 332 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 333 kFmtUnused, -1, -1, 334 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES, 335 "rors", "r!0d, r!1d", 1), 336 ENCODING_MAP(kThumbSbc, 0x4180, 337 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 338 kFmtUnused, -1, -1, 339 IS_BINARY_OP | REG_DEF0_USE01 | USES_CCODES | SETS_CCODES, 340 "sbcs", "r!0d, r!1d", 1), 341 ENCODING_MAP(kThumbStmia, 0xc000, 342 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, 343 kFmtUnused, -1, -1, 344 IS_BINARY_OP | REG_DEF0 | REG_USE0 | REG_USE_LIST1 | IS_STORE, 345 "stmia", "r!0d!!, <!1R>", 1), 346 ENCODING_MAP(kThumbStrRRI5, 0x6000, 347 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6, 348 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE, 349 "str", "r!0d, [r!1d, #!2E]", 1), 350 ENCODING_MAP(kThumbStrRRR, 0x5000, 351 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 352 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE012 | IS_STORE, 353 "str", "r!0d, [r!1d, r!2d]", 1), 354 ENCODING_MAP(kThumbStrSpRel, 0x9000, 355 kFmtBitBlt, 10, 8, kFmtUnused, -1, -1, kFmtBitBlt, 7, 0, 356 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE0 | REG_USE_SP 357 | IS_STORE, "str", "r!0d, [sp, #!2E]", 1), 358 ENCODING_MAP(kThumbStrbRRI5, 0x7000, 359 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6, 360 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE, 361 "strb", "r!0d, [r!1d, #!2d]", 1), 362 ENCODING_MAP(kThumbStrbRRR, 0x5400, 363 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 364 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE012 | IS_STORE, 365 "strb", "r!0d, [r!1d, r!2d]", 1), 366 ENCODING_MAP(kThumbStrhRRI5, 0x8000, 367 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 10, 6, 368 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE, 369 "strh", "r!0d, [r!1d, #!2F]", 1), 370 ENCODING_MAP(kThumbStrhRRR, 0x5200, 371 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 372 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE012 | IS_STORE, 373 "strh", "r!0d, [r!1d, r!2d]", 1), 374 ENCODING_MAP(kThumbSubRRI3, 0x1e00, 375 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 376 kFmtUnused, -1, -1, 377 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, 378 "subs", "r!0d, r!1d, #!2d]", 1), 379 ENCODING_MAP(kThumbSubRI8, 0x3800, 380 kFmtBitBlt, 10, 8, kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, 381 kFmtUnused, -1, -1, 382 IS_BINARY_OP | REG_DEF0_USE0 | SETS_CCODES, 383 "subs", "r!0d, #!1d", 1), 384 ENCODING_MAP(kThumbSubRRR, 0x1a00, 385 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtBitBlt, 8, 6, 386 kFmtUnused, -1, -1, 387 IS_TERTIARY_OP | REG_DEF0_USE12 | SETS_CCODES, 388 "subs", "r!0d, r!1d, r!2d", 1), 389 ENCODING_MAP(kThumbSubSpI7, 0xb080, 390 kFmtBitBlt, 6, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 391 kFmtUnused, -1, -1, 392 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP, 393 "sub", "sp, #!0d", 1), 394 ENCODING_MAP(kThumbSwi, 0xdf00, 395 kFmtBitBlt, 7, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH, 396 "swi", "!0d", 1), 397 ENCODING_MAP(kThumbTst, 0x4200, 398 kFmtBitBlt, 2, 0, kFmtBitBlt, 5, 3, kFmtUnused, -1, -1, 399 kFmtUnused, -1, -1, IS_UNARY_OP | REG_USE01 | SETS_CCODES, 400 "tst", "r!0d, r!1d", 1), 401 ENCODING_MAP(kThumb2Vldrs, 0xed900a00, 402 kFmtSfp, 22, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0, 403 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 404 "vldr", "!0s, [r!1d, #!2E]", 2), 405 ENCODING_MAP(kThumb2Vldrd, 0xed900b00, 406 kFmtDfp, 22, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0, 407 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 408 "vldr", "!0S, [r!1d, #!2E]", 2), 409 ENCODING_MAP(kThumb2Vmuls, 0xee200a00, 410 kFmtSfp, 22, 12, kFmtSfp, 7, 16, kFmtSfp, 5, 0, 411 kFmtUnused, -1, -1, 412 IS_TERTIARY_OP | REG_DEF0_USE12, 413 "vmuls", "!0s, !1s, !2s", 2), 414 ENCODING_MAP(kThumb2Vmuld, 0xee200b00, 415 kFmtDfp, 22, 12, kFmtDfp, 7, 16, kFmtDfp, 5, 0, 416 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 417 "vmuld", "!0S, !1S, !2S", 2), 418 ENCODING_MAP(kThumb2Vstrs, 0xed800a00, 419 kFmtSfp, 22, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0, 420 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE, 421 "vstr", "!0s, [r!1d, #!2E]", 2), 422 ENCODING_MAP(kThumb2Vstrd, 0xed800b00, 423 kFmtDfp, 22, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0, 424 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE, 425 "vstr", "!0S, [r!1d, #!2E]", 2), 426 ENCODING_MAP(kThumb2Vsubs, 0xee300a40, 427 kFmtSfp, 22, 12, kFmtSfp, 7, 16, kFmtSfp, 5, 0, 428 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 429 "vsub", "!0s, !1s, !2s", 2), 430 ENCODING_MAP(kThumb2Vsubd, 0xee300b40, 431 kFmtDfp, 22, 12, kFmtDfp, 7, 16, kFmtDfp, 5, 0, 432 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 433 "vsub", "!0S, !1S, !2S", 2), 434 ENCODING_MAP(kThumb2Vadds, 0xee300a00, 435 kFmtSfp, 22, 12, kFmtSfp, 7, 16, kFmtSfp, 5, 0, 436 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 437 "vadd", "!0s, !1s, !2s", 2), 438 ENCODING_MAP(kThumb2Vaddd, 0xee300b00, 439 kFmtDfp, 22, 12, kFmtDfp, 7, 16, kFmtDfp, 5, 0, 440 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 441 "vadd", "!0S, !1S, !2S", 2), 442 ENCODING_MAP(kThumb2Vdivs, 0xee800a00, 443 kFmtSfp, 22, 12, kFmtSfp, 7, 16, kFmtSfp, 5, 0, 444 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 445 "vdivs", "!0s, !1s, !2s", 2), 446 ENCODING_MAP(kThumb2Vdivd, 0xee800b00, 447 kFmtDfp, 22, 12, kFmtDfp, 7, 16, kFmtDfp, 5, 0, 448 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 449 "vdivd", "!0S, !1S, !2S", 2), 450 ENCODING_MAP(kThumb2VcvtIF, 0xeeb80ac0, 451 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1, 452 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 453 "vcvt.f32", "!0s, !1s", 2), 454 ENCODING_MAP(kThumb2VcvtID, 0xeeb80bc0, 455 kFmtDfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1, 456 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 457 "vcvt.f64", "!0S, !1s", 2), 458 ENCODING_MAP(kThumb2VcvtFI, 0xeebd0ac0, 459 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1, 460 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 461 "vcvt.s32.f32 ", "!0s, !1s", 2), 462 ENCODING_MAP(kThumb2VcvtDI, 0xeebd0bc0, 463 kFmtSfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1, 464 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 465 "vcvt.s32.f64 ", "!0s, !1S", 2), 466 ENCODING_MAP(kThumb2VcvtFd, 0xeeb70ac0, 467 kFmtDfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1, 468 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 469 "vcvt.f64.f32 ", "!0S, !1s", 2), 470 ENCODING_MAP(kThumb2VcvtDF, 0xeeb70bc0, 471 kFmtSfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1, 472 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 473 "vcvt.f32.f64 ", "!0s, !1S", 2), 474 ENCODING_MAP(kThumb2Vsqrts, 0xeeb10ac0, 475 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1, 476 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 477 "vsqrt.f32 ", "!0s, !1s", 2), 478 ENCODING_MAP(kThumb2Vsqrtd, 0xeeb10bc0, 479 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1, 480 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 481 "vsqrt.f64 ", "!0S, !1S", 2), 482 ENCODING_MAP(kThumb2MovImmShift, 0xf04f0000, /* no setflags encoding */ 483 kFmtBitBlt, 11, 8, kFmtModImm, -1, -1, kFmtUnused, -1, -1, 484 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0, 485 "mov", "r!0d, #!1m", 2), 486 ENCODING_MAP(kThumb2MovImm16, 0xf2400000, 487 kFmtBitBlt, 11, 8, kFmtImm16, -1, -1, kFmtUnused, -1, -1, 488 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0, 489 "mov", "r!0d, #!1M", 2), 490 ENCODING_MAP(kThumb2StrRRI12, 0xf8c00000, 491 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0, 492 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE, 493 "str", "r!0d, [r!1d, #!2d]", 2), 494 ENCODING_MAP(kThumb2LdrRRI12, 0xf8d00000, 495 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0, 496 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 497 "ldr", "r!0d, [r!1d, #!2d]", 2), 498 ENCODING_MAP(kThumb2StrRRI8Predec, 0xf8400c00, 499 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 8, 0, 500 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE, 501 "str", "r!0d, [r!1d, #-!2d]", 2), 502 ENCODING_MAP(kThumb2LdrRRI8Predec, 0xf8500c00, 503 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 8, 0, 504 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 505 "ldr", "r!0d, [r!1d, #-!2d]", 2), 506 ENCODING_MAP(kThumb2Cbnz, 0xb900, /* Note: does not affect flags */ 507 kFmtBitBlt, 2, 0, kFmtImm6, -1, -1, kFmtUnused, -1, -1, 508 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | IS_BRANCH, 509 "cbnz", "r!0d,!1t", 1), 510 ENCODING_MAP(kThumb2Cbz, 0xb100, /* Note: does not affect flags */ 511 kFmtBitBlt, 2, 0, kFmtImm6, -1, -1, kFmtUnused, -1, -1, 512 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | IS_BRANCH, 513 "cbz", "r!0d,!1t", 1), 514 ENCODING_MAP(kThumb2AddRRI12, 0xf2000000, 515 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtImm12, -1, -1, 516 kFmtUnused, -1, -1, 517 IS_TERTIARY_OP | REG_DEF0_USE1,/* Note: doesn't affect flags */ 518 "add", "r!0d,r!1d,#!2d", 2), 519 ENCODING_MAP(kThumb2MovRR, 0xea4f0000, /* no setflags encoding */ 520 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtUnused, -1, -1, 521 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 522 "mov", "r!0d, r!1d", 2), 523 ENCODING_MAP(kThumb2Vmovs, 0xeeb00a40, 524 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1, 525 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 526 "vmov.f32 ", " !0s, !1s", 2), 527 ENCODING_MAP(kThumb2Vmovd, 0xeeb00b40, 528 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1, 529 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 530 "vmov.f64 ", " !0S, !1S", 2), 531 ENCODING_MAP(kThumb2Ldmia, 0xe8900000, 532 kFmtBitBlt, 19, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 533 kFmtUnused, -1, -1, 534 IS_BINARY_OP | REG_DEF0_USE0 | REG_DEF_LIST1 | IS_LOAD, 535 "ldmia", "r!0d!!, <!1R>", 2), 536 ENCODING_MAP(kThumb2Stmia, 0xe8800000, 537 kFmtBitBlt, 19, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, 538 kFmtUnused, -1, -1, 539 IS_BINARY_OP | REG_DEF0_USE0 | REG_USE_LIST1 | IS_STORE, 540 "stmia", "r!0d!!, <!1R>", 2), 541 ENCODING_MAP(kThumb2AddRRR, 0xeb100000, /* setflags encoding */ 542 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 543 kFmtShift, -1, -1, 544 IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES, 545 "adds", "r!0d, r!1d, r!2d!3H", 2), 546 ENCODING_MAP(kThumb2SubRRR, 0xebb00000, /* setflags enconding */ 547 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 548 kFmtShift, -1, -1, 549 IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES, 550 "subs", "r!0d, r!1d, r!2d!3H", 2), 551 ENCODING_MAP(kThumb2SbcRRR, 0xeb700000, /* setflags encoding */ 552 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 553 kFmtShift, -1, -1, 554 IS_QUAD_OP | REG_DEF0_USE12 | USES_CCODES | SETS_CCODES, 555 "sbcs", "r!0d, r!1d, r!2d!3H", 2), 556 ENCODING_MAP(kThumb2CmpRR, 0xebb00f00, 557 kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, kFmtShift, -1, -1, 558 kFmtUnused, -1, -1, 559 IS_TERTIARY_OP | REG_USE01 | SETS_CCODES, 560 "cmp", "r!0d, r!1d", 2), 561 ENCODING_MAP(kThumb2SubRRI12, 0xf2a00000, 562 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtImm12, -1, -1, 563 kFmtUnused, -1, -1, 564 IS_TERTIARY_OP | REG_DEF0_USE1,/* Note: doesn't affect flags */ 565 "sub", "r!0d,r!1d,#!2d", 2), 566 ENCODING_MAP(kThumb2MvnImmShift, 0xf06f0000, /* no setflags encoding */ 567 kFmtBitBlt, 11, 8, kFmtModImm, -1, -1, kFmtUnused, -1, -1, 568 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0, 569 "mvn", "r!0d, #!1n", 2), 570 ENCODING_MAP(kThumb2Sel, 0xfaa0f080, 571 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 572 kFmtUnused, -1, -1, 573 IS_TERTIARY_OP | REG_DEF0_USE12 | USES_CCODES, 574 "sel", "r!0d, r!1d, r!2d", 2), 575 ENCODING_MAP(kThumb2Ubfx, 0xf3c00000, 576 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtLsb, -1, -1, 577 kFmtBWidth, 4, 0, IS_QUAD_OP | REG_DEF0_USE1, 578 "ubfx", "r!0d, r!1d, #!2d, #!3d", 2), 579 ENCODING_MAP(kThumb2Sbfx, 0xf3400000, 580 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtLsb, -1, -1, 581 kFmtBWidth, 4, 0, IS_QUAD_OP | REG_DEF0_USE1, 582 "sbfx", "r!0d, r!1d, #!2d, #!3d", 2), 583 ENCODING_MAP(kThumb2LdrRRR, 0xf8500000, 584 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 585 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_DEF0_USE12 | IS_LOAD, 586 "ldr", "r!0d, [r!1d, r!2d, LSL #!3d]", 2), 587 ENCODING_MAP(kThumb2LdrhRRR, 0xf8300000, 588 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 589 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_DEF0_USE12 | IS_LOAD, 590 "ldrh", "r!0d, [r!1d, r!2d, LSL #!3d]", 2), 591 ENCODING_MAP(kThumb2LdrshRRR, 0xf9300000, 592 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 593 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_DEF0_USE12 | IS_LOAD, 594 "ldrsh", "r!0d, [r!1d, r!2d, LSL #!3d]", 2), 595 ENCODING_MAP(kThumb2LdrbRRR, 0xf8100000, 596 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 597 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_DEF0_USE12 | IS_LOAD, 598 "ldrb", "r!0d, [r!1d, r!2d, LSL #!3d]", 2), 599 ENCODING_MAP(kThumb2LdrsbRRR, 0xf9100000, 600 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 601 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_DEF0_USE12 | IS_LOAD, 602 "ldrsb", "r!0d, [r!1d, r!2d, LSL #!3d]", 2), 603 ENCODING_MAP(kThumb2StrRRR, 0xf8400000, 604 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 605 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_USE012 | IS_STORE, 606 "str", "r!0d, [r!1d, r!2d, LSL #!3d]", 2), 607 ENCODING_MAP(kThumb2StrhRRR, 0xf8200000, 608 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 609 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_USE012 | IS_STORE, 610 "strh", "r!0d, [r!1d, r!2d, LSL #!3d]", 2), 611 ENCODING_MAP(kThumb2StrbRRR, 0xf8000000, 612 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 613 kFmtBitBlt, 5, 4, IS_QUAD_OP | REG_USE012 | IS_STORE, 614 "strb", "r!0d, [r!1d, r!2d, LSL #!3d]", 2), 615 ENCODING_MAP(kThumb2LdrhRRI12, 0xf8b00000, 616 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0, 617 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 618 "ldrh", "r!0d, [r!1d, #!2d]", 2), 619 ENCODING_MAP(kThumb2LdrshRRI12, 0xf9b00000, 620 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0, 621 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 622 "ldrsh", "r!0d, [r!1d, #!2d]", 2), 623 ENCODING_MAP(kThumb2LdrbRRI12, 0xf8900000, 624 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0, 625 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 626 "ldrb", "r!0d, [r!1d, #!2d]", 2), 627 ENCODING_MAP(kThumb2LdrsbRRI12, 0xf9900000, 628 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0, 629 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 630 "ldrsb", "r!0d, [r!1d, #!2d]", 2), 631 ENCODING_MAP(kThumb2StrhRRI12, 0xf8a00000, 632 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0, 633 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE, 634 "strh", "r!0d, [r!1d, #!2d]", 2), 635 ENCODING_MAP(kThumb2StrbRRI12, 0xf8800000, 636 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 0, 637 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | IS_STORE, 638 "strb", "r!0d, [r!1d, #!2d]", 2), 639 ENCODING_MAP(kThumb2Pop, 0xe8bd0000, 640 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 641 kFmtUnused, -1, -1, 642 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0 643 | IS_LOAD, "pop", "<!0R>", 2), 644 ENCODING_MAP(kThumb2Push, 0xe92d0000, 645 kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 646 kFmtUnused, -1, -1, 647 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE_LIST0 648 | IS_STORE, "push", "<!0R>", 2), 649 ENCODING_MAP(kThumb2CmpRI8, 0xf1b00f00, 650 kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, kFmtUnused, -1, -1, 651 kFmtUnused, -1, -1, 652 IS_BINARY_OP | REG_USE0 | SETS_CCODES, 653 "cmp", "r!0d, #!1m", 2), 654 ENCODING_MAP(kThumb2AdcRRR, 0xeb500000, /* setflags encoding */ 655 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 656 kFmtShift, -1, -1, 657 IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES, 658 "adcs", "r!0d, r!1d, r!2d!3H", 2), 659 ENCODING_MAP(kThumb2AndRRR, 0xea000000, 660 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 661 kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12, 662 "and", "r!0d, r!1d, r!2d!3H", 2), 663 ENCODING_MAP(kThumb2BicRRR, 0xea200000, 664 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 665 kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12, 666 "bic", "r!0d, r!1d, r!2d!3H", 2), 667 ENCODING_MAP(kThumb2CmnRR, 0xeb000000, 668 kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, kFmtShift, -1, -1, 669 kFmtUnused, -1, -1, 670 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, 671 "cmn", "r!0d, r!1d, shift !2d", 2), 672 ENCODING_MAP(kThumb2EorRRR, 0xea800000, 673 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 674 kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12, 675 "eor", "r!0d, r!1d, r!2d!3H", 2), 676 ENCODING_MAP(kThumb2MulRRR, 0xfb00f000, 677 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 678 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 679 "mul", "r!0d, r!1d, r!2d", 2), 680 ENCODING_MAP(kThumb2MnvRR, 0xea6f0000, 681 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtShift, -1, -1, 682 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 683 "mvn", "r!0d, r!1d, shift !2d", 2), 684 ENCODING_MAP(kThumb2RsubRRI8, 0xf1d00000, 685 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, 686 kFmtUnused, -1, -1, 687 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, 688 "rsb", "r!0d,r!1d,#!2m", 2), 689 ENCODING_MAP(kThumb2NegRR, 0xf1d00000, /* instance of rsub */ 690 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtUnused, -1, -1, 691 kFmtUnused, -1, -1, 692 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES, 693 "neg", "r!0d,r!1d", 2), 694 ENCODING_MAP(kThumb2OrrRRR, 0xea400000, 695 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 696 kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12, 697 "orr", "r!0d, r!1d, r!2d!3H", 2), 698 ENCODING_MAP(kThumb2TstRR, 0xea100f00, 699 kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, kFmtShift, -1, -1, 700 kFmtUnused, -1, -1, 701 IS_TERTIARY_OP | REG_USE01 | SETS_CCODES, 702 "tst", "r!0d, r!1d, shift !2d", 2), 703 ENCODING_MAP(kThumb2LslRRR, 0xfa00f000, 704 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 705 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 706 "lsl", "r!0d, r!1d, r!2d", 2), 707 ENCODING_MAP(kThumb2LsrRRR, 0xfa20f000, 708 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 709 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 710 "lsr", "r!0d, r!1d, r!2d", 2), 711 ENCODING_MAP(kThumb2AsrRRR, 0xfa40f000, 712 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 713 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 714 "asr", "r!0d, r!1d, r!2d", 2), 715 ENCODING_MAP(kThumb2RorRRR, 0xfa60f000, 716 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 717 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 718 "ror", "r!0d, r!1d, r!2d", 2), 719 ENCODING_MAP(kThumb2LslRRI5, 0xea4f0000, 720 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtShift5, -1, -1, 721 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 722 "lsl", "r!0d, r!1d, #!2d", 2), 723 ENCODING_MAP(kThumb2LsrRRI5, 0xea4f0010, 724 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtShift5, -1, -1, 725 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 726 "lsr", "r!0d, r!1d, #!2d", 2), 727 ENCODING_MAP(kThumb2AsrRRI5, 0xea4f0020, 728 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtShift5, -1, -1, 729 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 730 "asr", "r!0d, r!1d, #!2d", 2), 731 ENCODING_MAP(kThumb2RorRRI5, 0xea4f0030, 732 kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0, kFmtShift5, -1, -1, 733 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 734 "ror", "r!0d, r!1d, #!2d", 2), 735 ENCODING_MAP(kThumb2BicRRI8, 0xf0200000, 736 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, 737 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 738 "bic", "r!0d, r!1d, #!2m", 2), 739 ENCODING_MAP(kThumb2AndRRI8, 0xf0000000, 740 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, 741 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 742 "and", "r!0d, r!1d, #!2m", 2), 743 ENCODING_MAP(kThumb2OrrRRI8, 0xf0400000, 744 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, 745 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 746 "orr", "r!0d, r!1d, #!2m", 2), 747 ENCODING_MAP(kThumb2EorRRI8, 0xf0800000, 748 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, 749 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, 750 "eor", "r!0d, r!1d, #!2m", 2), 751 ENCODING_MAP(kThumb2AddRRI8, 0xf1100000, 752 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, 753 kFmtUnused, -1, -1, 754 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, 755 "adds", "r!0d, r!1d, #!2m", 2), 756 ENCODING_MAP(kThumb2AdcRRI8, 0xf1500000, 757 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, 758 kFmtUnused, -1, -1, 759 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES | USES_CCODES, 760 "adcs", "r!0d, r!1d, #!2m", 2), 761 ENCODING_MAP(kThumb2SubRRI8, 0xf1b00000, 762 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, 763 kFmtUnused, -1, -1, 764 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, 765 "subs", "r!0d, r!1d, #!2m", 2), 766 ENCODING_MAP(kThumb2SbcRRI8, 0xf1700000, 767 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, 768 kFmtUnused, -1, -1, 769 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES | USES_CCODES, 770 "sbcs", "r!0d, r!1d, #!2m", 2), 771 ENCODING_MAP(kThumb2It, 0xbf00, 772 kFmtBitBlt, 7, 4, kFmtBitBlt, 3, 0, kFmtModImm, -1, -1, 773 kFmtUnused, -1, -1, IS_BINARY_OP | IS_IT | USES_CCODES, 774 "it:!1b", "!0c", 1), 775 ENCODING_MAP(kThumb2Fmstat, 0xeef1fa10, 776 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 777 kFmtUnused, -1, -1, NO_OPERAND | SETS_CCODES, 778 "fmstat", "", 2), 779 ENCODING_MAP(kThumb2Vcmpd, 0xeeb40b40, 780 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1, 781 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01, 782 "vcmp.f64", "!0S, !1S", 2), 783 ENCODING_MAP(kThumb2Vcmps, 0xeeb40a40, 784 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1, 785 kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE01, 786 "vcmp.f32", "!0s, !1s", 2), 787 ENCODING_MAP(kThumb2LdrPcRel12, 0xf8df0000, 788 kFmtBitBlt, 15, 12, kFmtBitBlt, 11, 0, kFmtUnused, -1, -1, 789 kFmtUnused, -1, -1, 790 IS_TERTIARY_OP | REG_DEF0 | REG_USE_PC | IS_LOAD, 791 "ldr", "r!0d, [r15pc, #!1d]", 2), 792 ENCODING_MAP(kThumb2BCond, 0xf0008000, 793 kFmtBrOffset, -1, -1, kFmtBitBlt, 25, 22, kFmtUnused, -1, -1, 794 kFmtUnused, -1, -1, 795 IS_BINARY_OP | IS_BRANCH | USES_CCODES, 796 "b!1c", "!0t", 2), 797 ENCODING_MAP(kThumb2Vmovd_RR, 0xeeb00b40, 798 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1, 799 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 800 "vmov.f64", "!0S, !1S", 2), 801 ENCODING_MAP(kThumb2Vmovs_RR, 0xeeb00a40, 802 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1, 803 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 804 "vmov.f32", "!0s, !1s", 2), 805 ENCODING_MAP(kThumb2Fmrs, 0xee100a10, 806 kFmtBitBlt, 15, 12, kFmtSfp, 7, 16, kFmtUnused, -1, -1, 807 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 808 "fmrs", "r!0d, !1s", 2), 809 ENCODING_MAP(kThumb2Fmsr, 0xee000a10, 810 kFmtSfp, 7, 16, kFmtBitBlt, 15, 12, kFmtUnused, -1, -1, 811 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 812 "fmsr", "!0s, r!1d", 2), 813 ENCODING_MAP(kThumb2Fmrrd, 0xec500b10, 814 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtDfp, 5, 0, 815 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF01_USE2, 816 "fmrrd", "r!0d, r!1d, !2S", 2), 817 ENCODING_MAP(kThumb2Fmdrr, 0xec400b10, 818 kFmtDfp, 5, 0, kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, 819 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, 820 "fmdrr", "!0S, r!1d, r!2d", 2), 821 ENCODING_MAP(kThumb2Vabsd, 0xeeb00bc0, 822 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1, 823 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 824 "vabs.f64", "!0S, !1S", 2), 825 ENCODING_MAP(kThumb2Vabss, 0xeeb00ac0, 826 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1, 827 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 828 "vabs.f32", "!0s, !1s", 2), 829 ENCODING_MAP(kThumb2Vnegd, 0xeeb10b40, 830 kFmtDfp, 22, 12, kFmtDfp, 5, 0, kFmtUnused, -1, -1, 831 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 832 "vneg.f64", "!0S, !1S", 2), 833 ENCODING_MAP(kThumb2Vnegs, 0xeeb10a40, 834 kFmtSfp, 22, 12, kFmtSfp, 5, 0, kFmtUnused, -1, -1, 835 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, 836 "vneg.f32", "!0s, !1s", 2), 837 ENCODING_MAP(kThumb2Vmovs_IMM8, 0xeeb00a00, 838 kFmtSfp, 22, 12, kFmtFPImm, 16, 0, kFmtUnused, -1, -1, 839 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0, 840 "vmov.f32", "!0s, #0x!1h", 2), 841 ENCODING_MAP(kThumb2Vmovd_IMM8, 0xeeb00b00, 842 kFmtDfp, 22, 12, kFmtFPImm, 16, 0, kFmtUnused, -1, -1, 843 kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0, 844 "vmov.f64", "!0S, #0x!1h", 2), 845 ENCODING_MAP(kThumb2Mla, 0xfb000000, 846 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 847 kFmtBitBlt, 15, 12, 848 IS_QUAD_OP | REG_DEF0 | REG_USE1 | REG_USE2 | REG_USE3, 849 "mla", "r!0d, r!1d, r!2d, r!3d", 2), 850 ENCODING_MAP(kThumb2Umull, 0xfba00000, 851 kFmtBitBlt, 15, 12, kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, 852 kFmtBitBlt, 3, 0, 853 IS_QUAD_OP | REG_DEF0 | REG_DEF1 | REG_USE2 | REG_USE3, 854 "umull", "r!0d, r!1d, r!2d, r!3d", 2), 855 ENCODING_MAP(kThumb2Ldrex, 0xe8500f00, 856 kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0, 857 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD, 858 "ldrex", "r!0d, [r!1d, #!2E]", 2), 859 ENCODING_MAP(kThumb2Strex, 0xe8400000, 860 kFmtBitBlt, 11, 8, kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, 861 kFmtBitBlt, 7, 0, IS_QUAD_OP | REG_DEF0_USE12 | IS_STORE, 862 "strex", "r!0d,r!1d, [r!2d, #!2E]", 2), 863 ENCODING_MAP(kThumb2Clrex, 0xf3bf8f2f, 864 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 865 kFmtUnused, -1, -1, NO_OPERAND, 866 "clrex", "", 2), 867 ENCODING_MAP(kThumb2Bfi, 0xf3600000, 868 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtShift5, -1, -1, 869 kFmtBitBlt, 4, 0, IS_QUAD_OP | REG_DEF0_USE1, 870 "bfi", "r!0d,r!1d,#!2d,#!3d", 2), 871 ENCODING_MAP(kThumb2Bfc, 0xf36f0000, 872 kFmtBitBlt, 11, 8, kFmtShift5, -1, -1, kFmtBitBlt, 4, 0, 873 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0, 874 "bfc", "r!0d,#!1d,#!2d", 2), 875 ENCODING_MAP(kThumb2Dmb, 0xf3bf8f50, 876 kFmtBitBlt, 3, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 877 kFmtUnused, -1, -1, IS_UNARY_OP, 878 "dmb","#!0B",2), 879 ENCODING_MAP(kThumb2LdrPcReln12, 0xf85f0000, 880 kFmtBitBlt, 15, 12, kFmtBitBlt, 11, 0, kFmtUnused, -1, -1, 881 kFmtUnused, -1, -1, 882 IS_BINARY_OP | REG_DEF0 | REG_USE_PC | IS_LOAD, 883 "ldr", "r!0d, [r15pc, -#!1d]", 2), 884 ENCODING_MAP(kThumb2RsbRRR, 0xebd00000, /* setflags encoding */ 885 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, 886 kFmtShift, -1, -1, 887 IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES, 888 "rsb", "r!0d, r!1d, r!2d!3H", 2), 889 ENCODING_MAP(kThumbUndefined, 0xde00, 890 kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, 891 kFmtUnused, -1, -1, NO_OPERAND, 892 "undefined", "", 1), 893 }; 894 895 /* 896 * The fake NOP of moving r0 to r0 actually will incur data stalls if r0 is 897 * not ready. Since r5FP is not updated often, it is less likely to 898 * generate unnecessary stall cycles. 899 */ 900 #define PADDING_MOV_R5_R5 0x1C2D 901 902 /* Track the number of times that the code cache is patched */ 903 #if defined(WITH_JIT_TUNING) 904 #define UPDATE_CODE_CACHE_PATCHES() (gDvmJit.codeCachePatches++) 905 #else 906 #define UPDATE_CODE_CACHE_PATCHES() 907 #endif 908 909 /* Write the numbers in the constant and class pool to the output stream */ 910 static void installLiteralPools(CompilationUnit *cUnit) 911 { 912 int *dataPtr = (int *) ((char *) cUnit->baseAddr + cUnit->dataOffset); 913 /* Install number of class pointer literals */ 914 *dataPtr++ = cUnit->numClassPointers; 915 ArmLIR *dataLIR = (ArmLIR *) cUnit->classPointerList; 916 while (dataLIR) { 917 /* 918 * Install the callsiteinfo pointers into the cells for now. They will 919 * be converted into real pointers in dvmJitInstallClassObjectPointers. 920 */ 921 *dataPtr++ = dataLIR->operands[0]; 922 dataLIR = NEXT_LIR(dataLIR); 923 } 924 dataLIR = (ArmLIR *) cUnit->literalList; 925 while (dataLIR) { 926 *dataPtr++ = dataLIR->operands[0]; 927 dataLIR = NEXT_LIR(dataLIR); 928 } 929 } 930 931 /* 932 * Assemble the LIR into binary instruction format. Note that we may 933 * discover that pc-relative displacements may not fit the selected 934 * instruction. In those cases we will try to substitute a new code 935 * sequence or request that the trace be shortened and retried. 936 */ 937 static AssemblerStatus assembleInstructions(CompilationUnit *cUnit, 938 intptr_t startAddr) 939 { 940 short *bufferAddr = (short *) cUnit->codeBuffer; 941 ArmLIR *lir; 942 943 for (lir = (ArmLIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) { 944 if (lir->opcode < 0) { 945 if ((lir->opcode == kArmPseudoPseudoAlign4) && 946 /* 1 means padding is needed */ 947 (lir->operands[0] == 1)) { 948 *bufferAddr++ = PADDING_MOV_R5_R5; 949 } 950 continue; 951 } 952 953 if (lir->flags.isNop) { 954 continue; 955 } 956 957 if (lir->opcode == kThumbLdrPcRel || 958 lir->opcode == kThumb2LdrPcRel12 || 959 lir->opcode == kThumbAddPcRel || 960 ((lir->opcode == kThumb2Vldrd) && (lir->operands[1] == r15pc)) || 961 ((lir->opcode == kThumb2Vldrs) && (lir->operands[1] == r15pc))) { 962 ArmLIR *lirTarget = (ArmLIR *) lir->generic.target; 963 intptr_t pc = (lir->generic.offset + 4) & ~3; 964 intptr_t target = lirTarget->generic.offset; 965 int delta = target - pc; 966 if (delta & 0x3) { 967 ALOGE("PC-rel distance is not multiples of 4: %d", delta); 968 dvmCompilerAbort(cUnit); 969 } 970 if ((lir->opcode == kThumb2LdrPcRel12) && (delta > 4091)) { 971 if (cUnit->printMe) { 972 ALOGD("kThumb2LdrPcRel12@%x: delta=%d", lir->generic.offset, 973 delta); 974 dvmCompilerCodegenDump(cUnit); 975 } 976 return kRetryHalve; 977 } else if (delta > 1020) { 978 if (cUnit->printMe) { 979 ALOGD("kThumbLdrPcRel@%x: delta=%d", lir->generic.offset, 980 delta); 981 dvmCompilerCodegenDump(cUnit); 982 } 983 return kRetryHalve; 984 } 985 if ((lir->opcode == kThumb2Vldrs) || (lir->opcode == kThumb2Vldrd)) { 986 lir->operands[2] = delta >> 2; 987 } else { 988 lir->operands[1] = (lir->opcode == kThumb2LdrPcRel12) ? 989 delta : delta >> 2; 990 } 991 } else if (lir->opcode == kThumb2Cbnz || lir->opcode == kThumb2Cbz) { 992 ArmLIR *targetLIR = (ArmLIR *) lir->generic.target; 993 intptr_t pc = lir->generic.offset + 4; 994 intptr_t target = targetLIR->generic.offset; 995 int delta = target - pc; 996 if (delta > 126 || delta < 0) { 997 /* Convert to cmp rx,#0 / b[eq/ne] tgt pair */ 998 ArmLIR *newInst = 999 (ArmLIR *)dvmCompilerNew(sizeof(ArmLIR), true); 1000 /* Make new branch instruction and insert after */ 1001 newInst->opcode = kThumbBCond; 1002 newInst->operands[0] = 0; 1003 newInst->operands[1] = (lir->opcode == kThumb2Cbz) ? 1004 kArmCondEq : kArmCondNe; 1005 newInst->generic.target = lir->generic.target; 1006 dvmCompilerSetupResourceMasks(newInst); 1007 dvmCompilerInsertLIRAfter((LIR *)lir, (LIR *)newInst); 1008 /* Convert the cb[n]z to a cmp rx, #0 ] */ 1009 lir->opcode = kThumbCmpRI8; 1010 /* operand[0] is src1 in both cb[n]z & CmpRI8 */ 1011 lir->operands[1] = 0; 1012 lir->generic.target = 0; 1013 dvmCompilerSetupResourceMasks(lir); 1014 if (cUnit->printMe) { 1015 ALOGD("kThumb2Cbnz/kThumb2Cbz@%x: delta=%d", 1016 lir->generic.offset, delta); 1017 dvmCompilerCodegenDump(cUnit); 1018 } 1019 return kRetryAll; 1020 } else { 1021 lir->operands[1] = delta >> 1; 1022 } 1023 } else if (lir->opcode == kThumbBCond || 1024 lir->opcode == kThumb2BCond) { 1025 ArmLIR *targetLIR = (ArmLIR *) lir->generic.target; 1026 intptr_t pc = lir->generic.offset + 4; 1027 intptr_t target = targetLIR->generic.offset; 1028 int delta = target - pc; 1029 if ((lir->opcode == kThumbBCond) && (delta > 254 || delta < -256)) { 1030 if (cUnit->printMe) { 1031 ALOGD("kThumbBCond@%x: delta=%d", lir->generic.offset, 1032 delta); 1033 dvmCompilerCodegenDump(cUnit); 1034 } 1035 return kRetryHalve; 1036 } 1037 lir->operands[0] = delta >> 1; 1038 } else if (lir->opcode == kThumbBUncond) { 1039 ArmLIR *targetLIR = (ArmLIR *) lir->generic.target; 1040 intptr_t pc = lir->generic.offset + 4; 1041 intptr_t target = targetLIR->generic.offset; 1042 int delta = target - pc; 1043 if (delta > 2046 || delta < -2048) { 1044 ALOGE("Unconditional branch distance out of range: %d", delta); 1045 dvmCompilerAbort(cUnit); 1046 } 1047 lir->operands[0] = delta >> 1; 1048 } else if (lir->opcode == kThumbBlx1) { 1049 assert(NEXT_LIR(lir)->opcode == kThumbBlx2); 1050 /* curPC is Thumb */ 1051 intptr_t curPC = (startAddr + lir->generic.offset + 4) & ~3; 1052 intptr_t target = lir->operands[1]; 1053 1054 /* Match bit[1] in target with base */ 1055 if (curPC & 0x2) { 1056 target |= 0x2; 1057 } 1058 int delta = target - curPC; 1059 assert((delta >= -(1<<22)) && (delta <= ((1<<22)-2))); 1060 1061 lir->operands[0] = (delta >> 12) & 0x7ff; 1062 NEXT_LIR(lir)->operands[0] = (delta>> 1) & 0x7ff; 1063 } else if (lir->opcode == kThumbBl1) { 1064 assert(NEXT_LIR(lir)->opcode == kThumbBl2); 1065 /* Both curPC and target are Thumb */ 1066 intptr_t curPC = startAddr + lir->generic.offset + 4; 1067 intptr_t target = lir->operands[1]; 1068 1069 int delta = target - curPC; 1070 assert((delta >= -(1<<22)) && (delta <= ((1<<22)-2))); 1071 1072 lir->operands[0] = (delta >> 12) & 0x7ff; 1073 NEXT_LIR(lir)->operands[0] = (delta>> 1) & 0x7ff; 1074 } 1075 1076 ArmEncodingMap *encoder = &EncodingMap[lir->opcode]; 1077 u4 bits = encoder->skeleton; 1078 int i; 1079 for (i = 0; i < 4; i++) { 1080 u4 operand; 1081 u4 value; 1082 operand = lir->operands[i]; 1083 switch(encoder->fieldLoc[i].kind) { 1084 case kFmtUnused: 1085 break; 1086 case kFmtFPImm: 1087 value = ((operand & 0xF0) >> 4) << encoder->fieldLoc[i].end; 1088 value |= (operand & 0x0F) << encoder->fieldLoc[i].start; 1089 bits |= value; 1090 break; 1091 case kFmtBrOffset: 1092 value = ((operand & 0x80000) >> 19) << 26; 1093 value |= ((operand & 0x40000) >> 18) << 11; 1094 value |= ((operand & 0x20000) >> 17) << 13; 1095 value |= ((operand & 0x1f800) >> 11) << 16; 1096 value |= (operand & 0x007ff); 1097 bits |= value; 1098 break; 1099 case kFmtShift5: 1100 value = ((operand & 0x1c) >> 2) << 12; 1101 value |= (operand & 0x03) << 6; 1102 bits |= value; 1103 break; 1104 case kFmtShift: 1105 value = ((operand & 0x70) >> 4) << 12; 1106 value |= (operand & 0x0f) << 4; 1107 bits |= value; 1108 break; 1109 case kFmtBWidth: 1110 value = operand - 1; 1111 bits |= value; 1112 break; 1113 case kFmtLsb: 1114 value = ((operand & 0x1c) >> 2) << 12; 1115 value |= (operand & 0x03) << 6; 1116 bits |= value; 1117 break; 1118 case kFmtImm6: 1119 value = ((operand & 0x20) >> 5) << 9; 1120 value |= (operand & 0x1f) << 3; 1121 bits |= value; 1122 break; 1123 case kFmtBitBlt: 1124 value = (operand << encoder->fieldLoc[i].start) & 1125 ((1 << (encoder->fieldLoc[i].end + 1)) - 1); 1126 bits |= value; 1127 break; 1128 case kFmtDfp: { 1129 assert(DOUBLEREG(operand)); 1130 assert((operand & 0x1) == 0); 1131 int regName = (operand & FP_REG_MASK) >> 1; 1132 /* Snag the 1-bit slice and position it */ 1133 value = ((regName & 0x10) >> 4) << 1134 encoder->fieldLoc[i].end; 1135 /* Extract and position the 4-bit slice */ 1136 value |= (regName & 0x0f) << 1137 encoder->fieldLoc[i].start; 1138 bits |= value; 1139 break; 1140 } 1141 case kFmtSfp: 1142 assert(SINGLEREG(operand)); 1143 /* Snag the 1-bit slice and position it */ 1144 value = (operand & 0x1) << 1145 encoder->fieldLoc[i].end; 1146 /* Extract and position the 4-bit slice */ 1147 value |= ((operand & 0x1e) >> 1) << 1148 encoder->fieldLoc[i].start; 1149 bits |= value; 1150 break; 1151 case kFmtImm12: 1152 case kFmtModImm: 1153 value = ((operand & 0x800) >> 11) << 26; 1154 value |= ((operand & 0x700) >> 8) << 12; 1155 value |= operand & 0x0ff; 1156 bits |= value; 1157 break; 1158 case kFmtImm16: 1159 value = ((operand & 0x0800) >> 11) << 26; 1160 value |= ((operand & 0xf000) >> 12) << 16; 1161 value |= ((operand & 0x0700) >> 8) << 12; 1162 value |= operand & 0x0ff; 1163 bits |= value; 1164 break; 1165 default: 1166 assert(0); 1167 } 1168 } 1169 if (encoder->size == 2) { 1170 *bufferAddr++ = (bits >> 16) & 0xffff; 1171 } 1172 *bufferAddr++ = bits & 0xffff; 1173 } 1174 return kSuccess; 1175 } 1176 1177 static int assignLiteralOffsetCommon(LIR *lir, int offset) 1178 { 1179 for (;lir != NULL; lir = lir->next) { 1180 lir->offset = offset; 1181 offset += 4; 1182 } 1183 return offset; 1184 } 1185 1186 /* Determine the offset of each literal field */ 1187 static int assignLiteralOffset(CompilationUnit *cUnit, int offset) 1188 { 1189 /* Reserved for the size field of class pointer pool */ 1190 offset += 4; 1191 offset = assignLiteralOffsetCommon(cUnit->classPointerList, offset); 1192 offset = assignLiteralOffsetCommon(cUnit->literalList, offset); 1193 return offset; 1194 } 1195 1196 /* 1197 * Translation layout in the code cache. Note that the codeAddress pointer 1198 * in JitTable will point directly to the code body (field codeAddress). The 1199 * chain cell offset codeAddress - 2, and the address of the trace profile 1200 * counter is at codeAddress - 6. 1201 * 1202 * +----------------------------+ 1203 * | Trace Profile Counter addr | -> 4 bytes (PROF_COUNTER_ADDR_SIZE) 1204 * +----------------------------+ 1205 * +--| Offset to chain cell counts| -> 2 bytes (CHAIN_CELL_OFFSET_SIZE) 1206 * | +----------------------------+ 1207 * | | Trace profile code | <- entry point when profiling 1208 * | . - - - - - - - . 1209 * | | Code body | <- entry point when not profiling 1210 * | . . 1211 * | | | 1212 * | +----------------------------+ 1213 * | | Chaining Cells | -> 12/16 bytes, 4 byte aligned 1214 * | . . 1215 * | . . 1216 * | | | 1217 * | +----------------------------+ 1218 * | | Gap for large switch stmt | -> # cases >= MAX_CHAINED_SWITCH_CASES 1219 * | +----------------------------+ 1220 * +->| Chaining cell counts | -> 8 bytes, chain cell counts by type 1221 * +----------------------------+ 1222 * | Trace description | -> variable sized 1223 * . . 1224 * | | 1225 * +----------------------------+ 1226 * | # Class pointer pool size | -> 4 bytes 1227 * +----------------------------+ 1228 * | Class pointer pool | -> 4-byte aligned, variable size 1229 * . . 1230 * . . 1231 * | | 1232 * +----------------------------+ 1233 * | Literal pool | -> 4-byte aligned, variable size 1234 * . . 1235 * . . 1236 * | | 1237 * +----------------------------+ 1238 * 1239 */ 1240 1241 #define PROF_COUNTER_ADDR_SIZE 4 1242 #define CHAIN_CELL_OFFSET_SIZE 2 1243 1244 /* 1245 * Utility functions to navigate various parts in a trace. If we change the 1246 * layout/offset in the future, we just modify these functions and we don't need 1247 * to propagate the changes to all the use cases. 1248 */ 1249 static inline char *getTraceBase(const JitEntry *p) 1250 { 1251 return (char*)p->codeAddress - 1252 (PROF_COUNTER_ADDR_SIZE + CHAIN_CELL_OFFSET_SIZE + 1253 (p->u.info.instructionSet == DALVIK_JIT_ARM ? 0 : 1)); 1254 } 1255 1256 /* Handy function to retrieve the profile count */ 1257 static inline JitTraceCounter_t getProfileCount(const JitEntry *entry) 1258 { 1259 if (entry->dPC == 0 || entry->codeAddress == 0 || 1260 entry->codeAddress == dvmCompilerGetInterpretTemplate()) 1261 return 0; 1262 1263 JitTraceCounter_t **p = (JitTraceCounter_t **) getTraceBase(entry); 1264 1265 return **p; 1266 } 1267 1268 /* Handy function to reset the profile count */ 1269 static inline void resetProfileCount(const JitEntry *entry) 1270 { 1271 if (entry->dPC == 0 || entry->codeAddress == 0 || 1272 entry->codeAddress == dvmCompilerGetInterpretTemplate()) 1273 return; 1274 1275 JitTraceCounter_t **p = (JitTraceCounter_t **) getTraceBase(entry); 1276 1277 **p = 0; 1278 } 1279 1280 /* Get the pointer of the chain cell count */ 1281 static inline ChainCellCounts* getChainCellCountsPointer(const char *base) 1282 { 1283 /* 4 is the size of the profile count */ 1284 u2 *chainCellOffsetP = (u2 *) (base + PROF_COUNTER_ADDR_SIZE); 1285 u2 chainCellOffset = *chainCellOffsetP; 1286 return (ChainCellCounts *) ((char *) chainCellOffsetP + chainCellOffset); 1287 } 1288 1289 /* Get the size of all chaining cells */ 1290 static inline u4 getChainCellSize(const ChainCellCounts* pChainCellCounts) 1291 { 1292 int cellSize = 0; 1293 int i; 1294 1295 /* Get total count of chain cells */ 1296 for (i = 0; i < kChainingCellGap; i++) { 1297 if (i != kChainingCellInvokePredicted) { 1298 cellSize += pChainCellCounts->u.count[i] * 1299 (CHAIN_CELL_NORMAL_SIZE >> 2); 1300 } else { 1301 cellSize += pChainCellCounts->u.count[i] * 1302 (CHAIN_CELL_PREDICTED_SIZE >> 2); 1303 } 1304 } 1305 return cellSize; 1306 } 1307 1308 /* Get the starting pointer of the trace description section */ 1309 static JitTraceDescription* getTraceDescriptionPointer(const char *base) 1310 { 1311 ChainCellCounts* pCellCounts = getChainCellCountsPointer(base); 1312 return (JitTraceDescription*) ((char*)pCellCounts + sizeof(*pCellCounts)); 1313 } 1314 1315 /* Get the size of a trace description */ 1316 static int getTraceDescriptionSize(const JitTraceDescription *desc) 1317 { 1318 int runCount; 1319 /* Trace end is always of non-meta type (ie isCode == true) */ 1320 for (runCount = 0; ; runCount++) { 1321 if (desc->trace[runCount].isCode && 1322 desc->trace[runCount].info.frag.runEnd) 1323 break; 1324 } 1325 return sizeof(JitTraceDescription) + ((runCount+1) * sizeof(JitTraceRun)); 1326 } 1327 1328 #if defined(SIGNATURE_BREAKPOINT) 1329 /* Inspect the assembled instruction stream to find potential matches */ 1330 static void matchSignatureBreakpoint(const CompilationUnit *cUnit, 1331 unsigned int size) 1332 { 1333 unsigned int i, j; 1334 u4 *ptr = (u4 *) cUnit->codeBuffer; 1335 1336 for (i = 0; i < size - gDvmJit.signatureBreakpointSize + 1; i++) { 1337 if (ptr[i] == gDvmJit.signatureBreakpoint[0]) { 1338 for (j = 1; j < gDvmJit.signatureBreakpointSize; j++) { 1339 if (ptr[i+j] != gDvmJit.signatureBreakpoint[j]) { 1340 break; 1341 } 1342 } 1343 if (j == gDvmJit.signatureBreakpointSize) { 1344 ALOGD("Signature match starting from offset %#x (%d words)", 1345 i*4, gDvmJit.signatureBreakpointSize); 1346 int descSize = getTraceDescriptionSize(cUnit->traceDesc); 1347 JitTraceDescription *newCopy = 1348 (JitTraceDescription *) malloc(descSize); 1349 memcpy(newCopy, cUnit->traceDesc, descSize); 1350 dvmCompilerWorkEnqueue(NULL, kWorkOrderTraceDebug, newCopy); 1351 break; 1352 } 1353 } 1354 } 1355 } 1356 #endif 1357 1358 /* 1359 * Go over each instruction in the list and calculate the offset from the top 1360 * before sending them off to the assembler. If out-of-range branch distance is 1361 * seen rearrange the instructions a bit to correct it. 1362 */ 1363 void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info) 1364 { 1365 ArmLIR *armLIR; 1366 int offset = 0; 1367 int i; 1368 ChainCellCounts chainCellCounts; 1369 int descSize = (cUnit->jitMode == kJitMethod) ? 1370 0 : getTraceDescriptionSize(cUnit->traceDesc); 1371 int chainingCellGap = 0; 1372 1373 info->instructionSet = cUnit->instructionSet; 1374 1375 /* Beginning offset needs to allow space for chain cell offset */ 1376 for (armLIR = (ArmLIR *) cUnit->firstLIRInsn; 1377 armLIR; 1378 armLIR = NEXT_LIR(armLIR)) { 1379 armLIR->generic.offset = offset; 1380 if (armLIR->opcode >= 0 && !armLIR->flags.isNop) { 1381 armLIR->flags.size = EncodingMap[armLIR->opcode].size * 2; 1382 offset += armLIR->flags.size; 1383 } else if (armLIR->opcode == kArmPseudoPseudoAlign4) { 1384 if (offset & 0x2) { 1385 offset += 2; 1386 armLIR->operands[0] = 1; 1387 } else { 1388 armLIR->operands[0] = 0; 1389 } 1390 } 1391 /* Pseudo opcodes don't consume space */ 1392 } 1393 1394 /* Const values have to be word aligned */ 1395 offset = (offset + 3) & ~3; 1396 1397 u4 chainCellOffset = offset; 1398 ArmLIR *chainCellOffsetLIR = NULL; 1399 1400 if (cUnit->jitMode != kJitMethod) { 1401 /* 1402 * Get the gap (# of u4) between the offset of chaining cell count and 1403 * the bottom of real chaining cells. If the translation has chaining 1404 * cells, the gap is guaranteed to be multiples of 4. 1405 */ 1406 chainingCellGap = (offset - cUnit->chainingCellBottom->offset) >> 2; 1407 1408 /* Add space for chain cell counts & trace description */ 1409 chainCellOffsetLIR = (ArmLIR *) cUnit->chainCellOffsetLIR; 1410 assert(chainCellOffsetLIR); 1411 assert(chainCellOffset < 0x10000); 1412 assert(chainCellOffsetLIR->opcode == kArm16BitData && 1413 chainCellOffsetLIR->operands[0] == CHAIN_CELL_OFFSET_TAG); 1414 1415 /* 1416 * Adjust the CHAIN_CELL_OFFSET_TAG LIR's offset to remove the 1417 * space occupied by the pointer to the trace profiling counter. 1418 */ 1419 chainCellOffsetLIR->operands[0] = chainCellOffset - 4; 1420 1421 offset += sizeof(chainCellCounts) + descSize; 1422 1423 assert((offset & 0x3) == 0); /* Should still be word aligned */ 1424 } 1425 1426 /* Set up offsets for literals */ 1427 cUnit->dataOffset = offset; 1428 1429 /* 1430 * Assign each class pointer/constant an offset from the beginning of the 1431 * compilation unit. 1432 */ 1433 offset = assignLiteralOffset(cUnit, offset); 1434 1435 cUnit->totalSize = offset; 1436 1437 if (gDvmJit.codeCacheByteUsed + cUnit->totalSize > gDvmJit.codeCacheSize) { 1438 gDvmJit.codeCacheFull = true; 1439 info->discardResult = true; 1440 return; 1441 } 1442 1443 /* Allocate enough space for the code block */ 1444 cUnit->codeBuffer = (unsigned char *)dvmCompilerNew(chainCellOffset, true); 1445 if (cUnit->codeBuffer == NULL) { 1446 ALOGE("Code buffer allocation failure"); 1447 info->discardResult = true; 1448 return; 1449 } 1450 1451 /* 1452 * Attempt to assemble the trace. Note that assembleInstructions 1453 * may rewrite the code sequence and request a retry. 1454 */ 1455 cUnit->assemblerStatus = assembleInstructions(cUnit, 1456 (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed); 1457 1458 switch(cUnit->assemblerStatus) { 1459 case kSuccess: 1460 break; 1461 case kRetryAll: 1462 if (cUnit->assemblerRetries < MAX_ASSEMBLER_RETRIES) { 1463 if (cUnit->jitMode != kJitMethod) { 1464 /* Restore pristine chain cell marker on retry */ 1465 chainCellOffsetLIR->operands[0] = CHAIN_CELL_OFFSET_TAG; 1466 } 1467 return; 1468 } 1469 /* Too many retries - reset and try cutting the trace in half */ 1470 cUnit->assemblerRetries = 0; 1471 cUnit->assemblerStatus = kRetryHalve; 1472 return; 1473 case kRetryHalve: 1474 return; 1475 default: 1476 ALOGE("Unexpected assembler status: %d", cUnit->assemblerStatus); 1477 dvmAbort(); 1478 } 1479 1480 #if defined(SIGNATURE_BREAKPOINT) 1481 if (info->discardResult == false && gDvmJit.signatureBreakpoint != NULL && 1482 chainCellOffset/4 >= gDvmJit.signatureBreakpointSize) { 1483 matchSignatureBreakpoint(cUnit, chainCellOffset/4); 1484 } 1485 #endif 1486 1487 /* Don't go all the way if the goal is just to get the verbose output */ 1488 if (info->discardResult) return; 1489 1490 /* 1491 * The cache might disappear - acquire lock and check version 1492 * Continue holding lock until translation cache update is complete. 1493 * These actions are required here in the compiler thread because 1494 * it is unaffected by suspend requests and doesn't know if a 1495 * translation cache flush is in progress. 1496 */ 1497 dvmLockMutex(&gDvmJit.compilerLock); 1498 if (info->cacheVersion != gDvmJit.cacheVersion) { 1499 /* Cache changed - discard current translation */ 1500 info->discardResult = true; 1501 info->codeAddress = NULL; 1502 dvmUnlockMutex(&gDvmJit.compilerLock); 1503 return; 1504 } 1505 1506 cUnit->baseAddr = (char *) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed; 1507 gDvmJit.codeCacheByteUsed += offset; 1508 1509 UNPROTECT_CODE_CACHE(cUnit->baseAddr, offset); 1510 1511 /* Install the code block */ 1512 memcpy((char*)cUnit->baseAddr, cUnit->codeBuffer, chainCellOffset); 1513 gDvmJit.numCompilations++; 1514 1515 if (cUnit->jitMode != kJitMethod) { 1516 /* Install the chaining cell counts */ 1517 for (i=0; i< kChainingCellGap; i++) { 1518 chainCellCounts.u.count[i] = cUnit->numChainingCells[i]; 1519 } 1520 1521 /* Set the gap number in the chaining cell count structure */ 1522 chainCellCounts.u.count[kChainingCellGap] = chainingCellGap; 1523 1524 memcpy((char*)cUnit->baseAddr + chainCellOffset, &chainCellCounts, 1525 sizeof(chainCellCounts)); 1526 1527 /* Install the trace description */ 1528 memcpy((char*) cUnit->baseAddr + chainCellOffset + 1529 sizeof(chainCellCounts), 1530 cUnit->traceDesc, descSize); 1531 } 1532 1533 /* Write the literals directly into the code cache */ 1534 installLiteralPools(cUnit); 1535 1536 /* Flush dcache and invalidate the icache to maintain coherence */ 1537 dvmCompilerCacheFlush((long)cUnit->baseAddr, 1538 (long)((char *) cUnit->baseAddr + offset), 0); 1539 UPDATE_CODE_CACHE_PATCHES(); 1540 1541 PROTECT_CODE_CACHE(cUnit->baseAddr, offset); 1542 1543 /* Translation cache update complete - release lock */ 1544 dvmUnlockMutex(&gDvmJit.compilerLock); 1545 1546 /* Record code entry point and instruction set */ 1547 info->codeAddress = (char*)cUnit->baseAddr + cUnit->headerSize; 1548 /* If applicable, mark low bit to denote thumb */ 1549 if (info->instructionSet != DALVIK_JIT_ARM) 1550 info->codeAddress = (char*)info->codeAddress + 1; 1551 /* transfer the size of the profiling code */ 1552 info->profileCodeSize = cUnit->profileCodeSize; 1553 } 1554 1555 /* 1556 * Returns the skeleton bit pattern associated with an opcode. All 1557 * variable fields are zeroed. 1558 */ 1559 static u4 getSkeleton(ArmOpcode op) 1560 { 1561 return EncodingMap[op].skeleton; 1562 } 1563 1564 static u4 assembleChainingBranch(int branchOffset, bool thumbTarget) 1565 { 1566 u4 thumb1, thumb2; 1567 1568 if (!thumbTarget) { 1569 thumb1 = (getSkeleton(kThumbBlx1) | ((branchOffset>>12) & 0x7ff)); 1570 thumb2 = (getSkeleton(kThumbBlx2) | ((branchOffset>> 1) & 0x7ff)); 1571 } else if ((branchOffset < -2048) | (branchOffset > 2046)) { 1572 thumb1 = (getSkeleton(kThumbBl1) | ((branchOffset>>12) & 0x7ff)); 1573 thumb2 = (getSkeleton(kThumbBl2) | ((branchOffset>> 1) & 0x7ff)); 1574 } else { 1575 thumb1 = (getSkeleton(kThumbBUncond) | ((branchOffset>> 1) & 0x7ff)); 1576 thumb2 = getSkeleton(kThumbOrr); /* nop -> or r0, r0 */ 1577 } 1578 1579 return thumb2<<16 | thumb1; 1580 } 1581 1582 /* 1583 * Perform translation chain operation. 1584 * For ARM, we'll use a pair of thumb instructions to generate 1585 * an unconditional chaining branch of up to 4MB in distance. 1586 * Use a BL, because the generic "interpret" translation needs 1587 * the link register to find the dalvik pc of teh target. 1588 * 111HHooooooooooo 1589 * Where HH is 10 for the 1st inst, and 11 for the second and 1590 * the "o" field is each instruction's 11-bit contribution to the 1591 * 22-bit branch offset. 1592 * If the target is nearby, use a single-instruction bl. 1593 * If one or more threads is suspended, don't chain. 1594 */ 1595 void* dvmJitChain(void* tgtAddr, u4* branchAddr) 1596 { 1597 int baseAddr = (u4) branchAddr + 4; 1598 int branchOffset = (int) tgtAddr - baseAddr; 1599 u4 newInst; 1600 bool thumbTarget; 1601 1602 /* 1603 * Only chain translations when there is no urge to ask all threads to 1604 * suspend themselves via the interpreter. 1605 */ 1606 if ((gDvmJit.pProfTable != NULL) && (gDvm.sumThreadSuspendCount == 0) && 1607 (gDvmJit.codeCacheFull == false)) { 1608 assert((branchOffset >= -(1<<22)) && (branchOffset <= ((1<<22)-2))); 1609 1610 gDvmJit.translationChains++; 1611 1612 COMPILER_TRACE_CHAINING( 1613 ALOGD("Jit Runtime: chaining %#x to %#x", 1614 (int) branchAddr, (int) tgtAddr & -2)); 1615 1616 /* 1617 * NOTE: normally, all translations are Thumb[2] mode, with 1618 * a single exception: the default TEMPLATE_INTERPRET 1619 * pseudo-translation. If the need ever arises to 1620 * mix Arm & Thumb[2] translations, the following code should be 1621 * generalized. 1622 */ 1623 thumbTarget = (tgtAddr != dvmCompilerGetInterpretTemplate()); 1624 1625 newInst = assembleChainingBranch(branchOffset, thumbTarget); 1626 1627 /* 1628 * The second half-word instruction of the chaining cell must 1629 * either be a nop (which represents initial state), or is the 1630 * same exact branch halfword that we are trying to install. 1631 */ 1632 assert( ((*branchAddr >> 16) == getSkeleton(kThumbOrr)) || 1633 ((*branchAddr >> 16) == (newInst >> 16))); 1634 1635 UNPROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr)); 1636 1637 *branchAddr = newInst; 1638 dvmCompilerCacheFlush((long)branchAddr, (long)branchAddr + 4, 0); 1639 UPDATE_CODE_CACHE_PATCHES(); 1640 1641 PROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr)); 1642 1643 gDvmJit.hasNewChain = true; 1644 } 1645 1646 return tgtAddr; 1647 } 1648 1649 #if !defined(WITH_SELF_VERIFICATION) 1650 /* 1651 * Attempt to enqueue a work order to patch an inline cache for a predicted 1652 * chaining cell for virtual/interface calls. 1653 */ 1654 static void inlineCachePatchEnqueue(PredictedChainingCell *cellAddr, 1655 PredictedChainingCell *newContent) 1656 { 1657 /* 1658 * Make sure only one thread gets here since updating the cell (ie fast 1659 * path and queueing the request (ie the queued path) have to be done 1660 * in an atomic fashion. 1661 */ 1662 dvmLockMutex(&gDvmJit.compilerICPatchLock); 1663 1664 /* Fast path for uninitialized chaining cell */ 1665 if (cellAddr->clazz == NULL && 1666 cellAddr->branch == PREDICTED_CHAIN_BX_PAIR_INIT) { 1667 1668 UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1669 1670 cellAddr->method = newContent->method; 1671 cellAddr->branch = newContent->branch; 1672 /* 1673 * The update order matters - make sure clazz is updated last since it 1674 * will bring the uninitialized chaining cell to life. 1675 */ 1676 android_atomic_release_store((int32_t)newContent->clazz, 1677 (volatile int32_t *)(void *)&cellAddr->clazz); 1678 dvmCompilerCacheFlush((intptr_t) cellAddr, (intptr_t) (cellAddr+1), 0); 1679 UPDATE_CODE_CACHE_PATCHES(); 1680 1681 PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1682 1683 #if defined(WITH_JIT_TUNING) 1684 gDvmJit.icPatchInit++; 1685 #endif 1686 /* Check if this is a frequently missed clazz */ 1687 } else if (cellAddr->stagedClazz != newContent->clazz) { 1688 /* Not proven to be frequent yet - build up the filter cache */ 1689 UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1690 1691 cellAddr->stagedClazz = newContent->clazz; 1692 1693 UPDATE_CODE_CACHE_PATCHES(); 1694 PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1695 1696 #if defined(WITH_JIT_TUNING) 1697 gDvmJit.icPatchRejected++; 1698 #endif 1699 /* 1700 * Different classes but same method implementation - it is safe to just 1701 * patch the class value without the need to stop the world. 1702 */ 1703 } else if (cellAddr->method == newContent->method) { 1704 UNPROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1705 1706 cellAddr->clazz = newContent->clazz; 1707 /* No need to flush the cache here since the branch is not patched */ 1708 UPDATE_CODE_CACHE_PATCHES(); 1709 1710 PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); 1711 1712 #if defined(WITH_JIT_TUNING) 1713 gDvmJit.icPatchLockFree++; 1714 #endif 1715 /* 1716 * Cannot patch the chaining cell inline - queue it until the next safe 1717 * point. 1718 */ 1719 } else if (gDvmJit.compilerICPatchIndex < COMPILER_IC_PATCH_QUEUE_SIZE) { 1720 int index = gDvmJit.compilerICPatchIndex++; 1721 const ClassObject *clazz = newContent->clazz; 1722 1723 gDvmJit.compilerICPatchQueue[index].cellAddr = cellAddr; 1724 gDvmJit.compilerICPatchQueue[index].cellContent = *newContent; 1725 gDvmJit.compilerICPatchQueue[index].classDescriptor = clazz->descriptor; 1726 gDvmJit.compilerICPatchQueue[index].classLoader = clazz->classLoader; 1727 /* For verification purpose only */ 1728 gDvmJit.compilerICPatchQueue[index].serialNumber = clazz->serialNumber; 1729 #if defined(WITH_JIT_TUNING) 1730 gDvmJit.icPatchQueued++; 1731 #endif 1732 } else { 1733 /* Queue is full - just drop this patch request */ 1734 #if defined(WITH_JIT_TUNING) 1735 gDvmJit.icPatchDropped++; 1736 #endif 1737 } 1738 1739 dvmUnlockMutex(&gDvmJit.compilerICPatchLock); 1740 } 1741 #endif 1742 1743 /* 1744 * This method is called from the invoke templates for virtual and interface 1745 * methods to speculatively setup a chain to the callee. The templates are 1746 * written in assembly and have setup method, cell, and clazz at r0, r2, and 1747 * r3 respectively, so there is a unused argument in the list. Upon return one 1748 * of the following three results may happen: 1749 * 1) Chain is not setup because the callee is native. Reset the rechain 1750 * count to a big number so that it will take a long time before the next 1751 * rechain attempt to happen. 1752 * 2) Chain is not setup because the callee has not been created yet. Reset 1753 * the rechain count to a small number and retry in the near future. 1754 * 3) Enqueue the new content for the chaining cell which will be appled in 1755 * next safe point. 1756 */ 1757 const Method *dvmJitToPatchPredictedChain(const Method *method, 1758 Thread *self, 1759 PredictedChainingCell *cell, 1760 const ClassObject *clazz) 1761 { 1762 int newRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN; 1763 #if defined(WITH_SELF_VERIFICATION) 1764 newRechainCount = PREDICTED_CHAIN_COUNTER_AVOID; 1765 goto done; 1766 #else 1767 PredictedChainingCell newCell; 1768 int baseAddr, branchOffset, tgtAddr; 1769 if (dvmIsNativeMethod(method)) { 1770 UNPROTECT_CODE_CACHE(cell, sizeof(*cell)); 1771 1772 /* 1773 * Put a non-zero/bogus value in the clazz field so that it won't 1774 * trigger immediate patching and will continue to fail to match with 1775 * a real clazz pointer. 1776 */ 1777 cell->clazz = (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ; 1778 1779 UPDATE_CODE_CACHE_PATCHES(); 1780 PROTECT_CODE_CACHE(cell, sizeof(*cell)); 1781 goto done; 1782 } 1783 tgtAddr = (int) dvmJitGetTraceAddr(method->insns); 1784 1785 /* 1786 * Compilation not made yet for the callee. Reset the counter to a small 1787 * value and come back to check soon. 1788 */ 1789 if ((tgtAddr == 0) || 1790 ((void*)tgtAddr == dvmCompilerGetInterpretTemplate())) { 1791 COMPILER_TRACE_CHAINING( 1792 ALOGD("Jit Runtime: predicted chain %p to method %s%s delayed", 1793 cell, method->clazz->descriptor, method->name)); 1794 goto done; 1795 } 1796 1797 if (cell->clazz == NULL) { 1798 newRechainCount = self->icRechainCount; 1799 } 1800 1801 baseAddr = (int) cell + 4; // PC is cur_addr + 4 1802 branchOffset = tgtAddr - baseAddr; 1803 1804 newCell.branch = assembleChainingBranch(branchOffset, true); 1805 newCell.clazz = clazz; 1806 newCell.method = method; 1807 newCell.stagedClazz = NULL; 1808 1809 /* 1810 * Enter the work order to the queue and the chaining cell will be patched 1811 * the next time a safe point is entered. 1812 * 1813 * If the enqueuing fails reset the rechain count to a normal value so that 1814 * it won't get indefinitely delayed. 1815 */ 1816 inlineCachePatchEnqueue(cell, &newCell); 1817 #endif 1818 done: 1819 self->icRechainCount = newRechainCount; 1820 return method; 1821 } 1822 1823 /* 1824 * Patch the inline cache content based on the content passed from the work 1825 * order. 1826 */ 1827 void dvmCompilerPatchInlineCache(void) 1828 { 1829 int i; 1830 PredictedChainingCell *minAddr, *maxAddr; 1831 1832 /* Nothing to be done */ 1833 if (gDvmJit.compilerICPatchIndex == 0) return; 1834 1835 /* 1836 * Since all threads are already stopped we don't really need to acquire 1837 * the lock. But race condition can be easily introduced in the future w/o 1838 * paying attention so we still acquire the lock here. 1839 */ 1840 dvmLockMutex(&gDvmJit.compilerICPatchLock); 1841 1842 UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1843 1844 //ALOGD("Number of IC patch work orders: %d", gDvmJit.compilerICPatchIndex); 1845 1846 /* Initialize the min/max address range */ 1847 minAddr = (PredictedChainingCell *) 1848 ((char *) gDvmJit.codeCache + gDvmJit.codeCacheSize); 1849 maxAddr = (PredictedChainingCell *) gDvmJit.codeCache; 1850 1851 for (i = 0; i < gDvmJit.compilerICPatchIndex; i++) { 1852 ICPatchWorkOrder *workOrder = &gDvmJit.compilerICPatchQueue[i]; 1853 PredictedChainingCell *cellAddr = workOrder->cellAddr; 1854 PredictedChainingCell *cellContent = &workOrder->cellContent; 1855 ClassObject *clazz = dvmFindClassNoInit(workOrder->classDescriptor, 1856 workOrder->classLoader); 1857 1858 assert(clazz->serialNumber == workOrder->serialNumber); 1859 1860 /* Use the newly resolved clazz pointer */ 1861 cellContent->clazz = clazz; 1862 1863 COMPILER_TRACE_CHAINING( 1864 ALOGD("Jit Runtime: predicted chain %p from %s to %s (%s) " 1865 "patched", 1866 cellAddr, 1867 cellAddr->clazz->descriptor, 1868 cellContent->clazz->descriptor, 1869 cellContent->method->name)); 1870 1871 /* Patch the chaining cell */ 1872 *cellAddr = *cellContent; 1873 minAddr = (cellAddr < minAddr) ? cellAddr : minAddr; 1874 maxAddr = (cellAddr > maxAddr) ? cellAddr : maxAddr; 1875 } 1876 1877 /* Then synchronize the I/D cache */ 1878 dvmCompilerCacheFlush((long) minAddr, (long) (maxAddr+1), 0); 1879 UPDATE_CODE_CACHE_PATCHES(); 1880 1881 PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1882 1883 gDvmJit.compilerICPatchIndex = 0; 1884 dvmUnlockMutex(&gDvmJit.compilerICPatchLock); 1885 } 1886 1887 /* 1888 * Unchain a trace given the starting address of the translation 1889 * in the code cache. Refer to the diagram in dvmCompilerAssembleLIR. 1890 * Returns the address following the last cell unchained. Note that 1891 * the incoming codeAddr is a thumb code address, and therefore has 1892 * the low bit set. 1893 */ 1894 static u4* unchainSingle(JitEntry *trace) 1895 { 1896 const char *base = getTraceBase(trace); 1897 ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base); 1898 int cellSize = getChainCellSize(pChainCellCounts); 1899 u4* pChainCells; 1900 u4 newInst; 1901 int i,j; 1902 PredictedChainingCell *predChainCell; 1903 1904 if (cellSize == 0) 1905 return (u4 *) pChainCellCounts; 1906 1907 /* Locate the beginning of the chain cell region */ 1908 pChainCells = ((u4 *) pChainCellCounts) - cellSize - 1909 pChainCellCounts->u.count[kChainingCellGap]; 1910 1911 /* The cells are sorted in order - walk through them and reset */ 1912 for (i = 0; i < kChainingCellGap; i++) { 1913 int elemSize = CHAIN_CELL_NORMAL_SIZE >> 2; /* In 32-bit words */ 1914 if (i == kChainingCellInvokePredicted) { 1915 elemSize = CHAIN_CELL_PREDICTED_SIZE >> 2; 1916 } 1917 1918 for (j = 0; j < pChainCellCounts->u.count[i]; j++) { 1919 switch(i) { 1920 case kChainingCellNormal: 1921 case kChainingCellHot: 1922 case kChainingCellInvokeSingleton: 1923 case kChainingCellBackwardBranch: 1924 /* 1925 * Replace the 1st half-word of the cell with an 1926 * unconditional branch, leaving the 2nd half-word 1927 * untouched. This avoids problems with a thread 1928 * that is suspended between the two halves when 1929 * this unchaining takes place. 1930 */ 1931 newInst = *pChainCells; 1932 newInst &= 0xFFFF0000; 1933 newInst |= getSkeleton(kThumbBUncond); /* b offset is 0 */ 1934 *pChainCells = newInst; 1935 break; 1936 case kChainingCellInvokePredicted: 1937 predChainCell = (PredictedChainingCell *) pChainCells; 1938 /* 1939 * There could be a race on another mutator thread to use 1940 * this particular predicted cell and the check has passed 1941 * the clazz comparison. So we cannot safely wipe the 1942 * method and branch but it is safe to clear the clazz, 1943 * which serves as the key. 1944 */ 1945 predChainCell->clazz = PREDICTED_CHAIN_CLAZZ_INIT; 1946 break; 1947 default: 1948 ALOGE("Unexpected chaining type: %d", i); 1949 dvmAbort(); // dvmAbort OK here - can't safely recover 1950 } 1951 COMPILER_TRACE_CHAINING( 1952 ALOGD("Jit Runtime: unchaining %#x", (int)pChainCells)); 1953 pChainCells += elemSize; /* Advance by a fixed number of words */ 1954 } 1955 } 1956 return pChainCells; 1957 } 1958 1959 /* Unchain all translation in the cache. */ 1960 void dvmJitUnchainAll() 1961 { 1962 u4* lowAddress = NULL; 1963 u4* highAddress = NULL; 1964 if (gDvmJit.pJitEntryTable != NULL) { 1965 COMPILER_TRACE_CHAINING(LOGD("Jit Runtime: unchaining all")); 1966 dvmLockMutex(&gDvmJit.tableLock); 1967 1968 UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1969 1970 for (size_t i = 0; i < gDvmJit.jitTableSize; i++) { 1971 if (gDvmJit.pJitEntryTable[i].dPC && 1972 !gDvmJit.pJitEntryTable[i].u.info.isMethodEntry && 1973 gDvmJit.pJitEntryTable[i].codeAddress && 1974 (gDvmJit.pJitEntryTable[i].codeAddress != 1975 dvmCompilerGetInterpretTemplate())) { 1976 u4* lastAddress; 1977 lastAddress = unchainSingle(&gDvmJit.pJitEntryTable[i]); 1978 if (lowAddress == NULL || 1979 (u4*)gDvmJit.pJitEntryTable[i].codeAddress < 1980 lowAddress) 1981 lowAddress = lastAddress; 1982 if (lastAddress > highAddress) 1983 highAddress = lastAddress; 1984 } 1985 } 1986 dvmCompilerCacheFlush((long)lowAddress, (long)highAddress, 0); 1987 UPDATE_CODE_CACHE_PATCHES(); 1988 1989 PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 1990 1991 dvmUnlockMutex(&gDvmJit.tableLock); 1992 gDvmJit.translationChains = 0; 1993 } 1994 gDvmJit.hasNewChain = false; 1995 } 1996 1997 typedef struct jitProfileAddrToLine { 1998 u4 lineNum; 1999 u4 bytecodeOffset; 2000 } jitProfileAddrToLine; 2001 2002 2003 /* Callback function to track the bytecode offset/line number relationiship */ 2004 static int addrToLineCb (void *cnxt, u4 bytecodeOffset, u4 lineNum) 2005 { 2006 jitProfileAddrToLine *addrToLine = (jitProfileAddrToLine *) cnxt; 2007 2008 /* Best match so far for this offset */ 2009 if (addrToLine->bytecodeOffset >= bytecodeOffset) { 2010 addrToLine->lineNum = lineNum; 2011 } 2012 return 0; 2013 } 2014 2015 /* Dumps profile info for a single trace */ 2016 static int dumpTraceProfile(JitEntry *p, bool silent, bool reset, 2017 unsigned long sum) 2018 { 2019 int idx; 2020 2021 if (p->codeAddress == NULL) { 2022 if (!silent) 2023 ALOGD("TRACEPROFILE NULL"); 2024 return 0; 2025 } 2026 if (p->codeAddress == dvmCompilerGetInterpretTemplate()) { 2027 if (!silent) 2028 ALOGD("TRACEPROFILE INTERPRET_ONLY"); 2029 return 0; 2030 } 2031 JitTraceCounter_t count = getProfileCount(p); 2032 if (reset) { 2033 resetProfileCount(p); 2034 } 2035 if (silent) { 2036 return count; 2037 } 2038 JitTraceDescription *desc = getTraceDescriptionPointer(getTraceBase(p)); 2039 const Method *method = desc->method; 2040 char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype); 2041 jitProfileAddrToLine addrToLine = {0, desc->trace[0].info.frag.startOffset}; 2042 2043 /* 2044 * We may end up decoding the debug information for the same method 2045 * multiple times, but the tradeoff is we don't need to allocate extra 2046 * space to store the addr/line mapping. Since this is a debugging feature 2047 * and done infrequently so the slower but simpler mechanism should work 2048 * just fine. 2049 */ 2050 dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, 2051 dvmGetMethodCode(method), 2052 method->clazz->descriptor, 2053 method->prototype.protoIdx, 2054 method->accessFlags, 2055 addrToLineCb, NULL, &addrToLine); 2056 2057 ALOGD("TRACEPROFILE 0x%08x % 10d %5.2f%% [%#x(+%d), %d] %s%s;%s", 2058 (int) getTraceBase(p), 2059 count, 2060 ((float ) count) / sum * 100.0, 2061 desc->trace[0].info.frag.startOffset, 2062 desc->trace[0].info.frag.numInsts, 2063 addrToLine.lineNum, 2064 method->clazz->descriptor, method->name, methodDesc); 2065 free(methodDesc); 2066 2067 /* Find the last fragment (ie runEnd is set) */ 2068 for (idx = 0; 2069 desc->trace[idx].isCode && !desc->trace[idx].info.frag.runEnd; 2070 idx++) { 2071 } 2072 2073 /* 2074 * runEnd must comes with a JitCodeDesc frag. If isCode is false it must 2075 * be a meta info field (only used by callsite info for now). 2076 */ 2077 if (!desc->trace[idx].isCode) { 2078 const Method *method = (const Method *) 2079 desc->trace[idx+JIT_TRACE_CUR_METHOD-1].info.meta; 2080 char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype); 2081 /* Print the callee info in the trace */ 2082 ALOGD(" -> %s%s;%s", method->clazz->descriptor, method->name, 2083 methodDesc); 2084 } 2085 2086 return count; 2087 } 2088 2089 /* Create a copy of the trace descriptor of an existing compilation */ 2090 JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc, 2091 const JitEntry *knownEntry) 2092 { 2093 const JitEntry *jitEntry = knownEntry ? knownEntry 2094 : dvmJitFindEntry(pc, false); 2095 if ((jitEntry == NULL) || (jitEntry->codeAddress == 0)) 2096 return NULL; 2097 2098 JitTraceDescription *desc = 2099 getTraceDescriptionPointer(getTraceBase(jitEntry)); 2100 2101 /* Now make a copy and return */ 2102 int descSize = getTraceDescriptionSize(desc); 2103 JitTraceDescription *newCopy = (JitTraceDescription *) malloc(descSize); 2104 memcpy(newCopy, desc, descSize); 2105 return newCopy; 2106 } 2107 2108 /* qsort callback function */ 2109 static int sortTraceProfileCount(const void *entry1, const void *entry2) 2110 { 2111 const JitEntry *jitEntry1 = (const JitEntry *)entry1; 2112 const JitEntry *jitEntry2 = (const JitEntry *)entry2; 2113 2114 JitTraceCounter_t count1 = getProfileCount(jitEntry1); 2115 JitTraceCounter_t count2 = getProfileCount(jitEntry2); 2116 return (count1 == count2) ? 0 : ((count1 > count2) ? -1 : 1); 2117 } 2118 2119 /* Sort the trace profile counts and dump them */ 2120 void dvmCompilerSortAndPrintTraceProfiles() 2121 { 2122 JitEntry *sortedEntries; 2123 int numTraces = 0; 2124 unsigned long sum = 0; 2125 unsigned int i; 2126 2127 /* Make sure that the table is not changing */ 2128 dvmLockMutex(&gDvmJit.tableLock); 2129 2130 /* Sort the entries by descending order */ 2131 sortedEntries = (JitEntry *)malloc(sizeof(JitEntry) * gDvmJit.jitTableSize); 2132 if (sortedEntries == NULL) 2133 goto done; 2134 memcpy(sortedEntries, gDvmJit.pJitEntryTable, 2135 sizeof(JitEntry) * gDvmJit.jitTableSize); 2136 qsort(sortedEntries, gDvmJit.jitTableSize, sizeof(JitEntry), 2137 sortTraceProfileCount); 2138 2139 /* Analyze the sorted entries */ 2140 for (i=0; i < gDvmJit.jitTableSize; i++) { 2141 if (sortedEntries[i].dPC != 0) { 2142 sum += dumpTraceProfile(&sortedEntries[i], 2143 true /* silent */, 2144 false /* reset */, 2145 0); 2146 numTraces++; 2147 } 2148 } 2149 if (numTraces == 0) 2150 numTraces = 1; 2151 if (sum == 0) { 2152 sum = 1; 2153 } 2154 2155 ALOGD("JIT: Average execution count -> %d",(int)(sum / numTraces)); 2156 // How efficiently are we using code cache memory? Bigger is better. 2157 ALOGD("JIT: CodeCache efficiency -> %.2f",(float)sum / (float)gDvmJit.codeCacheByteUsed); 2158 2159 /* Dump the sorted entries. The count of each trace will be reset to 0. */ 2160 for (i=0; i < gDvmJit.jitTableSize; i++) { 2161 if (sortedEntries[i].dPC != 0) { 2162 dumpTraceProfile(&sortedEntries[i], 2163 false /* silent */, 2164 true /* reset */, 2165 sum); 2166 } 2167 } 2168 2169 for (i=0; i < gDvmJit.jitTableSize && i < 10; i++) { 2170 /* Stip interpreter stubs */ 2171 if (sortedEntries[i].codeAddress == dvmCompilerGetInterpretTemplate()) { 2172 continue; 2173 } 2174 JitTraceDescription* desc = 2175 dvmCopyTraceDescriptor(NULL, &sortedEntries[i]); 2176 if (desc) { 2177 dvmCompilerWorkEnqueue(sortedEntries[i].dPC, 2178 kWorkOrderTraceDebug, desc); 2179 } 2180 } 2181 2182 free(sortedEntries); 2183 done: 2184 dvmUnlockMutex(&gDvmJit.tableLock); 2185 return; 2186 } 2187 2188 static void findClassPointersSingleTrace(char *base, void (*callback)(void *)) 2189 { 2190 unsigned int chainTypeIdx, chainIdx; 2191 ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base); 2192 int cellSize = getChainCellSize(pChainCellCounts); 2193 /* Scan the chaining cells */ 2194 if (cellSize) { 2195 /* Locate the beginning of the chain cell region */ 2196 u4 *pChainCells = ((u4 *) pChainCellCounts) - cellSize - 2197 pChainCellCounts->u.count[kChainingCellGap]; 2198 /* The cells are sorted in order - walk through them */ 2199 for (chainTypeIdx = 0; chainTypeIdx < kChainingCellGap; 2200 chainTypeIdx++) { 2201 if (chainTypeIdx != kChainingCellInvokePredicted) { 2202 /* In 32-bit words */ 2203 pChainCells += (CHAIN_CELL_NORMAL_SIZE >> 2) * 2204 pChainCellCounts->u.count[chainTypeIdx]; 2205 continue; 2206 } 2207 for (chainIdx = 0; 2208 chainIdx < pChainCellCounts->u.count[chainTypeIdx]; 2209 chainIdx++) { 2210 PredictedChainingCell *cell = 2211 (PredictedChainingCell *) pChainCells; 2212 /* 2213 * Report the cell if it contains a sane class 2214 * pointer. 2215 */ 2216 if (cell->clazz != NULL && 2217 cell->clazz != 2218 (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ) { 2219 callback(&cell->clazz); 2220 } 2221 pChainCells += CHAIN_CELL_PREDICTED_SIZE >> 2; 2222 } 2223 } 2224 } 2225 2226 /* Scan the class pointer pool */ 2227 JitTraceDescription *desc = getTraceDescriptionPointer(base); 2228 int descSize = getTraceDescriptionSize(desc); 2229 int *classPointerP = (int *) ((char *) desc + descSize); 2230 int numClassPointers = *classPointerP++; 2231 for (; numClassPointers; numClassPointers--, classPointerP++) { 2232 callback(classPointerP); 2233 } 2234 } 2235 2236 /* 2237 * Scan class pointers in each translation and pass its address to the callback 2238 * function. Currently such a pointers can be found in the pointer pool and the 2239 * clazz field in the predicted chaining cells. 2240 */ 2241 void dvmJitScanAllClassPointers(void (*callback)(void *)) 2242 { 2243 UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 2244 2245 /* Handle the inflight compilation first */ 2246 if (gDvmJit.inflightBaseAddr) 2247 findClassPointersSingleTrace((char *) gDvmJit.inflightBaseAddr, 2248 callback); 2249 2250 if (gDvmJit.pJitEntryTable != NULL) { 2251 unsigned int traceIdx; 2252 dvmLockMutex(&gDvmJit.tableLock); 2253 for (traceIdx = 0; traceIdx < gDvmJit.jitTableSize; traceIdx++) { 2254 const JitEntry *entry = &gDvmJit.pJitEntryTable[traceIdx]; 2255 if (entry->dPC && 2256 !entry->u.info.isMethodEntry && 2257 entry->codeAddress && 2258 (entry->codeAddress != dvmCompilerGetInterpretTemplate())) { 2259 char *base = getTraceBase(entry); 2260 findClassPointersSingleTrace(base, callback); 2261 } 2262 } 2263 dvmUnlockMutex(&gDvmJit.tableLock); 2264 } 2265 UPDATE_CODE_CACHE_PATCHES(); 2266 2267 PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 2268 } 2269 2270 /* 2271 * Provide the final touch on the class object pointer pool to install the 2272 * actual pointers. The thread has to be in the running state. 2273 */ 2274 void dvmJitInstallClassObjectPointers(CompilationUnit *cUnit, char *codeAddress) 2275 { 2276 char *base = codeAddress - cUnit->headerSize - 2277 (cUnit->instructionSet == DALVIK_JIT_ARM ? 0 : 1); 2278 2279 /* Scan the class pointer pool */ 2280 JitTraceDescription *desc = getTraceDescriptionPointer(base); 2281 int descSize = getTraceDescriptionSize(desc); 2282 intptr_t *classPointerP = (int *) ((char *) desc + descSize); 2283 int numClassPointers = *(int *)classPointerP++; 2284 intptr_t *startClassPointerP = classPointerP; 2285 2286 /* 2287 * Change the thread state to VM_RUNNING so that GC won't be happening 2288 * when the assembler looks up the class pointers. May suspend the current 2289 * thread if there is a pending request before the state is actually 2290 * changed to RUNNING. 2291 */ 2292 dvmChangeStatus(gDvmJit.compilerThread, THREAD_RUNNING); 2293 2294 /* 2295 * Unprotecting the code cache will need to acquire the code cache 2296 * protection lock first. Doing so after the state change may increase the 2297 * time spent in the RUNNING state (which may delay the next GC request 2298 * should there be contention on codeCacheProtectionLock). In practice 2299 * this is probably not going to happen often since a GC is just served. 2300 * More importantly, acquiring the lock before the state change will 2301 * cause deadlock (b/4192964). 2302 */ 2303 UNPROTECT_CODE_CACHE(startClassPointerP, 2304 numClassPointers * sizeof(intptr_t)); 2305 #if defined(WITH_JIT_TUNING) 2306 u8 startTime = dvmGetRelativeTimeUsec(); 2307 #endif 2308 for (;numClassPointers; numClassPointers--) { 2309 CallsiteInfo *callsiteInfo = (CallsiteInfo *) *classPointerP; 2310 ClassObject *clazz = dvmFindClassNoInit( 2311 callsiteInfo->classDescriptor, callsiteInfo->classLoader); 2312 assert(!strcmp(clazz->descriptor, callsiteInfo->classDescriptor)); 2313 *classPointerP++ = (intptr_t) clazz; 2314 } 2315 2316 /* 2317 * Register the base address so that if GC kicks in after the thread state 2318 * has been changed to VMWAIT and before the compiled code is registered 2319 * in the JIT table, its content can be patched if class objects are 2320 * moved. 2321 */ 2322 gDvmJit.inflightBaseAddr = base; 2323 2324 #if defined(WITH_JIT_TUNING) 2325 u8 blockTime = dvmGetRelativeTimeUsec() - startTime; 2326 gDvmJit.compilerThreadBlockGCTime += blockTime; 2327 if (blockTime > gDvmJit.maxCompilerThreadBlockGCTime) 2328 gDvmJit.maxCompilerThreadBlockGCTime = blockTime; 2329 gDvmJit.numCompilerThreadBlockGC++; 2330 #endif 2331 UPDATE_CODE_CACHE_PATCHES(); 2332 2333 PROTECT_CODE_CACHE(startClassPointerP, numClassPointers * sizeof(intptr_t)); 2334 2335 /* Change the thread state back to VMWAIT */ 2336 dvmChangeStatus(gDvmJit.compilerThread, THREAD_VMWAIT); 2337 } 2338 2339 #if defined(WITH_SELF_VERIFICATION) 2340 /* 2341 * The following are used to keep compiled loads and stores from modifying 2342 * memory during self verification mode. 2343 * 2344 * Stores do not modify memory. Instead, the address and value pair are stored 2345 * into heapSpace. Addresses within heapSpace are unique. For accesses smaller 2346 * than a word, the word containing the address is loaded first before being 2347 * updated. 2348 * 2349 * Loads check heapSpace first and return data from there if an entry exists. 2350 * Otherwise, data is loaded from memory as usual. 2351 */ 2352 2353 /* Used to specify sizes of memory operations */ 2354 enum { 2355 kSVByte, 2356 kSVSignedByte, 2357 kSVHalfword, 2358 kSVSignedHalfword, 2359 kSVWord, 2360 kSVDoubleword, 2361 kSVVariable, 2362 }; 2363 2364 /* Load the value of a decoded register from the stack */ 2365 static int selfVerificationMemRegLoad(int* sp, int reg) 2366 { 2367 return *(sp + reg); 2368 } 2369 2370 /* Load the value of a decoded doubleword register from the stack */ 2371 static s8 selfVerificationMemRegLoadDouble(int* sp, int reg) 2372 { 2373 return *((s8*)(sp + reg)); 2374 } 2375 2376 /* Store the value of a decoded register out to the stack */ 2377 static void selfVerificationMemRegStore(int* sp, int data, int reg) 2378 { 2379 *(sp + reg) = data; 2380 } 2381 2382 /* Store the value of a decoded doubleword register out to the stack */ 2383 static void selfVerificationMemRegStoreDouble(int* sp, s8 data, int reg) 2384 { 2385 *((s8*)(sp + reg)) = data; 2386 } 2387 2388 /* 2389 * Load the specified size of data from the specified address, checking 2390 * heapSpace first if Self Verification mode wrote to it previously, and 2391 * falling back to actual memory otherwise. 2392 */ 2393 static int selfVerificationLoad(int addr, int size) 2394 { 2395 Thread *self = dvmThreadSelf(); 2396 ShadowSpace *shadowSpace = self->shadowSpace; 2397 ShadowHeap *heapSpacePtr; 2398 2399 int data; 2400 int maskedAddr = addr & 0xFFFFFFFC; 2401 int alignment = addr & 0x3; 2402 2403 for (heapSpacePtr = shadowSpace->heapSpace; 2404 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 2405 if (heapSpacePtr->addr == maskedAddr) { 2406 addr = ((unsigned int) &(heapSpacePtr->data)) | alignment; 2407 break; 2408 } 2409 } 2410 2411 switch (size) { 2412 case kSVByte: 2413 data = *((u1*) addr); 2414 break; 2415 case kSVSignedByte: 2416 data = *((s1*) addr); 2417 break; 2418 case kSVHalfword: 2419 data = *((u2*) addr); 2420 break; 2421 case kSVSignedHalfword: 2422 data = *((s2*) addr); 2423 break; 2424 case kSVWord: 2425 data = *((u4*) addr); 2426 break; 2427 default: 2428 ALOGE("*** ERROR: BAD SIZE IN selfVerificationLoad: %d", size); 2429 data = 0; 2430 dvmAbort(); 2431 } 2432 2433 //ALOGD("*** HEAP LOAD: Addr: %#x Data: %#x Size: %d", addr, data, size); 2434 return data; 2435 } 2436 2437 /* Like selfVerificationLoad, but specifically for doublewords */ 2438 static s8 selfVerificationLoadDoubleword(int addr) 2439 { 2440 Thread *self = dvmThreadSelf(); 2441 ShadowSpace* shadowSpace = self->shadowSpace; 2442 ShadowHeap* heapSpacePtr; 2443 2444 int addr2 = addr+4; 2445 unsigned int data = *((unsigned int*) addr); 2446 unsigned int data2 = *((unsigned int*) addr2); 2447 2448 for (heapSpacePtr = shadowSpace->heapSpace; 2449 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 2450 if (heapSpacePtr->addr == addr) { 2451 data = heapSpacePtr->data; 2452 } else if (heapSpacePtr->addr == addr2) { 2453 data2 = heapSpacePtr->data; 2454 } 2455 } 2456 2457 //ALOGD("*** HEAP LOAD DOUBLEWORD: Addr: %#x Data: %#x Data2: %#x", 2458 // addr, data, data2); 2459 return (((s8) data2) << 32) | data; 2460 } 2461 2462 /* 2463 * Handles a store of a specified size of data to a specified address. 2464 * This gets logged as an addr/data pair in heapSpace instead of modifying 2465 * memory. Addresses in heapSpace are unique, and accesses smaller than a 2466 * word pull the entire word from memory first before updating. 2467 */ 2468 static void selfVerificationStore(int addr, int data, int size) 2469 { 2470 Thread *self = dvmThreadSelf(); 2471 ShadowSpace *shadowSpace = self->shadowSpace; 2472 ShadowHeap *heapSpacePtr; 2473 2474 int maskedAddr = addr & 0xFFFFFFFC; 2475 int alignment = addr & 0x3; 2476 2477 //ALOGD("*** HEAP STORE: Addr: %#x Data: %#x Size: %d", addr, data, size); 2478 2479 for (heapSpacePtr = shadowSpace->heapSpace; 2480 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 2481 if (heapSpacePtr->addr == maskedAddr) break; 2482 } 2483 2484 if (heapSpacePtr == shadowSpace->heapSpaceTail) { 2485 heapSpacePtr->addr = maskedAddr; 2486 heapSpacePtr->data = *((unsigned int*) maskedAddr); 2487 shadowSpace->heapSpaceTail++; 2488 } 2489 2490 addr = ((unsigned int) &(heapSpacePtr->data)) | alignment; 2491 switch (size) { 2492 case kSVByte: 2493 *((u1*) addr) = data; 2494 break; 2495 case kSVSignedByte: 2496 *((s1*) addr) = data; 2497 break; 2498 case kSVHalfword: 2499 *((u2*) addr) = data; 2500 break; 2501 case kSVSignedHalfword: 2502 *((s2*) addr) = data; 2503 break; 2504 case kSVWord: 2505 *((u4*) addr) = data; 2506 break; 2507 default: 2508 ALOGE("*** ERROR: BAD SIZE IN selfVerificationSave: %d", size); 2509 dvmAbort(); 2510 } 2511 } 2512 2513 /* Like selfVerificationStore, but specifically for doublewords */ 2514 static void selfVerificationStoreDoubleword(int addr, s8 double_data) 2515 { 2516 Thread *self = dvmThreadSelf(); 2517 ShadowSpace *shadowSpace = self->shadowSpace; 2518 ShadowHeap *heapSpacePtr; 2519 2520 int addr2 = addr+4; 2521 int data = double_data; 2522 int data2 = double_data >> 32; 2523 bool store1 = false, store2 = false; 2524 2525 //ALOGD("*** HEAP STORE DOUBLEWORD: Addr: %#x Data: %#x, Data2: %#x", 2526 // addr, data, data2); 2527 2528 for (heapSpacePtr = shadowSpace->heapSpace; 2529 heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) { 2530 if (heapSpacePtr->addr == addr) { 2531 heapSpacePtr->data = data; 2532 store1 = true; 2533 } else if (heapSpacePtr->addr == addr2) { 2534 heapSpacePtr->data = data2; 2535 store2 = true; 2536 } 2537 } 2538 2539 if (!store1) { 2540 shadowSpace->heapSpaceTail->addr = addr; 2541 shadowSpace->heapSpaceTail->data = data; 2542 shadowSpace->heapSpaceTail++; 2543 } 2544 if (!store2) { 2545 shadowSpace->heapSpaceTail->addr = addr2; 2546 shadowSpace->heapSpaceTail->data = data2; 2547 shadowSpace->heapSpaceTail++; 2548 } 2549 } 2550 2551 /* 2552 * Decodes the memory instruction at the address specified in the link 2553 * register. All registers (r0-r12,lr) and fp registers (d0-d15) are stored 2554 * consecutively on the stack beginning at the specified stack pointer. 2555 * Calls the proper Self Verification handler for the memory instruction and 2556 * updates the link register to point past the decoded memory instruction. 2557 */ 2558 void dvmSelfVerificationMemOpDecode(int lr, int* sp) 2559 { 2560 enum { 2561 kMemOpLdrPcRel = 0x09, // ldr(3) [01001] rd[10..8] imm_8[7..0] 2562 kMemOpRRR = 0x0A, // Full opcode is 7 bits 2563 kMemOp2Single = 0x0A, // Used for Vstrs and Vldrs 2564 kMemOpRRR2 = 0x0B, // Full opcode is 7 bits 2565 kMemOp2Double = 0x0B, // Used for Vstrd and Vldrd 2566 kMemOpStrRRI5 = 0x0C, // str(1) [01100] imm_5[10..6] rn[5..3] rd[2..0] 2567 kMemOpLdrRRI5 = 0x0D, // ldr(1) [01101] imm_5[10..6] rn[5..3] rd[2..0] 2568 kMemOpStrbRRI5 = 0x0E, // strb(1) [01110] imm_5[10..6] rn[5..3] rd[2..0] 2569 kMemOpLdrbRRI5 = 0x0F, // ldrb(1) [01111] imm_5[10..6] rn[5..3] rd[2..0] 2570 kMemOpStrhRRI5 = 0x10, // strh(1) [10000] imm_5[10..6] rn[5..3] rd[2..0] 2571 kMemOpLdrhRRI5 = 0x11, // ldrh(1) [10001] imm_5[10..6] rn[5..3] rd[2..0] 2572 kMemOpLdrSpRel = 0x13, // ldr(4) [10011] rd[10..8] imm_8[7..0] 2573 kMemOpStmia = 0x18, // stmia [11000] rn[10..8] reglist [7..0] 2574 kMemOpLdmia = 0x19, // ldmia [11001] rn[10..8] reglist [7..0] 2575 kMemOpStrRRR = 0x28, // str(2) [0101000] rm[8..6] rn[5..3] rd[2..0] 2576 kMemOpStrhRRR = 0x29, // strh(2) [0101001] rm[8..6] rn[5..3] rd[2..0] 2577 kMemOpStrbRRR = 0x2A, // strb(2) [0101010] rm[8..6] rn[5..3] rd[2..0] 2578 kMemOpLdrsbRRR = 0x2B, // ldrsb [0101011] rm[8..6] rn[5..3] rd[2..0] 2579 kMemOpLdrRRR = 0x2C, // ldr(2) [0101100] rm[8..6] rn[5..3] rd[2..0] 2580 kMemOpLdrhRRR = 0x2D, // ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0] 2581 kMemOpLdrbRRR = 0x2E, // ldrb(2) [0101110] rm[8..6] rn[5..3] rd[2..0] 2582 kMemOpLdrshRRR = 0x2F, // ldrsh [0101111] rm[8..6] rn[5..3] rd[2..0] 2583 kMemOp2Stmia = 0xE88, // stmia [111010001000[ rn[19..16] mask[15..0] 2584 kMemOp2Ldmia = 0xE89, // ldmia [111010001001[ rn[19..16] mask[15..0] 2585 kMemOp2Stmia2 = 0xE8A, // stmia [111010001010[ rn[19..16] mask[15..0] 2586 kMemOp2Ldmia2 = 0xE8B, // ldmia [111010001011[ rn[19..16] mask[15..0] 2587 kMemOp2Vstr = 0xED8, // Used for Vstrs and Vstrd 2588 kMemOp2Vldr = 0xED9, // Used for Vldrs and Vldrd 2589 kMemOp2Vstr2 = 0xEDC, // Used for Vstrs and Vstrd 2590 kMemOp2Vldr2 = 0xEDD, // Used for Vstrs and Vstrd 2591 kMemOp2StrbRRR = 0xF80, /* str rt,[rn,rm,LSL #imm] [111110000000] 2592 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 2593 kMemOp2LdrbRRR = 0xF81, /* ldrb rt,[rn,rm,LSL #imm] [111110000001] 2594 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 2595 kMemOp2StrhRRR = 0xF82, /* str rt,[rn,rm,LSL #imm] [111110000010] 2596 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 2597 kMemOp2LdrhRRR = 0xF83, /* ldrh rt,[rn,rm,LSL #imm] [111110000011] 2598 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 2599 kMemOp2StrRRR = 0xF84, /* str rt,[rn,rm,LSL #imm] [111110000100] 2600 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 2601 kMemOp2LdrRRR = 0xF85, /* ldr rt,[rn,rm,LSL #imm] [111110000101] 2602 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 2603 kMemOp2StrbRRI12 = 0xF88, /* strb rt,[rn,#imm12] [111110001000] 2604 rt[15..12] rn[19..16] imm12[11..0] */ 2605 kMemOp2LdrbRRI12 = 0xF89, /* ldrb rt,[rn,#imm12] [111110001001] 2606 rt[15..12] rn[19..16] imm12[11..0] */ 2607 kMemOp2StrhRRI12 = 0xF8A, /* strh rt,[rn,#imm12] [111110001010] 2608 rt[15..12] rn[19..16] imm12[11..0] */ 2609 kMemOp2LdrhRRI12 = 0xF8B, /* ldrh rt,[rn,#imm12] [111110001011] 2610 rt[15..12] rn[19..16] imm12[11..0] */ 2611 kMemOp2StrRRI12 = 0xF8C, /* str(Imm,T3) rd,[rn,#imm12] [111110001100] 2612 rn[19..16] rt[15..12] imm12[11..0] */ 2613 kMemOp2LdrRRI12 = 0xF8D, /* ldr(Imm,T3) rd,[rn,#imm12] [111110001101] 2614 rn[19..16] rt[15..12] imm12[11..0] */ 2615 kMemOp2LdrsbRRR = 0xF91, /* ldrsb rt,[rn,rm,LSL #imm] [111110010001] 2616 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 2617 kMemOp2LdrshRRR = 0xF93, /* ldrsh rt,[rn,rm,LSL #imm] [111110010011] 2618 rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */ 2619 kMemOp2LdrsbRRI12 = 0xF99, /* ldrsb rt,[rn,#imm12] [111110011001] 2620 rt[15..12] rn[19..16] imm12[11..0] */ 2621 kMemOp2LdrshRRI12 = 0xF9B, /* ldrsh rt,[rn,#imm12] [111110011011] 2622 rt[15..12] rn[19..16] imm12[11..0] */ 2623 kMemOp2 = 0xE000, // top 3 bits set indicates Thumb2 2624 }; 2625 2626 int addr, offset, data; 2627 long long double_data; 2628 int size = kSVWord; 2629 bool store = false; 2630 unsigned int *lr_masked = (unsigned int *) (lr & 0xFFFFFFFE); 2631 unsigned int insn = *lr_masked; 2632 2633 int old_lr; 2634 old_lr = selfVerificationMemRegLoad(sp, 13); 2635 2636 if ((insn & kMemOp2) == kMemOp2) { 2637 insn = (insn << 16) | (insn >> 16); 2638 //ALOGD("*** THUMB2 - Addr: %#x Insn: %#x", lr, insn); 2639 2640 int opcode12 = (insn >> 20) & 0xFFF; 2641 int opcode4 = (insn >> 8) & 0xF; 2642 int imm2 = (insn >> 4) & 0x3; 2643 int imm8 = insn & 0xFF; 2644 int imm12 = insn & 0xFFF; 2645 int rd = (insn >> 12) & 0xF; 2646 int rm = insn & 0xF; 2647 int rn = (insn >> 16) & 0xF; 2648 int rt = (insn >> 12) & 0xF; 2649 bool wBack = true; 2650 2651 // Update the link register 2652 selfVerificationMemRegStore(sp, old_lr+4, 13); 2653 2654 // Determine whether the mem op is a store or load 2655 switch (opcode12) { 2656 case kMemOp2Stmia: 2657 case kMemOp2Stmia2: 2658 case kMemOp2Vstr: 2659 case kMemOp2Vstr2: 2660 case kMemOp2StrbRRR: 2661 case kMemOp2StrhRRR: 2662 case kMemOp2StrRRR: 2663 case kMemOp2StrbRRI12: 2664 case kMemOp2StrhRRI12: 2665 case kMemOp2StrRRI12: 2666 store = true; 2667 } 2668 2669 // Determine the size of the mem access 2670 switch (opcode12) { 2671 case kMemOp2StrbRRR: 2672 case kMemOp2LdrbRRR: 2673 case kMemOp2StrbRRI12: 2674 case kMemOp2LdrbRRI12: 2675 size = kSVByte; 2676 break; 2677 case kMemOp2LdrsbRRR: 2678 case kMemOp2LdrsbRRI12: 2679 size = kSVSignedByte; 2680 break; 2681 case kMemOp2StrhRRR: 2682 case kMemOp2LdrhRRR: 2683 case kMemOp2StrhRRI12: 2684 case kMemOp2LdrhRRI12: 2685 size = kSVHalfword; 2686 break; 2687 case kMemOp2LdrshRRR: 2688 case kMemOp2LdrshRRI12: 2689 size = kSVSignedHalfword; 2690 break; 2691 case kMemOp2Vstr: 2692 case kMemOp2Vstr2: 2693 case kMemOp2Vldr: 2694 case kMemOp2Vldr2: 2695 if (opcode4 == kMemOp2Double) size = kSVDoubleword; 2696 break; 2697 case kMemOp2Stmia: 2698 case kMemOp2Ldmia: 2699 case kMemOp2Stmia2: 2700 case kMemOp2Ldmia2: 2701 size = kSVVariable; 2702 break; 2703 } 2704 2705 // Load the value of the address 2706 addr = selfVerificationMemRegLoad(sp, rn); 2707 2708 // Figure out the offset 2709 switch (opcode12) { 2710 case kMemOp2Vstr: 2711 case kMemOp2Vstr2: 2712 case kMemOp2Vldr: 2713 case kMemOp2Vldr2: 2714 offset = imm8 << 2; 2715 if (opcode4 == kMemOp2Single) { 2716 rt = rd << 1; 2717 if (insn & 0x400000) rt |= 0x1; 2718 } else if (opcode4 == kMemOp2Double) { 2719 if (insn & 0x400000) rt |= 0x10; 2720 rt = rt << 1; 2721 } else { 2722 ALOGE("*** ERROR: UNRECOGNIZED VECTOR MEM OP: %x", opcode4); 2723 dvmAbort(); 2724 } 2725 rt += 14; 2726 break; 2727 case kMemOp2StrbRRR: 2728 case kMemOp2LdrbRRR: 2729 case kMemOp2StrhRRR: 2730 case kMemOp2LdrhRRR: 2731 case kMemOp2StrRRR: 2732 case kMemOp2LdrRRR: 2733 case kMemOp2LdrsbRRR: 2734 case kMemOp2LdrshRRR: 2735 offset = selfVerificationMemRegLoad(sp, rm) << imm2; 2736 break; 2737 case kMemOp2StrbRRI12: 2738 case kMemOp2LdrbRRI12: 2739 case kMemOp2StrhRRI12: 2740 case kMemOp2LdrhRRI12: 2741 case kMemOp2StrRRI12: 2742 case kMemOp2LdrRRI12: 2743 case kMemOp2LdrsbRRI12: 2744 case kMemOp2LdrshRRI12: 2745 offset = imm12; 2746 break; 2747 case kMemOp2Stmia: 2748 case kMemOp2Ldmia: 2749 wBack = false; 2750 case kMemOp2Stmia2: 2751 case kMemOp2Ldmia2: 2752 offset = 0; 2753 break; 2754 default: 2755 ALOGE("*** ERROR: UNRECOGNIZED THUMB2 MEM OP: %x", opcode12); 2756 offset = 0; 2757 dvmAbort(); 2758 } 2759 2760 // Handle the decoded mem op accordingly 2761 if (store) { 2762 if (size == kSVVariable) { 2763 ALOGD("*** THUMB2 STMIA CURRENTLY UNUSED (AND UNTESTED)"); 2764 int i; 2765 int regList = insn & 0xFFFF; 2766 for (i = 0; i < 16; i++) { 2767 if (regList & 0x1) { 2768 data = selfVerificationMemRegLoad(sp, i); 2769 selfVerificationStore(addr, data, kSVWord); 2770 addr += 4; 2771 } 2772 regList = regList >> 1; 2773 } 2774 if (wBack) selfVerificationMemRegStore(sp, addr, rn); 2775 } else if (size == kSVDoubleword) { 2776 double_data = selfVerificationMemRegLoadDouble(sp, rt); 2777 selfVerificationStoreDoubleword(addr+offset, double_data); 2778 } else { 2779 data = selfVerificationMemRegLoad(sp, rt); 2780 selfVerificationStore(addr+offset, data, size); 2781 } 2782 } else { 2783 if (size == kSVVariable) { 2784 ALOGD("*** THUMB2 LDMIA CURRENTLY UNUSED (AND UNTESTED)"); 2785 int i; 2786 int regList = insn & 0xFFFF; 2787 for (i = 0; i < 16; i++) { 2788 if (regList & 0x1) { 2789 data = selfVerificationLoad(addr, kSVWord); 2790 selfVerificationMemRegStore(sp, data, i); 2791 addr += 4; 2792 } 2793 regList = regList >> 1; 2794 } 2795 if (wBack) selfVerificationMemRegStore(sp, addr, rn); 2796 } else if (size == kSVDoubleword) { 2797 double_data = selfVerificationLoadDoubleword(addr+offset); 2798 selfVerificationMemRegStoreDouble(sp, double_data, rt); 2799 } else { 2800 data = selfVerificationLoad(addr+offset, size); 2801 selfVerificationMemRegStore(sp, data, rt); 2802 } 2803 } 2804 } else { 2805 //ALOGD("*** THUMB - Addr: %#x Insn: %#x", lr, insn); 2806 2807 // Update the link register 2808 selfVerificationMemRegStore(sp, old_lr+2, 13); 2809 2810 int opcode5 = (insn >> 11) & 0x1F; 2811 int opcode7 = (insn >> 9) & 0x7F; 2812 int imm = (insn >> 6) & 0x1F; 2813 int rd = (insn >> 8) & 0x7; 2814 int rm = (insn >> 6) & 0x7; 2815 int rn = (insn >> 3) & 0x7; 2816 int rt = insn & 0x7; 2817 2818 // Determine whether the mem op is a store or load 2819 switch (opcode5) { 2820 case kMemOpRRR: 2821 switch (opcode7) { 2822 case kMemOpStrRRR: 2823 case kMemOpStrhRRR: 2824 case kMemOpStrbRRR: 2825 store = true; 2826 } 2827 break; 2828 case kMemOpStrRRI5: 2829 case kMemOpStrbRRI5: 2830 case kMemOpStrhRRI5: 2831 case kMemOpStmia: 2832 store = true; 2833 } 2834 2835 // Determine the size of the mem access 2836 switch (opcode5) { 2837 case kMemOpRRR: 2838 case kMemOpRRR2: 2839 switch (opcode7) { 2840 case kMemOpStrbRRR: 2841 case kMemOpLdrbRRR: 2842 size = kSVByte; 2843 break; 2844 case kMemOpLdrsbRRR: 2845 size = kSVSignedByte; 2846 break; 2847 case kMemOpStrhRRR: 2848 case kMemOpLdrhRRR: 2849 size = kSVHalfword; 2850 break; 2851 case kMemOpLdrshRRR: 2852 size = kSVSignedHalfword; 2853 break; 2854 } 2855 break; 2856 case kMemOpStrbRRI5: 2857 case kMemOpLdrbRRI5: 2858 size = kSVByte; 2859 break; 2860 case kMemOpStrhRRI5: 2861 case kMemOpLdrhRRI5: 2862 size = kSVHalfword; 2863 break; 2864 case kMemOpStmia: 2865 case kMemOpLdmia: 2866 size = kSVVariable; 2867 break; 2868 } 2869 2870 // Load the value of the address 2871 if (opcode5 == kMemOpLdrPcRel) 2872 addr = selfVerificationMemRegLoad(sp, 4); 2873 else if (opcode5 == kMemOpStmia || opcode5 == kMemOpLdmia) 2874 addr = selfVerificationMemRegLoad(sp, rd); 2875 else 2876 addr = selfVerificationMemRegLoad(sp, rn); 2877 2878 // Figure out the offset 2879 switch (opcode5) { 2880 case kMemOpLdrPcRel: 2881 offset = (insn & 0xFF) << 2; 2882 rt = rd; 2883 break; 2884 case kMemOpRRR: 2885 case kMemOpRRR2: 2886 offset = selfVerificationMemRegLoad(sp, rm); 2887 break; 2888 case kMemOpStrRRI5: 2889 case kMemOpLdrRRI5: 2890 offset = imm << 2; 2891 break; 2892 case kMemOpStrhRRI5: 2893 case kMemOpLdrhRRI5: 2894 offset = imm << 1; 2895 break; 2896 case kMemOpStrbRRI5: 2897 case kMemOpLdrbRRI5: 2898 offset = imm; 2899 break; 2900 case kMemOpStmia: 2901 case kMemOpLdmia: 2902 offset = 0; 2903 break; 2904 default: 2905 ALOGE("*** ERROR: UNRECOGNIZED THUMB MEM OP: %x", opcode5); 2906 offset = 0; 2907 dvmAbort(); 2908 } 2909 2910 // Handle the decoded mem op accordingly 2911 if (store) { 2912 if (size == kSVVariable) { 2913 int i; 2914 int regList = insn & 0xFF; 2915 for (i = 0; i < 8; i++) { 2916 if (regList & 0x1) { 2917 data = selfVerificationMemRegLoad(sp, i); 2918 selfVerificationStore(addr, data, kSVWord); 2919 addr += 4; 2920 } 2921 regList = regList >> 1; 2922 } 2923 selfVerificationMemRegStore(sp, addr, rd); 2924 } else { 2925 data = selfVerificationMemRegLoad(sp, rt); 2926 selfVerificationStore(addr+offset, data, size); 2927 } 2928 } else { 2929 if (size == kSVVariable) { 2930 bool wBack = true; 2931 int i; 2932 int regList = insn & 0xFF; 2933 for (i = 0; i < 8; i++) { 2934 if (regList & 0x1) { 2935 if (i == rd) wBack = false; 2936 data = selfVerificationLoad(addr, kSVWord); 2937 selfVerificationMemRegStore(sp, data, i); 2938 addr += 4; 2939 } 2940 regList = regList >> 1; 2941 } 2942 if (wBack) selfVerificationMemRegStore(sp, addr, rd); 2943 } else { 2944 data = selfVerificationLoad(addr+offset, size); 2945 selfVerificationMemRegStore(sp, data, rt); 2946 } 2947 } 2948 } 2949 } 2950 #endif 2951