| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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_ |
| OLD | NEW |