OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
11 #include "src/compiler/osr.h" | 11 #include "src/compiler/osr.h" |
12 #include "src/ppc/macro-assembler-ppc.h" | 12 #include "src/s390/macro-assembler-s390.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 namespace compiler { | 16 namespace compiler { |
17 | 17 |
18 #define __ masm()-> | 18 #define __ masm()-> |
19 | 19 |
| 20 #define kScratchReg ip |
20 | 21 |
21 #define kScratchReg r11 | 22 // Adds S390-specific methods to convert InstructionOperands. |
22 | 23 class S390OperandConverter final : public InstructionOperandConverter { |
23 | |
24 // Adds PPC-specific methods to convert InstructionOperands. | |
25 class PPCOperandConverter final : public InstructionOperandConverter { | |
26 public: | 24 public: |
27 PPCOperandConverter(CodeGenerator* gen, Instruction* instr) | 25 S390OperandConverter(CodeGenerator* gen, Instruction* instr) |
28 : InstructionOperandConverter(gen, instr) {} | 26 : InstructionOperandConverter(gen, instr) {} |
29 | 27 |
30 size_t OutputCount() { return instr_->OutputCount(); } | 28 size_t OutputCount() { return instr_->OutputCount(); } |
31 | 29 |
32 RCBit OutputRCBit() const { | |
33 switch (instr_->flags_mode()) { | |
34 case kFlags_branch: | |
35 case kFlags_deoptimize: | |
36 case kFlags_set: | |
37 return SetRC; | |
38 case kFlags_none: | |
39 return LeaveRC; | |
40 } | |
41 UNREACHABLE(); | |
42 return LeaveRC; | |
43 } | |
44 | |
45 bool CompareLogical() const { | 30 bool CompareLogical() const { |
46 switch (instr_->flags_condition()) { | 31 switch (instr_->flags_condition()) { |
47 case kUnsignedLessThan: | 32 case kUnsignedLessThan: |
48 case kUnsignedGreaterThanOrEqual: | 33 case kUnsignedGreaterThanOrEqual: |
49 case kUnsignedLessThanOrEqual: | 34 case kUnsignedLessThanOrEqual: |
50 case kUnsignedGreaterThan: | 35 case kUnsignedGreaterThan: |
51 return true; | 36 return true; |
52 default: | 37 default: |
53 return false; | 38 return false; |
54 } | 39 } |
55 UNREACHABLE(); | 40 UNREACHABLE(); |
56 return false; | 41 return false; |
57 } | 42 } |
58 | 43 |
59 Operand InputImmediate(size_t index) { | 44 Operand InputImmediate(size_t index) { |
60 Constant constant = ToConstant(instr_->InputAt(index)); | 45 Constant constant = ToConstant(instr_->InputAt(index)); |
61 switch (constant.type()) { | 46 switch (constant.type()) { |
62 case Constant::kInt32: | 47 case Constant::kInt32: |
63 return Operand(constant.ToInt32()); | 48 return Operand(constant.ToInt32()); |
64 case Constant::kFloat32: | 49 case Constant::kFloat32: |
65 return Operand( | 50 return Operand( |
66 isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED)); | 51 isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED)); |
67 case Constant::kFloat64: | 52 case Constant::kFloat64: |
68 return Operand( | 53 return Operand( |
69 isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED)); | 54 isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED)); |
70 case Constant::kInt64: | 55 case Constant::kInt64: |
71 #if V8_TARGET_ARCH_PPC64 | 56 #if V8_TARGET_ARCH_S390X |
72 return Operand(constant.ToInt64()); | 57 return Operand(constant.ToInt64()); |
73 #endif | 58 #endif |
74 case Constant::kExternalReference: | 59 case Constant::kExternalReference: |
75 case Constant::kHeapObject: | 60 case Constant::kHeapObject: |
76 case Constant::kRpoNumber: | 61 case Constant::kRpoNumber: |
77 break; | 62 break; |
78 } | 63 } |
79 UNREACHABLE(); | 64 UNREACHABLE(); |
80 return Operand::Zero(); | 65 return Operand::Zero(); |
81 } | 66 } |
(...skipping 21 matching lines...) Expand all Loading... |
103 | 88 |
104 MemOperand ToMemOperand(InstructionOperand* op) const { | 89 MemOperand ToMemOperand(InstructionOperand* op) const { |
105 DCHECK_NOT_NULL(op); | 90 DCHECK_NOT_NULL(op); |
106 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); | 91 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); |
107 FrameOffset offset = frame_access_state()->GetFrameOffset( | 92 FrameOffset offset = frame_access_state()->GetFrameOffset( |
108 AllocatedOperand::cast(op)->index()); | 93 AllocatedOperand::cast(op)->index()); |
109 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); | 94 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); |
110 } | 95 } |
111 }; | 96 }; |
112 | 97 |
113 | 98 static inline bool HasRegisterInput(Instruction* instr, int index) { |
114 static inline bool HasRegisterInput(Instruction* instr, size_t index) { | |
115 return instr->InputAt(index)->IsRegister(); | 99 return instr->InputAt(index)->IsRegister(); |
116 } | 100 } |
117 | 101 |
118 | |
119 namespace { | 102 namespace { |
120 | 103 |
121 class OutOfLineLoadNAN32 final : public OutOfLineCode { | 104 class OutOfLineLoadNAN32 final : public OutOfLineCode { |
122 public: | 105 public: |
123 OutOfLineLoadNAN32(CodeGenerator* gen, DoubleRegister result) | 106 OutOfLineLoadNAN32(CodeGenerator* gen, DoubleRegister result) |
124 : OutOfLineCode(gen), result_(result) {} | 107 : OutOfLineCode(gen), result_(result) {} |
125 | 108 |
126 void Generate() final { | 109 void Generate() final { |
127 __ LoadDoubleLiteral(result_, std::numeric_limits<float>::quiet_NaN(), | 110 __ LoadDoubleLiteral(result_, std::numeric_limits<float>::quiet_NaN(), |
128 kScratchReg); | 111 kScratchReg); |
129 } | 112 } |
130 | 113 |
131 private: | 114 private: |
132 DoubleRegister const result_; | 115 DoubleRegister const result_; |
133 }; | 116 }; |
134 | 117 |
135 | |
136 class OutOfLineLoadNAN64 final : public OutOfLineCode { | 118 class OutOfLineLoadNAN64 final : public OutOfLineCode { |
137 public: | 119 public: |
138 OutOfLineLoadNAN64(CodeGenerator* gen, DoubleRegister result) | 120 OutOfLineLoadNAN64(CodeGenerator* gen, DoubleRegister result) |
139 : OutOfLineCode(gen), result_(result) {} | 121 : OutOfLineCode(gen), result_(result) {} |
140 | 122 |
141 void Generate() final { | 123 void Generate() final { |
142 __ LoadDoubleLiteral(result_, std::numeric_limits<double>::quiet_NaN(), | 124 __ LoadDoubleLiteral(result_, std::numeric_limits<double>::quiet_NaN(), |
143 kScratchReg); | 125 kScratchReg); |
144 } | 126 } |
145 | 127 |
146 private: | 128 private: |
147 DoubleRegister const result_; | 129 DoubleRegister const result_; |
148 }; | 130 }; |
149 | 131 |
150 | |
151 class OutOfLineLoadZero final : public OutOfLineCode { | 132 class OutOfLineLoadZero final : public OutOfLineCode { |
152 public: | 133 public: |
153 OutOfLineLoadZero(CodeGenerator* gen, Register result) | 134 OutOfLineLoadZero(CodeGenerator* gen, Register result) |
154 : OutOfLineCode(gen), result_(result) {} | 135 : OutOfLineCode(gen), result_(result) {} |
155 | 136 |
156 void Generate() final { __ li(result_, Operand::Zero()); } | 137 void Generate() final { __ LoadImmP(result_, Operand::Zero()); } |
157 | 138 |
158 private: | 139 private: |
159 Register const result_; | 140 Register const result_; |
160 }; | 141 }; |
161 | 142 |
162 | |
163 class OutOfLineRecordWrite final : public OutOfLineCode { | 143 class OutOfLineRecordWrite final : public OutOfLineCode { |
164 public: | 144 public: |
165 OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register offset, | 145 OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register offset, |
166 Register value, Register scratch0, Register scratch1, | 146 Register value, Register scratch0, Register scratch1, |
167 RecordWriteMode mode) | 147 RecordWriteMode mode) |
168 : OutOfLineCode(gen), | 148 : OutOfLineCode(gen), |
169 object_(object), | 149 object_(object), |
170 offset_(offset), | 150 offset_(offset), |
171 offset_immediate_(0), | 151 offset_immediate_(0), |
172 value_(value), | 152 value_(value), |
(...skipping 19 matching lines...) Expand all Loading... |
192 } | 172 } |
193 __ CheckPageFlag(value_, scratch0_, | 173 __ CheckPageFlag(value_, scratch0_, |
194 MemoryChunk::kPointersToHereAreInterestingMask, eq, | 174 MemoryChunk::kPointersToHereAreInterestingMask, eq, |
195 exit()); | 175 exit()); |
196 RememberedSetAction const remembered_set_action = | 176 RememberedSetAction const remembered_set_action = |
197 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET | 177 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET |
198 : OMIT_REMEMBERED_SET; | 178 : OMIT_REMEMBERED_SET; |
199 SaveFPRegsMode const save_fp_mode = | 179 SaveFPRegsMode const save_fp_mode = |
200 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; | 180 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; |
201 if (!frame()->needs_frame()) { | 181 if (!frame()->needs_frame()) { |
202 // We need to save and restore lr if the frame was elided. | 182 // We need to save and restore r14 if the frame was elided. |
203 __ mflr(scratch1_); | 183 __ Push(r14); |
204 __ Push(scratch1_); | |
205 } | 184 } |
206 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_, | 185 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_, |
207 remembered_set_action, save_fp_mode); | 186 remembered_set_action, save_fp_mode); |
208 if (offset_.is(no_reg)) { | 187 if (offset_.is(no_reg)) { |
209 __ addi(scratch1_, object_, Operand(offset_immediate_)); | 188 __ AddP(scratch1_, object_, Operand(offset_immediate_)); |
210 } else { | 189 } else { |
211 DCHECK_EQ(0, offset_immediate_); | 190 DCHECK_EQ(0, offset_immediate_); |
212 __ add(scratch1_, object_, offset_); | 191 __ AddP(scratch1_, object_, offset_); |
213 } | 192 } |
214 __ CallStub(&stub); | 193 __ CallStub(&stub); |
215 if (!frame()->needs_frame()) { | 194 if (!frame()->needs_frame()) { |
216 // We need to save and restore lr if the frame was elided. | 195 // We need to save and restore r14 if the frame was elided. |
217 __ Pop(scratch1_); | 196 __ Pop(r14); |
218 __ mtlr(scratch1_); | |
219 } | 197 } |
220 } | 198 } |
221 | 199 |
222 private: | 200 private: |
223 Register const object_; | 201 Register const object_; |
224 Register const offset_; | 202 Register const offset_; |
225 int32_t const offset_immediate_; // Valid if offset_.is(no_reg). | 203 int32_t const offset_immediate_; // Valid if offset_.is(no_reg). |
226 Register const value_; | 204 Register const value_; |
227 Register const scratch0_; | 205 Register const scratch0_; |
228 Register const scratch1_; | 206 Register const scratch1_; |
229 RecordWriteMode const mode_; | 207 RecordWriteMode const mode_; |
230 }; | 208 }; |
231 | 209 |
232 | |
233 Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) { | 210 Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) { |
234 switch (condition) { | 211 switch (condition) { |
235 case kEqual: | 212 case kEqual: |
236 return eq; | 213 return eq; |
237 case kNotEqual: | 214 case kNotEqual: |
238 return ne; | 215 return ne; |
239 case kSignedLessThan: | 216 case kSignedLessThan: |
240 case kUnsignedLessThan: | 217 case kUnsignedLessThan: |
241 return lt; | 218 return lt; |
242 case kSignedGreaterThanOrEqual: | 219 case kSignedGreaterThanOrEqual: |
243 case kUnsignedGreaterThanOrEqual: | 220 case kUnsignedGreaterThanOrEqual: |
244 return ge; | 221 return ge; |
245 case kSignedLessThanOrEqual: | 222 case kSignedLessThanOrEqual: |
246 case kUnsignedLessThanOrEqual: | 223 case kUnsignedLessThanOrEqual: |
247 return le; | 224 return le; |
248 case kSignedGreaterThan: | 225 case kSignedGreaterThan: |
249 case kUnsignedGreaterThan: | 226 case kUnsignedGreaterThan: |
250 return gt; | 227 return gt; |
251 case kOverflow: | 228 case kOverflow: |
252 // Overflow checked for add/sub only. | 229 // Overflow checked for AddP/SubP only. |
253 switch (op) { | 230 switch (op) { |
254 #if V8_TARGET_ARCH_PPC64 | 231 #if V8_TARGET_ARCH_S390X |
255 case kPPC_Add: | 232 case kS390_Add: |
256 case kPPC_Sub: | 233 case kS390_Sub: |
257 return lt; | 234 return lt; |
258 #endif | 235 #endif |
259 case kPPC_AddWithOverflow32: | 236 case kS390_AddWithOverflow32: |
260 case kPPC_SubWithOverflow32: | 237 case kS390_SubWithOverflow32: |
261 #if V8_TARGET_ARCH_PPC64 | 238 #if V8_TARGET_ARCH_S390X |
262 return ne; | 239 return ne; |
263 #else | 240 #else |
264 return lt; | 241 return lt; |
265 #endif | 242 #endif |
266 default: | 243 default: |
267 break; | 244 break; |
268 } | 245 } |
269 break; | 246 break; |
270 case kNotOverflow: | 247 case kNotOverflow: |
271 switch (op) { | 248 switch (op) { |
272 #if V8_TARGET_ARCH_PPC64 | 249 #if V8_TARGET_ARCH_S390X |
273 case kPPC_Add: | 250 case kS390_Add: |
274 case kPPC_Sub: | 251 case kS390_Sub: |
275 return ge; | 252 return ge; |
276 #endif | 253 #endif |
277 case kPPC_AddWithOverflow32: | 254 case kS390_AddWithOverflow32: |
278 case kPPC_SubWithOverflow32: | 255 case kS390_SubWithOverflow32: |
279 #if V8_TARGET_ARCH_PPC64 | 256 #if V8_TARGET_ARCH_S390X |
280 return eq; | 257 return eq; |
281 #else | 258 #else |
282 return ge; | 259 return ge; |
283 #endif | 260 #endif |
284 default: | 261 default: |
285 break; | 262 break; |
286 } | 263 } |
287 break; | 264 break; |
288 default: | 265 default: |
289 break; | 266 break; |
290 } | 267 } |
291 UNREACHABLE(); | 268 UNREACHABLE(); |
292 return kNoCondition; | 269 return kNoCondition; |
293 } | 270 } |
294 | 271 |
295 } // namespace | 272 } // namespace |
296 | 273 |
297 #define ASSEMBLE_FLOAT_UNOP_RC(asm_instr) \ | 274 #define ASSEMBLE_FLOAT_UNOP(asm_instr) \ |
| 275 do { \ |
| 276 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ |
| 277 } while (0) |
| 278 |
| 279 #define ASSEMBLE_FLOAT_BINOP(asm_instr) \ |
298 do { \ | 280 do { \ |
299 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ | 281 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ |
300 i.OutputRCBit()); \ | 282 i.InputDoubleRegister(1)); \ |
301 } while (0) | 283 } while (0) |
302 | 284 |
303 | |
304 #define ASSEMBLE_FLOAT_BINOP_RC(asm_instr) \ | |
305 do { \ | |
306 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ | |
307 i.InputDoubleRegister(1), i.OutputRCBit()); \ | |
308 } while (0) | |
309 | |
310 | |
311 #define ASSEMBLE_BINOP(asm_instr_reg, asm_instr_imm) \ | 285 #define ASSEMBLE_BINOP(asm_instr_reg, asm_instr_imm) \ |
312 do { \ | 286 do { \ |
313 if (HasRegisterInput(instr, 1)) { \ | 287 if (HasRegisterInput(instr, 1)) { \ |
314 __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \ | 288 __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \ |
315 i.InputRegister(1)); \ | 289 i.InputRegister(1)); \ |
316 } else { \ | 290 } else { \ |
317 __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \ | 291 __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \ |
318 i.InputImmediate(1)); \ | 292 i.InputImmediate(1)); \ |
319 } \ | 293 } \ |
320 } while (0) | 294 } while (0) |
321 | 295 |
322 | 296 #define ASSEMBLE_BINOP_INT(asm_instr_reg, asm_instr_imm) \ |
323 #define ASSEMBLE_BINOP_RC(asm_instr_reg, asm_instr_imm) \ | |
324 do { \ | 297 do { \ |
325 if (HasRegisterInput(instr, 1)) { \ | 298 if (HasRegisterInput(instr, 1)) { \ |
326 __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \ | 299 __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \ |
327 i.InputRegister(1), i.OutputRCBit()); \ | 300 i.InputRegister(1)); \ |
328 } else { \ | 301 } else { \ |
329 __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \ | 302 __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \ |
330 i.InputImmediate(1), i.OutputRCBit()); \ | 303 i.InputInt32(1)); \ |
331 } \ | 304 } \ |
332 } while (0) | 305 } while (0) |
333 | 306 |
334 | |
335 #define ASSEMBLE_BINOP_INT_RC(asm_instr_reg, asm_instr_imm) \ | |
336 do { \ | |
337 if (HasRegisterInput(instr, 1)) { \ | |
338 __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \ | |
339 i.InputRegister(1), i.OutputRCBit()); \ | |
340 } else { \ | |
341 __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \ | |
342 i.InputInt32(1), i.OutputRCBit()); \ | |
343 } \ | |
344 } while (0) | |
345 | |
346 | |
347 #define ASSEMBLE_ADD_WITH_OVERFLOW() \ | 307 #define ASSEMBLE_ADD_WITH_OVERFLOW() \ |
348 do { \ | 308 do { \ |
349 if (HasRegisterInput(instr, 1)) { \ | 309 if (HasRegisterInput(instr, 1)) { \ |
350 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ | 310 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ |
351 i.InputRegister(1), kScratchReg, r0); \ | 311 i.InputRegister(1), kScratchReg, r0); \ |
352 } else { \ | 312 } else { \ |
353 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ | 313 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ |
354 i.InputInt32(1), kScratchReg, r0); \ | 314 i.InputInt32(1), kScratchReg, r0); \ |
355 } \ | 315 } \ |
356 } while (0) | 316 } while (0) |
357 | 317 |
358 | |
359 #define ASSEMBLE_SUB_WITH_OVERFLOW() \ | 318 #define ASSEMBLE_SUB_WITH_OVERFLOW() \ |
360 do { \ | 319 do { \ |
361 if (HasRegisterInput(instr, 1)) { \ | 320 if (HasRegisterInput(instr, 1)) { \ |
362 __ SubAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ | 321 __ SubAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ |
363 i.InputRegister(1), kScratchReg, r0); \ | 322 i.InputRegister(1), kScratchReg, r0); \ |
364 } else { \ | 323 } else { \ |
365 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ | 324 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ |
366 -i.InputInt32(1), kScratchReg, r0); \ | 325 -i.InputInt32(1), kScratchReg, r0); \ |
367 } \ | 326 } \ |
368 } while (0) | 327 } while (0) |
369 | 328 |
370 | 329 #if V8_TARGET_ARCH_S390X |
371 #if V8_TARGET_ARCH_PPC64 | 330 #define ASSEMBLE_ADD_WITH_OVERFLOW32() \ |
372 #define ASSEMBLE_ADD_WITH_OVERFLOW32() \ | 331 do { \ |
373 do { \ | 332 ASSEMBLE_BINOP(AddP, AddP); \ |
374 ASSEMBLE_BINOP(add, addi); \ | 333 __ TestIfInt32(i.OutputRegister(), r0); \ |
375 __ TestIfInt32(i.OutputRegister(), r0, cr0); \ | |
376 } while (0) | 334 } while (0) |
377 | 335 |
378 | 336 #define ASSEMBLE_SUB_WITH_OVERFLOW32() \ |
379 #define ASSEMBLE_SUB_WITH_OVERFLOW32() \ | 337 do { \ |
380 do { \ | 338 ASSEMBLE_BINOP(SubP, SubP); \ |
381 ASSEMBLE_BINOP(sub, subi); \ | 339 __ TestIfInt32(i.OutputRegister(), r0); \ |
382 __ TestIfInt32(i.OutputRegister(), r0, cr0); \ | |
383 } while (0) | 340 } while (0) |
384 #else | 341 #else |
385 #define ASSEMBLE_ADD_WITH_OVERFLOW32 ASSEMBLE_ADD_WITH_OVERFLOW | 342 #define ASSEMBLE_ADD_WITH_OVERFLOW32 ASSEMBLE_ADD_WITH_OVERFLOW |
386 #define ASSEMBLE_SUB_WITH_OVERFLOW32 ASSEMBLE_SUB_WITH_OVERFLOW | 343 #define ASSEMBLE_SUB_WITH_OVERFLOW32 ASSEMBLE_SUB_WITH_OVERFLOW |
387 #endif | 344 #endif |
388 | 345 |
389 | 346 #define ASSEMBLE_COMPARE(cmp_instr, cmpl_instr) \ |
390 #define ASSEMBLE_COMPARE(cmp_instr, cmpl_instr) \ | 347 do { \ |
391 do { \ | 348 if (HasRegisterInput(instr, 1)) { \ |
392 const CRegister cr = cr0; \ | 349 if (i.CompareLogical()) { \ |
393 if (HasRegisterInput(instr, 1)) { \ | 350 __ cmpl_instr(i.InputRegister(0), i.InputRegister(1)); \ |
394 if (i.CompareLogical()) { \ | 351 } else { \ |
395 __ cmpl_instr(i.InputRegister(0), i.InputRegister(1), cr); \ | 352 __ cmp_instr(i.InputRegister(0), i.InputRegister(1)); \ |
396 } else { \ | 353 } \ |
397 __ cmp_instr(i.InputRegister(0), i.InputRegister(1), cr); \ | 354 } else { \ |
398 } \ | 355 if (i.CompareLogical()) { \ |
399 } else { \ | 356 __ cmpl_instr(i.InputRegister(0), i.InputImmediate(1)); \ |
400 if (i.CompareLogical()) { \ | 357 } else { \ |
401 __ cmpl_instr##i(i.InputRegister(0), i.InputImmediate(1), cr); \ | 358 __ cmp_instr(i.InputRegister(0), i.InputImmediate(1)); \ |
402 } else { \ | 359 } \ |
403 __ cmp_instr##i(i.InputRegister(0), i.InputImmediate(1), cr); \ | 360 } \ |
404 } \ | |
405 } \ | |
406 DCHECK_EQ(SetRC, i.OutputRCBit()); \ | |
407 } while (0) | 361 } while (0) |
408 | 362 |
409 | 363 #define ASSEMBLE_FLOAT_COMPARE(cmp_instr) \ |
410 #define ASSEMBLE_FLOAT_COMPARE(cmp_instr) \ | 364 do { \ |
411 do { \ | 365 __ cmp_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1); \ |
412 const CRegister cr = cr0; \ | |
413 __ cmp_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1), cr); \ | |
414 DCHECK_EQ(SetRC, i.OutputRCBit()); \ | |
415 } while (0) | 366 } while (0) |
416 | 367 |
417 | 368 // Divide instruction dr will implicity use register pair |
418 #define ASSEMBLE_MODULO(div_instr, mul_instr) \ | 369 // r0 & r1 below. |
419 do { \ | 370 // R0:R1 = R1 / divisor - R0 remainder |
420 const Register scratch = kScratchReg; \ | 371 // Copy remainder to output reg |
421 __ div_instr(scratch, i.InputRegister(0), i.InputRegister(1)); \ | 372 #define ASSEMBLE_MODULO(div_instr, shift_instr) \ |
422 __ mul_instr(scratch, scratch, i.InputRegister(1)); \ | 373 do { \ |
423 __ sub(i.OutputRegister(), i.InputRegister(0), scratch, LeaveOE, \ | 374 __ LoadRR(r0, i.InputRegister(0)); \ |
424 i.OutputRCBit()); \ | 375 __ shift_instr(r0, Operand(32)); \ |
| 376 __ div_instr(r0, i.InputRegister(1)); \ |
| 377 __ ltr(i.OutputRegister(), r0); \ |
425 } while (0) | 378 } while (0) |
426 | 379 |
427 | |
428 #define ASSEMBLE_FLOAT_MODULO() \ | 380 #define ASSEMBLE_FLOAT_MODULO() \ |
429 do { \ | 381 do { \ |
430 FrameScope scope(masm(), StackFrame::MANUAL); \ | 382 FrameScope scope(masm(), StackFrame::MANUAL); \ |
431 __ PrepareCallCFunction(0, 2, kScratchReg); \ | 383 __ PrepareCallCFunction(0, 2, kScratchReg); \ |
432 __ MovToFloatParameters(i.InputDoubleRegister(0), \ | 384 __ MovToFloatParameters(i.InputDoubleRegister(0), \ |
433 i.InputDoubleRegister(1)); \ | 385 i.InputDoubleRegister(1)); \ |
434 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), \ | 386 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), \ |
435 0, 2); \ | 387 0, 2); \ |
436 __ MovFromFloatResult(i.OutputDoubleRegister()); \ | 388 __ MovFromFloatResult(i.OutputDoubleRegister()); \ |
437 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | |
438 } while (0) | 389 } while (0) |
439 | 390 |
440 | 391 #define ASSEMBLE_FLOAT_MAX(double_scratch_reg, general_scratch_reg) \ |
441 #define ASSEMBLE_FLOAT_MAX(scratch_reg) \ | 392 do { \ |
442 do { \ | 393 Label ge, done; \ |
443 __ fsub(scratch_reg, i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \ | 394 __ cdbr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \ |
444 __ fsel(i.OutputDoubleRegister(), scratch_reg, i.InputDoubleRegister(0), \ | 395 __ bge(&ge, Label::kNear); \ |
445 i.InputDoubleRegister(1)); \ | 396 __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); \ |
| 397 __ b(&done, Label::kNear); \ |
| 398 __ bind(&ge); \ |
| 399 __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ |
| 400 __ bind(&done); \ |
446 } while (0) | 401 } while (0) |
447 | 402 |
448 | 403 #define ASSEMBLE_FLOAT_MIN(double_scratch_reg, general_scratch_reg) \ |
449 #define ASSEMBLE_FLOAT_MIN(scratch_reg) \ | 404 do { \ |
450 do { \ | 405 Label ge, done; \ |
451 __ fsub(scratch_reg, i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \ | 406 __ cdbr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \ |
452 __ fsel(i.OutputDoubleRegister(), scratch_reg, i.InputDoubleRegister(1), \ | 407 __ bge(&ge, Label::kNear); \ |
453 i.InputDoubleRegister(0)); \ | 408 __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ |
| 409 __ b(&done, Label::kNear); \ |
| 410 __ bind(&ge); \ |
| 411 __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); \ |
| 412 __ bind(&done); \ |
454 } while (0) | 413 } while (0) |
455 | 414 |
456 | 415 // Only MRI mode for these instructions available |
457 #define ASSEMBLE_LOAD_FLOAT(asm_instr, asm_instrx) \ | 416 #define ASSEMBLE_LOAD_FLOAT(asm_instr) \ |
458 do { \ | 417 do { \ |
459 DoubleRegister result = i.OutputDoubleRegister(); \ | 418 DoubleRegister result = i.OutputDoubleRegister(); \ |
460 AddressingMode mode = kMode_None; \ | 419 AddressingMode mode = kMode_None; \ |
461 MemOperand operand = i.MemoryOperand(&mode); \ | 420 MemOperand operand = i.MemoryOperand(&mode); \ |
462 if (mode == kMode_MRI) { \ | 421 __ asm_instr(result, operand); \ |
463 __ asm_instr(result, operand); \ | |
464 } else { \ | |
465 __ asm_instrx(result, operand); \ | |
466 } \ | |
467 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | |
468 } while (0) | 422 } while (0) |
469 | 423 |
470 | 424 #define ASSEMBLE_LOAD_INTEGER(asm_instr) \ |
471 #define ASSEMBLE_LOAD_INTEGER(asm_instr, asm_instrx) \ | 425 do { \ |
472 do { \ | 426 Register result = i.OutputRegister(); \ |
473 Register result = i.OutputRegister(); \ | 427 AddressingMode mode = kMode_None; \ |
474 AddressingMode mode = kMode_None; \ | 428 MemOperand operand = i.MemoryOperand(&mode); \ |
475 MemOperand operand = i.MemoryOperand(&mode); \ | 429 __ asm_instr(result, operand); \ |
476 if (mode == kMode_MRI) { \ | |
477 __ asm_instr(result, operand); \ | |
478 } else { \ | |
479 __ asm_instrx(result, operand); \ | |
480 } \ | |
481 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | |
482 } while (0) | 430 } while (0) |
483 | 431 |
484 | |
485 #define ASSEMBLE_STORE_FLOAT32() \ | 432 #define ASSEMBLE_STORE_FLOAT32() \ |
486 do { \ | 433 do { \ |
487 size_t index = 0; \ | 434 size_t index = 0; \ |
488 AddressingMode mode = kMode_None; \ | 435 AddressingMode mode = kMode_None; \ |
489 MemOperand operand = i.MemoryOperand(&mode, &index); \ | 436 MemOperand operand = i.MemoryOperand(&mode, &index); \ |
490 DoubleRegister value = i.InputDoubleRegister(index); \ | 437 DoubleRegister value = i.InputDoubleRegister(index); \ |
491 __ frsp(kScratchDoubleReg, value); \ | 438 __ StoreFloat32(value, operand); \ |
492 if (mode == kMode_MRI) { \ | |
493 __ stfs(kScratchDoubleReg, operand); \ | |
494 } else { \ | |
495 __ stfsx(kScratchDoubleReg, operand); \ | |
496 } \ | |
497 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | |
498 } while (0) | 439 } while (0) |
499 | 440 |
500 | |
501 #define ASSEMBLE_STORE_DOUBLE() \ | 441 #define ASSEMBLE_STORE_DOUBLE() \ |
502 do { \ | 442 do { \ |
503 size_t index = 0; \ | 443 size_t index = 0; \ |
504 AddressingMode mode = kMode_None; \ | 444 AddressingMode mode = kMode_None; \ |
505 MemOperand operand = i.MemoryOperand(&mode, &index); \ | 445 MemOperand operand = i.MemoryOperand(&mode, &index); \ |
506 DoubleRegister value = i.InputDoubleRegister(index); \ | 446 DoubleRegister value = i.InputDoubleRegister(index); \ |
507 if (mode == kMode_MRI) { \ | 447 __ StoreDouble(value, operand); \ |
508 __ stfd(value, operand); \ | |
509 } else { \ | |
510 __ stfdx(value, operand); \ | |
511 } \ | |
512 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | |
513 } while (0) | 448 } while (0) |
514 | 449 |
515 | 450 #define ASSEMBLE_STORE_INTEGER(asm_instr) \ |
516 #define ASSEMBLE_STORE_INTEGER(asm_instr, asm_instrx) \ | |
517 do { \ | 451 do { \ |
518 size_t index = 0; \ | 452 size_t index = 0; \ |
519 AddressingMode mode = kMode_None; \ | 453 AddressingMode mode = kMode_None; \ |
520 MemOperand operand = i.MemoryOperand(&mode, &index); \ | 454 MemOperand operand = i.MemoryOperand(&mode, &index); \ |
521 Register value = i.InputRegister(index); \ | 455 Register value = i.InputRegister(index); \ |
522 if (mode == kMode_MRI) { \ | 456 __ asm_instr(value, operand); \ |
523 __ asm_instr(value, operand); \ | |
524 } else { \ | |
525 __ asm_instrx(value, operand); \ | |
526 } \ | |
527 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | |
528 } while (0) | 457 } while (0) |
529 | 458 |
530 | |
531 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits. | 459 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits. |
532 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr, asm_instrx, width) \ | 460 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr, width) \ |
533 do { \ | 461 do { \ |
534 DoubleRegister result = i.OutputDoubleRegister(); \ | 462 DoubleRegister result = i.OutputDoubleRegister(); \ |
535 size_t index = 0; \ | 463 size_t index = 0; \ |
536 AddressingMode mode = kMode_None; \ | 464 AddressingMode mode = kMode_None; \ |
537 MemOperand operand = i.MemoryOperand(&mode, index); \ | 465 MemOperand operand = i.MemoryOperand(&mode, index); \ |
538 DCHECK_EQ(kMode_MRR, mode); \ | |
539 Register offset = operand.rb(); \ | 466 Register offset = operand.rb(); \ |
540 __ extsw(offset, offset); \ | 467 __ lgfr(offset, offset); \ |
541 if (HasRegisterInput(instr, 2)) { \ | 468 if (HasRegisterInput(instr, 2)) { \ |
542 __ cmplw(offset, i.InputRegister(2)); \ | 469 __ CmpLogical32(offset, i.InputRegister(2)); \ |
543 } else { \ | 470 } else { \ |
544 __ cmplwi(offset, i.InputImmediate(2)); \ | 471 __ CmpLogical32(offset, i.InputImmediate(2)); \ |
545 } \ | 472 } \ |
546 auto ool = new (zone()) OutOfLineLoadNAN##width(this, result); \ | 473 auto ool = new (zone()) OutOfLineLoadNAN##width(this, result); \ |
547 __ bge(ool->entry()); \ | 474 __ bge(ool->entry()); \ |
548 if (mode == kMode_MRI) { \ | 475 __ asm_instr(result, operand); \ |
549 __ asm_instr(result, operand); \ | |
550 } else { \ | |
551 __ asm_instrx(result, operand); \ | |
552 } \ | |
553 __ bind(ool->exit()); \ | 476 __ bind(ool->exit()); \ |
554 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | |
555 } while (0) | 477 } while (0) |
556 | 478 |
557 | |
558 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits. | 479 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits. |
559 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr, asm_instrx) \ | 480 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
560 do { \ | 481 do { \ |
561 Register result = i.OutputRegister(); \ | 482 Register result = i.OutputRegister(); \ |
562 size_t index = 0; \ | 483 size_t index = 0; \ |
563 AddressingMode mode = kMode_None; \ | 484 AddressingMode mode = kMode_None; \ |
564 MemOperand operand = i.MemoryOperand(&mode, index); \ | 485 MemOperand operand = i.MemoryOperand(&mode, index); \ |
565 DCHECK_EQ(kMode_MRR, mode); \ | |
566 Register offset = operand.rb(); \ | 486 Register offset = operand.rb(); \ |
567 __ extsw(offset, offset); \ | 487 __ lgfr(offset, offset); \ |
568 if (HasRegisterInput(instr, 2)) { \ | 488 if (HasRegisterInput(instr, 2)) { \ |
569 __ cmplw(offset, i.InputRegister(2)); \ | 489 __ CmpLogical32(offset, i.InputRegister(2)); \ |
570 } else { \ | 490 } else { \ |
571 __ cmplwi(offset, i.InputImmediate(2)); \ | 491 __ CmpLogical32(offset, i.InputImmediate(2)); \ |
572 } \ | 492 } \ |
573 auto ool = new (zone()) OutOfLineLoadZero(this, result); \ | 493 auto ool = new (zone()) OutOfLineLoadZero(this, result); \ |
574 __ bge(ool->entry()); \ | 494 __ bge(ool->entry()); \ |
575 if (mode == kMode_MRI) { \ | 495 __ asm_instr(result, operand); \ |
576 __ asm_instr(result, operand); \ | |
577 } else { \ | |
578 __ asm_instrx(result, operand); \ | |
579 } \ | |
580 __ bind(ool->exit()); \ | 496 __ bind(ool->exit()); \ |
581 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | |
582 } while (0) | 497 } while (0) |
583 | 498 |
584 | |
585 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits. | 499 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits. |
586 #define ASSEMBLE_CHECKED_STORE_FLOAT32() \ | 500 #define ASSEMBLE_CHECKED_STORE_FLOAT32() \ |
587 do { \ | 501 do { \ |
588 Label done; \ | 502 Label done; \ |
589 size_t index = 0; \ | 503 size_t index = 0; \ |
590 AddressingMode mode = kMode_None; \ | 504 AddressingMode mode = kMode_None; \ |
591 MemOperand operand = i.MemoryOperand(&mode, index); \ | 505 MemOperand operand = i.MemoryOperand(&mode, index); \ |
592 DCHECK_EQ(kMode_MRR, mode); \ | |
593 Register offset = operand.rb(); \ | 506 Register offset = operand.rb(); \ |
594 __ extsw(offset, offset); \ | 507 __ lgfr(offset, offset); \ |
595 if (HasRegisterInput(instr, 2)) { \ | 508 if (HasRegisterInput(instr, 2)) { \ |
596 __ cmplw(offset, i.InputRegister(2)); \ | 509 __ CmpLogical32(offset, i.InputRegister(2)); \ |
597 } else { \ | 510 } else { \ |
598 __ cmplwi(offset, i.InputImmediate(2)); \ | 511 __ CmpLogical32(offset, i.InputImmediate(2)); \ |
599 } \ | 512 } \ |
600 __ bge(&done); \ | 513 __ bge(&done); \ |
601 DoubleRegister value = i.InputDoubleRegister(3); \ | 514 DoubleRegister value = i.InputDoubleRegister(3); \ |
602 __ frsp(kScratchDoubleReg, value); \ | 515 __ StoreFloat32(value, operand); \ |
603 if (mode == kMode_MRI) { \ | |
604 __ stfs(kScratchDoubleReg, operand); \ | |
605 } else { \ | |
606 __ stfsx(kScratchDoubleReg, operand); \ | |
607 } \ | |
608 __ bind(&done); \ | 516 __ bind(&done); \ |
609 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | |
610 } while (0) | 517 } while (0) |
611 | 518 |
612 | |
613 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits. | 519 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits. |
614 #define ASSEMBLE_CHECKED_STORE_DOUBLE() \ | 520 #define ASSEMBLE_CHECKED_STORE_DOUBLE() \ |
615 do { \ | 521 do { \ |
616 Label done; \ | 522 Label done; \ |
617 size_t index = 0; \ | 523 size_t index = 0; \ |
618 AddressingMode mode = kMode_None; \ | 524 AddressingMode mode = kMode_None; \ |
619 MemOperand operand = i.MemoryOperand(&mode, index); \ | 525 MemOperand operand = i.MemoryOperand(&mode, index); \ |
620 DCHECK_EQ(kMode_MRR, mode); \ | 526 DCHECK_EQ(kMode_MRR, mode); \ |
621 Register offset = operand.rb(); \ | 527 Register offset = operand.rb(); \ |
622 __ extsw(offset, offset); \ | 528 __ lgfr(offset, offset); \ |
623 if (HasRegisterInput(instr, 2)) { \ | 529 if (HasRegisterInput(instr, 2)) { \ |
624 __ cmplw(offset, i.InputRegister(2)); \ | 530 __ CmpLogical32(offset, i.InputRegister(2)); \ |
625 } else { \ | 531 } else { \ |
626 __ cmplwi(offset, i.InputImmediate(2)); \ | 532 __ CmpLogical32(offset, i.InputImmediate(2)); \ |
627 } \ | 533 } \ |
628 __ bge(&done); \ | 534 __ bge(&done); \ |
629 DoubleRegister value = i.InputDoubleRegister(3); \ | 535 DoubleRegister value = i.InputDoubleRegister(3); \ |
630 if (mode == kMode_MRI) { \ | 536 __ StoreDouble(value, operand); \ |
631 __ stfd(value, operand); \ | |
632 } else { \ | |
633 __ stfdx(value, operand); \ | |
634 } \ | |
635 __ bind(&done); \ | 537 __ bind(&done); \ |
636 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | |
637 } while (0) | 538 } while (0) |
638 | 539 |
639 | |
640 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits. | 540 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits. |
641 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr, asm_instrx) \ | 541 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ |
642 do { \ | 542 do { \ |
643 Label done; \ | 543 Label done; \ |
644 size_t index = 0; \ | 544 size_t index = 0; \ |
645 AddressingMode mode = kMode_None; \ | 545 AddressingMode mode = kMode_None; \ |
646 MemOperand operand = i.MemoryOperand(&mode, index); \ | 546 MemOperand operand = i.MemoryOperand(&mode, index); \ |
647 DCHECK_EQ(kMode_MRR, mode); \ | 547 Register offset = operand.rb(); \ |
648 Register offset = operand.rb(); \ | 548 __ lgfr(offset, offset); \ |
649 __ extsw(offset, offset); \ | 549 if (HasRegisterInput(instr, 2)) { \ |
650 if (HasRegisterInput(instr, 2)) { \ | 550 __ CmpLogical32(offset, i.InputRegister(2)); \ |
651 __ cmplw(offset, i.InputRegister(2)); \ | 551 } else { \ |
652 } else { \ | 552 __ CmpLogical32(offset, i.InputImmediate(2)); \ |
653 __ cmplwi(offset, i.InputImmediate(2)); \ | 553 } \ |
654 } \ | 554 __ bge(&done); \ |
655 __ bge(&done); \ | 555 Register value = i.InputRegister(3); \ |
656 Register value = i.InputRegister(3); \ | 556 __ asm_instr(value, operand); \ |
657 if (mode == kMode_MRI) { \ | 557 __ bind(&done); \ |
658 __ asm_instr(value, operand); \ | |
659 } else { \ | |
660 __ asm_instrx(value, operand); \ | |
661 } \ | |
662 __ bind(&done); \ | |
663 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | |
664 } while (0) | 558 } while (0) |
665 | 559 |
666 | |
667 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 560 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { |
668 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | 561 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); |
669 if (sp_slot_delta > 0) { | 562 if (sp_slot_delta > 0) { |
670 __ Add(sp, sp, sp_slot_delta * kPointerSize, r0); | 563 __ AddP(sp, sp, Operand(sp_slot_delta * kPointerSize)); |
671 } | 564 } |
672 frame_access_state()->SetFrameAccessToDefault(); | 565 frame_access_state()->SetFrameAccessToDefault(); |
673 } | 566 } |
674 | 567 |
675 | |
676 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | 568 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { |
677 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | 569 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); |
678 if (sp_slot_delta < 0) { | 570 if (sp_slot_delta < 0) { |
679 __ Add(sp, sp, sp_slot_delta * kPointerSize, r0); | 571 __ AddP(sp, sp, Operand(sp_slot_delta * kPointerSize)); |
680 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | 572 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); |
681 } | 573 } |
682 if (frame()->needs_frame()) { | 574 if (frame()->needs_frame()) { |
683 __ RestoreFrameStateForTailCall(); | 575 __ RestoreFrameStateForTailCall(); |
684 } | 576 } |
685 frame_access_state()->SetFrameAccessToSP(); | 577 frame_access_state()->SetFrameAccessToSP(); |
686 } | 578 } |
687 | 579 |
688 | |
689 // Assembles an instruction after register allocation, producing machine code. | 580 // Assembles an instruction after register allocation, producing machine code. |
690 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 581 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
691 PPCOperandConverter i(this, instr); | 582 S390OperandConverter i(this, instr); |
692 ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode()); | 583 ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode()); |
693 | 584 |
694 switch (opcode) { | 585 switch (opcode) { |
695 case kArchCallCodeObject: { | 586 case kArchCallCodeObject: { |
696 v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool( | |
697 masm()); | |
698 EnsureSpaceForLazyDeopt(); | 587 EnsureSpaceForLazyDeopt(); |
699 if (HasRegisterInput(instr, 0)) { | 588 if (HasRegisterInput(instr, 0)) { |
700 __ addi(ip, i.InputRegister(0), | 589 __ AddP(ip, i.InputRegister(0), |
701 Operand(Code::kHeaderSize - kHeapObjectTag)); | 590 Operand(Code::kHeaderSize - kHeapObjectTag)); |
702 __ Call(ip); | 591 __ Call(ip); |
703 } else { | 592 } else { |
704 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 593 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
705 RelocInfo::CODE_TARGET); | 594 RelocInfo::CODE_TARGET); |
706 } | 595 } |
707 RecordCallPosition(instr); | 596 RecordCallPosition(instr); |
708 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
709 frame_access_state()->ClearSPDelta(); | 597 frame_access_state()->ClearSPDelta(); |
710 break; | 598 break; |
711 } | 599 } |
712 case kArchTailCallCodeObject: { | 600 case kArchTailCallCodeObject: { |
713 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 601 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
714 AssembleDeconstructActivationRecord(stack_param_delta); | 602 AssembleDeconstructActivationRecord(stack_param_delta); |
715 if (HasRegisterInput(instr, 0)) { | 603 if (HasRegisterInput(instr, 0)) { |
716 __ addi(ip, i.InputRegister(0), | 604 __ AddP(ip, i.InputRegister(0), |
717 Operand(Code::kHeaderSize - kHeapObjectTag)); | 605 Operand(Code::kHeaderSize - kHeapObjectTag)); |
718 __ Jump(ip); | 606 __ Jump(ip); |
719 } else { | 607 } else { |
720 // We cannot use the constant pool to load the target since | 608 // We cannot use the constant pool to load the target since |
721 // we've already restored the caller's frame. | 609 // we've already restored the caller's frame. |
722 ConstantPoolUnavailableScope constant_pool_unavailable(masm()); | 610 ConstantPoolUnavailableScope constant_pool_unavailable(masm()); |
723 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 611 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
724 RelocInfo::CODE_TARGET); | 612 RelocInfo::CODE_TARGET); |
725 } | 613 } |
726 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
727 frame_access_state()->ClearSPDelta(); | 614 frame_access_state()->ClearSPDelta(); |
728 break; | 615 break; |
729 } | 616 } |
730 case kArchCallJSFunction: { | 617 case kArchCallJSFunction: { |
731 v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool( | |
732 masm()); | |
733 EnsureSpaceForLazyDeopt(); | 618 EnsureSpaceForLazyDeopt(); |
734 Register func = i.InputRegister(0); | 619 Register func = i.InputRegister(0); |
735 if (FLAG_debug_code) { | 620 if (FLAG_debug_code) { |
736 // Check the function's context matches the context argument. | 621 // Check the function's context matches the context argument. |
737 __ LoadP(kScratchReg, | 622 __ LoadP(kScratchReg, |
738 FieldMemOperand(func, JSFunction::kContextOffset)); | 623 FieldMemOperand(func, JSFunction::kContextOffset)); |
739 __ cmp(cp, kScratchReg); | 624 __ CmpP(cp, kScratchReg); |
740 __ Assert(eq, kWrongFunctionContext); | 625 __ Assert(eq, kWrongFunctionContext); |
741 } | 626 } |
742 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 627 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
743 __ Call(ip); | 628 __ Call(ip); |
744 RecordCallPosition(instr); | 629 RecordCallPosition(instr); |
745 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
746 frame_access_state()->ClearSPDelta(); | 630 frame_access_state()->ClearSPDelta(); |
747 break; | 631 break; |
748 } | 632 } |
749 case kArchTailCallJSFunction: { | 633 case kArchTailCallJSFunction: { |
750 Register func = i.InputRegister(0); | 634 Register func = i.InputRegister(0); |
751 if (FLAG_debug_code) { | 635 if (FLAG_debug_code) { |
752 // Check the function's context matches the context argument. | 636 // Check the function's context matches the context argument. |
753 __ LoadP(kScratchReg, | 637 __ LoadP(kScratchReg, |
754 FieldMemOperand(func, JSFunction::kContextOffset)); | 638 FieldMemOperand(func, JSFunction::kContextOffset)); |
755 __ cmp(cp, kScratchReg); | 639 __ CmpP(cp, kScratchReg); |
756 __ Assert(eq, kWrongFunctionContext); | 640 __ Assert(eq, kWrongFunctionContext); |
757 } | 641 } |
758 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 642 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
759 AssembleDeconstructActivationRecord(stack_param_delta); | 643 AssembleDeconstructActivationRecord(stack_param_delta); |
760 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 644 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
761 __ Jump(ip); | 645 __ Jump(ip); |
762 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
763 frame_access_state()->ClearSPDelta(); | 646 frame_access_state()->ClearSPDelta(); |
764 break; | 647 break; |
765 } | 648 } |
766 case kArchPrepareCallCFunction: { | 649 case kArchPrepareCallCFunction: { |
767 int const num_parameters = MiscField::decode(instr->opcode()); | 650 int const num_parameters = MiscField::decode(instr->opcode()); |
768 __ PrepareCallCFunction(num_parameters, kScratchReg); | 651 __ PrepareCallCFunction(num_parameters, kScratchReg); |
769 // Frame alignment requires using FP-relative frame addressing. | 652 // Frame alignment requires using FP-relative frame addressing. |
770 frame_access_state()->SetFrameAccessToFP(); | 653 frame_access_state()->SetFrameAccessToFP(); |
771 break; | 654 break; |
772 } | 655 } |
773 case kArchPrepareTailCall: | 656 case kArchPrepareTailCall: |
774 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); | 657 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); |
775 break; | 658 break; |
776 case kArchCallCFunction: { | 659 case kArchCallCFunction: { |
777 int const num_parameters = MiscField::decode(instr->opcode()); | 660 int const num_parameters = MiscField::decode(instr->opcode()); |
778 if (instr->InputAt(0)->IsImmediate()) { | 661 if (instr->InputAt(0)->IsImmediate()) { |
779 ExternalReference ref = i.InputExternalReference(0); | 662 ExternalReference ref = i.InputExternalReference(0); |
780 __ CallCFunction(ref, num_parameters); | 663 __ CallCFunction(ref, num_parameters); |
781 } else { | 664 } else { |
782 Register func = i.InputRegister(0); | 665 Register func = i.InputRegister(0); |
783 __ CallCFunction(func, num_parameters); | 666 __ CallCFunction(func, num_parameters); |
784 } | 667 } |
785 frame_access_state()->SetFrameAccessToDefault(); | 668 frame_access_state()->SetFrameAccessToDefault(); |
786 frame_access_state()->ClearSPDelta(); | 669 frame_access_state()->ClearSPDelta(); |
787 break; | 670 break; |
788 } | 671 } |
789 case kArchJmp: | 672 case kArchJmp: |
790 AssembleArchJump(i.InputRpo(0)); | 673 AssembleArchJump(i.InputRpo(0)); |
791 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
792 break; | 674 break; |
793 case kArchLookupSwitch: | 675 case kArchLookupSwitch: |
794 AssembleArchLookupSwitch(instr); | 676 AssembleArchLookupSwitch(instr); |
795 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
796 break; | 677 break; |
797 case kArchTableSwitch: | 678 case kArchTableSwitch: |
798 AssembleArchTableSwitch(instr); | 679 AssembleArchTableSwitch(instr); |
799 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
800 break; | 680 break; |
801 case kArchNop: | 681 case kArchNop: |
802 case kArchThrowTerminator: | 682 case kArchThrowTerminator: |
803 // don't emit code for nops. | 683 // don't emit code for nops. |
804 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
805 break; | 684 break; |
806 case kArchDeoptimize: { | 685 case kArchDeoptimize: { |
807 int deopt_state_id = | 686 int deopt_state_id = |
808 BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore()); | 687 BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore()); |
809 Deoptimizer::BailoutType bailout_type = | 688 Deoptimizer::BailoutType bailout_type = |
810 Deoptimizer::BailoutType(MiscField::decode(instr->opcode())); | 689 Deoptimizer::BailoutType(MiscField::decode(instr->opcode())); |
811 AssembleDeoptimizerCall(deopt_state_id, bailout_type); | 690 AssembleDeoptimizerCall(deopt_state_id, bailout_type); |
812 break; | 691 break; |
813 } | 692 } |
814 case kArchRet: | 693 case kArchRet: |
815 AssembleReturn(); | 694 AssembleReturn(); |
816 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
817 break; | 695 break; |
818 case kArchStackPointer: | 696 case kArchStackPointer: |
819 __ mr(i.OutputRegister(), sp); | 697 __ LoadRR(i.OutputRegister(), sp); |
820 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
821 break; | 698 break; |
822 case kArchFramePointer: | 699 case kArchFramePointer: |
823 __ mr(i.OutputRegister(), fp); | 700 __ LoadRR(i.OutputRegister(), fp); |
824 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
825 break; | 701 break; |
826 case kArchParentFramePointer: | 702 case kArchParentFramePointer: |
827 if (frame_access_state()->frame()->needs_frame()) { | 703 if (frame_access_state()->frame()->needs_frame()) { |
828 __ LoadP(i.OutputRegister(), MemOperand(fp, 0)); | 704 __ LoadP(i.OutputRegister(), MemOperand(fp, 0)); |
829 } else { | 705 } else { |
830 __ mr(i.OutputRegister(), fp); | 706 __ LoadRR(i.OutputRegister(), fp); |
831 } | 707 } |
832 break; | 708 break; |
833 case kArchTruncateDoubleToI: | 709 case kArchTruncateDoubleToI: |
834 // TODO(mbrandy): move slow call to stub out of line. | 710 // TODO(mbrandy): move slow call to stub out of line. |
835 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); | 711 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); |
836 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
837 break; | 712 break; |
838 case kArchStoreWithWriteBarrier: { | 713 case kArchStoreWithWriteBarrier: { |
839 RecordWriteMode mode = | 714 RecordWriteMode mode = |
840 static_cast<RecordWriteMode>(MiscField::decode(instr->opcode())); | 715 static_cast<RecordWriteMode>(MiscField::decode(instr->opcode())); |
841 Register object = i.InputRegister(0); | 716 Register object = i.InputRegister(0); |
842 Register value = i.InputRegister(2); | 717 Register value = i.InputRegister(2); |
843 Register scratch0 = i.TempRegister(0); | 718 Register scratch0 = i.TempRegister(0); |
844 Register scratch1 = i.TempRegister(1); | 719 Register scratch1 = i.TempRegister(1); |
845 OutOfLineRecordWrite* ool; | 720 OutOfLineRecordWrite* ool; |
846 | 721 |
847 AddressingMode addressing_mode = | 722 AddressingMode addressing_mode = |
848 AddressingModeField::decode(instr->opcode()); | 723 AddressingModeField::decode(instr->opcode()); |
849 if (addressing_mode == kMode_MRI) { | 724 if (addressing_mode == kMode_MRI) { |
850 int32_t offset = i.InputInt32(1); | 725 int32_t offset = i.InputInt32(1); |
851 ool = new (zone()) OutOfLineRecordWrite(this, object, offset, value, | 726 ool = new (zone()) OutOfLineRecordWrite(this, object, offset, value, |
852 scratch0, scratch1, mode); | 727 scratch0, scratch1, mode); |
853 __ StoreP(value, MemOperand(object, offset)); | 728 __ StoreP(value, MemOperand(object, offset)); |
854 } else { | 729 } else { |
855 DCHECK_EQ(kMode_MRR, addressing_mode); | 730 DCHECK_EQ(kMode_MRR, addressing_mode); |
856 Register offset(i.InputRegister(1)); | 731 Register offset(i.InputRegister(1)); |
857 ool = new (zone()) OutOfLineRecordWrite(this, object, offset, value, | 732 ool = new (zone()) OutOfLineRecordWrite(this, object, offset, value, |
858 scratch0, scratch1, mode); | 733 scratch0, scratch1, mode); |
859 __ StorePX(value, MemOperand(object, offset)); | 734 __ StoreP(value, MemOperand(object, offset)); |
860 } | 735 } |
861 __ CheckPageFlag(object, scratch0, | 736 __ CheckPageFlag(object, scratch0, |
862 MemoryChunk::kPointersFromHereAreInterestingMask, ne, | 737 MemoryChunk::kPointersFromHereAreInterestingMask, ne, |
863 ool->entry()); | 738 ool->entry()); |
864 __ bind(ool->exit()); | 739 __ bind(ool->exit()); |
865 break; | 740 break; |
866 } | 741 } |
867 case kArchStackSlot: { | 742 case kArchStackSlot: { |
868 FrameOffset offset = | 743 FrameOffset offset = |
869 frame_access_state()->GetFrameOffset(i.InputInt32(0)); | 744 frame_access_state()->GetFrameOffset(i.InputInt32(0)); |
870 __ addi(i.OutputRegister(), offset.from_stack_pointer() ? sp : fp, | 745 __ AddP(i.OutputRegister(), offset.from_stack_pointer() ? sp : fp, |
871 Operand(offset.offset())); | 746 Operand(offset.offset())); |
872 break; | 747 break; |
873 } | 748 } |
874 case kPPC_And: | 749 case kS390_And: |
| 750 ASSEMBLE_BINOP(AndP, AndP); |
| 751 break; |
| 752 case kS390_AndComplement: |
| 753 __ NotP(i.InputRegister(1)); |
| 754 __ AndP(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); |
| 755 break; |
| 756 case kS390_Or: |
| 757 ASSEMBLE_BINOP(OrP, OrP); |
| 758 break; |
| 759 case kS390_OrComplement: |
| 760 __ NotP(i.InputRegister(1)); |
| 761 __ OrP(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); |
| 762 break; |
| 763 case kS390_Xor: |
| 764 ASSEMBLE_BINOP(XorP, XorP); |
| 765 break; |
| 766 case kS390_ShiftLeft32: |
875 if (HasRegisterInput(instr, 1)) { | 767 if (HasRegisterInput(instr, 1)) { |
876 __ and_(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 768 if (i.OutputRegister().is(i.InputRegister(1))) { |
877 i.OutputRCBit()); | 769 __ LoadRR(kScratchReg, i.InputRegister(1)); |
878 } else { | 770 __ ShiftLeft(i.OutputRegister(), i.InputRegister(0), kScratchReg); |
879 __ andi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1)); | 771 } else { |
880 } | 772 ASSEMBLE_BINOP(ShiftLeft, ShiftLeft); |
881 break; | 773 } |
882 case kPPC_AndComplement: | 774 } else { |
883 __ andc(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 775 ASSEMBLE_BINOP(ShiftLeft, ShiftLeft); |
884 i.OutputRCBit()); | 776 } |
885 break; | 777 #if V8_TARGET_ARCH_S390X |
886 case kPPC_Or: | 778 __ lgfr(i.OutputRegister(0), i.OutputRegister(0)); |
| 779 #endif |
| 780 break; |
| 781 #if V8_TARGET_ARCH_S390X |
| 782 case kS390_ShiftLeft64: |
| 783 ASSEMBLE_BINOP(sllg, sllg); |
| 784 break; |
| 785 #endif |
| 786 case kS390_ShiftRight32: |
887 if (HasRegisterInput(instr, 1)) { | 787 if (HasRegisterInput(instr, 1)) { |
888 __ orx(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 788 if (i.OutputRegister().is(i.InputRegister(1))) { |
889 i.OutputRCBit()); | 789 __ LoadRR(kScratchReg, i.InputRegister(1)); |
890 } else { | 790 __ ShiftRight(i.OutputRegister(), i.InputRegister(0), kScratchReg); |
891 __ ori(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1)); | 791 } else { |
892 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 792 ASSEMBLE_BINOP(ShiftRight, ShiftRight); |
893 } | 793 } |
894 break; | 794 } else { |
895 case kPPC_OrComplement: | 795 ASSEMBLE_BINOP(ShiftRight, ShiftRight); |
896 __ orc(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 796 } |
897 i.OutputRCBit()); | 797 #if V8_TARGET_ARCH_S390X |
898 break; | 798 __ lgfr(i.OutputRegister(0), i.OutputRegister(0)); |
899 case kPPC_Xor: | 799 #endif |
| 800 break; |
| 801 #if V8_TARGET_ARCH_S390X |
| 802 case kS390_ShiftRight64: |
| 803 ASSEMBLE_BINOP(srlg, srlg); |
| 804 break; |
| 805 #endif |
| 806 case kS390_ShiftRightAlg32: |
900 if (HasRegisterInput(instr, 1)) { | 807 if (HasRegisterInput(instr, 1)) { |
901 __ xor_(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 808 if (i.OutputRegister().is(i.InputRegister(1))) { |
902 i.OutputRCBit()); | 809 __ LoadRR(kScratchReg, i.InputRegister(1)); |
903 } else { | 810 __ ShiftRightArith(i.OutputRegister(), i.InputRegister(0), |
904 __ xori(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1)); | 811 kScratchReg); |
905 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 812 } else { |
906 } | 813 ASSEMBLE_BINOP(ShiftRightArith, ShiftRightArith); |
907 break; | 814 } |
908 case kPPC_ShiftLeft32: | 815 } else { |
909 ASSEMBLE_BINOP_RC(slw, slwi); | 816 ASSEMBLE_BINOP(ShiftRightArith, ShiftRightArith); |
910 break; | 817 } |
911 #if V8_TARGET_ARCH_PPC64 | 818 break; |
912 case kPPC_ShiftLeft64: | 819 #if V8_TARGET_ARCH_S390X |
913 ASSEMBLE_BINOP_RC(sld, sldi); | 820 case kS390_ShiftRightAlg64: |
914 break; | 821 ASSEMBLE_BINOP(srag, srag); |
915 #endif | 822 break; |
916 case kPPC_ShiftRight32: | 823 #endif |
917 ASSEMBLE_BINOP_RC(srw, srwi); | 824 case kS390_RotRight32: |
918 break; | |
919 #if V8_TARGET_ARCH_PPC64 | |
920 case kPPC_ShiftRight64: | |
921 ASSEMBLE_BINOP_RC(srd, srdi); | |
922 break; | |
923 #endif | |
924 case kPPC_ShiftRightAlg32: | |
925 ASSEMBLE_BINOP_INT_RC(sraw, srawi); | |
926 break; | |
927 #if V8_TARGET_ARCH_PPC64 | |
928 case kPPC_ShiftRightAlg64: | |
929 ASSEMBLE_BINOP_INT_RC(srad, sradi); | |
930 break; | |
931 #endif | |
932 case kPPC_RotRight32: | |
933 if (HasRegisterInput(instr, 1)) { | 825 if (HasRegisterInput(instr, 1)) { |
934 __ subfic(kScratchReg, i.InputRegister(1), Operand(32)); | 826 __ LoadComplementRR(kScratchReg, i.InputRegister(1)); |
935 __ rotlw(i.OutputRegister(), i.InputRegister(0), kScratchReg, | 827 __ rll(i.OutputRegister(), i.InputRegister(0), kScratchReg); |
936 i.OutputRCBit()); | 828 } else { |
937 } else { | 829 __ rll(i.OutputRegister(), i.InputRegister(0), |
938 int sh = i.InputInt32(1); | 830 Operand(32 - i.InputInt32(1))); |
939 __ rotrwi(i.OutputRegister(), i.InputRegister(0), sh, i.OutputRCBit()); | 831 } |
940 } | 832 break; |
941 break; | 833 #if V8_TARGET_ARCH_S390X |
942 #if V8_TARGET_ARCH_PPC64 | 834 case kS390_RotRight64: |
943 case kPPC_RotRight64: | |
944 if (HasRegisterInput(instr, 1)) { | 835 if (HasRegisterInput(instr, 1)) { |
945 __ subfic(kScratchReg, i.InputRegister(1), Operand(64)); | 836 __ LoadComplementRR(kScratchReg, i.InputRegister(1)); |
946 __ rotld(i.OutputRegister(), i.InputRegister(0), kScratchReg, | 837 __ rll(i.OutputRegister(), i.InputRegister(0), kScratchReg, |
947 i.OutputRCBit()); | 838 Operand(32)); |
948 } else { | 839 __ lgfr(i.OutputRegister(), i.OutputRegister()); |
949 int sh = i.InputInt32(1); | 840 } else { |
950 __ rotrdi(i.OutputRegister(), i.InputRegister(0), sh, i.OutputRCBit()); | 841 UNIMPLEMENTED(); // Not implemented for now |
951 } | 842 } |
952 break; | 843 break; |
953 #endif | 844 #endif |
954 case kPPC_Not: | 845 case kS390_Not: |
955 __ notx(i.OutputRegister(), i.InputRegister(0), i.OutputRCBit()); | 846 __ LoadRR(i.OutputRegister(), i.InputRegister(0)); |
956 break; | 847 __ NotP(i.OutputRegister()); |
957 case kPPC_RotLeftAndMask32: | 848 break; |
958 __ rlwinm(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1), | 849 case kS390_RotLeftAndMask32: |
959 31 - i.InputInt32(2), 31 - i.InputInt32(3), i.OutputRCBit()); | 850 if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) { |
960 break; | 851 int shiftAmount = i.InputInt32(1); |
961 #if V8_TARGET_ARCH_PPC64 | 852 int endBit = 63 - i.InputInt32(3); |
962 case kPPC_RotLeftAndClear64: | 853 int startBit = 63 - i.InputInt32(2); |
963 __ rldic(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1), | 854 __ rll(i.OutputRegister(), i.InputRegister(0), Operand(shiftAmount)); |
964 63 - i.InputInt32(2), i.OutputRCBit()); | 855 __ risbg(i.OutputRegister(), i.OutputRegister(), Operand(startBit), |
965 break; | 856 Operand(endBit), Operand::Zero(), true); |
966 case kPPC_RotLeftAndClearLeft64: | 857 } else { |
967 __ rldicl(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1), | 858 UNIMPLEMENTED(); |
968 63 - i.InputInt32(2), i.OutputRCBit()); | 859 } |
969 break; | 860 break; |
970 case kPPC_RotLeftAndClearRight64: | 861 #if V8_TARGET_ARCH_S390X |
971 __ rldicr(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1), | 862 case kS390_RotLeftAndClear64: |
972 63 - i.InputInt32(2), i.OutputRCBit()); | 863 UNIMPLEMENTED(); // Find correct instruction |
973 break; | 864 break; |
974 #endif | 865 case kS390_RotLeftAndClearLeft64: |
975 case kPPC_Add: | 866 if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) { |
976 #if V8_TARGET_ARCH_PPC64 | 867 int shiftAmount = i.InputInt32(1); |
| 868 int endBit = 63; |
| 869 int startBit = 63 - i.InputInt32(2); |
| 870 __ risbg(i.OutputRegister(), i.InputRegister(0), Operand(startBit), |
| 871 Operand(endBit), Operand(shiftAmount), true); |
| 872 } else { |
| 873 UNIMPLEMENTED(); |
| 874 } |
| 875 break; |
| 876 case kS390_RotLeftAndClearRight64: |
| 877 if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) { |
| 878 int shiftAmount = i.InputInt32(1); |
| 879 int endBit = 63 - i.InputInt32(2); |
| 880 int startBit = 0; |
| 881 __ risbg(i.OutputRegister(), i.InputRegister(0), Operand(startBit), |
| 882 Operand(endBit), Operand(shiftAmount), true); |
| 883 } else { |
| 884 UNIMPLEMENTED(); |
| 885 } |
| 886 break; |
| 887 #endif |
| 888 case kS390_Add: |
| 889 #if V8_TARGET_ARCH_S390X |
977 if (FlagsModeField::decode(instr->opcode()) != kFlags_none) { | 890 if (FlagsModeField::decode(instr->opcode()) != kFlags_none) { |
978 ASSEMBLE_ADD_WITH_OVERFLOW(); | 891 ASSEMBLE_ADD_WITH_OVERFLOW(); |
979 } else { | 892 } else { |
980 #endif | 893 #endif |
981 if (HasRegisterInput(instr, 1)) { | 894 ASSEMBLE_BINOP(AddP, AddP); |
982 __ add(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 895 #if V8_TARGET_ARCH_S390X |
983 LeaveOE, i.OutputRCBit()); | 896 } |
984 } else { | 897 #endif |
985 __ addi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1)); | 898 break; |
986 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 899 case kS390_AddWithOverflow32: |
987 } | |
988 #if V8_TARGET_ARCH_PPC64 | |
989 } | |
990 #endif | |
991 break; | |
992 case kPPC_AddWithOverflow32: | |
993 ASSEMBLE_ADD_WITH_OVERFLOW32(); | 900 ASSEMBLE_ADD_WITH_OVERFLOW32(); |
994 break; | 901 break; |
995 case kPPC_AddDouble: | 902 case kS390_AddFloat: |
996 ASSEMBLE_FLOAT_BINOP_RC(fadd); | 903 // Ensure we don't clobber right/InputReg(1) |
997 break; | 904 if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) { |
998 case kPPC_Sub: | 905 ASSEMBLE_FLOAT_UNOP(aebr); |
999 #if V8_TARGET_ARCH_PPC64 | 906 } else { |
| 907 if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) |
| 908 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
| 909 __ aebr(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); |
| 910 } |
| 911 break; |
| 912 case kS390_AddDouble: |
| 913 // Ensure we don't clobber right/InputReg(1) |
| 914 if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) { |
| 915 ASSEMBLE_FLOAT_UNOP(adbr); |
| 916 } else { |
| 917 if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) |
| 918 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
| 919 __ adbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); |
| 920 } |
| 921 break; |
| 922 case kS390_Sub: |
| 923 #if V8_TARGET_ARCH_S390X |
1000 if (FlagsModeField::decode(instr->opcode()) != kFlags_none) { | 924 if (FlagsModeField::decode(instr->opcode()) != kFlags_none) { |
1001 ASSEMBLE_SUB_WITH_OVERFLOW(); | 925 ASSEMBLE_SUB_WITH_OVERFLOW(); |
1002 } else { | 926 } else { |
1003 #endif | 927 #endif |
1004 if (HasRegisterInput(instr, 1)) { | 928 ASSEMBLE_BINOP(SubP, SubP); |
1005 __ sub(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 929 #if V8_TARGET_ARCH_S390X |
1006 LeaveOE, i.OutputRCBit()); | 930 } |
1007 } else { | 931 #endif |
1008 __ subi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1)); | 932 break; |
1009 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 933 case kS390_SubWithOverflow32: |
| 934 ASSEMBLE_SUB_WITH_OVERFLOW32(); |
| 935 break; |
| 936 case kS390_SubFloat: |
| 937 // OutputDoubleReg() = i.InputDoubleRegister(0) - i.InputDoubleRegister(1) |
| 938 if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) { |
| 939 __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1)); |
| 940 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
| 941 __ sebr(i.OutputDoubleRegister(), kScratchDoubleReg); |
| 942 } else { |
| 943 if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) { |
| 944 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
1010 } | 945 } |
1011 #if V8_TARGET_ARCH_PPC64 | 946 __ sebr(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); |
1012 } | 947 } |
1013 #endif | 948 break; |
1014 break; | 949 case kS390_SubDouble: |
1015 case kPPC_SubWithOverflow32: | 950 // OutputDoubleReg() = i.InputDoubleRegister(0) - i.InputDoubleRegister(1) |
1016 ASSEMBLE_SUB_WITH_OVERFLOW32(); | 951 if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) { |
1017 break; | 952 __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1)); |
1018 case kPPC_SubDouble: | 953 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
1019 ASSEMBLE_FLOAT_BINOP_RC(fsub); | 954 __ sdbr(i.OutputDoubleRegister(), kScratchDoubleReg); |
1020 break; | 955 } else { |
1021 case kPPC_Mul32: | 956 if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) { |
1022 __ mullw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 957 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
1023 LeaveOE, i.OutputRCBit()); | 958 } |
1024 break; | 959 __ sdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); |
1025 #if V8_TARGET_ARCH_PPC64 | 960 } |
1026 case kPPC_Mul64: | 961 break; |
1027 __ mulld(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 962 case kS390_Mul32: |
1028 LeaveOE, i.OutputRCBit()); | 963 #if V8_TARGET_ARCH_S390X |
1029 break; | 964 case kS390_Mul64: |
1030 #endif | 965 #endif |
1031 case kPPC_MulHigh32: | 966 __ Mul(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); |
1032 __ mulhw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 967 break; |
1033 i.OutputRCBit()); | 968 case kS390_MulHigh32: |
1034 break; | 969 __ LoadRR(r1, i.InputRegister(0)); |
1035 case kPPC_MulHighU32: | 970 __ mr_z(r0, i.InputRegister(1)); |
1036 __ mulhwu(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 971 __ LoadRR(i.OutputRegister(), r0); |
1037 i.OutputRCBit()); | 972 break; |
1038 break; | 973 case kS390_MulHighU32: |
1039 case kPPC_MulDouble: | 974 __ LoadRR(r1, i.InputRegister(0)); |
1040 ASSEMBLE_FLOAT_BINOP_RC(fmul); | 975 __ mlr(r0, i.InputRegister(1)); |
1041 break; | 976 __ LoadRR(i.OutputRegister(), r0); |
1042 case kPPC_Div32: | 977 break; |
1043 __ divw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); | 978 case kS390_MulFloat: |
1044 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 979 // Ensure we don't clobber right |
1045 break; | 980 if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) { |
1046 #if V8_TARGET_ARCH_PPC64 | 981 ASSEMBLE_FLOAT_UNOP(meebr); |
1047 case kPPC_Div64: | 982 } else { |
1048 __ divd(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); | 983 if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) |
1049 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 984 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
1050 break; | 985 __ meebr(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); |
1051 #endif | 986 } |
1052 case kPPC_DivU32: | 987 break; |
1053 __ divwu(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); | 988 case kS390_MulDouble: |
1054 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 989 // Ensure we don't clobber right |
1055 break; | 990 if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) { |
1056 #if V8_TARGET_ARCH_PPC64 | 991 ASSEMBLE_FLOAT_UNOP(mdbr); |
1057 case kPPC_DivU64: | 992 } else { |
1058 __ divdu(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); | 993 if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) |
1059 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 994 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
1060 break; | 995 __ mdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); |
1061 #endif | 996 } |
1062 case kPPC_DivDouble: | 997 break; |
1063 ASSEMBLE_FLOAT_BINOP_RC(fdiv); | 998 #if V8_TARGET_ARCH_S390X |
1064 break; | 999 case kS390_Div64: |
1065 case kPPC_Mod32: | 1000 #endif |
1066 ASSEMBLE_MODULO(divw, mullw); | 1001 case kS390_Div32: |
1067 break; | 1002 __ LoadRR(r0, i.InputRegister(0)); |
1068 #if V8_TARGET_ARCH_PPC64 | 1003 __ srda(r0, Operand(32)); |
1069 case kPPC_Mod64: | 1004 __ dr(r0, i.InputRegister(1)); |
1070 ASSEMBLE_MODULO(divd, mulld); | 1005 __ ltr(i.OutputRegister(), r1); |
1071 break; | 1006 break; |
1072 #endif | 1007 #if V8_TARGET_ARCH_S390X |
1073 case kPPC_ModU32: | 1008 case kS390_DivU64: |
1074 ASSEMBLE_MODULO(divwu, mullw); | 1009 __ LoadRR(r1, i.InputRegister(0)); |
1075 break; | 1010 __ LoadImmP(r0, Operand::Zero()); |
1076 #if V8_TARGET_ARCH_PPC64 | 1011 __ dlgr(r0, i.InputRegister(1)); // R0:R1 = R1 / divisor - |
1077 case kPPC_ModU64: | 1012 __ ltgr(i.OutputRegister(), r1); // Copy remainder to output reg |
1078 ASSEMBLE_MODULO(divdu, mulld); | 1013 break; |
1079 break; | 1014 #endif |
1080 #endif | 1015 case kS390_DivU32: |
1081 case kPPC_ModDouble: | 1016 __ LoadRR(r0, i.InputRegister(0)); |
1082 // TODO(bmeurer): We should really get rid of this special instruction, | 1017 __ srdl(r0, Operand(32)); |
1083 // and generate a CallAddress instruction instead. | 1018 __ dlr(r0, i.InputRegister(1)); // R0:R1 = R1 / divisor - |
| 1019 __ ltr(i.OutputRegister(), r1); // Copy remainder to output reg |
| 1020 break; |
| 1021 |
| 1022 case kS390_DivFloat: |
| 1023 // InputDoubleRegister(1)=InputDoubleRegister(0)/InputDoubleRegister(1) |
| 1024 if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) { |
| 1025 __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1)); |
| 1026 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
| 1027 __ debr(i.OutputDoubleRegister(), kScratchDoubleReg); |
| 1028 } else { |
| 1029 if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) |
| 1030 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
| 1031 __ debr(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); |
| 1032 } |
| 1033 break; |
| 1034 case kS390_DivDouble: |
| 1035 // InputDoubleRegister(1)=InputDoubleRegister(0)/InputDoubleRegister(1) |
| 1036 if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) { |
| 1037 __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1)); |
| 1038 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
| 1039 __ ddbr(i.OutputDoubleRegister(), kScratchDoubleReg); |
| 1040 } else { |
| 1041 if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) |
| 1042 __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
| 1043 __ ddbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); |
| 1044 } |
| 1045 break; |
| 1046 case kS390_Mod32: |
| 1047 ASSEMBLE_MODULO(dr, srda); |
| 1048 break; |
| 1049 case kS390_ModU32: |
| 1050 ASSEMBLE_MODULO(dlr, srdl); |
| 1051 break; |
| 1052 #if V8_TARGET_ARCH_S390X |
| 1053 case kS390_Mod64: |
| 1054 ASSEMBLE_MODULO(dr, srda); |
| 1055 break; |
| 1056 case kS390_ModU64: |
| 1057 ASSEMBLE_MODULO(dlr, srdl); |
| 1058 break; |
| 1059 #endif |
| 1060 case kS390_AbsFloat: |
| 1061 __ lpebr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
| 1062 break; |
| 1063 case kS390_SqrtFloat: |
| 1064 ASSEMBLE_FLOAT_UNOP(sqebr); |
| 1065 break; |
| 1066 case kS390_FloorFloat: |
| 1067 // ASSEMBLE_FLOAT_UNOP_RC(frim); |
| 1068 __ FloatFloor32(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
| 1069 kScratchReg); |
| 1070 break; |
| 1071 case kS390_CeilFloat: |
| 1072 __ FloatCeiling32(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
| 1073 kScratchReg, kScratchDoubleReg); |
| 1074 break; |
| 1075 case kS390_TruncateFloat: |
| 1076 __ fiebra(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
| 1077 v8::internal::Assembler::FIDBRA_ROUND_TOWARD_0); |
| 1078 break; |
| 1079 // Double operations |
| 1080 case kS390_ModDouble: |
1084 ASSEMBLE_FLOAT_MODULO(); | 1081 ASSEMBLE_FLOAT_MODULO(); |
1085 break; | 1082 break; |
1086 case kPPC_Neg: | 1083 case kS390_Neg: |
1087 __ neg(i.OutputRegister(), i.InputRegister(0), LeaveOE, i.OutputRCBit()); | 1084 __ LoadComplementRR(i.OutputRegister(), i.InputRegister(0)); |
1088 break; | 1085 break; |
1089 case kPPC_MaxDouble: | 1086 case kS390_MaxDouble: |
1090 ASSEMBLE_FLOAT_MAX(kScratchDoubleReg); | 1087 ASSEMBLE_FLOAT_MAX(kScratchDoubleReg, kScratchReg); |
1091 break; | 1088 break; |
1092 case kPPC_MinDouble: | 1089 case kS390_MinDouble: |
1093 ASSEMBLE_FLOAT_MIN(kScratchDoubleReg); | 1090 ASSEMBLE_FLOAT_MIN(kScratchDoubleReg, kScratchReg); |
1094 break; | 1091 break; |
1095 case kPPC_AbsDouble: | 1092 case kS390_AbsDouble: |
1096 ASSEMBLE_FLOAT_UNOP_RC(fabs); | 1093 __ lpdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
1097 break; | 1094 break; |
1098 case kPPC_SqrtDouble: | 1095 case kS390_SqrtDouble: |
1099 ASSEMBLE_FLOAT_UNOP_RC(fsqrt); | 1096 ASSEMBLE_FLOAT_UNOP(sqdbr); |
1100 break; | 1097 break; |
1101 case kPPC_FloorDouble: | 1098 case kS390_FloorDouble: |
1102 ASSEMBLE_FLOAT_UNOP_RC(frim); | 1099 __ FloatFloor64(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
1103 break; | 1100 kScratchReg); |
1104 case kPPC_CeilDouble: | 1101 break; |
1105 ASSEMBLE_FLOAT_UNOP_RC(frip); | 1102 case kS390_CeilDouble: |
1106 break; | 1103 __ FloatCeiling64(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
1107 case kPPC_TruncateDouble: | 1104 kScratchReg, kScratchDoubleReg); |
1108 ASSEMBLE_FLOAT_UNOP_RC(friz); | 1105 break; |
1109 break; | 1106 case kS390_TruncateDouble: |
1110 case kPPC_RoundDouble: | 1107 __ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
1111 ASSEMBLE_FLOAT_UNOP_RC(frin); | 1108 v8::internal::Assembler::FIDBRA_ROUND_TOWARD_0); |
1112 break; | 1109 break; |
1113 case kPPC_NegDouble: | 1110 case kS390_RoundDouble: |
1114 ASSEMBLE_FLOAT_UNOP_RC(fneg); | 1111 __ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
1115 break; | 1112 v8::internal::Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0); |
1116 case kPPC_Cntlz32: | 1113 break; |
1117 __ cntlzw_(i.OutputRegister(), i.InputRegister(0)); | 1114 case kS390_NegDouble: |
1118 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1115 ASSEMBLE_FLOAT_UNOP(lcdbr); |
1119 break; | 1116 break; |
1120 #if V8_TARGET_ARCH_PPC64 | 1117 case kS390_Cntlz32: { |
1121 case kPPC_Cntlz64: | 1118 __ llgfr(i.OutputRegister(), i.InputRegister(0)); |
1122 __ cntlzd_(i.OutputRegister(), i.InputRegister(0)); | 1119 __ flogr(r0, i.OutputRegister()); |
1123 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1120 __ LoadRR(i.OutputRegister(), r0); |
1124 break; | 1121 __ SubP(i.OutputRegister(), Operand(32)); |
1125 #endif | 1122 } break; |
1126 case kPPC_Popcnt32: | 1123 #if V8_TARGET_ARCH_S390X |
1127 __ popcntw(i.OutputRegister(), i.InputRegister(0)); | 1124 case kS390_Cntlz64: { |
1128 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1125 __ flogr(r0, i.InputRegister(0)); |
1129 break; | 1126 __ LoadRR(i.OutputRegister(), r0); |
1130 #if V8_TARGET_ARCH_PPC64 | 1127 } break; |
1131 case kPPC_Popcnt64: | 1128 #endif |
1132 __ popcntd(i.OutputRegister(), i.InputRegister(0)); | 1129 case kS390_Popcnt32: |
1133 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1130 __ Popcnt32(i.OutputRegister(), i.InputRegister(0)); |
1134 break; | 1131 break; |
1135 #endif | 1132 #if V8_TARGET_ARCH_S390X |
1136 case kPPC_Cmp32: | 1133 case kS390_Popcnt64: |
1137 ASSEMBLE_COMPARE(cmpw, cmplw); | 1134 __ Popcnt64(i.OutputRegister(), i.InputRegister(0)); |
1138 break; | 1135 break; |
1139 #if V8_TARGET_ARCH_PPC64 | 1136 #endif |
1140 case kPPC_Cmp64: | 1137 case kS390_Cmp32: |
1141 ASSEMBLE_COMPARE(cmp, cmpl); | 1138 ASSEMBLE_COMPARE(Cmp32, CmpLogical32); |
1142 break; | 1139 break; |
1143 #endif | 1140 #if V8_TARGET_ARCH_S390X |
1144 case kPPC_CmpDouble: | 1141 case kS390_Cmp64: |
1145 ASSEMBLE_FLOAT_COMPARE(fcmpu); | 1142 ASSEMBLE_COMPARE(CmpP, CmpLogicalP); |
1146 break; | 1143 break; |
1147 case kPPC_Tst32: | 1144 #endif |
| 1145 case kS390_CmpFloat: |
| 1146 __ cebr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); |
| 1147 break; |
| 1148 case kS390_CmpDouble: |
| 1149 __ cdbr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); |
| 1150 break; |
| 1151 case kS390_Tst32: |
1148 if (HasRegisterInput(instr, 1)) { | 1152 if (HasRegisterInput(instr, 1)) { |
1149 __ and_(r0, i.InputRegister(0), i.InputRegister(1), i.OutputRCBit()); | 1153 __ AndP(r0, i.InputRegister(0), i.InputRegister(1)); |
1150 } else { | 1154 } else { |
1151 __ andi(r0, i.InputRegister(0), i.InputImmediate(1)); | 1155 __ AndP(r0, i.InputRegister(0), i.InputImmediate(1)); |
1152 } | 1156 } |
1153 #if V8_TARGET_ARCH_PPC64 | 1157 #if V8_TARGET_ARCH_S390X |
1154 __ extsw(r0, r0, i.OutputRCBit()); | 1158 // TODO(john.yan): use ltgfr here. |
1155 #endif | 1159 __ lgfr(r0, r0); |
1156 DCHECK_EQ(SetRC, i.OutputRCBit()); | 1160 __ LoadAndTestP(r0, r0); |
1157 break; | 1161 #endif |
1158 #if V8_TARGET_ARCH_PPC64 | 1162 break; |
1159 case kPPC_Tst64: | 1163 #if V8_TARGET_ARCH_S390X |
| 1164 case kS390_Tst64: |
1160 if (HasRegisterInput(instr, 1)) { | 1165 if (HasRegisterInput(instr, 1)) { |
1161 __ and_(r0, i.InputRegister(0), i.InputRegister(1), i.OutputRCBit()); | 1166 __ AndP(r0, i.InputRegister(0), i.InputRegister(1)); |
1162 } else { | 1167 } else { |
1163 __ andi(r0, i.InputRegister(0), i.InputImmediate(1)); | 1168 __ AndP(r0, i.InputRegister(0), i.InputImmediate(1)); |
1164 } | 1169 } |
1165 DCHECK_EQ(SetRC, i.OutputRCBit()); | 1170 break; |
1166 break; | 1171 #endif |
1167 #endif | 1172 case kS390_Push: |
1168 case kPPC_Push: | |
1169 if (instr->InputAt(0)->IsDoubleRegister()) { | 1173 if (instr->InputAt(0)->IsDoubleRegister()) { |
1170 __ stfdu(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize)); | 1174 __ StoreDouble(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize)); |
| 1175 __ lay(sp, MemOperand(sp, -kDoubleSize)); |
1171 frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize); | 1176 frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize); |
1172 } else { | 1177 } else { |
1173 __ Push(i.InputRegister(0)); | 1178 __ Push(i.InputRegister(0)); |
1174 frame_access_state()->IncreaseSPDelta(1); | 1179 frame_access_state()->IncreaseSPDelta(1); |
1175 } | 1180 } |
1176 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1181 break; |
1177 break; | 1182 case kS390_PushFrame: { |
1178 case kPPC_PushFrame: { | |
1179 int num_slots = i.InputInt32(1); | 1183 int num_slots = i.InputInt32(1); |
1180 if (instr->InputAt(0)->IsDoubleRegister()) { | 1184 if (instr->InputAt(0)->IsDoubleRegister()) { |
1181 __ stfdu(i.InputDoubleRegister(0), | 1185 __ StoreDouble(i.InputDoubleRegister(0), |
1182 MemOperand(sp, -num_slots * kPointerSize)); | 1186 MemOperand(sp, -num_slots * kPointerSize)); |
1183 } else { | 1187 } else { |
1184 __ StorePU(i.InputRegister(0), | 1188 __ StoreP(i.InputRegister(0), |
1185 MemOperand(sp, -num_slots * kPointerSize)); | 1189 MemOperand(sp, -num_slots * kPointerSize)); |
1186 } | 1190 } |
1187 break; | 1191 __ lay(sp, MemOperand(sp, -num_slots * kPointerSize)); |
1188 } | 1192 break; |
1189 case kPPC_StoreToStackSlot: { | 1193 } |
| 1194 case kS390_StoreToStackSlot: { |
1190 int slot = i.InputInt32(1); | 1195 int slot = i.InputInt32(1); |
1191 if (instr->InputAt(0)->IsDoubleRegister()) { | 1196 if (instr->InputAt(0)->IsDoubleRegister()) { |
1192 __ stfd(i.InputDoubleRegister(0), MemOperand(sp, slot * kPointerSize)); | 1197 __ StoreDouble(i.InputDoubleRegister(0), |
| 1198 MemOperand(sp, slot * kPointerSize)); |
1193 } else { | 1199 } else { |
1194 __ StoreP(i.InputRegister(0), MemOperand(sp, slot * kPointerSize)); | 1200 __ StoreP(i.InputRegister(0), MemOperand(sp, slot * kPointerSize)); |
1195 } | 1201 } |
1196 break; | 1202 break; |
1197 } | 1203 } |
1198 case kPPC_ExtendSignWord8: | 1204 case kS390_ExtendSignWord8: |
1199 __ extsb(i.OutputRegister(), i.InputRegister(0)); | 1205 #if V8_TARGET_ARCH_S390X |
1200 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1206 __ lgbr(i.OutputRegister(), i.InputRegister(0)); |
1201 break; | 1207 #else |
1202 case kPPC_ExtendSignWord16: | 1208 __ lbr(i.OutputRegister(), i.InputRegister(0)); |
1203 __ extsh(i.OutputRegister(), i.InputRegister(0)); | 1209 #endif |
1204 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1210 break; |
1205 break; | 1211 case kS390_ExtendSignWord16: |
1206 #if V8_TARGET_ARCH_PPC64 | 1212 #if V8_TARGET_ARCH_S390X |
1207 case kPPC_ExtendSignWord32: | 1213 __ lghr(i.OutputRegister(), i.InputRegister(0)); |
1208 __ extsw(i.OutputRegister(), i.InputRegister(0)); | 1214 #else |
1209 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1215 __ lhr(i.OutputRegister(), i.InputRegister(0)); |
1210 break; | 1216 #endif |
1211 case kPPC_Uint32ToUint64: | 1217 break; |
| 1218 #if V8_TARGET_ARCH_S390X |
| 1219 case kS390_ExtendSignWord32: |
| 1220 __ lgfr(i.OutputRegister(), i.InputRegister(0)); |
| 1221 break; |
| 1222 case kS390_Uint32ToUint64: |
1212 // Zero extend | 1223 // Zero extend |
1213 __ clrldi(i.OutputRegister(), i.InputRegister(0), Operand(32)); | 1224 __ llgfr(i.OutputRegister(), i.InputRegister(0)); |
1214 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1225 break; |
1215 break; | 1226 case kS390_Int64ToInt32: |
1216 case kPPC_Int64ToInt32: | 1227 // sign extend |
1217 __ extsw(i.OutputRegister(), i.InputRegister(0)); | 1228 __ lgfr(i.OutputRegister(), i.InputRegister(0)); |
1218 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1229 break; |
1219 break; | 1230 case kS390_Int64ToFloat32: |
1220 case kPPC_Int64ToFloat32: | |
1221 __ ConvertInt64ToFloat(i.InputRegister(0), i.OutputDoubleRegister()); | 1231 __ ConvertInt64ToFloat(i.InputRegister(0), i.OutputDoubleRegister()); |
1222 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1232 break; |
1223 break; | 1233 case kS390_Int64ToDouble: |
1224 case kPPC_Int64ToDouble: | |
1225 __ ConvertInt64ToDouble(i.InputRegister(0), i.OutputDoubleRegister()); | 1234 __ ConvertInt64ToDouble(i.InputRegister(0), i.OutputDoubleRegister()); |
1226 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1235 break; |
1227 break; | 1236 case kS390_Uint64ToFloat32: |
1228 case kPPC_Uint64ToFloat32: | |
1229 __ ConvertUnsignedInt64ToFloat(i.InputRegister(0), | 1237 __ ConvertUnsignedInt64ToFloat(i.InputRegister(0), |
1230 i.OutputDoubleRegister()); | 1238 i.OutputDoubleRegister()); |
1231 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1239 break; |
1232 break; | 1240 case kS390_Uint64ToDouble: |
1233 case kPPC_Uint64ToDouble: | |
1234 __ ConvertUnsignedInt64ToDouble(i.InputRegister(0), | 1241 __ ConvertUnsignedInt64ToDouble(i.InputRegister(0), |
1235 i.OutputDoubleRegister()); | 1242 i.OutputDoubleRegister()); |
1236 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1243 break; |
1237 break; | 1244 #endif |
1238 #endif | 1245 case kS390_Int32ToFloat32: |
1239 case kPPC_Int32ToFloat32: | |
1240 __ ConvertIntToFloat(i.InputRegister(0), i.OutputDoubleRegister()); | 1246 __ ConvertIntToFloat(i.InputRegister(0), i.OutputDoubleRegister()); |
1241 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1247 break; |
1242 break; | 1248 case kS390_Int32ToDouble: |
1243 case kPPC_Int32ToDouble: | |
1244 __ ConvertIntToDouble(i.InputRegister(0), i.OutputDoubleRegister()); | 1249 __ ConvertIntToDouble(i.InputRegister(0), i.OutputDoubleRegister()); |
1245 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1250 break; |
1246 break; | 1251 case kS390_Uint32ToFloat32: |
1247 case kPPC_Uint32ToFloat32: | |
1248 __ ConvertUnsignedIntToFloat(i.InputRegister(0), | 1252 __ ConvertUnsignedIntToFloat(i.InputRegister(0), |
1249 i.OutputDoubleRegister()); | 1253 i.OutputDoubleRegister()); |
1250 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1254 break; |
1251 break; | 1255 case kS390_Uint32ToDouble: |
1252 case kPPC_Uint32ToDouble: | |
1253 __ ConvertUnsignedIntToDouble(i.InputRegister(0), | 1256 __ ConvertUnsignedIntToDouble(i.InputRegister(0), |
1254 i.OutputDoubleRegister()); | 1257 i.OutputDoubleRegister()); |
1255 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1258 break; |
1256 break; | 1259 case kS390_DoubleToInt32: |
1257 case kPPC_DoubleToInt32: | 1260 case kS390_DoubleToUint32: |
1258 case kPPC_DoubleToUint32: | 1261 case kS390_DoubleToInt64: { |
1259 case kPPC_DoubleToInt64: { | 1262 #if V8_TARGET_ARCH_S390X |
1260 #if V8_TARGET_ARCH_PPC64 | |
1261 bool check_conversion = | 1263 bool check_conversion = |
1262 (opcode == kPPC_DoubleToInt64 && i.OutputCount() > 1); | 1264 (opcode == kS390_DoubleToInt64 && i.OutputCount() > 1); |
| 1265 #endif |
| 1266 __ ConvertDoubleToInt64(i.InputDoubleRegister(0), |
| 1267 #if !V8_TARGET_ARCH_S390X |
| 1268 kScratchReg, |
| 1269 #endif |
| 1270 i.OutputRegister(0), kScratchDoubleReg); |
| 1271 #if V8_TARGET_ARCH_S390X |
1263 if (check_conversion) { | 1272 if (check_conversion) { |
1264 __ mtfsb0(VXCVI); // clear FPSCR:VXCVI bit | 1273 Label conversion_done; |
1265 } | 1274 __ LoadImmP(i.OutputRegister(1), Operand::Zero()); |
1266 #endif | 1275 __ b(Condition(1), &conversion_done); // special case |
1267 __ ConvertDoubleToInt64(i.InputDoubleRegister(0), | 1276 __ LoadImmP(i.OutputRegister(1), Operand(1)); |
1268 #if !V8_TARGET_ARCH_PPC64 | 1277 __ bind(&conversion_done); |
1269 kScratchReg, | 1278 } |
1270 #endif | 1279 #endif |
1271 i.OutputRegister(0), kScratchDoubleReg); | 1280 break; |
1272 #if V8_TARGET_ARCH_PPC64 | 1281 } |
| 1282 case kS390_Float32ToInt32: { |
| 1283 bool check_conversion = (i.OutputCount() > 1); |
| 1284 __ ConvertFloat32ToInt32(i.InputDoubleRegister(0), i.OutputRegister(0), |
| 1285 kScratchDoubleReg); |
1273 if (check_conversion) { | 1286 if (check_conversion) { |
1274 // Set 2nd output to zero if conversion fails. | 1287 Label conversion_done; |
1275 CRegister cr = cr7; | 1288 __ LoadImmP(i.OutputRegister(1), Operand::Zero()); |
1276 int crbit = v8::internal::Assembler::encode_crbit( | 1289 __ b(Condition(1), &conversion_done); // special case |
1277 cr, static_cast<CRBit>(VXCVI % CRWIDTH)); | 1290 __ LoadImmP(i.OutputRegister(1), Operand(1)); |
1278 __ mcrfs(cr, VXCVI); // extract FPSCR field containing VXCVI into cr7 | 1291 __ bind(&conversion_done); |
1279 if (CpuFeatures::IsSupported(ISELECT)) { | 1292 } |
1280 __ li(i.OutputRegister(1), Operand(1)); | 1293 break; |
1281 __ isel(i.OutputRegister(1), r0, i.OutputRegister(1), crbit); | 1294 } |
1282 } else { | 1295 case kS390_Float32ToUint32: { |
1283 __ li(i.OutputRegister(1), Operand::Zero()); | |
1284 __ bc(v8::internal::Assembler::kInstrSize * 2, BT, crbit); | |
1285 __ li(i.OutputRegister(1), Operand(1)); | |
1286 } | |
1287 } | |
1288 #endif | |
1289 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | |
1290 break; | |
1291 } | |
1292 #if V8_TARGET_ARCH_PPC64 | |
1293 case kPPC_DoubleToUint64: { | |
1294 bool check_conversion = (i.OutputCount() > 1); | 1296 bool check_conversion = (i.OutputCount() > 1); |
| 1297 __ ConvertFloat32ToUnsignedInt32(i.InputDoubleRegister(0), |
| 1298 i.OutputRegister(0), kScratchDoubleReg); |
1295 if (check_conversion) { | 1299 if (check_conversion) { |
1296 __ mtfsb0(VXCVI); // clear FPSCR:VXCVI bit | 1300 Label conversion_done; |
1297 } | 1301 __ LoadImmP(i.OutputRegister(1), Operand::Zero()); |
| 1302 __ b(Condition(1), &conversion_done); // special case |
| 1303 __ LoadImmP(i.OutputRegister(1), Operand(1)); |
| 1304 __ bind(&conversion_done); |
| 1305 } |
| 1306 break; |
| 1307 } |
| 1308 #if V8_TARGET_ARCH_S390X |
| 1309 case kS390_Float32ToUint64: { |
| 1310 bool check_conversion = (i.OutputCount() > 1); |
| 1311 __ ConvertFloat32ToUnsignedInt64(i.InputDoubleRegister(0), |
| 1312 i.OutputRegister(0), kScratchDoubleReg); |
| 1313 if (check_conversion) { |
| 1314 Label conversion_done; |
| 1315 __ LoadImmP(i.OutputRegister(1), Operand::Zero()); |
| 1316 __ b(Condition(1), &conversion_done); // special case |
| 1317 __ LoadImmP(i.OutputRegister(1), Operand(1)); |
| 1318 __ bind(&conversion_done); |
| 1319 } |
| 1320 break; |
| 1321 } |
| 1322 #endif |
| 1323 case kS390_Float32ToInt64: { |
| 1324 #if V8_TARGET_ARCH_S390X |
| 1325 bool check_conversion = |
| 1326 (opcode == kS390_Float32ToInt64 && i.OutputCount() > 1); |
| 1327 #endif |
| 1328 __ ConvertFloat32ToInt64(i.InputDoubleRegister(0), |
| 1329 #if !V8_TARGET_ARCH_S390X |
| 1330 kScratchReg, |
| 1331 #endif |
| 1332 i.OutputRegister(0), kScratchDoubleReg); |
| 1333 #if V8_TARGET_ARCH_S390X |
| 1334 if (check_conversion) { |
| 1335 Label conversion_done; |
| 1336 __ LoadImmP(i.OutputRegister(1), Operand::Zero()); |
| 1337 __ b(Condition(1), &conversion_done); // special case |
| 1338 __ LoadImmP(i.OutputRegister(1), Operand(1)); |
| 1339 __ bind(&conversion_done); |
| 1340 } |
| 1341 #endif |
| 1342 break; |
| 1343 } |
| 1344 #if V8_TARGET_ARCH_S390X |
| 1345 case kS390_DoubleToUint64: { |
| 1346 bool check_conversion = (i.OutputCount() > 1); |
1298 __ ConvertDoubleToUnsignedInt64(i.InputDoubleRegister(0), | 1347 __ ConvertDoubleToUnsignedInt64(i.InputDoubleRegister(0), |
1299 i.OutputRegister(0), kScratchDoubleReg); | 1348 i.OutputRegister(0), kScratchDoubleReg); |
1300 if (check_conversion) { | 1349 if (check_conversion) { |
1301 // Set 2nd output to zero if conversion fails. | 1350 Label conversion_done; |
1302 CRegister cr = cr7; | 1351 __ LoadImmP(i.OutputRegister(1), Operand::Zero()); |
1303 int crbit = v8::internal::Assembler::encode_crbit( | 1352 __ b(Condition(1), &conversion_done); // special case |
1304 cr, static_cast<CRBit>(VXCVI % CRWIDTH)); | 1353 __ LoadImmP(i.OutputRegister(1), Operand(1)); |
1305 __ mcrfs(cr, VXCVI); // extract FPSCR field containing VXCVI into cr7 | 1354 __ bind(&conversion_done); |
1306 if (CpuFeatures::IsSupported(ISELECT)) { | 1355 } |
1307 __ li(i.OutputRegister(1), Operand(1)); | 1356 break; |
1308 __ isel(i.OutputRegister(1), r0, i.OutputRegister(1), crbit); | 1357 } |
1309 } else { | 1358 #endif |
1310 __ li(i.OutputRegister(1), Operand::Zero()); | 1359 case kS390_DoubleToFloat32: |
1311 __ bc(v8::internal::Assembler::kInstrSize * 2, BT, crbit); | 1360 __ ledbr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
1312 __ li(i.OutputRegister(1), Operand(1)); | 1361 break; |
1313 } | 1362 case kS390_Float32ToDouble: |
1314 } | 1363 __ ldebr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
1315 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1364 break; |
1316 break; | 1365 case kS390_DoubleExtractLowWord32: |
1317 } | 1366 // TODO(john.yan): this can cause problem when interrupting, |
1318 #endif | 1367 // use freg->greg instruction |
1319 case kPPC_DoubleToFloat32: | 1368 __ stdy(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize)); |
1320 ASSEMBLE_FLOAT_UNOP_RC(frsp); | 1369 __ LoadlW(i.OutputRegister(), |
1321 break; | 1370 MemOperand(sp, -kDoubleSize + Register::kMantissaOffset)); |
1322 case kPPC_Float32ToDouble: | 1371 break; |
1323 // Nothing to do. | 1372 case kS390_DoubleExtractHighWord32: |
1324 __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); | 1373 // TODO(john.yan): this can cause problem when interrupting, |
1325 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1374 // use freg->greg instruction |
1326 break; | 1375 __ stdy(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize)); |
1327 case kPPC_DoubleExtractLowWord32: | 1376 __ LoadlW(i.OutputRegister(), |
1328 __ MovDoubleLowToInt(i.OutputRegister(), i.InputDoubleRegister(0)); | 1377 MemOperand(sp, -kDoubleSize + Register::kExponentOffset)); |
1329 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1378 break; |
1330 break; | 1379 case kS390_DoubleInsertLowWord32: |
1331 case kPPC_DoubleExtractHighWord32: | 1380 __ InsertDoubleLow(i.OutputDoubleRegister(), i.InputRegister(1)); |
1332 __ MovDoubleHighToInt(i.OutputRegister(), i.InputDoubleRegister(0)); | 1381 break; |
1333 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1382 case kS390_DoubleInsertHighWord32: |
1334 break; | 1383 __ InsertDoubleHigh(i.OutputDoubleRegister(), i.InputRegister(1)); |
1335 case kPPC_DoubleInsertLowWord32: | 1384 break; |
1336 __ InsertDoubleLow(i.OutputDoubleRegister(), i.InputRegister(1), r0); | 1385 case kS390_DoubleConstruct: |
1337 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1386 // TODO(john.yan): this can cause problem when interrupting, |
1338 break; | 1387 // use greg->freg instruction |
1339 case kPPC_DoubleInsertHighWord32: | 1388 #if V8_TARGET_LITTLE_ENDIAN |
1340 __ InsertDoubleHigh(i.OutputDoubleRegister(), i.InputRegister(1), r0); | 1389 __ StoreW(i.InputRegister(0), MemOperand(sp, -kDoubleSize / 2)); |
1341 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1390 __ StoreW(i.InputRegister(1), MemOperand(sp, -kDoubleSize)); |
1342 break; | |
1343 case kPPC_DoubleConstruct: | |
1344 #if V8_TARGET_ARCH_PPC64 | |
1345 __ MovInt64ComponentsToDouble(i.OutputDoubleRegister(), | |
1346 i.InputRegister(0), i.InputRegister(1), r0); | |
1347 #else | 1391 #else |
1348 __ MovInt64ToDouble(i.OutputDoubleRegister(), i.InputRegister(0), | 1392 __ StoreW(i.InputRegister(1), MemOperand(sp, -kDoubleSize / 2)); |
1349 i.InputRegister(1)); | 1393 __ StoreW(i.InputRegister(0), MemOperand(sp, -kDoubleSize)); |
1350 #endif | 1394 #endif |
1351 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1395 __ ldy(i.OutputDoubleRegister(), MemOperand(sp, -kDoubleSize)); |
1352 break; | 1396 break; |
1353 case kPPC_BitcastFloat32ToInt32: | 1397 case kS390_LoadWordS8: |
| 1398 ASSEMBLE_LOAD_INTEGER(LoadlB); |
| 1399 #if V8_TARGET_ARCH_S390X |
| 1400 __ lgbr(i.OutputRegister(), i.OutputRegister()); |
| 1401 #else |
| 1402 __ lbr(i.OutputRegister(), i.OutputRegister()); |
| 1403 #endif |
| 1404 break; |
| 1405 case kS390_BitcastFloat32ToInt32: |
1354 __ MovFloatToInt(i.OutputRegister(), i.InputDoubleRegister(0)); | 1406 __ MovFloatToInt(i.OutputRegister(), i.InputDoubleRegister(0)); |
1355 break; | 1407 break; |
1356 case kPPC_BitcastInt32ToFloat32: | 1408 case kS390_BitcastInt32ToFloat32: |
1357 __ MovIntToFloat(i.OutputDoubleRegister(), i.InputRegister(0)); | 1409 __ MovIntToFloat(i.OutputDoubleRegister(), i.InputRegister(0)); |
1358 break; | 1410 break; |
1359 #if V8_TARGET_ARCH_PPC64 | 1411 #if V8_TARGET_ARCH_S390X |
1360 case kPPC_BitcastDoubleToInt64: | 1412 case kS390_BitcastDoubleToInt64: |
1361 __ MovDoubleToInt64(i.OutputRegister(), i.InputDoubleRegister(0)); | 1413 __ MovDoubleToInt64(i.OutputRegister(), i.InputDoubleRegister(0)); |
1362 break; | 1414 break; |
1363 case kPPC_BitcastInt64ToDouble: | 1415 case kS390_BitcastInt64ToDouble: |
1364 __ MovInt64ToDouble(i.OutputDoubleRegister(), i.InputRegister(0)); | 1416 __ MovInt64ToDouble(i.OutputDoubleRegister(), i.InputRegister(0)); |
1365 break; | 1417 break; |
1366 #endif | 1418 #endif |
1367 case kPPC_LoadWordU8: | 1419 case kS390_LoadWordU8: |
1368 ASSEMBLE_LOAD_INTEGER(lbz, lbzx); | 1420 ASSEMBLE_LOAD_INTEGER(LoadlB); |
1369 break; | 1421 break; |
1370 case kPPC_LoadWordS8: | 1422 case kS390_LoadWordU16: |
1371 ASSEMBLE_LOAD_INTEGER(lbz, lbzx); | 1423 ASSEMBLE_LOAD_INTEGER(LoadLogicalHalfWordP); |
1372 __ extsb(i.OutputRegister(), i.OutputRegister()); | 1424 break; |
1373 break; | 1425 case kS390_LoadWordS16: |
1374 case kPPC_LoadWordU16: | 1426 ASSEMBLE_LOAD_INTEGER(LoadHalfWordP); |
1375 ASSEMBLE_LOAD_INTEGER(lhz, lhzx); | 1427 break; |
1376 break; | 1428 case kS390_LoadWordS32: |
1377 case kPPC_LoadWordS16: | 1429 ASSEMBLE_LOAD_INTEGER(LoadW); |
1378 ASSEMBLE_LOAD_INTEGER(lha, lhax); | 1430 break; |
1379 break; | 1431 #if V8_TARGET_ARCH_S390X |
1380 case kPPC_LoadWordS32: | 1432 case kS390_LoadWord64: |
1381 ASSEMBLE_LOAD_INTEGER(lwa, lwax); | 1433 ASSEMBLE_LOAD_INTEGER(lg); |
1382 break; | 1434 break; |
1383 #if V8_TARGET_ARCH_PPC64 | 1435 #endif |
1384 case kPPC_LoadWord64: | 1436 case kS390_LoadFloat32: |
1385 ASSEMBLE_LOAD_INTEGER(ld, ldx); | 1437 ASSEMBLE_LOAD_FLOAT(LoadFloat32); |
1386 break; | 1438 break; |
1387 #endif | 1439 case kS390_LoadDouble: |
1388 case kPPC_LoadFloat32: | 1440 ASSEMBLE_LOAD_FLOAT(LoadDouble); |
1389 ASSEMBLE_LOAD_FLOAT(lfs, lfsx); | 1441 break; |
1390 break; | 1442 case kS390_StoreWord8: |
1391 case kPPC_LoadDouble: | 1443 ASSEMBLE_STORE_INTEGER(StoreByte); |
1392 ASSEMBLE_LOAD_FLOAT(lfd, lfdx); | 1444 break; |
1393 break; | 1445 case kS390_StoreWord16: |
1394 case kPPC_StoreWord8: | 1446 ASSEMBLE_STORE_INTEGER(StoreHalfWord); |
1395 ASSEMBLE_STORE_INTEGER(stb, stbx); | 1447 break; |
1396 break; | 1448 case kS390_StoreWord32: |
1397 case kPPC_StoreWord16: | 1449 ASSEMBLE_STORE_INTEGER(StoreW); |
1398 ASSEMBLE_STORE_INTEGER(sth, sthx); | 1450 break; |
1399 break; | 1451 #if V8_TARGET_ARCH_S390X |
1400 case kPPC_StoreWord32: | 1452 case kS390_StoreWord64: |
1401 ASSEMBLE_STORE_INTEGER(stw, stwx); | 1453 ASSEMBLE_STORE_INTEGER(StoreP); |
1402 break; | 1454 break; |
1403 #if V8_TARGET_ARCH_PPC64 | 1455 #endif |
1404 case kPPC_StoreWord64: | 1456 case kS390_StoreFloat32: |
1405 ASSEMBLE_STORE_INTEGER(std, stdx); | |
1406 break; | |
1407 #endif | |
1408 case kPPC_StoreFloat32: | |
1409 ASSEMBLE_STORE_FLOAT32(); | 1457 ASSEMBLE_STORE_FLOAT32(); |
1410 break; | 1458 break; |
1411 case kPPC_StoreDouble: | 1459 case kS390_StoreDouble: |
1412 ASSEMBLE_STORE_DOUBLE(); | 1460 ASSEMBLE_STORE_DOUBLE(); |
1413 break; | 1461 break; |
1414 case kCheckedLoadInt8: | 1462 case kCheckedLoadInt8: |
1415 ASSEMBLE_CHECKED_LOAD_INTEGER(lbz, lbzx); | 1463 ASSEMBLE_CHECKED_LOAD_INTEGER(LoadlB); |
1416 __ extsb(i.OutputRegister(), i.OutputRegister()); | 1464 #if V8_TARGET_ARCH_S390X |
| 1465 __ lgbr(i.OutputRegister(), i.OutputRegister()); |
| 1466 #else |
| 1467 __ lbr(i.OutputRegister(), i.OutputRegister()); |
| 1468 #endif |
1417 break; | 1469 break; |
1418 case kCheckedLoadUint8: | 1470 case kCheckedLoadUint8: |
1419 ASSEMBLE_CHECKED_LOAD_INTEGER(lbz, lbzx); | 1471 ASSEMBLE_CHECKED_LOAD_INTEGER(LoadlB); |
1420 break; | 1472 break; |
1421 case kCheckedLoadInt16: | 1473 case kCheckedLoadInt16: |
1422 ASSEMBLE_CHECKED_LOAD_INTEGER(lha, lhax); | 1474 ASSEMBLE_CHECKED_LOAD_INTEGER(LoadHalfWordP); |
1423 break; | 1475 break; |
1424 case kCheckedLoadUint16: | 1476 case kCheckedLoadUint16: |
1425 ASSEMBLE_CHECKED_LOAD_INTEGER(lhz, lhzx); | 1477 ASSEMBLE_CHECKED_LOAD_INTEGER(LoadLogicalHalfWordP); |
1426 break; | 1478 break; |
1427 case kCheckedLoadWord32: | 1479 case kCheckedLoadWord32: |
1428 ASSEMBLE_CHECKED_LOAD_INTEGER(lwa, lwax); | 1480 ASSEMBLE_CHECKED_LOAD_INTEGER(LoadW); |
1429 break; | 1481 break; |
1430 case kCheckedLoadWord64: | 1482 case kCheckedLoadWord64: |
1431 #if V8_TARGET_ARCH_PPC64 | 1483 #if V8_TARGET_ARCH_S390X |
1432 ASSEMBLE_CHECKED_LOAD_INTEGER(ld, ldx); | 1484 ASSEMBLE_CHECKED_LOAD_INTEGER(LoadP); |
1433 #else | 1485 #else |
1434 UNREACHABLE(); | 1486 UNREACHABLE(); |
1435 #endif | 1487 #endif |
1436 break; | 1488 break; |
1437 case kCheckedLoadFloat32: | 1489 case kCheckedLoadFloat32: |
1438 ASSEMBLE_CHECKED_LOAD_FLOAT(lfs, lfsx, 32); | 1490 ASSEMBLE_CHECKED_LOAD_FLOAT(LoadFloat32, 32); |
1439 break; | 1491 break; |
1440 case kCheckedLoadFloat64: | 1492 case kCheckedLoadFloat64: |
1441 ASSEMBLE_CHECKED_LOAD_FLOAT(lfd, lfdx, 64); | 1493 ASSEMBLE_CHECKED_LOAD_FLOAT(LoadDouble, 64); |
1442 break; | 1494 break; |
1443 case kCheckedStoreWord8: | 1495 case kCheckedStoreWord8: |
1444 ASSEMBLE_CHECKED_STORE_INTEGER(stb, stbx); | 1496 ASSEMBLE_CHECKED_STORE_INTEGER(StoreByte); |
1445 break; | 1497 break; |
1446 case kCheckedStoreWord16: | 1498 case kCheckedStoreWord16: |
1447 ASSEMBLE_CHECKED_STORE_INTEGER(sth, sthx); | 1499 ASSEMBLE_CHECKED_STORE_INTEGER(StoreHalfWord); |
1448 break; | 1500 break; |
1449 case kCheckedStoreWord32: | 1501 case kCheckedStoreWord32: |
1450 ASSEMBLE_CHECKED_STORE_INTEGER(stw, stwx); | 1502 ASSEMBLE_CHECKED_STORE_INTEGER(StoreW); |
1451 break; | 1503 break; |
1452 case kCheckedStoreWord64: | 1504 case kCheckedStoreWord64: |
1453 #if V8_TARGET_ARCH_PPC64 | 1505 #if V8_TARGET_ARCH_S390X |
1454 ASSEMBLE_CHECKED_STORE_INTEGER(std, stdx); | 1506 ASSEMBLE_CHECKED_STORE_INTEGER(StoreP); |
1455 #else | 1507 #else |
1456 UNREACHABLE(); | 1508 UNREACHABLE(); |
1457 #endif | 1509 #endif |
1458 break; | 1510 break; |
1459 case kCheckedStoreFloat32: | 1511 case kCheckedStoreFloat32: |
1460 ASSEMBLE_CHECKED_STORE_FLOAT32(); | 1512 ASSEMBLE_CHECKED_STORE_FLOAT32(); |
1461 break; | 1513 break; |
1462 case kCheckedStoreFloat64: | 1514 case kCheckedStoreFloat64: |
1463 ASSEMBLE_CHECKED_STORE_DOUBLE(); | 1515 ASSEMBLE_CHECKED_STORE_DOUBLE(); |
1464 break; | 1516 break; |
1465 default: | 1517 default: |
1466 UNREACHABLE(); | 1518 UNREACHABLE(); |
1467 break; | 1519 break; |
1468 } | 1520 } |
1469 } // NOLINT(readability/fn_size) | 1521 } // NOLINT(readability/fn_size) |
1470 | 1522 |
1471 | |
1472 // Assembles branches after an instruction. | 1523 // Assembles branches after an instruction. |
1473 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 1524 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
1474 PPCOperandConverter i(this, instr); | 1525 S390OperandConverter i(this, instr); |
1475 Label* tlabel = branch->true_label; | 1526 Label* tlabel = branch->true_label; |
1476 Label* flabel = branch->false_label; | 1527 Label* flabel = branch->false_label; |
1477 ArchOpcode op = instr->arch_opcode(); | 1528 ArchOpcode op = instr->arch_opcode(); |
1478 FlagsCondition condition = branch->condition; | 1529 FlagsCondition condition = branch->condition; |
1479 CRegister cr = cr0; | |
1480 | 1530 |
1481 Condition cond = FlagsConditionToCondition(condition, op); | 1531 Condition cond = FlagsConditionToCondition(condition, op); |
1482 if (op == kPPC_CmpDouble) { | 1532 if (op == kS390_CmpDouble) { |
1483 // check for unordered if necessary | 1533 // check for unordered if necessary |
1484 if (cond == le) { | 1534 // Branching to flabel/tlabel according to what's expected by tests |
1485 __ bunordered(flabel, cr); | 1535 if (cond == le || cond == eq || cond == lt) { |
1486 // Unnecessary for eq/lt since only FU bit will be set. | 1536 __ bunordered(flabel); |
1487 } else if (cond == gt) { | 1537 } else if (cond == gt || cond == ne || cond == ge) { |
1488 __ bunordered(tlabel, cr); | 1538 __ bunordered(tlabel); |
1489 // Unnecessary for ne/ge since only FU bit will be set. | |
1490 } | 1539 } |
1491 } | 1540 } |
1492 __ b(cond, tlabel, cr); | 1541 __ b(cond, tlabel); |
1493 if (!branch->fallthru) __ b(flabel); // no fallthru to flabel. | 1542 if (!branch->fallthru) __ b(flabel); // no fallthru to flabel. |
1494 } | 1543 } |
1495 | 1544 |
1496 | |
1497 void CodeGenerator::AssembleArchJump(RpoNumber target) { | 1545 void CodeGenerator::AssembleArchJump(RpoNumber target) { |
1498 if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target)); | 1546 if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target)); |
1499 } | 1547 } |
1500 | 1548 |
1501 | |
1502 // Assembles boolean materializations after an instruction. | 1549 // Assembles boolean materializations after an instruction. |
1503 void CodeGenerator::AssembleArchBoolean(Instruction* instr, | 1550 void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
1504 FlagsCondition condition) { | 1551 FlagsCondition condition) { |
1505 PPCOperandConverter i(this, instr); | 1552 S390OperandConverter i(this, instr); |
1506 Label done; | 1553 Label done; |
1507 ArchOpcode op = instr->arch_opcode(); | 1554 ArchOpcode op = instr->arch_opcode(); |
1508 CRegister cr = cr0; | 1555 bool check_unordered = (op == kS390_CmpDouble || kS390_CmpFloat); |
1509 int reg_value = -1; | 1556 |
| 1557 // Overflow checked for add/sub only. |
| 1558 DCHECK((condition != kOverflow && condition != kNotOverflow) || |
| 1559 (op == kS390_AddWithOverflow32 || op == kS390_SubWithOverflow32)); |
1510 | 1560 |
1511 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 1561 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
1512 // last output of the instruction. | 1562 // last output of the instruction. |
1513 DCHECK_NE(0u, instr->OutputCount()); | 1563 DCHECK_NE(0u, instr->OutputCount()); |
1514 Register reg = i.OutputRegister(instr->OutputCount() - 1); | 1564 Register reg = i.OutputRegister(instr->OutputCount() - 1); |
1515 | |
1516 Condition cond = FlagsConditionToCondition(condition, op); | 1565 Condition cond = FlagsConditionToCondition(condition, op); |
1517 if (op == kPPC_CmpDouble) { | 1566 switch (cond) { |
1518 // check for unordered if necessary | 1567 case ne: |
1519 if (cond == le) { | 1568 case ge: |
1520 reg_value = 0; | 1569 case gt: |
1521 __ li(reg, Operand::Zero()); | 1570 if (check_unordered) { |
1522 __ bunordered(&done, cr); | 1571 __ LoadImmP(reg, Operand(1)); |
1523 } else if (cond == gt) { | 1572 __ LoadImmP(kScratchReg, Operand::Zero()); |
1524 reg_value = 1; | 1573 __ bunordered(&done); |
1525 __ li(reg, Operand(1)); | 1574 Label cond_true; |
1526 __ bunordered(&done, cr); | 1575 __ b(cond, &cond_true, Label::kNear); |
1527 } | 1576 __ LoadRR(reg, kScratchReg); |
1528 // Unnecessary for eq/lt & ne/ge since only FU bit will be set. | 1577 __ bind(&cond_true); |
1529 } | 1578 } else { |
1530 | 1579 Label cond_true, done_here; |
1531 if (CpuFeatures::IsSupported(ISELECT)) { | 1580 __ LoadImmP(reg, Operand(1)); |
1532 switch (cond) { | 1581 __ b(cond, &cond_true, Label::kNear); |
1533 case eq: | 1582 __ LoadImmP(reg, Operand::Zero()); |
1534 case lt: | 1583 __ bind(&cond_true); |
1535 case gt: | 1584 } |
1536 if (reg_value != 1) __ li(reg, Operand(1)); | 1585 break; |
1537 __ li(kScratchReg, Operand::Zero()); | 1586 case eq: |
1538 __ isel(cond, reg, reg, kScratchReg, cr); | 1587 case lt: |
1539 break; | 1588 case le: |
1540 case ne: | 1589 if (check_unordered) { |
1541 case ge: | 1590 __ LoadImmP(reg, Operand::Zero()); |
1542 case le: | 1591 __ LoadImmP(kScratchReg, Operand(1)); |
1543 if (reg_value != 1) __ li(reg, Operand(1)); | 1592 __ bunordered(&done); |
1544 // r0 implies logical zero in this form | 1593 Label cond_false; |
1545 __ isel(NegateCondition(cond), reg, r0, reg, cr); | 1594 __ b(NegateCondition(cond), &cond_false, Label::kNear); |
1546 break; | 1595 __ LoadRR(reg, kScratchReg); |
| 1596 __ bind(&cond_false); |
| 1597 } else { |
| 1598 __ LoadImmP(reg, Operand::Zero()); |
| 1599 Label cond_false; |
| 1600 __ b(NegateCondition(cond), &cond_false, Label::kNear); |
| 1601 __ LoadImmP(reg, Operand(1)); |
| 1602 __ bind(&cond_false); |
| 1603 } |
| 1604 break; |
1547 default: | 1605 default: |
1548 UNREACHABLE(); | 1606 UNREACHABLE(); |
1549 break; | 1607 break; |
1550 } | |
1551 } else { | |
1552 if (reg_value != 0) __ li(reg, Operand::Zero()); | |
1553 __ b(NegateCondition(cond), &done, cr); | |
1554 __ li(reg, Operand(1)); | |
1555 } | 1608 } |
1556 __ bind(&done); | 1609 __ bind(&done); |
1557 } | 1610 } |
1558 | 1611 |
1559 | |
1560 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { | 1612 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { |
1561 PPCOperandConverter i(this, instr); | 1613 S390OperandConverter i(this, instr); |
1562 Register input = i.InputRegister(0); | 1614 Register input = i.InputRegister(0); |
1563 for (size_t index = 2; index < instr->InputCount(); index += 2) { | 1615 for (size_t index = 2; index < instr->InputCount(); index += 2) { |
1564 __ Cmpi(input, Operand(i.InputInt32(index + 0)), r0); | 1616 __ CmpP(input, Operand(i.InputInt32(index + 0))); |
1565 __ beq(GetLabel(i.InputRpo(index + 1))); | 1617 __ beq(GetLabel(i.InputRpo(index + 1))); |
1566 } | 1618 } |
1567 AssembleArchJump(i.InputRpo(1)); | 1619 AssembleArchJump(i.InputRpo(1)); |
1568 } | 1620 } |
1569 | 1621 |
1570 | |
1571 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) { | 1622 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) { |
1572 PPCOperandConverter i(this, instr); | 1623 S390OperandConverter i(this, instr); |
1573 Register input = i.InputRegister(0); | 1624 Register input = i.InputRegister(0); |
1574 int32_t const case_count = static_cast<int32_t>(instr->InputCount() - 2); | 1625 int32_t const case_count = static_cast<int32_t>(instr->InputCount() - 2); |
1575 Label** cases = zone()->NewArray<Label*>(case_count); | 1626 Label** cases = zone()->NewArray<Label*>(case_count); |
1576 for (int32_t index = 0; index < case_count; ++index) { | 1627 for (int32_t index = 0; index < case_count; ++index) { |
1577 cases[index] = GetLabel(i.InputRpo(index + 2)); | 1628 cases[index] = GetLabel(i.InputRpo(index + 2)); |
1578 } | 1629 } |
1579 Label* const table = AddJumpTable(cases, case_count); | 1630 Label* const table = AddJumpTable(cases, case_count); |
1580 __ Cmpli(input, Operand(case_count), r0); | 1631 __ CmpLogicalP(input, Operand(case_count)); |
1581 __ bge(GetLabel(i.InputRpo(1))); | 1632 __ bge(GetLabel(i.InputRpo(1))); |
1582 __ mov_label_addr(kScratchReg, table); | 1633 __ larl(kScratchReg, table); |
1583 __ ShiftLeftImm(r0, input, Operand(kPointerSizeLog2)); | 1634 __ ShiftLeftP(r1, input, Operand(kPointerSizeLog2)); |
1584 __ LoadPX(kScratchReg, MemOperand(kScratchReg, r0)); | 1635 __ LoadP(kScratchReg, MemOperand(kScratchReg, r1)); |
1585 __ Jump(kScratchReg); | 1636 __ Jump(kScratchReg); |
1586 } | 1637 } |
1587 | 1638 |
1588 | |
1589 void CodeGenerator::AssembleDeoptimizerCall( | 1639 void CodeGenerator::AssembleDeoptimizerCall( |
1590 int deoptimization_id, Deoptimizer::BailoutType bailout_type) { | 1640 int deoptimization_id, Deoptimizer::BailoutType bailout_type) { |
1591 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | 1641 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( |
1592 isolate(), deoptimization_id, bailout_type); | 1642 isolate(), deoptimization_id, bailout_type); |
1593 // TODO(turbofan): We should be able to generate better code by sharing the | 1643 // TODO(turbofan): We should be able to generate better code by sharing the |
1594 // actual final call site and just bl'ing to it here, similar to what we do | 1644 // actual final call site and just bl'ing to it here, similar to what we do |
1595 // in the lithium backend. | 1645 // in the lithium backend. |
1596 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | 1646 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); |
1597 } | 1647 } |
1598 | 1648 |
1599 | |
1600 void CodeGenerator::AssemblePrologue() { | 1649 void CodeGenerator::AssemblePrologue() { |
1601 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1650 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| 1651 |
1602 if (descriptor->IsCFunctionCall()) { | 1652 if (descriptor->IsCFunctionCall()) { |
1603 __ function_descriptor(); | 1653 __ Push(r14, fp); |
1604 __ mflr(r0); | 1654 __ LoadRR(fp, sp); |
1605 if (FLAG_enable_embedded_constant_pool) { | |
1606 __ Push(r0, fp, kConstantPoolRegister); | |
1607 // Adjust FP to point to saved FP. | |
1608 __ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset)); | |
1609 } else { | |
1610 __ Push(r0, fp); | |
1611 __ mr(fp, sp); | |
1612 } | |
1613 } else if (descriptor->IsJSFunctionCall()) { | 1655 } else if (descriptor->IsJSFunctionCall()) { |
1614 __ Prologue(this->info()->GeneratePreagedPrologue(), ip); | 1656 __ Prologue(this->info()->GeneratePreagedPrologue(), ip); |
1615 } else if (frame()->needs_frame()) { | 1657 } else if (frame()->needs_frame()) { |
1616 if (!ABI_CALL_VIA_IP && info()->output_code_kind() == Code::WASM_FUNCTION) { | 1658 if (!ABI_CALL_VIA_IP && info()->output_code_kind() == Code::WASM_FUNCTION) { |
1617 // TODO(mbrandy): Restrict only to the wasm wrapper case. | 1659 // TODO(mbrandy): Restrict only to the wasm wrapper case. |
1618 __ StubPrologue(); | 1660 __ StubPrologue(); |
1619 } else { | 1661 } else { |
1620 __ StubPrologue(ip); | 1662 __ StubPrologue(ip); |
1621 } | 1663 } |
1622 } else { | 1664 } else { |
(...skipping 13 matching lines...) Expand all Loading... |
1636 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); | 1678 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); |
1637 osr_pc_offset_ = __ pc_offset(); | 1679 osr_pc_offset_ = __ pc_offset(); |
1638 stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots(); | 1680 stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots(); |
1639 } | 1681 } |
1640 | 1682 |
1641 const RegList double_saves = descriptor->CalleeSavedFPRegisters(); | 1683 const RegList double_saves = descriptor->CalleeSavedFPRegisters(); |
1642 if (double_saves != 0) { | 1684 if (double_saves != 0) { |
1643 stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots(); | 1685 stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots(); |
1644 } | 1686 } |
1645 if (stack_shrink_slots > 0) { | 1687 if (stack_shrink_slots > 0) { |
1646 __ Add(sp, sp, -stack_shrink_slots * kPointerSize, r0); | 1688 __ lay(sp, MemOperand(sp, -stack_shrink_slots * kPointerSize)); |
1647 } | 1689 } |
1648 | 1690 |
1649 // Save callee-saved Double registers. | 1691 // Save callee-saved Double registers. |
1650 if (double_saves != 0) { | 1692 if (double_saves != 0) { |
1651 __ MultiPushDoubles(double_saves); | 1693 __ MultiPushDoubles(double_saves); |
1652 DCHECK(kNumCalleeSavedDoubles == | 1694 DCHECK(kNumCalleeSavedDoubles == |
1653 base::bits::CountPopulation32(double_saves)); | 1695 base::bits::CountPopulation32(double_saves)); |
1654 frame()->AllocateSavedCalleeRegisterSlots(kNumCalleeSavedDoubles * | 1696 frame()->AllocateSavedCalleeRegisterSlots(kNumCalleeSavedDoubles * |
1655 (kDoubleSize / kPointerSize)); | 1697 (kDoubleSize / kPointerSize)); |
1656 } | 1698 } |
1657 | 1699 |
1658 // Save callee-saved registers. | 1700 // Save callee-saved registers. |
1659 const RegList saves = | 1701 const RegList saves = descriptor->CalleeSavedRegisters(); |
1660 FLAG_enable_embedded_constant_pool | |
1661 ? descriptor->CalleeSavedRegisters() & ~kConstantPoolRegister.bit() | |
1662 : descriptor->CalleeSavedRegisters(); | |
1663 if (saves != 0) { | 1702 if (saves != 0) { |
1664 __ MultiPush(saves); | 1703 __ MultiPush(saves); |
1665 // register save area does not include the fp or constant pool pointer. | 1704 // register save area does not include the fp or constant pool pointer. |
1666 const int num_saves = | 1705 const int num_saves = |
1667 kNumCalleeSaved - 1 - (FLAG_enable_embedded_constant_pool ? 1 : 0); | 1706 kNumCalleeSaved - 1 - (FLAG_enable_embedded_constant_pool ? 1 : 0); |
1668 DCHECK(num_saves == base::bits::CountPopulation32(saves)); | 1707 DCHECK(num_saves == base::bits::CountPopulation32(saves)); |
1669 frame()->AllocateSavedCalleeRegisterSlots(num_saves); | 1708 frame()->AllocateSavedCalleeRegisterSlots(num_saves); |
1670 } | 1709 } |
1671 } | 1710 } |
1672 | 1711 |
1673 | |
1674 void CodeGenerator::AssembleReturn() { | 1712 void CodeGenerator::AssembleReturn() { |
1675 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1713 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
1676 int pop_count = static_cast<int>(descriptor->StackParameterCount()); | 1714 int pop_count = static_cast<int>(descriptor->StackParameterCount()); |
1677 | 1715 |
1678 // Restore registers. | 1716 // Restore registers. |
1679 const RegList saves = | 1717 const RegList saves = descriptor->CalleeSavedRegisters(); |
1680 FLAG_enable_embedded_constant_pool | |
1681 ? descriptor->CalleeSavedRegisters() & ~kConstantPoolRegister.bit() | |
1682 : descriptor->CalleeSavedRegisters(); | |
1683 if (saves != 0) { | 1718 if (saves != 0) { |
1684 __ MultiPop(saves); | 1719 __ MultiPop(saves); |
1685 } | 1720 } |
1686 | 1721 |
1687 // Restore double registers. | 1722 // Restore double registers. |
1688 const RegList double_saves = descriptor->CalleeSavedFPRegisters(); | 1723 const RegList double_saves = descriptor->CalleeSavedFPRegisters(); |
1689 if (double_saves != 0) { | 1724 if (double_saves != 0) { |
1690 __ MultiPopDoubles(double_saves); | 1725 __ MultiPopDoubles(double_saves); |
1691 } | 1726 } |
1692 | 1727 |
1693 if (descriptor->IsCFunctionCall()) { | 1728 if (descriptor->IsCFunctionCall()) { |
1694 __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize); | 1729 __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize); |
1695 } else if (frame()->needs_frame()) { | 1730 } else if (frame()->needs_frame()) { |
1696 // Canonicalize JSFunction return sites for now. | 1731 // Canonicalize JSFunction return sites for now. |
1697 if (return_label_.is_bound()) { | 1732 if (return_label_.is_bound()) { |
1698 __ b(&return_label_); | 1733 __ b(&return_label_); |
1699 return; | 1734 return; |
1700 } else { | 1735 } else { |
1701 __ bind(&return_label_); | 1736 __ bind(&return_label_); |
1702 __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize); | 1737 __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize); |
1703 } | 1738 } |
1704 } else { | 1739 } else { |
1705 __ Drop(pop_count); | 1740 __ Drop(pop_count); |
1706 } | 1741 } |
1707 __ Ret(); | 1742 __ Ret(); |
1708 } | 1743 } |
1709 | 1744 |
1710 | |
1711 void CodeGenerator::AssembleMove(InstructionOperand* source, | 1745 void CodeGenerator::AssembleMove(InstructionOperand* source, |
1712 InstructionOperand* destination) { | 1746 InstructionOperand* destination) { |
1713 PPCOperandConverter g(this, nullptr); | 1747 S390OperandConverter g(this, nullptr); |
1714 // Dispatch on the source and destination operand kinds. Not all | 1748 // Dispatch on the source and destination operand kinds. Not all |
1715 // combinations are possible. | 1749 // combinations are possible. |
1716 if (source->IsRegister()) { | 1750 if (source->IsRegister()) { |
1717 DCHECK(destination->IsRegister() || destination->IsStackSlot()); | 1751 DCHECK(destination->IsRegister() || destination->IsStackSlot()); |
1718 Register src = g.ToRegister(source); | 1752 Register src = g.ToRegister(source); |
1719 if (destination->IsRegister()) { | 1753 if (destination->IsRegister()) { |
1720 __ Move(g.ToRegister(destination), src); | 1754 __ Move(g.ToRegister(destination), src); |
1721 } else { | 1755 } else { |
1722 __ StoreP(src, g.ToMemOperand(destination), r0); | 1756 __ StoreP(src, g.ToMemOperand(destination)); |
1723 } | 1757 } |
1724 } else if (source->IsStackSlot()) { | 1758 } else if (source->IsStackSlot()) { |
1725 DCHECK(destination->IsRegister() || destination->IsStackSlot()); | 1759 DCHECK(destination->IsRegister() || destination->IsStackSlot()); |
1726 MemOperand src = g.ToMemOperand(source); | 1760 MemOperand src = g.ToMemOperand(source); |
1727 if (destination->IsRegister()) { | 1761 if (destination->IsRegister()) { |
1728 __ LoadP(g.ToRegister(destination), src, r0); | 1762 __ LoadP(g.ToRegister(destination), src); |
1729 } else { | 1763 } else { |
1730 Register temp = kScratchReg; | 1764 Register temp = kScratchReg; |
1731 __ LoadP(temp, src, r0); | 1765 __ LoadP(temp, src, r0); |
1732 __ StoreP(temp, g.ToMemOperand(destination), r0); | 1766 __ StoreP(temp, g.ToMemOperand(destination)); |
1733 } | 1767 } |
1734 } else if (source->IsConstant()) { | 1768 } else if (source->IsConstant()) { |
1735 Constant src = g.ToConstant(source); | 1769 Constant src = g.ToConstant(source); |
1736 if (destination->IsRegister() || destination->IsStackSlot()) { | 1770 if (destination->IsRegister() || destination->IsStackSlot()) { |
1737 Register dst = | 1771 Register dst = |
1738 destination->IsRegister() ? g.ToRegister(destination) : kScratchReg; | 1772 destination->IsRegister() ? g.ToRegister(destination) : kScratchReg; |
1739 switch (src.type()) { | 1773 switch (src.type()) { |
1740 case Constant::kInt32: | 1774 case Constant::kInt32: |
1741 __ mov(dst, Operand(src.ToInt32())); | 1775 __ mov(dst, Operand(src.ToInt32())); |
1742 break; | 1776 break; |
(...skipping 18 matching lines...) Expand all Loading... |
1761 if (IsMaterializableFromFrame(src_object, &offset)) { | 1795 if (IsMaterializableFromFrame(src_object, &offset)) { |
1762 __ LoadP(dst, MemOperand(fp, offset)); | 1796 __ LoadP(dst, MemOperand(fp, offset)); |
1763 } else if (IsMaterializableFromRoot(src_object, &index)) { | 1797 } else if (IsMaterializableFromRoot(src_object, &index)) { |
1764 __ LoadRoot(dst, index); | 1798 __ LoadRoot(dst, index); |
1765 } else { | 1799 } else { |
1766 __ Move(dst, src_object); | 1800 __ Move(dst, src_object); |
1767 } | 1801 } |
1768 break; | 1802 break; |
1769 } | 1803 } |
1770 case Constant::kRpoNumber: | 1804 case Constant::kRpoNumber: |
1771 UNREACHABLE(); // TODO(dcarney): loading RPO constants on PPC. | 1805 UNREACHABLE(); // TODO(dcarney): loading RPO constants on S390. |
1772 break; | 1806 break; |
1773 } | 1807 } |
1774 if (destination->IsStackSlot()) { | 1808 if (destination->IsStackSlot()) { |
1775 __ StoreP(dst, g.ToMemOperand(destination), r0); | 1809 __ StoreP(dst, g.ToMemOperand(destination), r0); |
1776 } | 1810 } |
1777 } else { | 1811 } else { |
1778 DoubleRegister dst = destination->IsDoubleRegister() | 1812 DoubleRegister dst = destination->IsDoubleRegister() |
1779 ? g.ToDoubleRegister(destination) | 1813 ? g.ToDoubleRegister(destination) |
1780 : kScratchDoubleReg; | 1814 : kScratchDoubleReg; |
1781 double value = (src.type() == Constant::kFloat32) ? src.ToFloat32() | 1815 double value = (src.type() == Constant::kFloat32) ? src.ToFloat32() |
1782 : src.ToFloat64(); | 1816 : src.ToFloat64(); |
1783 __ LoadDoubleLiteral(dst, value, kScratchReg); | 1817 if (src.type() == Constant::kFloat32) { |
| 1818 __ LoadFloat32Literal(dst, src.ToFloat32(), kScratchReg); |
| 1819 } else { |
| 1820 __ LoadDoubleLiteral(dst, value, kScratchReg); |
| 1821 } |
| 1822 |
1784 if (destination->IsDoubleStackSlot()) { | 1823 if (destination->IsDoubleStackSlot()) { |
1785 __ StoreDouble(dst, g.ToMemOperand(destination), r0); | 1824 __ StoreDouble(dst, g.ToMemOperand(destination)); |
1786 } | 1825 } |
1787 } | 1826 } |
1788 } else if (source->IsDoubleRegister()) { | 1827 } else if (source->IsDoubleRegister()) { |
1789 DoubleRegister src = g.ToDoubleRegister(source); | 1828 DoubleRegister src = g.ToDoubleRegister(source); |
1790 if (destination->IsDoubleRegister()) { | 1829 if (destination->IsDoubleRegister()) { |
1791 DoubleRegister dst = g.ToDoubleRegister(destination); | 1830 DoubleRegister dst = g.ToDoubleRegister(destination); |
1792 __ Move(dst, src); | 1831 __ Move(dst, src); |
1793 } else { | 1832 } else { |
1794 DCHECK(destination->IsDoubleStackSlot()); | 1833 DCHECK(destination->IsDoubleStackSlot()); |
1795 __ StoreDouble(src, g.ToMemOperand(destination), r0); | 1834 __ StoreDouble(src, g.ToMemOperand(destination)); |
1796 } | 1835 } |
1797 } else if (source->IsDoubleStackSlot()) { | 1836 } else if (source->IsDoubleStackSlot()) { |
1798 DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot()); | 1837 DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot()); |
1799 MemOperand src = g.ToMemOperand(source); | 1838 MemOperand src = g.ToMemOperand(source); |
1800 if (destination->IsDoubleRegister()) { | 1839 if (destination->IsDoubleRegister()) { |
1801 __ LoadDouble(g.ToDoubleRegister(destination), src, r0); | 1840 __ LoadDouble(g.ToDoubleRegister(destination), src); |
1802 } else { | 1841 } else { |
1803 DoubleRegister temp = kScratchDoubleReg; | 1842 DoubleRegister temp = kScratchDoubleReg; |
1804 __ LoadDouble(temp, src, r0); | 1843 __ LoadDouble(temp, src); |
1805 __ StoreDouble(temp, g.ToMemOperand(destination), r0); | 1844 __ StoreDouble(temp, g.ToMemOperand(destination)); |
1806 } | 1845 } |
1807 } else { | 1846 } else { |
1808 UNREACHABLE(); | 1847 UNREACHABLE(); |
1809 } | 1848 } |
1810 } | 1849 } |
1811 | 1850 |
1812 | |
1813 void CodeGenerator::AssembleSwap(InstructionOperand* source, | 1851 void CodeGenerator::AssembleSwap(InstructionOperand* source, |
1814 InstructionOperand* destination) { | 1852 InstructionOperand* destination) { |
1815 PPCOperandConverter g(this, nullptr); | 1853 S390OperandConverter g(this, nullptr); |
1816 // Dispatch on the source and destination operand kinds. Not all | 1854 // Dispatch on the source and destination operand kinds. Not all |
1817 // combinations are possible. | 1855 // combinations are possible. |
1818 if (source->IsRegister()) { | 1856 if (source->IsRegister()) { |
1819 // Register-register. | 1857 // Register-register. |
1820 Register temp = kScratchReg; | 1858 Register temp = kScratchReg; |
1821 Register src = g.ToRegister(source); | 1859 Register src = g.ToRegister(source); |
1822 if (destination->IsRegister()) { | 1860 if (destination->IsRegister()) { |
1823 Register dst = g.ToRegister(destination); | 1861 Register dst = g.ToRegister(destination); |
1824 __ mr(temp, src); | 1862 __ LoadRR(temp, src); |
1825 __ mr(src, dst); | 1863 __ LoadRR(src, dst); |
1826 __ mr(dst, temp); | 1864 __ LoadRR(dst, temp); |
1827 } else { | 1865 } else { |
1828 DCHECK(destination->IsStackSlot()); | 1866 DCHECK(destination->IsStackSlot()); |
1829 MemOperand dst = g.ToMemOperand(destination); | 1867 MemOperand dst = g.ToMemOperand(destination); |
1830 __ mr(temp, src); | 1868 __ LoadRR(temp, src); |
1831 __ LoadP(src, dst); | 1869 __ LoadP(src, dst); |
1832 __ StoreP(temp, dst); | 1870 __ StoreP(temp, dst); |
1833 } | 1871 } |
1834 #if V8_TARGET_ARCH_PPC64 | 1872 #if V8_TARGET_ARCH_S390X |
1835 } else if (source->IsStackSlot() || source->IsDoubleStackSlot()) { | 1873 } else if (source->IsStackSlot() || source->IsDoubleStackSlot()) { |
1836 #else | 1874 #else |
1837 } else if (source->IsStackSlot()) { | 1875 } else if (source->IsStackSlot()) { |
1838 DCHECK(destination->IsStackSlot()); | 1876 DCHECK(destination->IsStackSlot()); |
1839 #endif | 1877 #endif |
1840 Register temp_0 = kScratchReg; | 1878 Register temp_0 = kScratchReg; |
1841 Register temp_1 = r0; | 1879 Register temp_1 = r0; |
1842 MemOperand src = g.ToMemOperand(source); | 1880 MemOperand src = g.ToMemOperand(source); |
1843 MemOperand dst = g.ToMemOperand(destination); | 1881 MemOperand dst = g.ToMemOperand(destination); |
1844 __ LoadP(temp_0, src); | 1882 __ LoadP(temp_0, src); |
1845 __ LoadP(temp_1, dst); | 1883 __ LoadP(temp_1, dst); |
1846 __ StoreP(temp_0, dst); | 1884 __ StoreP(temp_0, dst); |
1847 __ StoreP(temp_1, src); | 1885 __ StoreP(temp_1, src); |
1848 } else if (source->IsDoubleRegister()) { | 1886 } else if (source->IsDoubleRegister()) { |
1849 DoubleRegister temp = kScratchDoubleReg; | 1887 DoubleRegister temp = kScratchDoubleReg; |
1850 DoubleRegister src = g.ToDoubleRegister(source); | 1888 DoubleRegister src = g.ToDoubleRegister(source); |
1851 if (destination->IsDoubleRegister()) { | 1889 if (destination->IsDoubleRegister()) { |
1852 DoubleRegister dst = g.ToDoubleRegister(destination); | 1890 DoubleRegister dst = g.ToDoubleRegister(destination); |
1853 __ fmr(temp, src); | 1891 __ ldr(temp, src); |
1854 __ fmr(src, dst); | 1892 __ ldr(src, dst); |
1855 __ fmr(dst, temp); | 1893 __ ldr(dst, temp); |
1856 } else { | 1894 } else { |
1857 DCHECK(destination->IsDoubleStackSlot()); | 1895 DCHECK(destination->IsDoubleStackSlot()); |
1858 MemOperand dst = g.ToMemOperand(destination); | 1896 MemOperand dst = g.ToMemOperand(destination); |
1859 __ fmr(temp, src); | 1897 __ ldr(temp, src); |
1860 __ lfd(src, dst); | 1898 __ LoadDouble(src, dst); |
1861 __ stfd(temp, dst); | 1899 __ StoreDouble(temp, dst); |
1862 } | 1900 } |
1863 #if !V8_TARGET_ARCH_PPC64 | 1901 #if !V8_TARGET_ARCH_S390X |
1864 } else if (source->IsDoubleStackSlot()) { | 1902 } else if (source->IsDoubleStackSlot()) { |
1865 DCHECK(destination->IsDoubleStackSlot()); | 1903 DCHECK(destination->IsDoubleStackSlot()); |
1866 DoubleRegister temp_0 = kScratchDoubleReg; | 1904 DoubleRegister temp_0 = kScratchDoubleReg; |
1867 DoubleRegister temp_1 = d0; | 1905 DoubleRegister temp_1 = d0; |
1868 MemOperand src = g.ToMemOperand(source); | 1906 MemOperand src = g.ToMemOperand(source); |
1869 MemOperand dst = g.ToMemOperand(destination); | 1907 MemOperand dst = g.ToMemOperand(destination); |
1870 __ lfd(temp_0, src); | 1908 // TODO(joransiu): MVC opportunity |
1871 __ lfd(temp_1, dst); | 1909 __ LoadDouble(temp_0, src); |
1872 __ stfd(temp_0, dst); | 1910 __ LoadDouble(temp_1, dst); |
1873 __ stfd(temp_1, src); | 1911 __ StoreDouble(temp_0, dst); |
| 1912 __ StoreDouble(temp_1, src); |
1874 #endif | 1913 #endif |
1875 } else { | 1914 } else { |
1876 // No other combinations are possible. | 1915 // No other combinations are possible. |
1877 UNREACHABLE(); | 1916 UNREACHABLE(); |
1878 } | 1917 } |
1879 } | 1918 } |
1880 | 1919 |
1881 | |
1882 void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) { | 1920 void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) { |
1883 for (size_t index = 0; index < target_count; ++index) { | 1921 for (size_t index = 0; index < target_count; ++index) { |
1884 __ emit_label_addr(targets[index]); | 1922 __ emit_label_addr(targets[index]); |
1885 } | 1923 } |
1886 } | 1924 } |
1887 | 1925 |
1888 | |
1889 void CodeGenerator::AddNopForSmiCodeInlining() { | 1926 void CodeGenerator::AddNopForSmiCodeInlining() { |
1890 // We do not insert nops for inlined Smi code. | 1927 // We do not insert nops for inlined Smi code. |
1891 } | 1928 } |
1892 | 1929 |
1893 | |
1894 void CodeGenerator::EnsureSpaceForLazyDeopt() { | 1930 void CodeGenerator::EnsureSpaceForLazyDeopt() { |
1895 if (!info()->ShouldEnsureSpaceForLazyDeopt()) { | 1931 if (!info()->ShouldEnsureSpaceForLazyDeopt()) { |
1896 return; | 1932 return; |
1897 } | 1933 } |
1898 | 1934 |
1899 int space_needed = Deoptimizer::patch_size(); | 1935 int space_needed = Deoptimizer::patch_size(); |
1900 // Ensure that we have enough space after the previous lazy-bailout | 1936 // Ensure that we have enough space after the previous lazy-bailout |
1901 // instruction for patching the code here. | 1937 // instruction for patching the code here. |
1902 int current_pc = masm()->pc_offset(); | 1938 int current_pc = masm()->pc_offset(); |
1903 if (current_pc < last_lazy_deopt_pc_ + space_needed) { | 1939 if (current_pc < last_lazy_deopt_pc_ + space_needed) { |
1904 // Block tramoline pool emission for duration of padding. | |
1905 v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool( | |
1906 masm()); | |
1907 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 1940 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
1908 DCHECK_EQ(0, padding_size % v8::internal::Assembler::kInstrSize); | 1941 DCHECK_EQ(0, padding_size % 2); |
1909 while (padding_size > 0) { | 1942 while (padding_size > 0) { |
1910 __ nop(); | 1943 __ nop(); |
1911 padding_size -= v8::internal::Assembler::kInstrSize; | 1944 padding_size -= 2; |
1912 } | 1945 } |
1913 } | 1946 } |
1914 } | 1947 } |
1915 | 1948 |
1916 #undef __ | 1949 #undef __ |
1917 | 1950 |
1918 } // namespace compiler | 1951 } // namespace compiler |
1919 } // namespace internal | 1952 } // namespace internal |
1920 } // namespace v8 | 1953 } // namespace v8 |
OLD | NEW |