Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: src/mips/macro-assembler-mips.h

Issue 8139027: Version 3.6.5 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/mips/ic-mips.cc ('k') | src/mips/macro-assembler-mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 // Registers t8, t9, and at are reserved for use by the MacroAssembler. 43 // Registers t8, t9, and at are reserved for use by the MacroAssembler.
44 // 44 //
45 // The programmer should know that the MacroAssembler may clobber these three, 45 // The programmer should know that the MacroAssembler may clobber these three,
46 // but won't touch other registers except in special cases. 46 // but won't touch other registers except in special cases.
47 // 47 //
48 // Per the MIPS ABI, register t9 must be used for indirect function call 48 // Per the MIPS ABI, register t9 must be used for indirect function call
49 // via 'jalr t9' or 'jr t9' instructions. This is relied upon by gcc when 49 // via 'jalr t9' or 'jr t9' instructions. This is relied upon by gcc when
50 // trying to update gp register for position-independent-code. Whenever 50 // trying to update gp register for position-independent-code. Whenever
51 // MIPS generated code calls C code, it must be via t9 register. 51 // MIPS generated code calls C code, it must be via t9 register.
52 52
53 // Registers aliases 53
54 // Register aliases.
54 // cp is assumed to be a callee saved register. 55 // cp is assumed to be a callee saved register.
56 const Register lithiumScratchReg = s3; // Scratch register.
57 const Register lithiumScratchReg2 = s4; // Scratch register.
58 const Register condReg = s5; // Simulated (partial) condition code for mips.
55 const Register roots = s6; // Roots array pointer. 59 const Register roots = s6; // Roots array pointer.
56 const Register cp = s7; // JavaScript context pointer. 60 const Register cp = s7; // JavaScript context pointer.
57 const Register fp = s8_fp; // Alias for fp. 61 const Register fp = s8_fp; // Alias for fp.
58 // Registers used for condition evaluation. 62 const DoubleRegister lithiumScratchDouble = f30; // Double scratch register.
59 const Register condReg1 = s4;
60 const Register condReg2 = s5;
61
62 63
63 // Flags used for the AllocateInNewSpace functions. 64 // Flags used for the AllocateInNewSpace functions.
64 enum AllocationFlags { 65 enum AllocationFlags {
65 // No special flags. 66 // No special flags.
66 NO_ALLOCATION_FLAGS = 0, 67 NO_ALLOCATION_FLAGS = 0,
67 // Return the pointer to the allocated already tagged as a heap object. 68 // Return the pointer to the allocated already tagged as a heap object.
68 TAG_OBJECT = 1 << 0, 69 TAG_OBJECT = 1 << 0,
69 // The content of the result register already contains the allocation top in 70 // The content of the result register already contains the allocation top in
70 // new space. 71 // new space.
71 RESULT_CONTAINS_TOP = 1 << 1, 72 RESULT_CONTAINS_TOP = 1 << 1,
(...skipping 11 matching lines...) Expand all
83 // Don't load NaNs or infinities, branch to the non number case instead. 84 // Don't load NaNs or infinities, branch to the non number case instead.
84 AVOID_NANS_AND_INFINITIES = 1 << 1 85 AVOID_NANS_AND_INFINITIES = 1 << 1
85 }; 86 };
86 87
87 // Allow programmer to use Branch Delay Slot of Branches, Jumps, Calls. 88 // Allow programmer to use Branch Delay Slot of Branches, Jumps, Calls.
88 enum BranchDelaySlot { 89 enum BranchDelaySlot {
89 USE_DELAY_SLOT, 90 USE_DELAY_SLOT,
90 PROTECT 91 PROTECT
91 }; 92 };
92 93
94
95 // -----------------------------------------------------------------------------
96 // Static helper functions.
97
98 static MemOperand ContextOperand(Register context, int index) {
99 return MemOperand(context, Context::SlotOffset(index));
100 }
101
102
103 static inline MemOperand GlobalObjectOperand() {
104 return ContextOperand(cp, Context::GLOBAL_INDEX);
105 }
106
107
108 // Generate a MemOperand for loading a field from an object.
109 static inline MemOperand FieldMemOperand(Register object, int offset) {
110 return MemOperand(object, offset - kHeapObjectTag);
111 }
112
113
114 // Generate a MemOperand for storing arguments 5..N on the stack
115 // when calling CallCFunction().
116 static inline MemOperand CFunctionArgumentOperand(int index) {
117 ASSERT(index > kCArgSlotCount);
118 // Argument 5 takes the slot just past the four Arg-slots.
119 int offset = (index - 5) * kPointerSize + kCArgsSlotsSize;
120 return MemOperand(sp, offset);
121 }
122
123
93 // MacroAssembler implements a collection of frequently used macros. 124 // MacroAssembler implements a collection of frequently used macros.
94 class MacroAssembler: public Assembler { 125 class MacroAssembler: public Assembler {
95 public: 126 public:
96 // The isolate parameter can be NULL if the macro assembler should 127 // The isolate parameter can be NULL if the macro assembler should
97 // not use isolate-dependent functionality. In this case, it's the 128 // not use isolate-dependent functionality. In this case, it's the
98 // responsibility of the caller to never invoke such function on the 129 // responsibility of the caller to never invoke such function on the
99 // macro assembler. 130 // macro assembler.
100 MacroAssembler(Isolate* isolate, void* buffer, int size); 131 MacroAssembler(Isolate* isolate, void* buffer, int size);
101 132
102 // Arguments macros. 133 // Arguments macros.
(...skipping 28 matching lines...) Expand all
131 162
132 163
133 // Jump, Call, and Ret pseudo instructions implementing inter-working. 164 // Jump, Call, and Ret pseudo instructions implementing inter-working.
134 #define COND_ARGS Condition cond = al, Register rs = zero_reg, \ 165 #define COND_ARGS Condition cond = al, Register rs = zero_reg, \
135 const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT 166 const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
136 167
137 void Jump(Register target, COND_ARGS); 168 void Jump(Register target, COND_ARGS);
138 void Jump(intptr_t target, RelocInfo::Mode rmode, COND_ARGS); 169 void Jump(intptr_t target, RelocInfo::Mode rmode, COND_ARGS);
139 void Jump(Address target, RelocInfo::Mode rmode, COND_ARGS); 170 void Jump(Address target, RelocInfo::Mode rmode, COND_ARGS);
140 void Jump(Handle<Code> code, RelocInfo::Mode rmode, COND_ARGS); 171 void Jump(Handle<Code> code, RelocInfo::Mode rmode, COND_ARGS);
141 int CallSize(Register target, COND_ARGS); 172 static int CallSize(Register target, COND_ARGS);
142 void Call(Register target, COND_ARGS); 173 void Call(Register target, COND_ARGS);
143 int CallSize(Address target, RelocInfo::Mode rmode, COND_ARGS); 174 static int CallSize(Address target, RelocInfo::Mode rmode, COND_ARGS);
144 void Call(Address target, RelocInfo::Mode rmode, COND_ARGS); 175 void Call(Address target, RelocInfo::Mode rmode, COND_ARGS);
145 int CallSize(Handle<Code> code, 176 static int CallSize(Handle<Code> code,
146 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 177 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
147 unsigned ast_id = kNoASTId, 178 unsigned ast_id = kNoASTId,
148 COND_ARGS); 179 COND_ARGS);
149 void Call(Handle<Code> code, 180 void Call(Handle<Code> code,
150 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 181 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
151 unsigned ast_id = kNoASTId, 182 unsigned ast_id = kNoASTId,
152 COND_ARGS); 183 COND_ARGS);
153 void Ret(COND_ARGS); 184 void Ret(COND_ARGS);
154 inline void Ret(BranchDelaySlot bd) { 185 inline void Ret(BranchDelaySlot bd, Condition cond = al,
155 Ret(al, zero_reg, Operand(zero_reg), bd); 186 Register rs = zero_reg, const Operand& rt = Operand(zero_reg)) {
187 Ret(cond, rs, rt, bd);
156 } 188 }
157 189
158 #undef COND_ARGS 190 #undef COND_ARGS
159 191
160 // Emit code to discard a non-negative number of pointer-sized elements 192 // Emit code to discard a non-negative number of pointer-sized elements
161 // from the stack, clobbering only the sp register. 193 // from the stack, clobbering only the sp register.
162 void Drop(int count, 194 void Drop(int count,
163 Condition cond = cc_always, 195 Condition cond = cc_always,
164 Register reg = no_reg, 196 Register reg = no_reg,
165 const Operand& op = Operand(no_reg)); 197 const Operand& op = Operand(no_reg));
(...skipping 24 matching lines...) Expand all
190 inline void Move(Register dst_low, Register dst_high, FPURegister src) { 222 inline void Move(Register dst_low, Register dst_high, FPURegister src) {
191 mfc1(dst_low, src); 223 mfc1(dst_low, src);
192 mfc1(dst_high, FPURegister::from_code(src.code() + 1)); 224 mfc1(dst_high, FPURegister::from_code(src.code() + 1));
193 } 225 }
194 226
195 inline void Move(FPURegister dst, Register src_low, Register src_high) { 227 inline void Move(FPURegister dst, Register src_low, Register src_high) {
196 mtc1(src_low, dst); 228 mtc1(src_low, dst);
197 mtc1(src_high, FPURegister::from_code(dst.code() + 1)); 229 mtc1(src_high, FPURegister::from_code(dst.code() + 1));
198 } 230 }
199 231
232 void Move(FPURegister dst, double imm);
233
200 // Jump unconditionally to given label. 234 // Jump unconditionally to given label.
201 // We NEED a nop in the branch delay slot, as it used by v8, for example in 235 // We NEED a nop in the branch delay slot, as it used by v8, for example in
202 // CodeGenerator::ProcessDeferred(). 236 // CodeGenerator::ProcessDeferred().
203 // Currently the branch delay slot is filled by the MacroAssembler. 237 // Currently the branch delay slot is filled by the MacroAssembler.
204 // Use rather b(Label) for code generation. 238 // Use rather b(Label) for code generation.
205 void jmp(Label* L) { 239 void jmp(Label* L) {
206 Branch(L); 240 Branch(L);
207 } 241 }
208 242
209 // Load an object from the root table. 243 // Load an object from the root table.
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 } 544 }
511 545
512 // Pop two registers. Pops rightmost register first (from lower address). 546 // Pop two registers. Pops rightmost register first (from lower address).
513 void Pop(Register src1, Register src2) { 547 void Pop(Register src1, Register src2) {
514 ASSERT(!src1.is(src2)); 548 ASSERT(!src1.is(src2));
515 lw(src2, MemOperand(sp, 0 * kPointerSize)); 549 lw(src2, MemOperand(sp, 0 * kPointerSize));
516 lw(src1, MemOperand(sp, 1 * kPointerSize)); 550 lw(src1, MemOperand(sp, 1 * kPointerSize));
517 Addu(sp, sp, 2 * kPointerSize); 551 Addu(sp, sp, 2 * kPointerSize);
518 } 552 }
519 553
554 // Pop three registers. Pops rightmost register first (from lower address).
555 void Pop(Register src1, Register src2, Register src3) {
556 lw(src3, MemOperand(sp, 0 * kPointerSize));
557 lw(src2, MemOperand(sp, 1 * kPointerSize));
558 lw(src1, MemOperand(sp, 2 * kPointerSize));
559 Addu(sp, sp, 3 * kPointerSize);
560 }
561
520 void Pop(uint32_t count = 1) { 562 void Pop(uint32_t count = 1) {
521 Addu(sp, sp, Operand(count * kPointerSize)); 563 Addu(sp, sp, Operand(count * kPointerSize));
522 } 564 }
523 565
524 // Push and pop the registers that can hold pointers, as defined by the 566 // Push and pop the registers that can hold pointers, as defined by the
525 // RegList constant kSafepointSavedRegisters. 567 // RegList constant kSafepointSavedRegisters.
526 void PushSafepointRegisters(); 568 void PushSafepointRegisters();
527 void PopSafepointRegisters(); 569 void PopSafepointRegisters();
528 void PushSafepointRegistersAndDoubles(); 570 void PushSafepointRegistersAndDoubles();
529 void PopSafepointRegistersAndDoubles(); 571 void PopSafepointRegistersAndDoubles();
530 // Store value in register src in the safepoint stack slot for 572 // Store value in register src in the safepoint stack slot for
531 // register dst. 573 // register dst.
532 void StoreToSafepointRegisterSlot(Register src, Register dst); 574 void StoreToSafepointRegisterSlot(Register src, Register dst);
533 void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst); 575 void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst);
534 // Load the value of the src register from its safepoint stack slot 576 // Load the value of the src register from its safepoint stack slot
535 // into register dst. 577 // into register dst.
536 void LoadFromSafepointRegisterSlot(Register dst, Register src); 578 void LoadFromSafepointRegisterSlot(Register dst, Register src);
537 579
580 // Flush the I-cache from asm code. You should use CPU::FlushICache from C.
581 // Does not handle errors.
582 void FlushICache(Register address, unsigned instructions);
583
538 // MIPS32 R2 instruction macro. 584 // MIPS32 R2 instruction macro.
539 void Ins(Register rt, Register rs, uint16_t pos, uint16_t size); 585 void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
540 void Ext(Register rt, Register rs, uint16_t pos, uint16_t size); 586 void Ext(Register rt, Register rs, uint16_t pos, uint16_t size);
541 587
588 // ---------------------------------------------------------------------------
589 // FPU macros. These do not handle special cases like NaN or +- inf.
590
542 // Convert unsigned word to double. 591 // Convert unsigned word to double.
543 void Cvt_d_uw(FPURegister fd, FPURegister fs, FPURegister scratch); 592 void Cvt_d_uw(FPURegister fd, FPURegister fs, FPURegister scratch);
544 void Cvt_d_uw(FPURegister fd, Register rs, FPURegister scratch); 593 void Cvt_d_uw(FPURegister fd, Register rs, FPURegister scratch);
545 594
546 // Convert double to unsigned word. 595 // Convert double to unsigned word.
547 void Trunc_uw_d(FPURegister fd, FPURegister fs, FPURegister scratch); 596 void Trunc_uw_d(FPURegister fd, FPURegister fs, FPURegister scratch);
548 void Trunc_uw_d(FPURegister fd, Register rs, FPURegister scratch); 597 void Trunc_uw_d(FPURegister fd, Register rs, FPURegister scratch);
549 598
599 // Wrapper function for the different cmp/branch types.
600 void BranchF(Label* target,
601 Label* nan,
602 Condition cc,
603 FPURegister cmp1,
604 FPURegister cmp2,
605 BranchDelaySlot bd = PROTECT);
606
607 // Alternate (inline) version for better readability with USE_DELAY_SLOT.
608 inline void BranchF(BranchDelaySlot bd,
609 Label* target,
610 Label* nan,
611 Condition cc,
612 FPURegister cmp1,
613 FPURegister cmp2) {
614 BranchF(target, nan, cc, cmp1, cmp2, bd);
615 };
616
550 // Convert the HeapNumber pointed to by source to a 32bits signed integer 617 // Convert the HeapNumber pointed to by source to a 32bits signed integer
551 // dest. If the HeapNumber does not fit into a 32bits signed integer branch 618 // dest. If the HeapNumber does not fit into a 32bits signed integer branch
552 // to not_int32 label. If FPU is available double_scratch is used but not 619 // to not_int32 label. If FPU is available double_scratch is used but not
553 // scratch2. 620 // scratch2.
554 void ConvertToInt32(Register source, 621 void ConvertToInt32(Register source,
555 Register dest, 622 Register dest,
556 Register scratch, 623 Register scratch,
557 Register scratch2, 624 Register scratch2,
558 FPURegister double_scratch, 625 FPURegister double_scratch,
559 Label *not_int32); 626 Label *not_int32);
560 627
628 // Truncates a double using a specific rounding mode.
629 // The except_flag will contain any exceptions caused by the instruction.
630 // If check_inexact is kDontCheckForInexactConversion, then the inexacat
631 // exception is masked.
632 void EmitFPUTruncate(FPURoundingMode rounding_mode,
633 FPURegister result,
634 DoubleRegister double_input,
635 Register scratch1,
636 Register except_flag,
637 CheckForInexactConversion check_inexact
638 = kDontCheckForInexactConversion);
639
561 // Helper for EmitECMATruncate. 640 // Helper for EmitECMATruncate.
562 // This will truncate a floating-point value outside of the singed 32bit 641 // This will truncate a floating-point value outside of the singed 32bit
563 // integer range to a 32bit signed integer. 642 // integer range to a 32bit signed integer.
564 // Expects the double value loaded in input_high and input_low. 643 // Expects the double value loaded in input_high and input_low.
565 // Exits with the answer in 'result'. 644 // Exits with the answer in 'result'.
566 // Note that this code does not work for values in the 32bit range! 645 // Note that this code does not work for values in the 32bit range!
567 void EmitOutOfInt32RangeTruncate(Register result, 646 void EmitOutOfInt32RangeTruncate(Register result,
568 Register input_high, 647 Register input_high,
569 Register input_low, 648 Register input_low,
570 Register scratch); 649 Register scratch);
571 650
572 // Performs a truncating conversion of a floating point number as used by 651 // Performs a truncating conversion of a floating point number as used by
573 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 652 // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
574 // Exits with 'result' holding the answer and all other registers clobbered. 653 // Exits with 'result' holding the answer and all other registers clobbered.
575 void EmitECMATruncate(Register result, 654 void EmitECMATruncate(Register result,
576 FPURegister double_input, 655 FPURegister double_input,
577 FPURegister single_scratch, 656 FPURegister single_scratch,
578 Register scratch, 657 Register scratch,
579 Register scratch2, 658 Register scratch2,
580 Register scratch3); 659 Register scratch3);
581 660
582 // -------------------------------------------------------------------------
583 // Activation frames.
584
585 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
586 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
587
588 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
589 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
590
591 // Enter exit frame. 661 // Enter exit frame.
592 // argc - argument count to be dropped by LeaveExitFrame. 662 // argc - argument count to be dropped by LeaveExitFrame.
593 // save_doubles - saves FPU registers on stack, currently disabled. 663 // save_doubles - saves FPU registers on stack, currently disabled.
594 // stack_space - extra stack space. 664 // stack_space - extra stack space.
595 void EnterExitFrame(bool save_doubles, 665 void EnterExitFrame(bool save_doubles,
596 int stack_space = 0); 666 int stack_space = 0);
597 667
598 // Leave the current exit frame. 668 // Leave the current exit frame.
599 void LeaveExitFrame(bool save_doubles, Register arg_count); 669 void LeaveExitFrame(bool save_doubles, Register arg_count);
600 670
601 // Get the actual activation frame alignment for target environment. 671 // Get the actual activation frame alignment for target environment.
602 static int ActivationFrameAlignment(); 672 static int ActivationFrameAlignment();
603 673
604 // Make sure the stack is aligned. Only emits code in debug mode. 674 // Make sure the stack is aligned. Only emits code in debug mode.
605 void AssertStackIsAligned(); 675 void AssertStackIsAligned();
606 676
607 void LoadContext(Register dst, int context_chain_length); 677 void LoadContext(Register dst, int context_chain_length);
608 678
609 void LoadGlobalFunction(int index, Register function); 679 void LoadGlobalFunction(int index, Register function);
610 680
611 // Load the initial map from the global function. The registers 681 // Load the initial map from the global function. The registers
612 // function and map can be the same, function is then overwritten. 682 // function and map can be the same, function is then overwritten.
613 void LoadGlobalFunctionInitialMap(Register function, 683 void LoadGlobalFunctionInitialMap(Register function,
614 Register map, 684 Register map,
615 Register scratch); 685 Register scratch);
616 686
687
617 // ------------------------------------------------------------------------- 688 // -------------------------------------------------------------------------
618 // JavaScript invokes. 689 // JavaScript invokes.
619 690
620 // Setup call kind marking in t1. The method takes t1 as an 691 // Setup call kind marking in t1. The method takes t1 as an
621 // explicit first parameter to make the code more readable at the 692 // explicit first parameter to make the code more readable at the
622 // call sites. 693 // call sites.
623 void SetCallKind(Register dst, CallKind kind); 694 void SetCallKind(Register dst, CallKind kind);
624 695
625 // Invoke the JavaScript function code by either calling or jumping. 696 // Invoke the JavaScript function code by either calling or jumping.
626 void InvokeCode(Register code, 697 void InvokeCode(Register code,
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 void DispatchMap(Register obj, 818 void DispatchMap(Register obj,
748 Register scratch, 819 Register scratch,
749 Handle<Map> map, 820 Handle<Map> map,
750 Handle<Code> success, 821 Handle<Code> success,
751 SmiCheckType smi_check_type); 822 SmiCheckType smi_check_type);
752 823
753 // Generates code for reporting that an illegal operation has 824 // Generates code for reporting that an illegal operation has
754 // occurred. 825 // occurred.
755 void IllegalOperation(int num_arguments); 826 void IllegalOperation(int num_arguments);
756 827
828
829 // Load and check the instance type of an object for being a string.
830 // Loads the type into the second argument register.
831 // Returns a condition that will be enabled if the object was a string.
832 Condition IsObjectStringType(Register obj,
833 Register type,
834 Register result) {
835 lw(type, FieldMemOperand(obj, HeapObject::kMapOffset));
836 lbu(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
837 And(type, type, Operand(kIsNotStringMask));
838 ASSERT_EQ(0, kStringTag);
839 return eq;
840 }
841
842
757 // Picks out an array index from the hash field. 843 // Picks out an array index from the hash field.
758 // Register use: 844 // Register use:
759 // hash - holds the index's hash. Clobbered. 845 // hash - holds the index's hash. Clobbered.
760 // index - holds the overwritten index on exit. 846 // index - holds the overwritten index on exit.
761 void IndexFromHash(Register hash, Register index); 847 void IndexFromHash(Register hash, Register index);
762 848
763 // Get the number of least significant bits from a register. 849 // Get the number of least significant bits from a register.
764 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); 850 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
765 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); 851 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
766 852
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 // necessary. Do not perform a GC but instead return a retry after GC 958 // necessary. Do not perform a GC but instead return a retry after GC
873 // failure. 959 // failure.
874 MUST_USE_RESULT MaybeObject* TryTailCallExternalReference( 960 MUST_USE_RESULT MaybeObject* TryTailCallExternalReference(
875 const ExternalReference& ext, int num_arguments, int result_size); 961 const ExternalReference& ext, int num_arguments, int result_size);
876 962
877 // Convenience function: tail call a runtime routine (jump). 963 // Convenience function: tail call a runtime routine (jump).
878 void TailCallRuntime(Runtime::FunctionId fid, 964 void TailCallRuntime(Runtime::FunctionId fid,
879 int num_arguments, 965 int num_arguments,
880 int result_size); 966 int result_size);
881 967
968 int CalculateStackPassedWords(int num_reg_arguments,
969 int num_double_arguments);
970
882 // Before calling a C-function from generated code, align arguments on stack 971 // Before calling a C-function from generated code, align arguments on stack
883 // and add space for the four mips argument slots. 972 // and add space for the four mips argument slots.
884 // After aligning the frame, non-register arguments must be stored on the 973 // After aligning the frame, non-register arguments must be stored on the
885 // stack, after the argument-slots using helper: CFunctionArgumentOperand(). 974 // stack, after the argument-slots using helper: CFunctionArgumentOperand().
886 // The argument count assumes all arguments are word sized. 975 // The argument count assumes all arguments are word sized.
887 // Some compilers/platforms require the stack to be aligned when calling 976 // Some compilers/platforms require the stack to be aligned when calling
888 // C++ code. 977 // C++ code.
889 // Needs a scratch register to do some arithmetic. This register will be 978 // Needs a scratch register to do some arithmetic. This register will be
890 // trashed. 979 // trashed.
891 void PrepareCallCFunction(int num_arguments, Register scratch); 980 void PrepareCallCFunction(int num_reg_arguments,
981 int num_double_registers,
982 Register scratch);
983 void PrepareCallCFunction(int num_reg_arguments,
984 Register scratch);
892 985
893 // Arguments 1-4 are placed in registers a0 thru a3 respectively. 986 // Arguments 1-4 are placed in registers a0 thru a3 respectively.
894 // Arguments 5..n are stored to stack using following: 987 // Arguments 5..n are stored to stack using following:
895 // sw(t0, CFunctionArgumentOperand(5)); 988 // sw(t0, CFunctionArgumentOperand(5));
896 989
897 // Calls a C function and cleans up the space for arguments allocated 990 // Calls a C function and cleans up the space for arguments allocated
898 // by PrepareCallCFunction. The called function is not allowed to trigger a 991 // by PrepareCallCFunction. The called function is not allowed to trigger a
899 // garbage collection, since that might move the code and invalidate the 992 // garbage collection, since that might move the code and invalidate the
900 // return address (unless this is somehow accounted for by the called 993 // return address (unless this is somehow accounted for by the called
901 // function). 994 // function).
902 void CallCFunction(ExternalReference function, int num_arguments); 995 void CallCFunction(ExternalReference function, int num_arguments);
903 void CallCFunction(Register function, Register scratch, int num_arguments); 996 void CallCFunction(Register function, Register scratch, int num_arguments);
997 void CallCFunction(ExternalReference function,
998 int num_reg_arguments,
999 int num_double_arguments);
1000 void CallCFunction(Register function, Register scratch,
1001 int num_reg_arguments,
1002 int num_double_arguments);
904 void GetCFunctionDoubleResult(const DoubleRegister dst); 1003 void GetCFunctionDoubleResult(const DoubleRegister dst);
905 1004
906 // There are two ways of passing double arguments on MIPS, depending on 1005 // There are two ways of passing double arguments on MIPS, depending on
907 // whether soft or hard floating point ABI is used. These functions 1006 // whether soft or hard floating point ABI is used. These functions
908 // abstract parameter passing for the three different ways we call 1007 // abstract parameter passing for the three different ways we call
909 // C functions from generated code. 1008 // C functions from generated code.
910 void SetCallCDoubleArguments(DoubleRegister dreg); 1009 void SetCallCDoubleArguments(DoubleRegister dreg);
911 void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2); 1010 void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2);
912 void SetCallCDoubleArguments(DoubleRegister dreg, Register reg); 1011 void SetCallCDoubleArguments(DoubleRegister dreg, Register reg);
913 1012
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
969 void Check(Condition cc, const char* msg, Register rs, Operand rt); 1068 void Check(Condition cc, const char* msg, Register rs, Operand rt);
970 1069
971 // Print a message to stdout and abort execution. 1070 // Print a message to stdout and abort execution.
972 void Abort(const char* msg); 1071 void Abort(const char* msg);
973 1072
974 // Verify restrictions about code generated in stubs. 1073 // Verify restrictions about code generated in stubs.
975 void set_generating_stub(bool value) { generating_stub_ = value; } 1074 void set_generating_stub(bool value) { generating_stub_ = value; }
976 bool generating_stub() { return generating_stub_; } 1075 bool generating_stub() { return generating_stub_; }
977 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } 1076 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
978 bool allow_stub_calls() { return allow_stub_calls_; } 1077 bool allow_stub_calls() { return allow_stub_calls_; }
1078 void set_has_frame(bool value) { has_frame_ = value; }
1079 bool has_frame() { return has_frame_; }
1080 inline bool AllowThisStubCall(CodeStub* stub);
979 1081
980 // --------------------------------------------------------------------------- 1082 // ---------------------------------------------------------------------------
981 // Number utilities. 1083 // Number utilities.
982 1084
983 // Check whether the value of reg is a power of two and not zero. If not 1085 // Check whether the value of reg is a power of two and not zero. If not
984 // control continues at the label not_power_of_two. If reg is a power of two 1086 // control continues at the label not_power_of_two. If reg is a power of two
985 // the register scratch contains the value of (reg - 1) when control falls 1087 // the register scratch contains the value of (reg - 1) when control falls
986 // through. 1088 // through.
987 void JumpIfNotPowerOfTwoOrZero(Register reg, 1089 void JumpIfNotPowerOfTwoOrZero(Register reg,
988 Register scratch, 1090 Register scratch,
989 Label* not_power_of_two_or_zero); 1091 Label* not_power_of_two_or_zero);
990 1092
991 // ------------------------------------------------------------------------- 1093 // -------------------------------------------------------------------------
992 // Smi utilities. 1094 // Smi utilities.
993 1095
994 // Try to convert int32 to smi. If the value is to large, preserve 1096 // Try to convert int32 to smi. If the value is to large, preserve
995 // the original value and jump to not_a_smi. Destroys scratch and 1097 // the original value and jump to not_a_smi. Destroys scratch and
996 // sets flags. 1098 // sets flags.
997 // This is only used by crankshaft atm so it is unimplemented on MIPS. 1099 // This is only used by crankshaft atm so it is unimplemented on MIPS.
998 void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) { 1100 void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) {
999 UNIMPLEMENTED_MIPS(); 1101 UNIMPLEMENTED_MIPS();
1000 } 1102 }
1001 1103
1002 void SmiTag(Register reg) { 1104 void SmiTag(Register reg) {
1003 Addu(reg, reg, reg); 1105 Addu(reg, reg, reg);
1004 } 1106 }
1005 1107
1108 // Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow().
1109 void SmiTagCheckOverflow(Register reg, Register overflow) {
1110 mov(overflow, reg); // Save original value.
1111 addu(reg, reg, reg);
1112 xor_(overflow, overflow, reg); // Overflow if (value ^ 2 * value) < 0.
1113 }
1114
1006 void SmiTag(Register dst, Register src) { 1115 void SmiTag(Register dst, Register src) {
1007 Addu(dst, src, src); 1116 Addu(dst, src, src);
1008 } 1117 }
1009 1118
1010 void SmiUntag(Register reg) { 1119 void SmiUntag(Register reg) {
1011 sra(reg, reg, kSmiTagSize); 1120 sra(reg, reg, kSmiTagSize);
1012 } 1121 }
1013 1122
1014 void SmiUntag(Register dst, Register src) { 1123 void SmiUntag(Register dst, Register src) {
1015 sra(dst, src, kSmiTagSize); 1124 sra(dst, src, kSmiTagSize);
1016 } 1125 }
1017 1126
1018 // Jump the register contains a smi. 1127 // Jump the register contains a smi.
1019 inline void JumpIfSmi(Register value, Label* smi_label, 1128 inline void JumpIfSmi(Register value, Label* smi_label,
1020 Register scratch = at) { 1129 Register scratch = at,
1130 BranchDelaySlot bd = PROTECT) {
1021 ASSERT_EQ(0, kSmiTag); 1131 ASSERT_EQ(0, kSmiTag);
1022 andi(scratch, value, kSmiTagMask); 1132 andi(scratch, value, kSmiTagMask);
1023 Branch(smi_label, eq, scratch, Operand(zero_reg)); 1133 Branch(bd, smi_label, eq, scratch, Operand(zero_reg));
1024 } 1134 }
1025 1135
1026 // Jump if the register contains a non-smi. 1136 // Jump if the register contains a non-smi.
1027 inline void JumpIfNotSmi(Register value, Label* not_smi_label, 1137 inline void JumpIfNotSmi(Register value, Label* not_smi_label,
1028 Register scratch = at) { 1138 Register scratch = at) {
1029 ASSERT_EQ(0, kSmiTag); 1139 ASSERT_EQ(0, kSmiTag);
1030 andi(scratch, value, kSmiTagMask); 1140 andi(scratch, value, kSmiTagMask);
1031 Branch(not_smi_label, ne, scratch, Operand(zero_reg)); 1141 Branch(not_smi_label, ne, scratch, Operand(zero_reg));
1032 } 1142 }
1033 1143
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 Label* failure); 1193 Label* failure);
1084 1194
1085 // Test that both first and second are sequential ASCII strings. 1195 // Test that both first and second are sequential ASCII strings.
1086 // Check that they are non-smis. 1196 // Check that they are non-smis.
1087 void JumpIfNotBothSequentialAsciiStrings(Register first, 1197 void JumpIfNotBothSequentialAsciiStrings(Register first,
1088 Register second, 1198 Register second,
1089 Register scratch1, 1199 Register scratch1,
1090 Register scratch2, 1200 Register scratch2,
1091 Label* failure); 1201 Label* failure);
1092 1202
1203 void ClampUint8(Register output_reg, Register input_reg);
1204
1205 void ClampDoubleToUint8(Register result_reg,
1206 DoubleRegister input_reg,
1207 DoubleRegister temp_double_reg);
1208
1209
1093 void LoadInstanceDescriptors(Register map, Register descriptors); 1210 void LoadInstanceDescriptors(Register map, Register descriptors);
1094 1211
1212
1213 // Activation support.
1214 void EnterFrame(StackFrame::Type type);
1215 void LeaveFrame(StackFrame::Type type);
1216
1217 // Patch the relocated value (lui/ori pair).
1218 void PatchRelocatedValue(Register li_location,
1219 Register scratch,
1220 Register new_value);
1221
1095 private: 1222 private:
1096 void CallCFunctionHelper(Register function, 1223 void CallCFunctionHelper(Register function,
1097 ExternalReference function_reference, 1224 ExternalReference function_reference,
1098 Register scratch, 1225 Register scratch,
1099 int num_arguments); 1226 int num_reg_arguments,
1227 int num_double_arguments);
1100 1228
1101 void BranchShort(int16_t offset, BranchDelaySlot bdslot = PROTECT); 1229 void BranchShort(int16_t offset, BranchDelaySlot bdslot = PROTECT);
1102 void BranchShort(int16_t offset, Condition cond, Register rs, 1230 void BranchShort(int16_t offset, Condition cond, Register rs,
1103 const Operand& rt, 1231 const Operand& rt,
1104 BranchDelaySlot bdslot = PROTECT); 1232 BranchDelaySlot bdslot = PROTECT);
1105 void BranchShort(Label* L, BranchDelaySlot bdslot = PROTECT); 1233 void BranchShort(Label* L, BranchDelaySlot bdslot = PROTECT);
1106 void BranchShort(Label* L, Condition cond, Register rs, 1234 void BranchShort(Label* L, Condition cond, Register rs,
1107 const Operand& rt, 1235 const Operand& rt,
1108 BranchDelaySlot bdslot = PROTECT); 1236 BranchDelaySlot bdslot = PROTECT);
1109 void BranchAndLinkShort(int16_t offset, BranchDelaySlot bdslot = PROTECT); 1237 void BranchAndLinkShort(int16_t offset, BranchDelaySlot bdslot = PROTECT);
(...skipping 15 matching lines...) Expand all
1125 Register code_reg, 1253 Register code_reg,
1126 Label* done, 1254 Label* done,
1127 InvokeFlag flag, 1255 InvokeFlag flag,
1128 const CallWrapper& call_wrapper, 1256 const CallWrapper& call_wrapper,
1129 CallKind call_kind); 1257 CallKind call_kind);
1130 1258
1131 // Get the code for the given builtin. Returns if able to resolve 1259 // Get the code for the given builtin. Returns if able to resolve
1132 // the function in the 'resolved' flag. 1260 // the function in the 'resolved' flag.
1133 Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved); 1261 Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
1134 1262
1135 // Activation support.
1136 void EnterFrame(StackFrame::Type type);
1137 void LeaveFrame(StackFrame::Type type);
1138
1139 void InitializeNewString(Register string, 1263 void InitializeNewString(Register string,
1140 Register length, 1264 Register length,
1141 Heap::RootListIndex map_index, 1265 Heap::RootListIndex map_index,
1142 Register scratch1, 1266 Register scratch1,
1143 Register scratch2); 1267 Register scratch2);
1144 1268
1145 // Compute memory operands for safepoint stack slots. 1269 // Compute memory operands for safepoint stack slots.
1146 static int SafepointRegisterStackIndex(int reg_code); 1270 static int SafepointRegisterStackIndex(int reg_code);
1147 MemOperand SafepointRegisterSlot(Register reg); 1271 MemOperand SafepointRegisterSlot(Register reg);
1148 MemOperand SafepointRegistersAndDoublesSlot(Register reg); 1272 MemOperand SafepointRegistersAndDoublesSlot(Register reg);
1149 1273
1150 bool UseAbsoluteCodePointers();
1151
1152 bool generating_stub_; 1274 bool generating_stub_;
1153 bool allow_stub_calls_; 1275 bool allow_stub_calls_;
1276 bool has_frame_;
1154 // This handle will be patched with the code object on installation. 1277 // This handle will be patched with the code object on installation.
1155 Handle<Object> code_object_; 1278 Handle<Object> code_object_;
1156 1279
1157 // Needs access to SafepointRegisterStackIndex for optimized frame 1280 // Needs access to SafepointRegisterStackIndex for optimized frame
1158 // traversal. 1281 // traversal.
1159 friend class OptimizedFrame; 1282 friend class OptimizedFrame;
1160 }; 1283 };
1161 1284
1162 1285
1163 // The code patcher is used to patch (typically) small parts of code e.g. for 1286 // The code patcher is used to patch (typically) small parts of code e.g. for
(...skipping 20 matching lines...) Expand all
1184 void ChangeBranchCondition(Condition cond); 1307 void ChangeBranchCondition(Condition cond);
1185 1308
1186 private: 1309 private:
1187 byte* address_; // The address of the code being patched. 1310 byte* address_; // The address of the code being patched.
1188 int instructions_; // Number of instructions of the expected patch size. 1311 int instructions_; // Number of instructions of the expected patch size.
1189 int size_; // Number of bytes of the expected patch size. 1312 int size_; // Number of bytes of the expected patch size.
1190 MacroAssembler masm_; // Macro assembler used to generate the code. 1313 MacroAssembler masm_; // Macro assembler used to generate the code.
1191 }; 1314 };
1192 1315
1193 1316
1194 // -----------------------------------------------------------------------------
1195 // Static helper functions.
1196
1197 static MemOperand ContextOperand(Register context, int index) {
1198 return MemOperand(context, Context::SlotOffset(index));
1199 }
1200
1201
1202 static inline MemOperand GlobalObjectOperand() {
1203 return ContextOperand(cp, Context::GLOBAL_INDEX);
1204 }
1205
1206
1207 // Generate a MemOperand for loading a field from an object.
1208 static inline MemOperand FieldMemOperand(Register object, int offset) {
1209 return MemOperand(object, offset - kHeapObjectTag);
1210 }
1211
1212
1213 // Generate a MemOperand for storing arguments 5..N on the stack
1214 // when calling CallCFunction().
1215 static inline MemOperand CFunctionArgumentOperand(int index) {
1216 ASSERT(index > kCArgSlotCount);
1217 // Argument 5 takes the slot just past the four Arg-slots.
1218 int offset = (index - 5) * kPointerSize + kCArgsSlotsSize;
1219 return MemOperand(sp, offset);
1220 }
1221
1222 1317
1223 #ifdef GENERATED_CODE_COVERAGE 1318 #ifdef GENERATED_CODE_COVERAGE
1224 #define CODE_COVERAGE_STRINGIFY(x) #x 1319 #define CODE_COVERAGE_STRINGIFY(x) #x
1225 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) 1320 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
1226 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) 1321 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
1227 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> 1322 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
1228 #else 1323 #else
1229 #define ACCESS_MASM(masm) masm-> 1324 #define ACCESS_MASM(masm) masm->
1230 #endif 1325 #endif
1231 1326
1232 } } // namespace v8::internal 1327 } } // namespace v8::internal
1233 1328
1234 #endif // V8_MIPS_MACRO_ASSEMBLER_MIPS_H_ 1329 #endif // V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
OLDNEW
« no previous file with comments | « src/mips/ic-mips.cc ('k') | src/mips/macro-assembler-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698