OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_PPC_CODE_STUBS_PPC_H_ | 5 #ifndef V8_S390_CODE_STUBS_S390_H_ |
6 #define V8_PPC_CODE_STUBS_PPC_H_ | 6 #define V8_S390_CODE_STUBS_S390_H_ |
7 | 7 |
8 #include "src/ppc/frames-ppc.h" | 8 #include "src/s390/frames-s390.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 | 12 |
13 | |
14 void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code); | 13 void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code); |
15 | 14 |
16 | |
17 class StringHelper : public AllStatic { | 15 class StringHelper : public AllStatic { |
18 public: | 16 public: |
19 // Generate code for copying a large number of characters. This function | 17 // Generate code for copying a large number of characters. This function |
20 // is allowed to spend extra time setting up conditions to make copying | 18 // is allowed to spend extra time setting up conditions to make copying |
21 // faster. Copying of overlapping regions is not supported. | 19 // faster. Copying of overlapping regions is not supported. |
22 // Dest register ends at the position after the last character written. | 20 // Dest register ends at the position after the last character written. |
23 static void GenerateCopyCharacters(MacroAssembler* masm, Register dest, | 21 static void GenerateCopyCharacters(MacroAssembler* masm, Register dest, |
24 Register src, Register count, | 22 Register src, Register count, |
25 Register scratch, | 23 Register scratch, |
26 String::Encoding encoding); | 24 String::Encoding encoding); |
(...skipping 14 matching lines...) Expand all Loading... |
41 private: | 39 private: |
42 static void GenerateOneByteCharsCompareLoop(MacroAssembler* masm, | 40 static void GenerateOneByteCharsCompareLoop(MacroAssembler* masm, |
43 Register left, Register right, | 41 Register left, Register right, |
44 Register length, | 42 Register length, |
45 Register scratch1, | 43 Register scratch1, |
46 Label* chars_not_equal); | 44 Label* chars_not_equal); |
47 | 45 |
48 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper); | 46 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper); |
49 }; | 47 }; |
50 | 48 |
51 | |
52 class StoreRegistersStateStub : public PlatformCodeStub { | 49 class StoreRegistersStateStub : public PlatformCodeStub { |
53 public: | 50 public: |
54 explicit StoreRegistersStateStub(Isolate* isolate) | 51 explicit StoreRegistersStateStub(Isolate* isolate) |
55 : PlatformCodeStub(isolate) {} | 52 : PlatformCodeStub(isolate) {} |
56 | 53 |
57 static void GenerateAheadOfTime(Isolate* isolate); | 54 static void GenerateAheadOfTime(Isolate* isolate); |
58 | 55 |
59 private: | 56 private: |
60 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); | 57 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); |
61 DEFINE_PLATFORM_CODE_STUB(StoreRegistersState, PlatformCodeStub); | 58 DEFINE_PLATFORM_CODE_STUB(StoreRegistersState, PlatformCodeStub); |
62 }; | 59 }; |
63 | 60 |
64 | |
65 class RestoreRegistersStateStub : public PlatformCodeStub { | 61 class RestoreRegistersStateStub : public PlatformCodeStub { |
66 public: | 62 public: |
67 explicit RestoreRegistersStateStub(Isolate* isolate) | 63 explicit RestoreRegistersStateStub(Isolate* isolate) |
68 : PlatformCodeStub(isolate) {} | 64 : PlatformCodeStub(isolate) {} |
69 | 65 |
70 static void GenerateAheadOfTime(Isolate* isolate); | 66 static void GenerateAheadOfTime(Isolate* isolate); |
71 | 67 |
72 private: | 68 private: |
73 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); | 69 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); |
74 DEFINE_PLATFORM_CODE_STUB(RestoreRegistersState, PlatformCodeStub); | 70 DEFINE_PLATFORM_CODE_STUB(RestoreRegistersState, PlatformCodeStub); |
75 }; | 71 }; |
76 | 72 |
77 | |
78 class RecordWriteStub : public PlatformCodeStub { | 73 class RecordWriteStub : public PlatformCodeStub { |
79 public: | 74 public: |
80 RecordWriteStub(Isolate* isolate, Register object, Register value, | 75 RecordWriteStub(Isolate* isolate, Register object, Register value, |
81 Register address, RememberedSetAction remembered_set_action, | 76 Register address, RememberedSetAction remembered_set_action, |
82 SaveFPRegsMode fp_mode) | 77 SaveFPRegsMode fp_mode) |
83 : PlatformCodeStub(isolate), | 78 : PlatformCodeStub(isolate), |
84 regs_(object, // An input reg. | 79 regs_(object, // An input reg. |
85 address, // An input reg. | 80 address, // An input reg. |
86 value) { // One scratch reg. | 81 value) { // One scratch reg. |
87 minor_key_ = ObjectBits::encode(object.code()) | | 82 minor_key_ = ObjectBits::encode(object.code()) | |
88 ValueBits::encode(value.code()) | | 83 ValueBits::encode(value.code()) | |
89 AddressBits::encode(address.code()) | | 84 AddressBits::encode(address.code()) | |
90 RememberedSetActionBits::encode(remembered_set_action) | | 85 RememberedSetActionBits::encode(remembered_set_action) | |
91 SaveFPRegsModeBits::encode(fp_mode); | 86 SaveFPRegsModeBits::encode(fp_mode); |
92 } | 87 } |
93 | 88 |
94 RecordWriteStub(uint32_t key, Isolate* isolate) | 89 RecordWriteStub(uint32_t key, Isolate* isolate) |
95 : PlatformCodeStub(key, isolate), regs_(object(), address(), value()) {} | 90 : PlatformCodeStub(key, isolate), regs_(object(), address(), value()) {} |
96 | 91 |
97 enum Mode { STORE_BUFFER_ONLY, INCREMENTAL, INCREMENTAL_COMPACTION }; | 92 enum Mode { STORE_BUFFER_ONLY, INCREMENTAL, INCREMENTAL_COMPACTION }; |
98 | 93 |
99 bool SometimesSetsUpAFrame() override { return false; } | 94 bool SometimesSetsUpAFrame() override { return false; } |
100 | 95 |
101 static void PatchBranchIntoNop(MacroAssembler* masm, int pos) { | 96 // Patch an always taken branch into a NOP branch |
102 // Consider adding DCHECK here to catch bad patching | 97 static void PatchBranchCondMask(MacroAssembler* masm, int pos, Condition c) { |
103 masm->instr_at_put(pos, (masm->instr_at(pos) & ~kBOfieldMask) | BT); | 98 int32_t instrLen = masm->instr_length_at(pos); |
| 99 DCHECK(instrLen == 4 || instrLen == 6); |
| 100 |
| 101 if (instrLen == 4) { |
| 102 // BRC - Branch Mask @ Bits 23-20 |
| 103 FourByteInstr updatedMask = static_cast<FourByteInstr>(c) << 20; |
| 104 masm->instr_at_put<FourByteInstr>( |
| 105 pos, (masm->instr_at(pos) & ~kFourByteBrCondMask) | updatedMask); |
| 106 } else { |
| 107 // BRCL - Branch Mask @ Bits 39-36 |
| 108 SixByteInstr updatedMask = static_cast<SixByteInstr>(c) << 36; |
| 109 masm->instr_at_put<SixByteInstr>( |
| 110 pos, (masm->instr_at(pos) & ~kSixByteBrCondMask) | updatedMask); |
| 111 } |
104 } | 112 } |
105 | 113 |
106 static void PatchNopIntoBranch(MacroAssembler* masm, int pos) { | 114 static bool isBranchNop(SixByteInstr instr, int instrLength) { |
107 // Consider adding DCHECK here to catch bad patching | 115 if ((4 == instrLength && 0 == (instr & kFourByteBrCondMask)) || |
108 masm->instr_at_put(pos, (masm->instr_at(pos) & ~kBOfieldMask) | BF); | 116 // BRC - Check for 0x0 mask condition. |
| 117 (6 == instrLength && 0 == (instr & kSixByteBrCondMask))) { |
| 118 // BRCL - Check for 0x0 mask condition |
| 119 return true; |
| 120 } |
| 121 return false; |
109 } | 122 } |
110 | 123 |
111 static Mode GetMode(Code* stub) { | 124 static Mode GetMode(Code* stub) { |
112 Instr first_instruction = | 125 int32_t first_instr_length = |
113 Assembler::instr_at(stub->instruction_start() + Assembler::kInstrSize); | 126 Instruction::InstructionLength(stub->instruction_start()); |
114 Instr second_instruction = Assembler::instr_at(stub->instruction_start() + | 127 int32_t second_instr_length = Instruction::InstructionLength( |
115 (Assembler::kInstrSize * 2)); | 128 stub->instruction_start() + first_instr_length); |
116 | 129 |
117 // Consider adding DCHECK here to catch unexpected instruction sequence | 130 uint64_t first_instr = Assembler::instr_at(stub->instruction_start()); |
118 if (BF == (first_instruction & kBOfieldMask)) { | 131 uint64_t second_instr = |
| 132 Assembler::instr_at(stub->instruction_start() + first_instr_length); |
| 133 |
| 134 DCHECK(first_instr_length == 4 || first_instr_length == 6); |
| 135 DCHECK(second_instr_length == 4 || second_instr_length == 6); |
| 136 |
| 137 bool isFirstInstrNOP = isBranchNop(first_instr, first_instr_length); |
| 138 bool isSecondInstrNOP = isBranchNop(second_instr, second_instr_length); |
| 139 |
| 140 // STORE_BUFFER_ONLY has NOP on both branches |
| 141 if (isSecondInstrNOP && isFirstInstrNOP) return STORE_BUFFER_ONLY; |
| 142 // INCREMENTAL_COMPACTION has NOP on second branch. |
| 143 else if (isFirstInstrNOP && !isSecondInstrNOP) |
| 144 return INCREMENTAL_COMPACTION; |
| 145 // INCREMENTAL has NOP on first branch. |
| 146 else if (!isFirstInstrNOP && isSecondInstrNOP) |
119 return INCREMENTAL; | 147 return INCREMENTAL; |
120 } | |
121 | 148 |
122 if (BF == (second_instruction & kBOfieldMask)) { | 149 DCHECK(false); |
123 return INCREMENTAL_COMPACTION; | |
124 } | |
125 | |
126 return STORE_BUFFER_ONLY; | 150 return STORE_BUFFER_ONLY; |
127 } | 151 } |
128 | 152 |
129 static void Patch(Code* stub, Mode mode) { | 153 static void Patch(Code* stub, Mode mode) { |
130 MacroAssembler masm(stub->GetIsolate(), stub->instruction_start(), | 154 MacroAssembler masm(stub->GetIsolate(), stub->instruction_start(), |
131 stub->instruction_size(), CodeObjectRequired::kNo); | 155 stub->instruction_size(), CodeObjectRequired::kNo); |
| 156 |
| 157 // Get instruction lengths of two branches |
| 158 int32_t first_instr_length = masm.instr_length_at(0); |
| 159 int32_t second_instr_length = masm.instr_length_at(first_instr_length); |
| 160 |
132 switch (mode) { | 161 switch (mode) { |
133 case STORE_BUFFER_ONLY: | 162 case STORE_BUFFER_ONLY: |
134 DCHECK(GetMode(stub) == INCREMENTAL || | 163 DCHECK(GetMode(stub) == INCREMENTAL || |
135 GetMode(stub) == INCREMENTAL_COMPACTION); | 164 GetMode(stub) == INCREMENTAL_COMPACTION); |
136 | 165 |
137 PatchBranchIntoNop(&masm, Assembler::kInstrSize); | 166 PatchBranchCondMask(&masm, 0, CC_NOP); |
138 PatchBranchIntoNop(&masm, Assembler::kInstrSize * 2); | 167 PatchBranchCondMask(&masm, first_instr_length, CC_NOP); |
139 break; | 168 break; |
140 case INCREMENTAL: | 169 case INCREMENTAL: |
141 DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); | 170 DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); |
142 PatchNopIntoBranch(&masm, Assembler::kInstrSize); | 171 PatchBranchCondMask(&masm, 0, CC_ALWAYS); |
143 break; | 172 break; |
144 case INCREMENTAL_COMPACTION: | 173 case INCREMENTAL_COMPACTION: |
145 DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); | 174 DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); |
146 PatchNopIntoBranch(&masm, Assembler::kInstrSize * 2); | 175 PatchBranchCondMask(&masm, first_instr_length, CC_ALWAYS); |
147 break; | 176 break; |
148 } | 177 } |
149 DCHECK(GetMode(stub) == mode); | 178 DCHECK(GetMode(stub) == mode); |
150 Assembler::FlushICache(stub->GetIsolate(), | 179 Assembler::FlushICache(stub->GetIsolate(), stub->instruction_start(), |
151 stub->instruction_start() + Assembler::kInstrSize, | 180 first_instr_length + second_instr_length); |
152 2 * Assembler::kInstrSize); | |
153 } | 181 } |
154 | 182 |
155 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); | 183 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); |
156 | 184 |
157 private: | 185 private: |
158 // This is a helper class for freeing up 3 scratch registers. The input is | 186 // This is a helper class for freeing up 3 scratch registers. The input is |
159 // two registers that must be preserved and one scratch register provided by | 187 // two registers that must be preserved and one scratch register provided by |
160 // the caller. | 188 // the caller. |
161 class RegisterAllocation { | 189 class RegisterAllocation { |
162 public: | 190 public: |
163 RegisterAllocation(Register object, Register address, Register scratch0) | 191 RegisterAllocation(Register object, Register address, Register scratch0) |
164 : object_(object), address_(address), scratch0_(scratch0) { | 192 : object_(object), address_(address), scratch0_(scratch0) { |
165 DCHECK(!AreAliased(scratch0, object, address, no_reg)); | 193 DCHECK(!AreAliased(scratch0, object, address, no_reg)); |
166 scratch1_ = GetRegisterThatIsNotOneOf(object_, address_, scratch0_); | 194 scratch1_ = GetRegisterThatIsNotOneOf(object_, address_, scratch0_); |
167 } | 195 } |
168 | 196 |
169 void Save(MacroAssembler* masm) { | 197 void Save(MacroAssembler* masm) { |
170 DCHECK(!AreAliased(object_, address_, scratch1_, scratch0_)); | 198 DCHECK(!AreAliased(object_, address_, scratch1_, scratch0_)); |
171 // We don't have to save scratch0_ because it was given to us as | 199 // We don't have to save scratch0_ because it was given to us as |
172 // a scratch register. | 200 // a scratch register. |
173 masm->push(scratch1_); | 201 masm->push(scratch1_); |
174 } | 202 } |
175 | 203 |
176 void Restore(MacroAssembler* masm) { masm->pop(scratch1_); } | 204 void Restore(MacroAssembler* masm) { masm->pop(scratch1_); } |
177 | 205 |
178 // If we have to call into C then we need to save and restore all caller- | 206 // If we have to call into C then we need to save and restore all caller- |
179 // saved registers that were not already preserved. The scratch registers | 207 // saved registers that were not already preserved. The scratch registers |
180 // will be restored by other means so we don't bother pushing them here. | 208 // will be restored by other means so we don't bother pushing them here. |
181 void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) { | 209 void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) { |
182 masm->mflr(r0); | 210 masm->push(r14); |
183 masm->push(r0); | |
184 masm->MultiPush(kJSCallerSaved & ~scratch1_.bit()); | 211 masm->MultiPush(kJSCallerSaved & ~scratch1_.bit()); |
185 if (mode == kSaveFPRegs) { | 212 if (mode == kSaveFPRegs) { |
186 // Save all volatile FP registers except d0. | 213 // Save all volatile FP registers except d0. |
187 masm->MultiPushDoubles(kCallerSavedDoubles & ~d0.bit()); | 214 masm->MultiPushDoubles(kCallerSavedDoubles & ~d0.bit()); |
188 } | 215 } |
189 } | 216 } |
190 | 217 |
191 inline void RestoreCallerSaveRegisters(MacroAssembler* masm, | 218 inline void RestoreCallerSaveRegisters(MacroAssembler* masm, |
192 SaveFPRegsMode mode) { | 219 SaveFPRegsMode mode) { |
193 if (mode == kSaveFPRegs) { | 220 if (mode == kSaveFPRegs) { |
194 // Restore all volatile FP registers except d0. | 221 // Restore all volatile FP registers except d0. |
195 masm->MultiPopDoubles(kCallerSavedDoubles & ~d0.bit()); | 222 masm->MultiPopDoubles(kCallerSavedDoubles & ~d0.bit()); |
196 } | 223 } |
197 masm->MultiPop(kJSCallerSaved & ~scratch1_.bit()); | 224 masm->MultiPop(kJSCallerSaved & ~scratch1_.bit()); |
198 masm->pop(r0); | 225 masm->pop(r14); |
199 masm->mtlr(r0); | |
200 } | 226 } |
201 | 227 |
202 inline Register object() { return object_; } | 228 inline Register object() { return object_; } |
203 inline Register address() { return address_; } | 229 inline Register address() { return address_; } |
204 inline Register scratch0() { return scratch0_; } | 230 inline Register scratch0() { return scratch0_; } |
205 inline Register scratch1() { return scratch1_; } | 231 inline Register scratch1() { return scratch1_; } |
206 | 232 |
207 private: | 233 private: |
208 Register object_; | 234 Register object_; |
209 Register address_; | 235 Register address_; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 } | 270 } |
245 | 271 |
246 RememberedSetAction remembered_set_action() const { | 272 RememberedSetAction remembered_set_action() const { |
247 return RememberedSetActionBits::decode(minor_key_); | 273 return RememberedSetActionBits::decode(minor_key_); |
248 } | 274 } |
249 | 275 |
250 SaveFPRegsMode save_fp_regs_mode() const { | 276 SaveFPRegsMode save_fp_regs_mode() const { |
251 return SaveFPRegsModeBits::decode(minor_key_); | 277 return SaveFPRegsModeBits::decode(minor_key_); |
252 } | 278 } |
253 | 279 |
254 class ObjectBits : public BitField<int, 0, 5> {}; | 280 class ObjectBits : public BitField<int, 0, 4> {}; |
255 class ValueBits : public BitField<int, 5, 5> {}; | 281 class ValueBits : public BitField<int, 4, 4> {}; |
256 class AddressBits : public BitField<int, 10, 5> {}; | 282 class AddressBits : public BitField<int, 8, 4> {}; |
257 class RememberedSetActionBits : public BitField<RememberedSetAction, 15, 1> { | 283 class RememberedSetActionBits : public BitField<RememberedSetAction, 15, 1> { |
258 }; | 284 }; |
259 class SaveFPRegsModeBits : public BitField<SaveFPRegsMode, 16, 1> {}; | 285 class SaveFPRegsModeBits : public BitField<SaveFPRegsMode, 16, 1> {}; |
260 | 286 |
261 Label slow_; | 287 Label slow_; |
262 RegisterAllocation regs_; | 288 RegisterAllocation regs_; |
263 | 289 |
264 DISALLOW_COPY_AND_ASSIGN(RecordWriteStub); | 290 DISALLOW_COPY_AND_ASSIGN(RecordWriteStub); |
265 }; | 291 }; |
266 | 292 |
267 | |
268 // Trampoline stub to call into native code. To call safely into native code | 293 // Trampoline stub to call into native code. To call safely into native code |
269 // in the presence of compacting GC (which can move code objects) we need to | 294 // in the presence of compacting GC (which can move code objects) we need to |
270 // keep the code which called into native pinned in the memory. Currently the | 295 // keep the code which called into native pinned in the memory. Currently the |
271 // simplest approach is to generate such stub early enough so it can never be | 296 // simplest approach is to generate such stub early enough so it can never be |
272 // moved by GC | 297 // moved by GC |
273 class DirectCEntryStub : public PlatformCodeStub { | 298 class DirectCEntryStub : public PlatformCodeStub { |
274 public: | 299 public: |
275 explicit DirectCEntryStub(Isolate* isolate) : PlatformCodeStub(isolate) {} | 300 explicit DirectCEntryStub(Isolate* isolate) : PlatformCodeStub(isolate) {} |
276 void GenerateCall(MacroAssembler* masm, Register target); | 301 void GenerateCall(MacroAssembler* masm, Register target); |
277 | 302 |
278 private: | 303 private: |
279 bool NeedsImmovableCode() override { return true; } | 304 bool NeedsImmovableCode() override { return true; } |
280 | 305 |
281 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); | 306 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); |
282 DEFINE_PLATFORM_CODE_STUB(DirectCEntry, PlatformCodeStub); | 307 DEFINE_PLATFORM_CODE_STUB(DirectCEntry, PlatformCodeStub); |
283 }; | 308 }; |
284 | 309 |
285 | |
286 class NameDictionaryLookupStub : public PlatformCodeStub { | 310 class NameDictionaryLookupStub : public PlatformCodeStub { |
287 public: | 311 public: |
288 enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP }; | 312 enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP }; |
289 | 313 |
290 NameDictionaryLookupStub(Isolate* isolate, LookupMode mode) | 314 NameDictionaryLookupStub(Isolate* isolate, LookupMode mode) |
291 : PlatformCodeStub(isolate) { | 315 : PlatformCodeStub(isolate) { |
292 minor_key_ = LookupModeBits::encode(mode); | 316 minor_key_ = LookupModeBits::encode(mode); |
293 } | 317 } |
294 | 318 |
295 static void GenerateNegativeLookup(MacroAssembler* masm, Label* miss, | 319 static void GenerateNegativeLookup(MacroAssembler* masm, Label* miss, |
(...skipping 19 matching lines...) Expand all Loading... |
315 NameDictionary::kHeaderSize + | 339 NameDictionary::kHeaderSize + |
316 NameDictionary::kElementsStartIndex * kPointerSize; | 340 NameDictionary::kElementsStartIndex * kPointerSize; |
317 | 341 |
318 LookupMode mode() const { return LookupModeBits::decode(minor_key_); } | 342 LookupMode mode() const { return LookupModeBits::decode(minor_key_); } |
319 | 343 |
320 class LookupModeBits : public BitField<LookupMode, 0, 1> {}; | 344 class LookupModeBits : public BitField<LookupMode, 0, 1> {}; |
321 | 345 |
322 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); | 346 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); |
323 DEFINE_PLATFORM_CODE_STUB(NameDictionaryLookup, PlatformCodeStub); | 347 DEFINE_PLATFORM_CODE_STUB(NameDictionaryLookup, PlatformCodeStub); |
324 }; | 348 }; |
| 349 |
| 350 class FloatingPointHelper : public AllStatic { |
| 351 public: |
| 352 enum Destination { kFPRegisters, kCoreRegisters }; |
| 353 |
| 354 // Loads smis from r0 and r1 (right and left in binary operations) into |
| 355 // floating point registers. Depending on the destination the values ends up |
| 356 // either d7 and d6 or in r2/r3 and r0/r1 respectively. If the destination is |
| 357 // floating point registers VFP3 must be supported. If core registers are |
| 358 // requested when VFP3 is supported d6 and d7 will be scratched. |
| 359 static void LoadSmis(MacroAssembler* masm, Register scratch1, |
| 360 Register scratch2); |
| 361 |
| 362 // Loads objects from r0 and r1 (right and left in binary operations) into |
| 363 // floating point registers. Depending on the destination the values ends up |
| 364 // either d7 and d6 or in r2/r3 and r0/r1 respectively. If the destination is |
| 365 // floating point registers VFP3 must be supported. If core registers are |
| 366 // requested when VFP3 is supported d6 and d7 will still be scratched. If |
| 367 // either r0 or r1 is not a number (not smi and not heap number object) the |
| 368 // not_number label is jumped to with r0 and r1 intact. |
| 369 static void LoadOperands(MacroAssembler* masm, Register heap_number_map, |
| 370 Register scratch1, Register scratch2, |
| 371 Label* not_number); |
| 372 |
| 373 // Convert the smi or heap number in object to an int32 using the rules |
| 374 // for ToInt32 as described in ECMAScript 9.5.: the value is truncated |
| 375 // and brought into the range -2^31 .. +2^31 - 1. |
| 376 static void ConvertNumberToInt32(MacroAssembler* masm, Register object, |
| 377 Register dst, Register heap_number_map, |
| 378 Register scratch1, Register scratch2, |
| 379 Register scratch3, |
| 380 DoubleRegister double_scratch, |
| 381 Label* not_int32); |
| 382 |
| 383 // Converts the integer (untagged smi) in |src| to a double, storing |
| 384 // the result to |double_dst| |
| 385 static void ConvertIntToDouble(MacroAssembler* masm, Register src, |
| 386 DoubleRegister double_dst); |
| 387 |
| 388 // Converts the unsigned integer (untagged smi) in |src| to |
| 389 // a double, storing the result to |double_dst| |
| 390 static void ConvertUnsignedIntToDouble(MacroAssembler* masm, Register src, |
| 391 DoubleRegister double_dst); |
| 392 |
| 393 // Converts the integer (untagged smi) in |src| to |
| 394 // a float, storing the result in |dst| |
| 395 static void ConvertIntToFloat(MacroAssembler* masm, const DoubleRegister dst, |
| 396 const Register src); |
| 397 |
| 398 // Load the number from object into double_dst in the double format. |
| 399 // Control will jump to not_int32 if the value cannot be exactly represented |
| 400 // by a 32-bit integer. |
| 401 // Floating point value in the 32-bit integer range that are not exact integer |
| 402 // won't be loaded. |
| 403 static void LoadNumberAsInt32Double(MacroAssembler* masm, Register object, |
| 404 DoubleRegister double_dst, |
| 405 DoubleRegister double_scratch, |
| 406 Register heap_number_map, |
| 407 Register scratch1, Register scratch2, |
| 408 Label* not_int32); |
| 409 |
| 410 // Loads the number from object into dst as a 32-bit integer. |
| 411 // Control will jump to not_int32 if the object cannot be exactly represented |
| 412 // by a 32-bit integer. |
| 413 // Floating point value in the 32-bit integer range that are not exact integer |
| 414 // won't be converted. |
| 415 // scratch3 is not used when VFP3 is supported. |
| 416 static void LoadNumberAsInt32(MacroAssembler* masm, Register object, |
| 417 Register dst, Register heap_number_map, |
| 418 Register scratch1, Register scratch2, |
| 419 Register scratch3, |
| 420 DoubleRegister double_scratch0, |
| 421 DoubleRegister double_scratch1, |
| 422 Label* not_int32); |
| 423 |
| 424 // Generate non VFP3 code to check if a double can be exactly represented by a |
| 425 // 32-bit integer. This does not check for 0 or -0, which need |
| 426 // to be checked for separately. |
| 427 // Control jumps to not_int32 if the value is not a 32-bit integer, and falls |
| 428 // through otherwise. |
| 429 // src1 and src2 will be cloberred. |
| 430 // |
| 431 // Expected input: |
| 432 // - src1: higher (exponent) part of the double value. |
| 433 // - src2: lower (mantissa) part of the double value. |
| 434 // Output status: |
| 435 // - dst: 32 higher bits of the mantissa. (mantissa[51:20]) |
| 436 // - src2: contains 1. |
| 437 // - other registers are clobbered. |
| 438 static void DoubleIs32BitInteger(MacroAssembler* masm, Register src1, |
| 439 Register src2, Register dst, |
| 440 Register scratch, Label* not_int32); |
| 441 |
| 442 // Generates code to call a C function to do a double operation using core |
| 443 // registers. (Used when VFP3 is not supported.) |
| 444 // This code never falls through, but returns with a heap number containing |
| 445 // the result in r0. |
| 446 // Register heapnumber_result must be a heap number in which the |
| 447 // result of the operation will be stored. |
| 448 // Requires the following layout on entry: |
| 449 // r0: Left value (least significant part of mantissa). |
| 450 // r1: Left value (sign, exponent, top of mantissa). |
| 451 // r2: Right value (least significant part of mantissa). |
| 452 // r3: Right value (sign, exponent, top of mantissa). |
| 453 static void CallCCodeForDoubleOperation(MacroAssembler* masm, Token::Value op, |
| 454 Register heap_number_result, |
| 455 Register scratch); |
| 456 |
| 457 private: |
| 458 static void LoadNumber(MacroAssembler* masm, Register object, |
| 459 DoubleRegister dst, Register heap_number_map, |
| 460 Register scratch1, Register scratch2, |
| 461 Label* not_number); |
| 462 }; |
| 463 |
325 } // namespace internal | 464 } // namespace internal |
326 } // namespace v8 | 465 } // namespace v8 |
327 | 466 |
328 #endif // V8_PPC_CODE_STUBS_PPC_H_ | 467 #endif // V8_S390_CODE_STUBS_S390_H_ |
OLD | NEW |