| 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 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 } | 750 } |
| 751 addiu(sp, sp, 4 * NumSaved); | 751 addiu(sp, sp, 4 * NumSaved); |
| 752 } | 752 } |
| 753 | 753 |
| 754 | 754 |
| 755 void MacroAssembler::Ext(Register rt, | 755 void MacroAssembler::Ext(Register rt, |
| 756 Register rs, | 756 Register rs, |
| 757 uint16_t pos, | 757 uint16_t pos, |
| 758 uint16_t size) { | 758 uint16_t size) { |
| 759 ASSERT(pos < 32); | 759 ASSERT(pos < 32); |
| 760 ASSERT(pos + size < 32); | 760 ASSERT(pos + size < 33); |
| 761 | 761 |
| 762 if (mips32r2) { | 762 if (mips32r2) { |
| 763 ext_(rt, rs, pos, size); | 763 ext_(rt, rs, pos, size); |
| 764 } else { | 764 } else { |
| 765 // Move rs to rt and shift it left then right to get the | 765 // Move rs to rt and shift it left then right to get the |
| 766 // desired bitfield on the right side and zeroes on the left. | 766 // desired bitfield on the right side and zeroes on the left. |
| 767 sll(rt, rs, 32 - (pos + size)); | 767 int shift_left = 32 - (pos + size); |
| 768 srl(rt, rt, 32 - size); | 768 if (shift_left > 0) { |
| 769 sll(rt, rs, shift_left); |
| 770 } |
| 771 |
| 772 int shift_right = 32 - size; |
| 773 if (shift_right > 0) { |
| 774 srl(rt, rt, shift_right); |
| 775 } |
| 769 } | 776 } |
| 770 } | 777 } |
| 771 | 778 |
| 772 | 779 |
| 773 void MacroAssembler::Ins(Register rt, | 780 void MacroAssembler::Ins(Register rt, |
| 774 Register rs, | 781 Register rs, |
| 775 uint16_t pos, | 782 uint16_t pos, |
| 776 uint16_t size) { | 783 uint16_t size) { |
| 777 ASSERT(pos < 32); | 784 ASSERT(pos < 32); |
| 778 ASSERT(pos + size < 32); | 785 ASSERT(pos + size < 32); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 800 // t8 now contains the chunk from rs on the left and zeroes. | 807 // t8 now contains the chunk from rs on the left and zeroes. |
| 801 srl(t8, t8, 32 - size - pos); | 808 srl(t8, t8, 32 - size - pos); |
| 802 // t8 now contains the original chunk from rs in | 809 // t8 now contains the original chunk from rs in |
| 803 // the middle (proper position). | 810 // the middle (proper position). |
| 804 or_(rt, rt, t8); | 811 or_(rt, rt, t8); |
| 805 // rt now contains the result of the ins instruction in R2 mode. | 812 // rt now contains the result of the ins instruction in R2 mode. |
| 806 } | 813 } |
| 807 } | 814 } |
| 808 | 815 |
| 809 | 816 |
| 810 void MacroAssembler::Cvt_d_uw(FPURegister fd, FPURegister fs) { | 817 void MacroAssembler::Cvt_d_uw(FPURegister fd, |
| 811 // Move the data from fs to t4. | 818 FPURegister fs, |
| 812 mfc1(t4, fs); | 819 FPURegister scratch) { |
| 813 return Cvt_d_uw(fd, t4); | 820 // Move the data from fs to t8. |
| 821 mfc1(t8, fs); |
| 822 Cvt_d_uw(fd, t8, scratch); |
| 814 } | 823 } |
| 815 | 824 |
| 816 | 825 |
| 817 void MacroAssembler::Cvt_d_uw(FPURegister fd, Register rs) { | 826 void MacroAssembler::Cvt_d_uw(FPURegister fd, |
| 827 Register rs, |
| 828 FPURegister scratch) { |
| 818 // Convert rs to a FP value in fd (and fd + 1). | 829 // Convert rs to a FP value in fd (and fd + 1). |
| 819 // We do this by converting rs minus the MSB to avoid sign conversion, | 830 // We do this by converting rs minus the MSB to avoid sign conversion, |
| 820 // then adding 2^31-1 and 1 to the result. | 831 // then adding 2^31 to the result (if needed). |
| 821 | 832 |
| 822 ASSERT(!fd.is(f20)); | 833 ASSERT(!fd.is(scratch)); |
| 823 ASSERT(!rs.is(t9)); | 834 ASSERT(!rs.is(t9)); |
| 824 ASSERT(!rs.is(t8)); | 835 ASSERT(!rs.is(at)); |
| 825 | 836 |
| 826 // Save rs's MSB to t8. | 837 // Save rs's MSB to t9. |
| 827 And(t8, rs, 0x80000000); | 838 Ext(t9, rs, 31, 1); |
| 828 // Remove rs's MSB. | 839 // Remove rs's MSB. |
| 829 And(t9, rs, 0x7FFFFFFF); | 840 Ext(at, rs, 0, 31); |
| 830 // Move t9 to fd. | 841 // Move the result to fd. |
| 831 mtc1(t9, fd); | 842 mtc1(at, fd); |
| 832 | 843 |
| 833 // Convert fd to a real FP value. | 844 // Convert fd to a real FP value. |
| 834 cvt_d_w(fd, fd); | 845 cvt_d_w(fd, fd); |
| 835 | 846 |
| 836 Label conversion_done; | 847 Label conversion_done; |
| 837 | 848 |
| 838 // If rs's MSB was 0, it's done. | 849 // If rs's MSB was 0, it's done. |
| 839 // Otherwise we need to add that to the FP register. | 850 // Otherwise we need to add that to the FP register. |
| 840 Branch(&conversion_done, eq, t8, Operand(zero_reg)); | 851 Branch(&conversion_done, eq, t9, Operand(zero_reg)); |
| 841 | 852 |
| 842 // First load 2^31 - 1 into f20. | 853 // Load 2^31 into f20 as its float representation. |
| 843 Or(t9, zero_reg, 0x7FFFFFFF); | 854 li(at, 0x41E00000); |
| 844 mtc1(t9, f20); | 855 mtc1(at, FPURegister::from_code(scratch.code() + 1)); |
| 856 mtc1(zero_reg, scratch); |
| 857 // Add it to fd. |
| 858 add_d(fd, fd, scratch); |
| 845 | 859 |
| 846 // Convert it to FP and add it to fd. | |
| 847 cvt_d_w(f20, f20); | |
| 848 add_d(fd, fd, f20); | |
| 849 // Now add 1. | |
| 850 Or(t9, zero_reg, 1); | |
| 851 mtc1(t9, f20); | |
| 852 | |
| 853 cvt_d_w(f20, f20); | |
| 854 add_d(fd, fd, f20); | |
| 855 bind(&conversion_done); | 860 bind(&conversion_done); |
| 856 } | 861 } |
| 857 | 862 |
| 858 | 863 |
| 859 void MacroAssembler::Trunc_uw_d(FPURegister fd, FPURegister fs) { | 864 void MacroAssembler::Trunc_uw_d(FPURegister fd, |
| 860 Trunc_uw_d(fs, t4); | 865 FPURegister fs, |
| 861 mtc1(t4, fd); | 866 FPURegister scratch) { |
| 867 Trunc_uw_d(fs, t8, scratch); |
| 868 mtc1(t8, fd); |
| 862 } | 869 } |
| 863 | 870 |
| 864 | 871 |
| 865 void MacroAssembler::Trunc_uw_d(FPURegister fd, Register rs) { | 872 void MacroAssembler::Trunc_uw_d(FPURegister fd, |
| 866 ASSERT(!fd.is(f22)); | 873 Register rs, |
| 867 ASSERT(!rs.is(t8)); | 874 FPURegister scratch) { |
| 875 ASSERT(!fd.is(scratch)); |
| 876 ASSERT(!rs.is(at)); |
| 868 | 877 |
| 869 // Load 2^31 into f22. | 878 // Load 2^31 into scratch as its float representation. |
| 870 Or(t8, zero_reg, 0x80000000); | 879 li(at, 0x41E00000); |
| 871 Cvt_d_uw(f22, t8); | 880 mtc1(at, FPURegister::from_code(scratch.code() + 1)); |
| 872 | 881 mtc1(zero_reg, scratch); |
| 873 // Test if f22 > fd. | 882 // Test if scratch > fd. |
| 874 c(OLT, D, fd, f22); | 883 c(OLT, D, fd, scratch); |
| 875 | 884 |
| 876 Label simple_convert; | 885 Label simple_convert; |
| 877 // If fd < 2^31 we can convert it normally. | 886 // If fd < 2^31 we can convert it normally. |
| 878 bc1t(&simple_convert); | 887 bc1t(&simple_convert); |
| 879 | 888 |
| 880 // First we subtract 2^31 from fd, then trunc it to rs | 889 // First we subtract 2^31 from fd, then trunc it to rs |
| 881 // and add 2^31 to rs. | 890 // and add 2^31 to rs. |
| 882 | 891 sub_d(scratch, fd, scratch); |
| 883 sub_d(f22, fd, f22); | 892 trunc_w_d(scratch, scratch); |
| 884 trunc_w_d(f22, f22); | 893 mfc1(rs, scratch); |
| 885 mfc1(rs, f22); | 894 Or(rs, rs, 1 << 31); |
| 886 or_(rs, rs, t8); | |
| 887 | 895 |
| 888 Label done; | 896 Label done; |
| 889 Branch(&done); | 897 Branch(&done); |
| 890 // Simple conversion. | 898 // Simple conversion. |
| 891 bind(&simple_convert); | 899 bind(&simple_convert); |
| 892 trunc_w_d(f22, fd); | 900 trunc_w_d(scratch, fd); |
| 893 mfc1(rs, f22); | 901 mfc1(rs, scratch); |
| 894 | 902 |
| 895 bind(&done); | 903 bind(&done); |
| 896 } | 904 } |
| 897 | 905 |
| 898 | 906 |
| 899 // Tries to get a signed int32 out of a double precision floating point heap | 907 // Tries to get a signed int32 out of a double precision floating point heap |
| 900 // number. Rounds towards 0. Branch to 'not_int32' if the double is out of the | 908 // number. Rounds towards 0. Branch to 'not_int32' if the double is out of the |
| 901 // 32bits signed integer range. | 909 // 32bits signed integer range. |
| 902 // This method implementation differs from the ARM version for performance | 910 // This method implementation differs from the ARM version for performance |
| 903 // reasons. | 911 // reasons. |
| (...skipping 1333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2237 | 2245 |
| 2238 #endif // ENABLE_DEBUGGER_SUPPORT | 2246 #endif // ENABLE_DEBUGGER_SUPPORT |
| 2239 | 2247 |
| 2240 | 2248 |
| 2241 // --------------------------------------------------------------------------- | 2249 // --------------------------------------------------------------------------- |
| 2242 // Exception handling. | 2250 // Exception handling. |
| 2243 | 2251 |
| 2244 void MacroAssembler::PushTryHandler(CodeLocation try_location, | 2252 void MacroAssembler::PushTryHandler(CodeLocation try_location, |
| 2245 HandlerType type) { | 2253 HandlerType type) { |
| 2246 // Adjust this code if not the case. | 2254 // Adjust this code if not the case. |
| 2247 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | 2255 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 2256 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
| 2257 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); |
| 2258 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); |
| 2259 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); |
| 2260 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); |
| 2261 |
| 2248 // The return address is passed in register ra. | 2262 // The return address is passed in register ra. |
| 2249 if (try_location == IN_JAVASCRIPT) { | 2263 if (try_location == IN_JAVASCRIPT) { |
| 2250 if (type == TRY_CATCH_HANDLER) { | 2264 if (type == TRY_CATCH_HANDLER) { |
| 2251 li(t0, Operand(StackHandler::TRY_CATCH)); | 2265 li(t0, Operand(StackHandler::TRY_CATCH)); |
| 2252 } else { | 2266 } else { |
| 2253 li(t0, Operand(StackHandler::TRY_FINALLY)); | 2267 li(t0, Operand(StackHandler::TRY_FINALLY)); |
| 2254 } | 2268 } |
| 2255 ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize | |
| 2256 && StackHandlerConstants::kFPOffset == 2 * kPointerSize | |
| 2257 && StackHandlerConstants::kPCOffset == 3 * kPointerSize | |
| 2258 && StackHandlerConstants::kNextOffset == 0 * kPointerSize); | |
| 2259 // Save the current handler as the next handler. | 2269 // Save the current handler as the next handler. |
| 2260 li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); | 2270 li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); |
| 2261 lw(t1, MemOperand(t2)); | 2271 lw(t1, MemOperand(t2)); |
| 2262 | 2272 |
| 2263 addiu(sp, sp, -StackHandlerConstants::kSize); | 2273 addiu(sp, sp, -StackHandlerConstants::kSize); |
| 2264 sw(ra, MemOperand(sp, 12)); | 2274 sw(ra, MemOperand(sp, StackHandlerConstants::kPCOffset)); |
| 2265 sw(fp, MemOperand(sp, 8)); | 2275 sw(fp, MemOperand(sp, StackHandlerConstants::kFPOffset)); |
| 2266 sw(t0, MemOperand(sp, 4)); | 2276 sw(cp, MemOperand(sp, StackHandlerConstants::kContextOffset)); |
| 2267 sw(t1, MemOperand(sp, 0)); | 2277 sw(t0, MemOperand(sp, StackHandlerConstants::kStateOffset)); |
| 2278 sw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset)); |
| 2268 | 2279 |
| 2269 // Link this handler as the new current one. | 2280 // Link this handler as the new current one. |
| 2270 sw(sp, MemOperand(t2)); | 2281 sw(sp, MemOperand(t2)); |
| 2271 | 2282 |
| 2272 } else { | 2283 } else { |
| 2273 // Must preserve a0-a3, and s0 (argv). | 2284 // Must preserve a0-a3, and s0 (argv). |
| 2274 ASSERT(try_location == IN_JS_ENTRY); | 2285 ASSERT(try_location == IN_JS_ENTRY); |
| 2275 ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize | |
| 2276 && StackHandlerConstants::kFPOffset == 2 * kPointerSize | |
| 2277 && StackHandlerConstants::kPCOffset == 3 * kPointerSize | |
| 2278 && StackHandlerConstants::kNextOffset == 0 * kPointerSize); | |
| 2279 | |
| 2280 // The frame pointer does not point to a JS frame so we save NULL | 2286 // The frame pointer does not point to a JS frame so we save NULL |
| 2281 // for fp. We expect the code throwing an exception to check fp | 2287 // for fp. We expect the code throwing an exception to check fp |
| 2282 // before dereferencing it to restore the context. | 2288 // before dereferencing it to restore the context. |
| 2283 li(t0, Operand(StackHandler::ENTRY)); | 2289 li(t0, Operand(StackHandler::ENTRY)); |
| 2284 | 2290 |
| 2285 // Save the current handler as the next handler. | 2291 // Save the current handler as the next handler. |
| 2286 li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); | 2292 li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); |
| 2287 lw(t1, MemOperand(t2)); | 2293 lw(t1, MemOperand(t2)); |
| 2288 | 2294 |
| 2295 ASSERT(Smi::FromInt(0) == 0); // Used for no context. |
| 2296 |
| 2289 addiu(sp, sp, -StackHandlerConstants::kSize); | 2297 addiu(sp, sp, -StackHandlerConstants::kSize); |
| 2290 sw(ra, MemOperand(sp, 12)); | 2298 sw(ra, MemOperand(sp, StackHandlerConstants::kPCOffset)); |
| 2291 sw(zero_reg, MemOperand(sp, 8)); | 2299 sw(zero_reg, MemOperand(sp, StackHandlerConstants::kFPOffset)); |
| 2292 sw(t0, MemOperand(sp, 4)); | 2300 sw(zero_reg, MemOperand(sp, StackHandlerConstants::kContextOffset)); |
| 2293 sw(t1, MemOperand(sp, 0)); | 2301 sw(t0, MemOperand(sp, StackHandlerConstants::kStateOffset)); |
| 2302 sw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset)); |
| 2294 | 2303 |
| 2295 // Link this handler as the new current one. | 2304 // Link this handler as the new current one. |
| 2296 sw(sp, MemOperand(t2)); | 2305 sw(sp, MemOperand(t2)); |
| 2297 } | 2306 } |
| 2298 } | 2307 } |
| 2299 | 2308 |
| 2300 | 2309 |
| 2301 void MacroAssembler::PopTryHandler() { | 2310 void MacroAssembler::PopTryHandler() { |
| 2302 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); | 2311 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 2303 pop(a1); | 2312 pop(a1); |
| 2304 Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 2313 Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
| 2305 li(at, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); | 2314 li(at, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); |
| 2306 sw(a1, MemOperand(at)); | 2315 sw(a1, MemOperand(at)); |
| 2307 } | 2316 } |
| 2308 | 2317 |
| 2309 | 2318 |
| 2310 void MacroAssembler::Throw(Register value) { | 2319 void MacroAssembler::Throw(Register value) { |
| 2311 // v0 is expected to hold the exception. | 2320 // v0 is expected to hold the exception. |
| 2312 Move(v0, value); | 2321 Move(v0, value); |
| 2313 | 2322 |
| 2314 // Adjust this code if not the case. | 2323 // Adjust this code if not the case. |
| 2315 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | 2324 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 2325 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
| 2326 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); |
| 2327 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); |
| 2328 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); |
| 2329 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); |
| 2316 | 2330 |
| 2317 // Drop the sp to the top of the handler. | 2331 // Drop the sp to the top of the handler. |
| 2318 li(a3, Operand(ExternalReference(Isolate::k_handler_address, | 2332 li(a3, Operand(ExternalReference(Isolate::k_handler_address, |
| 2319 isolate()))); | 2333 isolate()))); |
| 2320 lw(sp, MemOperand(a3)); | 2334 lw(sp, MemOperand(a3)); |
| 2321 | 2335 |
| 2322 // Restore the next handler and frame pointer, discard handler state. | 2336 // Restore the next handler. |
| 2323 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 2324 pop(a2); | 2337 pop(a2); |
| 2325 sw(a2, MemOperand(a3)); | 2338 sw(a2, MemOperand(a3)); |
| 2326 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | |
| 2327 MultiPop(a3.bit() | fp.bit()); | |
| 2328 | 2339 |
| 2329 // Before returning we restore the context from the frame pointer if | 2340 // Restore context and frame pointer, discard state (a3). |
| 2330 // not NULL. The frame pointer is NULL in the exception handler of a | 2341 MultiPop(a3.bit() | cp.bit() | fp.bit()); |
| 2331 // JS entry frame. | 2342 |
| 2332 // Set cp to NULL if fp is NULL. | 2343 // If the handler is a JS frame, restore the context to the frame. |
| 2344 // (a3 == ENTRY) == (fp == 0) == (cp == 0), so we could test any |
| 2345 // of them. |
| 2333 Label done; | 2346 Label done; |
| 2334 Branch(USE_DELAY_SLOT, &done, eq, fp, Operand(zero_reg)); | 2347 Branch(&done, eq, fp, Operand(zero_reg)); |
| 2335 mov(cp, zero_reg); // In branch delay slot. | 2348 sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2336 lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 2337 bind(&done); | 2349 bind(&done); |
| 2338 | 2350 |
| 2339 #ifdef DEBUG | 2351 #ifdef DEBUG |
| 2340 // When emitting debug_code, set ra as return address for the jump. | 2352 // When emitting debug_code, set ra as return address for the jump. |
| 2341 // 5 instructions: add: 1, pop: 2, jump: 2. | 2353 // 5 instructions: add: 1, pop: 2, jump: 2. |
| 2342 const int kOffsetRaInstructions = 5; | 2354 const int kOffsetRaInstructions = 5; |
| 2343 Label find_ra; | 2355 Label find_ra; |
| 2344 | 2356 |
| 2345 if (emit_debug_code()) { | 2357 if (emit_debug_code()) { |
| 2346 // Compute ra for the Jump(t9). | 2358 // Compute ra for the Jump(t9). |
| 2347 const int kOffsetRaBytes = kOffsetRaInstructions * Assembler::kInstrSize; | 2359 const int kOffsetRaBytes = kOffsetRaInstructions * Assembler::kInstrSize; |
| 2348 | 2360 |
| 2349 // This branch-and-link sequence is needed to get the current PC on mips, | 2361 // This branch-and-link sequence is needed to get the current PC on mips, |
| 2350 // saved to the ra register. Then adjusted for instruction count. | 2362 // saved to the ra register. Then adjusted for instruction count. |
| 2351 bal(&find_ra); // bal exposes branch-delay. | 2363 bal(&find_ra); // bal exposes branch-delay. |
| 2352 nop(); // Branch delay slot nop. | 2364 nop(); // Branch delay slot nop. |
| 2353 bind(&find_ra); | 2365 bind(&find_ra); |
| 2354 addiu(ra, ra, kOffsetRaBytes); | 2366 addiu(ra, ra, kOffsetRaBytes); |
| 2355 } | 2367 } |
| 2356 #endif | 2368 #endif |
| 2357 | 2369 |
| 2358 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 2359 pop(t9); // 2 instructions: lw, add sp. | 2370 pop(t9); // 2 instructions: lw, add sp. |
| 2360 Jump(t9); // 2 instructions: jr, nop (in delay slot). | 2371 Jump(t9); // 2 instructions: jr, nop (in delay slot). |
| 2361 | 2372 |
| 2362 if (emit_debug_code()) { | 2373 if (emit_debug_code()) { |
| 2363 // Make sure that the expected number of instructions were generated. | 2374 // Make sure that the expected number of instructions were generated. |
| 2364 ASSERT_EQ(kOffsetRaInstructions, | 2375 ASSERT_EQ(kOffsetRaInstructions, |
| 2365 InstructionsGeneratedSince(&find_ra)); | 2376 InstructionsGeneratedSince(&find_ra)); |
| 2366 } | 2377 } |
| 2367 } | 2378 } |
| 2368 | 2379 |
| 2369 | 2380 |
| 2370 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, | 2381 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
| 2371 Register value) { | 2382 Register value) { |
| 2372 // Adjust this code if not the case. | 2383 // Adjust this code if not the case. |
| 2373 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | 2384 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 2385 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
| 2386 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); |
| 2387 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); |
| 2388 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); |
| 2389 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); |
| 2374 | 2390 |
| 2375 // v0 is expected to hold the exception. | 2391 // v0 is expected to hold the exception. |
| 2376 Move(v0, value); | 2392 Move(v0, value); |
| 2377 | 2393 |
| 2378 // Drop sp to the top stack handler. | 2394 // Drop sp to the top stack handler. |
| 2379 li(a3, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); | 2395 li(a3, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); |
| 2380 lw(sp, MemOperand(a3)); | 2396 lw(sp, MemOperand(a3)); |
| 2381 | 2397 |
| 2382 // Unwind the handlers until the ENTRY handler is found. | 2398 // Unwind the handlers until the ENTRY handler is found. |
| 2383 Label loop, done; | 2399 Label loop, done; |
| 2384 bind(&loop); | 2400 bind(&loop); |
| 2385 // Load the type of the current stack handler. | 2401 // Load the type of the current stack handler. |
| 2386 const int kStateOffset = StackHandlerConstants::kStateOffset; | 2402 const int kStateOffset = StackHandlerConstants::kStateOffset; |
| 2387 lw(a2, MemOperand(sp, kStateOffset)); | 2403 lw(a2, MemOperand(sp, kStateOffset)); |
| 2388 Branch(&done, eq, a2, Operand(StackHandler::ENTRY)); | 2404 Branch(&done, eq, a2, Operand(StackHandler::ENTRY)); |
| 2389 // Fetch the next handler in the list. | 2405 // Fetch the next handler in the list. |
| 2390 const int kNextOffset = StackHandlerConstants::kNextOffset; | 2406 const int kNextOffset = StackHandlerConstants::kNextOffset; |
| 2391 lw(sp, MemOperand(sp, kNextOffset)); | 2407 lw(sp, MemOperand(sp, kNextOffset)); |
| 2392 jmp(&loop); | 2408 jmp(&loop); |
| 2393 bind(&done); | 2409 bind(&done); |
| 2394 | 2410 |
| 2395 // Set the top handler address to next handler past the current ENTRY handler. | 2411 // Set the top handler address to next handler past the current ENTRY handler. |
| 2396 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 2397 pop(a2); | 2412 pop(a2); |
| 2398 sw(a2, MemOperand(a3)); | 2413 sw(a2, MemOperand(a3)); |
| 2399 | 2414 |
| 2400 if (type == OUT_OF_MEMORY) { | 2415 if (type == OUT_OF_MEMORY) { |
| 2401 // Set external caught exception to false. | 2416 // Set external caught exception to false. |
| 2402 ExternalReference external_caught( | 2417 ExternalReference external_caught( |
| 2403 Isolate::k_external_caught_exception_address, isolate()); | 2418 Isolate::k_external_caught_exception_address, isolate()); |
| 2404 li(a0, Operand(false, RelocInfo::NONE)); | 2419 li(a0, Operand(false, RelocInfo::NONE)); |
| 2405 li(a2, Operand(external_caught)); | 2420 li(a2, Operand(external_caught)); |
| 2406 sw(a0, MemOperand(a2)); | 2421 sw(a0, MemOperand(a2)); |
| 2407 | 2422 |
| 2408 // Set pending exception and v0 to out of memory exception. | 2423 // Set pending exception and v0 to out of memory exception. |
| 2409 Failure* out_of_memory = Failure::OutOfMemoryException(); | 2424 Failure* out_of_memory = Failure::OutOfMemoryException(); |
| 2410 li(v0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | 2425 li(v0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
| 2411 li(a2, Operand(ExternalReference(Isolate::k_pending_exception_address, | 2426 li(a2, Operand(ExternalReference(Isolate::k_pending_exception_address, |
| 2412 isolate()))); | 2427 isolate()))); |
| 2413 sw(v0, MemOperand(a2)); | 2428 sw(v0, MemOperand(a2)); |
| 2414 } | 2429 } |
| 2415 | 2430 |
| 2416 // Stack layout at this point. See also StackHandlerConstants. | 2431 // Stack layout at this point. See also StackHandlerConstants. |
| 2417 // sp -> state (ENTRY) | 2432 // sp -> state (ENTRY) |
| 2433 // cp |
| 2418 // fp | 2434 // fp |
| 2419 // ra | 2435 // ra |
| 2420 | 2436 |
| 2421 // Discard handler state (a2 is not used) and restore frame pointer. | 2437 // Restore context and frame pointer, discard state (r2). |
| 2422 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 2438 MultiPop(a2.bit() | cp.bit() | fp.bit()); |
| 2423 MultiPop(a2.bit() | fp.bit()); // a2: discarded state. | |
| 2424 // Before returning we restore the context from the frame pointer if | |
| 2425 // not NULL. The frame pointer is NULL in the exception handler of a | |
| 2426 // JS entry frame. | |
| 2427 Label cp_null; | |
| 2428 Branch(USE_DELAY_SLOT, &cp_null, eq, fp, Operand(zero_reg)); | |
| 2429 mov(cp, zero_reg); // In the branch delay slot. | |
| 2430 lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 2431 bind(&cp_null); | |
| 2432 | 2439 |
| 2433 #ifdef DEBUG | 2440 #ifdef DEBUG |
| 2434 // When emitting debug_code, set ra as return address for the jump. | 2441 // When emitting debug_code, set ra as return address for the jump. |
| 2435 // 5 instructions: add: 1, pop: 2, jump: 2. | 2442 // 5 instructions: add: 1, pop: 2, jump: 2. |
| 2436 const int kOffsetRaInstructions = 5; | 2443 const int kOffsetRaInstructions = 5; |
| 2437 Label find_ra; | 2444 Label find_ra; |
| 2438 | 2445 |
| 2439 if (emit_debug_code()) { | 2446 if (emit_debug_code()) { |
| 2440 // Compute ra for the Jump(t9). | 2447 // Compute ra for the Jump(t9). |
| 2441 const int kOffsetRaBytes = kOffsetRaInstructions * Assembler::kInstrSize; | 2448 const int kOffsetRaBytes = kOffsetRaInstructions * Assembler::kInstrSize; |
| 2442 | 2449 |
| 2443 // This branch-and-link sequence is needed to get the current PC on mips, | 2450 // This branch-and-link sequence is needed to get the current PC on mips, |
| 2444 // saved to the ra register. Then adjusted for instruction count. | 2451 // saved to the ra register. Then adjusted for instruction count. |
| 2445 bal(&find_ra); // bal exposes branch-delay slot. | 2452 bal(&find_ra); // bal exposes branch-delay slot. |
| 2446 nop(); // Branch delay slot nop. | 2453 nop(); // Branch delay slot nop. |
| 2447 bind(&find_ra); | 2454 bind(&find_ra); |
| 2448 addiu(ra, ra, kOffsetRaBytes); | 2455 addiu(ra, ra, kOffsetRaBytes); |
| 2449 } | 2456 } |
| 2450 #endif | 2457 #endif |
| 2451 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 2452 pop(t9); // 2 instructions: lw, add sp. | 2458 pop(t9); // 2 instructions: lw, add sp. |
| 2453 Jump(t9); // 2 instructions: jr, nop (in delay slot). | 2459 Jump(t9); // 2 instructions: jr, nop (in delay slot). |
| 2454 | 2460 |
| 2455 if (emit_debug_code()) { | 2461 if (emit_debug_code()) { |
| 2456 // Make sure that the expected number of instructions were generated. | 2462 // Make sure that the expected number of instructions were generated. |
| 2457 ASSERT_EQ(kOffsetRaInstructions, | 2463 ASSERT_EQ(kOffsetRaInstructions, |
| 2458 InstructionsGeneratedSince(&find_ra)); | 2464 InstructionsGeneratedSince(&find_ra)); |
| 2459 } | 2465 } |
| 2460 } | 2466 } |
| 2461 | 2467 |
| (...skipping 1829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4291 opcode == BGTZL); | 4297 opcode == BGTZL); |
| 4292 opcode = (cond == eq) ? BEQ : BNE; | 4298 opcode = (cond == eq) ? BEQ : BNE; |
| 4293 instr = (instr & ~kOpcodeMask) | opcode; | 4299 instr = (instr & ~kOpcodeMask) | opcode; |
| 4294 masm_.emit(instr); | 4300 masm_.emit(instr); |
| 4295 } | 4301 } |
| 4296 | 4302 |
| 4297 | 4303 |
| 4298 } } // namespace v8::internal | 4304 } } // namespace v8::internal |
| 4299 | 4305 |
| 4300 #endif // V8_TARGET_ARCH_MIPS | 4306 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |