blob: 04bdc34de7f889c7232fbfa3e228b3ce1a0d37b6 [file] [log] [blame]
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001/*
2 * Copyright (C) 2014 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 "code_generator_arm.h"
18#include "utils/assembler.h"
19#include "utils/arm/assembler_arm.h"
20
Nicolas Geoffray787c3072014-03-17 10:20:19 +000021#define __ reinterpret_cast<ArmAssembler*>(GetAssembler())->
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000022
23namespace art {
24namespace arm {
25
26void CodeGeneratorARM::GenerateFrameEntry() {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000027 __ PushList((1 << FP) | (1 << LR));
28 __ mov(FP, ShifterOperand(SP));
Nicolas Geoffray787c3072014-03-17 10:20:19 +000029 if (GetFrameSize() != 0) {
30 __ AddConstant(SP, -GetFrameSize());
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000031 }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000032}
33
34void CodeGeneratorARM::GenerateFrameExit() {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000035 __ mov(SP, ShifterOperand(FP));
36 __ PopList((1 << FP) | (1 << PC));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000037}
38
39void CodeGeneratorARM::Bind(Label* label) {
40 __ Bind(label);
41}
42
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000043void CodeGeneratorARM::Push(HInstruction* instruction, Location location) {
44 __ Push(location.reg<Register>());
45}
46
47void CodeGeneratorARM::Move(HInstruction* instruction, Location location) {
48 HIntConstant* constant = instruction->AsIntConstant();
49 if (constant != nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000050 __ LoadImmediate(location.reg<Register>(), constant->GetValue());
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000051 } else {
52 __ Pop(location.reg<Register>());
53 }
54}
55
56void LocationsBuilderARM::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000057 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000058}
59
Nicolas Geoffray787c3072014-03-17 10:20:19 +000060void InstructionCodeGeneratorARM::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000061 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +000062 if (GetGraph()->GetExitBlock() == successor) {
63 codegen_->GenerateFrameExit();
64 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
65 __ b(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000066 }
67}
68
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000069void LocationsBuilderARM::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000070 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000071}
72
Nicolas Geoffray787c3072014-03-17 10:20:19 +000073void InstructionCodeGeneratorARM::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000074 if (kIsDebugBuild) {
75 __ Comment("Unreachable");
76 __ bkpt(0);
77 }
78}
79
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000080void LocationsBuilderARM::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000081 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000082 locations->SetInAt(0, Location(R0));
Nicolas Geoffray787c3072014-03-17 10:20:19 +000083 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000084}
85
Nicolas Geoffray787c3072014-03-17 10:20:19 +000086void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000087 // TODO: Generate the input as a condition, instead of materializing in a register.
Nicolas Geoffray787c3072014-03-17 10:20:19 +000088 __ cmp(if_instr->GetLocations()->InAt(0).reg<Register>(), ShifterOperand(0));
89 __ b(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()), EQ);
90 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) {
91 __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000092 }
93}
94
95void LocationsBuilderARM::VisitEqual(HEqual* equal) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000096 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000097 locations->SetInAt(0, Location(R0));
98 locations->SetInAt(1, Location(R1));
99 locations->SetOut(Location(R0));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000100 equal->SetLocations(locations);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000101}
102
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000103void InstructionCodeGeneratorARM::VisitEqual(HEqual* equal) {
104 LocationSummary* locations = equal->GetLocations();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000105 __ teq(locations->InAt(0).reg<Register>(),
106 ShifterOperand(locations->InAt(1).reg<Register>()));
107 __ mov(locations->Out().reg<Register>(), ShifterOperand(1), EQ);
108 __ mov(locations->Out().reg<Register>(), ShifterOperand(0), NE);
109}
110
111void LocationsBuilderARM::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000112 local->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000113}
114
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000115void InstructionCodeGeneratorARM::VisitLocal(HLocal* local) {
116 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
117 codegen_->SetFrameSize(codegen_->GetFrameSize() + kWordSize);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000118}
119
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000120void LocationsBuilderARM::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000121 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(load);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000122 locations->SetOut(Location(R0));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000123 load->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000124}
125
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000126static int32_t GetStackSlot(HLocal* local) {
127 // We are currently using FP to access locals, so the offset must be negative.
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000128 return (local->GetRegNumber() + 1) * -kWordSize;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000129}
130
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000131void InstructionCodeGeneratorARM::VisitLoadLocal(HLoadLocal* load) {
132 LocationSummary* locations = load->GetLocations();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000133 __ LoadFromOffset(kLoadWord, locations->Out().reg<Register>(),
134 FP, GetStackSlot(load->GetLocal()));
135}
136
137void LocationsBuilderARM::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000138 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000139 locations->SetInAt(1, Location(R0));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000140 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000141}
142
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000143void InstructionCodeGeneratorARM::VisitStoreLocal(HStoreLocal* store) {
144 LocationSummary* locations = store->GetLocations();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000145 __ StoreToOffset(kStoreWord, locations->InAt(1).reg<Register>(),
146 FP, GetStackSlot(store->GetLocal()));
147}
148
149void LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000150 constant->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000151}
152
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000153void InstructionCodeGeneratorARM::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000154 // Will be generated at use site.
155}
156
157void LocationsBuilderARM::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000158 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000159}
160
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000161void InstructionCodeGeneratorARM::VisitReturnVoid(HReturnVoid* ret) {
162 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000163}
164
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000165void LocationsBuilderARM::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000166 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000167 locations->SetInAt(0, Location(R0));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000168 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000169}
170
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000171void InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) {
172 DCHECK_EQ(ret->GetLocations()->InAt(0).reg<Register>(), R0);
173 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000174}
175
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000176} // namespace arm
177} // namespace art