OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 5 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ |
6 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 6 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ |
7 | 7 |
8 #include "src/assembler.h" | 8 #include "src/assembler.h" |
9 #include "src/frames.h" | 9 #include "src/frames.h" |
10 #include "src/globals.h" | 10 #include "src/globals.h" |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 SmiCheck smi_check = INLINE_SMI_CHECK, | 307 SmiCheck smi_check = INLINE_SMI_CHECK, |
308 PointersToHereCheck pointers_to_here_check_for_value = | 308 PointersToHereCheck pointers_to_here_check_for_value = |
309 kPointersToHereMaybeInteresting); | 309 kPointersToHereMaybeInteresting); |
310 | 310 |
311 // Push a handle. | 311 // Push a handle. |
312 void Push(Handle<Object> handle); | 312 void Push(Handle<Object> handle); |
313 void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); } | 313 void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); } |
314 | 314 |
315 // Push two registers. Pushes leftmost register first (to highest address). | 315 // Push two registers. Pushes leftmost register first (to highest address). |
316 void Push(Register src1, Register src2, Condition cond = al) { | 316 void Push(Register src1, Register src2, Condition cond = al) { |
317 ASSERT(!src1.is(src2)); | 317 DCHECK(!src1.is(src2)); |
318 if (src1.code() > src2.code()) { | 318 if (src1.code() > src2.code()) { |
319 stm(db_w, sp, src1.bit() | src2.bit(), cond); | 319 stm(db_w, sp, src1.bit() | src2.bit(), cond); |
320 } else { | 320 } else { |
321 str(src1, MemOperand(sp, 4, NegPreIndex), cond); | 321 str(src1, MemOperand(sp, 4, NegPreIndex), cond); |
322 str(src2, MemOperand(sp, 4, NegPreIndex), cond); | 322 str(src2, MemOperand(sp, 4, NegPreIndex), cond); |
323 } | 323 } |
324 } | 324 } |
325 | 325 |
326 // Push three registers. Pushes leftmost register first (to highest address). | 326 // Push three registers. Pushes leftmost register first (to highest address). |
327 void Push(Register src1, Register src2, Register src3, Condition cond = al) { | 327 void Push(Register src1, Register src2, Register src3, Condition cond = al) { |
328 ASSERT(!src1.is(src2)); | 328 DCHECK(!src1.is(src2)); |
329 ASSERT(!src2.is(src3)); | 329 DCHECK(!src2.is(src3)); |
330 ASSERT(!src1.is(src3)); | 330 DCHECK(!src1.is(src3)); |
331 if (src1.code() > src2.code()) { | 331 if (src1.code() > src2.code()) { |
332 if (src2.code() > src3.code()) { | 332 if (src2.code() > src3.code()) { |
333 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); | 333 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); |
334 } else { | 334 } else { |
335 stm(db_w, sp, src1.bit() | src2.bit(), cond); | 335 stm(db_w, sp, src1.bit() | src2.bit(), cond); |
336 str(src3, MemOperand(sp, 4, NegPreIndex), cond); | 336 str(src3, MemOperand(sp, 4, NegPreIndex), cond); |
337 } | 337 } |
338 } else { | 338 } else { |
339 str(src1, MemOperand(sp, 4, NegPreIndex), cond); | 339 str(src1, MemOperand(sp, 4, NegPreIndex), cond); |
340 Push(src2, src3, cond); | 340 Push(src2, src3, cond); |
341 } | 341 } |
342 } | 342 } |
343 | 343 |
344 // Push four registers. Pushes leftmost register first (to highest address). | 344 // Push four registers. Pushes leftmost register first (to highest address). |
345 void Push(Register src1, | 345 void Push(Register src1, |
346 Register src2, | 346 Register src2, |
347 Register src3, | 347 Register src3, |
348 Register src4, | 348 Register src4, |
349 Condition cond = al) { | 349 Condition cond = al) { |
350 ASSERT(!src1.is(src2)); | 350 DCHECK(!src1.is(src2)); |
351 ASSERT(!src2.is(src3)); | 351 DCHECK(!src2.is(src3)); |
352 ASSERT(!src1.is(src3)); | 352 DCHECK(!src1.is(src3)); |
353 ASSERT(!src1.is(src4)); | 353 DCHECK(!src1.is(src4)); |
354 ASSERT(!src2.is(src4)); | 354 DCHECK(!src2.is(src4)); |
355 ASSERT(!src3.is(src4)); | 355 DCHECK(!src3.is(src4)); |
356 if (src1.code() > src2.code()) { | 356 if (src1.code() > src2.code()) { |
357 if (src2.code() > src3.code()) { | 357 if (src2.code() > src3.code()) { |
358 if (src3.code() > src4.code()) { | 358 if (src3.code() > src4.code()) { |
359 stm(db_w, | 359 stm(db_w, |
360 sp, | 360 sp, |
361 src1.bit() | src2.bit() | src3.bit() | src4.bit(), | 361 src1.bit() | src2.bit() | src3.bit() | src4.bit(), |
362 cond); | 362 cond); |
363 } else { | 363 } else { |
364 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); | 364 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); |
365 str(src4, MemOperand(sp, 4, NegPreIndex), cond); | 365 str(src4, MemOperand(sp, 4, NegPreIndex), cond); |
366 } | 366 } |
367 } else { | 367 } else { |
368 stm(db_w, sp, src1.bit() | src2.bit(), cond); | 368 stm(db_w, sp, src1.bit() | src2.bit(), cond); |
369 Push(src3, src4, cond); | 369 Push(src3, src4, cond); |
370 } | 370 } |
371 } else { | 371 } else { |
372 str(src1, MemOperand(sp, 4, NegPreIndex), cond); | 372 str(src1, MemOperand(sp, 4, NegPreIndex), cond); |
373 Push(src2, src3, src4, cond); | 373 Push(src2, src3, src4, cond); |
374 } | 374 } |
375 } | 375 } |
376 | 376 |
377 // Pop two registers. Pops rightmost register first (from lower address). | 377 // Pop two registers. Pops rightmost register first (from lower address). |
378 void Pop(Register src1, Register src2, Condition cond = al) { | 378 void Pop(Register src1, Register src2, Condition cond = al) { |
379 ASSERT(!src1.is(src2)); | 379 DCHECK(!src1.is(src2)); |
380 if (src1.code() > src2.code()) { | 380 if (src1.code() > src2.code()) { |
381 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); | 381 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); |
382 } else { | 382 } else { |
383 ldr(src2, MemOperand(sp, 4, PostIndex), cond); | 383 ldr(src2, MemOperand(sp, 4, PostIndex), cond); |
384 ldr(src1, MemOperand(sp, 4, PostIndex), cond); | 384 ldr(src1, MemOperand(sp, 4, PostIndex), cond); |
385 } | 385 } |
386 } | 386 } |
387 | 387 |
388 // Pop three registers. Pops rightmost register first (from lower address). | 388 // Pop three registers. Pops rightmost register first (from lower address). |
389 void Pop(Register src1, Register src2, Register src3, Condition cond = al) { | 389 void Pop(Register src1, Register src2, Register src3, Condition cond = al) { |
390 ASSERT(!src1.is(src2)); | 390 DCHECK(!src1.is(src2)); |
391 ASSERT(!src2.is(src3)); | 391 DCHECK(!src2.is(src3)); |
392 ASSERT(!src1.is(src3)); | 392 DCHECK(!src1.is(src3)); |
393 if (src1.code() > src2.code()) { | 393 if (src1.code() > src2.code()) { |
394 if (src2.code() > src3.code()) { | 394 if (src2.code() > src3.code()) { |
395 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); | 395 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); |
396 } else { | 396 } else { |
397 ldr(src3, MemOperand(sp, 4, PostIndex), cond); | 397 ldr(src3, MemOperand(sp, 4, PostIndex), cond); |
398 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); | 398 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); |
399 } | 399 } |
400 } else { | 400 } else { |
401 Pop(src2, src3, cond); | 401 Pop(src2, src3, cond); |
402 ldr(src1, MemOperand(sp, 4, PostIndex), cond); | 402 ldr(src1, MemOperand(sp, 4, PostIndex), cond); |
403 } | 403 } |
404 } | 404 } |
405 | 405 |
406 // Pop four registers. Pops rightmost register first (from lower address). | 406 // Pop four registers. Pops rightmost register first (from lower address). |
407 void Pop(Register src1, | 407 void Pop(Register src1, |
408 Register src2, | 408 Register src2, |
409 Register src3, | 409 Register src3, |
410 Register src4, | 410 Register src4, |
411 Condition cond = al) { | 411 Condition cond = al) { |
412 ASSERT(!src1.is(src2)); | 412 DCHECK(!src1.is(src2)); |
413 ASSERT(!src2.is(src3)); | 413 DCHECK(!src2.is(src3)); |
414 ASSERT(!src1.is(src3)); | 414 DCHECK(!src1.is(src3)); |
415 ASSERT(!src1.is(src4)); | 415 DCHECK(!src1.is(src4)); |
416 ASSERT(!src2.is(src4)); | 416 DCHECK(!src2.is(src4)); |
417 ASSERT(!src3.is(src4)); | 417 DCHECK(!src3.is(src4)); |
418 if (src1.code() > src2.code()) { | 418 if (src1.code() > src2.code()) { |
419 if (src2.code() > src3.code()) { | 419 if (src2.code() > src3.code()) { |
420 if (src3.code() > src4.code()) { | 420 if (src3.code() > src4.code()) { |
421 ldm(ia_w, | 421 ldm(ia_w, |
422 sp, | 422 sp, |
423 src1.bit() | src2.bit() | src3.bit() | src4.bit(), | 423 src1.bit() | src2.bit() | src3.bit() | src4.bit(), |
424 cond); | 424 cond); |
425 } else { | 425 } else { |
426 ldr(src4, MemOperand(sp, 4, PostIndex), cond); | 426 ldr(src4, MemOperand(sp, 4, PostIndex), cond); |
427 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); | 427 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
680 | 680 |
681 inline void MarkCode(NopMarkerTypes type) { | 681 inline void MarkCode(NopMarkerTypes type) { |
682 nop(type); | 682 nop(type); |
683 } | 683 } |
684 | 684 |
685 // Check if the given instruction is a 'type' marker. | 685 // Check if the given instruction is a 'type' marker. |
686 // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type)) | 686 // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type)) |
687 // These instructions are generated to mark special location in the code, | 687 // These instructions are generated to mark special location in the code, |
688 // like some special IC code. | 688 // like some special IC code. |
689 static inline bool IsMarkedCode(Instr instr, int type) { | 689 static inline bool IsMarkedCode(Instr instr, int type) { |
690 ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)); | 690 DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)); |
691 return IsNop(instr, type); | 691 return IsNop(instr, type); |
692 } | 692 } |
693 | 693 |
694 | 694 |
695 static inline int GetCodeMarker(Instr instr) { | 695 static inline int GetCodeMarker(Instr instr) { |
696 int dst_reg_offset = 12; | 696 int dst_reg_offset = 12; |
697 int dst_mask = 0xf << dst_reg_offset; | 697 int dst_mask = 0xf << dst_reg_offset; |
698 int src_mask = 0xf; | 698 int src_mask = 0xf; |
699 int dst_reg = (instr & dst_mask) >> dst_reg_offset; | 699 int dst_reg = (instr & dst_mask) >> dst_reg_offset; |
700 int src_reg = instr & src_mask; | 700 int src_reg = instr & src_mask; |
701 uint32_t non_register_mask = ~(dst_mask | src_mask); | 701 uint32_t non_register_mask = ~(dst_mask | src_mask); |
702 uint32_t mov_mask = al | 13 << 21; | 702 uint32_t mov_mask = al | 13 << 21; |
703 | 703 |
704 // Return <n> if we have a mov rn rn, else return -1. | 704 // Return <n> if we have a mov rn rn, else return -1. |
705 int type = ((instr & non_register_mask) == mov_mask) && | 705 int type = ((instr & non_register_mask) == mov_mask) && |
706 (dst_reg == src_reg) && | 706 (dst_reg == src_reg) && |
707 (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER) | 707 (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER) |
708 ? src_reg | 708 ? src_reg |
709 : -1; | 709 : -1; |
710 ASSERT((type == -1) || | 710 DCHECK((type == -1) || |
711 ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); | 711 ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); |
712 return type; | 712 return type; |
713 } | 713 } |
714 | 714 |
715 | 715 |
716 // --------------------------------------------------------------------------- | 716 // --------------------------------------------------------------------------- |
717 // Allocation support | 717 // Allocation support |
718 | 718 |
719 // Allocate an object in new space or old pointer space. The object_size is | 719 // Allocate an object in new space or old pointer space. The object_size is |
720 // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS | 720 // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
940 // Loads the type into the second argument register. | 940 // Loads the type into the second argument register. |
941 // Returns a condition that will be enabled if the object was a string | 941 // Returns a condition that will be enabled if the object was a string |
942 // and the passed-in condition passed. If the passed-in condition failed | 942 // and the passed-in condition passed. If the passed-in condition failed |
943 // then flags remain unchanged. | 943 // then flags remain unchanged. |
944 Condition IsObjectStringType(Register obj, | 944 Condition IsObjectStringType(Register obj, |
945 Register type, | 945 Register type, |
946 Condition cond = al) { | 946 Condition cond = al) { |
947 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset), cond); | 947 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset), cond); |
948 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset), cond); | 948 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset), cond); |
949 tst(type, Operand(kIsNotStringMask), cond); | 949 tst(type, Operand(kIsNotStringMask), cond); |
950 ASSERT_EQ(0, kStringTag); | 950 DCHECK_EQ(0, kStringTag); |
951 return eq; | 951 return eq; |
952 } | 952 } |
953 | 953 |
954 | 954 |
955 // Picks out an array index from the hash field. | 955 // Picks out an array index from the hash field. |
956 // Register use: | 956 // Register use: |
957 // hash - holds the index's hash. Clobbered. | 957 // hash - holds the index's hash. Clobbered. |
958 // index - holds the overwritten index on exit. | 958 // index - holds the overwritten index on exit. |
959 void IndexFromHash(Register hash, Register index); | 959 void IndexFromHash(Register hash, Register index); |
960 | 960 |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 const CallWrapper& call_wrapper = NullCallWrapper()); | 1137 const CallWrapper& call_wrapper = NullCallWrapper()); |
1138 | 1138 |
1139 // Store the code object for the given builtin in the target register and | 1139 // Store the code object for the given builtin in the target register and |
1140 // setup the function in r1. | 1140 // setup the function in r1. |
1141 void GetBuiltinEntry(Register target, Builtins::JavaScript id); | 1141 void GetBuiltinEntry(Register target, Builtins::JavaScript id); |
1142 | 1142 |
1143 // Store the function for the given builtin in the target register. | 1143 // Store the function for the given builtin in the target register. |
1144 void GetBuiltinFunction(Register target, Builtins::JavaScript id); | 1144 void GetBuiltinFunction(Register target, Builtins::JavaScript id); |
1145 | 1145 |
1146 Handle<Object> CodeObject() { | 1146 Handle<Object> CodeObject() { |
1147 ASSERT(!code_object_.is_null()); | 1147 DCHECK(!code_object_.is_null()); |
1148 return code_object_; | 1148 return code_object_; |
1149 } | 1149 } |
1150 | 1150 |
1151 | 1151 |
1152 // Emit code for a truncating division by a constant. The dividend register is | 1152 // Emit code for a truncating division by a constant. The dividend register is |
1153 // unchanged and ip gets clobbered. Dividend and result must be different. | 1153 // unchanged and ip gets clobbered. Dividend and result must be different. |
1154 void TruncatingDiv(Register result, Register dividend, int32_t divisor); | 1154 void TruncatingDiv(Register result, Register dividend, int32_t divisor); |
1155 | 1155 |
1156 // --------------------------------------------------------------------------- | 1156 // --------------------------------------------------------------------------- |
1157 // StatsCounter support | 1157 // StatsCounter support |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1540 | 1540 |
1541 class FrameAndConstantPoolScope { | 1541 class FrameAndConstantPoolScope { |
1542 public: | 1542 public: |
1543 FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type) | 1543 FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type) |
1544 : masm_(masm), | 1544 : masm_(masm), |
1545 type_(type), | 1545 type_(type), |
1546 old_has_frame_(masm->has_frame()), | 1546 old_has_frame_(masm->has_frame()), |
1547 old_constant_pool_available_(masm->is_constant_pool_available()) { | 1547 old_constant_pool_available_(masm->is_constant_pool_available()) { |
1548 // We only want to enable constant pool access for non-manual frame scopes | 1548 // We only want to enable constant pool access for non-manual frame scopes |
1549 // to ensure the constant pool pointer is valid throughout the scope. | 1549 // to ensure the constant pool pointer is valid throughout the scope. |
1550 ASSERT(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE); | 1550 DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE); |
1551 masm->set_has_frame(true); | 1551 masm->set_has_frame(true); |
1552 masm->set_constant_pool_available(true); | 1552 masm->set_constant_pool_available(true); |
1553 masm->EnterFrame(type, !old_constant_pool_available_); | 1553 masm->EnterFrame(type, !old_constant_pool_available_); |
1554 } | 1554 } |
1555 | 1555 |
1556 ~FrameAndConstantPoolScope() { | 1556 ~FrameAndConstantPoolScope() { |
1557 masm_->LeaveFrame(type_); | 1557 masm_->LeaveFrame(type_); |
1558 masm_->set_has_frame(old_has_frame_); | 1558 masm_->set_has_frame(old_has_frame_); |
1559 masm_->set_constant_pool_available(old_constant_pool_available_); | 1559 masm_->set_constant_pool_available(old_constant_pool_available_); |
1560 } | 1560 } |
1561 | 1561 |
1562 // Normally we generate the leave-frame code when this object goes | 1562 // Normally we generate the leave-frame code when this object goes |
1563 // out of scope. Sometimes we may need to generate the code somewhere else | 1563 // out of scope. Sometimes we may need to generate the code somewhere else |
1564 // in addition. Calling this will achieve that, but the object stays in | 1564 // in addition. Calling this will achieve that, but the object stays in |
1565 // scope, the MacroAssembler is still marked as being in a frame scope, and | 1565 // scope, the MacroAssembler is still marked as being in a frame scope, and |
1566 // the code will be generated again when it goes out of scope. | 1566 // the code will be generated again when it goes out of scope. |
1567 void GenerateLeaveFrame() { | 1567 void GenerateLeaveFrame() { |
1568 ASSERT(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE); | 1568 DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE); |
1569 masm_->LeaveFrame(type_); | 1569 masm_->LeaveFrame(type_); |
1570 } | 1570 } |
1571 | 1571 |
1572 private: | 1572 private: |
1573 MacroAssembler* masm_; | 1573 MacroAssembler* masm_; |
1574 StackFrame::Type type_; | 1574 StackFrame::Type type_; |
1575 bool old_has_frame_; | 1575 bool old_has_frame_; |
1576 bool old_constant_pool_available_; | 1576 bool old_constant_pool_available_; |
1577 | 1577 |
1578 DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope); | 1578 DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1622 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) | 1622 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) |
1623 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> | 1623 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> |
1624 #else | 1624 #else |
1625 #define ACCESS_MASM(masm) masm-> | 1625 #define ACCESS_MASM(masm) masm-> |
1626 #endif | 1626 #endif |
1627 | 1627 |
1628 | 1628 |
1629 } } // namespace v8::internal | 1629 } } // namespace v8::internal |
1630 | 1630 |
1631 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 1631 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ |
OLD | NEW |