1efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
2efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Copyright (C) 2012 The Android Open Source Project
3efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
4efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Licensed under the Apache License, Version 2.0 (the "License");
5efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * you may not use this file except in compliance with the License.
6efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * You may obtain a copy of the License at
7efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
8efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *      http://www.apache.org/licenses/LICENSE-2.0
9efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
10efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Unless required by applicable law or agreed to in writing, software
11efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * distributed under the License is distributed on an "AS IS" BASIS,
12efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See the License for the specific language governing permissions and
14efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * limitations under the License.
15efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
16efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1702031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_mips.h"
18107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers
19107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers#include <inttypes.h>
20107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers
21107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers#include <string>
22107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers
237940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/compiler_internals.h"
247940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h"
25641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "mips_lir.h"
26efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
27efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art {
28efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
29089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr[] =
30091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    {rs_rZERO, rs_rAT, rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rT0, rs_rT1, rs_rT2,
31091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee     rs_rT3, rs_rT4, rs_rT5, rs_rT6, rs_rT7, rs_rS0, rs_rS1, rs_rS2, rs_rS3, rs_rS4, rs_rS5,
32091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee     rs_rS6, rs_rS7, rs_rT8, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rFP, rs_rRA};
33089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_regs_arr[] =
34091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
35091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee     rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15};
36089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_regs_arr[] =
37091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7};
38089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage reserved_regs_arr[] =
39091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    {rs_rZERO, rs_rAT, rs_rS0, rs_rS1, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rRA};
40089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr[] =
41091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    {rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rT0, rs_rT1, rs_rT2, rs_rT3, rs_rT4,
42091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee     rs_rT5, rs_rT6, rs_rT7, rs_rT8};
43089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_temps_arr[] =
44091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
45091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee     rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15};
46089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_temps_arr[] =
47091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7};
48091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
49089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> empty_pool;
50089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs(core_regs_arr);
51089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_regs(sp_regs_arr);
52089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_regs(dp_regs_arr);
53089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs(reserved_regs_arr);
54089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps(core_temps_arr);
55089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_temps(sp_temps_arr);
56089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_temps(dp_temps_arr);
57efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
582ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation MipsMir2Lir::LocCReturn() {
5900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  return mips_loc_c_return;
60efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
61efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
62a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbeeRegLocation MipsMir2Lir::LocCReturnRef() {
63a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee  return mips_loc_c_return;
64a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee}
65a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee
662ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation MipsMir2Lir::LocCReturnWide() {
6700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  return mips_loc_c_return_wide;
68efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
69efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
702ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation MipsMir2Lir::LocCReturnFloat() {
7100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  return mips_loc_c_return_float;
72efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
73efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
742ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation MipsMir2Lir::LocCReturnDouble() {
7500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  return mips_loc_c_return_double;
76efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
77efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
782db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung// Convert k64BitSolo into k64BitPair
792db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas LeungRegStorage MipsMir2Lir::Solo64ToPair64(RegStorage reg) {
802db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung    DCHECK(reg.IsDouble());
812db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung    int reg_num = (reg.GetRegNum() & ~1) | RegStorage::kFloatingPoint;
822db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung    return RegStorage(RegStorage::k64BitPair, reg_num, reg_num + 1);
832db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung}
842db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung
85efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Return a target-dependent special register.
862700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeRegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
87091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  RegStorage res_reg;
88efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  switch (reg) {
89091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kSelf: res_reg = rs_rMIPS_SELF; break;
90091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kSuspend: res_reg =  rs_rMIPS_SUSPEND; break;
91091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kLr: res_reg =  rs_rMIPS_LR; break;
92091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kPc: res_reg =  rs_rMIPS_PC; break;
93091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kSp: res_reg =  rs_rMIPS_SP; break;
94091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kArg0: res_reg = rs_rMIPS_ARG0; break;
95091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kArg1: res_reg = rs_rMIPS_ARG1; break;
96091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kArg2: res_reg = rs_rMIPS_ARG2; break;
97091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kArg3: res_reg = rs_rMIPS_ARG3; break;
98091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kFArg0: res_reg = rs_rMIPS_FARG0; break;
99091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kFArg1: res_reg = rs_rMIPS_FARG1; break;
100091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kFArg2: res_reg = rs_rMIPS_FARG2; break;
101091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kFArg3: res_reg = rs_rMIPS_FARG3; break;
102091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kRet0: res_reg = rs_rMIPS_RET0; break;
103091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kRet1: res_reg = rs_rMIPS_RET1; break;
104091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kInvokeTgt: res_reg = rs_rMIPS_INVOKE_TGT; break;
105091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kHiddenArg: res_reg = rs_rT0; break;
106091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
107091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kCount: res_reg = rs_rMIPS_COUNT; break;
10858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    default: res_reg = RegStorage::InvalidReg();
109efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
110091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  return res_reg;
111efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
112efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1132700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeRegStorage MipsMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
1143bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
1153bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  switch (arg_num) {
1163bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru    case 0:
1172700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      return rs_rMIPS_ARG1;
1183bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru    case 1:
1192700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      return rs_rMIPS_ARG2;
1203bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru    case 2:
1212700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      return rs_rMIPS_ARG3;
1223bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru    default:
1232700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      return RegStorage::InvalidReg();
1243bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  }
1253bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru}
1263bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru
127efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
128efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Decode the register id.
129efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
1308dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir MarkoResourceMask MipsMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
1318dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  return reg.IsDouble()
1328dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko      /* Each double register is equal to a pair of single-precision FP registers */
1332db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung#if (FR_BIT == 0)
1342db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung      ? ResourceMask::TwoBits((reg.GetRegNum() & ~1) + kMipsFPReg0)
1352db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung#else
1368dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko      ? ResourceMask::TwoBits(reg.GetRegNum() * 2 + kMipsFPReg0)
1372db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung#endif
1388dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko      : ResourceMask::Bit(reg.IsSingle() ? reg.GetRegNum() + kMipsFPReg0 : reg.GetRegNum());
139efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
140efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1418dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir MarkoResourceMask MipsMir2Lir::GetPCUseDefEncoding() const {
1428dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  return ResourceMask::Bit(kMipsRegPC);
143efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
144efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
145efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1468dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Markovoid MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags,
1478dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko                                           ResourceMask* use_mask, ResourceMask* def_mask) {
1481fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(cu_->instruction_set, kMips);
149b48819db07f9a0992a72173380c24249d7fc648abuzbee  DCHECK(!lir->flags.use_def_invalid);
150efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
151efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Mips-specific resource map setup here.
152efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (flags & REG_DEF_SP) {
1538dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    def_mask->SetBit(kMipsRegSP);
154efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
155efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
156efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (flags & REG_USE_SP) {
1578dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    use_mask->SetBit(kMipsRegSP);
158efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
159efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
160efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (flags & REG_DEF_LR) {
1618dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    def_mask->SetBit(kMipsRegLR);
162efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
1639da5c1013215176f2a4dbe7a804be899e12d5f68buzbee
1649da5c1013215176f2a4dbe7a804be899e12d5f68buzbee  if (flags & REG_DEF_HI) {
1658dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    def_mask->SetBit(kMipsRegHI);
1669da5c1013215176f2a4dbe7a804be899e12d5f68buzbee  }
1679da5c1013215176f2a4dbe7a804be899e12d5f68buzbee
1689da5c1013215176f2a4dbe7a804be899e12d5f68buzbee  if (flags & REG_DEF_LO) {
1698dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    def_mask->SetBit(kMipsRegLO);
1709da5c1013215176f2a4dbe7a804be899e12d5f68buzbee  }
1719da5c1013215176f2a4dbe7a804be899e12d5f68buzbee
1729da5c1013215176f2a4dbe7a804be899e12d5f68buzbee  if (flags & REG_USE_HI) {
1738dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    use_mask->SetBit(kMipsRegHI);
1749da5c1013215176f2a4dbe7a804be899e12d5f68buzbee  }
1759da5c1013215176f2a4dbe7a804be899e12d5f68buzbee
1769da5c1013215176f2a4dbe7a804be899e12d5f68buzbee  if (flags & REG_USE_LO) {
1778dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    use_mask->SetBit(kMipsRegLO);
1789da5c1013215176f2a4dbe7a804be899e12d5f68buzbee  }
179efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
180efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
181efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* For dumping instructions */
182efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#define MIPS_REG_COUNT 32
183fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic const char *mips_reg_name[MIPS_REG_COUNT] = {
184efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
185efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
186efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
187efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
188efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
189efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
190efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
191efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Interpret a format string and build a string no longer than size
192efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See format key in Assemble.c.
193efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
1942ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstd::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
195efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  std::string buf;
196efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int i;
197fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  const char *fmt_end = &fmt[strlen(fmt)];
198efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  char tbuf[256];
199efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  char nc;
200fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (fmt < fmt_end) {
201efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    int operand;
202efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    if (*fmt == '!') {
203efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      fmt++;
204fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK_LT(fmt, fmt_end);
205efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      nc = *fmt++;
20638f85e4892f6504971bde994fec81fd61780ac30Brian Carlstrom      if (nc == '!') {
207efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        strcpy(tbuf, "!");
208efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      } else {
209fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee         DCHECK_LT(fmt, fmt_end);
210cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee         DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
211efc6369224b036a1fb77849f7ae65b3492c832c0buzbee         operand = lir->operands[nc-'0'];
212efc6369224b036a1fb77849f7ae65b3492c832c0buzbee         switch (*fmt++) {
213efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'b':
214b1eba213afaf7fa6445de863ddc9680ab99762eaBrian Carlstrom             strcpy(tbuf, "0000");
21538f85e4892f6504971bde994fec81fd61780ac30Brian Carlstrom             for (i = 3; i >= 0; i--) {
216efc6369224b036a1fb77849f7ae65b3492c832c0buzbee               tbuf[i] += operand & 1;
217efc6369224b036a1fb77849f7ae65b3492c832c0buzbee               operand >>= 1;
218efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             }
219efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
220efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 's':
221091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee             snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
222efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
223efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'S':
224091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee             DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
225091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee             snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
226efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
227efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'h':
228988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers             snprintf(tbuf, arraysize(tbuf), "%04x", operand);
229efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
230efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'M':
231efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'd':
232988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers             snprintf(tbuf, arraysize(tbuf), "%d", operand);
233efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
234efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'D':
235988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers             snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
236efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
237efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'E':
238988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers             snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
239efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
240efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'F':
241988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers             snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
242efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
243efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 't':
244107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers             snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
245107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers                 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
246107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers                 lir->target);
247efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
248efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'T':
249988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers             snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
250efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
251efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'u': {
252efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             int offset_1 = lir->operands[0];
253efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             int offset_2 = NEXT_LIR(lir)->operands[0];
254cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee             uintptr_t target =
255fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
256efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
257988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers             snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
258efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
259efc6369224b036a1fb77849f7ae65b3492c832c0buzbee          }
260efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
261efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           /* Nothing to print for BLX_2 */
262efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'v':
263efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             strcpy(tbuf, "see above");
264efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
265efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'r':
266efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
267fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee             strcpy(tbuf, mips_reg_name[operand]);
268efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
269efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           case 'N':
270efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             // Placeholder for delay slot handling
271efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             strcpy(tbuf, ";  nop");
272efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
273efc6369224b036a1fb77849f7ae65b3492c832c0buzbee           default:
274b1eba213afaf7fa6445de863ddc9680ab99762eaBrian Carlstrom             strcpy(tbuf, "DecodeError");
275efc6369224b036a1fb77849f7ae65b3492c832c0buzbee             break;
276efc6369224b036a1fb77849f7ae65b3492c832c0buzbee         }
277efc6369224b036a1fb77849f7ae65b3492c832c0buzbee         buf += tbuf;
278efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      }
279efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
280efc6369224b036a1fb77849f7ae65b3492c832c0buzbee       buf += *fmt++;
281efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
282efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
283efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return buf;
284efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
285efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
286efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// FIXME: need to redo resource maps for MIPS - fix this at that time
2878dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Markovoid MipsMir2Lir::DumpResourceMask(LIR *mips_lir, const ResourceMask& mask, const char *prefix) {
288efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  char buf[256];
289efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  buf[0] = 0;
290efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
2918dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  if (mask.Equals(kEncodeAll)) {
292efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    strcpy(buf, "all");
293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    char num[8];
295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    int i;
296efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
297efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    for (i = 0; i < kMipsRegEnd; i++) {
2988dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko      if (mask.HasBit(i)) {
299988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers        snprintf(num, arraysize(num), "%d ", i);
300efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        strcat(buf, num);
301efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      }
302efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3048dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mask.HasBit(ResourceMask::kCCode)) {
305efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      strcat(buf, "cc ");
306efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
3078dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mask.HasBit(ResourceMask::kFPStatus)) {
308efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      strcat(buf, "fpcc ");
309efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
310efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    /* Memory bits */
3118dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mips_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
312988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers      snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
313988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers               DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
314988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers               DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
315efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
3168dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mask.HasBit(ResourceMask::kLiteral)) {
317efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      strcat(buf, "lit ");
318efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
319efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3208dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mask.HasBit(ResourceMask::kHeapRef)) {
321efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      strcat(buf, "heap ");
322efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
3238dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mask.HasBit(ResourceMask::kMustNotAlias)) {
324efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      strcat(buf, "noalias ");
325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
326efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
327efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (buf[0]) {
328efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    LOG(INFO) << prefix << ": " <<  buf;
329efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
330efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
333311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * TUNING: is true leaf?  Can't just use METHOD_IS_LEAF to determine as some
334efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * instructions might call out to C/assembly helper functions.  Until
335efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * machinery is in place, always spill lr.
336efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
337efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3382ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MipsMir2Lir::AdjustSpillMask() {
339091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
3401fd3346740dfb7f47be9922312b68a4227fada96buzbee  num_core_spills_++;
341efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
342efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
343efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* Clobber all regs that might be used by an external C call */
34431c2aac7137b69d5622eea09597500731fbee2efVladimir Markovoid MipsMir2Lir::ClobberCallerSave() {
345091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rZERO);
346091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rAT);
347091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rV0);
348091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rV1);
349091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rA0);
350091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rA1);
351091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rA2);
352091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rA3);
353091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rT0);
354091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rT1);
355091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rT2);
356091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rT3);
357091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rT4);
358091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rT5);
359091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rT6);
360091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rT7);
361091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rT8);
362091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rT9);
363091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rK0);
364091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rK1);
365091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rGP);
366091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rFP);
367091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rRA);
368091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF0);
369091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF1);
370091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF2);
371091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF3);
372091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF4);
373091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF5);
374091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF6);
375091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF7);
376091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF8);
377091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF9);
378091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF10);
379091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF11);
380091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF12);
381091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF13);
382091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF14);
383091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rF15);
384091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rD0);
385091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rD1);
386091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rD2);
387091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rD3);
388091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rD4);
389091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rD5);
390091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rD6);
391091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rD7);
3921fd3346740dfb7f47be9922312b68a4227fada96buzbee}
3931fd3346740dfb7f47be9922312b68a4227fada96buzbee
3942ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation MipsMir2Lir::GetReturnWideAlt() {
39552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
39652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  RegLocation res = LocCReturnWide();
397efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
398efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
399efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4002ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation MipsMir2Lir::GetReturnAlt() {
40152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
40252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  RegLocation res = LocCReturn();
403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
406efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */
4072ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MipsMir2Lir::LockCallTemps() {
408091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rMIPS_ARG0);
409091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rMIPS_ARG1);
410091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rMIPS_ARG2);
411091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rMIPS_ARG3);
412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
413efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
414efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */
4152ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MipsMir2Lir::FreeCallTemps() {
416091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rMIPS_ARG0);
417091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rMIPS_ARG1);
418091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rMIPS_ARG2);
419091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rMIPS_ARG3);
420efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
421efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
422b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampebool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
423efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#if ANDROID_SMP != 0
4241fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
425b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe  return true;
426b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe#else
427b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe  return false;
428efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif
429efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
430efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4312ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MipsMir2Lir::CompilerInitializeRegAlloc() {
432b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee  reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */, sp_regs,
433b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee                                        dp_regs, reserved_regs, empty_pool /* reserved64 */,
434b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee                                        core_temps, empty_pool /* core64_temps */, sp_temps,
435b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee                                        dp_temps);
436091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
437091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Target-specific adjustments.
438091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
439091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Alias single precision floats to appropriate half of overlapping double.
440091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
441091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
442091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    int sp_reg_num = info->GetReg().GetRegNum();
4432db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung#if (FR_BIT == 0)
4442db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung    int dp_reg_num = sp_reg_num & ~1;
4452db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung#else
446091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    int dp_reg_num = sp_reg_num >> 1;
4472db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung#endif
448091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
449091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
450091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    // Double precision register's master storage should refer to itself.
451091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
452091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    // Redirect single precision's master storage to master.
453091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    info->SetMaster(dp_reg_info);
454091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    // Singles should show a single 32-bit mask bit, at first referring to the low half.
455091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    DCHECK_EQ(info->StorageMask(), 0x1U);
456091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    if (sp_reg_num & 1) {
457091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      // For odd singles, change to user the high word of the backing double.
458091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      info->SetStorageMask(0x2);
459efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
460efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
461091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
462091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
463091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // TODO: adjust when we roll to hard float calling convention.
464091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  reg_pool_->next_core_reg_ = 2;
465091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  reg_pool_->next_sp_reg_ = 2;
4662db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung#if (FR_BIT == 0)
4672db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung  reg_pool_->next_dp_reg_ = 2;
4682db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung#else
469091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  reg_pool_->next_dp_reg_ = 1;
4702db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung#endif
471efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
472efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
473efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
474efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * In the Arm code a it is typical to use the link register
475efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * to hold the target address.  However, for Mips we must
476efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * ensure that all branch instructions can be restarted if
477efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * there is a trap in the shadow.  Allocate a temp register.
478efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
479984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas GampeRegStorage MipsMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
480695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee  // NOTE: native pointer.
481984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe  LoadWordDisp(rs_rMIPS_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rT9);
4822700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  return rs_rT9;
483efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
484efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
485b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave AllisonLIR* MipsMir2Lir::CheckSuspendUsingLoad() {
4862700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  RegStorage tmp = AllocTemp();
487695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee  // NOTE: native pointer.
488dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
489b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison  LIR *inst = LoadWordDisp(tmp, 0, tmp);
490b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison  FreeTemp(tmp);
491b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison  return inst;
492b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison}
493b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison
494d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas LeungLIR* MipsMir2Lir::GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest) {
495d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  DCHECK(!r_dest.IsFloat());  // See RegClassForFieldLoadStore().
496d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  DCHECK(r_dest.IsPair());
497d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  ClobberCallerSave();
498d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  LockCallTemps();  // Using fixed registers
499d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  RegStorage reg_ptr = TargetReg(kArg0);
500d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  OpRegRegImm(kOpAdd, reg_ptr, r_base, displacement);
501984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe  RegStorage r_tgt = LoadHelper(kQuickA64Load);
502d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  LIR *ret = OpReg(kOpBlx, r_tgt);
503d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  RegStorage reg_ret = RegStorage::MakeRegPair(TargetReg(kRet0), TargetReg(kRet1));
504d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  OpRegCopyWide(r_dest, reg_ret);
505d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  return ret;
506d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung}
507d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung
508d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas LeungLIR* MipsMir2Lir::GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src) {
509d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  DCHECK(!r_src.IsFloat());  // See RegClassForFieldLoadStore().
510d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  DCHECK(r_src.IsPair());
511d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  ClobberCallerSave();
512d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  LockCallTemps();  // Using fixed registers
513d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  RegStorage temp_ptr = AllocTemp();
514d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  OpRegRegImm(kOpAdd, temp_ptr, r_base, displacement);
515d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  RegStorage temp_value = AllocTempWide();
516d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  OpRegCopyWide(temp_value, r_src);
517d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  RegStorage reg_ptr = TargetReg(kArg0);
518d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  OpRegCopy(reg_ptr, temp_ptr);
519d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  RegStorage reg_value = RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3));
520d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  OpRegCopyWide(reg_value, temp_value);
521d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  FreeTemp(temp_ptr);
522d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  FreeTemp(temp_value);
523984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe  RegStorage r_tgt = LoadHelper(kQuickA64Store);
524d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung  return OpReg(kOpBlx, r_tgt);
525d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung}
526d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung
5272ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MipsMir2Lir::SpillCoreRegs() {
5281fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (num_core_spills_ == 0) {
529efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return;
530efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
5311fd3346740dfb7f47be9922312b68a4227fada96buzbee  uint32_t mask = core_spill_mask_;
5321fd3346740dfb7f47be9922312b68a4227fada96buzbee  int offset = num_core_spills_ * 4;
5332700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  OpRegImm(kOpSub, rs_rSP, offset);
534efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  for (int reg = 0; mask; mask >>= 1, reg++) {
535efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    if (mask & 0x1) {
536efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      offset -= 4;
537695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee      Store32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
538efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
539efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
540efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
541efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5422ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MipsMir2Lir::UnSpillCoreRegs() {
5431fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (num_core_spills_ == 0) {
544efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return;
545efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
5461fd3346740dfb7f47be9922312b68a4227fada96buzbee  uint32_t mask = core_spill_mask_;
5471fd3346740dfb7f47be9922312b68a4227fada96buzbee  int offset = frame_size_;
548efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  for (int reg = 0; mask; mask >>= 1, reg++) {
549efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    if (mask & 0x1) {
550efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      offset -= 4;
551695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee      Load32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
552efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
553efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
5542700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  OpRegImm(kOpAdd, rs_rSP, frame_size_);
555efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
556efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5572ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
558cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  return (lir->opcode == kMipsB);
559efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
560efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
561674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir MarkoRegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
5622db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung  if (UNLIKELY(is_volatile)) {
563d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung    // On Mips, atomic 64-bit load/store requires a core register.
5642db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung    // Smaller aligned load/store is atomic for both core and fp registers.
5652db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung    if (size == k64 || size == kDouble) {
566d9cb8ae2ed78f957a773af61759432d7a7bf78afDouglas Leung      return kCoreReg;
5672db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung    }
5682db3e269e3051dacb3c8a4af8f03fdad9b0fd740Douglas Leung  }
569674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  // TODO: Verify that both core and fp registers are suitable for smaller sizes.
570674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  return RegClassBySize(size);
571674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko}
572674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko
573862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
574862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee    : Mir2Lir(cu, mir_graph, arena) {
57502031b185b4653e6c72e21f7a51238b903f6d638buzbee  for (int i = 0; i < kMipsLast; i++) {
5761fd3346740dfb7f47be9922312b68a4227fada96buzbee    if (MipsMir2Lir::EncodingMap[i].opcode != i) {
5771fd3346740dfb7f47be9922312b68a4227fada96buzbee      LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
57802031b185b4653e6c72e21f7a51238b903f6d638buzbee                 << " is wrong: expecting " << i << ", seeing "
5791fd3346740dfb7f47be9922312b68a4227fada96buzbee                 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
580efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
581efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
582efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
583efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
584862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
585862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee                           ArenaAllocator* const arena) {
586862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  return new MipsMir2Lir(cu, mir_graph, arena);
5871fd3346740dfb7f47be9922312b68a4227fada96buzbee}
5881fd3346740dfb7f47be9922312b68a4227fada96buzbee
5892ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromuint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
590409fe94ad529d9334587be80b9f6a3d166805508buzbee  DCHECK(!IsPseudoLirOp(opcode));
5911fd3346740dfb7f47be9922312b68a4227fada96buzbee  return MipsMir2Lir::EncodingMap[opcode].flags;
5921bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee}
5931bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
5942ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* MipsMir2Lir::GetTargetInstName(int opcode) {
595409fe94ad529d9334587be80b9f6a3d166805508buzbee  DCHECK(!IsPseudoLirOp(opcode));
5961fd3346740dfb7f47be9922312b68a4227fada96buzbee  return MipsMir2Lir::EncodingMap[opcode].name;
5971bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee}
5981bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
5992ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
600409fe94ad529d9334587be80b9f6a3d166805508buzbee  DCHECK(!IsPseudoLirOp(opcode));
6011fd3346740dfb7f47be9922312b68a4227fada96buzbee  return MipsMir2Lir::EncodingMap[opcode].fmt;
6021bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee}
6031bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
6047934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom}  // namespace art
605