blob: c4bda5645e9ddee92d8e50333ec59dd1c59cb4b3 [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_x86.h"
18#include "utils/assembler.h"
19#include "utils/x86/assembler_x86.h"
20
Nicolas Geoffray787c3072014-03-17 10:20:19 +000021#define __ reinterpret_cast<X86Assembler*>(GetAssembler())->
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000022
23namespace art {
24namespace x86 {
25
26void CodeGeneratorX86::GenerateFrameEntry() {
27 __ pushl(EBP);
28 __ movl(EBP, ESP);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000029
Nicolas Geoffray787c3072014-03-17 10:20:19 +000030 if (GetFrameSize() != 0) {
31 __ subl(ESP, Immediate(GetFrameSize()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000032 }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000033}
34
35void CodeGeneratorX86::GenerateFrameExit() {
36 __ movl(ESP, EBP);
37 __ popl(EBP);
38}
39
40void CodeGeneratorX86::Bind(Label* label) {
41 __ Bind(label);
42}
43
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000044void CodeGeneratorX86::Push(HInstruction* instruction, Location location) {
45 __ pushl(location.reg<Register>());
46}
47
48void CodeGeneratorX86::Move(HInstruction* instruction, Location location) {
49 HIntConstant* constant = instruction->AsIntConstant();
50 if (constant != nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000051 __ movl(location.reg<Register>(), Immediate(constant->GetValue()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000052 } else {
53 __ popl(location.reg<Register>());
54 }
55}
56
57void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000058 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000059}
60
Nicolas Geoffray787c3072014-03-17 10:20:19 +000061void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000062 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +000063 if (GetGraph()->GetExitBlock() == successor) {
64 codegen_->GenerateFrameExit();
65 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
66 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000067 }
68}
69
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000070void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000071 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000072}
73
Nicolas Geoffray787c3072014-03-17 10:20:19 +000074void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000075 if (kIsDebugBuild) {
76 __ Comment("Unreachable");
77 __ int3();
78 }
79}
80
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000081void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000082 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000083 locations->SetInAt(0, Location(EAX));
Nicolas Geoffray787c3072014-03-17 10:20:19 +000084 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000085}
86
Nicolas Geoffray787c3072014-03-17 10:20:19 +000087void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000088 // TODO: Generate the input as a condition, instead of materializing in a register.
Nicolas Geoffray787c3072014-03-17 10:20:19 +000089 __ cmpl(if_instr->GetLocations()->InAt(0).reg<Register>(), Immediate(0));
90 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
91 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) {
92 __ jmp(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000093 }
94}
95
96void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000097 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000098}
99
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000100void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
101 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
102 codegen_->SetFrameSize(codegen_->GetFrameSize() + kWordSize);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000103}
104
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000105void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000106 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(local);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000107 locations->SetOut(Location(EAX));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000108 local->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000109}
110
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000111static int32_t GetStackSlot(HLocal* local) {
112 // We are currently using EBP to access locals, so the offset must be negative.
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000113 return (local->GetRegNumber() + 1) * -kWordSize;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000114}
115
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000116void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
117 __ movl(load->GetLocations()->Out().reg<Register>(),
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000118 Address(EBP, GetStackSlot(load->GetLocal())));
119}
120
121void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000122 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(local);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000123 locations->SetInAt(1, Location(EAX));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000124 local->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000125}
126
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000127void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000128 __ movl(Address(EBP, GetStackSlot(store->GetLocal())),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000129 store->GetLocations()->InAt(1).reg<Register>());
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000130}
131
132void LocationsBuilderX86::VisitEqual(HEqual* equal) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000133 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000134 locations->SetInAt(0, Location(EAX));
135 locations->SetInAt(1, Location(ECX));
136 locations->SetOut(Location(EAX));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000137 equal->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000138}
139
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000140void InstructionCodeGeneratorX86::VisitEqual(HEqual* equal) {
141 __ cmpl(equal->GetLocations()->InAt(0).reg<Register>(),
142 equal->GetLocations()->InAt(1).reg<Register>());
143 __ setb(kEqual, equal->GetLocations()->Out().reg<Register>());
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000144}
145
146void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000147 constant->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000148}
149
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000150void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000151 // Will be generated at use site.
152}
153
154void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000155 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000156}
157
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000158void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
159 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000160 __ ret();
161}
162
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000163void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000164 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000165 locations->SetInAt(0, Location(EAX));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000166 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000167}
168
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000169void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
170 DCHECK_EQ(ret->GetLocations()->InAt(0).reg<Register>(), EAX);
171 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000172 __ ret();
173}
174
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000175} // namespace x86
176} // namespace art