blob: 18f1cde353806cb24e6fe2ff71dc85afa4312e5a [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"
Brian Carlstrom7940e442013-07-12 13:46:57 -070020#include "dex/quick/mir_to_lir-inl.h"
buzbeeb5860fb2014-06-21 15:31:01 -070021#include "dex/reg_storage_eq.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070022#include "mips_lir.h"
23
24namespace art {
25
26/* This file contains codegen for the MIPS32 ISA. */
buzbee2700f7e2014-03-07 09:46:20 -080027LIR* MipsMir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070028 int opcode;
29 /* must be both DOUBLE or both not DOUBLE */
buzbee091cc402014-03-31 10:14:40 -070030 DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble());
31 if (r_dest.IsDouble()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070032 opcode = kMipsFmovd;
33 } else {
buzbee091cc402014-03-31 10:14:40 -070034 if (r_dest.IsSingle()) {
35 if (r_src.IsSingle()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070036 opcode = kMipsFmovs;
37 } else {
38 /* note the operands are swapped for the mtc1 instr */
buzbee2700f7e2014-03-07 09:46:20 -080039 RegStorage t_opnd = r_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -070040 r_src = r_dest;
41 r_dest = t_opnd;
42 opcode = kMipsMtc1;
43 }
44 } else {
buzbee091cc402014-03-31 10:14:40 -070045 DCHECK(r_src.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070046 opcode = kMipsMfc1;
47 }
48 }
buzbee2700f7e2014-03-07 09:46:20 -080049 LIR* res = RawLIR(current_dalvik_offset_, opcode, r_src.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -070050 if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
51 res->flags.is_nop = true;
52 }
53 return res;
54}
55
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070056bool MipsMir2Lir::InexpensiveConstantInt(int32_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070057 return ((value == 0) || IsUint(16, value) || ((value < 0) && (value >= -32768)));
58}
59
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070060bool MipsMir2Lir::InexpensiveConstantFloat(int32_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070061 UNUSED(value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070062 return false; // TUNING
63}
64
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070065bool MipsMir2Lir::InexpensiveConstantLong(int64_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070066 UNUSED(value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070067 return false; // TUNING
68}
69
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070070bool MipsMir2Lir::InexpensiveConstantDouble(int64_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070071 UNUSED(value);
Brian Carlstrom7934ac22013-07-26 10:54:15 -070072 return false; // TUNING
Brian Carlstrom7940e442013-07-12 13:46:57 -070073}
74
75/*
76 * Load a immediate using a shortcut if possible; otherwise
77 * grab from the per-translation literal pool. If target is
78 * a high register, build constant into a low register and copy.
79 *
80 * No additional register clobbering operation performed. Use this version when
81 * 1) r_dest is freshly returned from AllocTemp or
82 * 2) The codegen is under fixed register usage
83 */
buzbee2700f7e2014-03-07 09:46:20 -080084LIR* MipsMir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070085 LIR *res;
86
buzbee2700f7e2014-03-07 09:46:20 -080087 RegStorage r_dest_save = r_dest;
buzbee091cc402014-03-31 10:14:40 -070088 int is_fp_reg = r_dest.IsFloat();
Brian Carlstrom7940e442013-07-12 13:46:57 -070089 if (is_fp_reg) {
buzbee091cc402014-03-31 10:14:40 -070090 DCHECK(r_dest.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070091 r_dest = AllocTemp();
92 }
93
94 /* See if the value can be constructed cheaply */
95 if (value == 0) {
buzbee2700f7e2014-03-07 09:46:20 -080096 res = NewLIR2(kMipsMove, r_dest.GetReg(), rZERO);
Brian Carlstrom7940e442013-07-12 13:46:57 -070097 } else if ((value > 0) && (value <= 65535)) {
buzbee2700f7e2014-03-07 09:46:20 -080098 res = NewLIR3(kMipsOri, r_dest.GetReg(), rZERO, value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070099 } else if ((value < 0) && (value >= -32768)) {
buzbee2700f7e2014-03-07 09:46:20 -0800100 res = NewLIR3(kMipsAddiu, r_dest.GetReg(), rZERO, value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700101 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800102 res = NewLIR2(kMipsLui, r_dest.GetReg(), value >> 16);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700103 if (value & 0xffff)
buzbee2700f7e2014-03-07 09:46:20 -0800104 NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700105 }
106
107 if (is_fp_reg) {
buzbee2700f7e2014-03-07 09:46:20 -0800108 NewLIR2(kMipsMtc1, r_dest.GetReg(), r_dest_save.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700109 FreeTemp(r_dest);
110 }
111
112 return res;
113}
114
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700115LIR* MipsMir2Lir::OpUnconditionalBranch(LIR* target) {
Brian Carlstromdf629502013-07-17 22:39:56 -0700116 LIR* res = NewLIR1(kMipsB, 0 /* offset to be patched during assembly*/);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700117 res->target = target;
118 return res;
119}
120
buzbee2700f7e2014-03-07 09:46:20 -0800121LIR* MipsMir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700122 MipsOpCode opcode = kMipsNop;
123 switch (op) {
124 case kOpBlx:
125 opcode = kMipsJalr;
126 break;
127 case kOpBx:
buzbee2700f7e2014-03-07 09:46:20 -0800128 return NewLIR1(kMipsJr, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700129 break;
130 default:
131 LOG(FATAL) << "Bad case in OpReg";
132 }
buzbee2700f7e2014-03-07 09:46:20 -0800133 return NewLIR2(opcode, rRA, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700134}
135
buzbee2700f7e2014-03-07 09:46:20 -0800136LIR* MipsMir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700137 LIR *res;
138 bool neg = (value < 0);
139 int abs_value = (neg) ? -value : value;
140 bool short_form = (abs_value & 0xff) == abs_value;
141 MipsOpCode opcode = kMipsNop;
142 switch (op) {
143 case kOpAdd:
144 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
145 break;
146 case kOpSub:
147 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
148 break;
149 default:
150 LOG(FATAL) << "Bad case in OpRegImm";
151 break;
152 }
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700153 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800154 res = NewLIR2(opcode, r_dest_src1.GetReg(), abs_value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700155 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800156 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700157 res = LoadConstant(r_scratch, value);
158 if (op == kOpCmp)
buzbee2700f7e2014-03-07 09:46:20 -0800159 NewLIR2(opcode, r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700160 else
buzbee2700f7e2014-03-07 09:46:20 -0800161 NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700162 }
163 return res;
164}
165
buzbee2700f7e2014-03-07 09:46:20 -0800166LIR* MipsMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700167 MipsOpCode opcode = kMipsNop;
168 switch (op) {
169 case kOpAdd:
170 opcode = kMipsAddu;
171 break;
172 case kOpSub:
173 opcode = kMipsSubu;
174 break;
175 case kOpAnd:
176 opcode = kMipsAnd;
177 break;
178 case kOpMul:
179 opcode = kMipsMul;
180 break;
181 case kOpOr:
182 opcode = kMipsOr;
183 break;
184 case kOpXor:
185 opcode = kMipsXor;
186 break;
187 case kOpLsl:
188 opcode = kMipsSllv;
189 break;
190 case kOpLsr:
191 opcode = kMipsSrlv;
192 break;
193 case kOpAsr:
194 opcode = kMipsSrav;
195 break;
196 case kOpAdc:
197 case kOpSbc:
198 LOG(FATAL) << "No carry bit on MIPS";
199 break;
200 default:
201 LOG(FATAL) << "bad case in OpRegRegReg";
202 break;
203 }
buzbee2700f7e2014-03-07 09:46:20 -0800204 return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700205}
206
buzbee2700f7e2014-03-07 09:46:20 -0800207LIR* MipsMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700208 LIR *res;
209 MipsOpCode opcode = kMipsNop;
210 bool short_form = true;
211
212 switch (op) {
213 case kOpAdd:
214 if (IS_SIMM16(value)) {
215 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700216 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700217 short_form = false;
218 opcode = kMipsAddu;
219 }
220 break;
221 case kOpSub:
222 if (IS_SIMM16((-value))) {
223 value = -value;
224 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700225 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700226 short_form = false;
227 opcode = kMipsSubu;
228 }
229 break;
230 case kOpLsl:
231 DCHECK(value >= 0 && value <= 31);
232 opcode = kMipsSll;
233 break;
234 case kOpLsr:
235 DCHECK(value >= 0 && value <= 31);
236 opcode = kMipsSrl;
237 break;
238 case kOpAsr:
239 DCHECK(value >= 0 && value <= 31);
240 opcode = kMipsSra;
241 break;
242 case kOpAnd:
243 if (IS_UIMM16((value))) {
244 opcode = kMipsAndi;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700245 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700246 short_form = false;
247 opcode = kMipsAnd;
248 }
249 break;
250 case kOpOr:
251 if (IS_UIMM16((value))) {
252 opcode = kMipsOri;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700253 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700254 short_form = false;
255 opcode = kMipsOr;
256 }
257 break;
258 case kOpXor:
259 if (IS_UIMM16((value))) {
260 opcode = kMipsXori;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700261 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700262 short_form = false;
263 opcode = kMipsXor;
264 }
265 break;
266 case kOpMul:
267 short_form = false;
268 opcode = kMipsMul;
269 break;
270 default:
271 LOG(FATAL) << "Bad case in OpRegRegImm";
272 break;
273 }
274
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700275 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800276 res = NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700277 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700278 if (r_dest != r_src1) {
279 res = LoadConstant(r_dest, value);
buzbee2700f7e2014-03-07 09:46:20 -0800280 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700281 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800282 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700283 res = LoadConstant(r_scratch, value);
buzbee2700f7e2014-03-07 09:46:20 -0800284 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700285 }
286 }
287 return res;
288}
289
buzbee2700f7e2014-03-07 09:46:20 -0800290LIR* MipsMir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700291 MipsOpCode opcode = kMipsNop;
292 LIR *res;
293 switch (op) {
294 case kOpMov:
295 opcode = kMipsMove;
296 break;
297 case kOpMvn:
buzbee2700f7e2014-03-07 09:46:20 -0800298 return NewLIR3(kMipsNor, r_dest_src1.GetReg(), r_src2.GetReg(), rZERO);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700299 case kOpNeg:
buzbee2700f7e2014-03-07 09:46:20 -0800300 return NewLIR3(kMipsSubu, r_dest_src1.GetReg(), rZERO, r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700301 case kOpAdd:
302 case kOpAnd:
303 case kOpMul:
304 case kOpOr:
305 case kOpSub:
306 case kOpXor:
307 return OpRegRegReg(op, r_dest_src1, r_dest_src1, r_src2);
308 case kOp2Byte:
Ian Rogersd582fa42014-11-05 23:46:43 -0800309 if (cu_->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
310 ->IsMipsIsaRevGreaterThanEqual2()) {
311 res = NewLIR2(kMipsSeb, r_dest_src1.GetReg(), r_src2.GetReg());
312 } else {
313 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 24);
314 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 24);
315 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700316 return res;
317 case kOp2Short:
Ian Rogersd582fa42014-11-05 23:46:43 -0800318 if (cu_->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
319 ->IsMipsIsaRevGreaterThanEqual2()) {
320 res = NewLIR2(kMipsSeh, r_dest_src1.GetReg(), r_src2.GetReg());
321 } else {
322 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 16);
323 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 16);
324 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700325 return res;
326 case kOp2Char:
buzbee2700f7e2014-03-07 09:46:20 -0800327 return NewLIR3(kMipsAndi, r_dest_src1.GetReg(), r_src2.GetReg(), 0xFFFF);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700328 default:
329 LOG(FATAL) << "Bad case in OpRegReg";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700330 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700331 }
buzbee2700f7e2014-03-07 09:46:20 -0800332 return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700333}
334
buzbee2700f7e2014-03-07 09:46:20 -0800335LIR* MipsMir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset,
336 MoveType move_type) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700337 UNUSED(r_dest, r_base, offset, move_type);
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800338 UNIMPLEMENTED(FATAL);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700339 UNREACHABLE();
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800340}
341
buzbee2700f7e2014-03-07 09:46:20 -0800342LIR* MipsMir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700343 UNUSED(r_base, offset, r_src, move_type);
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800344 UNIMPLEMENTED(FATAL);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700345 UNREACHABLE();
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800346}
347
buzbee2700f7e2014-03-07 09:46:20 -0800348LIR* MipsMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700349 UNUSED(op, cc, r_dest, r_src);
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800350 LOG(FATAL) << "Unexpected use of OpCondRegReg for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700351 UNREACHABLE();
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800352}
353
buzbee2700f7e2014-03-07 09:46:20 -0800354LIR* MipsMir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700355 LIR *res;
Douglas Leung2db3e262014-06-25 16:02:55 -0700356 if (!r_dest.IsPair()) {
357 // Form 64-bit pair
358 r_dest = Solo64ToPair64(r_dest);
359 }
buzbee2700f7e2014-03-07 09:46:20 -0800360 res = LoadConstantNoClobber(r_dest.GetLow(), Low32Bits(value));
361 LoadConstantNoClobber(r_dest.GetHigh(), High32Bits(value));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700362 return res;
363}
364
365/* Load value from base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800366LIR* MipsMir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700367 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700368 LIR *first = NULL;
369 LIR *res;
370 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800371 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700372
buzbee091cc402014-03-31 10:14:40 -0700373 if (r_dest.IsFloat()) {
374 DCHECK(r_dest.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700375 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700376 size = kSingle;
377 } else {
378 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700379 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700380 }
381
382 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800383 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700384 } else {
385 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800386 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700387 }
388
389 switch (size) {
390 case kSingle:
391 opcode = kMipsFlwc1;
392 break;
buzbee695d13a2014-04-19 13:32:20 -0700393 case k32:
394 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700395 opcode = kMipsLw;
396 break;
397 case kUnsignedHalf:
398 opcode = kMipsLhu;
399 break;
400 case kSignedHalf:
401 opcode = kMipsLh;
402 break;
403 case kUnsignedByte:
404 opcode = kMipsLbu;
405 break;
406 case kSignedByte:
407 opcode = kMipsLb;
408 break;
409 default:
410 LOG(FATAL) << "Bad case in LoadBaseIndexed";
411 }
412
buzbee2700f7e2014-03-07 09:46:20 -0800413 res = NewLIR3(opcode, r_dest.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700414 FreeTemp(t_reg);
415 return (first) ? first : res;
416}
417
418/* store value base base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800419LIR* MipsMir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700420 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700421 LIR *first = NULL;
422 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800423 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700424
buzbee091cc402014-03-31 10:14:40 -0700425 if (r_src.IsFloat()) {
426 DCHECK(r_src.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700427 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700428 size = kSingle;
429 } else {
430 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700431 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700432 }
433
434 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800435 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700436 } else {
437 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800438 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700439 }
440
441 switch (size) {
442 case kSingle:
443 opcode = kMipsFswc1;
444 break;
buzbee695d13a2014-04-19 13:32:20 -0700445 case k32:
446 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700447 opcode = kMipsSw;
448 break;
449 case kUnsignedHalf:
450 case kSignedHalf:
451 opcode = kMipsSh;
452 break;
453 case kUnsignedByte:
454 case kSignedByte:
455 opcode = kMipsSb;
456 break;
457 default:
458 LOG(FATAL) << "Bad case in StoreBaseIndexed";
459 }
buzbee2700f7e2014-03-07 09:46:20 -0800460 NewLIR3(opcode, r_src.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700461 return first;
462}
463
buzbee2700f7e2014-03-07 09:46:20 -0800464// FIXME: don't split r_dest into 2 containers.
465LIR* MipsMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
Douglas Leung2db3e262014-06-25 16:02:55 -0700466 OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700467/*
468 * Load value from base + displacement. Optionally perform null check
469 * on base (which must have an associated s_reg and MIR). If not
470 * performing null check, incoming MIR can be null. IMPORTANT: this
471 * code must not allocate any new temps. If a new register is needed
472 * and base and dest are the same, spill some other register to
473 * rlp and then restore.
474 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700475 LIR *res;
476 LIR *load = NULL;
477 LIR *load2 = NULL;
478 MipsOpCode opcode = kMipsNop;
479 bool short_form = IS_SIMM16(displacement);
Douglas Leung2db3e262014-06-25 16:02:55 -0700480 bool pair = r_dest.IsPair();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700481
482 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700483 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700484 case kDouble:
Douglas Leung2db3e262014-06-25 16:02:55 -0700485 if (!pair) {
486 // Form 64-bit pair
487 r_dest = Solo64ToPair64(r_dest);
488 pair = 1;
489 }
buzbee091cc402014-03-31 10:14:40 -0700490 if (r_dest.IsFloat()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700491 DCHECK_EQ(r_dest.GetLowReg(), r_dest.GetHighReg() - 1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700492 opcode = kMipsFlwc1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700493 } else {
494 opcode = kMipsLw;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700495 }
496 short_form = IS_SIMM16_2WORD(displacement);
497 DCHECK_EQ((displacement & 0x3), 0);
498 break;
buzbee695d13a2014-04-19 13:32:20 -0700499 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700500 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700501 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700502 opcode = kMipsLw;
buzbee091cc402014-03-31 10:14:40 -0700503 if (r_dest.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700504 opcode = kMipsFlwc1;
buzbee091cc402014-03-31 10:14:40 -0700505 DCHECK(r_dest.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700506 }
507 DCHECK_EQ((displacement & 0x3), 0);
508 break;
509 case kUnsignedHalf:
510 opcode = kMipsLhu;
511 DCHECK_EQ((displacement & 0x1), 0);
512 break;
513 case kSignedHalf:
514 opcode = kMipsLh;
515 DCHECK_EQ((displacement & 0x1), 0);
516 break;
517 case kUnsignedByte:
518 opcode = kMipsLbu;
519 break;
520 case kSignedByte:
521 opcode = kMipsLb;
522 break;
523 default:
524 LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
525 }
526
527 if (short_form) {
528 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800529 load = res = NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700530 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700531 load = res = NewLIR3(opcode, r_dest.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
532 load2 = NewLIR3(opcode, r_dest.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700533 }
534 } else {
535 if (pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800536 RegStorage r_tmp = AllocTemp();
537 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
Douglas Leung2db3e262014-06-25 16:02:55 -0700538 load = NewLIR3(opcode, r_dest.GetLowReg(), LOWORD_OFFSET, r_tmp.GetReg());
539 load2 = NewLIR3(opcode, r_dest.GetHighReg(), HIWORD_OFFSET, r_tmp.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700540 FreeTemp(r_tmp);
541 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800542 RegStorage r_tmp = (r_base == r_dest) ? AllocTemp() : r_dest;
543 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
544 load = NewLIR3(opcode, r_dest.GetReg(), 0, r_tmp.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700545 if (r_tmp != r_dest)
546 FreeTemp(r_tmp);
547 }
548 }
549
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100550 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
Ian Rogersb28c1c02014-11-08 11:21:21 -0800551 DCHECK_EQ(r_base, rs_rMIPS_SP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700552 AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
553 true /* is_load */, pair /* is64bit */);
554 if (pair) {
555 AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
556 true /* is_load */, pair /* is64bit */);
557 }
558 }
559 return load;
560}
561
Andreas Gampede686762014-06-24 18:42:06 +0000562LIR* MipsMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000563 OpSize size, VolatileKind is_volatile) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700564 if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble))) {
565 // Do atomic 64-bit load.
566 return GenAtomic64Load(r_base, displacement, r_dest);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000567 }
568
buzbee695d13a2014-04-19 13:32:20 -0700569 // TODO: base this on target.
570 if (size == kWord) {
571 size = k32;
572 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000573 LIR* load;
Douglas Leung2db3e262014-06-25 16:02:55 -0700574 load = LoadBaseDispBody(r_base, displacement, r_dest, size);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000575
576 if (UNLIKELY(is_volatile == kVolatile)) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700577 GenMemBarrier(kLoadAny);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000578 }
579
580 return load;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700581}
582
Vladimir Marko455759b2014-05-06 20:49:36 +0100583// FIXME: don't split r_dest into 2 containers.
buzbee2700f7e2014-03-07 09:46:20 -0800584LIR* MipsMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement,
Douglas Leung2db3e262014-06-25 16:02:55 -0700585 RegStorage r_src, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700586 LIR *res;
587 LIR *store = NULL;
588 LIR *store2 = NULL;
589 MipsOpCode opcode = kMipsNop;
590 bool short_form = IS_SIMM16(displacement);
buzbee091cc402014-03-31 10:14:40 -0700591 bool pair = r_src.IsPair();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700592
593 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700594 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700595 case kDouble:
Douglas Leung2db3e262014-06-25 16:02:55 -0700596 if (!pair) {
597 // Form 64-bit pair
598 r_src = Solo64ToPair64(r_src);
599 pair = 1;
600 }
buzbee091cc402014-03-31 10:14:40 -0700601 if (r_src.IsFloat()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700602 DCHECK_EQ(r_src.GetLowReg(), r_src.GetHighReg() - 1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700603 opcode = kMipsFswc1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700604 } else {
605 opcode = kMipsSw;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700606 }
607 short_form = IS_SIMM16_2WORD(displacement);
608 DCHECK_EQ((displacement & 0x3), 0);
609 break;
buzbee695d13a2014-04-19 13:32:20 -0700610 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700611 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700612 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700613 opcode = kMipsSw;
buzbee091cc402014-03-31 10:14:40 -0700614 if (r_src.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700615 opcode = kMipsFswc1;
buzbee091cc402014-03-31 10:14:40 -0700616 DCHECK(r_src.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700617 }
618 DCHECK_EQ((displacement & 0x3), 0);
619 break;
620 case kUnsignedHalf:
621 case kSignedHalf:
622 opcode = kMipsSh;
623 DCHECK_EQ((displacement & 0x1), 0);
624 break;
625 case kUnsignedByte:
626 case kSignedByte:
627 opcode = kMipsSb;
628 break;
629 default:
buzbee2700f7e2014-03-07 09:46:20 -0800630 LOG(FATAL) << "Bad case in StoreBaseDispBody";
Brian Carlstrom7940e442013-07-12 13:46:57 -0700631 }
632
633 if (short_form) {
634 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800635 store = res = NewLIR3(opcode, r_src.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700636 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700637 store = res = NewLIR3(opcode, r_src.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
638 store2 = NewLIR3(opcode, r_src.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700639 }
640 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800641 RegStorage r_scratch = AllocTemp();
642 res = OpRegRegImm(kOpAdd, r_scratch, r_base, displacement);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700643 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800644 store = NewLIR3(opcode, r_src.GetReg(), 0, r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700645 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700646 store = NewLIR3(opcode, r_src.GetLowReg(), LOWORD_OFFSET, r_scratch.GetReg());
647 store2 = NewLIR3(opcode, r_src.GetHighReg(), HIWORD_OFFSET, r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700648 }
649 FreeTemp(r_scratch);
650 }
651
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100652 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
Ian Rogersb28c1c02014-11-08 11:21:21 -0800653 DCHECK_EQ(r_base, rs_rMIPS_SP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700654 AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
655 false /* is_load */, pair /* is64bit */);
656 if (pair) {
657 AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
658 false /* is_load */, pair /* is64bit */);
659 }
660 }
661
662 return res;
663}
664
Andreas Gampede686762014-06-24 18:42:06 +0000665LIR* MipsMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000666 OpSize size, VolatileKind is_volatile) {
667 if (is_volatile == kVolatile) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700668 // Ensure that prior accesses become visible to other threads first.
669 GenMemBarrier(kAnyStore);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000670 }
671
Andreas Gampe3c12c512014-06-24 18:46:29 +0000672 LIR* store;
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700673 if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble))) {
674 // Do atomic 64-bit load.
675 store = GenAtomic64Store(r_base, displacement, r_src);
676 } else {
677 // TODO: base this on target.
678 if (size == kWord) {
679 size = k32;
680 }
681 store = StoreBaseDispBody(r_base, displacement, r_src, size);
682 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000683
684 if (UNLIKELY(is_volatile == kVolatile)) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700685 // Preserve order with respect to any subsequent volatile loads.
686 // We need StoreLoad, but that generally requires the most expensive barrier.
687 GenMemBarrier(kAnyAny);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000688 }
689
690 return store;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700691}
692
buzbee2700f7e2014-03-07 09:46:20 -0800693LIR* MipsMir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700694 UNUSED(op, r_base, disp);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700695 LOG(FATAL) << "Unexpected use of OpMem for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700696 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700697}
698
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700699LIR* MipsMir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700700 UNUSED(cc, target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700701 LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700702 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700703}
704
Andreas Gampe98430592014-07-27 19:44:50 -0700705LIR* MipsMir2Lir::InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700706 UNUSED(trampoline); // The address of the trampoline is already loaded into r_tgt.
Andreas Gampe98430592014-07-27 19:44:50 -0700707 return OpReg(op, r_tgt);
708}
709
Brian Carlstrom7940e442013-07-12 13:46:57 -0700710} // namespace art