blob: 4bece136bca412909541dd97357d038a64e4baed [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <string>
18
19#include "arm_lir.h"
20#include "codegen_arm.h"
21#include "dex/compiler_internals.h"
22#include "dex/quick/mir_to_lir-inl.h"
23
24namespace art {
25
26static int core_regs[] = {r0, r1, r2, r3, rARM_SUSPEND, r5, r6, r7, r8, rARM_SELF, r10,
27 r11, r12, rARM_SP, rARM_LR, rARM_PC};
28static int ReservedRegs[] = {rARM_SUSPEND, rARM_SELF, rARM_SP, rARM_LR, rARM_PC};
29static int FpRegs[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
30 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15,
31 fr16, fr17, fr18, fr19, fr20, fr21, fr22, fr23,
32 fr24, fr25, fr26, fr27, fr28, fr29, fr30, fr31};
33static int core_temps[] = {r0, r1, r2, r3, r12};
34static int fp_temps[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
35 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15};
36
37RegLocation ArmMir2Lir::LocCReturn()
38{
39 RegLocation res = ARM_LOC_C_RETURN;
40 return res;
41}
42
43RegLocation ArmMir2Lir::LocCReturnWide()
44{
45 RegLocation res = ARM_LOC_C_RETURN_WIDE;
46 return res;
47}
48
49RegLocation ArmMir2Lir::LocCReturnFloat()
50{
51 RegLocation res = ARM_LOC_C_RETURN_FLOAT;
52 return res;
53}
54
55RegLocation ArmMir2Lir::LocCReturnDouble()
56{
57 RegLocation res = ARM_LOC_C_RETURN_DOUBLE;
58 return res;
59}
60
61// Return a target-dependent special register.
62int ArmMir2Lir::TargetReg(SpecialTargetRegister reg) {
63 int res = INVALID_REG;
64 switch (reg) {
65 case kSelf: res = rARM_SELF; break;
66 case kSuspend: res = rARM_SUSPEND; break;
67 case kLr: res = rARM_LR; break;
68 case kPc: res = rARM_PC; break;
69 case kSp: res = rARM_SP; break;
70 case kArg0: res = rARM_ARG0; break;
71 case kArg1: res = rARM_ARG1; break;
72 case kArg2: res = rARM_ARG2; break;
73 case kArg3: res = rARM_ARG3; break;
74 case kFArg0: res = rARM_FARG0; break;
75 case kFArg1: res = rARM_FARG1; break;
76 case kFArg2: res = rARM_FARG2; break;
77 case kFArg3: res = rARM_FARG3; break;
78 case kRet0: res = rARM_RET0; break;
79 case kRet1: res = rARM_RET1; break;
80 case kInvokeTgt: res = rARM_INVOKE_TGT; break;
81 case kCount: res = rARM_COUNT; break;
82 }
83 return res;
84}
85
86
87// Create a double from a pair of singles.
88int ArmMir2Lir::S2d(int low_reg, int high_reg)
89{
90 return ARM_S2D(low_reg, high_reg);
91}
92
93// Return mask to strip off fp reg flags and bias.
94uint32_t ArmMir2Lir::FpRegMask()
95{
96 return ARM_FP_REG_MASK;
97}
98
99// True if both regs single, both core or both double.
100bool ArmMir2Lir::SameRegType(int reg1, int reg2)
101{
102 return (ARM_REGTYPE(reg1) == ARM_REGTYPE(reg2));
103}
104
105/*
106 * Decode the register id.
107 */
108uint64_t ArmMir2Lir::GetRegMaskCommon(int reg)
109{
110 uint64_t seed;
111 int shift;
112 int reg_id;
113
114
115 reg_id = reg & 0x1f;
116 /* Each double register is equal to a pair of single-precision FP registers */
117 seed = ARM_DOUBLEREG(reg) ? 3 : 1;
118 /* FP register starts at bit position 16 */
119 shift = ARM_FPREG(reg) ? kArmFPReg0 : 0;
120 /* Expand the double register id into single offset */
121 shift += reg_id;
122 return (seed << shift);
123}
124
125uint64_t ArmMir2Lir::GetPCUseDefEncoding()
126{
127 return ENCODE_ARM_REG_PC;
128}
129
130void ArmMir2Lir::SetupTargetResourceMasks(LIR* lir)
131{
132 DCHECK_EQ(cu_->instruction_set, kThumb2);
133
134 // Thumb2 specific setup
135 uint64_t flags = ArmMir2Lir::EncodingMap[lir->opcode].flags;
136 int opcode = lir->opcode;
137
138 if (flags & REG_DEF_SP) {
139 lir->def_mask |= ENCODE_ARM_REG_SP;
140 }
141
142 if (flags & REG_USE_SP) {
143 lir->use_mask |= ENCODE_ARM_REG_SP;
144 }
145
146 if (flags & REG_DEF_LIST0) {
147 lir->def_mask |= ENCODE_ARM_REG_LIST(lir->operands[0]);
148 }
149
150 if (flags & REG_DEF_LIST1) {
151 lir->def_mask |= ENCODE_ARM_REG_LIST(lir->operands[1]);
152 }
153
154 if (flags & REG_DEF_FPCS_LIST0) {
155 lir->def_mask |= ENCODE_ARM_REG_FPCS_LIST(lir->operands[0]);
156 }
157
158 if (flags & REG_DEF_FPCS_LIST2) {
159 for (int i = 0; i < lir->operands[2]; i++) {
160 SetupRegMask(&lir->def_mask, lir->operands[1] + i);
161 }
162 }
163
164 if (flags & REG_USE_PC) {
165 lir->use_mask |= ENCODE_ARM_REG_PC;
166 }
167
168 /* Conservatively treat the IT block */
169 if (flags & IS_IT) {
170 lir->def_mask = ENCODE_ALL;
171 }
172
173 if (flags & REG_USE_LIST0) {
174 lir->use_mask |= ENCODE_ARM_REG_LIST(lir->operands[0]);
175 }
176
177 if (flags & REG_USE_LIST1) {
178 lir->use_mask |= ENCODE_ARM_REG_LIST(lir->operands[1]);
179 }
180
181 if (flags & REG_USE_FPCS_LIST0) {
182 lir->use_mask |= ENCODE_ARM_REG_FPCS_LIST(lir->operands[0]);
183 }
184
185 if (flags & REG_USE_FPCS_LIST2) {
186 for (int i = 0; i < lir->operands[2]; i++) {
187 SetupRegMask(&lir->use_mask, lir->operands[1] + i);
188 }
189 }
190 /* Fixup for kThumbPush/lr and kThumbPop/pc */
191 if (opcode == kThumbPush || opcode == kThumbPop) {
192 uint64_t r8Mask = GetRegMaskCommon(r8);
193 if ((opcode == kThumbPush) && (lir->use_mask & r8Mask)) {
194 lir->use_mask &= ~r8Mask;
195 lir->use_mask |= ENCODE_ARM_REG_LR;
196 } else if ((opcode == kThumbPop) && (lir->def_mask & r8Mask)) {
197 lir->def_mask &= ~r8Mask;
198 lir->def_mask |= ENCODE_ARM_REG_PC;
199 }
200 }
201 if (flags & REG_DEF_LR) {
202 lir->def_mask |= ENCODE_ARM_REG_LR;
203 }
204}
205
206ArmConditionCode ArmMir2Lir::ArmConditionEncoding(ConditionCode ccode)
207{
208 ArmConditionCode res;
209 switch (ccode) {
210 case kCondEq: res = kArmCondEq; break;
211 case kCondNe: res = kArmCondNe; break;
212 case kCondCs: res = kArmCondCs; break;
213 case kCondCc: res = kArmCondCc; break;
214 case kCondMi: res = kArmCondMi; break;
215 case kCondPl: res = kArmCondPl; break;
216 case kCondVs: res = kArmCondVs; break;
217 case kCondVc: res = kArmCondVc; break;
218 case kCondHi: res = kArmCondHi; break;
219 case kCondLs: res = kArmCondLs; break;
220 case kCondGe: res = kArmCondGe; break;
221 case kCondLt: res = kArmCondLt; break;
222 case kCondGt: res = kArmCondGt; break;
223 case kCondLe: res = kArmCondLe; break;
224 case kCondAl: res = kArmCondAl; break;
225 case kCondNv: res = kArmCondNv; break;
226 default:
227 LOG(FATAL) << "Bad condition code " << ccode;
228 res = static_cast<ArmConditionCode>(0); // Quiet gcc
229 }
230 return res;
231}
232
233static const char* core_reg_names[16] = {
234 "r0",
235 "r1",
236 "r2",
237 "r3",
238 "r4",
239 "r5",
240 "r6",
241 "r7",
242 "r8",
243 "rSELF",
244 "r10",
245 "r11",
246 "r12",
247 "sp",
248 "lr",
249 "pc",
250};
251
252
253static const char* shift_names[4] = {
254 "lsl",
255 "lsr",
256 "asr",
257 "ror"};
258
259/* Decode and print a ARM register name */
260static char* DecodeRegList(int opcode, int vector, char* buf)
261{
262 int i;
263 bool printed = false;
264 buf[0] = 0;
265 for (i = 0; i < 16; i++, vector >>= 1) {
266 if (vector & 0x1) {
267 int reg_id = i;
268 if (opcode == kThumbPush && i == 8) {
269 reg_id = r14lr;
270 } else if (opcode == kThumbPop && i == 8) {
271 reg_id = r15pc;
272 }
273 if (printed) {
274 sprintf(buf + strlen(buf), ", r%d", reg_id);
275 } else {
276 printed = true;
277 sprintf(buf, "r%d", reg_id);
278 }
279 }
280 }
281 return buf;
282}
283
284static char* DecodeFPCSRegList(int count, int base, char* buf)
285{
286 sprintf(buf, "s%d", base);
287 for (int i = 1; i < count; i++) {
288 sprintf(buf + strlen(buf), ", s%d",base + i);
289 }
290 return buf;
291}
292
293static int ExpandImmediate(int value)
294{
295 int mode = (value & 0xf00) >> 8;
296 uint32_t bits = value & 0xff;
297 switch (mode) {
298 case 0:
299 return bits;
300 case 1:
301 return (bits << 16) | bits;
302 case 2:
303 return (bits << 24) | (bits << 8);
304 case 3:
305 return (bits << 24) | (bits << 16) | (bits << 8) | bits;
306 default:
307 break;
308 }
309 bits = (bits | 0x80) << 24;
310 return bits >> (((value & 0xf80) >> 7) - 8);
311}
312
313const char* cc_names[] = {"eq","ne","cs","cc","mi","pl","vs","vc",
314 "hi","ls","ge","lt","gt","le","al","nv"};
315/*
316 * Interpret a format string and build a string no longer than size
317 * See format key in Assemble.c.
318 */
319std::string ArmMir2Lir::BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr)
320{
321 std::string buf;
322 int i;
323 const char* fmt_end = &fmt[strlen(fmt)];
324 char tbuf[256];
325 const char* name;
326 char nc;
327 while (fmt < fmt_end) {
328 int operand;
329 if (*fmt == '!') {
330 fmt++;
331 DCHECK_LT(fmt, fmt_end);
332 nc = *fmt++;
333 if (nc=='!') {
334 strcpy(tbuf, "!");
335 } else {
336 DCHECK_LT(fmt, fmt_end);
337 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4U);
338 operand = lir->operands[nc-'0'];
339 switch (*fmt++) {
340 case 'H':
341 if (operand != 0) {
342 sprintf(tbuf, ", %s %d",shift_names[operand & 0x3], operand >> 2);
343 } else {
344 strcpy(tbuf,"");
345 }
346 break;
347 case 'B':
348 switch (operand) {
349 case kSY:
350 name = "sy";
351 break;
352 case kST:
353 name = "st";
354 break;
355 case kISH:
356 name = "ish";
357 break;
358 case kISHST:
359 name = "ishst";
360 break;
361 case kNSH:
362 name = "nsh";
363 break;
364 case kNSHST:
365 name = "shst";
366 break;
367 default:
368 name = "DecodeError2";
369 break;
370 }
371 strcpy(tbuf, name);
372 break;
373 case 'b':
374 strcpy(tbuf,"0000");
375 for (i=3; i>= 0; i--) {
376 tbuf[i] += operand & 1;
377 operand >>= 1;
378 }
379 break;
380 case 'n':
381 operand = ~ExpandImmediate(operand);
382 sprintf(tbuf,"%d [%#x]", operand, operand);
383 break;
384 case 'm':
385 operand = ExpandImmediate(operand);
386 sprintf(tbuf,"%d [%#x]", operand, operand);
387 break;
388 case 's':
389 sprintf(tbuf,"s%d",operand & ARM_FP_REG_MASK);
390 break;
391 case 'S':
392 sprintf(tbuf,"d%d",(operand & ARM_FP_REG_MASK) >> 1);
393 break;
394 case 'h':
395 sprintf(tbuf,"%04x", operand);
396 break;
397 case 'M':
398 case 'd':
399 sprintf(tbuf,"%d", operand);
400 break;
401 case 'C':
402 DCHECK_LT(operand, static_cast<int>(
403 sizeof(core_reg_names)/sizeof(core_reg_names[0])));
404 sprintf(tbuf,"%s",core_reg_names[operand]);
405 break;
406 case 'E':
407 sprintf(tbuf,"%d", operand*4);
408 break;
409 case 'F':
410 sprintf(tbuf,"%d", operand*2);
411 break;
412 case 'c':
413 strcpy(tbuf, cc_names[operand]);
414 break;
415 case 't':
416 sprintf(tbuf,"0x%08x (L%p)",
417 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 +
418 (operand << 1),
419 lir->target);
420 break;
421 case 'u': {
422 int offset_1 = lir->operands[0];
423 int offset_2 = NEXT_LIR(lir)->operands[0];
424 uintptr_t target =
425 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) &
426 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
427 0xfffffffc;
428 sprintf(tbuf, "%p", reinterpret_cast<void *>(target));
429 break;
430 }
431
432 /* Nothing to print for BLX_2 */
433 case 'v':
434 strcpy(tbuf, "see above");
435 break;
436 case 'R':
437 DecodeRegList(lir->opcode, operand, tbuf);
438 break;
439 case 'P':
440 DecodeFPCSRegList(operand, 16, tbuf);
441 break;
442 case 'Q':
443 DecodeFPCSRegList(operand, 0, tbuf);
444 break;
445 default:
446 strcpy(tbuf,"DecodeError1");
447 break;
448 }
449 buf += tbuf;
450 }
451 } else {
452 buf += *fmt++;
453 }
454 }
455 return buf;
456}
457
458void ArmMir2Lir::DumpResourceMask(LIR* arm_lir, uint64_t mask, const char* prefix)
459{
460 char buf[256];
461 buf[0] = 0;
462
463 if (mask == ENCODE_ALL) {
464 strcpy(buf, "all");
465 } else {
466 char num[8];
467 int i;
468
469 for (i = 0; i < kArmRegEnd; i++) {
470 if (mask & (1ULL << i)) {
471 sprintf(num, "%d ", i);
472 strcat(buf, num);
473 }
474 }
475
476 if (mask & ENCODE_CCODE) {
477 strcat(buf, "cc ");
478 }
479 if (mask & ENCODE_FP_STATUS) {
480 strcat(buf, "fpcc ");
481 }
482
483 /* Memory bits */
484 if (arm_lir && (mask & ENCODE_DALVIK_REG)) {
485 sprintf(buf + strlen(buf), "dr%d%s", arm_lir->alias_info & 0xffff,
486 (arm_lir->alias_info & 0x80000000) ? "(+1)" : "");
487 }
488 if (mask & ENCODE_LITERAL) {
489 strcat(buf, "lit ");
490 }
491
492 if (mask & ENCODE_HEAP_REF) {
493 strcat(buf, "heap ");
494 }
495 if (mask & ENCODE_MUST_NOT_ALIAS) {
496 strcat(buf, "noalias ");
497 }
498 }
499 if (buf[0]) {
500 LOG(INFO) << prefix << ": " << buf;
501 }
502}
503
504bool ArmMir2Lir::IsUnconditionalBranch(LIR* lir)
505{
506 return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond));
507}
508
509ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
510 : Mir2Lir(cu, mir_graph, arena) {
511 // Sanity check - make sure encoding map lines up.
512 for (int i = 0; i < kArmLast; i++) {
513 if (ArmMir2Lir::EncodingMap[i].opcode != i) {
514 LOG(FATAL) << "Encoding order for " << ArmMir2Lir::EncodingMap[i].name
515 << " is wrong: expecting " << i << ", seeing "
516 << static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode);
517 }
518 }
519}
520
521Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
522 ArenaAllocator* const arena) {
523 return new ArmMir2Lir(cu, mir_graph, arena);
524}
525
526/*
527 * Alloc a pair of core registers, or a double. Low reg in low byte,
528 * high reg in next byte.
529 */
530int ArmMir2Lir::AllocTypedTempPair(bool fp_hint, int reg_class)
531{
532 int high_reg;
533 int low_reg;
534 int res = 0;
535
536 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
537 low_reg = AllocTempDouble();
538 high_reg = low_reg + 1;
539 } else {
540 low_reg = AllocTemp();
541 high_reg = AllocTemp();
542 }
543 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
544 return res;
545}
546
547int ArmMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class)
548{
549 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg))
550 return AllocTempFloat();
551 return AllocTemp();
552}
553
554void ArmMir2Lir::CompilerInitializeRegAlloc()
555{
556 int num_regs = sizeof(core_regs)/sizeof(*core_regs);
557 int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs);
558 int num_temps = sizeof(core_temps)/sizeof(*core_temps);
559 int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs);
560 int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps);
561 reg_pool_ = static_cast<RegisterPool*>(arena_->NewMem(sizeof(*reg_pool_), true,
562 ArenaAllocator::kAllocRegAlloc));
563 reg_pool_->num_core_regs = num_regs;
564 reg_pool_->core_regs = reinterpret_cast<RegisterInfo*>
565 (arena_->NewMem(num_regs * sizeof(*reg_pool_->core_regs), true,
566 ArenaAllocator::kAllocRegAlloc));
567 reg_pool_->num_fp_regs = num_fp_regs;
568 reg_pool_->FPRegs = static_cast<RegisterInfo*>
569 (arena_->NewMem(num_fp_regs * sizeof(*reg_pool_->FPRegs), true,
570 ArenaAllocator::kAllocRegAlloc));
571 CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs);
572 CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs);
573 // Keep special registers from being allocated
574 for (int i = 0; i < num_reserved; i++) {
575 if (NO_SUSPEND && (ReservedRegs[i] == rARM_SUSPEND)) {
576 //To measure cost of suspend check
577 continue;
578 }
579 MarkInUse(ReservedRegs[i]);
580 }
581 // Mark temp regs - all others not in use can be used for promotion
582 for (int i = 0; i < num_temps; i++) {
583 MarkTemp(core_temps[i]);
584 }
585 for (int i = 0; i < num_fp_temps; i++) {
586 MarkTemp(fp_temps[i]);
587 }
588
589 // Start allocation at r2 in an attempt to avoid clobbering return values
590 reg_pool_->next_core_reg = r2;
591}
592
593void ArmMir2Lir::FreeRegLocTemps(RegLocation rl_keep,
594 RegLocation rl_free)
595{
596 if ((rl_free.low_reg != rl_keep.low_reg) && (rl_free.low_reg != rl_keep.high_reg) &&
597 (rl_free.high_reg != rl_keep.low_reg) && (rl_free.high_reg != rl_keep.high_reg)) {
598 // No overlap, free both
599 FreeTemp(rl_free.low_reg);
600 FreeTemp(rl_free.high_reg);
601 }
602}
603/*
604 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
605 * instructions might call out to C/assembly helper functions. Until
606 * machinery is in place, always spill lr.
607 */
608
609void ArmMir2Lir::AdjustSpillMask()
610{
611 core_spill_mask_ |= (1 << rARM_LR);
612 num_core_spills_++;
613}
614
615/*
616 * Mark a callee-save fp register as promoted. Note that
617 * vpush/vpop uses contiguous register lists so we must
618 * include any holes in the mask. Associate holes with
619 * Dalvik register INVALID_VREG (0xFFFFU).
620 */
621void ArmMir2Lir::MarkPreservedSingle(int v_reg, int reg)
622{
623 DCHECK_GE(reg, ARM_FP_REG_MASK + ARM_FP_CALLEE_SAVE_BASE);
624 reg = (reg & ARM_FP_REG_MASK) - ARM_FP_CALLEE_SAVE_BASE;
625 // Ensure fp_vmap_table is large enough
626 int table_size = fp_vmap_table_.size();
627 for (int i = table_size; i < (reg + 1); i++) {
628 fp_vmap_table_.push_back(INVALID_VREG);
629 }
630 // Add the current mapping
631 fp_vmap_table_[reg] = v_reg;
632 // Size of fp_vmap_table is high-water mark, use to set mask
633 num_fp_spills_ = fp_vmap_table_.size();
634 fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE;
635}
636
637void ArmMir2Lir::FlushRegWide(int reg1, int reg2)
638{
639 RegisterInfo* info1 = GetRegInfo(reg1);
640 RegisterInfo* info2 = GetRegInfo(reg2);
641 DCHECK(info1 && info2 && info1->pair && info2->pair &&
642 (info1->partner == info2->reg) &&
643 (info2->partner == info1->reg));
644 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
645 if (!(info1->is_temp && info2->is_temp)) {
646 /* Should not happen. If it does, there's a problem in eval_loc */
647 LOG(FATAL) << "Long half-temp, half-promoted";
648 }
649
650 info1->dirty = false;
651 info2->dirty = false;
652 if (mir_graph_->SRegToVReg(info2->s_reg) <
653 mir_graph_->SRegToVReg(info1->s_reg))
654 info1 = info2;
655 int v_reg = mir_graph_->SRegToVReg(info1->s_reg);
656 StoreBaseDispWide(rARM_SP, VRegOffset(v_reg), info1->reg, info1->partner);
657 }
658}
659
660void ArmMir2Lir::FlushReg(int reg)
661{
662 RegisterInfo* info = GetRegInfo(reg);
663 if (info->live && info->dirty) {
664 info->dirty = false;
665 int v_reg = mir_graph_->SRegToVReg(info->s_reg);
666 StoreBaseDisp(rARM_SP, VRegOffset(v_reg), reg, kWord);
667 }
668}
669
670/* Give access to the target-dependent FP register encoding to common code */
671bool ArmMir2Lir::IsFpReg(int reg) {
672 return ARM_FPREG(reg);
673}
674
675/* Clobber all regs that might be used by an external C call */
676void ArmMir2Lir::ClobberCalleeSave()
677{
678 Clobber(r0);
679 Clobber(r1);
680 Clobber(r2);
681 Clobber(r3);
682 Clobber(r12);
683 Clobber(r14lr);
684 Clobber(fr0);
685 Clobber(fr1);
686 Clobber(fr2);
687 Clobber(fr3);
688 Clobber(fr4);
689 Clobber(fr5);
690 Clobber(fr6);
691 Clobber(fr7);
692 Clobber(fr8);
693 Clobber(fr9);
694 Clobber(fr10);
695 Clobber(fr11);
696 Clobber(fr12);
697 Clobber(fr13);
698 Clobber(fr14);
699 Clobber(fr15);
700}
701
702RegLocation ArmMir2Lir::GetReturnWideAlt()
703{
704 RegLocation res = LocCReturnWide();
705 res.low_reg = r2;
706 res.high_reg = r3;
707 Clobber(r2);
708 Clobber(r3);
709 MarkInUse(r2);
710 MarkInUse(r3);
711 MarkPair(res.low_reg, res.high_reg);
712 return res;
713}
714
715RegLocation ArmMir2Lir::GetReturnAlt()
716{
717 RegLocation res = LocCReturn();
718 res.low_reg = r1;
719 Clobber(r1);
720 MarkInUse(r1);
721 return res;
722}
723
724ArmMir2Lir::RegisterInfo* ArmMir2Lir::GetRegInfo(int reg)
725{
726 return ARM_FPREG(reg) ? &reg_pool_->FPRegs[reg & ARM_FP_REG_MASK]
727 : &reg_pool_->core_regs[reg];
728}
729
730/* To be used when explicitly managing register use */
731void ArmMir2Lir::LockCallTemps()
732{
733 LockTemp(r0);
734 LockTemp(r1);
735 LockTemp(r2);
736 LockTemp(r3);
737}
738
739/* To be used when explicitly managing register use */
740void ArmMir2Lir::FreeCallTemps()
741{
742 FreeTemp(r0);
743 FreeTemp(r1);
744 FreeTemp(r2);
745 FreeTemp(r3);
746}
747
748int ArmMir2Lir::LoadHelper(int offset)
749{
750 LoadWordDisp(rARM_SELF, offset, rARM_LR);
751 return rARM_LR;
752}
753
754uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode)
755{
756 return ArmMir2Lir::EncodingMap[opcode].flags;
757}
758
759const char* ArmMir2Lir::GetTargetInstName(int opcode)
760{
761 return ArmMir2Lir::EncodingMap[opcode].name;
762}
763
764const char* ArmMir2Lir::GetTargetInstFmt(int opcode)
765{
766 return ArmMir2Lir::EncodingMap[opcode].fmt;
767}
768
769} // namespace art