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