blob: 1e217fbe7556a8f7511ec21cfa8be1cc574c266b [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
buzbeee6285f92012-12-06 15:57:46 -080055bool MipsCodegen::InexpensiveConstant(int reg, int value)
56{
57 bool res = false;
58 if (value == 0) {
59 res = true;
60 } else if (IsUint(16, value)) {
61 res = true;
62 } else if ((value < 0) && (value >= -32768)) {
63 res = true;
64 }
65 return res;
66}
67
buzbeee3acd072012-02-25 17:03:10 -080068/*
69 * Load a immediate using a shortcut if possible; otherwise
70 * grab from the per-translation literal pool. If target is
71 * a high register, build constant into a low register and copy.
72 *
73 * No additional register clobbering operation performed. Use this version when
buzbeefa57c472012-11-21 12:06:18 -080074 * 1) r_dest is freshly returned from AllocTemp or
buzbeee3acd072012-02-25 17:03:10 -080075 * 2) The codegen is under fixed register usage
76 */
buzbee02031b12012-11-23 09:41:35 -080077LIR* MipsCodegen::LoadConstantNoClobber(CompilationUnit *cu, int r_dest, int value)
buzbeee3acd072012-02-25 17:03:10 -080078{
Bill Buzbeea114add2012-05-03 15:00:40 -070079 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -080080
buzbeefa57c472012-11-21 12:06:18 -080081 int r_dest_save = r_dest;
82 int is_fp_reg = MIPS_FPREG(r_dest);
83 if (is_fp_reg) {
84 DCHECK(MIPS_SINGLEREG(r_dest));
85 r_dest = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -070086 }
buzbeee3acd072012-02-25 17:03:10 -080087
Bill Buzbeea114add2012-05-03 15:00:40 -070088 /* See if the value can be constructed cheaply */
89 if (value == 0) {
buzbeefa57c472012-11-21 12:06:18 -080090 res = NewLIR2(cu, kMipsMove, r_dest, r_ZERO);
Bill Buzbeea114add2012-05-03 15:00:40 -070091 } else if ((value > 0) && (value <= 65535)) {
buzbeefa57c472012-11-21 12:06:18 -080092 res = NewLIR3(cu, kMipsOri, r_dest, r_ZERO, value);
Bill Buzbeea114add2012-05-03 15:00:40 -070093 } else if ((value < 0) && (value >= -32768)) {
buzbeefa57c472012-11-21 12:06:18 -080094 res = NewLIR3(cu, kMipsAddiu, r_dest, r_ZERO, value);
Bill Buzbeea114add2012-05-03 15:00:40 -070095 } else {
buzbeefa57c472012-11-21 12:06:18 -080096 res = NewLIR2(cu, kMipsLui, r_dest, value>>16);
Bill Buzbeea114add2012-05-03 15:00:40 -070097 if (value & 0xffff)
buzbeefa57c472012-11-21 12:06:18 -080098 NewLIR3(cu, kMipsOri, r_dest, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -070099 }
buzbeee3acd072012-02-25 17:03:10 -0800100
buzbeefa57c472012-11-21 12:06:18 -0800101 if (is_fp_reg) {
102 NewLIR2(cu, kMipsMtc1, r_dest, r_dest_save);
103 FreeTemp(cu, r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 }
buzbeee3acd072012-02-25 17:03:10 -0800105
Bill Buzbeea114add2012-05-03 15:00:40 -0700106 return res;
buzbeee3acd072012-02-25 17:03:10 -0800107}
108
buzbee02031b12012-11-23 09:41:35 -0800109LIR* MipsCodegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target)
buzbeee3acd072012-02-25 17:03:10 -0800110{
buzbee02031b12012-11-23 09:41:35 -0800111 LIR* res = NewLIR1(cu, kMipsB, 0 /* offset to be patched during assembly*/ );
112 res->target = target;
113 return res;
buzbeee3acd072012-02-25 17:03:10 -0800114}
115
buzbee02031b12012-11-23 09:41:35 -0800116LIR* MipsCodegen::OpReg(CompilationUnit *cu, OpKind op, int r_dest_src)
buzbeee3acd072012-02-25 17:03:10 -0800117{
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 MipsOpCode opcode = kMipsNop;
119 switch (op) {
120 case kOpBlx:
121 opcode = kMipsJalr;
122 break;
123 case kOpBx:
buzbeefa57c472012-11-21 12:06:18 -0800124 return NewLIR1(cu, kMipsJr, r_dest_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700125 break;
126 default:
buzbee52a77fc2012-11-20 19:50:46 -0800127 LOG(FATAL) << "Bad case in OpReg";
Bill Buzbeea114add2012-05-03 15:00:40 -0700128 }
buzbeefa57c472012-11-21 12:06:18 -0800129 return NewLIR2(cu, opcode, r_RA, r_dest_src);
buzbeee3acd072012-02-25 17:03:10 -0800130}
131
buzbee02031b12012-11-23 09:41:35 -0800132LIR* MipsCodegen::OpRegImm(CompilationUnit *cu, OpKind op, int r_dest_src1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 int value)
buzbeee3acd072012-02-25 17:03:10 -0800134{
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 LIR *res;
136 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800137 int abs_value = (neg) ? -value : value;
138 bool short_form = (abs_value & 0xff) == abs_value;
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 MipsOpCode opcode = kMipsNop;
140 switch (op) {
141 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800142 return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700143 break;
144 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800145 return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 break;
147 default:
buzbee52a77fc2012-11-20 19:50:46 -0800148 LOG(FATAL) << "Bad case in OpRegImm";
Bill Buzbeea114add2012-05-03 15:00:40 -0700149 break;
150 }
buzbeefa57c472012-11-21 12:06:18 -0800151 if (short_form)
152 res = NewLIR2(cu, opcode, r_dest_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700153 else {
buzbeefa57c472012-11-21 12:06:18 -0800154 int r_scratch = AllocTemp(cu);
155 res = LoadConstant(cu, r_scratch, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700156 if (op == kOpCmp)
buzbeefa57c472012-11-21 12:06:18 -0800157 NewLIR2(cu, opcode, r_dest_src1, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700158 else
buzbeefa57c472012-11-21 12:06:18 -0800159 NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700160 }
161 return res;
buzbeee3acd072012-02-25 17:03:10 -0800162}
163
buzbee02031b12012-11-23 09:41:35 -0800164LIR* MipsCodegen::OpRegRegReg(CompilationUnit *cu, OpKind op, int r_dest, int r_src1, int r_src2)
buzbeee3acd072012-02-25 17:03:10 -0800165{
Bill Buzbeea114add2012-05-03 15:00:40 -0700166 MipsOpCode opcode = kMipsNop;
167 switch (op) {
168 case kOpAdd:
169 opcode = kMipsAddu;
170 break;
171 case kOpSub:
172 opcode = kMipsSubu;
173 break;
174 case kOpAnd:
175 opcode = kMipsAnd;
176 break;
177 case kOpMul:
178 opcode = kMipsMul;
179 break;
180 case kOpOr:
181 opcode = kMipsOr;
182 break;
183 case kOpXor:
184 opcode = kMipsXor;
185 break;
186 case kOpLsl:
187 opcode = kMipsSllv;
188 break;
189 case kOpLsr:
190 opcode = kMipsSrlv;
191 break;
192 case kOpAsr:
193 opcode = kMipsSrav;
194 break;
195 case kOpAdc:
196 case kOpSbc:
197 LOG(FATAL) << "No carry bit on MIPS";
198 break;
199 default:
buzbee52a77fc2012-11-20 19:50:46 -0800200 LOG(FATAL) << "bad case in OpRegRegReg";
Bill Buzbeea114add2012-05-03 15:00:40 -0700201 break;
202 }
buzbeefa57c472012-11-21 12:06:18 -0800203 return NewLIR3(cu, opcode, r_dest, r_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800204}
205
buzbee02031b12012-11-23 09:41:35 -0800206LIR* MipsCodegen::OpRegRegImm(CompilationUnit *cu, OpKind op, int r_dest, int r_src1, int value)
buzbeee3acd072012-02-25 17:03:10 -0800207{
Bill Buzbeea114add2012-05-03 15:00:40 -0700208 LIR *res;
209 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800210 bool short_form = true;
buzbeee3acd072012-02-25 17:03:10 -0800211
Bill Buzbeea114add2012-05-03 15:00:40 -0700212 switch (op) {
213 case kOpAdd:
214 if (IS_SIMM16(value)) {
215 opcode = kMipsAddiu;
216 }
217 else {
buzbeefa57c472012-11-21 12:06:18 -0800218 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700219 opcode = kMipsAddu;
220 }
221 break;
222 case kOpSub:
223 if (IS_SIMM16((-value))) {
224 value = -value;
225 opcode = kMipsAddiu;
226 }
227 else {
buzbeefa57c472012-11-21 12:06:18 -0800228 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700229 opcode = kMipsSubu;
230 }
231 break;
232 case kOpLsl:
233 DCHECK(value >= 0 && value <= 31);
234 opcode = kMipsSll;
235 break;
236 case kOpLsr:
237 DCHECK(value >= 0 && value <= 31);
238 opcode = kMipsSrl;
239 break;
240 case kOpAsr:
241 DCHECK(value >= 0 && value <= 31);
242 opcode = kMipsSra;
243 break;
244 case kOpAnd:
245 if (IS_UIMM16((value))) {
246 opcode = kMipsAndi;
247 }
248 else {
buzbeefa57c472012-11-21 12:06:18 -0800249 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700250 opcode = kMipsAnd;
251 }
252 break;
253 case kOpOr:
254 if (IS_UIMM16((value))) {
255 opcode = kMipsOri;
256 }
257 else {
buzbeefa57c472012-11-21 12:06:18 -0800258 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700259 opcode = kMipsOr;
260 }
261 break;
262 case kOpXor:
263 if (IS_UIMM16((value))) {
264 opcode = kMipsXori;
265 }
266 else {
buzbeefa57c472012-11-21 12:06:18 -0800267 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 opcode = kMipsXor;
269 }
270 break;
271 case kOpMul:
buzbeefa57c472012-11-21 12:06:18 -0800272 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700273 opcode = kMipsMul;
274 break;
275 default:
buzbee52a77fc2012-11-20 19:50:46 -0800276 LOG(FATAL) << "Bad case in OpRegRegImm";
Bill Buzbeea114add2012-05-03 15:00:40 -0700277 break;
278 }
buzbeee3acd072012-02-25 17:03:10 -0800279
buzbeefa57c472012-11-21 12:06:18 -0800280 if (short_form)
281 res = NewLIR3(cu, opcode, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700282 else {
buzbeefa57c472012-11-21 12:06:18 -0800283 if (r_dest != r_src1) {
284 res = LoadConstant(cu, r_dest, value);
285 NewLIR3(cu, opcode, r_dest, r_src1, r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700286 } else {
buzbeefa57c472012-11-21 12:06:18 -0800287 int r_scratch = AllocTemp(cu);
288 res = LoadConstant(cu, r_scratch, value);
289 NewLIR3(cu, opcode, r_dest, r_src1, r_scratch);
buzbeee3acd072012-02-25 17:03:10 -0800290 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700291 }
292 return res;
buzbeee3acd072012-02-25 17:03:10 -0800293}
294
buzbee02031b12012-11-23 09:41:35 -0800295LIR* MipsCodegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int r_src2)
buzbeee3acd072012-02-25 17:03:10 -0800296{
Bill Buzbeea114add2012-05-03 15:00:40 -0700297 MipsOpCode opcode = kMipsNop;
298 LIR *res;
299 switch (op) {
300 case kOpMov:
301 opcode = kMipsMove;
302 break;
303 case kOpMvn:
buzbeefa57c472012-11-21 12:06:18 -0800304 return NewLIR3(cu, kMipsNor, r_dest_src1, r_src2, r_ZERO);
Bill Buzbeea114add2012-05-03 15:00:40 -0700305 case kOpNeg:
buzbeefa57c472012-11-21 12:06:18 -0800306 return NewLIR3(cu, kMipsSubu, r_dest_src1, r_ZERO, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700307 case kOpAdd:
308 case kOpAnd:
309 case kOpMul:
310 case kOpOr:
311 case kOpSub:
312 case kOpXor:
buzbeefa57c472012-11-21 12:06:18 -0800313 return OpRegRegReg(cu, op, r_dest_src1, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700314 case kOp2Byte:
buzbeee3acd072012-02-25 17:03:10 -0800315#if __mips_isa_rev>=2
buzbeefa57c472012-11-21 12:06:18 -0800316 res = NewLIR2(cu, kMipsSeb, r_dest_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800317#else
buzbeefa57c472012-11-21 12:06:18 -0800318 res = OpRegRegImm(cu, kOpLsl, r_dest_src1, r_src2, 24);
319 OpRegRegImm(cu, kOpAsr, r_dest_src1, r_dest_src1, 24);
buzbeee3acd072012-02-25 17:03:10 -0800320#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700321 return res;
322 case kOp2Short:
buzbeee3acd072012-02-25 17:03:10 -0800323#if __mips_isa_rev>=2
buzbeefa57c472012-11-21 12:06:18 -0800324 res = NewLIR2(cu, kMipsSeh, r_dest_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800325#else
buzbeefa57c472012-11-21 12:06:18 -0800326 res = OpRegRegImm(cu, kOpLsl, r_dest_src1, r_src2, 16);
327 OpRegRegImm(cu, kOpAsr, r_dest_src1, r_dest_src1, 16);
buzbeee3acd072012-02-25 17:03:10 -0800328#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700329 return res;
330 case kOp2Char:
buzbeefa57c472012-11-21 12:06:18 -0800331 return NewLIR3(cu, kMipsAndi, r_dest_src1, r_src2, 0xFFFF);
Bill Buzbeea114add2012-05-03 15:00:40 -0700332 default:
buzbee52a77fc2012-11-20 19:50:46 -0800333 LOG(FATAL) << "Bad case in OpRegReg";
Bill Buzbeea114add2012-05-03 15:00:40 -0700334 break;
335 }
buzbeefa57c472012-11-21 12:06:18 -0800336 return NewLIR2(cu, opcode, r_dest_src1, r_src2);
buzbeee3acd072012-02-25 17:03:10 -0800337}
338
buzbee02031b12012-11-23 09:41:35 -0800339LIR* MipsCodegen::LoadConstantValueWide(CompilationUnit *cu, int r_dest_lo, int r_dest_hi,
340 int val_lo, int val_hi)
buzbeee3acd072012-02-25 17:03:10 -0800341{
Bill Buzbeea114add2012-05-03 15:00:40 -0700342 LIR *res;
buzbeefa57c472012-11-21 12:06:18 -0800343 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
344 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700345 return res;
buzbeee3acd072012-02-25 17:03:10 -0800346}
347
348/* Load value from base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800349LIR* MipsCodegen::LoadBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_dest,
350 int scale, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800351{
Bill Buzbeea114add2012-05-03 15:00:40 -0700352 LIR *first = NULL;
353 LIR *res;
354 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800355 int t_reg = AllocTemp(cu);
buzbeee3acd072012-02-25 17:03:10 -0800356
buzbeefa57c472012-11-21 12:06:18 -0800357 if (MIPS_FPREG(r_dest)) {
358 DCHECK(MIPS_SINGLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700359 DCHECK((size == kWord) || (size == kSingle));
360 size = kSingle;
361 } else {
362 if (size == kSingle)
363 size = kWord;
364 }
buzbeee3acd072012-02-25 17:03:10 -0800365
Bill Buzbeea114add2012-05-03 15:00:40 -0700366 if (!scale) {
buzbeefa57c472012-11-21 12:06:18 -0800367 first = NewLIR3(cu, kMipsAddu, t_reg , rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700368 } else {
buzbeefa57c472012-11-21 12:06:18 -0800369 first = OpRegRegImm(cu, kOpLsl, t_reg, r_index, scale);
370 NewLIR3(cu, kMipsAddu, t_reg , rBase, t_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700371 }
buzbeee3acd072012-02-25 17:03:10 -0800372
Bill Buzbeea114add2012-05-03 15:00:40 -0700373 switch (size) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700374 case kSingle:
375 opcode = kMipsFlwc1;
376 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700377 case kWord:
378 opcode = kMipsLw;
379 break;
380 case kUnsignedHalf:
381 opcode = kMipsLhu;
382 break;
383 case kSignedHalf:
384 opcode = kMipsLh;
385 break;
386 case kUnsignedByte:
387 opcode = kMipsLbu;
388 break;
389 case kSignedByte:
390 opcode = kMipsLb;
391 break;
392 default:
buzbee52a77fc2012-11-20 19:50:46 -0800393 LOG(FATAL) << "Bad case in LoadBaseIndexed";
Bill Buzbeea114add2012-05-03 15:00:40 -0700394 }
buzbeee3acd072012-02-25 17:03:10 -0800395
buzbeefa57c472012-11-21 12:06:18 -0800396 res = NewLIR3(cu, opcode, r_dest, 0, t_reg);
397 FreeTemp(cu, t_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700398 return (first) ? first : res;
buzbeee3acd072012-02-25 17:03:10 -0800399}
400
401/* store value base base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800402LIR* MipsCodegen::StoreBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_src,
403 int scale, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800404{
Bill Buzbeea114add2012-05-03 15:00:40 -0700405 LIR *first = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700406 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800407 int r_new_index = r_index;
408 int t_reg = AllocTemp(cu);
buzbeee3acd072012-02-25 17:03:10 -0800409
buzbeefa57c472012-11-21 12:06:18 -0800410 if (MIPS_FPREG(r_src)) {
411 DCHECK(MIPS_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700412 DCHECK((size == kWord) || (size == kSingle));
413 size = kSingle;
414 } else {
415 if (size == kSingle)
416 size = kWord;
417 }
buzbeee3acd072012-02-25 17:03:10 -0800418
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 if (!scale) {
buzbeefa57c472012-11-21 12:06:18 -0800420 first = NewLIR3(cu, kMipsAddu, t_reg , rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700421 } else {
buzbeefa57c472012-11-21 12:06:18 -0800422 first = OpRegRegImm(cu, kOpLsl, t_reg, r_index, scale);
423 NewLIR3(cu, kMipsAddu, t_reg , rBase, t_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700424 }
buzbeee3acd072012-02-25 17:03:10 -0800425
Bill Buzbeea114add2012-05-03 15:00:40 -0700426 switch (size) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 case kSingle:
428 opcode = kMipsFswc1;
429 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700430 case kWord:
431 opcode = kMipsSw;
432 break;
433 case kUnsignedHalf:
434 case kSignedHalf:
435 opcode = kMipsSh;
436 break;
437 case kUnsignedByte:
438 case kSignedByte:
439 opcode = kMipsSb;
440 break;
441 default:
buzbee52a77fc2012-11-20 19:50:46 -0800442 LOG(FATAL) << "Bad case in StoreBaseIndexed";
Bill Buzbeea114add2012-05-03 15:00:40 -0700443 }
buzbeefa57c472012-11-21 12:06:18 -0800444 NewLIR3(cu, opcode, r_src, 0, t_reg);
445 FreeTemp(cu, r_new_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700446 return first;
buzbeee3acd072012-02-25 17:03:10 -0800447}
448
buzbee02031b12012-11-23 09:41:35 -0800449LIR* MipsCodegen::LoadBaseDispBody(CompilationUnit *cu, int rBase, int displacement, int r_dest,
450 int r_dest_hi, OpSize size, int s_reg)
buzbeee3acd072012-02-25 17:03:10 -0800451/*
452 * Load value from base + displacement. Optionally perform null check
buzbeefa57c472012-11-21 12:06:18 -0800453 * on base (which must have an associated s_reg and MIR). If not
buzbeee3acd072012-02-25 17:03:10 -0800454 * performing null check, incoming MIR can be null. IMPORTANT: this
455 * code must not allocate any new temps. If a new register is needed
456 * and base and dest are the same, spill some other register to
457 * rlp and then restore.
458 */
459{
Bill Buzbeea114add2012-05-03 15:00:40 -0700460 LIR *res;
461 LIR *load = NULL;
462 LIR *load2 = NULL;
463 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800464 bool short_form = IS_SIMM16(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700465 bool pair = false;
buzbeee3acd072012-02-25 17:03:10 -0800466
Bill Buzbeea114add2012-05-03 15:00:40 -0700467 switch (size) {
468 case kLong:
469 case kDouble:
470 pair = true;
471 opcode = kMipsLw;
buzbeefa57c472012-11-21 12:06:18 -0800472 if (MIPS_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700473 opcode = kMipsFlwc1;
buzbeefa57c472012-11-21 12:06:18 -0800474 if (MIPS_DOUBLEREG(r_dest)) {
475 r_dest = r_dest - MIPS_FP_DOUBLE;
buzbeee3acd072012-02-25 17:03:10 -0800476 } else {
buzbeefa57c472012-11-21 12:06:18 -0800477 DCHECK(MIPS_FPREG(r_dest_hi));
478 DCHECK(r_dest == (r_dest_hi - 1));
buzbeee3acd072012-02-25 17:03:10 -0800479 }
buzbeefa57c472012-11-21 12:06:18 -0800480 r_dest_hi = r_dest + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700481 }
buzbeefa57c472012-11-21 12:06:18 -0800482 short_form = IS_SIMM16_2WORD(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 DCHECK_EQ((displacement & 0x3), 0);
484 break;
485 case kWord:
486 case kSingle:
487 opcode = kMipsLw;
buzbeefa57c472012-11-21 12:06:18 -0800488 if (MIPS_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 opcode = kMipsFlwc1;
buzbeefa57c472012-11-21 12:06:18 -0800490 DCHECK(MIPS_SINGLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700491 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700492 DCHECK_EQ((displacement & 0x3), 0);
493 break;
494 case kUnsignedHalf:
495 opcode = kMipsLhu;
496 DCHECK_EQ((displacement & 0x1), 0);
497 break;
498 case kSignedHalf:
499 opcode = kMipsLh;
500 DCHECK_EQ((displacement & 0x1), 0);
501 break;
502 case kUnsignedByte:
503 opcode = kMipsLbu;
504 break;
505 case kSignedByte:
506 opcode = kMipsLb;
507 break;
508 default:
buzbee52a77fc2012-11-20 19:50:46 -0800509 LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 }
511
buzbeefa57c472012-11-21 12:06:18 -0800512 if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700513 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800514 load = res = NewLIR3(cu, opcode, r_dest, displacement, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800515 } else {
buzbeefa57c472012-11-21 12:06:18 -0800516 load = res = NewLIR3(cu, opcode, r_dest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700517 displacement + LOWORD_OFFSET, rBase);
buzbeefa57c472012-11-21 12:06:18 -0800518 load2 = NewLIR3(cu, opcode, r_dest_hi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700519 displacement + HIWORD_OFFSET, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800520 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700521 } else {
522 if (pair) {
buzbeefa57c472012-11-21 12:06:18 -0800523 int r_tmp = AllocFreeTemp(cu);
524 res = OpRegRegImm(cu, kOpAdd, r_tmp, rBase, displacement);
525 load = NewLIR3(cu, opcode, r_dest, LOWORD_OFFSET, r_tmp);
526 load2 = NewLIR3(cu, opcode, r_dest_hi, HIWORD_OFFSET, r_tmp);
527 FreeTemp(cu, r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700528 } else {
buzbeefa57c472012-11-21 12:06:18 -0800529 int r_tmp = (rBase == r_dest) ? AllocFreeTemp(cu) : r_dest;
530 res = OpRegRegImm(cu, kOpAdd, r_tmp, rBase, displacement);
531 load = NewLIR3(cu, opcode, r_dest, 0, r_tmp);
532 if (r_tmp != r_dest)
533 FreeTemp(cu, r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 }
535 }
buzbeee3acd072012-02-25 17:03:10 -0800536
buzbeef0504cd2012-11-13 16:31:10 -0800537 if (rBase == rMIPS_SP) {
buzbee02031b12012-11-23 09:41:35 -0800538 AnnotateDalvikRegAccess(cu, load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800539 true /* is_load */, pair /* is64bit */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700540 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800541 AnnotateDalvikRegAccess(cu, load2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800542 true /* is_load */, pair /* is64bit */);
buzbeee3acd072012-02-25 17:03:10 -0800543 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 }
545 return load;
buzbeee3acd072012-02-25 17:03:10 -0800546}
547
buzbee02031b12012-11-23 09:41:35 -0800548LIR* MipsCodegen::LoadBaseDisp(CompilationUnit *cu, int rBase, int displacement, int r_dest,
549 OpSize size, int s_reg)
buzbeee3acd072012-02-25 17:03:10 -0800550{
buzbeefa57c472012-11-21 12:06:18 -0800551 return LoadBaseDispBody(cu, rBase, displacement, r_dest, -1,
552 size, s_reg);
buzbeee3acd072012-02-25 17:03:10 -0800553}
554
buzbee02031b12012-11-23 09:41:35 -0800555LIR* MipsCodegen::LoadBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
556 int r_dest_lo, int r_dest_hi, int s_reg)
buzbeee3acd072012-02-25 17:03:10 -0800557{
buzbee02031b12012-11-23 09:41:35 -0800558 return LoadBaseDispBody(cu, rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
buzbeee3acd072012-02-25 17:03:10 -0800559}
560
buzbee02031b12012-11-23 09:41:35 -0800561LIR* MipsCodegen::StoreBaseDispBody(CompilationUnit *cu, int rBase, int displacement,
562 int r_src, int r_src_hi, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800563{
Bill Buzbeea114add2012-05-03 15:00:40 -0700564 LIR *res;
565 LIR *store = NULL;
566 LIR *store2 = NULL;
567 MipsOpCode opcode = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800568 bool short_form = IS_SIMM16(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700569 bool pair = false;
buzbeee3acd072012-02-25 17:03:10 -0800570
Bill Buzbeea114add2012-05-03 15:00:40 -0700571 switch (size) {
572 case kLong:
573 case kDouble:
574 pair = true;
575 opcode = kMipsSw;
buzbeefa57c472012-11-21 12:06:18 -0800576 if (MIPS_FPREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700577 opcode = kMipsFswc1;
buzbeefa57c472012-11-21 12:06:18 -0800578 if (MIPS_DOUBLEREG(r_src)) {
579 r_src = r_src - MIPS_FP_DOUBLE;
buzbeee3acd072012-02-25 17:03:10 -0800580 } else {
buzbeefa57c472012-11-21 12:06:18 -0800581 DCHECK(MIPS_FPREG(r_src_hi));
582 DCHECK_EQ(r_src, (r_src_hi - 1));
buzbeee3acd072012-02-25 17:03:10 -0800583 }
buzbeefa57c472012-11-21 12:06:18 -0800584 r_src_hi = r_src + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700585 }
buzbeefa57c472012-11-21 12:06:18 -0800586 short_form = IS_SIMM16_2WORD(displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700587 DCHECK_EQ((displacement & 0x3), 0);
588 break;
589 case kWord:
590 case kSingle:
591 opcode = kMipsSw;
buzbeefa57c472012-11-21 12:06:18 -0800592 if (MIPS_FPREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700593 opcode = kMipsFswc1;
buzbeefa57c472012-11-21 12:06:18 -0800594 DCHECK(MIPS_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700595 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700596 DCHECK_EQ((displacement & 0x3), 0);
597 break;
598 case kUnsignedHalf:
599 case kSignedHalf:
600 opcode = kMipsSh;
601 DCHECK_EQ((displacement & 0x1), 0);
602 break;
603 case kUnsignedByte:
604 case kSignedByte:
605 opcode = kMipsSb;
606 break;
607 default:
buzbee52a77fc2012-11-20 19:50:46 -0800608 LOG(FATAL) << "Bad case in StoreBaseIndexedBody";
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 }
610
buzbeefa57c472012-11-21 12:06:18 -0800611 if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700612 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800613 store = res = NewLIR3(cu, opcode, r_src, displacement, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800614 } else {
buzbeefa57c472012-11-21 12:06:18 -0800615 store = res = NewLIR3(cu, opcode, r_src, displacement + LOWORD_OFFSET,
Bill Buzbeea114add2012-05-03 15:00:40 -0700616 rBase);
buzbeefa57c472012-11-21 12:06:18 -0800617 store2 = NewLIR3(cu, opcode, r_src_hi, displacement + HIWORD_OFFSET,
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 rBase);
buzbeee3acd072012-02-25 17:03:10 -0800619 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700620 } else {
buzbeefa57c472012-11-21 12:06:18 -0800621 int r_scratch = AllocTemp(cu);
622 res = OpRegRegImm(cu, kOpAdd, r_scratch, rBase, displacement);
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800624 store = NewLIR3(cu, opcode, r_src, 0, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700625 } else {
buzbeefa57c472012-11-21 12:06:18 -0800626 store = NewLIR3(cu, opcode, r_src, LOWORD_OFFSET, r_scratch);
627 store2 = NewLIR3(cu, opcode, r_src_hi, HIWORD_OFFSET, r_scratch);
buzbeee3acd072012-02-25 17:03:10 -0800628 }
buzbeefa57c472012-11-21 12:06:18 -0800629 FreeTemp(cu, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700630 }
buzbeee3acd072012-02-25 17:03:10 -0800631
buzbeef0504cd2012-11-13 16:31:10 -0800632 if (rBase == rMIPS_SP) {
buzbee02031b12012-11-23 09:41:35 -0800633 AnnotateDalvikRegAccess(cu, store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
634 false /* is_load */, pair /* is64bit */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700635 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800636 AnnotateDalvikRegAccess(cu, store2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800637 false /* is_load */, pair /* is64bit */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700638 }
639 }
640
641 return res;
buzbeee3acd072012-02-25 17:03:10 -0800642}
643
buzbee02031b12012-11-23 09:41:35 -0800644LIR* MipsCodegen::StoreBaseDisp(CompilationUnit *cu, int rBase, int displacement, int r_src,
645 OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800646{
buzbeefa57c472012-11-21 12:06:18 -0800647 return StoreBaseDispBody(cu, rBase, displacement, r_src, -1, size);
buzbeee3acd072012-02-25 17:03:10 -0800648}
649
buzbee02031b12012-11-23 09:41:35 -0800650LIR* MipsCodegen::StoreBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
651 int r_src_lo, int r_src_hi)
buzbeee3acd072012-02-25 17:03:10 -0800652{
buzbeefa57c472012-11-21 12:06:18 -0800653 return StoreBaseDispBody(cu, rBase, displacement, r_src_lo, r_src_hi, kLong);
buzbeee3acd072012-02-25 17:03:10 -0800654}
655
buzbee02031b12012-11-23 09:41:35 -0800656LIR* MipsCodegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
buzbeeb046e162012-10-30 15:48:42 -0700657{
buzbee52a77fc2012-11-20 19:50:46 -0800658 LOG(FATAL) << "Unexpected use of OpThreadMem for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700659 return NULL;
660}
661
buzbee02031b12012-11-23 09:41:35 -0800662LIR* MipsCodegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
buzbeeb046e162012-10-30 15:48:42 -0700663{
buzbee52a77fc2012-11-20 19:50:46 -0800664 LOG(FATAL) << "Unexpected use of OpMem for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700665 return NULL;
666}
667
buzbee02031b12012-11-23 09:41:35 -0800668LIR* MipsCodegen::StoreBaseIndexedDisp(CompilationUnit *cu,
buzbeefa57c472012-11-21 12:06:18 -0800669 int rBase, int r_index, int scale, int displacement,
670 int r_src, int r_src_hi,
671 OpSize size, int s_reg)
buzbeeb046e162012-10-30 15:48:42 -0700672{
buzbee52a77fc2012-11-20 19:50:46 -0800673 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700674 return NULL;
675}
676
buzbee02031b12012-11-23 09:41:35 -0800677LIR* MipsCodegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase,
buzbeeb046e162012-10-30 15:48:42 -0700678 int offset)
679{
buzbee52a77fc2012-11-20 19:50:46 -0800680 LOG(FATAL) << "Unexpected use of OpRegMem for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700681 return NULL;
682}
683
buzbee02031b12012-11-23 09:41:35 -0800684LIR* MipsCodegen::LoadBaseIndexedDisp(CompilationUnit *cu,
buzbeefa57c472012-11-21 12:06:18 -0800685 int rBase, int r_index, int scale, int displacement,
686 int r_dest, int r_dest_hi,
687 OpSize size, int s_reg)
buzbeeb046e162012-10-30 15:48:42 -0700688{
buzbee52a77fc2012-11-20 19:50:46 -0800689 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700690 return NULL;
691}
692
buzbee02031b12012-11-23 09:41:35 -0800693LIR* MipsCodegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target)
buzbeeb046e162012-10-30 15:48:42 -0700694{
buzbee52a77fc2012-11-20 19:50:46 -0800695 LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS";
buzbeeb046e162012-10-30 15:48:42 -0700696 return NULL;
697}
698
buzbeee3acd072012-02-25 17:03:10 -0800699} // namespace art