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