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/compiler_internals.h"
     19 #include "dex/quick/mir_to_lir-inl.h"
     20 #include "mips_lir.h"
     21 
     22 #include <string>
     23 
     24 namespace art {
     25 
     26 static int core_regs[] = {r_ZERO, r_AT, r_V0, r_V1, r_A0, r_A1, r_A2, r_A3,
     27                           r_T0, r_T1, r_T2, r_T3, r_T4, r_T5, r_T6, r_T7,
     28                           r_S0, r_S1, r_S2, r_S3, r_S4, r_S5, r_S6, r_S7, r_T8,
     29                           r_T9, r_K0, r_K1, r_GP, r_SP, r_FP, r_RA};
     30 static int ReservedRegs[] = {r_ZERO, r_AT, r_S0, r_S1, r_K0, r_K1, r_GP, r_SP,
     31                              r_RA};
     32 static int core_temps[] = {r_V0, r_V1, r_A0, r_A1, r_A2, r_A3, r_T0, r_T1, r_T2,
     33                            r_T3, r_T4, r_T5, r_T6, r_T7, r_T8};
     34 static int FpRegs[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
     35                        r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
     36 static int fp_temps[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
     37                          r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
     38 
     39 RegLocation MipsMir2Lir::LocCReturn() {
     40   RegLocation res = MIPS_LOC_C_RETURN;
     41   return res;
     42 }
     43 
     44 RegLocation MipsMir2Lir::LocCReturnWide() {
     45   RegLocation res = MIPS_LOC_C_RETURN_WIDE;
     46   return res;
     47 }
     48 
     49 RegLocation MipsMir2Lir::LocCReturnFloat() {
     50   RegLocation res = MIPS_LOC_C_RETURN_FLOAT;
     51   return res;
     52 }
     53 
     54 RegLocation MipsMir2Lir::LocCReturnDouble() {
     55   RegLocation res = MIPS_LOC_C_RETURN_DOUBLE;
     56   return res;
     57 }
     58 
     59 // Return a target-dependent special register.
     60 int MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
     61   int res = INVALID_REG;
     62   switch (reg) {
     63     case kSelf: res = rMIPS_SELF; break;
     64     case kSuspend: res =  rMIPS_SUSPEND; break;
     65     case kLr: res =  rMIPS_LR; break;
     66     case kPc: res =  rMIPS_PC; break;
     67     case kSp: res =  rMIPS_SP; break;
     68     case kArg0: res = rMIPS_ARG0; break;
     69     case kArg1: res = rMIPS_ARG1; break;
     70     case kArg2: res = rMIPS_ARG2; break;
     71     case kArg3: res = rMIPS_ARG3; break;
     72     case kFArg0: res = rMIPS_FARG0; break;
     73     case kFArg1: res = rMIPS_FARG1; break;
     74     case kFArg2: res = rMIPS_FARG2; break;
     75     case kFArg3: res = rMIPS_FARG3; break;
     76     case kRet0: res = rMIPS_RET0; break;
     77     case kRet1: res = rMIPS_RET1; break;
     78     case kInvokeTgt: res = rMIPS_INVOKE_TGT; break;
     79     case kCount: res = rMIPS_COUNT; break;
     80   }
     81   return res;
     82 }
     83 
     84 // Create a double from a pair of singles.
     85 int MipsMir2Lir::S2d(int low_reg, int high_reg) {
     86   return MIPS_S2D(low_reg, high_reg);
     87 }
     88 
     89 // Return mask to strip off fp reg flags and bias.
     90 uint32_t MipsMir2Lir::FpRegMask() {
     91   return MIPS_FP_REG_MASK;
     92 }
     93 
     94 // True if both regs single, both core or both double.
     95 bool MipsMir2Lir::SameRegType(int reg1, int reg2) {
     96   return (MIPS_REGTYPE(reg1) == MIPS_REGTYPE(reg2));
     97 }
     98 
     99 /*
    100  * Decode the register id.
    101  */
    102 uint64_t MipsMir2Lir::GetRegMaskCommon(int reg) {
    103   uint64_t seed;
    104   int shift;
    105   int reg_id;
    106 
    107 
    108   reg_id = reg & 0x1f;
    109   /* Each double register is equal to a pair of single-precision FP registers */
    110   seed = MIPS_DOUBLEREG(reg) ? 3 : 1;
    111   /* FP register starts at bit position 16 */
    112   shift = MIPS_FPREG(reg) ? kMipsFPReg0 : 0;
    113   /* Expand the double register id into single offset */
    114   shift += reg_id;
    115   return (seed << shift);
    116 }
    117 
    118 uint64_t MipsMir2Lir::GetPCUseDefEncoding() {
    119   return ENCODE_MIPS_REG_PC;
    120 }
    121 
    122 
    123 void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir) {
    124   DCHECK_EQ(cu_->instruction_set, kMips);
    125 
    126   // Mips-specific resource map setup here.
    127   uint64_t flags = MipsMir2Lir::EncodingMap[lir->opcode].flags;
    128 
    129   if (flags & REG_DEF_SP) {
    130     lir->def_mask |= ENCODE_MIPS_REG_SP;
    131   }
    132 
    133   if (flags & REG_USE_SP) {
    134     lir->use_mask |= ENCODE_MIPS_REG_SP;
    135   }
    136 
    137   if (flags & REG_DEF_LR) {
    138     lir->def_mask |= ENCODE_MIPS_REG_LR;
    139   }
    140 }
    141 
    142 /* For dumping instructions */
    143 #define MIPS_REG_COUNT 32
    144 static const char *mips_reg_name[MIPS_REG_COUNT] = {
    145   "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
    146   "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
    147   "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
    148   "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
    149 };
    150 
    151 /*
    152  * Interpret a format string and build a string no longer than size
    153  * See format key in Assemble.c.
    154  */
    155 std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
    156   std::string buf;
    157   int i;
    158   const char *fmt_end = &fmt[strlen(fmt)];
    159   char tbuf[256];
    160   char nc;
    161   while (fmt < fmt_end) {
    162     int operand;
    163     if (*fmt == '!') {
    164       fmt++;
    165       DCHECK_LT(fmt, fmt_end);
    166       nc = *fmt++;
    167       if (nc == '!') {
    168         strcpy(tbuf, "!");
    169       } else {
    170          DCHECK_LT(fmt, fmt_end);
    171          DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
    172          operand = lir->operands[nc-'0'];
    173          switch (*fmt++) {
    174            case 'b':
    175              strcpy(tbuf, "0000");
    176              for (i = 3; i >= 0; i--) {
    177                tbuf[i] += operand & 1;
    178                operand >>= 1;
    179              }
    180              break;
    181            case 's':
    182              sprintf(tbuf, "$f%d", operand & MIPS_FP_REG_MASK);
    183              break;
    184            case 'S':
    185              DCHECK_EQ(((operand & MIPS_FP_REG_MASK) & 1), 0);
    186              sprintf(tbuf, "$f%d", operand & MIPS_FP_REG_MASK);
    187              break;
    188            case 'h':
    189              sprintf(tbuf, "%04x", operand);
    190              break;
    191            case 'M':
    192            case 'd':
    193              sprintf(tbuf, "%d", operand);
    194              break;
    195            case 'D':
    196              sprintf(tbuf, "%d", operand+1);
    197              break;
    198            case 'E':
    199              sprintf(tbuf, "%d", operand*4);
    200              break;
    201            case 'F':
    202              sprintf(tbuf, "%d", operand*2);
    203              break;
    204            case 't':
    205              sprintf(tbuf, "0x%08x (L%p)", reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 +
    206                      (operand << 2), lir->target);
    207              break;
    208            case 'T':
    209              sprintf(tbuf, "0x%08x", operand << 2);
    210              break;
    211            case 'u': {
    212              int offset_1 = lir->operands[0];
    213              int offset_2 = NEXT_LIR(lir)->operands[0];
    214              uintptr_t target =
    215                  (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
    216                  (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
    217              sprintf(tbuf, "%p", reinterpret_cast<void*>(target));
    218              break;
    219           }
    220 
    221            /* Nothing to print for BLX_2 */
    222            case 'v':
    223              strcpy(tbuf, "see above");
    224              break;
    225            case 'r':
    226              DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
    227              strcpy(tbuf, mips_reg_name[operand]);
    228              break;
    229            case 'N':
    230              // Placeholder for delay slot handling
    231              strcpy(tbuf, ";  nop");
    232              break;
    233            default:
    234              strcpy(tbuf, "DecodeError");
    235              break;
    236          }
    237          buf += tbuf;
    238       }
    239     } else {
    240        buf += *fmt++;
    241     }
    242   }
    243   return buf;
    244 }
    245 
    246 // FIXME: need to redo resource maps for MIPS - fix this at that time
    247 void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) {
    248   char buf[256];
    249   buf[0] = 0;
    250 
    251   if (mask == ENCODE_ALL) {
    252     strcpy(buf, "all");
    253   } else {
    254     char num[8];
    255     int i;
    256 
    257     for (i = 0; i < kMipsRegEnd; i++) {
    258       if (mask & (1ULL << i)) {
    259         sprintf(num, "%d ", i);
    260         strcat(buf, num);
    261       }
    262     }
    263 
    264     if (mask & ENCODE_CCODE) {
    265       strcat(buf, "cc ");
    266     }
    267     if (mask & ENCODE_FP_STATUS) {
    268       strcat(buf, "fpcc ");
    269     }
    270     /* Memory bits */
    271     if (mips_lir && (mask & ENCODE_DALVIK_REG)) {
    272       sprintf(buf + strlen(buf), "dr%d%s", mips_lir->alias_info & 0xffff,
    273               (mips_lir->alias_info & 0x80000000) ? "(+1)" : "");
    274     }
    275     if (mask & ENCODE_LITERAL) {
    276       strcat(buf, "lit ");
    277     }
    278 
    279     if (mask & ENCODE_HEAP_REF) {
    280       strcat(buf, "heap ");
    281     }
    282     if (mask & ENCODE_MUST_NOT_ALIAS) {
    283       strcat(buf, "noalias ");
    284     }
    285   }
    286   if (buf[0]) {
    287     LOG(INFO) << prefix << ": " <<  buf;
    288   }
    289 }
    290 
    291 /*
    292  * TUNING: is true leaf?  Can't just use METHOD_IS_LEAF to determine as some
    293  * instructions might call out to C/assembly helper functions.  Until
    294  * machinery is in place, always spill lr.
    295  */
    296 
    297 void MipsMir2Lir::AdjustSpillMask() {
    298   core_spill_mask_ |= (1 << r_RA);
    299   num_core_spills_++;
    300 }
    301 
    302 /*
    303  * Mark a callee-save fp register as promoted.  Note that
    304  * vpush/vpop uses contiguous register lists so we must
    305  * include any holes in the mask.  Associate holes with
    306  * Dalvik register INVALID_VREG (0xFFFFU).
    307  */
    308 void MipsMir2Lir::MarkPreservedSingle(int s_reg, int reg) {
    309   LOG(FATAL) << "No support yet for promoted FP regs";
    310 }
    311 
    312 void MipsMir2Lir::FlushRegWide(int reg1, int reg2) {
    313   RegisterInfo* info1 = GetRegInfo(reg1);
    314   RegisterInfo* info2 = GetRegInfo(reg2);
    315   DCHECK(info1 && info2 && info1->pair && info2->pair &&
    316          (info1->partner == info2->reg) &&
    317          (info2->partner == info1->reg));
    318   if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
    319     if (!(info1->is_temp && info2->is_temp)) {
    320       /* Should not happen.  If it does, there's a problem in eval_loc */
    321       LOG(FATAL) << "Long half-temp, half-promoted";
    322     }
    323 
    324     info1->dirty = false;
    325     info2->dirty = false;
    326     if (mir_graph_->SRegToVReg(info2->s_reg) < mir_graph_->SRegToVReg(info1->s_reg))
    327       info1 = info2;
    328     int v_reg = mir_graph_->SRegToVReg(info1->s_reg);
    329     StoreBaseDispWide(rMIPS_SP, VRegOffset(v_reg), info1->reg, info1->partner);
    330   }
    331 }
    332 
    333 void MipsMir2Lir::FlushReg(int reg) {
    334   RegisterInfo* info = GetRegInfo(reg);
    335   if (info->live && info->dirty) {
    336     info->dirty = false;
    337     int v_reg = mir_graph_->SRegToVReg(info->s_reg);
    338     StoreBaseDisp(rMIPS_SP, VRegOffset(v_reg), reg, kWord);
    339   }
    340 }
    341 
    342 /* Give access to the target-dependent FP register encoding to common code */
    343 bool MipsMir2Lir::IsFpReg(int reg) {
    344   return MIPS_FPREG(reg);
    345 }
    346 
    347 /* Clobber all regs that might be used by an external C call */
    348 void MipsMir2Lir::ClobberCalleeSave() {
    349   Clobber(r_ZERO);
    350   Clobber(r_AT);
    351   Clobber(r_V0);
    352   Clobber(r_V1);
    353   Clobber(r_A0);
    354   Clobber(r_A1);
    355   Clobber(r_A2);
    356   Clobber(r_A3);
    357   Clobber(r_T0);
    358   Clobber(r_T1);
    359   Clobber(r_T2);
    360   Clobber(r_T3);
    361   Clobber(r_T4);
    362   Clobber(r_T5);
    363   Clobber(r_T6);
    364   Clobber(r_T7);
    365   Clobber(r_T8);
    366   Clobber(r_T9);
    367   Clobber(r_K0);
    368   Clobber(r_K1);
    369   Clobber(r_GP);
    370   Clobber(r_FP);
    371   Clobber(r_RA);
    372   Clobber(r_F0);
    373   Clobber(r_F1);
    374   Clobber(r_F2);
    375   Clobber(r_F3);
    376   Clobber(r_F4);
    377   Clobber(r_F5);
    378   Clobber(r_F6);
    379   Clobber(r_F7);
    380   Clobber(r_F8);
    381   Clobber(r_F9);
    382   Clobber(r_F10);
    383   Clobber(r_F11);
    384   Clobber(r_F12);
    385   Clobber(r_F13);
    386   Clobber(r_F14);
    387   Clobber(r_F15);
    388 }
    389 
    390 RegLocation MipsMir2Lir::GetReturnWideAlt() {
    391   UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
    392   RegLocation res = LocCReturnWide();
    393   return res;
    394 }
    395 
    396 RegLocation MipsMir2Lir::GetReturnAlt() {
    397   UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
    398   RegLocation res = LocCReturn();
    399   return res;
    400 }
    401 
    402 MipsMir2Lir::RegisterInfo* MipsMir2Lir::GetRegInfo(int reg) {
    403   return MIPS_FPREG(reg) ? &reg_pool_->FPRegs[reg & MIPS_FP_REG_MASK]
    404             : &reg_pool_->core_regs[reg];
    405 }
    406 
    407 /* To be used when explicitly managing register use */
    408 void MipsMir2Lir::LockCallTemps() {
    409   LockTemp(rMIPS_ARG0);
    410   LockTemp(rMIPS_ARG1);
    411   LockTemp(rMIPS_ARG2);
    412   LockTemp(rMIPS_ARG3);
    413 }
    414 
    415 /* To be used when explicitly managing register use */
    416 void MipsMir2Lir::FreeCallTemps() {
    417   FreeTemp(rMIPS_ARG0);
    418   FreeTemp(rMIPS_ARG1);
    419   FreeTemp(rMIPS_ARG2);
    420   FreeTemp(rMIPS_ARG3);
    421 }
    422 
    423 void MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
    424 #if ANDROID_SMP != 0
    425   NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
    426 #endif
    427 }
    428 
    429 /*
    430  * Alloc a pair of core registers, or a double.  Low reg in low byte,
    431  * high reg in next byte.
    432  */
    433 int MipsMir2Lir::AllocTypedTempPair(bool fp_hint,
    434                   int reg_class) {
    435   int high_reg;
    436   int low_reg;
    437   int res = 0;
    438 
    439   if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
    440     low_reg = AllocTempDouble();
    441     high_reg = low_reg + 1;
    442     res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
    443     return res;
    444   }
    445 
    446   low_reg = AllocTemp();
    447   high_reg = AllocTemp();
    448   res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
    449   return res;
    450 }
    451 
    452 int MipsMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
    453   if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
    454     return AllocTempFloat();
    455 }
    456   return AllocTemp();
    457 }
    458 
    459 void MipsMir2Lir::CompilerInitializeRegAlloc() {
    460   int num_regs = sizeof(core_regs)/sizeof(*core_regs);
    461   int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs);
    462   int num_temps = sizeof(core_temps)/sizeof(*core_temps);
    463   int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs);
    464   int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps);
    465   reg_pool_ = static_cast<RegisterPool*>(arena_->Alloc(sizeof(*reg_pool_),
    466                                                        ArenaAllocator::kAllocRegAlloc));
    467   reg_pool_->num_core_regs = num_regs;
    468   reg_pool_->core_regs = static_cast<RegisterInfo*>
    469      (arena_->Alloc(num_regs * sizeof(*reg_pool_->core_regs), ArenaAllocator::kAllocRegAlloc));
    470   reg_pool_->num_fp_regs = num_fp_regs;
    471   reg_pool_->FPRegs = static_cast<RegisterInfo*>
    472       (arena_->Alloc(num_fp_regs * sizeof(*reg_pool_->FPRegs), ArenaAllocator::kAllocRegAlloc));
    473   CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs);
    474   CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs);
    475   // Keep special registers from being allocated
    476   for (int i = 0; i < num_reserved; i++) {
    477     if (NO_SUSPEND && (ReservedRegs[i] == rMIPS_SUSPEND)) {
    478       // To measure cost of suspend check
    479       continue;
    480     }
    481     MarkInUse(ReservedRegs[i]);
    482   }
    483   // Mark temp regs - all others not in use can be used for promotion
    484   for (int i = 0; i < num_temps; i++) {
    485     MarkTemp(core_temps[i]);
    486   }
    487   for (int i = 0; i < num_fp_temps; i++) {
    488     MarkTemp(fp_temps[i]);
    489   }
    490 }
    491 
    492 void MipsMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
    493   if ((rl_free.low_reg != rl_keep.low_reg) && (rl_free.low_reg != rl_keep.high_reg) &&
    494     (rl_free.high_reg != rl_keep.low_reg) && (rl_free.high_reg != rl_keep.high_reg)) {
    495     // No overlap, free both
    496     FreeTemp(rl_free.low_reg);
    497     FreeTemp(rl_free.high_reg);
    498   }
    499 }
    500 /*
    501  * In the Arm code a it is typical to use the link register
    502  * to hold the target address.  However, for Mips we must
    503  * ensure that all branch instructions can be restarted if
    504  * there is a trap in the shadow.  Allocate a temp register.
    505  */
    506 int MipsMir2Lir::LoadHelper(ThreadOffset offset) {
    507   LoadWordDisp(rMIPS_SELF, offset.Int32Value(), r_T9);
    508   return r_T9;
    509 }
    510 
    511 void MipsMir2Lir::SpillCoreRegs() {
    512   if (num_core_spills_ == 0) {
    513     return;
    514   }
    515   uint32_t mask = core_spill_mask_;
    516   int offset = num_core_spills_ * 4;
    517   OpRegImm(kOpSub, rMIPS_SP, offset);
    518   for (int reg = 0; mask; mask >>= 1, reg++) {
    519     if (mask & 0x1) {
    520       offset -= 4;
    521       StoreWordDisp(rMIPS_SP, offset, reg);
    522     }
    523   }
    524 }
    525 
    526 void MipsMir2Lir::UnSpillCoreRegs() {
    527   if (num_core_spills_ == 0) {
    528     return;
    529   }
    530   uint32_t mask = core_spill_mask_;
    531   int offset = frame_size_;
    532   for (int reg = 0; mask; mask >>= 1, reg++) {
    533     if (mask & 0x1) {
    534       offset -= 4;
    535       LoadWordDisp(rMIPS_SP, offset, reg);
    536     }
    537   }
    538   OpRegImm(kOpAdd, rMIPS_SP, frame_size_);
    539 }
    540 
    541 bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
    542   return (lir->opcode == kMipsB);
    543 }
    544 
    545 MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
    546     : Mir2Lir(cu, mir_graph, arena) {
    547   for (int i = 0; i < kMipsLast; i++) {
    548     if (MipsMir2Lir::EncodingMap[i].opcode != i) {
    549       LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
    550                  << " is wrong: expecting " << i << ", seeing "
    551                  << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
    552     }
    553   }
    554 }
    555 
    556 Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
    557                            ArenaAllocator* const arena) {
    558   return new MipsMir2Lir(cu, mir_graph, arena);
    559 }
    560 
    561 uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
    562   return MipsMir2Lir::EncodingMap[opcode].flags;
    563 }
    564 
    565 const char* MipsMir2Lir::GetTargetInstName(int opcode) {
    566   return MipsMir2Lir::EncodingMap[opcode].name;
    567 }
    568 
    569 const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
    570   return MipsMir2Lir::EncodingMap[opcode].fmt;
    571 }
    572 
    573 }  // namespace art
    574