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