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

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

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 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/macro-assembler-mips.h ('k') | src/mips/regexp-macro-assembler-mips.h » ('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 : Assembler(arg_isolate, buffer, size), 43 : Assembler(arg_isolate, buffer, size),
44 generating_stub_(false), 44 generating_stub_(false),
45 allow_stub_calls_(true) { 45 allow_stub_calls_(true) {
46 if (isolate() != NULL) { 46 if (isolate() != NULL) {
47 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), 47 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
48 isolate()); 48 isolate());
49 } 49 }
50 } 50 }
51 51
52 52
53 // Arguments macros.
54 #define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2
55 #define COND_ARGS cond, r1, r2
56
57 #define REGISTER_TARGET_BODY(Name) \
58 void MacroAssembler::Name(Register target, \
59 BranchDelaySlot bd) { \
60 Name(Operand(target), bd); \
61 } \
62 void MacroAssembler::Name(Register target, COND_TYPED_ARGS, \
63 BranchDelaySlot bd) { \
64 Name(Operand(target), COND_ARGS, bd); \
65 }
66
67
68 #define INT_PTR_TARGET_BODY(Name) \
69 void MacroAssembler::Name(intptr_t target, RelocInfo::Mode rmode, \
70 BranchDelaySlot bd) { \
71 Name(Operand(target, rmode), bd); \
72 } \
73 void MacroAssembler::Name(intptr_t target, \
74 RelocInfo::Mode rmode, \
75 COND_TYPED_ARGS, \
76 BranchDelaySlot bd) { \
77 Name(Operand(target, rmode), COND_ARGS, bd); \
78 }
79
80
81 #define BYTE_PTR_TARGET_BODY(Name) \
82 void MacroAssembler::Name(byte* target, RelocInfo::Mode rmode, \
83 BranchDelaySlot bd) { \
84 Name(reinterpret_cast<intptr_t>(target), rmode, bd); \
85 } \
86 void MacroAssembler::Name(byte* target, \
87 RelocInfo::Mode rmode, \
88 COND_TYPED_ARGS, \
89 BranchDelaySlot bd) { \
90 Name(reinterpret_cast<intptr_t>(target), rmode, COND_ARGS, bd); \
91 }
92
93
94 #define CODE_TARGET_BODY(Name) \
95 void MacroAssembler::Name(Handle<Code> target, RelocInfo::Mode rmode, \
96 BranchDelaySlot bd) { \
97 Name(reinterpret_cast<intptr_t>(target.location()), rmode, bd); \
98 } \
99 void MacroAssembler::Name(Handle<Code> target, \
100 RelocInfo::Mode rmode, \
101 COND_TYPED_ARGS, \
102 BranchDelaySlot bd) { \
103 Name(reinterpret_cast<intptr_t>(target.location()), rmode, COND_ARGS, bd); \
104 }
105
106
107 REGISTER_TARGET_BODY(Jump)
108 REGISTER_TARGET_BODY(Call)
109 INT_PTR_TARGET_BODY(Jump)
110 INT_PTR_TARGET_BODY(Call)
111 BYTE_PTR_TARGET_BODY(Jump)
112 BYTE_PTR_TARGET_BODY(Call)
113 CODE_TARGET_BODY(Jump)
114 CODE_TARGET_BODY(Call)
115
116 #undef COND_TYPED_ARGS
117 #undef COND_ARGS
118 #undef REGISTER_TARGET_BODY
119 #undef BYTE_PTR_TARGET_BODY
120 #undef CODE_TARGET_BODY
121
122
123 void MacroAssembler::Ret(BranchDelaySlot bd) {
124 Jump(Operand(ra), bd);
125 }
126
127
128 void MacroAssembler::Ret(Condition cond, Register r1, const Operand& r2,
129 BranchDelaySlot bd) {
130 Jump(Operand(ra), cond, r1, r2, bd);
131 }
132
133
134 void MacroAssembler::LoadRoot(Register destination, 53 void MacroAssembler::LoadRoot(Register destination,
135 Heap::RootListIndex index) { 54 Heap::RootListIndex index) {
136 lw(destination, MemOperand(s6, index << kPointerSizeLog2)); 55 lw(destination, MemOperand(s6, index << kPointerSizeLog2));
137 } 56 }
138 57
139 58
140 void MacroAssembler::LoadRoot(Register destination, 59 void MacroAssembler::LoadRoot(Register destination,
141 Heap::RootListIndex index, 60 Heap::RootListIndex index,
142 Condition cond, 61 Condition cond,
143 Register src1, const Operand& src2) { 62 Register src1, const Operand& src2) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 kPageSizeBits - Page::kRegionSizeLog2); 105 kPageSizeBits - Page::kRegionSizeLog2);
187 106
188 // Mark region dirty. 107 // Mark region dirty.
189 lw(scratch, MemOperand(object, Page::kDirtyFlagOffset)); 108 lw(scratch, MemOperand(object, Page::kDirtyFlagOffset));
190 li(at, Operand(1)); 109 li(at, Operand(1));
191 sllv(at, at, address); 110 sllv(at, at, address);
192 or_(scratch, scratch, at); 111 or_(scratch, scratch, at);
193 sw(scratch, MemOperand(object, Page::kDirtyFlagOffset)); 112 sw(scratch, MemOperand(object, Page::kDirtyFlagOffset));
194 } 113 }
195 114
115
196 // Push and pop all registers that can hold pointers. 116 // Push and pop all registers that can hold pointers.
197 void MacroAssembler::PushSafepointRegisters() { 117 void MacroAssembler::PushSafepointRegisters() {
198 // Safepoints expect a block of kNumSafepointRegisters values on the 118 // Safepoints expect a block of kNumSafepointRegisters values on the
199 // stack, so adjust the stack for unsaved registers. 119 // stack, so adjust the stack for unsaved registers.
200 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; 120 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
201 ASSERT(num_unsaved >= 0); 121 ASSERT(num_unsaved >= 0);
202 Subu(sp, sp, Operand(num_unsaved * kPointerSize)); 122 Subu(sp, sp, Operand(num_unsaved * kPointerSize));
203 MultiPush(kSafepointSavedRegisters); 123 MultiPush(kSafepointSavedRegisters);
204 } 124 }
205 125
126
206 void MacroAssembler::PopSafepointRegisters() { 127 void MacroAssembler::PopSafepointRegisters() {
207 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; 128 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
208 MultiPop(kSafepointSavedRegisters); 129 MultiPop(kSafepointSavedRegisters);
209 Addu(sp, sp, Operand(num_unsaved * kPointerSize)); 130 Addu(sp, sp, Operand(num_unsaved * kPointerSize));
210 } 131 }
211 132
133
212 void MacroAssembler::PushSafepointRegistersAndDoubles() { 134 void MacroAssembler::PushSafepointRegistersAndDoubles() {
213 PushSafepointRegisters(); 135 PushSafepointRegisters();
214 Subu(sp, sp, Operand(FPURegister::kNumAllocatableRegisters * kDoubleSize)); 136 Subu(sp, sp, Operand(FPURegister::kNumAllocatableRegisters * kDoubleSize));
215 for (int i = 0; i < FPURegister::kNumAllocatableRegisters; i+=2) { 137 for (int i = 0; i < FPURegister::kNumAllocatableRegisters; i+=2) {
216 FPURegister reg = FPURegister::FromAllocationIndex(i); 138 FPURegister reg = FPURegister::FromAllocationIndex(i);
217 sdc1(reg, MemOperand(sp, i * kDoubleSize)); 139 sdc1(reg, MemOperand(sp, i * kDoubleSize));
218 } 140 }
219 } 141 }
220 142
143
221 void MacroAssembler::PopSafepointRegistersAndDoubles() { 144 void MacroAssembler::PopSafepointRegistersAndDoubles() {
222 for (int i = 0; i < FPURegister::kNumAllocatableRegisters; i+=2) { 145 for (int i = 0; i < FPURegister::kNumAllocatableRegisters; i+=2) {
223 FPURegister reg = FPURegister::FromAllocationIndex(i); 146 FPURegister reg = FPURegister::FromAllocationIndex(i);
224 ldc1(reg, MemOperand(sp, i * kDoubleSize)); 147 ldc1(reg, MemOperand(sp, i * kDoubleSize));
225 } 148 }
226 Addu(sp, sp, Operand(FPURegister::kNumAllocatableRegisters * kDoubleSize)); 149 Addu(sp, sp, Operand(FPURegister::kNumAllocatableRegisters * kDoubleSize));
227 PopSafepointRegisters(); 150 PopSafepointRegisters();
228 } 151 }
229 152
153
230 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src, 154 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src,
231 Register dst) { 155 Register dst) {
232 sw(src, SafepointRegistersAndDoublesSlot(dst)); 156 sw(src, SafepointRegistersAndDoublesSlot(dst));
233 } 157 }
234 158
235 159
236 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) { 160 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
237 sw(src, SafepointRegisterSlot(dst)); 161 sw(src, SafepointRegisterSlot(dst));
238 } 162 }
239 163
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 Context::SECURITY_TOKEN_INDEX * kPointerSize; 336 Context::SECURITY_TOKEN_INDEX * kPointerSize;
413 337
414 lw(scratch, FieldMemOperand(scratch, token_offset)); 338 lw(scratch, FieldMemOperand(scratch, token_offset));
415 lw(at, FieldMemOperand(at, token_offset)); 339 lw(at, FieldMemOperand(at, token_offset));
416 Branch(miss, ne, scratch, Operand(at)); 340 Branch(miss, ne, scratch, Operand(at));
417 341
418 bind(&same_contexts); 342 bind(&same_contexts);
419 } 343 }
420 344
421 345
346 void MacroAssembler::LoadFromNumberDictionary(Label* miss,
347 Register elements,
348 Register key,
349 Register result,
350 Register reg0,
351 Register reg1,
352 Register reg2) {
353 // Register use:
354 //
355 // elements - holds the slow-case elements of the receiver on entry.
356 // Unchanged unless 'result' is the same register.
357 //
358 // key - holds the smi key on entry.
359 // Unchanged unless 'result' is the same register.
360 //
361 //
362 // result - holds the result on exit if the load succeeded.
363 // Allowed to be the same as 'key' or 'result'.
364 // Unchanged on bailout so 'key' or 'result' can be used
365 // in further computation.
366 //
367 // Scratch registers:
368 //
369 // reg0 - holds the untagged key on entry and holds the hash once computed.
370 //
371 // reg1 - Used to hold the capacity mask of the dictionary.
372 //
373 // reg2 - Used for the index into the dictionary.
374 // at - Temporary (avoid MacroAssembler instructions also using 'at').
375 Label done;
376
377 // Compute the hash code from the untagged key. This must be kept in sync
378 // with ComputeIntegerHash in utils.h.
379 //
380 // hash = ~hash + (hash << 15);
381 nor(reg1, reg0, zero_reg);
382 sll(at, reg0, 15);
383 addu(reg0, reg1, at);
384
385 // hash = hash ^ (hash >> 12);
386 srl(at, reg0, 12);
387 xor_(reg0, reg0, at);
388
389 // hash = hash + (hash << 2);
390 sll(at, reg0, 2);
391 addu(reg0, reg0, at);
392
393 // hash = hash ^ (hash >> 4);
394 srl(at, reg0, 4);
395 xor_(reg0, reg0, at);
396
397 // hash = hash * 2057;
398 li(reg1, Operand(2057));
399 mul(reg0, reg0, reg1);
400
401 // hash = hash ^ (hash >> 16);
402 srl(at, reg0, 16);
403 xor_(reg0, reg0, at);
404
405 // Compute the capacity mask.
406 lw(reg1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset));
407 sra(reg1, reg1, kSmiTagSize);
408 Subu(reg1, reg1, Operand(1));
409
410 // Generate an unrolled loop that performs a few probes before giving up.
411 static const int kProbes = 4;
412 for (int i = 0; i < kProbes; i++) {
413 // Use reg2 for index calculations and keep the hash intact in reg0.
414 mov(reg2, reg0);
415 // Compute the masked index: (hash + i + i * i) & mask.
416 if (i > 0) {
417 Addu(reg2, reg2, Operand(NumberDictionary::GetProbeOffset(i)));
418 }
419 and_(reg2, reg2, reg1);
420
421 // Scale the index by multiplying by the element size.
422 ASSERT(NumberDictionary::kEntrySize == 3);
423 sll(at, reg2, 1); // 2x.
424 addu(reg2, reg2, at); // reg2 = reg2 * 3.
425
426 // Check if the key is identical to the name.
427 sll(at, reg2, kPointerSizeLog2);
428 addu(reg2, elements, at);
429
430 lw(at, FieldMemOperand(reg2, NumberDictionary::kElementsStartOffset));
431 if (i != kProbes - 1) {
432 Branch(&done, eq, key, Operand(at));
433 } else {
434 Branch(miss, ne, key, Operand(at));
435 }
436 }
437
438 bind(&done);
439 // Check that the value is a normal property.
440 // reg2: elements + (index * kPointerSize).
441 const int kDetailsOffset =
442 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
443 lw(reg1, FieldMemOperand(reg2, kDetailsOffset));
444 And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask())));
445 Branch(miss, ne, at, Operand(zero_reg));
446
447 // Get the value at the masked, scaled index and return.
448 const int kValueOffset =
449 NumberDictionary::kElementsStartOffset + kPointerSize;
450 lw(result, FieldMemOperand(reg2, kValueOffset));
451 }
452
453
422 // --------------------------------------------------------------------------- 454 // ---------------------------------------------------------------------------
423 // Instruction macros. 455 // Instruction macros.
424 456
425 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) { 457 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) {
426 if (rt.is_reg()) { 458 if (rt.is_reg()) {
427 addu(rd, rs, rt.rm()); 459 addu(rd, rs, rt.rm());
428 } else { 460 } else {
429 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { 461 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
430 addiu(rd, rs, rt.imm32_); 462 addiu(rd, rs, rt.imm32_);
431 } else { 463 } else {
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 RecordRelocInfo(j.rmode_, j.imm32_); 695 RecordRelocInfo(j.rmode_, j.imm32_);
664 } 696 }
665 // We need always the same number of instructions as we may need to patch 697 // We need always the same number of instructions as we may need to patch
666 // this code to load another value which may need 2 instructions to load. 698 // this code to load another value which may need 2 instructions to load.
667 lui(rd, (j.imm32_ & kHiMask) >> kLuiShift); 699 lui(rd, (j.imm32_ & kHiMask) >> kLuiShift);
668 ori(rd, rd, (j.imm32_ & kImm16Mask)); 700 ori(rd, rd, (j.imm32_ & kImm16Mask));
669 } 701 }
670 } 702 }
671 703
672 704
673 // Exception-generating instructions and debugging support.
674 void MacroAssembler::stop(const char* msg) {
675 // TO_UPGRADE: Just a break for now. Maybe we could upgrade it.
676 // We use the 0x54321 value to be able to find it easily when reading memory.
677 break_(0x54321);
678 }
679
680
681 void MacroAssembler::MultiPush(RegList regs) { 705 void MacroAssembler::MultiPush(RegList regs) {
682 int16_t NumSaved = 0; 706 int16_t NumSaved = 0;
683 int16_t NumToPush = NumberOfBitsSet(regs); 707 int16_t NumToPush = NumberOfBitsSet(regs);
684 708
685 addiu(sp, sp, -4 * NumToPush); 709 addiu(sp, sp, -4 * NumToPush);
686 for (int16_t i = kNumRegisters; i > 0; i--) { 710 for (int16_t i = kNumRegisters; i > 0; i--) {
687 if ((regs & (1 << i)) != 0) { 711 if ((regs & (1 << i)) != 0) {
688 sw(ToRegister(i), MemOperand(sp, 4 * (NumToPush - ++NumSaved))); 712 sw(ToRegister(i), MemOperand(sp, 4 * (NumToPush - ++NumSaved)));
689 } 713 }
690 } 714 }
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 857
834 858
835 void MacroAssembler::Trunc_uw_d(FPURegister fd, FPURegister fs) { 859 void MacroAssembler::Trunc_uw_d(FPURegister fd, FPURegister fs) {
836 Trunc_uw_d(fs, t4); 860 Trunc_uw_d(fs, t4);
837 mtc1(t4, fd); 861 mtc1(t4, fd);
838 } 862 }
839 863
840 864
841 void MacroAssembler::Trunc_uw_d(FPURegister fd, Register rs) { 865 void MacroAssembler::Trunc_uw_d(FPURegister fd, Register rs) {
842 ASSERT(!fd.is(f22)); 866 ASSERT(!fd.is(f22));
843 ASSERT(!rs.is(t6)); 867 ASSERT(!rs.is(t8));
844 868
845 // Load 2^31 into f22. 869 // Load 2^31 into f22.
846 Or(t6, zero_reg, 0x80000000); 870 Or(t8, zero_reg, 0x80000000);
847 Cvt_d_uw(f22, t6); 871 Cvt_d_uw(f22, t8);
848 872
849 // Test if f22 > fd. 873 // Test if f22 > fd.
850 c(OLT, D, fd, f22); 874 c(OLT, D, fd, f22);
851 875
852 Label simple_convert; 876 Label simple_convert;
853 // If fd < 2^31 we can convert it normally. 877 // If fd < 2^31 we can convert it normally.
854 bc1t(&simple_convert); 878 bc1t(&simple_convert);
855 879
856 // First we subtract 2^31 from fd, then trunc it to rs 880 // First we subtract 2^31 from fd, then trunc it to rs
857 // and add 2^31 to rs. 881 // and add 2^31 to rs.
858 882
859 sub_d(f22, fd, f22); 883 sub_d(f22, fd, f22);
860 trunc_w_d(f22, f22); 884 trunc_w_d(f22, f22);
861 mfc1(rs, f22); 885 mfc1(rs, f22);
862 or_(rs, rs, t6); 886 or_(rs, rs, t8);
863 887
864 Label done; 888 Label done;
865 Branch(&done); 889 Branch(&done);
866 // Simple conversion. 890 // Simple conversion.
867 bind(&simple_convert); 891 bind(&simple_convert);
868 trunc_w_d(f22, fd); 892 trunc_w_d(f22, fd);
869 mfc1(rs, f22); 893 mfc1(rs, f22);
870 894
871 bind(&done); 895 bind(&done);
872 } 896 }
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1045 // Restore sign if necessary. 1069 // Restore sign if necessary.
1046 mov(scratch, sign); 1070 mov(scratch, sign);
1047 result = sign; 1071 result = sign;
1048 sign = no_reg; 1072 sign = no_reg;
1049 Subu(result, zero_reg, input_high); 1073 Subu(result, zero_reg, input_high);
1050 movz(result, input_high, scratch); 1074 movz(result, input_high, scratch);
1051 bind(&done); 1075 bind(&done);
1052 } 1076 }
1053 1077
1054 1078
1079 void MacroAssembler::EmitECMATruncate(Register result,
1080 FPURegister double_input,
1081 FPURegister single_scratch,
1082 Register scratch,
1083 Register input_high,
1084 Register input_low) {
1085 CpuFeatures::Scope scope(FPU);
1086 ASSERT(!input_high.is(result));
1087 ASSERT(!input_low.is(result));
1088 ASSERT(!input_low.is(input_high));
1089 ASSERT(!scratch.is(result) &&
1090 !scratch.is(input_high) &&
1091 !scratch.is(input_low));
1092 ASSERT(!single_scratch.is(double_input));
1093
1094 Label done;
1095 Label manual;
1096
1097 // Clear cumulative exception flags and save the FCSR.
1098 Register scratch2 = input_high;
1099 cfc1(scratch2, FCSR);
1100 ctc1(zero_reg, FCSR);
1101 // Try a conversion to a signed integer.
1102 trunc_w_d(single_scratch, double_input);
1103 mfc1(result, single_scratch);
1104 // Retrieve and restore the FCSR.
1105 cfc1(scratch, FCSR);
1106 ctc1(scratch2, FCSR);
1107 // Check for overflow and NaNs.
1108 And(scratch,
1109 scratch,
1110 kFCSROverflowFlagMask | kFCSRUnderflowFlagMask | kFCSRInvalidOpFlagMask);
1111 // If we had no exceptions we are done.
1112 Branch(&done, eq, scratch, Operand(zero_reg));
1113
1114 // Load the double value and perform a manual truncation.
1115 Move(input_low, input_high, double_input);
1116 EmitOutOfInt32RangeTruncate(result,
1117 input_high,
1118 input_low,
1119 scratch);
1120 bind(&done);
1121 }
1122
1123
1055 void MacroAssembler::GetLeastBitsFromSmi(Register dst, 1124 void MacroAssembler::GetLeastBitsFromSmi(Register dst,
1056 Register src, 1125 Register src,
1057 int num_least_bits) { 1126 int num_least_bits) {
1058 Ext(dst, src, kSmiTagSize, num_least_bits); 1127 Ext(dst, src, kSmiTagSize, num_least_bits);
1059 } 1128 }
1060 1129
1061 1130
1062 void MacroAssembler::GetLeastBitsFromInt32(Register dst, 1131 void MacroAssembler::GetLeastBitsFromInt32(Register dst,
1063 Register src, 1132 Register src,
1064 int num_least_bits) { 1133 int num_least_bits) {
1065 And(dst, src, Operand((1 << num_least_bits) - 1)); 1134 And(dst, src, Operand((1 << num_least_bits) - 1));
1066 } 1135 }
1067 1136
1068 1137
1069 // Emulated condtional branches do not emit a nop in the branch delay slot. 1138 // Emulated condtional branches do not emit a nop in the branch delay slot.
1070 // 1139 //
1071 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. 1140 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct.
1072 #define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT( \ 1141 #define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT( \
1073 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \ 1142 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \
1074 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) 1143 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg))))
1075 1144
1076 1145
1146 bool MacroAssembler::UseAbsoluteCodePointers() {
1147 if (is_trampoline_emitted()) {
1148 return true;
1149 } else {
1150 return false;
1151 }
1152 }
1153
1154
1077 void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) { 1155 void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) {
1156 BranchShort(offset, bdslot);
1157 }
1158
1159
1160 void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs,
1161 const Operand& rt,
1162 BranchDelaySlot bdslot) {
1163 BranchShort(offset, cond, rs, rt, bdslot);
1164 }
1165
1166
1167 void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) {
1168 bool is_label_near = is_near(L);
1169 if (UseAbsoluteCodePointers() && !is_label_near) {
1170 Jr(L, bdslot);
1171 } else {
1172 BranchShort(L, bdslot);
1173 }
1174 }
1175
1176
1177 void MacroAssembler::Branch(Label* L, Condition cond, Register rs,
1178 const Operand& rt,
1179 BranchDelaySlot bdslot) {
1180 bool is_label_near = is_near(L);
1181 if (UseAbsoluteCodePointers() && !is_label_near) {
1182 Label skip;
1183 Condition neg_cond = NegateCondition(cond);
1184 BranchShort(&skip, neg_cond, rs, rt);
1185 Jr(L, bdslot);
1186 bind(&skip);
1187 } else {
1188 BranchShort(L, cond, rs, rt, bdslot);
1189 }
1190 }
1191
1192
1193 void MacroAssembler::BranchShort(int16_t offset, BranchDelaySlot bdslot) {
1078 b(offset); 1194 b(offset);
1079 1195
1080 // Emit a nop in the branch delay slot if required. 1196 // Emit a nop in the branch delay slot if required.
1081 if (bdslot == PROTECT) 1197 if (bdslot == PROTECT)
1082 nop(); 1198 nop();
1083 } 1199 }
1084 1200
1085 1201
1086 void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, 1202 void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs,
1087 const Operand& rt, 1203 const Operand& rt,
1088 BranchDelaySlot bdslot) { 1204 BranchDelaySlot bdslot) {
1089 BRANCH_ARGS_CHECK(cond, rs, rt); 1205 BRANCH_ARGS_CHECK(cond, rs, rt);
1090 ASSERT(!rs.is(zero_reg)); 1206 ASSERT(!rs.is(zero_reg));
1091 Register r2 = no_reg; 1207 Register r2 = no_reg;
1092 Register scratch = at; 1208 Register scratch = at;
1093 1209
1094 if (rt.is_reg()) { 1210 if (rt.is_reg()) {
1095 // We don't want any other register but scratch clobbered. 1211 // We don't want any other register but scratch clobbered.
1096 ASSERT(!scratch.is(rs) && !scratch.is(rt.rm_)); 1212 ASSERT(!scratch.is(rs) && !scratch.is(rt.rm_));
1097 r2 = rt.rm_; 1213 r2 = rt.rm_;
1098 switch (cond) { 1214 switch (cond) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 case Ugreater_equal: 1266 case Ugreater_equal:
1151 if (r2.is(zero_reg)) { 1267 if (r2.is(zero_reg)) {
1152 bgez(rs, offset); 1268 bgez(rs, offset);
1153 } else { 1269 } else {
1154 sltu(scratch, rs, r2); 1270 sltu(scratch, rs, r2);
1155 beq(scratch, zero_reg, offset); 1271 beq(scratch, zero_reg, offset);
1156 } 1272 }
1157 break; 1273 break;
1158 case Uless: 1274 case Uless:
1159 if (r2.is(zero_reg)) { 1275 if (r2.is(zero_reg)) {
1160 b(offset); 1276 // No code needs to be emitted.
1277 return;
1161 } else { 1278 } else {
1162 sltu(scratch, rs, r2); 1279 sltu(scratch, rs, r2);
1163 bne(scratch, zero_reg, offset); 1280 bne(scratch, zero_reg, offset);
1164 } 1281 }
1165 break; 1282 break;
1166 case Uless_equal: 1283 case Uless_equal:
1167 if (r2.is(zero_reg)) { 1284 if (r2.is(zero_reg)) {
1168 b(offset); 1285 b(offset);
1169 } else { 1286 } else {
1170 sltu(scratch, r2, rs); 1287 sltu(scratch, r2, rs);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 break; 1326 break;
1210 case greater_equal: 1327 case greater_equal:
1211 if (rt.imm32_ == 0) { 1328 if (rt.imm32_ == 0) {
1212 bgez(rs, offset); 1329 bgez(rs, offset);
1213 } else if (is_int16(rt.imm32_)) { 1330 } else if (is_int16(rt.imm32_)) {
1214 slti(scratch, rs, rt.imm32_); 1331 slti(scratch, rs, rt.imm32_);
1215 beq(scratch, zero_reg, offset); 1332 beq(scratch, zero_reg, offset);
1216 } else { 1333 } else {
1217 r2 = scratch; 1334 r2 = scratch;
1218 li(r2, rt); 1335 li(r2, rt);
1219 sltu(scratch, rs, r2); 1336 slt(scratch, rs, r2);
1220 beq(scratch, zero_reg, offset); 1337 beq(scratch, zero_reg, offset);
1221 } 1338 }
1222 break; 1339 break;
1223 case less: 1340 case less:
1224 if (rt.imm32_ == 0) { 1341 if (rt.imm32_ == 0) {
1225 bltz(rs, offset); 1342 bltz(rs, offset);
1226 } else if (is_int16(rt.imm32_)) { 1343 } else if (is_int16(rt.imm32_)) {
1227 slti(scratch, rs, rt.imm32_); 1344 slti(scratch, rs, rt.imm32_);
1228 bne(scratch, zero_reg, offset); 1345 bne(scratch, zero_reg, offset);
1229 } else { 1346 } else {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1262 beq(scratch, zero_reg, offset); 1379 beq(scratch, zero_reg, offset);
1263 } else { 1380 } else {
1264 r2 = scratch; 1381 r2 = scratch;
1265 li(r2, rt); 1382 li(r2, rt);
1266 sltu(scratch, rs, r2); 1383 sltu(scratch, rs, r2);
1267 beq(scratch, zero_reg, offset); 1384 beq(scratch, zero_reg, offset);
1268 } 1385 }
1269 break; 1386 break;
1270 case Uless: 1387 case Uless:
1271 if (rt.imm32_ == 0) { 1388 if (rt.imm32_ == 0) {
1272 b(offset); 1389 // No code needs to be emitted.
1390 return;
1273 } else if (is_int16(rt.imm32_)) { 1391 } else if (is_int16(rt.imm32_)) {
1274 sltiu(scratch, rs, rt.imm32_); 1392 sltiu(scratch, rs, rt.imm32_);
1275 bne(scratch, zero_reg, offset); 1393 bne(scratch, zero_reg, offset);
1276 } else { 1394 } else {
1277 r2 = scratch; 1395 r2 = scratch;
1278 li(r2, rt); 1396 li(r2, rt);
1279 sltu(scratch, rs, r2); 1397 sltu(scratch, rs, r2);
1280 bne(scratch, zero_reg, offset); 1398 bne(scratch, zero_reg, offset);
1281 } 1399 }
1282 break; 1400 break;
(...skipping 10 matching lines...) Expand all
1293 default: 1411 default:
1294 UNREACHABLE(); 1412 UNREACHABLE();
1295 } 1413 }
1296 } 1414 }
1297 // Emit a nop in the branch delay slot if required. 1415 // Emit a nop in the branch delay slot if required.
1298 if (bdslot == PROTECT) 1416 if (bdslot == PROTECT)
1299 nop(); 1417 nop();
1300 } 1418 }
1301 1419
1302 1420
1303 void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) { 1421 void MacroAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) {
1304 // We use branch_offset as an argument for the branch instructions to be sure 1422 // We use branch_offset as an argument for the branch instructions to be sure
1305 // it is called just before generating the branch instruction, as needed. 1423 // it is called just before generating the branch instruction, as needed.
1306 1424
1307 b(shifted_branch_offset(L, false)); 1425 b(shifted_branch_offset(L, false));
1308 1426
1309 // Emit a nop in the branch delay slot if required. 1427 // Emit a nop in the branch delay slot if required.
1310 if (bdslot == PROTECT) 1428 if (bdslot == PROTECT)
1311 nop(); 1429 nop();
1312 } 1430 }
1313 1431
1314 1432
1315 void MacroAssembler::Branch(Label* L, Condition cond, Register rs, 1433 void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
1316 const Operand& rt, 1434 const Operand& rt,
1317 BranchDelaySlot bdslot) { 1435 BranchDelaySlot bdslot) {
1318 BRANCH_ARGS_CHECK(cond, rs, rt); 1436 BRANCH_ARGS_CHECK(cond, rs, rt);
1319 1437
1320 int32_t offset; 1438 int32_t offset;
1321 Register r2 = no_reg; 1439 Register r2 = no_reg;
1322 Register scratch = at; 1440 Register scratch = at;
1323 if (rt.is_reg()) { 1441 if (rt.is_reg()) {
1324 r2 = rt.rm_; 1442 r2 = rt.rm_;
1325 // Be careful to always use shifted_branch_offset only just before the 1443 // Be careful to always use shifted_branch_offset only just before the
1326 // branch instruction, as the location will be remember for patching the 1444 // branch instruction, as the location will be remember for patching the
1327 // target. 1445 // target.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1395 offset = shifted_branch_offset(L, false); 1513 offset = shifted_branch_offset(L, false);
1396 bgez(rs, offset); 1514 bgez(rs, offset);
1397 } else { 1515 } else {
1398 sltu(scratch, rs, r2); 1516 sltu(scratch, rs, r2);
1399 offset = shifted_branch_offset(L, false); 1517 offset = shifted_branch_offset(L, false);
1400 beq(scratch, zero_reg, offset); 1518 beq(scratch, zero_reg, offset);
1401 } 1519 }
1402 break; 1520 break;
1403 case Uless: 1521 case Uless:
1404 if (r2.is(zero_reg)) { 1522 if (r2.is(zero_reg)) {
1405 offset = shifted_branch_offset(L, false); 1523 // No code needs to be emitted.
1406 b(offset); 1524 return;
1407 } else { 1525 } else {
1408 sltu(scratch, rs, r2); 1526 sltu(scratch, rs, r2);
1409 offset = shifted_branch_offset(L, false); 1527 offset = shifted_branch_offset(L, false);
1410 bne(scratch, zero_reg, offset); 1528 bne(scratch, zero_reg, offset);
1411 } 1529 }
1412 break; 1530 break;
1413 case Uless_equal: 1531 case Uless_equal:
1414 if (r2.is(zero_reg)) { 1532 if (r2.is(zero_reg)) {
1415 offset = shifted_branch_offset(L, false); 1533 offset = shifted_branch_offset(L, false);
1416 b(offset); 1534 b(offset);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1461 if (rt.imm32_ == 0) { 1579 if (rt.imm32_ == 0) {
1462 offset = shifted_branch_offset(L, false); 1580 offset = shifted_branch_offset(L, false);
1463 bgez(rs, offset); 1581 bgez(rs, offset);
1464 } else if (is_int16(rt.imm32_)) { 1582 } else if (is_int16(rt.imm32_)) {
1465 slti(scratch, rs, rt.imm32_); 1583 slti(scratch, rs, rt.imm32_);
1466 offset = shifted_branch_offset(L, false); 1584 offset = shifted_branch_offset(L, false);
1467 beq(scratch, zero_reg, offset); 1585 beq(scratch, zero_reg, offset);
1468 } else { 1586 } else {
1469 r2 = scratch; 1587 r2 = scratch;
1470 li(r2, rt); 1588 li(r2, rt);
1471 sltu(scratch, rs, r2); 1589 slt(scratch, rs, r2);
1472 offset = shifted_branch_offset(L, false); 1590 offset = shifted_branch_offset(L, false);
1473 beq(scratch, zero_reg, offset); 1591 beq(scratch, zero_reg, offset);
1474 } 1592 }
1475 break; 1593 break;
1476 case less: 1594 case less:
1477 if (rt.imm32_ == 0) { 1595 if (rt.imm32_ == 0) {
1478 offset = shifted_branch_offset(L, false); 1596 offset = shifted_branch_offset(L, false);
1479 bltz(rs, offset); 1597 bltz(rs, offset);
1480 } else if (is_int16(rt.imm32_)) { 1598 } else if (is_int16(rt.imm32_)) {
1481 slti(scratch, rs, rt.imm32_); 1599 slti(scratch, rs, rt.imm32_);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1525 } else { 1643 } else {
1526 r2 = scratch; 1644 r2 = scratch;
1527 li(r2, rt); 1645 li(r2, rt);
1528 sltu(scratch, rs, r2); 1646 sltu(scratch, rs, r2);
1529 offset = shifted_branch_offset(L, false); 1647 offset = shifted_branch_offset(L, false);
1530 beq(scratch, zero_reg, offset); 1648 beq(scratch, zero_reg, offset);
1531 } 1649 }
1532 break; 1650 break;
1533 case Uless: 1651 case Uless:
1534 if (rt.imm32_ == 0) { 1652 if (rt.imm32_ == 0) {
1535 offset = shifted_branch_offset(L, false); 1653 // No code needs to be emitted.
1536 b(offset); 1654 return;
1537 } else if (is_int16(rt.imm32_)) { 1655 } else if (is_int16(rt.imm32_)) {
1538 sltiu(scratch, rs, rt.imm32_); 1656 sltiu(scratch, rs, rt.imm32_);
1539 offset = shifted_branch_offset(L, false); 1657 offset = shifted_branch_offset(L, false);
1540 bne(scratch, zero_reg, offset); 1658 bne(scratch, zero_reg, offset);
1541 } else { 1659 } else {
1542 r2 = scratch; 1660 r2 = scratch;
1543 li(r2, rt); 1661 li(r2, rt);
1544 sltu(scratch, rs, r2); 1662 sltu(scratch, rs, r2);
1545 offset = shifted_branch_offset(L, false); 1663 offset = shifted_branch_offset(L, false);
1546 bne(scratch, zero_reg, offset); 1664 bne(scratch, zero_reg, offset);
(...skipping 16 matching lines...) Expand all
1563 } 1681 }
1564 } 1682 }
1565 // Check that offset could actually hold on an int16_t. 1683 // Check that offset could actually hold on an int16_t.
1566 ASSERT(is_int16(offset)); 1684 ASSERT(is_int16(offset));
1567 // Emit a nop in the branch delay slot if required. 1685 // Emit a nop in the branch delay slot if required.
1568 if (bdslot == PROTECT) 1686 if (bdslot == PROTECT)
1569 nop(); 1687 nop();
1570 } 1688 }
1571 1689
1572 1690
1691 void MacroAssembler::BranchAndLink(int16_t offset, BranchDelaySlot bdslot) {
1692 BranchAndLinkShort(offset, bdslot);
1693 }
1694
1695
1696 void MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs,
1697 const Operand& rt,
1698 BranchDelaySlot bdslot) {
1699 BranchAndLinkShort(offset, cond, rs, rt, bdslot);
1700 }
1701
1702
1703 void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) {
1704 bool is_label_near = is_near(L);
1705 if (UseAbsoluteCodePointers() && !is_label_near) {
1706 Jalr(L, bdslot);
1707 } else {
1708 BranchAndLinkShort(L, bdslot);
1709 }
1710 }
1711
1712
1713 void MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs,
1714 const Operand& rt,
1715 BranchDelaySlot bdslot) {
1716 bool is_label_near = is_near(L);
1717 if (UseAbsoluteCodePointers() && !is_label_near) {
1718 Label skip;
1719 Condition neg_cond = NegateCondition(cond);
1720 BranchShort(&skip, neg_cond, rs, rt);
1721 Jalr(L, bdslot);
1722 bind(&skip);
1723 } else {
1724 BranchAndLinkShort(L, cond, rs, rt, bdslot);
1725 }
1726 }
1727
1728
1573 // We need to use a bgezal or bltzal, but they can't be used directly with the 1729 // We need to use a bgezal or bltzal, but they can't be used directly with the
1574 // slt instructions. We could use sub or add instead but we would miss overflow 1730 // slt instructions. We could use sub or add instead but we would miss overflow
1575 // cases, so we keep slt and add an intermediate third instruction. 1731 // cases, so we keep slt and add an intermediate third instruction.
1576 void MacroAssembler::BranchAndLink(int16_t offset, 1732 void MacroAssembler::BranchAndLinkShort(int16_t offset,
1577 BranchDelaySlot bdslot) { 1733 BranchDelaySlot bdslot) {
1578 bal(offset); 1734 bal(offset);
1579 1735
1580 // Emit a nop in the branch delay slot if required. 1736 // Emit a nop in the branch delay slot if required.
1581 if (bdslot == PROTECT) 1737 if (bdslot == PROTECT)
1582 nop(); 1738 nop();
1583 } 1739 }
1584 1740
1585 1741
1586 void MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs, 1742 void MacroAssembler::BranchAndLinkShort(int16_t offset, Condition cond,
1587 const Operand& rt, 1743 Register rs, const Operand& rt,
1588 BranchDelaySlot bdslot) { 1744 BranchDelaySlot bdslot) {
1589 BRANCH_ARGS_CHECK(cond, rs, rt); 1745 BRANCH_ARGS_CHECK(cond, rs, rt);
1590 Register r2 = no_reg; 1746 Register r2 = no_reg;
1591 Register scratch = at; 1747 Register scratch = at;
1592 1748
1593 if (rt.is_reg()) { 1749 if (rt.is_reg()) {
1594 r2 = rt.rm_; 1750 r2 = rt.rm_;
1595 } else if (cond != cc_always) { 1751 } else if (cond != cc_always) {
1596 r2 = scratch; 1752 r2 = scratch;
1597 li(r2, rt); 1753 li(r2, rt);
1598 } 1754 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1658 1814
1659 default: 1815 default:
1660 UNREACHABLE(); 1816 UNREACHABLE();
1661 } 1817 }
1662 // Emit a nop in the branch delay slot if required. 1818 // Emit a nop in the branch delay slot if required.
1663 if (bdslot == PROTECT) 1819 if (bdslot == PROTECT)
1664 nop(); 1820 nop();
1665 } 1821 }
1666 1822
1667 1823
1668 void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) { 1824 void MacroAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) {
1669 bal(shifted_branch_offset(L, false)); 1825 bal(shifted_branch_offset(L, false));
1670 1826
1671 // Emit a nop in the branch delay slot if required. 1827 // Emit a nop in the branch delay slot if required.
1672 if (bdslot == PROTECT) 1828 if (bdslot == PROTECT)
1673 nop(); 1829 nop();
1674 } 1830 }
1675 1831
1676 1832
1677 void MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs, 1833 void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs,
1678 const Operand& rt, 1834 const Operand& rt,
1679 BranchDelaySlot bdslot) { 1835 BranchDelaySlot bdslot) {
1680 BRANCH_ARGS_CHECK(cond, rs, rt); 1836 BRANCH_ARGS_CHECK(cond, rs, rt);
1681 1837
1682 int32_t offset; 1838 int32_t offset;
1683 Register r2 = no_reg; 1839 Register r2 = no_reg;
1684 Register scratch = at; 1840 Register scratch = at;
1685 if (rt.is_reg()) { 1841 if (rt.is_reg()) {
1686 r2 = rt.rm_; 1842 r2 = rt.rm_;
1687 } else if (cond != cc_always) { 1843 } else if (cond != cc_always) {
1688 r2 = scratch; 1844 r2 = scratch;
1689 li(r2, rt); 1845 li(r2, rt);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1765 1921
1766 // Check that offset could actually hold on an int16_t. 1922 // Check that offset could actually hold on an int16_t.
1767 ASSERT(is_int16(offset)); 1923 ASSERT(is_int16(offset));
1768 1924
1769 // Emit a nop in the branch delay slot if required. 1925 // Emit a nop in the branch delay slot if required.
1770 if (bdslot == PROTECT) 1926 if (bdslot == PROTECT)
1771 nop(); 1927 nop();
1772 } 1928 }
1773 1929
1774 1930
1775 void MacroAssembler::Jump(const Operand& target, BranchDelaySlot bdslot) { 1931 void MacroAssembler::Jump(Register target,
1932 Condition cond,
1933 Register rs,
1934 const Operand& rt,
1935 BranchDelaySlot bd) {
1776 BlockTrampolinePoolScope block_trampoline_pool(this); 1936 BlockTrampolinePoolScope block_trampoline_pool(this);
1777 if (target.is_reg()) { 1937 if (cond == cc_always) {
1778 jr(target.rm()); 1938 jr(target);
1779 } else { 1939 } else {
1780 if (!MustUseReg(target.rmode_)) { 1940 BRANCH_ARGS_CHECK(cond, rs, rt);
1781 j(target.imm32_); 1941 Branch(2, NegateCondition(cond), rs, rt);
1782 } else { 1942 jr(target);
1783 li(t9, target);
1784 jr(t9);
1785 }
1786 } 1943 }
1787 // Emit a nop in the branch delay slot if required. 1944 // Emit a nop in the branch delay slot if required.
1788 if (bdslot == PROTECT) 1945 if (bd == PROTECT)
1789 nop(); 1946 nop();
1790 } 1947 }
1791 1948
1792 1949
1793 void MacroAssembler::Jump(const Operand& target, 1950 void MacroAssembler::Jump(intptr_t target,
1794 Condition cond, Register rs, const Operand& rt, 1951 RelocInfo::Mode rmode,
1795 BranchDelaySlot bdslot) { 1952 Condition cond,
1796 BlockTrampolinePoolScope block_trampoline_pool(this); 1953 Register rs,
1797 BRANCH_ARGS_CHECK(cond, rs, rt); 1954 const Operand& rt,
1798 if (target.is_reg()) { 1955 BranchDelaySlot bd) {
1799 if (cond == cc_always) { 1956 li(t9, Operand(target, rmode));
1800 jr(target.rm()); 1957 Jump(t9, cond, rs, rt, bd);
1801 } else {
1802 Branch(2, NegateCondition(cond), rs, rt);
1803 jr(target.rm());
1804 }
1805 } else { // Not register target.
1806 if (!MustUseReg(target.rmode_)) {
1807 if (cond == cc_always) {
1808 j(target.imm32_);
1809 } else {
1810 Branch(2, NegateCondition(cond), rs, rt);
1811 j(target.imm32_); // Will generate only one instruction.
1812 }
1813 } else { // MustUseReg(target).
1814 li(t9, target);
1815 if (cond == cc_always) {
1816 jr(t9);
1817 } else {
1818 Branch(2, NegateCondition(cond), rs, rt);
1819 jr(t9); // Will generate only one instruction.
1820 }
1821 }
1822 }
1823 // Emit a nop in the branch delay slot if required.
1824 if (bdslot == PROTECT)
1825 nop();
1826 } 1958 }
1827 1959
1828 1960
1829 int MacroAssembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode) { 1961 void MacroAssembler::Jump(Address target,
1830 return 4 * kInstrSize; 1962 RelocInfo::Mode rmode,
1963 Condition cond,
1964 Register rs,
1965 const Operand& rt,
1966 BranchDelaySlot bd) {
1967 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1968 Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd);
1831 } 1969 }
1832 1970
1833 1971
1834 int MacroAssembler::CallSize(Register reg) { 1972 void MacroAssembler::Jump(Handle<Code> code,
1835 return 2 * kInstrSize; 1973 RelocInfo::Mode rmode,
1974 Condition cond,
1975 Register rs,
1976 const Operand& rt,
1977 BranchDelaySlot bd) {
1978 ASSERT(RelocInfo::IsCodeTarget(rmode));
1979 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd);
1980 }
1981
1982
1983 int MacroAssembler::CallSize(Register target,
1984 Condition cond,
1985 Register rs,
1986 const Operand& rt,
1987 BranchDelaySlot bd) {
1988 int size = 0;
1989
1990 if (cond == cc_always) {
1991 size += 1;
1992 } else {
1993 size += 3;
1994 }
1995
1996 if (bd == PROTECT)
1997 size += 1;
1998
1999 return size * kInstrSize;
1836 } 2000 }
1837 2001
1838 2002
1839 // Note: To call gcc-compiled C code on mips, you must call thru t9. 2003 // Note: To call gcc-compiled C code on mips, you must call thru t9.
1840 void MacroAssembler::Call(const Operand& target, BranchDelaySlot bdslot) { 2004 void MacroAssembler::Call(Register target,
2005 Condition cond,
2006 Register rs,
2007 const Operand& rt,
2008 BranchDelaySlot bd) {
1841 BlockTrampolinePoolScope block_trampoline_pool(this); 2009 BlockTrampolinePoolScope block_trampoline_pool(this);
1842 if (target.is_reg()) { 2010 Label start;
1843 jalr(target.rm()); 2011 bind(&start);
1844 } else { // !target.is_reg(). 2012 if (cond == cc_always) {
1845 if (!MustUseReg(target.rmode_)) { 2013 jalr(target);
1846 jal(target.imm32_); 2014 } else {
1847 } else { // MustUseReg(target). 2015 BRANCH_ARGS_CHECK(cond, rs, rt);
1848 // Must record previous source positions before the 2016 Branch(2, NegateCondition(cond), rs, rt);
1849 // li() generates a new code target. 2017 jalr(target);
1850 positions_recorder()->WriteRecordedPositions(); 2018 }
1851 li(t9, target); 2019 // Emit a nop in the branch delay slot if required.
1852 jalr(t9); 2020 if (bd == PROTECT)
1853 } 2021 nop();
2022
2023 ASSERT_EQ(CallSize(target, cond, rs, rt, bd),
2024 SizeOfCodeGeneratedSince(&start));
2025 }
2026
2027
2028 int MacroAssembler::CallSize(Address target,
2029 RelocInfo::Mode rmode,
2030 Condition cond,
2031 Register rs,
2032 const Operand& rt,
2033 BranchDelaySlot bd) {
2034 int size = CallSize(t9, cond, rs, rt, bd);
2035 return size + 2 * kInstrSize;
2036 }
2037
2038
2039 void MacroAssembler::Call(Address target,
2040 RelocInfo::Mode rmode,
2041 Condition cond,
2042 Register rs,
2043 const Operand& rt,
2044 BranchDelaySlot bd) {
2045 BlockTrampolinePoolScope block_trampoline_pool(this);
2046 Label start;
2047 bind(&start);
2048 int32_t target_int = reinterpret_cast<int32_t>(target);
2049 // Must record previous source positions before the
2050 // li() generates a new code target.
2051 positions_recorder()->WriteRecordedPositions();
2052 li(t9, Operand(target_int, rmode), true);
2053 Call(t9, cond, rs, rt, bd);
2054 ASSERT_EQ(CallSize(target, rmode, cond, rs, rt, bd),
2055 SizeOfCodeGeneratedSince(&start));
2056 }
2057
2058
2059 int MacroAssembler::CallSize(Handle<Code> code,
2060 RelocInfo::Mode rmode,
2061 unsigned ast_id,
2062 Condition cond,
2063 Register rs,
2064 const Operand& rt,
2065 BranchDelaySlot bd) {
2066 return CallSize(reinterpret_cast<Address>(code.location()),
2067 rmode, cond, rs, rt, bd);
2068 }
2069
2070
2071 void MacroAssembler::Call(Handle<Code> code,
2072 RelocInfo::Mode rmode,
2073 unsigned ast_id,
2074 Condition cond,
2075 Register rs,
2076 const Operand& rt,
2077 BranchDelaySlot bd) {
2078 BlockTrampolinePoolScope block_trampoline_pool(this);
2079 Label start;
2080 bind(&start);
2081 ASSERT(RelocInfo::IsCodeTarget(rmode));
2082 if (rmode == RelocInfo::CODE_TARGET && ast_id != kNoASTId) {
2083 ASSERT(ast_id_for_reloc_info_ == kNoASTId);
2084 ast_id_for_reloc_info_ = ast_id;
2085 rmode = RelocInfo::CODE_TARGET_WITH_ID;
2086 }
2087 Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd);
2088 ASSERT_EQ(CallSize(code, rmode, ast_id, cond, rs, rt),
2089 SizeOfCodeGeneratedSince(&start));
2090 }
2091
2092
2093 void MacroAssembler::Ret(Condition cond,
2094 Register rs,
2095 const Operand& rt,
2096 BranchDelaySlot bd) {
2097 Jump(ra, cond, rs, rt, bd);
2098 }
2099
2100
2101 void MacroAssembler::J(Label* L, BranchDelaySlot bdslot) {
2102 BlockTrampolinePoolScope block_trampoline_pool(this);
2103
2104 uint32_t imm28;
2105 imm28 = jump_address(L);
2106 imm28 &= kImm28Mask;
2107 { BlockGrowBufferScope block_buf_growth(this);
2108 // Buffer growth (and relocation) must be blocked for internal references
2109 // until associated instructions are emitted and available to be patched.
2110 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
2111 j(imm28);
1854 } 2112 }
1855 // Emit a nop in the branch delay slot if required. 2113 // Emit a nop in the branch delay slot if required.
1856 if (bdslot == PROTECT) 2114 if (bdslot == PROTECT)
1857 nop();
1858 }
1859
1860
1861 // Note: To call gcc-compiled C code on mips, you must call thru t9.
1862 void MacroAssembler::Call(const Operand& target,
1863 Condition cond, Register rs, const Operand& rt,
1864 BranchDelaySlot bdslot) {
1865 BlockTrampolinePoolScope block_trampoline_pool(this);
1866 BRANCH_ARGS_CHECK(cond, rs, rt);
1867 if (target.is_reg()) {
1868 if (cond == cc_always) {
1869 jalr(target.rm());
1870 } else {
1871 Branch(2, NegateCondition(cond), rs, rt);
1872 jalr(target.rm());
1873 }
1874 } else { // !target.is_reg().
1875 if (!MustUseReg(target.rmode_)) {
1876 if (cond == cc_always) {
1877 jal(target.imm32_);
1878 } else {
1879 Branch(2, NegateCondition(cond), rs, rt);
1880 jal(target.imm32_); // Will generate only one instruction.
1881 }
1882 } else { // MustUseReg(target)
1883 li(t9, target);
1884 if (cond == cc_always) {
1885 jalr(t9);
1886 } else {
1887 Branch(2, NegateCondition(cond), rs, rt);
1888 jalr(t9); // Will generate only one instruction.
1889 }
1890 }
1891 }
1892 // Emit a nop in the branch delay slot if required.
1893 if (bdslot == PROTECT)
1894 nop(); 2115 nop();
1895 } 2116 }
1896 2117
1897 2118
1898 void MacroAssembler::CallWithAstId(Handle<Code> code, 2119 void MacroAssembler::Jr(Label* L, BranchDelaySlot bdslot) {
1899 RelocInfo::Mode rmode, 2120 BlockTrampolinePoolScope block_trampoline_pool(this);
1900 unsigned ast_id, 2121
1901 Condition cond, 2122 uint32_t imm32;
1902 Register r1, 2123 imm32 = jump_address(L);
1903 const Operand& r2) { 2124 { BlockGrowBufferScope block_buf_growth(this);
1904 ASSERT(rmode == RelocInfo::CODE_TARGET_WITH_ID); 2125 // Buffer growth (and relocation) must be blocked for internal references
1905 ASSERT(ast_id != kNoASTId); 2126 // until associated instructions are emitted and available to be patched.
1906 ASSERT(ast_id_for_reloc_info_ == kNoASTId); 2127 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
1907 ast_id_for_reloc_info_ = ast_id; 2128 lui(at, (imm32 & kHiMask) >> kLuiShift);
1908 Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond, r1, r2); 2129 ori(at, at, (imm32 & kImm16Mask));
2130 }
2131 jr(at);
2132
2133 // Emit a nop in the branch delay slot if required.
2134 if (bdslot == PROTECT)
2135 nop();
1909 } 2136 }
1910 2137
1911 2138
1912 void MacroAssembler::Drop(int count, 2139 void MacroAssembler::Jalr(Label* L, BranchDelaySlot bdslot) {
1913 Condition cond, 2140 BlockTrampolinePoolScope block_trampoline_pool(this);
1914 Register reg, 2141
1915 const Operand& op) { 2142 uint32_t imm32;
1916 if (count <= 0) { 2143 imm32 = jump_address(L);
1917 return; 2144 { BlockGrowBufferScope block_buf_growth(this);
2145 // Buffer growth (and relocation) must be blocked for internal references
2146 // until associated instructions are emitted and available to be patched.
2147 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
2148 lui(at, (imm32 & kHiMask) >> kLuiShift);
2149 ori(at, at, (imm32 & kImm16Mask));
1918 } 2150 }
2151 jalr(at);
1919 2152
1920 Label skip; 2153 // Emit a nop in the branch delay slot if required.
1921 2154 if (bdslot == PROTECT)
1922 if (cond != al) { 2155 nop();
1923 Branch(&skip, NegateCondition(cond), reg, op);
1924 }
1925
1926 if (count > 0) {
1927 addiu(sp, sp, count * kPointerSize);
1928 }
1929
1930 if (cond != al) {
1931 bind(&skip);
1932 }
1933 } 2156 }
1934 2157
1935 2158
1936 void MacroAssembler::DropAndRet(int drop, 2159 void MacroAssembler::DropAndRet(int drop,
1937 Condition cond, 2160 Condition cond,
1938 Register r1, 2161 Register r1,
1939 const Operand& r2) { 2162 const Operand& r2) {
1940 // This is a workaround to make sure only one branch instruction is 2163 // This is a workaround to make sure only one branch instruction is
1941 // generated. It relies on Drop and Ret not creating branches if 2164 // generated. It relies on Drop and Ret not creating branches if
1942 // cond == cc_always. 2165 // cond == cc_always.
1943 Label skip; 2166 Label skip;
1944 if (cond != cc_always) { 2167 if (cond != cc_always) {
1945 Branch(&skip, NegateCondition(cond), r1, r2); 2168 Branch(&skip, NegateCondition(cond), r1, r2);
1946 } 2169 }
1947 2170
1948 Drop(drop); 2171 Drop(drop);
1949 Ret(); 2172 Ret();
1950 2173
1951 if (cond != cc_always) { 2174 if (cond != cc_always) {
1952 bind(&skip); 2175 bind(&skip);
1953 } 2176 }
1954 } 2177 }
1955 2178
1956 2179
2180 void MacroAssembler::Drop(int count,
2181 Condition cond,
2182 Register reg,
2183 const Operand& op) {
2184 if (count <= 0) {
2185 return;
2186 }
2187
2188 Label skip;
2189
2190 if (cond != al) {
2191 Branch(&skip, NegateCondition(cond), reg, op);
2192 }
2193
2194 addiu(sp, sp, count * kPointerSize);
2195
2196 if (cond != al) {
2197 bind(&skip);
2198 }
2199 }
2200
2201
2202
1957 void MacroAssembler::Swap(Register reg1, 2203 void MacroAssembler::Swap(Register reg1,
1958 Register reg2, 2204 Register reg2,
1959 Register scratch) { 2205 Register scratch) {
1960 if (scratch.is(no_reg)) { 2206 if (scratch.is(no_reg)) {
1961 Xor(reg1, reg1, Operand(reg2)); 2207 Xor(reg1, reg1, Operand(reg2));
1962 Xor(reg2, reg2, Operand(reg1)); 2208 Xor(reg2, reg2, Operand(reg1));
1963 Xor(reg1, reg1, Operand(reg2)); 2209 Xor(reg1, reg1, Operand(reg2));
1964 } else { 2210 } else {
1965 mov(scratch, reg1); 2211 mov(scratch, reg1);
1966 mov(reg1, reg2); 2212 mov(reg1, reg2);
1967 mov(reg2, scratch); 2213 mov(reg2, scratch);
1968 } 2214 }
1969 } 2215 }
1970 2216
1971 2217
1972 void MacroAssembler::Call(Label* target) { 2218 void MacroAssembler::Call(Label* target) {
1973 BranchAndLink(target); 2219 BranchAndLink(target);
1974 } 2220 }
1975 2221
1976 2222
2223 void MacroAssembler::Push(Handle<Object> handle) {
2224 li(at, Operand(handle));
2225 push(at);
2226 }
2227
2228
1977 #ifdef ENABLE_DEBUGGER_SUPPORT 2229 #ifdef ENABLE_DEBUGGER_SUPPORT
1978 2230
1979 void MacroAssembler::DebugBreak() { 2231 void MacroAssembler::DebugBreak() {
1980 ASSERT(allow_stub_calls()); 2232 ASSERT(allow_stub_calls());
1981 mov(a0, zero_reg); 2233 mov(a0, zero_reg);
1982 li(a1, Operand(ExternalReference(Runtime::kDebugBreak, isolate()))); 2234 li(a1, Operand(ExternalReference(Runtime::kDebugBreak, isolate())));
1983 CEntryStub ces(1); 2235 CEntryStub ces(1);
1984 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); 2236 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
1985 } 2237 }
1986 2238
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after
2508 AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 2760 AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
2509 sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset)); 2761 sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
2510 } 2762 }
2511 2763
2512 2764
2513 void MacroAssembler::AllocateHeapNumberWithValue(Register result, 2765 void MacroAssembler::AllocateHeapNumberWithValue(Register result,
2514 FPURegister value, 2766 FPURegister value,
2515 Register scratch1, 2767 Register scratch1,
2516 Register scratch2, 2768 Register scratch2,
2517 Label* gc_required) { 2769 Label* gc_required) {
2518 LoadRoot(t6, Heap::kHeapNumberMapRootIndex); 2770 LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
2519 AllocateHeapNumber(result, scratch1, scratch2, t6, gc_required); 2771 AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required);
2520 sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset)); 2772 sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset));
2521 } 2773 }
2522 2774
2523 2775
2524 // Copies a fixed number of fields of heap objects from src to dst. 2776 // Copies a fixed number of fields of heap objects from src to dst.
2525 void MacroAssembler::CopyFields(Register dst, 2777 void MacroAssembler::CopyFields(Register dst,
2526 Register src, 2778 Register src,
2527 RegList temps, 2779 RegList temps,
2528 int field_count) { 2780 int field_count) {
2529 ASSERT((temps & dst.bit()) == 0); 2781 ASSERT((temps & dst.bit()) == 0);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2598 lbu(scratch, MemOperand(src)); 2850 lbu(scratch, MemOperand(src));
2599 Addu(src, src, 1); 2851 Addu(src, src, 1);
2600 sb(scratch, MemOperand(dst)); 2852 sb(scratch, MemOperand(dst));
2601 Addu(dst, dst, 1); 2853 Addu(dst, dst, 1);
2602 Subu(length, length, Operand(1)); 2854 Subu(length, length, Operand(1));
2603 Branch(&byte_loop_1, ne, length, Operand(zero_reg)); 2855 Branch(&byte_loop_1, ne, length, Operand(zero_reg));
2604 bind(&done); 2856 bind(&done);
2605 } 2857 }
2606 2858
2607 2859
2860 void MacroAssembler::CheckFastElements(Register map,
2861 Register scratch,
2862 Label* fail) {
2863 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0);
2864 lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
2865 Branch(fail, hi, scratch, Operand(Map::kMaximumBitField2FastElementValue));
2866 }
2867
2868
2608 void MacroAssembler::CheckMap(Register obj, 2869 void MacroAssembler::CheckMap(Register obj,
2609 Register scratch, 2870 Register scratch,
2610 Handle<Map> map, 2871 Handle<Map> map,
2611 Label* fail, 2872 Label* fail,
2612 SmiCheckType smi_check_type) { 2873 SmiCheckType smi_check_type) {
2613 if (smi_check_type == DO_SMI_CHECK) { 2874 if (smi_check_type == DO_SMI_CHECK) {
2614 JumpIfSmi(obj, fail); 2875 JumpIfSmi(obj, fail);
2615 } 2876 }
2616 lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); 2877 lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
2617 li(at, Operand(map)); 2878 li(at, Operand(map));
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
2768 3029
2769 if (!definitely_matches) { 3030 if (!definitely_matches) {
2770 if (!code_constant.is_null()) { 3031 if (!code_constant.is_null()) {
2771 li(a3, Operand(code_constant)); 3032 li(a3, Operand(code_constant));
2772 addiu(a3, a3, Code::kHeaderSize - kHeapObjectTag); 3033 addiu(a3, a3, Code::kHeaderSize - kHeapObjectTag);
2773 } 3034 }
2774 3035
2775 Handle<Code> adaptor = 3036 Handle<Code> adaptor =
2776 isolate()->builtins()->ArgumentsAdaptorTrampoline(); 3037 isolate()->builtins()->ArgumentsAdaptorTrampoline();
2777 if (flag == CALL_FUNCTION) { 3038 if (flag == CALL_FUNCTION) {
2778 call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET)); 3039 call_wrapper.BeforeCall(CallSize(adaptor));
2779 SetCallKind(t1, call_kind); 3040 SetCallKind(t1, call_kind);
2780 Call(adaptor, RelocInfo::CODE_TARGET); 3041 Call(adaptor);
2781 call_wrapper.AfterCall(); 3042 call_wrapper.AfterCall();
2782 jmp(done); 3043 jmp(done);
2783 } else { 3044 } else {
2784 SetCallKind(t1, call_kind); 3045 SetCallKind(t1, call_kind);
2785 Jump(adaptor, RelocInfo::CODE_TARGET); 3046 Jump(adaptor, RelocInfo::CODE_TARGET);
2786 } 3047 }
2787 bind(&regular_invoke); 3048 bind(&regular_invoke);
2788 } 3049 }
2789 } 3050 }
2790 3051
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2854 sra(expected_reg, expected_reg, kSmiTagSize); 3115 sra(expected_reg, expected_reg, kSmiTagSize);
2855 lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); 3116 lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
2856 3117
2857 ParameterCount expected(expected_reg); 3118 ParameterCount expected(expected_reg);
2858 InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind); 3119 InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind);
2859 } 3120 }
2860 3121
2861 3122
2862 void MacroAssembler::InvokeFunction(JSFunction* function, 3123 void MacroAssembler::InvokeFunction(JSFunction* function,
2863 const ParameterCount& actual, 3124 const ParameterCount& actual,
2864 InvokeFlag flag) { 3125 InvokeFlag flag,
3126 CallKind call_kind) {
2865 ASSERT(function->is_compiled()); 3127 ASSERT(function->is_compiled());
2866 3128
2867 // Get the function and setup the context. 3129 // Get the function and setup the context.
2868 li(a1, Operand(Handle<JSFunction>(function))); 3130 li(a1, Operand(Handle<JSFunction>(function)));
2869 lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); 3131 lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
2870 3132
2871 // Invoke the cached code. 3133 // Invoke the cached code.
2872 Handle<Code> code(function->code()); 3134 Handle<Code> code(function->code());
2873 ParameterCount expected(function->shared()->formal_parameter_count()); 3135 ParameterCount expected(function->shared()->formal_parameter_count());
2874 if (V8::UseCrankshaft()) { 3136 if (V8::UseCrankshaft()) {
2875 UNIMPLEMENTED_MIPS(); 3137 UNIMPLEMENTED_MIPS();
2876 } else { 3138 } else {
2877 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag); 3139 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag, call_kind);
2878 } 3140 }
2879 } 3141 }
2880 3142
2881 3143
2882 void MacroAssembler::IsObjectJSObjectType(Register heap_object, 3144 void MacroAssembler::IsObjectJSObjectType(Register heap_object,
2883 Register map, 3145 Register map,
2884 Register scratch, 3146 Register scratch,
2885 Label* fail) { 3147 Label* fail) {
2886 lw(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); 3148 lw(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
2887 IsInstanceJSObjectType(map, scratch, fail); 3149 IsInstanceJSObjectType(map, scratch, fail);
2888 } 3150 }
2889 3151
2890 3152
2891 void MacroAssembler::IsInstanceJSObjectType(Register map, 3153 void MacroAssembler::IsInstanceJSObjectType(Register map,
2892 Register scratch, 3154 Register scratch,
2893 Label* fail) { 3155 Label* fail) {
2894 lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); 3156 lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
2895 Branch(fail, lt, scratch, Operand(FIRST_JS_OBJECT_TYPE)); 3157 Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2896 Branch(fail, gt, scratch, Operand(LAST_JS_OBJECT_TYPE)); 3158 Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2897 } 3159 }
2898 3160
2899 3161
2900 void MacroAssembler::IsObjectJSStringType(Register object, 3162 void MacroAssembler::IsObjectJSStringType(Register object,
2901 Register scratch, 3163 Register scratch,
2902 Label* fail) { 3164 Label* fail) {
2903 ASSERT(kNotStringTag != 0); 3165 ASSERT(kNotStringTag != 0);
2904 3166
2905 lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); 3167 lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
2906 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 3168 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2966 lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); 3228 lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
2967 } 3229 }
2968 3230
2969 3231
2970 // ----------------------------------------------------------------------------- 3232 // -----------------------------------------------------------------------------
2971 // Runtime calls. 3233 // Runtime calls.
2972 3234
2973 void MacroAssembler::CallStub(CodeStub* stub, Condition cond, 3235 void MacroAssembler::CallStub(CodeStub* stub, Condition cond,
2974 Register r1, const Operand& r2) { 3236 Register r1, const Operand& r2) {
2975 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. 3237 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs.
2976 Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2); 3238 Call(stub->GetCode(), RelocInfo::CODE_TARGET, kNoASTId, cond, r1, r2);
2977 } 3239 }
2978 3240
2979 3241
2980 MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub, Condition cond, 3242 MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub, Condition cond,
2981 Register r1, const Operand& r2) { 3243 Register r1, const Operand& r2) {
2982 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. 3244 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs.
2983 Object* result; 3245 Object* result;
2984 { MaybeObject* maybe_result = stub->TryGetCode(); 3246 { MaybeObject* maybe_result = stub->TryGetCode();
2985 if (!maybe_result->ToObject(&result)) return maybe_result; 3247 if (!maybe_result->ToObject(&result)) return maybe_result;
2986 } 3248 }
2987 Call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, cond, r1, r2); 3249 Call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET,
3250 kNoASTId, cond, r1, r2);
2988 return result; 3251 return result;
2989 } 3252 }
2990 3253
2991 3254
2992
2993 void MacroAssembler::TailCallStub(CodeStub* stub) { 3255 void MacroAssembler::TailCallStub(CodeStub* stub) {
2994 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. 3256 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs.
2995 Jump(stub->GetCode(), RelocInfo::CODE_TARGET); 3257 Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
2996 } 3258 }
2997 3259
3260
2998 MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub, 3261 MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub,
2999 Condition cond, 3262 Condition cond,
3000 Register r1, 3263 Register r1,
3001 const Operand& r2) { 3264 const Operand& r2) {
3002 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. 3265 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs.
3003 Object* result; 3266 Object* result;
3004 { MaybeObject* maybe_result = stub->TryGetCode(); 3267 { MaybeObject* maybe_result = stub->TryGetCode();
3005 if (!maybe_result->ToObject(&result)) return maybe_result; 3268 if (!maybe_result->ToObject(&result)) return maybe_result;
3006 } 3269 }
3007 Jump(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, cond, r1, r2); 3270 Jump(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, cond, r1, r2);
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
3183 Register right, 3446 Register right,
3184 Register overflow_dst, 3447 Register overflow_dst,
3185 Register scratch) { 3448 Register scratch) {
3186 ASSERT(!dst.is(overflow_dst)); 3449 ASSERT(!dst.is(overflow_dst));
3187 ASSERT(!dst.is(scratch)); 3450 ASSERT(!dst.is(scratch));
3188 ASSERT(!overflow_dst.is(scratch)); 3451 ASSERT(!overflow_dst.is(scratch));
3189 ASSERT(!overflow_dst.is(left)); 3452 ASSERT(!overflow_dst.is(left));
3190 ASSERT(!overflow_dst.is(right)); 3453 ASSERT(!overflow_dst.is(right));
3191 ASSERT(!left.is(right)); 3454 ASSERT(!left.is(right));
3192 3455
3193 // TODO(kalmard) There must be a way to optimize dst == left and dst == right
3194 // cases.
3195
3196 if (dst.is(left)) { 3456 if (dst.is(left)) {
3197 addu(overflow_dst, left, right); 3457 mov(scratch, left); // Preserve left.
3198 xor_(dst, overflow_dst, left); 3458 addu(dst, left, right); // Left is overwritten.
3199 xor_(scratch, overflow_dst, right); 3459 xor_(scratch, dst, scratch); // Original left.
3200 and_(scratch, scratch, dst); 3460 xor_(overflow_dst, dst, right);
3201 mov(dst, overflow_dst); 3461 and_(overflow_dst, overflow_dst, scratch);
3202 mov(overflow_dst, scratch);
3203 } else if (dst.is(right)) { 3462 } else if (dst.is(right)) {
3204 addu(overflow_dst, left, right); 3463 mov(scratch, right); // Preserve right.
3205 xor_(dst, overflow_dst, right); 3464 addu(dst, left, right); // Right is overwritten.
3206 xor_(scratch, overflow_dst, left); 3465 xor_(scratch, dst, scratch); // Original right.
3207 and_(scratch, scratch, dst); 3466 xor_(overflow_dst, dst, left);
3208 mov(dst, overflow_dst); 3467 and_(overflow_dst, overflow_dst, scratch);
3209 mov(overflow_dst, scratch);
3210 } else { 3468 } else {
3211 addu(dst, left, right); 3469 addu(dst, left, right);
3212 xor_(overflow_dst, dst, left); 3470 xor_(overflow_dst, dst, left);
3213 xor_(scratch, dst, right); 3471 xor_(scratch, dst, right);
3214 and_(overflow_dst, scratch, overflow_dst); 3472 and_(overflow_dst, scratch, overflow_dst);
3215 } 3473 }
3216 } 3474 }
3217 3475
3218 3476
3219 void MacroAssembler::SubuAndCheckForOverflow(Register dst, 3477 void MacroAssembler::SubuAndCheckForOverflow(Register dst,
3220 Register left, 3478 Register left,
3221 Register right, 3479 Register right,
3222 Register overflow_dst, 3480 Register overflow_dst,
3223 Register scratch) { 3481 Register scratch) {
3224 ASSERT(!dst.is(overflow_dst)); 3482 ASSERT(!dst.is(overflow_dst));
3225 ASSERT(!dst.is(scratch)); 3483 ASSERT(!dst.is(scratch));
3226 ASSERT(!overflow_dst.is(scratch)); 3484 ASSERT(!overflow_dst.is(scratch));
3227 ASSERT(!overflow_dst.is(left)); 3485 ASSERT(!overflow_dst.is(left));
3228 ASSERT(!overflow_dst.is(right)); 3486 ASSERT(!overflow_dst.is(right));
3229 ASSERT(!left.is(right)); 3487 ASSERT(!left.is(right));
3230 ASSERT(!scratch.is(left)); 3488 ASSERT(!scratch.is(left));
3231 ASSERT(!scratch.is(right)); 3489 ASSERT(!scratch.is(right));
3232 3490
3233 // TODO(kalmard) There must be a way to optimize dst == left and dst == right
3234 // cases.
3235
3236 if (dst.is(left)) { 3491 if (dst.is(left)) {
3237 subu(overflow_dst, left, right); 3492 mov(scratch, left); // Preserve left.
3238 xor_(scratch, overflow_dst, left); 3493 subu(dst, left, right); // Left is overwritten.
3239 xor_(dst, left, right); 3494 xor_(overflow_dst, dst, scratch); // scratch is original left.
3240 and_(scratch, scratch, dst); 3495 xor_(scratch, scratch, right); // scratch is original left.
3241 mov(dst, overflow_dst); 3496 and_(overflow_dst, scratch, overflow_dst);
3242 mov(overflow_dst, scratch);
3243 } else if (dst.is(right)) { 3497 } else if (dst.is(right)) {
3244 subu(overflow_dst, left, right); 3498 mov(scratch, right); // Preserve right.
3245 xor_(dst, left, right); 3499 subu(dst, left, right); // Right is overwritten.
3246 xor_(scratch, overflow_dst, left); 3500 xor_(overflow_dst, dst, left);
3247 and_(scratch, scratch, dst); 3501 xor_(scratch, left, scratch); // Original right.
3248 mov(dst, overflow_dst); 3502 and_(overflow_dst, scratch, overflow_dst);
3249 mov(overflow_dst, scratch);
3250 } else { 3503 } else {
3251 subu(dst, left, right); 3504 subu(dst, left, right);
3252 xor_(overflow_dst, dst, left); 3505 xor_(overflow_dst, dst, left);
3253 xor_(scratch, left, right); 3506 xor_(scratch, left, right);
3254 and_(overflow_dst, scratch, overflow_dst); 3507 and_(overflow_dst, scratch, overflow_dst);
3255 } 3508 }
3256 } 3509 }
3257 3510
3258 3511
3259 void MacroAssembler::CallRuntime(const Runtime::Function* f, 3512 void MacroAssembler::CallRuntime(const Runtime::Function* f,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
3308 int num_arguments, 3561 int num_arguments,
3309 int result_size) { 3562 int result_size) {
3310 // TODO(1236192): Most runtime routines don't need the number of 3563 // TODO(1236192): Most runtime routines don't need the number of
3311 // arguments passed in because it is constant. At some point we 3564 // arguments passed in because it is constant. At some point we
3312 // should remove this need and make the runtime routine entry code 3565 // should remove this need and make the runtime routine entry code
3313 // smarter. 3566 // smarter.
3314 li(a0, Operand(num_arguments)); 3567 li(a0, Operand(num_arguments));
3315 JumpToExternalReference(ext); 3568 JumpToExternalReference(ext);
3316 } 3569 }
3317 3570
3571
3318 MaybeObject* MacroAssembler::TryTailCallExternalReference( 3572 MaybeObject* MacroAssembler::TryTailCallExternalReference(
3319 const ExternalReference& ext, int num_arguments, int result_size) { 3573 const ExternalReference& ext, int num_arguments, int result_size) {
3320 // TODO(1236192): Most runtime routines don't need the number of 3574 // TODO(1236192): Most runtime routines don't need the number of
3321 // arguments passed in because it is constant. At some point we 3575 // arguments passed in because it is constant. At some point we
3322 // should remove this need and make the runtime routine entry code 3576 // should remove this need and make the runtime routine entry code
3323 // smarter. 3577 // smarter.
3324 li(a0, num_arguments); 3578 li(a0, num_arguments);
3325 return TryJumpToExternalReference(ext); 3579 return TryJumpToExternalReference(ext);
3326 } 3580 }
3327 3581
(...skipping 21 matching lines...) Expand all
3349 return TryTailCallStub(&stub); 3603 return TryTailCallStub(&stub);
3350 } 3604 }
3351 3605
3352 3606
3353 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, 3607 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
3354 InvokeFlag flag, 3608 InvokeFlag flag,
3355 const CallWrapper& call_wrapper) { 3609 const CallWrapper& call_wrapper) {
3356 GetBuiltinEntry(t9, id); 3610 GetBuiltinEntry(t9, id);
3357 if (flag == CALL_FUNCTION) { 3611 if (flag == CALL_FUNCTION) {
3358 call_wrapper.BeforeCall(CallSize(t9)); 3612 call_wrapper.BeforeCall(CallSize(t9));
3613 SetCallKind(t1, CALL_AS_METHOD);
3359 Call(t9); 3614 Call(t9);
3360 call_wrapper.AfterCall(); 3615 call_wrapper.AfterCall();
3361 } else { 3616 } else {
3362 ASSERT(flag == JUMP_FUNCTION); 3617 ASSERT(flag == JUMP_FUNCTION);
3618 SetCallKind(t1, CALL_AS_METHOD);
3363 Jump(t9); 3619 Jump(t9);
3364 } 3620 }
3365 } 3621 }
3366 3622
3367 3623
3368 void MacroAssembler::GetBuiltinFunction(Register target, 3624 void MacroAssembler::GetBuiltinFunction(Register target,
3369 Builtins::JavaScript id) { 3625 Builtins::JavaScript id) {
3370 // Load the builtins object into target register. 3626 // Load the builtins object into target register.
3371 lw(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 3627 lw(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
3372 lw(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); 3628 lw(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
3502 while (abort_instructions++ < kExpectedAbortInstructions) { 3758 while (abort_instructions++ < kExpectedAbortInstructions) {
3503 nop(); 3759 nop();
3504 } 3760 }
3505 } 3761 }
3506 } 3762 }
3507 3763
3508 3764
3509 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { 3765 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
3510 if (context_chain_length > 0) { 3766 if (context_chain_length > 0) {
3511 // Move up the chain of contexts to the context containing the slot. 3767 // Move up the chain of contexts to the context containing the slot.
3512 lw(dst, MemOperand(cp, Context::SlotOffset(Context::CLOSURE_INDEX))); 3768 lw(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
3513 // Load the function context (which is the incoming, outer context).
3514 lw(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
3515 for (int i = 1; i < context_chain_length; i++) { 3769 for (int i = 1; i < context_chain_length; i++) {
3516 lw(dst, MemOperand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); 3770 lw(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
3517 lw(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
3518 } 3771 }
3519 } else { 3772 } else {
3520 // Slot is in the current function context. Move it into the 3773 // Slot is in the current function context. Move it into the
3521 // destination register in case we store into it (the write barrier 3774 // destination register in case we store into it (the write barrier
3522 // cannot be allowed to destroy the context in esi). 3775 // cannot be allowed to destroy the context in esi).
3523 Move(dst, cp); 3776 Move(dst, cp);
3524 } 3777 }
3525
3526 // We should not have found a 'with' context by walking the context chain
3527 // (i.e., the static scope chain and runtime context chain do not agree).
3528 // A variable occurring in such a scope should have slot type LOOKUP and
3529 // not CONTEXT.
3530 if (emit_debug_code()) {
3531 lw(t9, MemOperand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
3532 Check(eq, "Yo dawg, I heard you liked function contexts "
3533 "so I put function contexts in all your contexts",
3534 dst, Operand(t9));
3535 }
3536 } 3778 }
3537 3779
3538 3780
3539 void MacroAssembler::LoadGlobalFunction(int index, Register function) { 3781 void MacroAssembler::LoadGlobalFunction(int index, Register function) {
3540 // Load the global or builtins object from the current context. 3782 // Load the global or builtins object from the current context.
3541 lw(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 3783 lw(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
3542 // Load the global context from the global or builtins object. 3784 // Load the global context from the global or builtins object.
3543 lw(function, FieldMemOperand(function, 3785 lw(function, FieldMemOperand(function,
3544 GlobalObject::kGlobalContextOffset)); 3786 GlobalObject::kGlobalContextOffset));
3545 // Load the function from the global context. 3787 // Load the function from the global context.
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
3711 return OS::ActivationFrameAlignment(); 3953 return OS::ActivationFrameAlignment();
3712 #else // defined(V8_HOST_ARCH_MIPS) 3954 #else // defined(V8_HOST_ARCH_MIPS)
3713 // If we are using the simulator then we should always align to the expected 3955 // If we are using the simulator then we should always align to the expected
3714 // alignment. As the simulator is used to generate snapshots we do not know 3956 // alignment. As the simulator is used to generate snapshots we do not know
3715 // if the target platform will need alignment, so this is controlled from a 3957 // if the target platform will need alignment, so this is controlled from a
3716 // flag. 3958 // flag.
3717 return FLAG_sim_stack_alignment; 3959 return FLAG_sim_stack_alignment;
3718 #endif // defined(V8_HOST_ARCH_MIPS) 3960 #endif // defined(V8_HOST_ARCH_MIPS)
3719 } 3961 }
3720 3962
3963
3721 void MacroAssembler::AssertStackIsAligned() { 3964 void MacroAssembler::AssertStackIsAligned() {
3722 if (emit_debug_code()) { 3965 if (emit_debug_code()) {
3723 const int frame_alignment = ActivationFrameAlignment(); 3966 const int frame_alignment = ActivationFrameAlignment();
3724 const int frame_alignment_mask = frame_alignment - 1; 3967 const int frame_alignment_mask = frame_alignment - 1;
3725 3968
3726 if (frame_alignment > kPointerSize) { 3969 if (frame_alignment > kPointerSize) {
3727 Label alignment_as_expected; 3970 Label alignment_as_expected;
3728 ASSERT(IsPowerOf2(frame_alignment)); 3971 ASSERT(IsPowerOf2(frame_alignment));
3729 andi(at, sp, frame_alignment_mask); 3972 andi(at, sp, frame_alignment_mask);
3730 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); 3973 Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
4047 opcode == BGTZL); 4290 opcode == BGTZL);
4048 opcode = (cond == eq) ? BEQ : BNE; 4291 opcode = (cond == eq) ? BEQ : BNE;
4049 instr = (instr & ~kOpcodeMask) | opcode; 4292 instr = (instr & ~kOpcodeMask) | opcode;
4050 masm_.emit(instr); 4293 masm_.emit(instr);
4051 } 4294 }
4052 4295
4053 4296
4054 } } // namespace v8::internal 4297 } } // namespace v8::internal
4055 4298
4056 #endif // V8_TARGET_ARCH_MIPS 4299 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/macro-assembler-mips.h ('k') | src/mips/regexp-macro-assembler-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698