code_generator_arm.cc revision 787c3076635cf117eb646c5a89a9014b2072fb44
1/*
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
21#define __ reinterpret_cast<ArmAssembler*>(GetAssembler())->
22
23namespace art {
24namespace arm {
25
26void CodeGeneratorARM::GenerateFrameEntry() {
27  __ PushList((1 << FP) | (1 << LR));
28  __ mov(FP, ShifterOperand(SP));
29  if (GetFrameSize() != 0) {
30    __ AddConstant(SP, -GetFrameSize());
31  }
32}
33
34void CodeGeneratorARM::GenerateFrameExit() {
35  __ mov(SP, ShifterOperand(FP));
36  __ PopList((1 << FP) | (1 << PC));
37}
38
39void CodeGeneratorARM::Bind(Label* label) {
40  __ Bind(label);
41}
42
43void 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) {
50    __ LoadImmediate(location.reg<Register>(), constant->GetValue());
51  } else {
52    __ Pop(location.reg<Register>());
53  }
54}
55
56void LocationsBuilderARM::VisitGoto(HGoto* got) {
57  got->SetLocations(nullptr);
58}
59
60void InstructionCodeGeneratorARM::VisitGoto(HGoto* got) {
61  HBasicBlock* successor = got->GetSuccessor();
62  if (GetGraph()->GetExitBlock() == successor) {
63    codegen_->GenerateFrameExit();
64  } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
65    __ b(codegen_->GetLabelOf(successor));
66  }
67}
68
69void LocationsBuilderARM::VisitExit(HExit* exit) {
70  exit->SetLocations(nullptr);
71}
72
73void InstructionCodeGeneratorARM::VisitExit(HExit* exit) {
74  if (kIsDebugBuild) {
75    __ Comment("Unreachable");
76    __ bkpt(0);
77  }
78}
79
80void LocationsBuilderARM::VisitIf(HIf* if_instr) {
81  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
82  locations->SetInAt(0, Location(R0));
83  if_instr->SetLocations(locations);
84}
85
86void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) {
87  // TODO: Generate the input as a condition, instead of materializing in a register.
88  __ 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()));
92  }
93}
94
95void LocationsBuilderARM::VisitEqual(HEqual* equal) {
96  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal);
97  locations->SetInAt(0, Location(R0));
98  locations->SetInAt(1, Location(R1));
99  locations->SetOut(Location(R0));
100  equal->SetLocations(locations);
101}
102
103void InstructionCodeGeneratorARM::VisitEqual(HEqual* equal) {
104  LocationSummary* locations = equal->GetLocations();
105  __ 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) {
112  local->SetLocations(nullptr);
113}
114
115void InstructionCodeGeneratorARM::VisitLocal(HLocal* local) {
116  DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
117  codegen_->SetFrameSize(codegen_->GetFrameSize() + kWordSize);
118}
119
120void LocationsBuilderARM::VisitLoadLocal(HLoadLocal* load) {
121  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(load);
122  locations->SetOut(Location(R0));
123  load->SetLocations(locations);
124}
125
126static int32_t GetStackSlot(HLocal* local) {
127  // We are currently using FP to access locals, so the offset must be negative.
128  return (local->GetRegNumber() + 1) * -kWordSize;
129}
130
131void InstructionCodeGeneratorARM::VisitLoadLocal(HLoadLocal* load) {
132  LocationSummary* locations = load->GetLocations();
133  __ LoadFromOffset(kLoadWord, locations->Out().reg<Register>(),
134                    FP, GetStackSlot(load->GetLocal()));
135}
136
137void LocationsBuilderARM::VisitStoreLocal(HStoreLocal* store) {
138  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
139  locations->SetInAt(1, Location(R0));
140  store->SetLocations(locations);
141}
142
143void InstructionCodeGeneratorARM::VisitStoreLocal(HStoreLocal* store) {
144  LocationSummary* locations = store->GetLocations();
145  __ StoreToOffset(kStoreWord, locations->InAt(1).reg<Register>(),
146                   FP, GetStackSlot(store->GetLocal()));
147}
148
149void LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) {
150  constant->SetLocations(nullptr);
151}
152
153void InstructionCodeGeneratorARM::VisitIntConstant(HIntConstant* constant) {
154  // Will be generated at use site.
155}
156
157void LocationsBuilderARM::VisitReturnVoid(HReturnVoid* ret) {
158  ret->SetLocations(nullptr);
159}
160
161void InstructionCodeGeneratorARM::VisitReturnVoid(HReturnVoid* ret) {
162  codegen_->GenerateFrameExit();
163}
164
165void LocationsBuilderARM::VisitReturn(HReturn* ret) {
166  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
167  locations->SetInAt(0, Location(R0));
168  ret->SetLocations(locations);
169}
170
171void InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) {
172  DCHECK_EQ(ret->GetLocations()->InAt(0).reg<Register>(), R0);
173  codegen_->GenerateFrameExit();
174}
175
176}  // namespace arm
177}  // namespace art
178