| 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 |