blob: 6f6bf68feac9849ddbab86a50e00b4eade376177 [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"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080020#include "base/logging.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070021#include "dex/quick/mir_to_lir-inl.h"
buzbeeb5860fb2014-06-21 15:31:01 -070022#include "dex/reg_storage_eq.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080023#include "driver/compiler_driver.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070024#include "mips_lir.h"
25
26namespace art {
27
28/* This file contains codegen for the MIPS32 ISA. */
buzbee2700f7e2014-03-07 09:46:20 -080029LIR* MipsMir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070030 int opcode;
31 /* must be both DOUBLE or both not DOUBLE */
buzbee091cc402014-03-31 10:14:40 -070032 DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble());
33 if (r_dest.IsDouble()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070034 opcode = kMipsFmovd;
35 } else {
buzbee091cc402014-03-31 10:14:40 -070036 if (r_dest.IsSingle()) {
37 if (r_src.IsSingle()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070038 opcode = kMipsFmovs;
39 } else {
40 /* note the operands are swapped for the mtc1 instr */
buzbee2700f7e2014-03-07 09:46:20 -080041 RegStorage t_opnd = r_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -070042 r_src = r_dest;
43 r_dest = t_opnd;
44 opcode = kMipsMtc1;
45 }
46 } else {
buzbee091cc402014-03-31 10:14:40 -070047 DCHECK(r_src.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070048 opcode = kMipsMfc1;
49 }
50 }
buzbee2700f7e2014-03-07 09:46:20 -080051 LIR* res = RawLIR(current_dalvik_offset_, opcode, r_src.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -070052 if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
53 res->flags.is_nop = true;
54 }
55 return res;
56}
57
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070058bool MipsMir2Lir::InexpensiveConstantInt(int32_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070059 return ((value == 0) || IsUint(16, value) || ((value < 0) && (value >= -32768)));
60}
61
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070062bool MipsMir2Lir::InexpensiveConstantFloat(int32_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070063 UNUSED(value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070064 return false; // TUNING
65}
66
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070067bool MipsMir2Lir::InexpensiveConstantLong(int64_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070068 UNUSED(value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070069 return false; // TUNING
70}
71
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070072bool MipsMir2Lir::InexpensiveConstantDouble(int64_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070073 UNUSED(value);
Brian Carlstrom7934ac22013-07-26 10:54:15 -070074 return false; // TUNING
Brian Carlstrom7940e442013-07-12 13:46:57 -070075}
76
77/*
78 * Load a immediate using a shortcut if possible; otherwise
79 * grab from the per-translation literal pool. If target is
80 * a high register, build constant into a low register and copy.
81 *
82 * No additional register clobbering operation performed. Use this version when
83 * 1) r_dest is freshly returned from AllocTemp or
84 * 2) The codegen is under fixed register usage
85 */
buzbee2700f7e2014-03-07 09:46:20 -080086LIR* MipsMir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070087 LIR *res;
88
buzbee2700f7e2014-03-07 09:46:20 -080089 RegStorage r_dest_save = r_dest;
buzbee091cc402014-03-31 10:14:40 -070090 int is_fp_reg = r_dest.IsFloat();
Brian Carlstrom7940e442013-07-12 13:46:57 -070091 if (is_fp_reg) {
buzbee091cc402014-03-31 10:14:40 -070092 DCHECK(r_dest.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070093 r_dest = AllocTemp();
94 }
95
96 /* See if the value can be constructed cheaply */
97 if (value == 0) {
buzbee2700f7e2014-03-07 09:46:20 -080098 res = NewLIR2(kMipsMove, r_dest.GetReg(), rZERO);
Brian Carlstrom7940e442013-07-12 13:46:57 -070099 } else if ((value > 0) && (value <= 65535)) {
buzbee2700f7e2014-03-07 09:46:20 -0800100 res = NewLIR3(kMipsOri, r_dest.GetReg(), rZERO, value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700101 } else if ((value < 0) && (value >= -32768)) {
buzbee2700f7e2014-03-07 09:46:20 -0800102 res = NewLIR3(kMipsAddiu, r_dest.GetReg(), rZERO, value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700103 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800104 res = NewLIR2(kMipsLui, r_dest.GetReg(), value >> 16);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700105 if (value & 0xffff)
buzbee2700f7e2014-03-07 09:46:20 -0800106 NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700107 }
108
109 if (is_fp_reg) {
buzbee2700f7e2014-03-07 09:46:20 -0800110 NewLIR2(kMipsMtc1, r_dest.GetReg(), r_dest_save.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700111 FreeTemp(r_dest);
112 }
113
114 return res;
115}
116
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700117LIR* MipsMir2Lir::OpUnconditionalBranch(LIR* target) {
Brian Carlstromdf629502013-07-17 22:39:56 -0700118 LIR* res = NewLIR1(kMipsB, 0 /* offset to be patched during assembly*/);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700119 res->target = target;
120 return res;
121}
122
buzbee2700f7e2014-03-07 09:46:20 -0800123LIR* MipsMir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700124 MipsOpCode opcode = kMipsNop;
125 switch (op) {
126 case kOpBlx:
127 opcode = kMipsJalr;
128 break;
129 case kOpBx:
Andreas Gampe8d365912015-01-13 11:32:32 -0800130 return NewLIR2(kMipsJalr, rZERO, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700131 break;
132 default:
133 LOG(FATAL) << "Bad case in OpReg";
134 }
buzbee2700f7e2014-03-07 09:46:20 -0800135 return NewLIR2(opcode, rRA, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700136}
137
buzbee2700f7e2014-03-07 09:46:20 -0800138LIR* MipsMir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700139 LIR *res;
140 bool neg = (value < 0);
141 int abs_value = (neg) ? -value : value;
142 bool short_form = (abs_value & 0xff) == abs_value;
143 MipsOpCode opcode = kMipsNop;
144 switch (op) {
145 case kOpAdd:
146 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
147 break;
148 case kOpSub:
149 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
150 break;
151 default:
152 LOG(FATAL) << "Bad case in OpRegImm";
153 break;
154 }
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700155 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800156 res = NewLIR2(opcode, r_dest_src1.GetReg(), abs_value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700157 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800158 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700159 res = LoadConstant(r_scratch, value);
160 if (op == kOpCmp)
buzbee2700f7e2014-03-07 09:46:20 -0800161 NewLIR2(opcode, r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700162 else
buzbee2700f7e2014-03-07 09:46:20 -0800163 NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700164 }
165 return res;
166}
167
buzbee2700f7e2014-03-07 09:46:20 -0800168LIR* MipsMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700169 MipsOpCode opcode = kMipsNop;
170 switch (op) {
171 case kOpAdd:
172 opcode = kMipsAddu;
173 break;
174 case kOpSub:
175 opcode = kMipsSubu;
176 break;
177 case kOpAnd:
178 opcode = kMipsAnd;
179 break;
180 case kOpMul:
181 opcode = kMipsMul;
182 break;
183 case kOpOr:
184 opcode = kMipsOr;
185 break;
186 case kOpXor:
187 opcode = kMipsXor;
188 break;
189 case kOpLsl:
190 opcode = kMipsSllv;
191 break;
192 case kOpLsr:
193 opcode = kMipsSrlv;
194 break;
195 case kOpAsr:
196 opcode = kMipsSrav;
197 break;
198 case kOpAdc:
199 case kOpSbc:
200 LOG(FATAL) << "No carry bit on MIPS";
201 break;
202 default:
203 LOG(FATAL) << "bad case in OpRegRegReg";
204 break;
205 }
buzbee2700f7e2014-03-07 09:46:20 -0800206 return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700207}
208
buzbee2700f7e2014-03-07 09:46:20 -0800209LIR* MipsMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700210 LIR *res;
211 MipsOpCode opcode = kMipsNop;
212 bool short_form = true;
213
214 switch (op) {
215 case kOpAdd:
216 if (IS_SIMM16(value)) {
217 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700218 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700219 short_form = false;
220 opcode = kMipsAddu;
221 }
222 break;
223 case kOpSub:
224 if (IS_SIMM16((-value))) {
225 value = -value;
226 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700227 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700228 short_form = false;
229 opcode = kMipsSubu;
230 }
231 break;
232 case kOpLsl:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800233 DCHECK(value >= 0 && value <= 31);
234 opcode = kMipsSll;
235 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700236 case kOpLsr:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800237 DCHECK(value >= 0 && value <= 31);
238 opcode = kMipsSrl;
239 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240 case kOpAsr:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800241 DCHECK(value >= 0 && value <= 31);
242 opcode = kMipsSra;
243 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700244 case kOpAnd:
245 if (IS_UIMM16((value))) {
246 opcode = kMipsAndi;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700247 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700248 short_form = false;
249 opcode = kMipsAnd;
250 }
251 break;
252 case kOpOr:
253 if (IS_UIMM16((value))) {
254 opcode = kMipsOri;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700255 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700256 short_form = false;
257 opcode = kMipsOr;
258 }
259 break;
260 case kOpXor:
261 if (IS_UIMM16((value))) {
262 opcode = kMipsXori;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700263 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700264 short_form = false;
265 opcode = kMipsXor;
266 }
267 break;
268 case kOpMul:
269 short_form = false;
270 opcode = kMipsMul;
271 break;
272 default:
273 LOG(FATAL) << "Bad case in OpRegRegImm";
274 break;
275 }
276
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700277 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800278 res = NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700279 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700280 if (r_dest != r_src1) {
281 res = LoadConstant(r_dest, value);
buzbee2700f7e2014-03-07 09:46:20 -0800282 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700283 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800284 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700285 res = LoadConstant(r_scratch, value);
buzbee2700f7e2014-03-07 09:46:20 -0800286 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700287 }
288 }
289 return res;
290}
291
buzbee2700f7e2014-03-07 09:46:20 -0800292LIR* MipsMir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700293 MipsOpCode opcode = kMipsNop;
294 LIR *res;
295 switch (op) {
296 case kOpMov:
297 opcode = kMipsMove;
298 break;
299 case kOpMvn:
buzbee2700f7e2014-03-07 09:46:20 -0800300 return NewLIR3(kMipsNor, r_dest_src1.GetReg(), r_src2.GetReg(), rZERO);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700301 case kOpNeg:
buzbee2700f7e2014-03-07 09:46:20 -0800302 return NewLIR3(kMipsSubu, r_dest_src1.GetReg(), rZERO, r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700303 case kOpAdd:
304 case kOpAnd:
305 case kOpMul:
306 case kOpOr:
307 case kOpSub:
308 case kOpXor:
309 return OpRegRegReg(op, r_dest_src1, r_dest_src1, r_src2);
310 case kOp2Byte:
Andreas Gampe0b9203e2015-01-22 20:39:27 -0800311 if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
Ian Rogersd582fa42014-11-05 23:46:43 -0800312 ->IsMipsIsaRevGreaterThanEqual2()) {
313 res = NewLIR2(kMipsSeb, r_dest_src1.GetReg(), r_src2.GetReg());
314 } else {
315 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 24);
316 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 24);
317 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700318 return res;
319 case kOp2Short:
Andreas Gampe0b9203e2015-01-22 20:39:27 -0800320 if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
Ian Rogersd582fa42014-11-05 23:46:43 -0800321 ->IsMipsIsaRevGreaterThanEqual2()) {
322 res = NewLIR2(kMipsSeh, r_dest_src1.GetReg(), r_src2.GetReg());
323 } else {
324 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 16);
325 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 16);
326 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700327 return res;
328 case kOp2Char:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800329 return NewLIR3(kMipsAndi, r_dest_src1.GetReg(), r_src2.GetReg(), 0xFFFF);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700330 default:
331 LOG(FATAL) << "Bad case in OpRegReg";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700332 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700333 }
buzbee2700f7e2014-03-07 09:46:20 -0800334 return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700335}
336
buzbee2700f7e2014-03-07 09:46:20 -0800337LIR* MipsMir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset,
338 MoveType move_type) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700339 UNUSED(r_dest, r_base, offset, move_type);
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800340 UNIMPLEMENTED(FATAL);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700341 UNREACHABLE();
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800342}
343
buzbee2700f7e2014-03-07 09:46:20 -0800344LIR* MipsMir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700345 UNUSED(r_base, offset, r_src, move_type);
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800346 UNIMPLEMENTED(FATAL);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700347 UNREACHABLE();
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800348}
349
buzbee2700f7e2014-03-07 09:46:20 -0800350LIR* MipsMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700351 UNUSED(op, cc, r_dest, r_src);
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800352 LOG(FATAL) << "Unexpected use of OpCondRegReg for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700353 UNREACHABLE();
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800354}
355
buzbee2700f7e2014-03-07 09:46:20 -0800356LIR* MipsMir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700357 LIR *res;
Douglas Leung2db3e262014-06-25 16:02:55 -0700358 if (!r_dest.IsPair()) {
359 // Form 64-bit pair
360 r_dest = Solo64ToPair64(r_dest);
361 }
buzbee2700f7e2014-03-07 09:46:20 -0800362 res = LoadConstantNoClobber(r_dest.GetLow(), Low32Bits(value));
363 LoadConstantNoClobber(r_dest.GetHigh(), High32Bits(value));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700364 return res;
365}
366
367/* Load value from base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800368LIR* MipsMir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700369 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700370 LIR *first = NULL;
371 LIR *res;
372 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800373 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700374
buzbee091cc402014-03-31 10:14:40 -0700375 if (r_dest.IsFloat()) {
376 DCHECK(r_dest.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700377 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700378 size = kSingle;
379 } else {
380 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700381 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700382 }
383
384 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800385 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700386 } else {
387 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800388 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700389 }
390
391 switch (size) {
392 case kSingle:
393 opcode = kMipsFlwc1;
394 break;
buzbee695d13a2014-04-19 13:32:20 -0700395 case k32:
396 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700397 opcode = kMipsLw;
398 break;
399 case kUnsignedHalf:
400 opcode = kMipsLhu;
401 break;
402 case kSignedHalf:
403 opcode = kMipsLh;
404 break;
405 case kUnsignedByte:
406 opcode = kMipsLbu;
407 break;
408 case kSignedByte:
409 opcode = kMipsLb;
410 break;
411 default:
412 LOG(FATAL) << "Bad case in LoadBaseIndexed";
413 }
414
buzbee2700f7e2014-03-07 09:46:20 -0800415 res = NewLIR3(opcode, r_dest.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700416 FreeTemp(t_reg);
417 return (first) ? first : res;
418}
419
420/* store value base base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800421LIR* MipsMir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700422 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700423 LIR *first = NULL;
424 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800425 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700426
buzbee091cc402014-03-31 10:14:40 -0700427 if (r_src.IsFloat()) {
428 DCHECK(r_src.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700429 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700430 size = kSingle;
431 } else {
432 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700433 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700434 }
435
436 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800437 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700438 } else {
439 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800440 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700441 }
442
443 switch (size) {
444 case kSingle:
445 opcode = kMipsFswc1;
446 break;
buzbee695d13a2014-04-19 13:32:20 -0700447 case k32:
448 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700449 opcode = kMipsSw;
450 break;
451 case kUnsignedHalf:
452 case kSignedHalf:
453 opcode = kMipsSh;
454 break;
455 case kUnsignedByte:
456 case kSignedByte:
457 opcode = kMipsSb;
458 break;
459 default:
460 LOG(FATAL) << "Bad case in StoreBaseIndexed";
461 }
buzbee2700f7e2014-03-07 09:46:20 -0800462 NewLIR3(opcode, r_src.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700463 return first;
464}
465
buzbee2700f7e2014-03-07 09:46:20 -0800466// FIXME: don't split r_dest into 2 containers.
467LIR* MipsMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
Douglas Leung2db3e262014-06-25 16:02:55 -0700468 OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700469/*
470 * Load value from base + displacement. Optionally perform null check
471 * on base (which must have an associated s_reg and MIR). If not
472 * performing null check, incoming MIR can be null. IMPORTANT: this
473 * code must not allocate any new temps. If a new register is needed
474 * and base and dest are the same, spill some other register to
475 * rlp and then restore.
476 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700477 LIR *res;
478 LIR *load = NULL;
479 LIR *load2 = NULL;
480 MipsOpCode opcode = kMipsNop;
481 bool short_form = IS_SIMM16(displacement);
Douglas Leung2db3e262014-06-25 16:02:55 -0700482 bool pair = r_dest.IsPair();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700483
484 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700485 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700486 case kDouble:
Douglas Leung2db3e262014-06-25 16:02:55 -0700487 if (!pair) {
488 // Form 64-bit pair
489 r_dest = Solo64ToPair64(r_dest);
490 pair = 1;
491 }
buzbee091cc402014-03-31 10:14:40 -0700492 if (r_dest.IsFloat()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700493 DCHECK_EQ(r_dest.GetLowReg(), r_dest.GetHighReg() - 1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700494 opcode = kMipsFlwc1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700495 } else {
496 opcode = kMipsLw;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700497 }
498 short_form = IS_SIMM16_2WORD(displacement);
499 DCHECK_EQ((displacement & 0x3), 0);
500 break;
buzbee695d13a2014-04-19 13:32:20 -0700501 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700502 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700503 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700504 opcode = kMipsLw;
buzbee091cc402014-03-31 10:14:40 -0700505 if (r_dest.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700506 opcode = kMipsFlwc1;
buzbee091cc402014-03-31 10:14:40 -0700507 DCHECK(r_dest.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700508 }
509 DCHECK_EQ((displacement & 0x3), 0);
510 break;
511 case kUnsignedHalf:
512 opcode = kMipsLhu;
513 DCHECK_EQ((displacement & 0x1), 0);
514 break;
515 case kSignedHalf:
516 opcode = kMipsLh;
517 DCHECK_EQ((displacement & 0x1), 0);
518 break;
519 case kUnsignedByte:
520 opcode = kMipsLbu;
521 break;
522 case kSignedByte:
523 opcode = kMipsLb;
524 break;
525 default:
526 LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
527 }
528
529 if (short_form) {
530 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800531 load = res = NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700532 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700533 load = res = NewLIR3(opcode, r_dest.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
534 load2 = NewLIR3(opcode, r_dest.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700535 }
536 } else {
537 if (pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800538 RegStorage r_tmp = AllocTemp();
539 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
Douglas Leung2db3e262014-06-25 16:02:55 -0700540 load = NewLIR3(opcode, r_dest.GetLowReg(), LOWORD_OFFSET, r_tmp.GetReg());
541 load2 = NewLIR3(opcode, r_dest.GetHighReg(), HIWORD_OFFSET, r_tmp.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700542 FreeTemp(r_tmp);
543 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800544 RegStorage r_tmp = (r_base == r_dest) ? AllocTemp() : r_dest;
545 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
546 load = NewLIR3(opcode, r_dest.GetReg(), 0, r_tmp.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700547 if (r_tmp != r_dest)
548 FreeTemp(r_tmp);
549 }
550 }
551
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100552 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
Ian Rogersb28c1c02014-11-08 11:21:21 -0800553 DCHECK_EQ(r_base, rs_rMIPS_SP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700554 AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
555 true /* is_load */, pair /* is64bit */);
556 if (pair) {
557 AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
558 true /* is_load */, pair /* is64bit */);
559 }
560 }
561 return load;
562}
563
Andreas Gampede686762014-06-24 18:42:06 +0000564LIR* MipsMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000565 OpSize size, VolatileKind is_volatile) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700566 if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble))) {
567 // Do atomic 64-bit load.
568 return GenAtomic64Load(r_base, displacement, r_dest);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000569 }
570
buzbee695d13a2014-04-19 13:32:20 -0700571 // TODO: base this on target.
572 if (size == kWord) {
573 size = k32;
574 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000575 LIR* load;
Douglas Leung2db3e262014-06-25 16:02:55 -0700576 load = LoadBaseDispBody(r_base, displacement, r_dest, size);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000577
578 if (UNLIKELY(is_volatile == kVolatile)) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700579 GenMemBarrier(kLoadAny);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000580 }
581
582 return load;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700583}
584
Vladimir Marko455759b2014-05-06 20:49:36 +0100585// FIXME: don't split r_dest into 2 containers.
buzbee2700f7e2014-03-07 09:46:20 -0800586LIR* MipsMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement,
Douglas Leung2db3e262014-06-25 16:02:55 -0700587 RegStorage r_src, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700588 LIR *res;
589 LIR *store = NULL;
590 LIR *store2 = NULL;
591 MipsOpCode opcode = kMipsNop;
592 bool short_form = IS_SIMM16(displacement);
buzbee091cc402014-03-31 10:14:40 -0700593 bool pair = r_src.IsPair();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700594
595 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700596 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700597 case kDouble:
Douglas Leung2db3e262014-06-25 16:02:55 -0700598 if (!pair) {
599 // Form 64-bit pair
600 r_src = Solo64ToPair64(r_src);
601 pair = 1;
602 }
buzbee091cc402014-03-31 10:14:40 -0700603 if (r_src.IsFloat()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700604 DCHECK_EQ(r_src.GetLowReg(), r_src.GetHighReg() - 1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700605 opcode = kMipsFswc1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700606 } else {
607 opcode = kMipsSw;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700608 }
609 short_form = IS_SIMM16_2WORD(displacement);
610 DCHECK_EQ((displacement & 0x3), 0);
611 break;
buzbee695d13a2014-04-19 13:32:20 -0700612 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700613 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700614 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700615 opcode = kMipsSw;
buzbee091cc402014-03-31 10:14:40 -0700616 if (r_src.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700617 opcode = kMipsFswc1;
buzbee091cc402014-03-31 10:14:40 -0700618 DCHECK(r_src.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700619 }
620 DCHECK_EQ((displacement & 0x3), 0);
621 break;
622 case kUnsignedHalf:
623 case kSignedHalf:
624 opcode = kMipsSh;
625 DCHECK_EQ((displacement & 0x1), 0);
626 break;
627 case kUnsignedByte:
628 case kSignedByte:
629 opcode = kMipsSb;
630 break;
631 default:
buzbee2700f7e2014-03-07 09:46:20 -0800632 LOG(FATAL) << "Bad case in StoreBaseDispBody";
Brian Carlstrom7940e442013-07-12 13:46:57 -0700633 }
634
635 if (short_form) {
636 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800637 store = res = NewLIR3(opcode, r_src.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700638 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700639 store = res = NewLIR3(opcode, r_src.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
640 store2 = NewLIR3(opcode, r_src.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700641 }
642 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800643 RegStorage r_scratch = AllocTemp();
644 res = OpRegRegImm(kOpAdd, r_scratch, r_base, displacement);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700645 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800646 store = NewLIR3(opcode, r_src.GetReg(), 0, r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700647 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700648 store = NewLIR3(opcode, r_src.GetLowReg(), LOWORD_OFFSET, r_scratch.GetReg());
649 store2 = NewLIR3(opcode, r_src.GetHighReg(), HIWORD_OFFSET, r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700650 }
651 FreeTemp(r_scratch);
652 }
653
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100654 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
Ian Rogersb28c1c02014-11-08 11:21:21 -0800655 DCHECK_EQ(r_base, rs_rMIPS_SP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700656 AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
657 false /* is_load */, pair /* is64bit */);
658 if (pair) {
659 AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
660 false /* is_load */, pair /* is64bit */);
661 }
662 }
663
664 return res;
665}
666
Andreas Gampede686762014-06-24 18:42:06 +0000667LIR* MipsMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000668 OpSize size, VolatileKind is_volatile) {
669 if (is_volatile == kVolatile) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700670 // Ensure that prior accesses become visible to other threads first.
671 GenMemBarrier(kAnyStore);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000672 }
673
Andreas Gampe3c12c512014-06-24 18:46:29 +0000674 LIR* store;
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700675 if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble))) {
676 // Do atomic 64-bit load.
677 store = GenAtomic64Store(r_base, displacement, r_src);
678 } else {
679 // TODO: base this on target.
680 if (size == kWord) {
681 size = k32;
682 }
683 store = StoreBaseDispBody(r_base, displacement, r_src, size);
684 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000685
686 if (UNLIKELY(is_volatile == kVolatile)) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700687 // Preserve order with respect to any subsequent volatile loads.
688 // We need StoreLoad, but that generally requires the most expensive barrier.
689 GenMemBarrier(kAnyAny);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000690 }
691
692 return store;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700693}
694
buzbee2700f7e2014-03-07 09:46:20 -0800695LIR* MipsMir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700696 UNUSED(op, r_base, disp);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700697 LOG(FATAL) << "Unexpected use of OpMem for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700698 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700699}
700
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700701LIR* MipsMir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700702 UNUSED(cc, target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700703 LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700704 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700705}
706
Andreas Gampe98430592014-07-27 19:44:50 -0700707LIR* MipsMir2Lir::InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700708 UNUSED(trampoline); // The address of the trampoline is already loaded into r_tgt.
Andreas Gampe98430592014-07-27 19:44:50 -0700709 return OpReg(op, r_tgt);
710}
711
Brian Carlstrom7940e442013-07-12 13:46:57 -0700712} // namespace art