blob: 3b7e0ed23b8fdd95994386995d3b6d141873b4dc [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
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"
Ian Rogersd582fa42014-11-05 23:46:43 -080018
19#include "arch/mips/instruction_set_features_mips.h"
Nikola Veljkovic2d873b62015-02-20 17:21:15 +010020#include "arch/mips/entrypoints_direct_mips.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080021#include "base/logging.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070022#include "dex/quick/mir_to_lir-inl.h"
buzbeeb5860fb2014-06-21 15:31:01 -070023#include "dex/reg_storage_eq.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080024#include "driver/compiler_driver.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070025#include "mips_lir.h"
26
27namespace art {
28
29/* This file contains codegen for the MIPS32 ISA. */
buzbee2700f7e2014-03-07 09:46:20 -080030LIR* MipsMir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070031 int opcode;
32 /* must be both DOUBLE or both not DOUBLE */
buzbee091cc402014-03-31 10:14:40 -070033 DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble());
34 if (r_dest.IsDouble()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070035 opcode = kMipsFmovd;
36 } else {
buzbee091cc402014-03-31 10:14:40 -070037 if (r_dest.IsSingle()) {
38 if (r_src.IsSingle()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070039 opcode = kMipsFmovs;
40 } else {
41 /* note the operands are swapped for the mtc1 instr */
buzbee2700f7e2014-03-07 09:46:20 -080042 RegStorage t_opnd = r_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -070043 r_src = r_dest;
44 r_dest = t_opnd;
45 opcode = kMipsMtc1;
46 }
47 } else {
buzbee091cc402014-03-31 10:14:40 -070048 DCHECK(r_src.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070049 opcode = kMipsMfc1;
50 }
51 }
buzbee2700f7e2014-03-07 09:46:20 -080052 LIR* res = RawLIR(current_dalvik_offset_, opcode, r_src.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -070053 if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
54 res->flags.is_nop = true;
55 }
56 return res;
57}
58
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070059bool MipsMir2Lir::InexpensiveConstantInt(int32_t value) {
Andreas Gampeab1eb0d2015-02-13 19:23:55 -080060 // For encodings, see LoadConstantNoClobber below.
61 return ((value == 0) || IsUint<16>(value) || IsInt<16>(value));
Brian Carlstrom7940e442013-07-12 13:46:57 -070062}
63
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070064bool MipsMir2Lir::InexpensiveConstantFloat(int32_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070065 UNUSED(value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070066 return false; // TUNING
67}
68
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070069bool MipsMir2Lir::InexpensiveConstantLong(int64_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070070 UNUSED(value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070071 return false; // TUNING
72}
73
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070074bool MipsMir2Lir::InexpensiveConstantDouble(int64_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070075 UNUSED(value);
Brian Carlstrom7934ac22013-07-26 10:54:15 -070076 return false; // TUNING
Brian Carlstrom7940e442013-07-12 13:46:57 -070077}
78
79/*
80 * Load a immediate using a shortcut if possible; otherwise
81 * grab from the per-translation literal pool. If target is
82 * a high register, build constant into a low register and copy.
83 *
84 * No additional register clobbering operation performed. Use this version when
85 * 1) r_dest is freshly returned from AllocTemp or
86 * 2) The codegen is under fixed register usage
87 */
buzbee2700f7e2014-03-07 09:46:20 -080088LIR* MipsMir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070089 LIR *res;
90
buzbee2700f7e2014-03-07 09:46:20 -080091 RegStorage r_dest_save = r_dest;
buzbee091cc402014-03-31 10:14:40 -070092 int is_fp_reg = r_dest.IsFloat();
Brian Carlstrom7940e442013-07-12 13:46:57 -070093 if (is_fp_reg) {
buzbee091cc402014-03-31 10:14:40 -070094 DCHECK(r_dest.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070095 r_dest = AllocTemp();
96 }
97
98 /* See if the value can be constructed cheaply */
99 if (value == 0) {
buzbee2700f7e2014-03-07 09:46:20 -0800100 res = NewLIR2(kMipsMove, r_dest.GetReg(), rZERO);
Andreas Gampeab1eb0d2015-02-13 19:23:55 -0800101 } else if (IsUint<16>(value)) {
102 // Use OR with (unsigned) immediate to encode 16b unsigned int.
buzbee2700f7e2014-03-07 09:46:20 -0800103 res = NewLIR3(kMipsOri, r_dest.GetReg(), rZERO, value);
Andreas Gampeab1eb0d2015-02-13 19:23:55 -0800104 } else if (IsInt<16>(value)) {
105 // Use ADD with (signed) immediate to encode 16b signed int.
buzbee2700f7e2014-03-07 09:46:20 -0800106 res = NewLIR3(kMipsAddiu, r_dest.GetReg(), rZERO, value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700107 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800108 res = NewLIR2(kMipsLui, r_dest.GetReg(), value >> 16);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700109 if (value & 0xffff)
buzbee2700f7e2014-03-07 09:46:20 -0800110 NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700111 }
112
113 if (is_fp_reg) {
buzbee2700f7e2014-03-07 09:46:20 -0800114 NewLIR2(kMipsMtc1, r_dest.GetReg(), r_dest_save.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700115 FreeTemp(r_dest);
116 }
117
118 return res;
119}
120
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700121LIR* MipsMir2Lir::OpUnconditionalBranch(LIR* target) {
Brian Carlstromdf629502013-07-17 22:39:56 -0700122 LIR* res = NewLIR1(kMipsB, 0 /* offset to be patched during assembly*/);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700123 res->target = target;
124 return res;
125}
126
buzbee2700f7e2014-03-07 09:46:20 -0800127LIR* MipsMir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700128 MipsOpCode opcode = kMipsNop;
129 switch (op) {
130 case kOpBlx:
131 opcode = kMipsJalr;
132 break;
133 case kOpBx:
Andreas Gampe8d365912015-01-13 11:32:32 -0800134 return NewLIR2(kMipsJalr, rZERO, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700135 break;
136 default:
137 LOG(FATAL) << "Bad case in OpReg";
138 }
buzbee2700f7e2014-03-07 09:46:20 -0800139 return NewLIR2(opcode, rRA, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700140}
141
buzbee2700f7e2014-03-07 09:46:20 -0800142LIR* MipsMir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700143 LIR *res;
144 bool neg = (value < 0);
145 int abs_value = (neg) ? -value : value;
146 bool short_form = (abs_value & 0xff) == abs_value;
147 MipsOpCode opcode = kMipsNop;
148 switch (op) {
149 case kOpAdd:
150 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
151 break;
152 case kOpSub:
153 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
154 break;
155 default:
156 LOG(FATAL) << "Bad case in OpRegImm";
157 break;
158 }
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700159 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800160 res = NewLIR2(opcode, r_dest_src1.GetReg(), abs_value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700161 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800162 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700163 res = LoadConstant(r_scratch, value);
164 if (op == kOpCmp)
buzbee2700f7e2014-03-07 09:46:20 -0800165 NewLIR2(opcode, r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700166 else
buzbee2700f7e2014-03-07 09:46:20 -0800167 NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700168 }
169 return res;
170}
171
buzbee2700f7e2014-03-07 09:46:20 -0800172LIR* MipsMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700173 MipsOpCode opcode = kMipsNop;
174 switch (op) {
175 case kOpAdd:
176 opcode = kMipsAddu;
177 break;
178 case kOpSub:
179 opcode = kMipsSubu;
180 break;
181 case kOpAnd:
182 opcode = kMipsAnd;
183 break;
184 case kOpMul:
Douglas Leung027f0ff2015-02-27 19:05:03 -0800185 if (isaIsR6_) {
186 opcode = kMipsR6Mul;
187 } else {
188 opcode = kMipsMul;
189 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700190 break;
191 case kOpOr:
192 opcode = kMipsOr;
193 break;
194 case kOpXor:
195 opcode = kMipsXor;
196 break;
197 case kOpLsl:
198 opcode = kMipsSllv;
199 break;
200 case kOpLsr:
201 opcode = kMipsSrlv;
202 break;
203 case kOpAsr:
204 opcode = kMipsSrav;
205 break;
206 case kOpAdc:
207 case kOpSbc:
208 LOG(FATAL) << "No carry bit on MIPS";
209 break;
210 default:
211 LOG(FATAL) << "bad case in OpRegRegReg";
212 break;
213 }
buzbee2700f7e2014-03-07 09:46:20 -0800214 return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700215}
216
buzbee2700f7e2014-03-07 09:46:20 -0800217LIR* MipsMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700218 LIR *res;
219 MipsOpCode opcode = kMipsNop;
220 bool short_form = true;
221
222 switch (op) {
223 case kOpAdd:
224 if (IS_SIMM16(value)) {
225 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700226 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700227 short_form = false;
228 opcode = kMipsAddu;
229 }
230 break;
231 case kOpSub:
232 if (IS_SIMM16((-value))) {
233 value = -value;
234 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700235 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700236 short_form = false;
237 opcode = kMipsSubu;
238 }
239 break;
240 case kOpLsl:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800241 DCHECK(value >= 0 && value <= 31);
242 opcode = kMipsSll;
243 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700244 case kOpLsr:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800245 DCHECK(value >= 0 && value <= 31);
246 opcode = kMipsSrl;
247 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700248 case kOpAsr:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800249 DCHECK(value >= 0 && value <= 31);
250 opcode = kMipsSra;
251 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700252 case kOpAnd:
253 if (IS_UIMM16((value))) {
254 opcode = kMipsAndi;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700255 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700256 short_form = false;
257 opcode = kMipsAnd;
258 }
259 break;
260 case kOpOr:
261 if (IS_UIMM16((value))) {
262 opcode = kMipsOri;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700263 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700264 short_form = false;
265 opcode = kMipsOr;
266 }
267 break;
268 case kOpXor:
269 if (IS_UIMM16((value))) {
270 opcode = kMipsXori;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700271 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700272 short_form = false;
273 opcode = kMipsXor;
274 }
275 break;
276 case kOpMul:
277 short_form = false;
Douglas Leung027f0ff2015-02-27 19:05:03 -0800278 if (isaIsR6_) {
279 opcode = kMipsR6Mul;
280 } else {
281 opcode = kMipsMul;
282 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700283 break;
284 default:
285 LOG(FATAL) << "Bad case in OpRegRegImm";
286 break;
287 }
288
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700289 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800290 res = NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700291 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700292 if (r_dest != r_src1) {
293 res = LoadConstant(r_dest, value);
buzbee2700f7e2014-03-07 09:46:20 -0800294 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700295 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800296 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700297 res = LoadConstant(r_scratch, value);
buzbee2700f7e2014-03-07 09:46:20 -0800298 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700299 }
300 }
301 return res;
302}
303
buzbee2700f7e2014-03-07 09:46:20 -0800304LIR* MipsMir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700305 MipsOpCode opcode = kMipsNop;
306 LIR *res;
307 switch (op) {
308 case kOpMov:
309 opcode = kMipsMove;
310 break;
311 case kOpMvn:
buzbee2700f7e2014-03-07 09:46:20 -0800312 return NewLIR3(kMipsNor, r_dest_src1.GetReg(), r_src2.GetReg(), rZERO);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700313 case kOpNeg:
buzbee2700f7e2014-03-07 09:46:20 -0800314 return NewLIR3(kMipsSubu, r_dest_src1.GetReg(), rZERO, r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700315 case kOpAdd:
316 case kOpAnd:
317 case kOpMul:
318 case kOpOr:
319 case kOpSub:
320 case kOpXor:
321 return OpRegRegReg(op, r_dest_src1, r_dest_src1, r_src2);
322 case kOp2Byte:
Andreas Gampe0b9203e2015-01-22 20:39:27 -0800323 if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
Ian Rogersd582fa42014-11-05 23:46:43 -0800324 ->IsMipsIsaRevGreaterThanEqual2()) {
325 res = NewLIR2(kMipsSeb, r_dest_src1.GetReg(), r_src2.GetReg());
326 } else {
327 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 24);
328 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 24);
329 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700330 return res;
331 case kOp2Short:
Andreas Gampe0b9203e2015-01-22 20:39:27 -0800332 if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
Ian Rogersd582fa42014-11-05 23:46:43 -0800333 ->IsMipsIsaRevGreaterThanEqual2()) {
334 res = NewLIR2(kMipsSeh, r_dest_src1.GetReg(), r_src2.GetReg());
335 } else {
336 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 16);
337 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 16);
338 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700339 return res;
340 case kOp2Char:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800341 return NewLIR3(kMipsAndi, r_dest_src1.GetReg(), r_src2.GetReg(), 0xFFFF);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700342 default:
343 LOG(FATAL) << "Bad case in OpRegReg";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700344 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700345 }
buzbee2700f7e2014-03-07 09:46:20 -0800346 return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700347}
348
buzbee2700f7e2014-03-07 09:46:20 -0800349LIR* MipsMir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset,
350 MoveType move_type) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700351 UNUSED(r_dest, r_base, offset, move_type);
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800352 UNIMPLEMENTED(FATAL);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700353 UNREACHABLE();
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800354}
355
buzbee2700f7e2014-03-07 09:46:20 -0800356LIR* MipsMir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700357 UNUSED(r_base, offset, r_src, move_type);
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800358 UNIMPLEMENTED(FATAL);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700359 UNREACHABLE();
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800360}
361
buzbee2700f7e2014-03-07 09:46:20 -0800362LIR* MipsMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700363 UNUSED(op, cc, r_dest, r_src);
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800364 LOG(FATAL) << "Unexpected use of OpCondRegReg for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700365 UNREACHABLE();
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800366}
367
buzbee2700f7e2014-03-07 09:46:20 -0800368LIR* MipsMir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700369 LIR *res;
Douglas Leung027f0ff2015-02-27 19:05:03 -0800370 if (fpuIs32Bit_ || !r_dest.IsFloat()) {
371 // 32bit FPU (pairs) or loading into GPR.
372 if (!r_dest.IsPair()) {
373 // Form 64-bit pair
374 r_dest = Solo64ToPair64(r_dest);
375 }
376 res = LoadConstantNoClobber(r_dest.GetLow(), Low32Bits(value));
377 LoadConstantNoClobber(r_dest.GetHigh(), High32Bits(value));
378 } else {
379 // Here if we have a 64bit FPU and loading into FPR.
380 RegStorage r_temp = AllocTemp();
381 r_dest = Fp64ToSolo32(r_dest);
382 res = LoadConstantNoClobber(r_dest, Low32Bits(value));
383 LoadConstantNoClobber(r_temp, High32Bits(value));
384 NewLIR2(kMipsMthc1, r_temp.GetReg(), r_dest.GetReg());
385 FreeTemp(r_temp);
Douglas Leung2db3e262014-06-25 16:02:55 -0700386 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700387 return res;
388}
389
390/* Load value from base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800391LIR* MipsMir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700392 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700393 LIR *first = NULL;
394 LIR *res;
395 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800396 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700397
buzbee091cc402014-03-31 10:14:40 -0700398 if (r_dest.IsFloat()) {
399 DCHECK(r_dest.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700400 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700401 size = kSingle;
402 } else {
403 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700404 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700405 }
406
407 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800408 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700409 } else {
410 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800411 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700412 }
413
414 switch (size) {
415 case kSingle:
416 opcode = kMipsFlwc1;
417 break;
buzbee695d13a2014-04-19 13:32:20 -0700418 case k32:
419 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700420 opcode = kMipsLw;
421 break;
422 case kUnsignedHalf:
423 opcode = kMipsLhu;
424 break;
425 case kSignedHalf:
426 opcode = kMipsLh;
427 break;
428 case kUnsignedByte:
429 opcode = kMipsLbu;
430 break;
431 case kSignedByte:
432 opcode = kMipsLb;
433 break;
434 default:
435 LOG(FATAL) << "Bad case in LoadBaseIndexed";
436 }
437
buzbee2700f7e2014-03-07 09:46:20 -0800438 res = NewLIR3(opcode, r_dest.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700439 FreeTemp(t_reg);
440 return (first) ? first : res;
441}
442
443/* store value base base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800444LIR* MipsMir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700445 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700446 LIR *first = NULL;
447 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800448 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700449
buzbee091cc402014-03-31 10:14:40 -0700450 if (r_src.IsFloat()) {
451 DCHECK(r_src.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700452 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700453 size = kSingle;
454 } else {
455 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700456 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700457 }
458
459 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800460 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700461 } else {
462 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800463 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700464 }
465
466 switch (size) {
467 case kSingle:
468 opcode = kMipsFswc1;
469 break;
buzbee695d13a2014-04-19 13:32:20 -0700470 case k32:
471 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700472 opcode = kMipsSw;
473 break;
474 case kUnsignedHalf:
475 case kSignedHalf:
476 opcode = kMipsSh;
477 break;
478 case kUnsignedByte:
479 case kSignedByte:
480 opcode = kMipsSb;
481 break;
482 default:
483 LOG(FATAL) << "Bad case in StoreBaseIndexed";
484 }
buzbee2700f7e2014-03-07 09:46:20 -0800485 NewLIR3(opcode, r_src.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700486 return first;
487}
488
buzbee2700f7e2014-03-07 09:46:20 -0800489// FIXME: don't split r_dest into 2 containers.
490LIR* MipsMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
Douglas Leung2db3e262014-06-25 16:02:55 -0700491 OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700492/*
493 * Load value from base + displacement. Optionally perform null check
494 * on base (which must have an associated s_reg and MIR). If not
495 * performing null check, incoming MIR can be null. IMPORTANT: this
496 * code must not allocate any new temps. If a new register is needed
497 * and base and dest are the same, spill some other register to
498 * rlp and then restore.
499 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700500 LIR *res;
501 LIR *load = NULL;
502 LIR *load2 = NULL;
503 MipsOpCode opcode = kMipsNop;
504 bool short_form = IS_SIMM16(displacement);
Douglas Leung027f0ff2015-02-27 19:05:03 -0800505 bool is64bit = false;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700506
507 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700508 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700509 case kDouble:
Douglas Leung027f0ff2015-02-27 19:05:03 -0800510 is64bit = true;
511 if (fpuIs32Bit_ && !r_dest.IsPair()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700512 // Form 64-bit pair
513 r_dest = Solo64ToPair64(r_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700514 }
515 short_form = IS_SIMM16_2WORD(displacement);
Douglas Leung027f0ff2015-02-27 19:05:03 -0800516 FALLTHROUGH_INTENDED;
buzbee695d13a2014-04-19 13:32:20 -0700517 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700518 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700519 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700520 opcode = kMipsLw;
buzbee091cc402014-03-31 10:14:40 -0700521 if (r_dest.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700522 opcode = kMipsFlwc1;
Douglas Leung027f0ff2015-02-27 19:05:03 -0800523 if (!is64bit) {
524 DCHECK(r_dest.IsSingle());
525 } else {
526 DCHECK(r_dest.IsDouble());
527 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700528 }
529 DCHECK_EQ((displacement & 0x3), 0);
530 break;
531 case kUnsignedHalf:
532 opcode = kMipsLhu;
533 DCHECK_EQ((displacement & 0x1), 0);
534 break;
535 case kSignedHalf:
536 opcode = kMipsLh;
537 DCHECK_EQ((displacement & 0x1), 0);
538 break;
539 case kUnsignedByte:
540 opcode = kMipsLbu;
541 break;
542 case kSignedByte:
543 opcode = kMipsLb;
544 break;
545 default:
546 LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
547 }
548
549 if (short_form) {
Douglas Leung027f0ff2015-02-27 19:05:03 -0800550 if (!is64bit) {
buzbee2700f7e2014-03-07 09:46:20 -0800551 load = res = NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700552 } else {
Douglas Leung027f0ff2015-02-27 19:05:03 -0800553 if (fpuIs32Bit_ || !r_dest.IsFloat()) {
554 DCHECK(r_dest.IsPair());
555 load = res = NewLIR3(opcode, r_dest.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
556 load2 = NewLIR3(opcode, r_dest.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
557 } else {
558 // Here if 64bit fpu and r_dest is a 64bit fp register.
559 RegStorage r_tmp = AllocTemp();
560 // FIXME: why is r_dest a 64BitPair here???
561 r_dest = Fp64ToSolo32(r_dest);
562 load = res = NewLIR3(kMipsFlwc1, r_dest.GetReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
563 load2 = NewLIR3(kMipsLw, r_tmp.GetReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
564 NewLIR2(kMipsMthc1, r_tmp.GetReg(), r_dest.GetReg());
565 FreeTemp(r_tmp);
566 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700567 }
568 } else {
Douglas Leung027f0ff2015-02-27 19:05:03 -0800569 if (!is64bit) {
570 RegStorage r_tmp = (r_base == r_dest || r_dest.IsFloat()) ? AllocTemp() : r_dest;
buzbee2700f7e2014-03-07 09:46:20 -0800571 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
572 load = NewLIR3(opcode, r_dest.GetReg(), 0, r_tmp.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700573 if (r_tmp != r_dest)
574 FreeTemp(r_tmp);
Douglas Leung027f0ff2015-02-27 19:05:03 -0800575 } else {
576 RegStorage r_tmp = AllocTemp();
577 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
578 if (fpuIs32Bit_ || !r_dest.IsFloat()) {
579 DCHECK(r_dest.IsPair());
580 load = NewLIR3(opcode, r_dest.GetLowReg(), LOWORD_OFFSET, r_tmp.GetReg());
581 load2 = NewLIR3(opcode, r_dest.GetHighReg(), HIWORD_OFFSET, r_tmp.GetReg());
582 } else {
583 // Here if 64bit fpu and r_dest is a 64bit fp register
584 r_dest = Fp64ToSolo32(r_dest);
585 load = res = NewLIR3(kMipsFlwc1, r_dest.GetReg(), LOWORD_OFFSET, r_tmp.GetReg());
586 load2 = NewLIR3(kMipsLw, r_tmp.GetReg(), HIWORD_OFFSET, r_tmp.GetReg());
587 NewLIR2(kMipsMthc1, r_tmp.GetReg(), r_dest.GetReg());
588 }
589 FreeTemp(r_tmp);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700590 }
591 }
592
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100593 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
Ian Rogersb28c1c02014-11-08 11:21:21 -0800594 DCHECK_EQ(r_base, rs_rMIPS_SP);
Douglas Leung027f0ff2015-02-27 19:05:03 -0800595 AnnotateDalvikRegAccess(load, (displacement + (is64bit ? LOWORD_OFFSET : 0)) >> 2,
596 true /* is_load */, is64bit /* is64bit */);
597 if (is64bit) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700598 AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
Douglas Leung027f0ff2015-02-27 19:05:03 -0800599 true /* is_load */, is64bit /* is64bit */);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700600 }
601 }
602 return load;
603}
604
Andreas Gampede686762014-06-24 18:42:06 +0000605LIR* MipsMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000606 OpSize size, VolatileKind is_volatile) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700607 if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble))) {
608 // Do atomic 64-bit load.
609 return GenAtomic64Load(r_base, displacement, r_dest);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000610 }
611
buzbee695d13a2014-04-19 13:32:20 -0700612 // TODO: base this on target.
613 if (size == kWord) {
614 size = k32;
615 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000616 LIR* load;
Douglas Leung2db3e262014-06-25 16:02:55 -0700617 load = LoadBaseDispBody(r_base, displacement, r_dest, size);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000618
619 if (UNLIKELY(is_volatile == kVolatile)) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700620 GenMemBarrier(kLoadAny);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000621 }
622
623 return load;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700624}
625
Vladimir Marko455759b2014-05-06 20:49:36 +0100626// FIXME: don't split r_dest into 2 containers.
buzbee2700f7e2014-03-07 09:46:20 -0800627LIR* MipsMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement,
Douglas Leung2db3e262014-06-25 16:02:55 -0700628 RegStorage r_src, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700629 LIR *res;
630 LIR *store = NULL;
631 LIR *store2 = NULL;
632 MipsOpCode opcode = kMipsNop;
633 bool short_form = IS_SIMM16(displacement);
Douglas Leung027f0ff2015-02-27 19:05:03 -0800634 bool is64bit = false;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700635
636 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700637 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700638 case kDouble:
Douglas Leung027f0ff2015-02-27 19:05:03 -0800639 is64bit = true;
640 if (fpuIs32Bit_ && !r_src.IsPair()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700641 // Form 64-bit pair
642 r_src = Solo64ToPair64(r_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700643 }
644 short_form = IS_SIMM16_2WORD(displacement);
Douglas Leung027f0ff2015-02-27 19:05:03 -0800645 FALLTHROUGH_INTENDED;
buzbee695d13a2014-04-19 13:32:20 -0700646 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700647 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700648 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700649 opcode = kMipsSw;
buzbee091cc402014-03-31 10:14:40 -0700650 if (r_src.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700651 opcode = kMipsFswc1;
Douglas Leung027f0ff2015-02-27 19:05:03 -0800652 if (!is64bit) {
653 DCHECK(r_src.IsSingle());
654 } else {
655 DCHECK(r_src.IsDouble());
656 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700657 }
658 DCHECK_EQ((displacement & 0x3), 0);
659 break;
660 case kUnsignedHalf:
661 case kSignedHalf:
662 opcode = kMipsSh;
663 DCHECK_EQ((displacement & 0x1), 0);
664 break;
665 case kUnsignedByte:
666 case kSignedByte:
667 opcode = kMipsSb;
668 break;
669 default:
buzbee2700f7e2014-03-07 09:46:20 -0800670 LOG(FATAL) << "Bad case in StoreBaseDispBody";
Brian Carlstrom7940e442013-07-12 13:46:57 -0700671 }
672
673 if (short_form) {
Douglas Leung027f0ff2015-02-27 19:05:03 -0800674 if (!is64bit) {
buzbee2700f7e2014-03-07 09:46:20 -0800675 store = res = NewLIR3(opcode, r_src.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700676 } else {
Douglas Leung027f0ff2015-02-27 19:05:03 -0800677 if (fpuIs32Bit_ || !r_src.IsFloat()) {
678 DCHECK(r_src.IsPair());
679 store = res = NewLIR3(opcode, r_src.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
680 store2 = NewLIR3(opcode, r_src.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
681 } else {
682 // Here if 64bit fpu and r_src is a 64bit fp register
683 RegStorage r_tmp = AllocTemp();
684 r_src = Fp64ToSolo32(r_src);
685 store = res = NewLIR3(kMipsFswc1, r_src.GetReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
686 NewLIR2(kMipsMfhc1, r_tmp.GetReg(), r_src.GetReg());
687 store2 = NewLIR3(kMipsSw, r_tmp.GetReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
688 FreeTemp(r_tmp);
689 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700690 }
691 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800692 RegStorage r_scratch = AllocTemp();
693 res = OpRegRegImm(kOpAdd, r_scratch, r_base, displacement);
Douglas Leung027f0ff2015-02-27 19:05:03 -0800694 if (!is64bit) {
buzbee2700f7e2014-03-07 09:46:20 -0800695 store = NewLIR3(opcode, r_src.GetReg(), 0, r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700696 } else {
Douglas Leung027f0ff2015-02-27 19:05:03 -0800697 if (fpuIs32Bit_ || !r_src.IsFloat()) {
698 DCHECK(r_src.IsPair());
699 store = NewLIR3(opcode, r_src.GetLowReg(), LOWORD_OFFSET, r_scratch.GetReg());
700 store2 = NewLIR3(opcode, r_src.GetHighReg(), HIWORD_OFFSET, r_scratch.GetReg());
701 } else {
702 // Here if 64bit fpu and r_src is a 64bit fp register
703 RegStorage r_tmp = AllocTemp();
704 r_src = Fp64ToSolo32(r_src);
705 store = NewLIR3(kMipsFswc1, r_src.GetReg(), LOWORD_OFFSET, r_scratch.GetReg());
706 NewLIR2(kMipsMfhc1, r_tmp.GetReg(), r_src.GetReg());
707 store2 = NewLIR3(kMipsSw, r_tmp.GetReg(), HIWORD_OFFSET, r_scratch.GetReg());
708 FreeTemp(r_tmp);
709 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700710 }
711 FreeTemp(r_scratch);
712 }
713
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100714 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
Ian Rogersb28c1c02014-11-08 11:21:21 -0800715 DCHECK_EQ(r_base, rs_rMIPS_SP);
Douglas Leung027f0ff2015-02-27 19:05:03 -0800716 AnnotateDalvikRegAccess(store, (displacement + (is64bit ? LOWORD_OFFSET : 0)) >> 2,
717 false /* is_load */, is64bit /* is64bit */);
718 if (is64bit) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700719 AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
Douglas Leung027f0ff2015-02-27 19:05:03 -0800720 false /* is_load */, is64bit /* is64bit */);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700721 }
722 }
723
724 return res;
725}
726
Andreas Gampede686762014-06-24 18:42:06 +0000727LIR* MipsMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000728 OpSize size, VolatileKind is_volatile) {
729 if (is_volatile == kVolatile) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700730 // Ensure that prior accesses become visible to other threads first.
731 GenMemBarrier(kAnyStore);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000732 }
733
Andreas Gampe3c12c512014-06-24 18:46:29 +0000734 LIR* store;
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700735 if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble))) {
736 // Do atomic 64-bit load.
737 store = GenAtomic64Store(r_base, displacement, r_src);
738 } else {
739 // TODO: base this on target.
740 if (size == kWord) {
741 size = k32;
742 }
743 store = StoreBaseDispBody(r_base, displacement, r_src, size);
744 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000745
746 if (UNLIKELY(is_volatile == kVolatile)) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700747 // Preserve order with respect to any subsequent volatile loads.
748 // We need StoreLoad, but that generally requires the most expensive barrier.
749 GenMemBarrier(kAnyAny);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000750 }
751
752 return store;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700753}
754
buzbee2700f7e2014-03-07 09:46:20 -0800755LIR* MipsMir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700756 UNUSED(op, r_base, disp);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700757 LOG(FATAL) << "Unexpected use of OpMem for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700758 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700759}
760
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700761LIR* MipsMir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700762 UNUSED(cc, target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700763 LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700764 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700765}
766
Andreas Gampe98430592014-07-27 19:44:50 -0700767LIR* MipsMir2Lir::InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) {
Nikola Veljkovic2d873b62015-02-20 17:21:15 +0100768 if (IsDirectEntrypoint(trampoline)) {
769 // Reserve argument space on stack (for $a0-$a3) for
770 // entrypoints that directly reference native implementations.
771 // This is not safe in general, as it violates the frame size
772 // of the Quick method, but it is used here only for calling
773 // native functions, outside of the runtime.
774 OpRegImm(kOpSub, rs_rSP, 16);
775 LIR* retVal = OpReg(op, r_tgt);
776 OpRegImm(kOpAdd, rs_rSP, 16);
777 return retVal;
778 }
779
Andreas Gampe98430592014-07-27 19:44:50 -0700780 return OpReg(op, r_tgt);
781}
782
Brian Carlstrom7940e442013-07-12 13:46:57 -0700783} // namespace art