blob: 12d054cf3c1d210a2bd736b8b1c9c65c506000ea [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
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
buzbee02031b12012-11-23 09:41:35 -080017#include "codegen_mips.h"
Brian Carlstrom641ce032013-01-31 15:21:37 -080018#include "compiler/codegen/codegen_util.h"
19#include "compiler/codegen/ralloc_util.h"
20#include "mips_lir.h"
buzbee1bc37c62012-11-20 13:35:41 -080021
buzbeee3acd072012-02-25 17:03:10 -080022namespace art {
23
buzbeeb046e162012-10-30 15:48:42 -070024/* This file contains codegen for the MIPS32 ISA. */
buzbee02031b12012-11-23 09:41:35 -080025LIR* MipsCodegen::OpFpRegCopy(CompilationUnit *cu, int r_dest, int r_src)
buzbeee3acd072012-02-25 17:03:10 -080026{
Bill Buzbeea114add2012-05-03 15:00:40 -070027 int opcode;
28 /* must be both DOUBLE or both not DOUBLE */
buzbeefa57c472012-11-21 12:06:18 -080029 DCHECK_EQ(MIPS_DOUBLEREG(r_dest),MIPS_DOUBLEREG(r_src));
30 if (MIPS_DOUBLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070031 opcode = kMipsFmovd;
32 } else {
buzbeefa57c472012-11-21 12:06:18 -080033 if (MIPS_SINGLEREG(r_dest)) {
34 if (MIPS_SINGLEREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070035 opcode = kMipsFmovs;
36 } else {
37 /* note the operands are swapped for the mtc1 instr */
buzbeefa57c472012-11-21 12:06:18 -080038 int t_opnd = r_src;
39 r_src = r_dest;
40 r_dest = t_opnd;
Bill Buzbeea114add2012-05-03 15:00:40 -070041 opcode = kMipsMtc1;
42 }
buzbeee3acd072012-02-25 17:03:10 -080043 } else {
buzbeefa57c472012-11-21 12:06:18 -080044 DCHECK(MIPS_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -070045 opcode = kMipsMfc1;
buzbeee3acd072012-02-25 17:03:10 -080046 }
Bill Buzbeea114add2012-05-03 15:00:40 -070047 }
buzbeefa57c472012-11-21 12:06:18 -080048 LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_src, r_dest);
49 if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
50 res->flags.is_nop = true;
Bill Buzbeea114add2012-05-03 15:00:40 -070051 }
52 return res;
buzbeee3acd072012-02-25 17:03:10 -080053}
buzbeee3acd072012-02-25 17:03:10 -080054
buzbee4ef3e452012-12-14 13:35:28 -080055bool MipsCodegen::InexpensiveConstantInt(int32_t value)
buzbeee6285f92012-12-06 15:57:46 -080056{
buzbee4ef3e452012-12-14 13:35:28 -080057 return ((value == 0) || IsUint(16, value) || ((value < 0) && (value >= -32768)));
58}
59
60bool MipsCodegen::InexpensiveConstantFloat(int32_t value)
61{
62 return false; // TUNING
63}
64
65bool MipsCodegen::InexpensiveConstantLong(int64_t value)
66{
67 return false; // TUNING
68}
69
70bool MipsCodegen::InexpensiveConstantDouble(int64_t value)
71{
72 return false; // TUNING
buzbeee6285f92012-12-06 15:57:46 -080073}
74
buzbeee3acd072012-02-25 17:03:10 -080075/*
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
buzbeefa57c472012-11-21 12:06:18 -080081 * 1) r_dest is freshly returned from AllocTemp or
buzbeee3acd072012-02-25 17:03:10 -080082 * 2) The codegen is under fixed register usage
83 */
buzbee02031b12012-11-23 09:41:35 -080084LIR* MipsCodegen::LoadConstantNoClobber(CompilationUnit *cu, int r_dest, int value)
buzbeee3acd072012-02-25 17:03:10 -080085{
Bill Buzbeea114add2012-05-03 15:00:40 -070086 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -080087
buzbeefa57c472012-11-21 12:06:18 -080088 int r_dest_save = r_dest;
89 int is_fp_reg = MIPS_FPREG(r_dest);
90 if (is_fp_reg) {
91 DCHECK(MIPS_SINGLEREG(r_dest));
92 r_dest = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -070093 }
buzbeee3acd072012-02-25 17:03:10 -080094
Bill Buzbeea114add2012-05-03 15:00:40 -070095 /* See if the value can be constructed cheaply */
96 if (value == 0) {
buzbeefa57c472012-11-21 12:06:18 -080097 res = NewLIR2(cu, kMipsMove, r_dest, r_ZERO);
Bill Buzbeea114add2012-05-03 15:00:40 -070098 } else if ((value > 0) && (value <= 65535)) {
buzbeefa57c472012-11-21 12:06:18 -080099 res = NewLIR3(cu, kMipsOri, r_dest, r_ZERO, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700100 } else if ((value < 0) && (value >= -32768)) {
buzbeefa57c472012-11-21 12:06:18 -0800101 res = NewLIR3(cu, kMipsAddiu, r_dest, r_ZERO, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700102 } else {
buzbeefa57c472012-11-21 12:06:18 -0800103 res = NewLIR2(cu, kMipsLui, r_dest, value>>16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 if (value & 0xffff)
buzbeefa57c472012-11-21 12:06:18 -0800105 NewLIR3(cu, kMipsOri, r_dest, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700106 }
buzbeee3acd072012-02-25 17:03:10 -0800107
buzbeefa57c472012-11-21 12:06:18 -0800108 if (is_fp_reg) {
109 NewLIR2(cu, kMipsMtc1, r_dest, r_dest_save);
110 FreeTemp(cu, r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 }
buzbeee3acd072012-02-25 17:03:10 -0800112
Bill Buzbeea114add2012-05-03 15:00:40 -0700113 return res;
buzbeee3acd072012-02-25 17:03:10 -0800114}
115
buzbee02031b12012-11-23 09:41:35 -0800116LIR* MipsCodegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target)
buzbeee3acd072012-02-25 17:03:10 -0800117{
buzbee02031b12012-11-23 09:41:35 -0800118 LIR* res = NewLIR1(cu, kMipsB, 0 /* offset to be patched during assembly*/ );
119 res->target = target;
120 return res;
buzbeee3acd072012-02-25 17:03:10 -0800121}
122
buzbee02031b12012-11-23 09:41:35 -0800123LIR* MipsCodegen::OpReg(CompilationUnit *cu, OpKind op, int r_dest_src)
buzbeee3acd072012-02-25 17:03:10 -0800124{
Bill Buzbeea114add2012-05-03 15:00:40 -0700125 MipsOpCode opcode = kMipsNop;
126 switch (op) {
127 case kOpBlx:
128 opcode = kMipsJalr;
129 break;
130 case kOpBx:
buzbeefa57c472012-11-21 12:06:18 -0800131 return NewLIR1(cu, kMipsJr, r_dest_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700132 break;
133 default:
buzbee52a77fc2012-11-20 19:50:46 -0800134 LOG(FATAL) << "Bad case in OpReg";
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 }
buzbeefa57c472012-11-21 12:06:18 -0800136 return NewLIR2(cu, opcode, r_RA, r_dest_src);
buzbeee3acd072012-02-25 17:03:10 -0800137}
138
buzbee02031b12012-11-23 09:41:35 -0800139LIR* MipsCodegen::OpRegImm(CompilationUnit *cu, OpKind op, int r_dest_src1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 int value)
buzbeee3acd072012-02-25 17:03:10 -0800141{
Bill Buzbeea114add2012-05-03 15:00:40 -0700142 LIR *res;
143 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800144 int abs_value = (neg) ? -value : value;
145 bool short_form = (abs_value & 0xff) == abs_value;
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 MipsOpCode opcode = kMipsNop;
147 switch (op) {
148 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800149 return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700150 break;
151 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800152 return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700153 break;
154 default:
buzbee52a77fc2012-11-20 19:50:46 -0800155 LOG(FATAL) << "Bad case in OpRegImm";
Bill Buzbeea114add2012-05-03 15:00:40 -0700156 break;
157 }
buzbeefa57c472012-11-21 12:06:18 -0800158 if (short_form)
159 res = NewLIR2(cu, opcode, r_dest_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700160 else {
buzbeefa57c472012-11-21 12:06:18 -0800161 int r_scratch = AllocTemp(cu);
162 res = LoadConstant(cu, r_scratch, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700163 if (op == kOpCmp)
buzbeefa57c472012-11-21 12:06:18 -0800164 NewLIR2(cu, opcode, r_dest_src1, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700165 else
buzbeefa57c472012-11-21 12:06:18 -0800166 NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700167 }
168 return res;
buzbeee3acd072012-02-25 17:03:10 -0800169}
170
buzbee02031b12012-11-23 09:41:35 -0800171LIR* MipsCodegen::OpRegRegReg(CompilationUnit *cu, OpKind op, int r_dest, int r_src1, int r_src2)
buzbeee3acd072012-02-25 17:03:10 -0800172{
Bill Buzbeea114add2012-05-03 15:00:40 -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:
185 opcode = kMipsMul;
186 break;
187 case kOpOr:
188 opcode = kMipsOr;
189 break;
190 case kOpXor:
191 opcode = kMipsXor;
192 break;
193 case kOpLsl:
194 opcode = kMipsSllv;
195 break;
196 case kOpLsr:
197 opcode = kMipsSrlv;
198 break;
199 case kOpAsr:
200 opcode = kMipsSrav;
201 break;
202 case kOpAdc:
203 case kOpSbc:
204 LOG(FATAL) << "No carry bit on MIPS";
205 break;
206 default:
buzbee52a77fc2012-11-20 19:50:46 -0800207 LOG(FATAL) << "bad case in OpRegRegReg";
Bill Buzbeea114add2012-05-03 15:00:40 -0700208 break;
209 }
buzbeefa57c472012-11-21 12:06:18 -0800210 return NewLIR3(cu, opcode, r_dest, r_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800211}
212
buzbee02031b12012-11-23 09:41:35 -0800213LIR* MipsCodegen::OpRegRegImm(CompilationUnit *cu, OpKind op, int r_dest, int r_src1, int value)
buzbeee3acd072012-02-25 17:03:10 -0800214{
Bill Buzbeea114add2012-05-03 15:00:40 -0700215 LIR *res;
216 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800217 bool short_form = true;
buzbeee3acd072012-02-25 17:03:10 -0800218
Bill Buzbeea114add2012-05-03 15:00:40 -0700219 switch (op) {
220 case kOpAdd:
221 if (IS_SIMM16(value)) {
222 opcode = kMipsAddiu;
223 }
224 else {
buzbeefa57c472012-11-21 12:06:18 -0800225 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700226 opcode = kMipsAddu;
227 }
228 break;
229 case kOpSub:
230 if (IS_SIMM16((-value))) {
231 value = -value;
232 opcode = kMipsAddiu;
233 }
234 else {
buzbeefa57c472012-11-21 12:06:18 -0800235 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700236 opcode = kMipsSubu;
237 }
238 break;
239 case kOpLsl:
240 DCHECK(value >= 0 && value <= 31);
241 opcode = kMipsSll;
242 break;
243 case kOpLsr:
244 DCHECK(value >= 0 && value <= 31);
245 opcode = kMipsSrl;
246 break;
247 case kOpAsr:
248 DCHECK(value >= 0 && value <= 31);
249 opcode = kMipsSra;
250 break;
251 case kOpAnd:
252 if (IS_UIMM16((value))) {
253 opcode = kMipsAndi;
254 }
255 else {
buzbeefa57c472012-11-21 12:06:18 -0800256 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 opcode = kMipsAnd;
258 }
259 break;
260 case kOpOr:
261 if (IS_UIMM16((value))) {
262 opcode = kMipsOri;
263 }
264 else {
buzbeefa57c472012-11-21 12:06:18 -0800265 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700266 opcode = kMipsOr;
267 }
268 break;
269 case kOpXor:
270 if (IS_UIMM16((value))) {
271 opcode = kMipsXori;
272 }
273 else {
buzbeefa57c472012-11-21 12:06:18 -0800274 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700275 opcode = kMipsXor;
276 }
277 break;
278 case kOpMul:
buzbeefa57c472012-11-21 12:06:18 -0800279 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 opcode = kMipsMul;
281 break;
282 default:
buzbee52a77fc2012-11-20 19:50:46 -0800283 LOG(FATAL) << "Bad case in OpRegRegImm";
Bill Buzbeea114add2012-05-03 15:00:40 -0700284 break;
285 }
buzbeee3acd072012-02-25 17:03:10 -0800286
buzbeefa57c472012-11-21 12:06:18 -0800287 if (short_form)
288 res = NewLIR3(cu, opcode, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700289 else {
buzbeefa57c472012-11-21 12:06:18 -0800290 if (r_dest != r_src1) {
291 res = LoadConstant(cu, r_dest, value);
292 NewLIR3(cu, opcode, r_dest, r_src1, r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700293 } else {
buzbeefa57c472012-11-21 12:06:18 -0800294 int r_scratch = AllocTemp(cu);
295 res = LoadConstant(cu, r_scratch, value);
296 NewLIR3(cu, opcode, r_dest, r_src1, r_scratch);
buzbeee3acd072012-02-25 17:03:10 -0800297 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700298 }
299 return res;
buzbeee3acd072012-02-25 17:03:10 -0800300}
301
buzbee02031b12012-11-23 09:41:35 -0800302LIR* MipsCodegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int r_src2)
buzbeee3acd072012-02-25 17:03:10 -0800303{
Bill Buzbeea114add2012-05-03 15:00:40 -0700304 MipsOpCode opcode = kMipsNop;
305 LIR *res;
306 switch (op) {
307 case kOpMov:
308 opcode = kMipsMove;
309 break;
310 case kOpMvn:
buzbeefa57c472012-11-21 12:06:18 -0800311 return NewLIR3(cu, kMipsNor, r_dest_src1, r_src2, r_ZERO);
Bill Buzbeea114add2012-05-03 15:00:40 -0700312 case kOpNeg:
buzbeefa57c472012-11-21 12:06:18 -0800313 return NewLIR3(cu, kMipsSubu, r_dest_src1, r_ZERO, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700314 case kOpAdd:
315 case kOpAnd:
316 case kOpMul:
317 case kOpOr:
318 case kOpSub:
319 case kOpXor:
buzbeefa57c472012-11-21 12:06:18 -0800320 return OpRegRegReg(cu, op, r_dest_src1, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700321 case kOp2Byte:
buzbeee3acd072012-02-25 17:03:10 -0800322#if __mips_isa_rev>=2
buzbeefa57c472012-11-21 12:06:18 -0800323 res = NewLIR2(cu, kMipsSeb, r_dest_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800324#else
buzbeefa57c472012-11-21 12:06:18 -0800325 res = OpRegRegImm(cu, kOpLsl, r_dest_src1, r_src2, 24);
326 OpRegRegImm(cu, kOpAsr, r_dest_src1, r_dest_src1, 24);
buzbeee3acd072012-02-25 17:03:10 -0800327#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700328 return res;
329 case kOp2Short:
buzbeee3acd072012-02-25 17:03:10 -0800330#if __mips_isa_rev>=2
buzbeefa57c472012-11-21 12:06:18 -0800331 res = NewLIR2(cu, kMipsSeh, r_dest_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800332#else
buzbeefa57c472012-11-21 12:06:18 -0800333 res = OpRegRegImm(cu, kOpLsl, r_dest_src1, r_src2, 16);
334 OpRegRegImm(cu, kOpAsr, r_dest_src1, r_dest_src1, 16);
buzbeee3acd072012-02-25 17:03:10 -0800335#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700336 return res;
337 case kOp2Char:
buzbeefa57c472012-11-21 12:06:18 -0800338 return NewLIR3(cu, kMipsAndi, r_dest_src1, r_src2, 0xFFFF);
Bill Buzbeea114add2012-05-03 15:00:40 -0700339 default:
buzbee52a77fc2012-11-20 19:50:46 -0800340 LOG(FATAL) << "Bad case in OpRegReg";
Bill Buzbeea114add2012-05-03 15:00:40 -0700341 break;
342 }
buzbeefa57c472012-11-21 12:06:18 -0800343 return NewLIR2(cu, opcode, r_dest_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800344}
345
buzbee4ef3e452012-12-14 13:35:28 -0800346LIR* MipsCodegen::LoadConstantWide(CompilationUnit *cu, int r_dest_lo, int r_dest_hi, int64_t value)
buzbeee3acd072012-02-25 17:03:10 -0800347{
Bill Buzbeea114add2012-05-03 15:00:40 -0700348 LIR *res;
buzbee4ef3e452012-12-14 13:35:28 -0800349 res = LoadConstantNoClobber(cu, r_dest_lo, Low32Bits(value));
350 LoadConstantNoClobber(cu, r_dest_hi, High32Bits(value));
Bill Buzbeea114add2012-05-03 15:00:40 -0700351 return res;
buzbeee3acd072012-02-25 17:03:10 -0800352}
353
354/* Load value from base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800355LIR* MipsCodegen::LoadBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_dest,
356 int scale, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800357{
Bill Buzbeea114add2012-05-03 15:00:40 -0700358 LIR *first = NULL;
359 LIR *res;
360 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800361 int t_reg = AllocTemp(cu);
buzbeee3acd072012-02-25 17:03:10 -0800362
buzbeefa57c472012-11-21 12:06:18 -0800363 if (MIPS_FPREG(r_dest)) {
364 DCHECK(MIPS_SINGLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700365 DCHECK((size == kWord) || (size == kSingle));
366 size = kSingle;
367 } else {
368 if (size == kSingle)
369 size = kWord;
370 }
buzbeee3acd072012-02-25 17:03:10 -0800371
Bill Buzbeea114add2012-05-03 15:00:40 -0700372 if (!scale) {
buzbeefa57c472012-11-21 12:06:18 -0800373 first = NewLIR3(cu, kMipsAddu, t_reg , rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700374 } else {
buzbeefa57c472012-11-21 12:06:18 -0800375 first = OpRegRegImm(cu, kOpLsl, t_reg, r_index, scale);
376 NewLIR3(cu, kMipsAddu, t_reg , rBase, t_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700377 }
buzbeee3acd072012-02-25 17:03:10 -0800378
Bill Buzbeea114add2012-05-03 15:00:40 -0700379 switch (size) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700380 case kSingle:
381 opcode = kMipsFlwc1;
382 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700383 case kWord:
384 opcode = kMipsLw;
385 break;
386 case kUnsignedHalf:
387 opcode = kMipsLhu;
388 break;
389 case kSignedHalf:
390 opcode = kMipsLh;
391 break;
392 case kUnsignedByte:
393 opcode = kMipsLbu;
394 break;
395 case kSignedByte:
396 opcode = kMipsLb;
397 break;
398 default:
buzbee52a77fc2012-11-20 19:50:46 -0800399 LOG(FATAL) << "Bad case in LoadBaseIndexed";
Bill Buzbeea114add2012-05-03 15:00:40 -0700400 }
buzbeee3acd072012-02-25 17:03:10 -0800401
buzbeefa57c472012-11-21 12:06:18 -0800402 res = NewLIR3(cu, opcode, r_dest, 0, t_reg);
403 FreeTemp(cu, t_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700404 return (first) ? first : res;
buzbeee3acd072012-02-25 17:03:10 -0800405}
406
407/* store value base base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800408LIR* MipsCodegen::StoreBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_src,
409 int scale, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800410{
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 LIR *first = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700412 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800413 int r_new_index = r_index;
414 int t_reg = AllocTemp(cu);
buzbeee3acd072012-02-25 17:03:10 -0800415
buzbeefa57c472012-11-21 12:06:18 -0800416 if (MIPS_FPREG(r_src)) {
417 DCHECK(MIPS_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700418 DCHECK((size == kWord) || (size == kSingle));
419 size = kSingle;
420 } else {
421 if (size == kSingle)
422 size = kWord;
423 }
buzbeee3acd072012-02-25 17:03:10 -0800424
Bill Buzbeea114add2012-05-03 15:00:40 -0700425 if (!scale) {
buzbeefa57c472012-11-21 12:06:18 -0800426 first = NewLIR3(cu, kMipsAddu, t_reg , rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 } else {
buzbeefa57c472012-11-21 12:06:18 -0800428 first = OpRegRegImm(cu, kOpLsl, t_reg, r_index, scale);
429 NewLIR3(cu, kMipsAddu, t_reg , rBase, t_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700430 }
buzbeee3acd072012-02-25 17:03:10 -0800431
Bill Buzbeea114add2012-05-03 15:00:40 -0700432 switch (size) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700433 case kSingle:
434 opcode = kMipsFswc1;
435 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700436 case kWord:
437 opcode = kMipsSw;
438 break;
439 case kUnsignedHalf:
440 case kSignedHalf:
441 opcode = kMipsSh;
442 break;
443 case kUnsignedByte:
444 case kSignedByte:
445 opcode = kMipsSb;
446 break;
447 default:
buzbee52a77fc2012-11-20 19:50:46 -0800448 LOG(FATAL) << "Bad case in StoreBaseIndexed";
Bill Buzbeea114add2012-05-03 15:00:40 -0700449 }
buzbeefa57c472012-11-21 12:06:18 -0800450 NewLIR3(cu, opcode, r_src, 0, t_reg);
451 FreeTemp(cu, r_new_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700452 return first;
buzbeee3acd072012-02-25 17:03:10 -0800453}
454
buzbee02031b12012-11-23 09:41:35 -0800455LIR* MipsCodegen::LoadBaseDispBody(CompilationUnit *cu, int rBase, int displacement, int r_dest,
456 int r_dest_hi, OpSize size, int s_reg)
buzbeee3acd072012-02-25 17:03:10 -0800457/*
458 * Load value from base + displacement. Optionally perform null check
buzbeefa57c472012-11-21 12:06:18 -0800459 * on base (which must have an associated s_reg and MIR). If not
buzbeee3acd072012-02-25 17:03:10 -0800460 * performing null check, incoming MIR can be null. IMPORTANT: this
461 * code must not allocate any new temps. If a new register is needed
462 * and base and dest are the same, spill some other register to
463 * rlp and then restore.
464 */
465{
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 LIR *res;
467 LIR *load = NULL;
468 LIR *load2 = NULL;
469 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800470 bool short_form = IS_SIMM16(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700471 bool pair = false;
buzbeee3acd072012-02-25 17:03:10 -0800472
Bill Buzbeea114add2012-05-03 15:00:40 -0700473 switch (size) {
474 case kLong:
475 case kDouble:
476 pair = true;
477 opcode = kMipsLw;
buzbeefa57c472012-11-21 12:06:18 -0800478 if (MIPS_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700479 opcode = kMipsFlwc1;
buzbeefa57c472012-11-21 12:06:18 -0800480 if (MIPS_DOUBLEREG(r_dest)) {
481 r_dest = r_dest - MIPS_FP_DOUBLE;
buzbeee3acd072012-02-25 17:03:10 -0800482 } else {
buzbeefa57c472012-11-21 12:06:18 -0800483 DCHECK(MIPS_FPREG(r_dest_hi));
484 DCHECK(r_dest == (r_dest_hi - 1));
buzbeee3acd072012-02-25 17:03:10 -0800485 }
buzbeefa57c472012-11-21 12:06:18 -0800486 r_dest_hi = r_dest + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700487 }
buzbeefa57c472012-11-21 12:06:18 -0800488 short_form = IS_SIMM16_2WORD(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 DCHECK_EQ((displacement & 0x3), 0);
490 break;
491 case kWord:
492 case kSingle:
493 opcode = kMipsLw;
buzbeefa57c472012-11-21 12:06:18 -0800494 if (MIPS_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700495 opcode = kMipsFlwc1;
buzbeefa57c472012-11-21 12:06:18 -0800496 DCHECK(MIPS_SINGLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 DCHECK_EQ((displacement & 0x3), 0);
499 break;
500 case kUnsignedHalf:
501 opcode = kMipsLhu;
502 DCHECK_EQ((displacement & 0x1), 0);
503 break;
504 case kSignedHalf:
505 opcode = kMipsLh;
506 DCHECK_EQ((displacement & 0x1), 0);
507 break;
508 case kUnsignedByte:
509 opcode = kMipsLbu;
510 break;
511 case kSignedByte:
512 opcode = kMipsLb;
513 break;
514 default:
buzbee52a77fc2012-11-20 19:50:46 -0800515 LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
Bill Buzbeea114add2012-05-03 15:00:40 -0700516 }
517
buzbeefa57c472012-11-21 12:06:18 -0800518 if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700519 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800520 load = res = NewLIR3(cu, opcode, r_dest, displacement, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800521 } else {
buzbeefa57c472012-11-21 12:06:18 -0800522 load = res = NewLIR3(cu, opcode, r_dest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700523 displacement + LOWORD_OFFSET, rBase);
buzbeefa57c472012-11-21 12:06:18 -0800524 load2 = NewLIR3(cu, opcode, r_dest_hi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700525 displacement + HIWORD_OFFSET, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800526 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700527 } else {
528 if (pair) {
buzbeefa57c472012-11-21 12:06:18 -0800529 int r_tmp = AllocFreeTemp(cu);
530 res = OpRegRegImm(cu, kOpAdd, r_tmp, rBase, displacement);
531 load = NewLIR3(cu, opcode, r_dest, LOWORD_OFFSET, r_tmp);
532 load2 = NewLIR3(cu, opcode, r_dest_hi, HIWORD_OFFSET, r_tmp);
533 FreeTemp(cu, r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 } else {
buzbeefa57c472012-11-21 12:06:18 -0800535 int r_tmp = (rBase == r_dest) ? AllocFreeTemp(cu) : r_dest;
536 res = OpRegRegImm(cu, kOpAdd, r_tmp, rBase, displacement);
537 load = NewLIR3(cu, opcode, r_dest, 0, r_tmp);
538 if (r_tmp != r_dest)
539 FreeTemp(cu, r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700540 }
541 }
buzbeee3acd072012-02-25 17:03:10 -0800542
buzbeef0504cd2012-11-13 16:31:10 -0800543 if (rBase == rMIPS_SP) {
buzbee02031b12012-11-23 09:41:35 -0800544 AnnotateDalvikRegAccess(cu, load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800545 true /* is_load */, pair /* is64bit */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700546 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800547 AnnotateDalvikRegAccess(cu, load2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800548 true /* is_load */, pair /* is64bit */);
buzbeee3acd072012-02-25 17:03:10 -0800549 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 }
551 return load;
buzbeee3acd072012-02-25 17:03:10 -0800552}
553
buzbee02031b12012-11-23 09:41:35 -0800554LIR* MipsCodegen::LoadBaseDisp(CompilationUnit *cu, int rBase, int displacement, int r_dest,
555 OpSize size, int s_reg)
buzbeee3acd072012-02-25 17:03:10 -0800556{
buzbeefa57c472012-11-21 12:06:18 -0800557 return LoadBaseDispBody(cu, rBase, displacement, r_dest, -1,
558 size, s_reg);
buzbeee3acd072012-02-25 17:03:10 -0800559}
560
buzbee02031b12012-11-23 09:41:35 -0800561LIR* MipsCodegen::LoadBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
562 int r_dest_lo, int r_dest_hi, int s_reg)
buzbeee3acd072012-02-25 17:03:10 -0800563{
buzbee02031b12012-11-23 09:41:35 -0800564 return LoadBaseDispBody(cu, rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
buzbeee3acd072012-02-25 17:03:10 -0800565}
566
buzbee02031b12012-11-23 09:41:35 -0800567LIR* MipsCodegen::StoreBaseDispBody(CompilationUnit *cu, int rBase, int displacement,
568 int r_src, int r_src_hi, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800569{
Bill Buzbeea114add2012-05-03 15:00:40 -0700570 LIR *res;
571 LIR *store = NULL;
572 LIR *store2 = NULL;
573 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800574 bool short_form = IS_SIMM16(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 bool pair = false;
buzbeee3acd072012-02-25 17:03:10 -0800576
Bill Buzbeea114add2012-05-03 15:00:40 -0700577 switch (size) {
578 case kLong:
579 case kDouble:
580 pair = true;
581 opcode = kMipsSw;
buzbeefa57c472012-11-21 12:06:18 -0800582 if (MIPS_FPREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700583 opcode = kMipsFswc1;
buzbeefa57c472012-11-21 12:06:18 -0800584 if (MIPS_DOUBLEREG(r_src)) {
585 r_src = r_src - MIPS_FP_DOUBLE;
buzbeee3acd072012-02-25 17:03:10 -0800586 } else {
buzbeefa57c472012-11-21 12:06:18 -0800587 DCHECK(MIPS_FPREG(r_src_hi));
588 DCHECK_EQ(r_src, (r_src_hi - 1));
buzbeee3acd072012-02-25 17:03:10 -0800589 }
buzbeefa57c472012-11-21 12:06:18 -0800590 r_src_hi = r_src + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700591 }
buzbeefa57c472012-11-21 12:06:18 -0800592 short_form = IS_SIMM16_2WORD(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700593 DCHECK_EQ((displacement & 0x3), 0);
594 break;
595 case kWord:
596 case kSingle:
597 opcode = kMipsSw;
buzbeefa57c472012-11-21 12:06:18 -0800598 if (MIPS_FPREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700599 opcode = kMipsFswc1;
buzbeefa57c472012-11-21 12:06:18 -0800600 DCHECK(MIPS_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700601 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700602 DCHECK_EQ((displacement & 0x3), 0);
603 break;
604 case kUnsignedHalf:
605 case kSignedHalf:
606 opcode = kMipsSh;
607 DCHECK_EQ((displacement & 0x1), 0);
608 break;
609 case kUnsignedByte:
610 case kSignedByte:
611 opcode = kMipsSb;
612 break;
613 default:
buzbee52a77fc2012-11-20 19:50:46 -0800614 LOG(FATAL) << "Bad case in StoreBaseIndexedBody";
Bill Buzbeea114add2012-05-03 15:00:40 -0700615 }
616
buzbeefa57c472012-11-21 12:06:18 -0800617 if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800619 store = res = NewLIR3(cu, opcode, r_src, displacement, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800620 } else {
buzbeefa57c472012-11-21 12:06:18 -0800621 store = res = NewLIR3(cu, opcode, r_src, displacement + LOWORD_OFFSET,
Bill Buzbeea114add2012-05-03 15:00:40 -0700622 rBase);
buzbeefa57c472012-11-21 12:06:18 -0800623 store2 = NewLIR3(cu, opcode, r_src_hi, displacement + HIWORD_OFFSET,
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 rBase);
buzbeee3acd072012-02-25 17:03:10 -0800625 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700626 } else {
buzbeefa57c472012-11-21 12:06:18 -0800627 int r_scratch = AllocTemp(cu);
628 res = OpRegRegImm(cu, kOpAdd, r_scratch, rBase, displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700629 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800630 store = NewLIR3(cu, opcode, r_src, 0, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700631 } else {
buzbeefa57c472012-11-21 12:06:18 -0800632 store = NewLIR3(cu, opcode, r_src, LOWORD_OFFSET, r_scratch);
633 store2 = NewLIR3(cu, opcode, r_src_hi, HIWORD_OFFSET, r_scratch);
buzbeee3acd072012-02-25 17:03:10 -0800634 }
buzbeefa57c472012-11-21 12:06:18 -0800635 FreeTemp(cu, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700636 }
buzbeee3acd072012-02-25 17:03:10 -0800637
buzbeef0504cd2012-11-13 16:31:10 -0800638 if (rBase == rMIPS_SP) {
buzbee02031b12012-11-23 09:41:35 -0800639 AnnotateDalvikRegAccess(cu, store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
640 false /* is_load */, pair /* is64bit */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700641 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800642 AnnotateDalvikRegAccess(cu, store2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800643 false /* is_load */, pair /* is64bit */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700644 }
645 }
646
647 return res;
buzbeee3acd072012-02-25 17:03:10 -0800648}
649
buzbee02031b12012-11-23 09:41:35 -0800650LIR* MipsCodegen::StoreBaseDisp(CompilationUnit *cu, int rBase, int displacement, int r_src,
651 OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800652{
buzbeefa57c472012-11-21 12:06:18 -0800653 return StoreBaseDispBody(cu, rBase, displacement, r_src, -1, size);
buzbeee3acd072012-02-25 17:03:10 -0800654}
655
buzbee02031b12012-11-23 09:41:35 -0800656LIR* MipsCodegen::StoreBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
657 int r_src_lo, int r_src_hi)
buzbeee3acd072012-02-25 17:03:10 -0800658{
buzbeefa57c472012-11-21 12:06:18 -0800659 return StoreBaseDispBody(cu, rBase, displacement, r_src_lo, r_src_hi, kLong);
buzbeee3acd072012-02-25 17:03:10 -0800660}
661
buzbee02031b12012-11-23 09:41:35 -0800662LIR* MipsCodegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
buzbeeb046e162012-10-30 15:48:42 -0700663{
buzbee52a77fc2012-11-20 19:50:46 -0800664 LOG(FATAL) << "Unexpected use of OpThreadMem for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700665 return NULL;
666}
667
buzbee02031b12012-11-23 09:41:35 -0800668LIR* MipsCodegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
buzbeeb046e162012-10-30 15:48:42 -0700669{
buzbee52a77fc2012-11-20 19:50:46 -0800670 LOG(FATAL) << "Unexpected use of OpMem for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700671 return NULL;
672}
673
buzbee02031b12012-11-23 09:41:35 -0800674LIR* MipsCodegen::StoreBaseIndexedDisp(CompilationUnit *cu,
buzbeefa57c472012-11-21 12:06:18 -0800675 int rBase, int r_index, int scale, int displacement,
676 int r_src, int r_src_hi,
677 OpSize size, int s_reg)
buzbeeb046e162012-10-30 15:48:42 -0700678{
buzbee52a77fc2012-11-20 19:50:46 -0800679 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700680 return NULL;
681}
682
buzbee02031b12012-11-23 09:41:35 -0800683LIR* MipsCodegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase,
buzbeeb046e162012-10-30 15:48:42 -0700684 int offset)
685{
buzbee52a77fc2012-11-20 19:50:46 -0800686 LOG(FATAL) << "Unexpected use of OpRegMem for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700687 return NULL;
688}
689
buzbee02031b12012-11-23 09:41:35 -0800690LIR* MipsCodegen::LoadBaseIndexedDisp(CompilationUnit *cu,
buzbeefa57c472012-11-21 12:06:18 -0800691 int rBase, int r_index, int scale, int displacement,
692 int r_dest, int r_dest_hi,
693 OpSize size, int s_reg)
buzbeeb046e162012-10-30 15:48:42 -0700694{
buzbee52a77fc2012-11-20 19:50:46 -0800695 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700696 return NULL;
697}
698
buzbee02031b12012-11-23 09:41:35 -0800699LIR* MipsCodegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target)
buzbeeb046e162012-10-30 15:48:42 -0700700{
buzbee52a77fc2012-11-20 19:50:46 -0800701 LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700702 return NULL;
703}
704
buzbeee3acd072012-02-25 17:03:10 -0800705} // namespace art