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