blob: 44d75d1b587e25990430ba0a6ecebd97fce311c2 [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
buzbee1bc37c62012-11-20 13:35:41 -080017#include "mips_lir.h"
buzbee02031b12012-11-23 09:41:35 -080018#include "codegen_mips.h"
buzbee1bc37c62012-11-20 13:35:41 -080019#include "../codegen_util.h"
20#include "../ralloc_util.h"
21
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
55/*
56 * Load a immediate using a shortcut if possible; otherwise
57 * grab from the per-translation literal pool. If target is
58 * a high register, build constant into a low register and copy.
59 *
60 * No additional register clobbering operation performed. Use this version when
buzbeefa57c472012-11-21 12:06:18 -080061 * 1) r_dest is freshly returned from AllocTemp or
buzbeee3acd072012-02-25 17:03:10 -080062 * 2) The codegen is under fixed register usage
63 */
buzbee02031b12012-11-23 09:41:35 -080064LIR* MipsCodegen::LoadConstantNoClobber(CompilationUnit *cu, int r_dest, int value)
buzbeee3acd072012-02-25 17:03:10 -080065{
Bill Buzbeea114add2012-05-03 15:00:40 -070066 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -080067
buzbeefa57c472012-11-21 12:06:18 -080068 int r_dest_save = r_dest;
69 int is_fp_reg = MIPS_FPREG(r_dest);
70 if (is_fp_reg) {
71 DCHECK(MIPS_SINGLEREG(r_dest));
72 r_dest = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -070073 }
buzbeee3acd072012-02-25 17:03:10 -080074
Bill Buzbeea114add2012-05-03 15:00:40 -070075 /* See if the value can be constructed cheaply */
76 if (value == 0) {
buzbeefa57c472012-11-21 12:06:18 -080077 res = NewLIR2(cu, kMipsMove, r_dest, r_ZERO);
Bill Buzbeea114add2012-05-03 15:00:40 -070078 } else if ((value > 0) && (value <= 65535)) {
buzbeefa57c472012-11-21 12:06:18 -080079 res = NewLIR3(cu, kMipsOri, r_dest, r_ZERO, value);
Bill Buzbeea114add2012-05-03 15:00:40 -070080 } else if ((value < 0) && (value >= -32768)) {
buzbeefa57c472012-11-21 12:06:18 -080081 res = NewLIR3(cu, kMipsAddiu, r_dest, r_ZERO, value);
Bill Buzbeea114add2012-05-03 15:00:40 -070082 } else {
buzbeefa57c472012-11-21 12:06:18 -080083 res = NewLIR2(cu, kMipsLui, r_dest, value>>16);
Bill Buzbeea114add2012-05-03 15:00:40 -070084 if (value & 0xffff)
buzbeefa57c472012-11-21 12:06:18 -080085 NewLIR3(cu, kMipsOri, r_dest, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -070086 }
buzbeee3acd072012-02-25 17:03:10 -080087
buzbeefa57c472012-11-21 12:06:18 -080088 if (is_fp_reg) {
89 NewLIR2(cu, kMipsMtc1, r_dest, r_dest_save);
90 FreeTemp(cu, r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -070091 }
buzbeee3acd072012-02-25 17:03:10 -080092
Bill Buzbeea114add2012-05-03 15:00:40 -070093 return res;
buzbeee3acd072012-02-25 17:03:10 -080094}
95
buzbee02031b12012-11-23 09:41:35 -080096LIR* MipsCodegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target)
buzbeee3acd072012-02-25 17:03:10 -080097{
buzbee02031b12012-11-23 09:41:35 -080098 LIR* res = NewLIR1(cu, kMipsB, 0 /* offset to be patched during assembly*/ );
99 res->target = target;
100 return res;
buzbeee3acd072012-02-25 17:03:10 -0800101}
102
buzbee02031b12012-11-23 09:41:35 -0800103LIR* MipsCodegen::OpReg(CompilationUnit *cu, OpKind op, int r_dest_src)
buzbeee3acd072012-02-25 17:03:10 -0800104{
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 MipsOpCode opcode = kMipsNop;
106 switch (op) {
107 case kOpBlx:
108 opcode = kMipsJalr;
109 break;
110 case kOpBx:
buzbeefa57c472012-11-21 12:06:18 -0800111 return NewLIR1(cu, kMipsJr, r_dest_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700112 break;
113 default:
buzbee52a77fc2012-11-20 19:50:46 -0800114 LOG(FATAL) << "Bad case in OpReg";
Bill Buzbeea114add2012-05-03 15:00:40 -0700115 }
buzbeefa57c472012-11-21 12:06:18 -0800116 return NewLIR2(cu, opcode, r_RA, r_dest_src);
buzbeee3acd072012-02-25 17:03:10 -0800117}
118
buzbee02031b12012-11-23 09:41:35 -0800119LIR* MipsCodegen::OpRegImm(CompilationUnit *cu, OpKind op, int r_dest_src1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 int value)
buzbeee3acd072012-02-25 17:03:10 -0800121{
Bill Buzbeea114add2012-05-03 15:00:40 -0700122 LIR *res;
123 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800124 int abs_value = (neg) ? -value : value;
125 bool short_form = (abs_value & 0xff) == abs_value;
Bill Buzbeea114add2012-05-03 15:00:40 -0700126 MipsOpCode opcode = kMipsNop;
127 switch (op) {
128 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800129 return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700130 break;
131 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800132 return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 break;
134 default:
buzbee52a77fc2012-11-20 19:50:46 -0800135 LOG(FATAL) << "Bad case in OpRegImm";
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 break;
137 }
buzbeefa57c472012-11-21 12:06:18 -0800138 if (short_form)
139 res = NewLIR2(cu, opcode, r_dest_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 else {
buzbeefa57c472012-11-21 12:06:18 -0800141 int r_scratch = AllocTemp(cu);
142 res = LoadConstant(cu, r_scratch, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700143 if (op == kOpCmp)
buzbeefa57c472012-11-21 12:06:18 -0800144 NewLIR2(cu, opcode, r_dest_src1, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700145 else
buzbeefa57c472012-11-21 12:06:18 -0800146 NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700147 }
148 return res;
buzbeee3acd072012-02-25 17:03:10 -0800149}
150
buzbee02031b12012-11-23 09:41:35 -0800151LIR* MipsCodegen::OpRegRegReg(CompilationUnit *cu, OpKind op, int r_dest, int r_src1, int r_src2)
buzbeee3acd072012-02-25 17:03:10 -0800152{
Bill Buzbeea114add2012-05-03 15:00:40 -0700153 MipsOpCode opcode = kMipsNop;
154 switch (op) {
155 case kOpAdd:
156 opcode = kMipsAddu;
157 break;
158 case kOpSub:
159 opcode = kMipsSubu;
160 break;
161 case kOpAnd:
162 opcode = kMipsAnd;
163 break;
164 case kOpMul:
165 opcode = kMipsMul;
166 break;
167 case kOpOr:
168 opcode = kMipsOr;
169 break;
170 case kOpXor:
171 opcode = kMipsXor;
172 break;
173 case kOpLsl:
174 opcode = kMipsSllv;
175 break;
176 case kOpLsr:
177 opcode = kMipsSrlv;
178 break;
179 case kOpAsr:
180 opcode = kMipsSrav;
181 break;
182 case kOpAdc:
183 case kOpSbc:
184 LOG(FATAL) << "No carry bit on MIPS";
185 break;
186 default:
buzbee52a77fc2012-11-20 19:50:46 -0800187 LOG(FATAL) << "bad case in OpRegRegReg";
Bill Buzbeea114add2012-05-03 15:00:40 -0700188 break;
189 }
buzbeefa57c472012-11-21 12:06:18 -0800190 return NewLIR3(cu, opcode, r_dest, r_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800191}
192
buzbee02031b12012-11-23 09:41:35 -0800193LIR* MipsCodegen::OpRegRegImm(CompilationUnit *cu, OpKind op, int r_dest, int r_src1, int value)
buzbeee3acd072012-02-25 17:03:10 -0800194{
Bill Buzbeea114add2012-05-03 15:00:40 -0700195 LIR *res;
196 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800197 bool short_form = true;
buzbeee3acd072012-02-25 17:03:10 -0800198
Bill Buzbeea114add2012-05-03 15:00:40 -0700199 switch (op) {
200 case kOpAdd:
201 if (IS_SIMM16(value)) {
202 opcode = kMipsAddiu;
203 }
204 else {
buzbeefa57c472012-11-21 12:06:18 -0800205 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700206 opcode = kMipsAddu;
207 }
208 break;
209 case kOpSub:
210 if (IS_SIMM16((-value))) {
211 value = -value;
212 opcode = kMipsAddiu;
213 }
214 else {
buzbeefa57c472012-11-21 12:06:18 -0800215 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700216 opcode = kMipsSubu;
217 }
218 break;
219 case kOpLsl:
220 DCHECK(value >= 0 && value <= 31);
221 opcode = kMipsSll;
222 break;
223 case kOpLsr:
224 DCHECK(value >= 0 && value <= 31);
225 opcode = kMipsSrl;
226 break;
227 case kOpAsr:
228 DCHECK(value >= 0 && value <= 31);
229 opcode = kMipsSra;
230 break;
231 case kOpAnd:
232 if (IS_UIMM16((value))) {
233 opcode = kMipsAndi;
234 }
235 else {
buzbeefa57c472012-11-21 12:06:18 -0800236 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700237 opcode = kMipsAnd;
238 }
239 break;
240 case kOpOr:
241 if (IS_UIMM16((value))) {
242 opcode = kMipsOri;
243 }
244 else {
buzbeefa57c472012-11-21 12:06:18 -0800245 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700246 opcode = kMipsOr;
247 }
248 break;
249 case kOpXor:
250 if (IS_UIMM16((value))) {
251 opcode = kMipsXori;
252 }
253 else {
buzbeefa57c472012-11-21 12:06:18 -0800254 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700255 opcode = kMipsXor;
256 }
257 break;
258 case kOpMul:
buzbeefa57c472012-11-21 12:06:18 -0800259 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700260 opcode = kMipsMul;
261 break;
262 default:
buzbee52a77fc2012-11-20 19:50:46 -0800263 LOG(FATAL) << "Bad case in OpRegRegImm";
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 break;
265 }
buzbeee3acd072012-02-25 17:03:10 -0800266
buzbeefa57c472012-11-21 12:06:18 -0800267 if (short_form)
268 res = NewLIR3(cu, opcode, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700269 else {
buzbeefa57c472012-11-21 12:06:18 -0800270 if (r_dest != r_src1) {
271 res = LoadConstant(cu, r_dest, value);
272 NewLIR3(cu, opcode, r_dest, r_src1, r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700273 } else {
buzbeefa57c472012-11-21 12:06:18 -0800274 int r_scratch = AllocTemp(cu);
275 res = LoadConstant(cu, r_scratch, value);
276 NewLIR3(cu, opcode, r_dest, r_src1, r_scratch);
buzbeee3acd072012-02-25 17:03:10 -0800277 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700278 }
279 return res;
buzbeee3acd072012-02-25 17:03:10 -0800280}
281
buzbee02031b12012-11-23 09:41:35 -0800282LIR* MipsCodegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int r_src2)
buzbeee3acd072012-02-25 17:03:10 -0800283{
Bill Buzbeea114add2012-05-03 15:00:40 -0700284 MipsOpCode opcode = kMipsNop;
285 LIR *res;
286 switch (op) {
287 case kOpMov:
288 opcode = kMipsMove;
289 break;
290 case kOpMvn:
buzbeefa57c472012-11-21 12:06:18 -0800291 return NewLIR3(cu, kMipsNor, r_dest_src1, r_src2, r_ZERO);
Bill Buzbeea114add2012-05-03 15:00:40 -0700292 case kOpNeg:
buzbeefa57c472012-11-21 12:06:18 -0800293 return NewLIR3(cu, kMipsSubu, r_dest_src1, r_ZERO, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700294 case kOpAdd:
295 case kOpAnd:
296 case kOpMul:
297 case kOpOr:
298 case kOpSub:
299 case kOpXor:
buzbeefa57c472012-11-21 12:06:18 -0800300 return OpRegRegReg(cu, op, r_dest_src1, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700301 case kOp2Byte:
buzbeee3acd072012-02-25 17:03:10 -0800302#if __mips_isa_rev>=2
buzbeefa57c472012-11-21 12:06:18 -0800303 res = NewLIR2(cu, kMipsSeb, r_dest_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800304#else
buzbeefa57c472012-11-21 12:06:18 -0800305 res = OpRegRegImm(cu, kOpLsl, r_dest_src1, r_src2, 24);
306 OpRegRegImm(cu, kOpAsr, r_dest_src1, r_dest_src1, 24);
buzbeee3acd072012-02-25 17:03:10 -0800307#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700308 return res;
309 case kOp2Short:
buzbeee3acd072012-02-25 17:03:10 -0800310#if __mips_isa_rev>=2
buzbeefa57c472012-11-21 12:06:18 -0800311 res = NewLIR2(cu, kMipsSeh, r_dest_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800312#else
buzbeefa57c472012-11-21 12:06:18 -0800313 res = OpRegRegImm(cu, kOpLsl, r_dest_src1, r_src2, 16);
314 OpRegRegImm(cu, kOpAsr, r_dest_src1, r_dest_src1, 16);
buzbeee3acd072012-02-25 17:03:10 -0800315#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700316 return res;
317 case kOp2Char:
buzbeefa57c472012-11-21 12:06:18 -0800318 return NewLIR3(cu, kMipsAndi, r_dest_src1, r_src2, 0xFFFF);
Bill Buzbeea114add2012-05-03 15:00:40 -0700319 default:
buzbee52a77fc2012-11-20 19:50:46 -0800320 LOG(FATAL) << "Bad case in OpRegReg";
Bill Buzbeea114add2012-05-03 15:00:40 -0700321 break;
322 }
buzbeefa57c472012-11-21 12:06:18 -0800323 return NewLIR2(cu, opcode, r_dest_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800324}
325
buzbee02031b12012-11-23 09:41:35 -0800326LIR* MipsCodegen::LoadConstantValueWide(CompilationUnit *cu, int r_dest_lo, int r_dest_hi,
327 int val_lo, int val_hi)
buzbeee3acd072012-02-25 17:03:10 -0800328{
Bill Buzbeea114add2012-05-03 15:00:40 -0700329 LIR *res;
buzbeefa57c472012-11-21 12:06:18 -0800330 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
331 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700332 return res;
buzbeee3acd072012-02-25 17:03:10 -0800333}
334
335/* Load value from base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800336LIR* MipsCodegen::LoadBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_dest,
337 int scale, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800338{
Bill Buzbeea114add2012-05-03 15:00:40 -0700339 LIR *first = NULL;
340 LIR *res;
341 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800342 int t_reg = AllocTemp(cu);
buzbeee3acd072012-02-25 17:03:10 -0800343
buzbeefa57c472012-11-21 12:06:18 -0800344 if (MIPS_FPREG(r_dest)) {
345 DCHECK(MIPS_SINGLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700346 DCHECK((size == kWord) || (size == kSingle));
347 size = kSingle;
348 } else {
349 if (size == kSingle)
350 size = kWord;
351 }
buzbeee3acd072012-02-25 17:03:10 -0800352
Bill Buzbeea114add2012-05-03 15:00:40 -0700353 if (!scale) {
buzbeefa57c472012-11-21 12:06:18 -0800354 first = NewLIR3(cu, kMipsAddu, t_reg , rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700355 } else {
buzbeefa57c472012-11-21 12:06:18 -0800356 first = OpRegRegImm(cu, kOpLsl, t_reg, r_index, scale);
357 NewLIR3(cu, kMipsAddu, t_reg , rBase, t_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700358 }
buzbeee3acd072012-02-25 17:03:10 -0800359
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 switch (size) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700361 case kSingle:
362 opcode = kMipsFlwc1;
363 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700364 case kWord:
365 opcode = kMipsLw;
366 break;
367 case kUnsignedHalf:
368 opcode = kMipsLhu;
369 break;
370 case kSignedHalf:
371 opcode = kMipsLh;
372 break;
373 case kUnsignedByte:
374 opcode = kMipsLbu;
375 break;
376 case kSignedByte:
377 opcode = kMipsLb;
378 break;
379 default:
buzbee52a77fc2012-11-20 19:50:46 -0800380 LOG(FATAL) << "Bad case in LoadBaseIndexed";
Bill Buzbeea114add2012-05-03 15:00:40 -0700381 }
buzbeee3acd072012-02-25 17:03:10 -0800382
buzbeefa57c472012-11-21 12:06:18 -0800383 res = NewLIR3(cu, opcode, r_dest, 0, t_reg);
384 FreeTemp(cu, t_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700385 return (first) ? first : res;
buzbeee3acd072012-02-25 17:03:10 -0800386}
387
388/* store value base base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800389LIR* MipsCodegen::StoreBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_src,
390 int scale, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800391{
Bill Buzbeea114add2012-05-03 15:00:40 -0700392 LIR *first = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700393 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800394 int r_new_index = r_index;
395 int t_reg = AllocTemp(cu);
buzbeee3acd072012-02-25 17:03:10 -0800396
buzbeefa57c472012-11-21 12:06:18 -0800397 if (MIPS_FPREG(r_src)) {
398 DCHECK(MIPS_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700399 DCHECK((size == kWord) || (size == kSingle));
400 size = kSingle;
401 } else {
402 if (size == kSingle)
403 size = kWord;
404 }
buzbeee3acd072012-02-25 17:03:10 -0800405
Bill Buzbeea114add2012-05-03 15:00:40 -0700406 if (!scale) {
buzbeefa57c472012-11-21 12:06:18 -0800407 first = NewLIR3(cu, kMipsAddu, t_reg , rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700408 } else {
buzbeefa57c472012-11-21 12:06:18 -0800409 first = OpRegRegImm(cu, kOpLsl, t_reg, r_index, scale);
410 NewLIR3(cu, kMipsAddu, t_reg , rBase, t_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 }
buzbeee3acd072012-02-25 17:03:10 -0800412
Bill Buzbeea114add2012-05-03 15:00:40 -0700413 switch (size) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700414 case kSingle:
415 opcode = kMipsFswc1;
416 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700417 case kWord:
418 opcode = kMipsSw;
419 break;
420 case kUnsignedHalf:
421 case kSignedHalf:
422 opcode = kMipsSh;
423 break;
424 case kUnsignedByte:
425 case kSignedByte:
426 opcode = kMipsSb;
427 break;
428 default:
buzbee52a77fc2012-11-20 19:50:46 -0800429 LOG(FATAL) << "Bad case in StoreBaseIndexed";
Bill Buzbeea114add2012-05-03 15:00:40 -0700430 }
buzbeefa57c472012-11-21 12:06:18 -0800431 NewLIR3(cu, opcode, r_src, 0, t_reg);
432 FreeTemp(cu, r_new_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700433 return first;
buzbeee3acd072012-02-25 17:03:10 -0800434}
435
buzbee02031b12012-11-23 09:41:35 -0800436LIR* MipsCodegen::LoadBaseDispBody(CompilationUnit *cu, int rBase, int displacement, int r_dest,
437 int r_dest_hi, OpSize size, int s_reg)
buzbeee3acd072012-02-25 17:03:10 -0800438/*
439 * Load value from base + displacement. Optionally perform null check
buzbeefa57c472012-11-21 12:06:18 -0800440 * on base (which must have an associated s_reg and MIR). If not
buzbeee3acd072012-02-25 17:03:10 -0800441 * performing null check, incoming MIR can be null. IMPORTANT: this
442 * code must not allocate any new temps. If a new register is needed
443 * and base and dest are the same, spill some other register to
444 * rlp and then restore.
445 */
446{
Bill Buzbeea114add2012-05-03 15:00:40 -0700447 LIR *res;
448 LIR *load = NULL;
449 LIR *load2 = NULL;
450 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800451 bool short_form = IS_SIMM16(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700452 bool pair = false;
buzbeee3acd072012-02-25 17:03:10 -0800453
Bill Buzbeea114add2012-05-03 15:00:40 -0700454 switch (size) {
455 case kLong:
456 case kDouble:
457 pair = true;
458 opcode = kMipsLw;
buzbeefa57c472012-11-21 12:06:18 -0800459 if (MIPS_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700460 opcode = kMipsFlwc1;
buzbeefa57c472012-11-21 12:06:18 -0800461 if (MIPS_DOUBLEREG(r_dest)) {
462 r_dest = r_dest - MIPS_FP_DOUBLE;
buzbeee3acd072012-02-25 17:03:10 -0800463 } else {
buzbeefa57c472012-11-21 12:06:18 -0800464 DCHECK(MIPS_FPREG(r_dest_hi));
465 DCHECK(r_dest == (r_dest_hi - 1));
buzbeee3acd072012-02-25 17:03:10 -0800466 }
buzbeefa57c472012-11-21 12:06:18 -0800467 r_dest_hi = r_dest + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700468 }
buzbeefa57c472012-11-21 12:06:18 -0800469 short_form = IS_SIMM16_2WORD(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700470 DCHECK_EQ((displacement & 0x3), 0);
471 break;
472 case kWord:
473 case kSingle:
474 opcode = kMipsLw;
buzbeefa57c472012-11-21 12:06:18 -0800475 if (MIPS_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700476 opcode = kMipsFlwc1;
buzbeefa57c472012-11-21 12:06:18 -0800477 DCHECK(MIPS_SINGLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700478 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700479 DCHECK_EQ((displacement & 0x3), 0);
480 break;
481 case kUnsignedHalf:
482 opcode = kMipsLhu;
483 DCHECK_EQ((displacement & 0x1), 0);
484 break;
485 case kSignedHalf:
486 opcode = kMipsLh;
487 DCHECK_EQ((displacement & 0x1), 0);
488 break;
489 case kUnsignedByte:
490 opcode = kMipsLbu;
491 break;
492 case kSignedByte:
493 opcode = kMipsLb;
494 break;
495 default:
buzbee52a77fc2012-11-20 19:50:46 -0800496 LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 }
498
buzbeefa57c472012-11-21 12:06:18 -0800499 if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800501 load = res = NewLIR3(cu, opcode, r_dest, displacement, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800502 } else {
buzbeefa57c472012-11-21 12:06:18 -0800503 load = res = NewLIR3(cu, opcode, r_dest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700504 displacement + LOWORD_OFFSET, rBase);
buzbeefa57c472012-11-21 12:06:18 -0800505 load2 = NewLIR3(cu, opcode, r_dest_hi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700506 displacement + HIWORD_OFFSET, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800507 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700508 } else {
509 if (pair) {
buzbeefa57c472012-11-21 12:06:18 -0800510 int r_tmp = AllocFreeTemp(cu);
511 res = OpRegRegImm(cu, kOpAdd, r_tmp, rBase, displacement);
512 load = NewLIR3(cu, opcode, r_dest, LOWORD_OFFSET, r_tmp);
513 load2 = NewLIR3(cu, opcode, r_dest_hi, HIWORD_OFFSET, r_tmp);
514 FreeTemp(cu, r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700515 } else {
buzbeefa57c472012-11-21 12:06:18 -0800516 int r_tmp = (rBase == r_dest) ? AllocFreeTemp(cu) : r_dest;
517 res = OpRegRegImm(cu, kOpAdd, r_tmp, rBase, displacement);
518 load = NewLIR3(cu, opcode, r_dest, 0, r_tmp);
519 if (r_tmp != r_dest)
520 FreeTemp(cu, r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700521 }
522 }
buzbeee3acd072012-02-25 17:03:10 -0800523
buzbeef0504cd2012-11-13 16:31:10 -0800524 if (rBase == rMIPS_SP) {
buzbee02031b12012-11-23 09:41:35 -0800525 AnnotateDalvikRegAccess(cu, load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800526 true /* is_load */, pair /* is64bit */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700527 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800528 AnnotateDalvikRegAccess(cu, load2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800529 true /* is_load */, pair /* is64bit */);
buzbeee3acd072012-02-25 17:03:10 -0800530 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700531 }
532 return load;
buzbeee3acd072012-02-25 17:03:10 -0800533}
534
buzbee02031b12012-11-23 09:41:35 -0800535LIR* MipsCodegen::LoadBaseDisp(CompilationUnit *cu, int rBase, int displacement, int r_dest,
536 OpSize size, int s_reg)
buzbeee3acd072012-02-25 17:03:10 -0800537{
buzbeefa57c472012-11-21 12:06:18 -0800538 return LoadBaseDispBody(cu, rBase, displacement, r_dest, -1,
539 size, s_reg);
buzbeee3acd072012-02-25 17:03:10 -0800540}
541
buzbee02031b12012-11-23 09:41:35 -0800542LIR* MipsCodegen::LoadBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
543 int r_dest_lo, int r_dest_hi, int s_reg)
buzbeee3acd072012-02-25 17:03:10 -0800544{
buzbee02031b12012-11-23 09:41:35 -0800545 return LoadBaseDispBody(cu, rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
buzbeee3acd072012-02-25 17:03:10 -0800546}
547
buzbee02031b12012-11-23 09:41:35 -0800548LIR* MipsCodegen::StoreBaseDispBody(CompilationUnit *cu, int rBase, int displacement,
549 int r_src, int r_src_hi, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800550{
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 LIR *res;
552 LIR *store = NULL;
553 LIR *store2 = NULL;
554 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800555 bool short_form = IS_SIMM16(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700556 bool pair = false;
buzbeee3acd072012-02-25 17:03:10 -0800557
Bill Buzbeea114add2012-05-03 15:00:40 -0700558 switch (size) {
559 case kLong:
560 case kDouble:
561 pair = true;
562 opcode = kMipsSw;
buzbeefa57c472012-11-21 12:06:18 -0800563 if (MIPS_FPREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700564 opcode = kMipsFswc1;
buzbeefa57c472012-11-21 12:06:18 -0800565 if (MIPS_DOUBLEREG(r_src)) {
566 r_src = r_src - MIPS_FP_DOUBLE;
buzbeee3acd072012-02-25 17:03:10 -0800567 } else {
buzbeefa57c472012-11-21 12:06:18 -0800568 DCHECK(MIPS_FPREG(r_src_hi));
569 DCHECK_EQ(r_src, (r_src_hi - 1));
buzbeee3acd072012-02-25 17:03:10 -0800570 }
buzbeefa57c472012-11-21 12:06:18 -0800571 r_src_hi = r_src + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700572 }
buzbeefa57c472012-11-21 12:06:18 -0800573 short_form = IS_SIMM16_2WORD(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700574 DCHECK_EQ((displacement & 0x3), 0);
575 break;
576 case kWord:
577 case kSingle:
578 opcode = kMipsSw;
buzbeefa57c472012-11-21 12:06:18 -0800579 if (MIPS_FPREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700580 opcode = kMipsFswc1;
buzbeefa57c472012-11-21 12:06:18 -0800581 DCHECK(MIPS_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700582 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700583 DCHECK_EQ((displacement & 0x3), 0);
584 break;
585 case kUnsignedHalf:
586 case kSignedHalf:
587 opcode = kMipsSh;
588 DCHECK_EQ((displacement & 0x1), 0);
589 break;
590 case kUnsignedByte:
591 case kSignedByte:
592 opcode = kMipsSb;
593 break;
594 default:
buzbee52a77fc2012-11-20 19:50:46 -0800595 LOG(FATAL) << "Bad case in StoreBaseIndexedBody";
Bill Buzbeea114add2012-05-03 15:00:40 -0700596 }
597
buzbeefa57c472012-11-21 12:06:18 -0800598 if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700599 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800600 store = res = NewLIR3(cu, opcode, r_src, displacement, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800601 } else {
buzbeefa57c472012-11-21 12:06:18 -0800602 store = res = NewLIR3(cu, opcode, r_src, displacement + LOWORD_OFFSET,
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 rBase);
buzbeefa57c472012-11-21 12:06:18 -0800604 store2 = NewLIR3(cu, opcode, r_src_hi, displacement + HIWORD_OFFSET,
Bill Buzbeea114add2012-05-03 15:00:40 -0700605 rBase);
buzbeee3acd072012-02-25 17:03:10 -0800606 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700607 } else {
buzbeefa57c472012-11-21 12:06:18 -0800608 int r_scratch = AllocTemp(cu);
609 res = OpRegRegImm(cu, kOpAdd, r_scratch, rBase, displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700610 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800611 store = NewLIR3(cu, opcode, r_src, 0, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700612 } else {
buzbeefa57c472012-11-21 12:06:18 -0800613 store = NewLIR3(cu, opcode, r_src, LOWORD_OFFSET, r_scratch);
614 store2 = NewLIR3(cu, opcode, r_src_hi, HIWORD_OFFSET, r_scratch);
buzbeee3acd072012-02-25 17:03:10 -0800615 }
buzbeefa57c472012-11-21 12:06:18 -0800616 FreeTemp(cu, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700617 }
buzbeee3acd072012-02-25 17:03:10 -0800618
buzbeef0504cd2012-11-13 16:31:10 -0800619 if (rBase == rMIPS_SP) {
buzbee02031b12012-11-23 09:41:35 -0800620 AnnotateDalvikRegAccess(cu, store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
621 false /* is_load */, pair /* is64bit */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700622 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800623 AnnotateDalvikRegAccess(cu, store2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800624 false /* is_load */, pair /* is64bit */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700625 }
626 }
627
628 return res;
buzbeee3acd072012-02-25 17:03:10 -0800629}
630
buzbee02031b12012-11-23 09:41:35 -0800631LIR* MipsCodegen::StoreBaseDisp(CompilationUnit *cu, int rBase, int displacement, int r_src,
632 OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800633{
buzbeefa57c472012-11-21 12:06:18 -0800634 return StoreBaseDispBody(cu, rBase, displacement, r_src, -1, size);
buzbeee3acd072012-02-25 17:03:10 -0800635}
636
buzbee02031b12012-11-23 09:41:35 -0800637LIR* MipsCodegen::StoreBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
638 int r_src_lo, int r_src_hi)
buzbeee3acd072012-02-25 17:03:10 -0800639{
buzbeefa57c472012-11-21 12:06:18 -0800640 return StoreBaseDispBody(cu, rBase, displacement, r_src_lo, r_src_hi, kLong);
buzbeee3acd072012-02-25 17:03:10 -0800641}
642
buzbee02031b12012-11-23 09:41:35 -0800643void MipsCodegen::LoadPair(CompilationUnit *cu, int base, int low_reg, int high_reg)
buzbeee3acd072012-02-25 17:03:10 -0800644{
buzbeefa57c472012-11-21 12:06:18 -0800645 LoadWordDisp(cu, base, LOWORD_OFFSET , low_reg);
646 LoadWordDisp(cu, base, HIWORD_OFFSET , high_reg);
buzbeee3acd072012-02-25 17:03:10 -0800647}
648
buzbee02031b12012-11-23 09:41:35 -0800649LIR* MipsCodegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
buzbeeb046e162012-10-30 15:48:42 -0700650{
buzbee52a77fc2012-11-20 19:50:46 -0800651 LOG(FATAL) << "Unexpected use of OpThreadMem for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700652 return NULL;
653}
654
buzbee02031b12012-11-23 09:41:35 -0800655LIR* MipsCodegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
buzbeeb046e162012-10-30 15:48:42 -0700656{
buzbee52a77fc2012-11-20 19:50:46 -0800657 LOG(FATAL) << "Unexpected use of OpMem for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700658 return NULL;
659}
660
buzbee02031b12012-11-23 09:41:35 -0800661LIR* MipsCodegen::StoreBaseIndexedDisp(CompilationUnit *cu,
buzbeefa57c472012-11-21 12:06:18 -0800662 int rBase, int r_index, int scale, int displacement,
663 int r_src, int r_src_hi,
664 OpSize size, int s_reg)
buzbeeb046e162012-10-30 15:48:42 -0700665{
buzbee52a77fc2012-11-20 19:50:46 -0800666 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700667 return NULL;
668}
669
buzbee02031b12012-11-23 09:41:35 -0800670LIR* MipsCodegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase,
buzbeeb046e162012-10-30 15:48:42 -0700671 int offset)
672{
buzbee52a77fc2012-11-20 19:50:46 -0800673 LOG(FATAL) << "Unexpected use of OpRegMem for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700674 return NULL;
675}
676
buzbee02031b12012-11-23 09:41:35 -0800677LIR* MipsCodegen::LoadBaseIndexedDisp(CompilationUnit *cu,
buzbeefa57c472012-11-21 12:06:18 -0800678 int rBase, int r_index, int scale, int displacement,
679 int r_dest, int r_dest_hi,
680 OpSize size, int s_reg)
buzbeeb046e162012-10-30 15:48:42 -0700681{
buzbee52a77fc2012-11-20 19:50:46 -0800682 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700683 return NULL;
684}
685
buzbee02031b12012-11-23 09:41:35 -0800686LIR* MipsCodegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target)
buzbeeb046e162012-10-30 15:48:42 -0700687{
buzbee52a77fc2012-11-20 19:50:46 -0800688 LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700689 return NULL;
690}
691
buzbeee3acd072012-02-25 17:03:10 -0800692} // namespace art