OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/arm/macro-assembler-arm.h" | 7 #include "src/arm/macro-assembler-arm.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); | 129 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); |
130 } | 130 } |
131 }; | 131 }; |
132 | 132 |
133 | 133 |
134 // Assembles an instruction after register allocation, producing machine code. | 134 // Assembles an instruction after register allocation, producing machine code. |
135 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 135 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
136 ArmOperandConverter i(this, instr); | 136 ArmOperandConverter i(this, instr); |
137 | 137 |
138 switch (ArchOpcodeField::decode(instr->opcode())) { | 138 switch (ArchOpcodeField::decode(instr->opcode())) { |
| 139 case kArchCallAddress: { |
| 140 DirectCEntryStub stub(isolate()); |
| 141 stub.GenerateCall(masm(), i.InputRegister(0)); |
| 142 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 143 break; |
| 144 } |
| 145 case kArchCallCodeObject: { |
| 146 if (instr->InputAt(0)->IsImmediate()) { |
| 147 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
| 148 RelocInfo::CODE_TARGET); |
| 149 } else { |
| 150 __ add(ip, i.InputRegister(0), |
| 151 Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 152 __ Call(ip); |
| 153 } |
| 154 AddSafepointAndDeopt(instr); |
| 155 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 156 break; |
| 157 } |
| 158 case kArchCallJSFunction: { |
| 159 // TODO(jarin) The load of the context should be separated from the call. |
| 160 Register func = i.InputRegister(0); |
| 161 __ ldr(cp, FieldMemOperand(func, JSFunction::kContextOffset)); |
| 162 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
| 163 __ Call(ip); |
| 164 AddSafepointAndDeopt(instr); |
| 165 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 166 break; |
| 167 } |
| 168 case kArchDeoptimize: { |
| 169 int deoptimization_id = MiscField::decode(instr->opcode()); |
| 170 BuildTranslation(instr, 0, deoptimization_id); |
| 171 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( |
| 172 isolate(), deoptimization_id, Deoptimizer::LAZY); |
| 173 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); |
| 174 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 175 break; |
| 176 } |
| 177 case kArchDrop: { |
| 178 int words = MiscField::decode(instr->opcode()); |
| 179 __ Drop(words); |
| 180 DCHECK_LT(0, words); |
| 181 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 182 break; |
| 183 } |
139 case kArchJmp: | 184 case kArchJmp: |
140 __ b(code_->GetLabel(i.InputBlock(0))); | 185 __ b(code_->GetLabel(i.InputBlock(0))); |
141 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 186 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
142 break; | 187 break; |
143 case kArchNop: | 188 case kArchNop: |
144 // don't emit code for nops. | 189 // don't emit code for nops. |
145 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 190 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
146 break; | 191 break; |
147 case kArchRet: | 192 case kArchRet: |
148 AssembleReturn(); | 193 AssembleReturn(); |
149 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 194 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
150 break; | 195 break; |
151 case kArchDeoptimize: { | |
152 int deoptimization_id = MiscField::decode(instr->opcode()); | |
153 BuildTranslation(instr, 0, deoptimization_id); | |
154 | |
155 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | |
156 isolate(), deoptimization_id, Deoptimizer::LAZY); | |
157 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | |
158 DCHECK_EQ(LeaveCC, i.OutputSBit()); | |
159 break; | |
160 } | |
161 case kArchTruncateDoubleToI: | 196 case kArchTruncateDoubleToI: |
162 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); | 197 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); |
163 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 198 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
164 break; | 199 break; |
165 case kArmAdd: | 200 case kArmAdd: |
166 __ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1), | 201 __ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1), |
167 i.OutputSBit()); | 202 i.OutputSBit()); |
168 break; | 203 break; |
169 case kArmAnd: | 204 case kArmAnd: |
170 __ and_(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1), | 205 __ and_(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1), |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 264 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
230 break; | 265 break; |
231 } | 266 } |
232 case kArmUbfx: { | 267 case kArmUbfx: { |
233 CpuFeatureScope scope(masm(), ARMv7); | 268 CpuFeatureScope scope(masm(), ARMv7); |
234 __ ubfx(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1), | 269 __ ubfx(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1), |
235 i.InputInt8(2)); | 270 i.InputInt8(2)); |
236 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 271 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
237 break; | 272 break; |
238 } | 273 } |
239 case kArmCallCodeObject: { | |
240 if (instr->InputAt(0)->IsImmediate()) { | |
241 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | |
242 __ Call(code, RelocInfo::CODE_TARGET); | |
243 } else { | |
244 Register reg = i.InputRegister(0); | |
245 int entry = Code::kHeaderSize - kHeapObjectTag; | |
246 __ ldr(reg, MemOperand(reg, entry)); | |
247 __ Call(reg); | |
248 } | |
249 | |
250 AddSafepointAndDeopt(instr); | |
251 | |
252 DCHECK_EQ(LeaveCC, i.OutputSBit()); | |
253 break; | |
254 } | |
255 case kArmCallJSFunction: { | |
256 Register func = i.InputRegister(0); | |
257 | |
258 // TODO(jarin) The load of the context should be separated from the call. | |
259 __ ldr(cp, FieldMemOperand(func, JSFunction::kContextOffset)); | |
260 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | |
261 __ Call(ip); | |
262 | |
263 AddSafepointAndDeopt(instr); | |
264 | |
265 DCHECK_EQ(LeaveCC, i.OutputSBit()); | |
266 break; | |
267 } | |
268 case kArmCallAddress: { | |
269 DirectCEntryStub stub(isolate()); | |
270 stub.GenerateCall(masm(), i.InputRegister(0)); | |
271 DCHECK_EQ(LeaveCC, i.OutputSBit()); | |
272 break; | |
273 } | |
274 case kArmPush: | |
275 __ Push(i.InputRegister(0)); | |
276 DCHECK_EQ(LeaveCC, i.OutputSBit()); | |
277 break; | |
278 case kArmDrop: { | |
279 int words = MiscField::decode(instr->opcode()); | |
280 __ Drop(words); | |
281 DCHECK_EQ(LeaveCC, i.OutputSBit()); | |
282 break; | |
283 } | |
284 case kArmCmp: | 274 case kArmCmp: |
285 __ cmp(i.InputRegister(0), i.InputOperand2(1)); | 275 __ cmp(i.InputRegister(0), i.InputOperand2(1)); |
286 DCHECK_EQ(SetCC, i.OutputSBit()); | 276 DCHECK_EQ(SetCC, i.OutputSBit()); |
287 break; | 277 break; |
288 case kArmCmn: | 278 case kArmCmn: |
289 __ cmn(i.InputRegister(0), i.InputOperand2(1)); | 279 __ cmn(i.InputRegister(0), i.InputOperand2(1)); |
290 DCHECK_EQ(SetCC, i.OutputSBit()); | 280 DCHECK_EQ(SetCC, i.OutputSBit()); |
291 break; | 281 break; |
292 case kArmTst: | 282 case kArmTst: |
293 __ tst(i.InputRegister(0), i.InputOperand2(1)); | 283 __ tst(i.InputRegister(0), i.InputOperand2(1)); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 __ vldr(i.OutputDoubleRegister(), i.InputOffset()); | 425 __ vldr(i.OutputDoubleRegister(), i.InputOffset()); |
436 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 426 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
437 break; | 427 break; |
438 case kArmVstr64: { | 428 case kArmVstr64: { |
439 int index = 0; | 429 int index = 0; |
440 MemOperand operand = i.InputOffset(&index); | 430 MemOperand operand = i.InputOffset(&index); |
441 __ vstr(i.InputDoubleRegister(index), operand); | 431 __ vstr(i.InputDoubleRegister(index), operand); |
442 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 432 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
443 break; | 433 break; |
444 } | 434 } |
| 435 case kArmPush: |
| 436 __ Push(i.InputRegister(0)); |
| 437 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 438 break; |
445 case kArmStoreWriteBarrier: { | 439 case kArmStoreWriteBarrier: { |
446 Register object = i.InputRegister(0); | 440 Register object = i.InputRegister(0); |
447 Register index = i.InputRegister(1); | 441 Register index = i.InputRegister(1); |
448 Register value = i.InputRegister(2); | 442 Register value = i.InputRegister(2); |
449 __ add(index, object, index); | 443 __ add(index, object, index); |
450 __ str(value, MemOperand(index)); | 444 __ str(value, MemOperand(index)); |
451 SaveFPRegsMode mode = | 445 SaveFPRegsMode mode = |
452 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; | 446 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; |
453 LinkRegisterStatus lr_status = kLRHasNotBeenSaved; | 447 LinkRegisterStatus lr_status = kLRHasNotBeenSaved; |
454 __ RecordWrite(object, index, value, lr_status, mode); | 448 __ RecordWrite(object, index, value, lr_status, mode); |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 | 841 |
848 void CodeGenerator::AddNopForSmiCodeInlining() { | 842 void CodeGenerator::AddNopForSmiCodeInlining() { |
849 // On 32-bit ARM we do not insert nops for inlined Smi code. | 843 // On 32-bit ARM we do not insert nops for inlined Smi code. |
850 UNREACHABLE(); | 844 UNREACHABLE(); |
851 } | 845 } |
852 | 846 |
853 #undef __ | 847 #undef __ |
854 } | 848 } |
855 } | 849 } |
856 } // namespace v8::internal::compiler | 850 } // namespace v8::internal::compiler |
OLD | NEW |