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

Side by Side Diff: src/compiler/x87/code-generator-x87.cc

Issue 1179763004: X87: enable the X87 turbofan support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/x87/OWNERS ('k') | src/compiler/x87/instruction-codes-x87.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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/compiler/code-generator-impl.h" 7 #include "src/compiler/code-generator-impl.h"
8 #include "src/compiler/gap-resolver.h" 8 #include "src/compiler/gap-resolver.h"
9 #include "src/compiler/node-matchers.h" 9 #include "src/compiler/node-matchers.h"
10 #include "src/ia32/assembler-ia32.h"
11 #include "src/ia32/macro-assembler-ia32.h"
12 #include "src/scopes.h" 10 #include "src/scopes.h"
11 #include "src/x87/assembler-x87.h"
12 #include "src/x87/macro-assembler-x87.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 20
21 #define kScratchDoubleReg xmm0 21 // Adds X87 specific methods for decoding operands.
22 22 class X87OperandConverter : public InstructionOperandConverter {
23
24 // Adds IA-32 specific methods for decoding operands.
25 class IA32OperandConverter : public InstructionOperandConverter {
26 public: 23 public:
27 IA32OperandConverter(CodeGenerator* gen, Instruction* instr) 24 X87OperandConverter(CodeGenerator* gen, Instruction* instr)
28 : InstructionOperandConverter(gen, instr) {} 25 : InstructionOperandConverter(gen, instr) {}
29 26
30 Operand InputOperand(size_t index, int extra = 0) { 27 Operand InputOperand(size_t index, int extra = 0) {
31 return ToOperand(instr_->InputAt(index), extra); 28 return ToOperand(instr_->InputAt(index), extra);
32 } 29 }
33 30
34 Immediate InputImmediate(size_t index) { 31 Immediate InputImmediate(size_t index) {
35 return ToImmediate(instr_->InputAt(index)); 32 return ToImmediate(instr_->InputAt(index));
36 } 33 }
37 34
38 Operand OutputOperand() { return ToOperand(instr_->Output()); } 35 Operand OutputOperand() { return ToOperand(instr_->Output()); }
39 36
40 Operand ToOperand(InstructionOperand* op, int extra = 0) { 37 Operand ToOperand(InstructionOperand* op, int extra = 0) {
41 if (op->IsRegister()) { 38 if (op->IsRegister()) {
42 DCHECK(extra == 0); 39 DCHECK(extra == 0);
43 return Operand(ToRegister(op)); 40 return Operand(ToRegister(op));
44 } else if (op->IsDoubleRegister()) { 41 } else if (op->IsDoubleRegister()) {
45 DCHECK(extra == 0); 42 DCHECK(extra == 0);
46 return Operand(ToDoubleRegister(op)); 43 UNIMPLEMENTED();
47 } 44 }
48 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); 45 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
49 // The linkage computes where all spill slots are located. 46 // The linkage computes where all spill slots are located.
50 FrameOffset offset = linkage()->GetFrameOffset( 47 FrameOffset offset = linkage()->GetFrameOffset(
51 AllocatedOperand::cast(op)->index(), frame(), extra); 48 AllocatedOperand::cast(op)->index(), frame(), extra);
52 return Operand(offset.from_stack_pointer() ? esp : ebp, offset.offset()); 49 return Operand(offset.from_stack_pointer() ? esp : ebp, offset.offset());
53 } 50 }
54 51
55 Operand HighOperand(InstructionOperand* op) { 52 Operand HighOperand(InstructionOperand* op) {
56 DCHECK(op->IsDoubleStackSlot()); 53 DCHECK(op->IsDoubleStackSlot());
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 177
181 void Generate() final { __ xor_(result_, result_); } 178 void Generate() final { __ xor_(result_, result_); }
182 179
183 private: 180 private:
184 Register const result_; 181 Register const result_;
185 }; 182 };
186 183
187 184
188 class OutOfLineLoadFloat final : public OutOfLineCode { 185 class OutOfLineLoadFloat final : public OutOfLineCode {
189 public: 186 public:
190 OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result) 187 OutOfLineLoadFloat(CodeGenerator* gen, X87Register result)
191 : OutOfLineCode(gen), result_(result) {} 188 : OutOfLineCode(gen), result_(result) {}
192 189
193 void Generate() final { __ pcmpeqd(result_, result_); } 190 void Generate() final {
191 DCHECK(result_.code() == 0);
192 USE(result_);
193 __ fstp(0);
194 __ push(Immediate(0xffffffff));
195 __ push(Immediate(0x7fffffff));
196 __ fld_d(MemOperand(esp, 0));
197 __ lea(esp, Operand(esp, kDoubleSize));
198 }
194 199
195 private: 200 private:
196 XMMRegister const result_; 201 X87Register const result_;
197 }; 202 };
198 203
199 204
200 class OutOfLineTruncateDoubleToI final : public OutOfLineCode { 205 class OutOfLineTruncateDoubleToI final : public OutOfLineCode {
201 public: 206 public:
202 OutOfLineTruncateDoubleToI(CodeGenerator* gen, Register result, 207 OutOfLineTruncateDoubleToI(CodeGenerator* gen, Register result,
203 XMMRegister input) 208 X87Register input)
204 : OutOfLineCode(gen), result_(result), input_(input) {} 209 : OutOfLineCode(gen), result_(result), input_(input) {}
205 210
206 void Generate() final { 211 void Generate() final {
207 __ sub(esp, Immediate(kDoubleSize)); 212 UNIMPLEMENTED();
208 __ movsd(MemOperand(esp, 0), input_); 213 USE(result_);
209 __ SlowTruncateToI(result_, esp, 0); 214 USE(input_);
210 __ add(esp, Immediate(kDoubleSize));
211 } 215 }
212 216
213 private: 217 private:
214 Register const result_; 218 Register const result_;
215 XMMRegister const input_; 219 X87Register const input_;
216 }; 220 };
217 221
218 } // namespace 222 } // namespace
219 223
220 224
221 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ 225 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \
222 do { \ 226 do { \
223 auto result = i.OutputDoubleRegister(); \ 227 auto result = i.OutputDoubleRegister(); \
224 auto offset = i.InputRegister(0); \ 228 auto offset = i.InputRegister(0); \
229 DCHECK(result.code() == 0); \
225 if (instr->InputAt(1)->IsRegister()) { \ 230 if (instr->InputAt(1)->IsRegister()) { \
226 __ cmp(offset, i.InputRegister(1)); \ 231 __ cmp(offset, i.InputRegister(1)); \
227 } else { \ 232 } else { \
228 __ cmp(offset, i.InputImmediate(1)); \ 233 __ cmp(offset, i.InputImmediate(1)); \
229 } \ 234 } \
230 OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \ 235 OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \
231 __ j(above_equal, ool->entry()); \ 236 __ j(above_equal, ool->entry()); \
232 __ asm_instr(result, i.MemoryOperand(2)); \ 237 __ fstp(0); \
238 __ asm_instr(i.MemoryOperand(2)); \
233 __ bind(ool->exit()); \ 239 __ bind(ool->exit()); \
234 } while (false) 240 } while (false)
235 241
236 242
237 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ 243 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \
238 do { \ 244 do { \
239 auto result = i.OutputRegister(); \ 245 auto result = i.OutputRegister(); \
240 auto offset = i.InputRegister(0); \ 246 auto offset = i.InputRegister(0); \
241 if (instr->InputAt(1)->IsRegister()) { \ 247 if (instr->InputAt(1)->IsRegister()) { \
242 __ cmp(offset, i.InputRegister(1)); \ 248 __ cmp(offset, i.InputRegister(1)); \
243 } else { \ 249 } else { \
244 __ cmp(offset, i.InputImmediate(1)); \ 250 __ cmp(offset, i.InputImmediate(1)); \
245 } \ 251 } \
246 OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \ 252 OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \
247 __ j(above_equal, ool->entry()); \ 253 __ j(above_equal, ool->entry()); \
248 __ asm_instr(result, i.MemoryOperand(2)); \ 254 __ asm_instr(result, i.MemoryOperand(2)); \
249 __ bind(ool->exit()); \ 255 __ bind(ool->exit()); \
250 } while (false) 256 } while (false)
251 257
252 258
253 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr) \ 259 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr) \
254 do { \ 260 do { \
255 auto offset = i.InputRegister(0); \ 261 auto offset = i.InputRegister(0); \
256 if (instr->InputAt(1)->IsRegister()) { \ 262 if (instr->InputAt(1)->IsRegister()) { \
257 __ cmp(offset, i.InputRegister(1)); \ 263 __ cmp(offset, i.InputRegister(1)); \
258 } else { \ 264 } else { \
259 __ cmp(offset, i.InputImmediate(1)); \ 265 __ cmp(offset, i.InputImmediate(1)); \
260 } \ 266 } \
261 Label done; \ 267 Label done; \
262 __ j(above_equal, &done, Label::kNear); \ 268 DCHECK(i.InputDoubleRegister(2).code() == 0); \
263 __ asm_instr(i.MemoryOperand(3), i.InputDoubleRegister(2)); \ 269 __ j(above_equal, &done, Label::kNear); \
264 __ bind(&done); \ 270 __ asm_instr(i.MemoryOperand(3)); \
271 __ bind(&done); \
265 } while (false) 272 } while (false)
266 273
267 274
268 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ 275 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \
269 do { \ 276 do { \
270 auto offset = i.InputRegister(0); \ 277 auto offset = i.InputRegister(0); \
271 if (instr->InputAt(1)->IsRegister()) { \ 278 if (instr->InputAt(1)->IsRegister()) { \
272 __ cmp(offset, i.InputRegister(1)); \ 279 __ cmp(offset, i.InputRegister(1)); \
273 } else { \ 280 } else { \
274 __ cmp(offset, i.InputImmediate(1)); \ 281 __ cmp(offset, i.InputImmediate(1)); \
(...skipping 21 matching lines...) Expand all
296 kPointerSize) 303 kPointerSize)
297 : 0; 304 : 0;
298 __ pop(Operand(esp, bytes_to_pop)); 305 __ pop(Operand(esp, bytes_to_pop));
299 __ add(esp, Immediate(bytes_to_pop)); 306 __ add(esp, Immediate(bytes_to_pop));
300 } 307 }
301 } 308 }
302 309
303 310
304 // Assembles an instruction after register allocation, producing machine code. 311 // Assembles an instruction after register allocation, producing machine code.
305 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { 312 void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
306 IA32OperandConverter i(this, instr); 313 X87OperandConverter i(this, instr);
307 314
308 switch (ArchOpcodeField::decode(instr->opcode())) { 315 switch (ArchOpcodeField::decode(instr->opcode())) {
309 case kArchCallCodeObject: { 316 case kArchCallCodeObject: {
310 EnsureSpaceForLazyDeopt(); 317 EnsureSpaceForLazyDeopt();
311 if (HasImmediateInput(instr, 0)) { 318 if (HasImmediateInput(instr, 0)) {
312 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); 319 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
313 __ call(code, RelocInfo::CODE_TARGET); 320 __ call(code, RelocInfo::CODE_TARGET);
314 } else { 321 } else {
315 Register reg = i.InputRegister(0); 322 Register reg = i.InputRegister(0);
316 __ call(Operand(reg, Code::kHeaderSize - kHeapObjectTag)); 323 __ call(Operand(reg, Code::kHeaderSize - kHeapObjectTag));
317 } 324 }
318 RecordCallPosition(instr); 325 RecordCallPosition(instr);
326 bool double_result =
327 instr->HasOutput() && instr->Output()->IsDoubleRegister();
328 if (double_result) {
329 __ lea(esp, Operand(esp, -kDoubleSize));
330 __ fstp_d(Operand(esp, 0));
331 }
332 __ fninit();
333 if (double_result) {
334 __ fld_d(Operand(esp, 0));
335 __ lea(esp, Operand(esp, kDoubleSize));
336 } else {
337 __ fld1();
338 }
319 break; 339 break;
320 } 340 }
321 case kArchTailCallCodeObject: { 341 case kArchTailCallCodeObject: {
322 AssembleDeconstructActivationRecord(); 342 AssembleDeconstructActivationRecord();
323 if (HasImmediateInput(instr, 0)) { 343 if (HasImmediateInput(instr, 0)) {
324 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); 344 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
325 __ jmp(code, RelocInfo::CODE_TARGET); 345 __ jmp(code, RelocInfo::CODE_TARGET);
326 } else { 346 } else {
327 Register reg = i.InputRegister(0); 347 Register reg = i.InputRegister(0);
328 __ jmp(Operand(reg, Code::kHeaderSize - kHeapObjectTag)); 348 __ jmp(Operand(reg, Code::kHeaderSize - kHeapObjectTag));
329 } 349 }
330 break; 350 break;
331 } 351 }
332 case kArchCallJSFunction: { 352 case kArchCallJSFunction: {
333 EnsureSpaceForLazyDeopt(); 353 EnsureSpaceForLazyDeopt();
334 Register func = i.InputRegister(0); 354 Register func = i.InputRegister(0);
335 if (FLAG_debug_code) { 355 if (FLAG_debug_code) {
336 // Check the function's context matches the context argument. 356 // Check the function's context matches the context argument.
337 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); 357 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
338 __ Assert(equal, kWrongFunctionContext); 358 __ Assert(equal, kWrongFunctionContext);
339 } 359 }
340 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); 360 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
341 RecordCallPosition(instr); 361 RecordCallPosition(instr);
362 bool double_result =
363 instr->HasOutput() && instr->Output()->IsDoubleRegister();
364 if (double_result) {
365 __ lea(esp, Operand(esp, -kDoubleSize));
366 __ fstp_d(Operand(esp, 0));
367 }
368 __ fninit();
369 if (double_result) {
370 __ fld_d(Operand(esp, 0));
371 __ lea(esp, Operand(esp, kDoubleSize));
372 } else {
373 __ fld1();
374 }
342 break; 375 break;
343 } 376 }
344 case kArchTailCallJSFunction: { 377 case kArchTailCallJSFunction: {
345 Register func = i.InputRegister(0); 378 Register func = i.InputRegister(0);
346 if (FLAG_debug_code) { 379 if (FLAG_debug_code) {
347 // Check the function's context matches the context argument. 380 // Check the function's context matches the context argument.
348 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); 381 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
349 __ Assert(equal, kWrongFunctionContext); 382 __ Assert(equal, kWrongFunctionContext);
350 } 383 }
351 AssembleDeconstructActivationRecord(); 384 AssembleDeconstructActivationRecord();
(...skipping 14 matching lines...) Expand all
366 break; 399 break;
367 case kArchDeoptimize: { 400 case kArchDeoptimize: {
368 int deopt_state_id = 401 int deopt_state_id =
369 BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore()); 402 BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
370 AssembleDeoptimizerCall(deopt_state_id, Deoptimizer::EAGER); 403 AssembleDeoptimizerCall(deopt_state_id, Deoptimizer::EAGER);
371 break; 404 break;
372 } 405 }
373 case kArchRet: 406 case kArchRet:
374 AssembleReturn(); 407 AssembleReturn();
375 break; 408 break;
409 case kArchFramePointer:
410 __ mov(i.OutputRegister(), ebp);
411 break;
376 case kArchStackPointer: 412 case kArchStackPointer:
377 __ mov(i.OutputRegister(), esp); 413 __ mov(i.OutputRegister(), esp);
378 break; 414 break;
379 case kArchFramePointer:
380 __ mov(i.OutputRegister(), ebp);
381 break;
382 case kArchTruncateDoubleToI: { 415 case kArchTruncateDoubleToI: {
383 auto result = i.OutputRegister();
384 auto input = i.InputDoubleRegister(0); 416 auto input = i.InputDoubleRegister(0);
385 auto ool = new (zone()) OutOfLineTruncateDoubleToI(this, result, input); 417 USE(input);
386 __ cvttsd2si(result, Operand(input)); 418 DCHECK(input.code() == 0);
387 __ cmp(result, 1); 419 auto result_reg = i.OutputRegister();
388 __ j(overflow, ool->entry()); 420 __ TruncateX87TOSToI(result_reg);
389 __ bind(ool->exit()); 421 break;
390 break; 422 }
391 } 423 case kX87Add:
392 case kIA32Add:
393 if (HasImmediateInput(instr, 1)) { 424 if (HasImmediateInput(instr, 1)) {
394 __ add(i.InputOperand(0), i.InputImmediate(1)); 425 __ add(i.InputOperand(0), i.InputImmediate(1));
395 } else { 426 } else {
396 __ add(i.InputRegister(0), i.InputOperand(1)); 427 __ add(i.InputRegister(0), i.InputOperand(1));
397 } 428 }
398 break; 429 break;
399 case kIA32And: 430 case kX87And:
400 if (HasImmediateInput(instr, 1)) { 431 if (HasImmediateInput(instr, 1)) {
401 __ and_(i.InputOperand(0), i.InputImmediate(1)); 432 __ and_(i.InputOperand(0), i.InputImmediate(1));
402 } else { 433 } else {
403 __ and_(i.InputRegister(0), i.InputOperand(1)); 434 __ and_(i.InputRegister(0), i.InputOperand(1));
404 } 435 }
405 break; 436 break;
406 case kIA32Cmp: 437 case kX87Cmp:
407 if (HasImmediateInput(instr, 1)) { 438 if (HasImmediateInput(instr, 1)) {
408 __ cmp(i.InputOperand(0), i.InputImmediate(1)); 439 __ cmp(i.InputOperand(0), i.InputImmediate(1));
409 } else { 440 } else {
410 __ cmp(i.InputRegister(0), i.InputOperand(1)); 441 __ cmp(i.InputRegister(0), i.InputOperand(1));
411 } 442 }
412 break; 443 break;
413 case kIA32Test: 444 case kX87Test:
414 if (HasImmediateInput(instr, 1)) { 445 if (HasImmediateInput(instr, 1)) {
415 __ test(i.InputOperand(0), i.InputImmediate(1)); 446 __ test(i.InputOperand(0), i.InputImmediate(1));
416 } else { 447 } else {
417 __ test(i.InputRegister(0), i.InputOperand(1)); 448 __ test(i.InputRegister(0), i.InputOperand(1));
418 } 449 }
419 break; 450 break;
420 case kIA32Imul: 451 case kX87Imul:
421 if (HasImmediateInput(instr, 1)) { 452 if (HasImmediateInput(instr, 1)) {
422 __ imul(i.OutputRegister(), i.InputOperand(0), i.InputInt32(1)); 453 __ imul(i.OutputRegister(), i.InputOperand(0), i.InputInt32(1));
423 } else { 454 } else {
424 __ imul(i.OutputRegister(), i.InputOperand(1)); 455 __ imul(i.OutputRegister(), i.InputOperand(1));
425 } 456 }
426 break; 457 break;
427 case kIA32ImulHigh: 458 case kX87ImulHigh:
428 __ imul(i.InputRegister(1)); 459 __ imul(i.InputRegister(1));
429 break; 460 break;
430 case kIA32UmulHigh: 461 case kX87UmulHigh:
431 __ mul(i.InputRegister(1)); 462 __ mul(i.InputRegister(1));
432 break; 463 break;
433 case kIA32Idiv: 464 case kX87Idiv:
434 __ cdq(); 465 __ cdq();
435 __ idiv(i.InputOperand(1)); 466 __ idiv(i.InputOperand(1));
436 break; 467 break;
437 case kIA32Udiv: 468 case kX87Udiv:
438 __ Move(edx, Immediate(0)); 469 __ Move(edx, Immediate(0));
439 __ div(i.InputOperand(1)); 470 __ div(i.InputOperand(1));
440 break; 471 break;
441 case kIA32Not: 472 case kX87Not:
442 __ not_(i.OutputOperand()); 473 __ not_(i.OutputOperand());
443 break; 474 break;
444 case kIA32Neg: 475 case kX87Neg:
445 __ neg(i.OutputOperand()); 476 __ neg(i.OutputOperand());
446 break; 477 break;
447 case kIA32Or: 478 case kX87Or:
448 if (HasImmediateInput(instr, 1)) { 479 if (HasImmediateInput(instr, 1)) {
449 __ or_(i.InputOperand(0), i.InputImmediate(1)); 480 __ or_(i.InputOperand(0), i.InputImmediate(1));
450 } else { 481 } else {
451 __ or_(i.InputRegister(0), i.InputOperand(1)); 482 __ or_(i.InputRegister(0), i.InputOperand(1));
452 } 483 }
453 break; 484 break;
454 case kIA32Xor: 485 case kX87Xor:
455 if (HasImmediateInput(instr, 1)) { 486 if (HasImmediateInput(instr, 1)) {
456 __ xor_(i.InputOperand(0), i.InputImmediate(1)); 487 __ xor_(i.InputOperand(0), i.InputImmediate(1));
457 } else { 488 } else {
458 __ xor_(i.InputRegister(0), i.InputOperand(1)); 489 __ xor_(i.InputRegister(0), i.InputOperand(1));
459 } 490 }
460 break; 491 break;
461 case kIA32Sub: 492 case kX87Sub:
462 if (HasImmediateInput(instr, 1)) { 493 if (HasImmediateInput(instr, 1)) {
463 __ sub(i.InputOperand(0), i.InputImmediate(1)); 494 __ sub(i.InputOperand(0), i.InputImmediate(1));
464 } else { 495 } else {
465 __ sub(i.InputRegister(0), i.InputOperand(1)); 496 __ sub(i.InputRegister(0), i.InputOperand(1));
466 } 497 }
467 break; 498 break;
468 case kIA32Shl: 499 case kX87Shl:
469 if (HasImmediateInput(instr, 1)) { 500 if (HasImmediateInput(instr, 1)) {
470 __ shl(i.OutputOperand(), i.InputInt5(1)); 501 __ shl(i.OutputOperand(), i.InputInt5(1));
471 } else { 502 } else {
472 __ shl_cl(i.OutputOperand()); 503 __ shl_cl(i.OutputOperand());
473 } 504 }
474 break; 505 break;
475 case kIA32Shr: 506 case kX87Shr:
476 if (HasImmediateInput(instr, 1)) { 507 if (HasImmediateInput(instr, 1)) {
477 __ shr(i.OutputOperand(), i.InputInt5(1)); 508 __ shr(i.OutputOperand(), i.InputInt5(1));
478 } else { 509 } else {
479 __ shr_cl(i.OutputOperand()); 510 __ shr_cl(i.OutputOperand());
480 } 511 }
481 break; 512 break;
482 case kIA32Sar: 513 case kX87Sar:
483 if (HasImmediateInput(instr, 1)) { 514 if (HasImmediateInput(instr, 1)) {
484 __ sar(i.OutputOperand(), i.InputInt5(1)); 515 __ sar(i.OutputOperand(), i.InputInt5(1));
485 } else { 516 } else {
486 __ sar_cl(i.OutputOperand()); 517 __ sar_cl(i.OutputOperand());
487 } 518 }
488 break; 519 break;
489 case kIA32Ror: 520 case kX87Ror:
490 if (HasImmediateInput(instr, 1)) { 521 if (HasImmediateInput(instr, 1)) {
491 __ ror(i.OutputOperand(), i.InputInt5(1)); 522 __ ror(i.OutputOperand(), i.InputInt5(1));
492 } else { 523 } else {
493 __ ror_cl(i.OutputOperand()); 524 __ ror_cl(i.OutputOperand());
494 } 525 }
495 break; 526 break;
496 case kIA32Lzcnt: 527 case kX87Lzcnt:
497 __ Lzcnt(i.OutputRegister(), i.InputOperand(0)); 528 __ Lzcnt(i.OutputRegister(), i.InputOperand(0));
498 break; 529 break;
499 case kSSEFloat32Cmp: 530 case kX87LoadFloat64Constant: {
500 __ ucomiss(i.InputDoubleRegister(0), i.InputOperand(1)); 531 InstructionOperand* source = instr->InputAt(0);
501 break; 532 InstructionOperand* destination = instr->Output();
502 case kSSEFloat32Add: 533 DCHECK(source->IsConstant());
503 __ addss(i.InputDoubleRegister(0), i.InputOperand(1)); 534 X87OperandConverter g(this, NULL);
504 break; 535 Constant src_constant = g.ToConstant(source);
505 case kSSEFloat32Sub: 536
506 __ subss(i.InputDoubleRegister(0), i.InputOperand(1)); 537 DCHECK_EQ(Constant::kFloat64, src_constant.type());
507 break; 538 uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64());
508 case kSSEFloat32Mul: 539 uint32_t lower = static_cast<uint32_t>(src);
509 __ mulss(i.InputDoubleRegister(0), i.InputOperand(1)); 540 uint32_t upper = static_cast<uint32_t>(src >> 32);
510 break; 541 if (destination->IsDoubleRegister()) {
511 case kSSEFloat32Div: 542 __ sub(esp, Immediate(kDoubleSize));
512 __ divss(i.InputDoubleRegister(0), i.InputOperand(1)); 543 __ mov(MemOperand(esp, 0), Immediate(lower));
513 // Don't delete this mov. It may improve performance on some CPUs, 544 __ mov(MemOperand(esp, kInt32Size), Immediate(upper));
514 // when there is a (v)mulss depending on the result. 545 __ fstp(0);
515 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); 546 __ fld_d(MemOperand(esp, 0));
516 break; 547 __ add(esp, Immediate(kDoubleSize));
517 case kSSEFloat32Max: 548 } else {
518 __ maxss(i.InputDoubleRegister(0), i.InputOperand(1)); 549 UNREACHABLE();
519 break; 550 }
520 case kSSEFloat32Min: 551 break;
521 __ minss(i.InputDoubleRegister(0), i.InputOperand(1)); 552 }
522 break; 553 case kX87Float32Cmp: {
523 case kSSEFloat32Sqrt: 554 __ fld_s(MemOperand(esp, kFloatSize));
524 __ sqrtss(i.OutputDoubleRegister(), i.InputOperand(0)); 555 __ fld_s(MemOperand(esp, 0));
525 break; 556 __ FCmp();
526 case kSSEFloat32Abs: { 557 __ lea(esp, Operand(esp, 2 * kFloatSize));
527 // TODO(bmeurer): Use 128-bit constants. 558 break;
528 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); 559 }
529 __ psrlq(kScratchDoubleReg, 33); 560 case kX87Float32Add: {
530 __ andps(i.OutputDoubleRegister(), kScratchDoubleReg); 561 __ X87SetFPUCW(0x027F);
531 break; 562 __ fstp(0);
532 } 563 __ fld_s(MemOperand(esp, 0));
533 case kSSEFloat32Neg: { 564 __ fld_s(MemOperand(esp, kFloatSize));
534 // TODO(bmeurer): Use 128-bit constants. 565 __ faddp();
535 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); 566 // Clear stack.
536 __ psllq(kScratchDoubleReg, 31); 567 __ lea(esp, Operand(esp, 2 * kFloatSize));
537 __ xorps(i.OutputDoubleRegister(), kScratchDoubleReg); 568 // Restore the default value of control word.
538 break; 569 __ X87SetFPUCW(0x037F);
539 } 570 break;
540 case kSSEFloat64Cmp: 571 }
541 __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1)); 572 case kX87Float32Sub: {
542 break; 573 __ X87SetFPUCW(0x027F);
543 case kSSEFloat64Add: 574 __ fstp(0);
544 __ addsd(i.InputDoubleRegister(0), i.InputOperand(1)); 575 __ fld_s(MemOperand(esp, kFloatSize));
545 break; 576 __ fld_s(MemOperand(esp, 0));
546 case kSSEFloat64Sub: 577 __ fsubp();
547 __ subsd(i.InputDoubleRegister(0), i.InputOperand(1)); 578 // Clear stack.
548 break; 579 __ lea(esp, Operand(esp, 2 * kFloatSize));
549 case kSSEFloat64Mul: 580 // Restore the default value of control word.
550 __ mulsd(i.InputDoubleRegister(0), i.InputOperand(1)); 581 __ X87SetFPUCW(0x037F);
551 break; 582 break;
552 case kSSEFloat64Div: 583 }
553 __ divsd(i.InputDoubleRegister(0), i.InputOperand(1)); 584 case kX87Float32Mul: {
554 // Don't delete this mov. It may improve performance on some CPUs, 585 __ X87SetFPUCW(0x027F);
555 // when there is a (v)mulsd depending on the result. 586 __ fstp(0);
556 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); 587 __ fld_s(MemOperand(esp, kFloatSize));
557 break; 588 __ fld_s(MemOperand(esp, 0));
558 case kSSEFloat64Max: 589 __ fmulp();
559 __ maxsd(i.InputDoubleRegister(0), i.InputOperand(1)); 590 // Clear stack.
560 break; 591 __ lea(esp, Operand(esp, 2 * kFloatSize));
561 case kSSEFloat64Min: 592 // Restore the default value of control word.
562 __ minsd(i.InputDoubleRegister(0), i.InputOperand(1)); 593 __ X87SetFPUCW(0x037F);
563 break; 594 break;
564 case kSSEFloat64Mod: { 595 }
565 // TODO(dcarney): alignment is wrong. 596 case kX87Float32Div: {
597 __ X87SetFPUCW(0x027F);
598 __ fstp(0);
599 __ fld_s(MemOperand(esp, kFloatSize));
600 __ fld_s(MemOperand(esp, 0));
601 __ fdivp();
602 // Clear stack.
603 __ lea(esp, Operand(esp, 2 * kFloatSize));
604 // Restore the default value of control word.
605 __ X87SetFPUCW(0x037F);
606 break;
607 }
608 case kX87Float32Max: {
609 Label check_nan_left, check_zero, return_left, return_right;
610 Condition condition = below;
611 __ fstp(0);
612 __ fld_s(MemOperand(esp, kFloatSize));
613 __ fld_s(MemOperand(esp, 0));
614 __ fld(1);
615 __ fld(1);
616 __ FCmp();
617 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN.
618 __ j(equal, &check_zero, Label::kNear); // left == right.
619 __ j(condition, &return_left, Label::kNear);
620 __ jmp(&return_right, Label::kNear);
621
622 __ bind(&check_zero);
623 __ fld(0);
624 __ fldz();
625 __ FCmp();
626 __ j(not_equal, &return_left, Label::kNear); // left == right != 0.
627
628 __ fadd(1);
629 __ jmp(&return_left, Label::kNear);
630
631 __ bind(&check_nan_left);
632 __ fld(0);
633 __ fld(0);
634 __ FCmp(); // NaN check.
635 __ j(parity_even, &return_left, Label::kNear); // left == NaN.
636
637 __ bind(&return_right);
638 __ fxch();
639
640 __ bind(&return_left);
641 __ fstp(0);
642 __ lea(esp, Operand(esp, 2 * kFloatSize));
643 break;
644 }
645 case kX87Float32Min: {
646 Label check_nan_left, check_zero, return_left, return_right;
647 Condition condition = above;
648 __ fstp(0);
649 __ fld_s(MemOperand(esp, kFloatSize));
650 __ fld_s(MemOperand(esp, 0));
651 __ fld(1);
652 __ fld(1);
653 __ FCmp();
654 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN.
655 __ j(equal, &check_zero, Label::kNear); // left == right.
656 __ j(condition, &return_left, Label::kNear);
657 __ jmp(&return_right, Label::kNear);
658
659 __ bind(&check_zero);
660 __ fld(0);
661 __ fldz();
662 __ FCmp();
663 __ j(not_equal, &return_left, Label::kNear); // left == right != 0.
664 // At this point, both left and right are either 0 or -0.
665 // Push st0 and st1 to stack, then pop them to temp registers and OR them,
666 // load it to left.
667 __ push(eax);
668 __ fld(1);
669 __ fld(1);
670 __ sub(esp, Immediate(2 * kPointerSize));
671 __ fstp_s(MemOperand(esp, 0));
672 __ fstp_s(MemOperand(esp, kPointerSize));
673 __ pop(eax);
674 __ xor_(MemOperand(esp, 0), eax);
675 __ fstp(0);
676 __ fld_s(MemOperand(esp, 0));
677 __ pop(eax); // restore esp
678 __ pop(eax); // restore esp
679 __ jmp(&return_left, Label::kNear);
680
681 __ bind(&check_nan_left);
682 __ fld(0);
683 __ fld(0);
684 __ FCmp(); // NaN check.
685 __ j(parity_even, &return_left, Label::kNear); // left == NaN.
686
687 __ bind(&return_right);
688 __ fxch();
689
690 __ bind(&return_left);
691 __ fstp(0);
692 __ lea(esp, Operand(esp, 2 * kFloatSize));
693 break;
694 }
695 case kX87Float32Sqrt: {
696 __ fstp(0);
697 __ fld_s(MemOperand(esp, 0));
698 __ fsqrt();
699 __ lea(esp, Operand(esp, kFloatSize));
700 break;
701 }
702 case kX87Float32Abs: {
703 __ fstp(0);
704 __ fld_s(MemOperand(esp, 0));
705 __ fabs();
706 __ lea(esp, Operand(esp, kFloatSize));
707 break;
708 }
709 case kX87Float64Add: {
710 __ X87SetFPUCW(0x027F);
711 __ fstp(0);
712 __ fld_d(MemOperand(esp, 0));
713 __ fld_d(MemOperand(esp, kDoubleSize));
714 __ faddp();
715 // Clear stack.
716 __ lea(esp, Operand(esp, 2 * kDoubleSize));
717 // Restore the default value of control word.
718 __ X87SetFPUCW(0x037F);
719 break;
720 }
721 case kX87Float64Sub: {
722 __ X87SetFPUCW(0x027F);
723 __ fstp(0);
724 __ fld_d(MemOperand(esp, kDoubleSize));
725 __ fsub_d(MemOperand(esp, 0));
726 // Clear stack.
727 __ lea(esp, Operand(esp, 2 * kDoubleSize));
728 // Restore the default value of control word.
729 __ X87SetFPUCW(0x037F);
730 break;
731 }
732 case kX87Float64Mul: {
733 __ X87SetFPUCW(0x027F);
734 __ fstp(0);
735 __ fld_d(MemOperand(esp, kDoubleSize));
736 __ fmul_d(MemOperand(esp, 0));
737 // Clear stack.
738 __ lea(esp, Operand(esp, 2 * kDoubleSize));
739 // Restore the default value of control word.
740 __ X87SetFPUCW(0x037F);
741 break;
742 }
743 case kX87Float64Div: {
744 __ X87SetFPUCW(0x027F);
745 __ fstp(0);
746 __ fld_d(MemOperand(esp, kDoubleSize));
747 __ fdiv_d(MemOperand(esp, 0));
748 // Clear stack.
749 __ lea(esp, Operand(esp, 2 * kDoubleSize));
750 // Restore the default value of control word.
751 __ X87SetFPUCW(0x037F);
752 break;
753 }
754 case kX87Float64Mod: {
755 FrameScope frame_scope(&masm_, StackFrame::MANUAL);
756 __ mov(eax, esp);
757 __ PrepareCallCFunction(4, eax);
758 __ fstp(0);
759 __ fld_d(MemOperand(eax, 0));
760 __ fstp_d(Operand(esp, 1 * kDoubleSize));
761 __ fld_d(MemOperand(eax, kDoubleSize));
762 __ fstp_d(Operand(esp, 0));
763 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()),
764 4);
765 __ lea(esp, Operand(esp, 2 * kDoubleSize));
766 break;
767 }
768 case kX87Float64Max: {
769 Label check_nan_left, check_zero, return_left, return_right;
770 Condition condition = below;
771 __ fstp(0);
772 __ fld_d(MemOperand(esp, kDoubleSize));
773 __ fld_d(MemOperand(esp, 0));
774 __ fld(1);
775 __ fld(1);
776 __ FCmp();
777 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN.
778 __ j(equal, &check_zero, Label::kNear); // left == right.
779 __ j(condition, &return_left, Label::kNear);
780 __ jmp(&return_right, Label::kNear);
781
782 __ bind(&check_zero);
783 __ fld(0);
784 __ fldz();
785 __ FCmp();
786 __ j(not_equal, &return_left, Label::kNear); // left == right != 0.
787
788 __ fadd(1);
789 __ jmp(&return_left, Label::kNear);
790
791 __ bind(&check_nan_left);
792 __ fld(0);
793 __ fld(0);
794 __ FCmp(); // NaN check.
795 __ j(parity_even, &return_left, Label::kNear); // left == NaN.
796
797 __ bind(&return_right);
798 __ fxch();
799
800 __ bind(&return_left);
801 __ fstp(0);
802 __ lea(esp, Operand(esp, 2 * kDoubleSize));
803 break;
804 }
805 case kX87Float64Min: {
806 Label check_nan_left, check_zero, return_left, return_right;
807 Condition condition = above;
808 __ fstp(0);
809 __ fld_d(MemOperand(esp, kDoubleSize));
810 __ fld_d(MemOperand(esp, 0));
811 __ fld(1);
812 __ fld(1);
813 __ FCmp();
814 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN.
815 __ j(equal, &check_zero, Label::kNear); // left == right.
816 __ j(condition, &return_left, Label::kNear);
817 __ jmp(&return_right, Label::kNear);
818
819 __ bind(&check_zero);
820 __ fld(0);
821 __ fldz();
822 __ FCmp();
823 __ j(not_equal, &return_left, Label::kNear); // left == right != 0.
824 // At this point, both left and right are either 0 or -0.
825 // Push st0 and st1 to stack, then pop them to temp registers and OR them,
826 // load it to left.
827 __ push(eax);
828 __ fld(1);
829 __ fld(1);
830 __ sub(esp, Immediate(2 * kPointerSize));
831 __ fstp_s(MemOperand(esp, 0));
832 __ fstp_s(MemOperand(esp, kPointerSize));
833 __ pop(eax);
834 __ xor_(MemOperand(esp, 0), eax);
835 __ fstp(0);
836 __ fld_s(MemOperand(esp, 0));
837 __ pop(eax); // restore esp
838 __ pop(eax); // restore esp
839 __ jmp(&return_left, Label::kNear);
840
841 __ bind(&check_nan_left);
842 __ fld(0);
843 __ fld(0);
844 __ FCmp(); // NaN check.
845 __ j(parity_even, &return_left, Label::kNear); // left == NaN.
846
847 __ bind(&return_right);
848 __ fxch();
849
850 __ bind(&return_left);
851 __ fstp(0);
852 __ lea(esp, Operand(esp, 2 * kDoubleSize));
853 break;
854 }
855 case kX87Float64Abs: {
856 __ fstp(0);
857 __ fld_d(MemOperand(esp, 0));
858 __ fabs();
859 __ lea(esp, Operand(esp, kDoubleSize));
860 break;
861 }
862 case kX87Int32ToFloat64: {
863 InstructionOperand* input = instr->InputAt(0);
864 DCHECK(input->IsRegister() || input->IsStackSlot());
865 __ fstp(0);
866 if (input->IsRegister()) {
867 Register input_reg = i.InputRegister(0);
868 __ push(input_reg);
869 __ fild_s(Operand(esp, 0));
870 __ pop(input_reg);
871 } else {
872 __ fild_s(i.InputOperand(0));
873 }
874 break;
875 }
876 case kX87Float32ToFloat64: {
877 InstructionOperand* input = instr->InputAt(0);
878 if (input->IsDoubleRegister()) {
879 __ sub(esp, Immediate(kDoubleSize));
880 __ fstp_d(MemOperand(esp, 0));
881 __ fld_d(MemOperand(esp, 0));
882 __ add(esp, Immediate(kDoubleSize));
883 } else {
884 DCHECK(input->IsDoubleStackSlot());
885 __ fstp(0);
886 __ fld_s(i.InputOperand(0));
887 }
888 break;
889 }
890 case kX87Uint32ToFloat64: {
891 __ fstp(0);
892 __ LoadUint32NoSSE2(i.InputRegister(0));
893 break;
894 }
895 case kX87Float64ToInt32: {
896 if (!instr->InputAt(0)->IsDoubleRegister()) {
897 __ fld_d(i.InputOperand(0));
898 }
899 __ TruncateX87TOSToI(i.OutputRegister(0));
900 if (!instr->InputAt(0)->IsDoubleRegister()) {
901 __ fstp(0);
902 }
903 break;
904 }
905 case kX87Float64ToFloat32: {
906 InstructionOperand* input = instr->InputAt(0);
907 if (input->IsDoubleRegister()) {
908 __ sub(esp, Immediate(kDoubleSize));
909 __ fstp_s(MemOperand(esp, 0));
910 __ fld_s(MemOperand(esp, 0));
911 __ add(esp, Immediate(kDoubleSize));
912 } else {
913 DCHECK(input->IsDoubleStackSlot());
914 __ fstp(0);
915 __ fld_d(i.InputOperand(0));
916 __ sub(esp, Immediate(kDoubleSize));
917 __ fstp_s(MemOperand(esp, 0));
918 __ fld_s(MemOperand(esp, 0));
919 __ add(esp, Immediate(kDoubleSize));
920 }
921 break;
922 }
923 case kX87Float64ToUint32: {
924 __ push_imm32(-2147483648);
925 if (!instr->InputAt(0)->IsDoubleRegister()) {
926 __ fld_d(i.InputOperand(0));
927 }
928 __ fild_s(Operand(esp, 0));
929 __ fadd(1);
930 __ fstp(0);
931 __ TruncateX87TOSToI(i.OutputRegister(0));
932 __ add(esp, Immediate(kInt32Size));
933 __ add(i.OutputRegister(), Immediate(0x80000000));
934 if (!instr->InputAt(0)->IsDoubleRegister()) {
935 __ fstp(0);
936 }
937 break;
938 }
939 case kX87Float64ExtractHighWord32: {
940 if (instr->InputAt(0)->IsDoubleRegister()) {
941 __ sub(esp, Immediate(kDoubleSize));
942 __ fst_d(MemOperand(esp, 0));
943 __ mov(i.OutputRegister(), MemOperand(esp, kDoubleSize / 2));
944 __ add(esp, Immediate(kDoubleSize));
945 } else {
946 InstructionOperand* input = instr->InputAt(0);
947 USE(input);
948 DCHECK(input->IsDoubleStackSlot());
949 __ mov(i.OutputRegister(), i.InputOperand(0, kDoubleSize / 2));
950 }
951 break;
952 }
953 case kX87Float64ExtractLowWord32: {
954 if (instr->InputAt(0)->IsDoubleRegister()) {
955 __ sub(esp, Immediate(kDoubleSize));
956 __ fst_d(MemOperand(esp, 0));
957 __ mov(i.OutputRegister(), MemOperand(esp, 0));
958 __ add(esp, Immediate(kDoubleSize));
959 } else {
960 InstructionOperand* input = instr->InputAt(0);
961 USE(input);
962 DCHECK(input->IsDoubleStackSlot());
963 __ mov(i.OutputRegister(), i.InputOperand(0));
964 }
965 break;
966 }
967 case kX87Float64InsertHighWord32: {
566 __ sub(esp, Immediate(kDoubleSize)); 968 __ sub(esp, Immediate(kDoubleSize));
567 // Move values to st(0) and st(1). 969 __ fstp_d(MemOperand(esp, 0));
568 __ movsd(Operand(esp, 0), i.InputDoubleRegister(1)); 970 __ mov(MemOperand(esp, kDoubleSize / 2), i.InputRegister(1));
569 __ fld_d(Operand(esp, 0)); 971 __ fld_d(MemOperand(esp, 0));
570 __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
571 __ fld_d(Operand(esp, 0));
572 // Loop while fprem isn't done.
573 Label mod_loop;
574 __ bind(&mod_loop);
575 // This instructions traps on all kinds inputs, but we are assuming the
576 // floating point control word is set to ignore them all.
577 __ fprem();
578 // The following 2 instruction implicitly use eax.
579 __ fnstsw_ax();
580 __ sahf();
581 __ j(parity_even, &mod_loop);
582 // Move output to stack and clean up.
583 __ fstp(1);
584 __ fstp_d(Operand(esp, 0));
585 __ movsd(i.OutputDoubleRegister(), Operand(esp, 0));
586 __ add(esp, Immediate(kDoubleSize)); 972 __ add(esp, Immediate(kDoubleSize));
587 break; 973 break;
588 } 974 }
589 case kSSEFloat64Abs: { 975 case kX87Float64InsertLowWord32: {
590 // TODO(bmeurer): Use 128-bit constants. 976 __ sub(esp, Immediate(kDoubleSize));
591 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); 977 __ fstp_d(MemOperand(esp, 0));
592 __ psrlq(kScratchDoubleReg, 1); 978 __ mov(MemOperand(esp, 0), i.InputRegister(1));
593 __ andpd(i.OutputDoubleRegister(), kScratchDoubleReg); 979 __ fld_d(MemOperand(esp, 0));
594 break; 980 __ add(esp, Immediate(kDoubleSize));
595 } 981 break;
596 case kSSEFloat64Neg: { 982 }
597 // TODO(bmeurer): Use 128-bit constants. 983 case kX87Float64Sqrt: {
598 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); 984 __ fstp(0);
599 __ psllq(kScratchDoubleReg, 63); 985 __ fld_d(MemOperand(esp, 0));
600 __ xorpd(i.OutputDoubleRegister(), kScratchDoubleReg); 986 __ fsqrt();
601 break; 987 __ lea(esp, Operand(esp, kDoubleSize));
602 } 988 break;
603 case kSSEFloat64Sqrt: 989 }
604 __ sqrtsd(i.OutputDoubleRegister(), i.InputOperand(0)); 990 case kX87Float64Round: {
605 break; 991 RoundingMode mode =
606 case kSSEFloat64Round: {
607 CpuFeatureScope sse_scope(masm(), SSE4_1);
608 RoundingMode const mode =
609 static_cast<RoundingMode>(MiscField::decode(instr->opcode())); 992 static_cast<RoundingMode>(MiscField::decode(instr->opcode()));
610 __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode); 993 if (mode == MiscField::encode(kRoundDown)) {
611 break; 994 __ X87SetRC(0x0400);
612 } 995 } else {
613 case kSSEFloat32ToFloat64: 996 __ X87SetRC(0x0c00);
614 __ cvtss2sd(i.OutputDoubleRegister(), i.InputOperand(0)); 997 }
615 break; 998
616 case kSSEFloat64ToFloat32: 999 if (!instr->InputAt(0)->IsDoubleRegister()) {
617 __ cvtsd2ss(i.OutputDoubleRegister(), i.InputOperand(0)); 1000 InstructionOperand* input = instr->InputAt(0);
618 break; 1001 USE(input);
619 case kSSEFloat64ToInt32: 1002 DCHECK(input->IsDoubleStackSlot());
620 __ cvttsd2si(i.OutputRegister(), i.InputOperand(0)); 1003 __ fstp(0);
621 break; 1004 __ fld_d(i.InputOperand(0));
622 case kSSEFloat64ToUint32: { 1005 }
623 __ Move(kScratchDoubleReg, -2147483648.0); 1006 __ frndint();
624 __ addsd(kScratchDoubleReg, i.InputOperand(0)); 1007 __ X87SetRC(0x0000);
625 __ cvttsd2si(i.OutputRegister(), kScratchDoubleReg); 1008 break;
626 __ add(i.OutputRegister(), Immediate(0x80000000)); 1009 }
627 break; 1010 case kX87Float64Cmp: {
628 } 1011 __ fld_d(MemOperand(esp, kDoubleSize));
629 case kSSEInt32ToFloat64: 1012 __ fld_d(MemOperand(esp, 0));
630 __ cvtsi2sd(i.OutputDoubleRegister(), i.InputOperand(0)); 1013 __ FCmp();
631 break; 1014 __ lea(esp, Operand(esp, 2 * kDoubleSize));
632 case kSSEUint32ToFloat64: 1015 break;
633 __ LoadUint32(i.OutputDoubleRegister(), i.InputOperand(0)); 1016 }
634 break; 1017 case kX87Movsxbl:
635 case kSSEFloat64ExtractLowWord32:
636 if (instr->InputAt(0)->IsDoubleStackSlot()) {
637 __ mov(i.OutputRegister(), i.InputOperand(0));
638 } else {
639 __ movd(i.OutputRegister(), i.InputDoubleRegister(0));
640 }
641 break;
642 case kSSEFloat64ExtractHighWord32:
643 if (instr->InputAt(0)->IsDoubleStackSlot()) {
644 __ mov(i.OutputRegister(), i.InputOperand(0, kDoubleSize / 2));
645 } else {
646 __ Pextrd(i.OutputRegister(), i.InputDoubleRegister(0), 1);
647 }
648 break;
649 case kSSEFloat64InsertLowWord32:
650 __ Pinsrd(i.OutputDoubleRegister(), i.InputOperand(1), 0);
651 break;
652 case kSSEFloat64InsertHighWord32:
653 __ Pinsrd(i.OutputDoubleRegister(), i.InputOperand(1), 1);
654 break;
655 case kSSEFloat64LoadLowWord32:
656 __ movd(i.OutputDoubleRegister(), i.InputOperand(0));
657 break;
658 case kAVXFloat32Add: {
659 CpuFeatureScope avx_scope(masm(), AVX);
660 __ vaddss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
661 i.InputOperand(1));
662 break;
663 }
664 case kAVXFloat32Sub: {
665 CpuFeatureScope avx_scope(masm(), AVX);
666 __ vsubss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
667 i.InputOperand(1));
668 break;
669 }
670 case kAVXFloat32Mul: {
671 CpuFeatureScope avx_scope(masm(), AVX);
672 __ vmulss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
673 i.InputOperand(1));
674 break;
675 }
676 case kAVXFloat32Div: {
677 CpuFeatureScope avx_scope(masm(), AVX);
678 __ vdivss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
679 i.InputOperand(1));
680 // Don't delete this mov. It may improve performance on some CPUs,
681 // when there is a (v)mulss depending on the result.
682 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
683 break;
684 }
685 case kAVXFloat32Max: {
686 CpuFeatureScope avx_scope(masm(), AVX);
687 __ vmaxss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
688 i.InputOperand(1));
689 break;
690 }
691 case kAVXFloat32Min: {
692 CpuFeatureScope avx_scope(masm(), AVX);
693 __ vminss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
694 i.InputOperand(1));
695 break;
696 }
697 case kAVXFloat64Add: {
698 CpuFeatureScope avx_scope(masm(), AVX);
699 __ vaddsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
700 i.InputOperand(1));
701 break;
702 }
703 case kAVXFloat64Sub: {
704 CpuFeatureScope avx_scope(masm(), AVX);
705 __ vsubsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
706 i.InputOperand(1));
707 break;
708 }
709 case kAVXFloat64Mul: {
710 CpuFeatureScope avx_scope(masm(), AVX);
711 __ vmulsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
712 i.InputOperand(1));
713 break;
714 }
715 case kAVXFloat64Div: {
716 CpuFeatureScope avx_scope(masm(), AVX);
717 __ vdivsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
718 i.InputOperand(1));
719 // Don't delete this mov. It may improve performance on some CPUs,
720 // when there is a (v)mulsd depending on the result.
721 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
722 break;
723 }
724 case kAVXFloat64Max: {
725 CpuFeatureScope avx_scope(masm(), AVX);
726 __ vmaxsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
727 i.InputOperand(1));
728 break;
729 }
730 case kAVXFloat64Min: {
731 CpuFeatureScope avx_scope(masm(), AVX);
732 __ vminsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
733 i.InputOperand(1));
734 break;
735 }
736 case kAVXFloat32Abs: {
737 // TODO(bmeurer): Use RIP relative 128-bit constants.
738 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
739 __ psrlq(kScratchDoubleReg, 33);
740 CpuFeatureScope avx_scope(masm(), AVX);
741 __ vandps(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
742 break;
743 }
744 case kAVXFloat32Neg: {
745 // TODO(bmeurer): Use RIP relative 128-bit constants.
746 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
747 __ psllq(kScratchDoubleReg, 31);
748 CpuFeatureScope avx_scope(masm(), AVX);
749 __ vxorps(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
750 break;
751 }
752 case kAVXFloat64Abs: {
753 // TODO(bmeurer): Use RIP relative 128-bit constants.
754 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
755 __ psrlq(kScratchDoubleReg, 1);
756 CpuFeatureScope avx_scope(masm(), AVX);
757 __ vandpd(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
758 break;
759 }
760 case kAVXFloat64Neg: {
761 // TODO(bmeurer): Use RIP relative 128-bit constants.
762 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
763 __ psllq(kScratchDoubleReg, 63);
764 CpuFeatureScope avx_scope(masm(), AVX);
765 __ vxorpd(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
766 break;
767 }
768 case kIA32Movsxbl:
769 __ movsx_b(i.OutputRegister(), i.MemoryOperand()); 1018 __ movsx_b(i.OutputRegister(), i.MemoryOperand());
770 break; 1019 break;
771 case kIA32Movzxbl: 1020 case kX87Movzxbl:
772 __ movzx_b(i.OutputRegister(), i.MemoryOperand()); 1021 __ movzx_b(i.OutputRegister(), i.MemoryOperand());
773 break; 1022 break;
774 case kIA32Movb: { 1023 case kX87Movb: {
775 size_t index = 0; 1024 size_t index = 0;
776 Operand operand = i.MemoryOperand(&index); 1025 Operand operand = i.MemoryOperand(&index);
777 if (HasImmediateInput(instr, index)) { 1026 if (HasImmediateInput(instr, index)) {
778 __ mov_b(operand, i.InputInt8(index)); 1027 __ mov_b(operand, i.InputInt8(index));
779 } else { 1028 } else {
780 __ mov_b(operand, i.InputRegister(index)); 1029 __ mov_b(operand, i.InputRegister(index));
781 } 1030 }
782 break; 1031 break;
783 } 1032 }
784 case kIA32Movsxwl: 1033 case kX87Movsxwl:
785 __ movsx_w(i.OutputRegister(), i.MemoryOperand()); 1034 __ movsx_w(i.OutputRegister(), i.MemoryOperand());
786 break; 1035 break;
787 case kIA32Movzxwl: 1036 case kX87Movzxwl:
788 __ movzx_w(i.OutputRegister(), i.MemoryOperand()); 1037 __ movzx_w(i.OutputRegister(), i.MemoryOperand());
789 break; 1038 break;
790 case kIA32Movw: { 1039 case kX87Movw: {
791 size_t index = 0; 1040 size_t index = 0;
792 Operand operand = i.MemoryOperand(&index); 1041 Operand operand = i.MemoryOperand(&index);
793 if (HasImmediateInput(instr, index)) { 1042 if (HasImmediateInput(instr, index)) {
794 __ mov_w(operand, i.InputInt16(index)); 1043 __ mov_w(operand, i.InputInt16(index));
795 } else { 1044 } else {
796 __ mov_w(operand, i.InputRegister(index)); 1045 __ mov_w(operand, i.InputRegister(index));
797 } 1046 }
798 break; 1047 break;
799 } 1048 }
800 case kIA32Movl: 1049 case kX87Movl:
801 if (instr->HasOutput()) { 1050 if (instr->HasOutput()) {
802 __ mov(i.OutputRegister(), i.MemoryOperand()); 1051 __ mov(i.OutputRegister(), i.MemoryOperand());
803 } else { 1052 } else {
804 size_t index = 0; 1053 size_t index = 0;
805 Operand operand = i.MemoryOperand(&index); 1054 Operand operand = i.MemoryOperand(&index);
806 if (HasImmediateInput(instr, index)) { 1055 if (HasImmediateInput(instr, index)) {
807 __ mov(operand, i.InputImmediate(index)); 1056 __ mov(operand, i.InputImmediate(index));
808 } else { 1057 } else {
809 __ mov(operand, i.InputRegister(index)); 1058 __ mov(operand, i.InputRegister(index));
810 } 1059 }
811 } 1060 }
812 break; 1061 break;
813 case kIA32Movsd: 1062 case kX87Movsd: {
814 if (instr->HasOutput()) { 1063 if (instr->HasOutput()) {
815 __ movsd(i.OutputDoubleRegister(), i.MemoryOperand()); 1064 X87Register output = i.OutputDoubleRegister();
1065 USE(output);
1066 DCHECK(output.code() == 0);
1067 __ fstp(0);
1068 __ fld_d(i.MemoryOperand());
816 } else { 1069 } else {
817 size_t index = 0; 1070 size_t index = 0;
818 Operand operand = i.MemoryOperand(&index); 1071 Operand operand = i.MemoryOperand(&index);
819 __ movsd(operand, i.InputDoubleRegister(index)); 1072 __ fst_d(operand);
820 } 1073 }
821 break; 1074 break;
822 case kIA32Movss: 1075 }
1076 case kX87Movss: {
823 if (instr->HasOutput()) { 1077 if (instr->HasOutput()) {
824 __ movss(i.OutputDoubleRegister(), i.MemoryOperand()); 1078 X87Register output = i.OutputDoubleRegister();
1079 USE(output);
1080 DCHECK(output.code() == 0);
1081 __ fstp(0);
1082 __ fld_s(i.MemoryOperand());
825 } else { 1083 } else {
826 size_t index = 0; 1084 size_t index = 0;
827 Operand operand = i.MemoryOperand(&index); 1085 Operand operand = i.MemoryOperand(&index);
828 __ movss(operand, i.InputDoubleRegister(index)); 1086 __ fst_s(operand);
829 } 1087 }
830 break; 1088 break;
831 case kIA32Lea: { 1089 }
1090 case kX87Lea: {
832 AddressingMode mode = AddressingModeField::decode(instr->opcode()); 1091 AddressingMode mode = AddressingModeField::decode(instr->opcode());
833 // Shorten "leal" to "addl", "subl" or "shll" if the register allocation 1092 // Shorten "leal" to "addl", "subl" or "shll" if the register allocation
834 // and addressing mode just happens to work out. The "addl"/"subl" forms 1093 // and addressing mode just happens to work out. The "addl"/"subl" forms
835 // in these cases are faster based on measurements. 1094 // in these cases are faster based on measurements.
836 if (mode == kMode_MI) { 1095 if (mode == kMode_MI) {
837 __ Move(i.OutputRegister(), Immediate(i.InputInt32(0))); 1096 __ Move(i.OutputRegister(), Immediate(i.InputInt32(0)));
838 } else if (i.InputRegister(0).is(i.OutputRegister())) { 1097 } else if (i.InputRegister(0).is(i.OutputRegister())) {
839 if (mode == kMode_MRI) { 1098 if (mode == kMode_MRI) {
840 int32_t constant_summand = i.InputInt32(1); 1099 int32_t constant_summand = i.InputInt32(1);
841 if (constant_summand > 0) { 1100 if (constant_summand > 0) {
(...skipping 14 matching lines...) Expand all
856 } else if (mode == kMode_M8) { 1115 } else if (mode == kMode_M8) {
857 __ shl(i.OutputRegister(), 3); 1116 __ shl(i.OutputRegister(), 3);
858 } else { 1117 } else {
859 __ lea(i.OutputRegister(), i.MemoryOperand()); 1118 __ lea(i.OutputRegister(), i.MemoryOperand());
860 } 1119 }
861 } else { 1120 } else {
862 __ lea(i.OutputRegister(), i.MemoryOperand()); 1121 __ lea(i.OutputRegister(), i.MemoryOperand());
863 } 1122 }
864 break; 1123 break;
865 } 1124 }
866 case kIA32Push: 1125 case kX87Push:
867 if (HasImmediateInput(instr, 0)) { 1126 if (HasImmediateInput(instr, 0)) {
868 __ push(i.InputImmediate(0)); 1127 __ push(i.InputImmediate(0));
869 } else { 1128 } else {
870 __ push(i.InputOperand(0)); 1129 __ push(i.InputOperand(0));
871 } 1130 }
872 break; 1131 break;
873 case kIA32StoreWriteBarrier: { 1132 case kX87PushFloat32:
1133 __ lea(esp, Operand(esp, -kFloatSize));
1134 if (instr->InputAt(0)->IsDoubleStackSlot()) {
1135 __ fld_s(i.InputOperand(0));
1136 __ fstp_s(MemOperand(esp, 0));
1137 } else if (instr->InputAt(0)->IsDoubleRegister()) {
1138 __ fst_s(MemOperand(esp, 0));
1139 } else {
1140 UNREACHABLE();
1141 }
1142 break;
1143 case kX87PushFloat64:
1144 __ lea(esp, Operand(esp, -kDoubleSize));
1145 if (instr->InputAt(0)->IsDoubleStackSlot()) {
1146 __ fld_d(i.InputOperand(0));
1147 __ fstp_d(MemOperand(esp, 0));
1148 } else if (instr->InputAt(0)->IsDoubleRegister()) {
1149 __ fst_d(MemOperand(esp, 0));
1150 } else {
1151 UNREACHABLE();
1152 }
1153 break;
1154 case kX87StoreWriteBarrier: {
874 Register object = i.InputRegister(0); 1155 Register object = i.InputRegister(0);
875 Register value = i.InputRegister(2); 1156 Register value = i.InputRegister(2);
876 SaveFPRegsMode mode = 1157 SaveFPRegsMode mode =
877 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; 1158 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
878 if (HasImmediateInput(instr, 1)) { 1159 if (HasImmediateInput(instr, 1)) {
879 int index = i.InputInt32(1); 1160 int index = i.InputInt32(1);
880 Register scratch = i.TempRegister(1); 1161 Register scratch = i.TempRegister(1);
881 __ mov(Operand(object, index), value); 1162 __ mov(Operand(object, index), value);
882 __ RecordWriteContextSlot(object, index, value, scratch, mode); 1163 __ RecordWriteContextSlot(object, index, value, scratch, mode);
883 } else { 1164 } else {
(...skipping 13 matching lines...) Expand all
897 case kCheckedLoadInt16: 1178 case kCheckedLoadInt16:
898 ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_w); 1179 ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_w);
899 break; 1180 break;
900 case kCheckedLoadUint16: 1181 case kCheckedLoadUint16:
901 ASSEMBLE_CHECKED_LOAD_INTEGER(movzx_w); 1182 ASSEMBLE_CHECKED_LOAD_INTEGER(movzx_w);
902 break; 1183 break;
903 case kCheckedLoadWord32: 1184 case kCheckedLoadWord32:
904 ASSEMBLE_CHECKED_LOAD_INTEGER(mov); 1185 ASSEMBLE_CHECKED_LOAD_INTEGER(mov);
905 break; 1186 break;
906 case kCheckedLoadFloat32: 1187 case kCheckedLoadFloat32:
907 ASSEMBLE_CHECKED_LOAD_FLOAT(movss); 1188 ASSEMBLE_CHECKED_LOAD_FLOAT(fld_s);
908 break; 1189 break;
909 case kCheckedLoadFloat64: 1190 case kCheckedLoadFloat64:
910 ASSEMBLE_CHECKED_LOAD_FLOAT(movsd); 1191 ASSEMBLE_CHECKED_LOAD_FLOAT(fld_d);
911 break; 1192 break;
912 case kCheckedStoreWord8: 1193 case kCheckedStoreWord8:
913 ASSEMBLE_CHECKED_STORE_INTEGER(mov_b); 1194 ASSEMBLE_CHECKED_STORE_INTEGER(mov_b);
914 break; 1195 break;
915 case kCheckedStoreWord16: 1196 case kCheckedStoreWord16:
916 ASSEMBLE_CHECKED_STORE_INTEGER(mov_w); 1197 ASSEMBLE_CHECKED_STORE_INTEGER(mov_w);
917 break; 1198 break;
918 case kCheckedStoreWord32: 1199 case kCheckedStoreWord32:
919 ASSEMBLE_CHECKED_STORE_INTEGER(mov); 1200 ASSEMBLE_CHECKED_STORE_INTEGER(mov);
920 break; 1201 break;
921 case kCheckedStoreFloat32: 1202 case kCheckedStoreFloat32:
922 ASSEMBLE_CHECKED_STORE_FLOAT(movss); 1203 ASSEMBLE_CHECKED_STORE_FLOAT(fst_s);
923 break; 1204 break;
924 case kCheckedStoreFloat64: 1205 case kCheckedStoreFloat64:
925 ASSEMBLE_CHECKED_STORE_FLOAT(movsd); 1206 ASSEMBLE_CHECKED_STORE_FLOAT(fst_d);
926 break; 1207 break;
927 case kIA32StackCheck: { 1208 case kX87StackCheck: {
928 ExternalReference const stack_limit = 1209 ExternalReference const stack_limit =
929 ExternalReference::address_of_stack_limit(isolate()); 1210 ExternalReference::address_of_stack_limit(isolate());
930 __ cmp(esp, Operand::StaticVariable(stack_limit)); 1211 __ cmp(esp, Operand::StaticVariable(stack_limit));
931 break; 1212 break;
932 } 1213 }
933 } 1214 }
934 } // NOLINT(readability/fn_size) 1215 } // NOLINT(readability/fn_size)
935 1216
936 1217
937 // Assembles a branch after an instruction. 1218 // Assembles a branch after an instruction.
938 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { 1219 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
939 IA32OperandConverter i(this, instr); 1220 X87OperandConverter i(this, instr);
940 Label::Distance flabel_distance = 1221 Label::Distance flabel_distance =
941 branch->fallthru ? Label::kNear : Label::kFar; 1222 branch->fallthru ? Label::kNear : Label::kFar;
942 Label* tlabel = branch->true_label; 1223 Label* tlabel = branch->true_label;
943 Label* flabel = branch->false_label; 1224 Label* flabel = branch->false_label;
944 switch (branch->condition) { 1225 switch (branch->condition) {
945 case kUnorderedEqual: 1226 case kUnorderedEqual:
946 __ j(parity_even, flabel, flabel_distance); 1227 __ j(parity_even, flabel, flabel_distance);
947 // Fall through. 1228 // Fall through.
948 case kEqual: 1229 case kEqual:
949 __ j(equal, tlabel); 1230 __ j(equal, tlabel);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 1272
992 1273
993 void CodeGenerator::AssembleArchJump(RpoNumber target) { 1274 void CodeGenerator::AssembleArchJump(RpoNumber target) {
994 if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target)); 1275 if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target));
995 } 1276 }
996 1277
997 1278
998 // Assembles boolean materializations after an instruction. 1279 // Assembles boolean materializations after an instruction.
999 void CodeGenerator::AssembleArchBoolean(Instruction* instr, 1280 void CodeGenerator::AssembleArchBoolean(Instruction* instr,
1000 FlagsCondition condition) { 1281 FlagsCondition condition) {
1001 IA32OperandConverter i(this, instr); 1282 X87OperandConverter i(this, instr);
1002 Label done; 1283 Label done;
1003 1284
1004 // Materialize a full 32-bit 1 or 0 value. The result register is always the 1285 // Materialize a full 32-bit 1 or 0 value. The result register is always the
1005 // last output of the instruction. 1286 // last output of the instruction.
1006 Label check; 1287 Label check;
1007 DCHECK_NE(0u, instr->OutputCount()); 1288 DCHECK_NE(0u, instr->OutputCount());
1008 Register reg = i.OutputRegister(instr->OutputCount() - 1); 1289 Register reg = i.OutputRegister(instr->OutputCount() - 1);
1009 Condition cc = no_condition; 1290 Condition cc = no_condition;
1010 switch (condition) { 1291 switch (condition) {
1011 case kUnorderedEqual: 1292 case kUnorderedEqual:
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 __ Move(reg, Immediate(0)); 1348 __ Move(reg, Immediate(0));
1068 __ jmp(&done, Label::kNear); 1349 __ jmp(&done, Label::kNear);
1069 __ bind(&set); 1350 __ bind(&set);
1070 __ mov(reg, Immediate(1)); 1351 __ mov(reg, Immediate(1));
1071 } 1352 }
1072 __ bind(&done); 1353 __ bind(&done);
1073 } 1354 }
1074 1355
1075 1356
1076 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { 1357 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
1077 IA32OperandConverter i(this, instr); 1358 X87OperandConverter i(this, instr);
1078 Register input = i.InputRegister(0); 1359 Register input = i.InputRegister(0);
1079 for (size_t index = 2; index < instr->InputCount(); index += 2) { 1360 for (size_t index = 2; index < instr->InputCount(); index += 2) {
1080 __ cmp(input, Immediate(i.InputInt32(index + 0))); 1361 __ cmp(input, Immediate(i.InputInt32(index + 0)));
1081 __ j(equal, GetLabel(i.InputRpo(index + 1))); 1362 __ j(equal, GetLabel(i.InputRpo(index + 1)));
1082 } 1363 }
1083 AssembleArchJump(i.InputRpo(1)); 1364 AssembleArchJump(i.InputRpo(1));
1084 } 1365 }
1085 1366
1086 1367
1087 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) { 1368 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
1088 IA32OperandConverter i(this, instr); 1369 X87OperandConverter i(this, instr);
1089 Register input = i.InputRegister(0); 1370 Register input = i.InputRegister(0);
1090 size_t const case_count = instr->InputCount() - 2; 1371 size_t const case_count = instr->InputCount() - 2;
1091 Label** cases = zone()->NewArray<Label*>(case_count); 1372 Label** cases = zone()->NewArray<Label*>(case_count);
1092 for (size_t index = 0; index < case_count; ++index) { 1373 for (size_t index = 0; index < case_count; ++index) {
1093 cases[index] = GetLabel(i.InputRpo(index + 2)); 1374 cases[index] = GetLabel(i.InputRpo(index + 2));
1094 } 1375 }
1095 Label* const table = AddJumpTable(cases, case_count); 1376 Label* const table = AddJumpTable(cases, case_count);
1096 __ cmp(input, Immediate(case_count)); 1377 __ cmp(input, Immediate(case_count));
1097 __ j(above_equal, GetLabel(i.InputRpo(1))); 1378 __ j(above_equal, GetLabel(i.InputRpo(1)));
1098 __ jmp(Operand::JumpTable(input, times_4, table)); 1379 __ jmp(Operand::JumpTable(input, times_4, table));
1099 } 1380 }
1100 1381
1101 1382
1102 void CodeGenerator::AssembleDeoptimizerCall( 1383 void CodeGenerator::AssembleDeoptimizerCall(
1103 int deoptimization_id, Deoptimizer::BailoutType bailout_type) { 1384 int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
1104 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( 1385 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
1105 isolate(), deoptimization_id, bailout_type); 1386 isolate(), deoptimization_id, bailout_type);
1106 __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY); 1387 __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
1107 } 1388 }
1108 1389
1109 1390
1110 // The calling convention for JSFunctions on IA32 passes arguments on the 1391 // The calling convention for JSFunctions on X87 passes arguments on the
1111 // stack and the JSFunction and context in EDI and ESI, respectively, thus 1392 // stack and the JSFunction and context in EDI and ESI, respectively, thus
1112 // the steps of the call look as follows: 1393 // the steps of the call look as follows:
1113 1394
1114 // --{ before the call instruction }-------------------------------------------- 1395 // --{ before the call instruction }--------------------------------------------
1115 // | caller frame | 1396 // | caller frame |
1116 // ^ esp ^ ebp 1397 // ^ esp ^ ebp
1117 1398
1118 // --{ push arguments and setup ESI, EDI }-------------------------------------- 1399 // --{ push arguments and setup ESI, EDI }--------------------------------------
1119 // | args + receiver | caller frame | 1400 // | args + receiver | caller frame |
1120 // ^ esp ^ ebp 1401 // ^ esp ^ ebp
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1155 // --{ pop ebp }----------------------------------------------------------- 1436 // --{ pop ebp }-----------------------------------------------------------
1156 // | | RET | args + receiver | caller frame | 1437 // | | RET | args + receiver | caller frame |
1157 // ^ esp ^ ebp 1438 // ^ esp ^ ebp
1158 1439
1159 // --{ ret #A+1 }----------------------------------------------------------- 1440 // --{ ret #A+1 }-----------------------------------------------------------
1160 // | | caller frame | 1441 // | | caller frame |
1161 // ^ esp ^ ebp 1442 // ^ esp ^ ebp
1162 1443
1163 1444
1164 // Runtime function calls are accomplished by doing a stub call to the 1445 // Runtime function calls are accomplished by doing a stub call to the
1165 // CEntryStub (a real code object). On IA32 passes arguments on the 1446 // CEntryStub (a real code object). On X87 passes arguments on the
1166 // stack, the number of arguments in EAX, the address of the runtime function 1447 // stack, the number of arguments in EAX, the address of the runtime function
1167 // in EBX, and the context in ESI. 1448 // in EBX, and the context in ESI.
1168 1449
1169 // --{ before the call instruction }-------------------------------------------- 1450 // --{ before the call instruction }--------------------------------------------
1170 // | caller frame | 1451 // | caller frame |
1171 // ^ esp ^ ebp 1452 // ^ esp ^ ebp
1172 1453
1173 // --{ push arguments and setup EAX, EBX, and ESI }----------------------------- 1454 // --{ push arguments and setup EAX, EBX, and ESI }-----------------------------
1174 // | args + receiver | caller frame | 1455 // | args + receiver | caller frame |
1175 // ^ esp ^ ebp 1456 // ^ esp ^ ebp
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 // TODO(titzer): cannot address target function == local #-1 1559 // TODO(titzer): cannot address target function == local #-1
1279 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1560 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1280 DCHECK(stack_slots >= frame()->GetOsrStackSlotCount()); 1561 DCHECK(stack_slots >= frame()->GetOsrStackSlotCount());
1281 stack_slots -= frame()->GetOsrStackSlotCount(); 1562 stack_slots -= frame()->GetOsrStackSlotCount();
1282 } 1563 }
1283 1564
1284 if (stack_slots > 0) { 1565 if (stack_slots > 0) {
1285 // Allocate the stack slots used by this frame. 1566 // Allocate the stack slots used by this frame.
1286 __ sub(esp, Immediate(stack_slots * kPointerSize)); 1567 __ sub(esp, Immediate(stack_slots * kPointerSize));
1287 } 1568 }
1569
1570 // Initailize FPU state.
1571 __ fninit();
1572 __ fld1();
1288 } 1573 }
1289 1574
1290 1575
1291 void CodeGenerator::AssembleReturn() { 1576 void CodeGenerator::AssembleReturn() {
1292 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); 1577 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1293 int stack_slots = frame()->GetSpillSlotCount(); 1578 int stack_slots = frame()->GetSpillSlotCount();
1294 if (descriptor->kind() == CallDescriptor::kCallAddress) { 1579 if (descriptor->kind() == CallDescriptor::kCallAddress) {
1295 const RegList saves = descriptor->CalleeSavedRegisters(); 1580 const RegList saves = descriptor->CalleeSavedRegisters();
1296 if (frame()->GetRegisterSaveAreaSize() > 0) { 1581 if (frame()->GetRegisterSaveAreaSize() > 0) {
1297 // Remove this frame's spill slots first. 1582 // Remove this frame's spill slots first.
(...skipping 23 matching lines...) Expand all
1321 : 0; 1606 : 0;
1322 __ Ret(pop_count * kPointerSize, ebx); 1607 __ Ret(pop_count * kPointerSize, ebx);
1323 } else { 1608 } else {
1324 __ ret(0); 1609 __ ret(0);
1325 } 1610 }
1326 } 1611 }
1327 1612
1328 1613
1329 void CodeGenerator::AssembleMove(InstructionOperand* source, 1614 void CodeGenerator::AssembleMove(InstructionOperand* source,
1330 InstructionOperand* destination) { 1615 InstructionOperand* destination) {
1331 IA32OperandConverter g(this, NULL); 1616 X87OperandConverter g(this, NULL);
1332 // Dispatch on the source and destination operand kinds. Not all 1617 // Dispatch on the source and destination operand kinds. Not all
1333 // combinations are possible. 1618 // combinations are possible.
1334 if (source->IsRegister()) { 1619 if (source->IsRegister()) {
1335 DCHECK(destination->IsRegister() || destination->IsStackSlot()); 1620 DCHECK(destination->IsRegister() || destination->IsStackSlot());
1336 Register src = g.ToRegister(source); 1621 Register src = g.ToRegister(source);
1337 Operand dst = g.ToOperand(destination); 1622 Operand dst = g.ToOperand(destination);
1338 __ mov(dst, src); 1623 __ mov(dst, src);
1339 } else if (source->IsStackSlot()) { 1624 } else if (source->IsStackSlot()) {
1340 DCHECK(destination->IsRegister() || destination->IsStackSlot()); 1625 DCHECK(destination->IsRegister() || destination->IsStackSlot());
1341 Operand src = g.ToOperand(source); 1626 Operand src = g.ToOperand(source);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1379 } else if (destination->IsRegister()) { 1664 } else if (destination->IsRegister()) {
1380 Register dst = g.ToRegister(destination); 1665 Register dst = g.ToRegister(destination);
1381 __ Move(dst, g.ToImmediate(source)); 1666 __ Move(dst, g.ToImmediate(source));
1382 } else if (destination->IsStackSlot()) { 1667 } else if (destination->IsStackSlot()) {
1383 Operand dst = g.ToOperand(destination); 1668 Operand dst = g.ToOperand(destination);
1384 __ Move(dst, g.ToImmediate(source)); 1669 __ Move(dst, g.ToImmediate(source));
1385 } else if (src_constant.type() == Constant::kFloat32) { 1670 } else if (src_constant.type() == Constant::kFloat32) {
1386 // TODO(turbofan): Can we do better here? 1671 // TODO(turbofan): Can we do better here?
1387 uint32_t src = bit_cast<uint32_t>(src_constant.ToFloat32()); 1672 uint32_t src = bit_cast<uint32_t>(src_constant.ToFloat32());
1388 if (destination->IsDoubleRegister()) { 1673 if (destination->IsDoubleRegister()) {
1389 XMMRegister dst = g.ToDoubleRegister(destination); 1674 __ sub(esp, Immediate(kInt32Size));
1390 __ Move(dst, src); 1675 __ mov(MemOperand(esp, 0), Immediate(src));
1676 // always only push one value into the x87 stack.
1677 __ fstp(0);
1678 __ fld_s(MemOperand(esp, 0));
1679 __ add(esp, Immediate(kInt32Size));
1391 } else { 1680 } else {
1392 DCHECK(destination->IsDoubleStackSlot()); 1681 DCHECK(destination->IsDoubleStackSlot());
1393 Operand dst = g.ToOperand(destination); 1682 Operand dst = g.ToOperand(destination);
1394 __ Move(dst, Immediate(src)); 1683 __ Move(dst, Immediate(src));
1395 } 1684 }
1396 } else { 1685 } else {
1397 DCHECK_EQ(Constant::kFloat64, src_constant.type()); 1686 DCHECK_EQ(Constant::kFloat64, src_constant.type());
1398 uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64()); 1687 uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64());
1399 uint32_t lower = static_cast<uint32_t>(src); 1688 uint32_t lower = static_cast<uint32_t>(src);
1400 uint32_t upper = static_cast<uint32_t>(src >> 32); 1689 uint32_t upper = static_cast<uint32_t>(src >> 32);
1401 if (destination->IsDoubleRegister()) { 1690 if (destination->IsDoubleRegister()) {
1402 XMMRegister dst = g.ToDoubleRegister(destination); 1691 __ sub(esp, Immediate(kDoubleSize));
1403 __ Move(dst, src); 1692 __ mov(MemOperand(esp, 0), Immediate(lower));
1693 __ mov(MemOperand(esp, kInt32Size), Immediate(upper));
1694 // always only push one value into the x87 stack.
1695 __ fstp(0);
1696 __ fld_d(MemOperand(esp, 0));
1697 __ add(esp, Immediate(kDoubleSize));
1404 } else { 1698 } else {
1405 DCHECK(destination->IsDoubleStackSlot()); 1699 DCHECK(destination->IsDoubleStackSlot());
1406 Operand dst0 = g.ToOperand(destination); 1700 Operand dst0 = g.ToOperand(destination);
1407 Operand dst1 = g.HighOperand(destination); 1701 Operand dst1 = g.HighOperand(destination);
1408 __ Move(dst0, Immediate(lower)); 1702 __ Move(dst0, Immediate(lower));
1409 __ Move(dst1, Immediate(upper)); 1703 __ Move(dst1, Immediate(upper));
1410 } 1704 }
1411 } 1705 }
1412 } else if (source->IsDoubleRegister()) { 1706 } else if (source->IsDoubleRegister()) {
1413 XMMRegister src = g.ToDoubleRegister(source); 1707 DCHECK(destination->IsDoubleStackSlot());
1414 if (destination->IsDoubleRegister()) { 1708 Operand dst = g.ToOperand(destination);
1415 XMMRegister dst = g.ToDoubleRegister(destination); 1709 auto allocated = AllocatedOperand::cast(*source);
1416 __ movaps(dst, src); 1710 switch (allocated.machine_type()) {
1417 } else { 1711 case kRepFloat32:
1418 DCHECK(destination->IsDoubleStackSlot()); 1712 __ fst_s(dst);
1419 Operand dst = g.ToOperand(destination); 1713 break;
1420 __ movsd(dst, src); 1714 case kRepFloat64:
1715 __ fst_d(dst);
1716 break;
1717 default:
1718 UNREACHABLE();
1421 } 1719 }
1422 } else if (source->IsDoubleStackSlot()) { 1720 } else if (source->IsDoubleStackSlot()) {
1423 DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot()); 1721 DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
1424 Operand src = g.ToOperand(source); 1722 Operand src = g.ToOperand(source);
1723 auto allocated = AllocatedOperand::cast(*source);
1425 if (destination->IsDoubleRegister()) { 1724 if (destination->IsDoubleRegister()) {
1426 XMMRegister dst = g.ToDoubleRegister(destination); 1725 // always only push one value into the x87 stack.
1427 __ movsd(dst, src); 1726 __ fstp(0);
1727 switch (allocated.machine_type()) {
1728 case kRepFloat32:
1729 __ fld_s(src);
1730 break;
1731 case kRepFloat64:
1732 __ fld_d(src);
1733 break;
1734 default:
1735 UNREACHABLE();
1736 }
1428 } else { 1737 } else {
1429 Operand dst = g.ToOperand(destination); 1738 Operand dst = g.ToOperand(destination);
1430 __ movsd(kScratchDoubleReg, src); 1739 switch (allocated.machine_type()) {
1431 __ movsd(dst, kScratchDoubleReg); 1740 case kRepFloat32:
1741 __ fld_s(src);
1742 __ fstp_s(dst);
1743 break;
1744 case kRepFloat64:
1745 __ fld_d(src);
1746 __ fstp_d(dst);
1747 break;
1748 default:
1749 UNREACHABLE();
1750 }
1432 } 1751 }
1433 } else { 1752 } else {
1434 UNREACHABLE(); 1753 UNREACHABLE();
1435 } 1754 }
1436 } 1755 }
1437 1756
1438 1757
1439 void CodeGenerator::AssembleSwap(InstructionOperand* source, 1758 void CodeGenerator::AssembleSwap(InstructionOperand* source,
1440 InstructionOperand* destination) { 1759 InstructionOperand* destination) {
1441 IA32OperandConverter g(this, NULL); 1760 X87OperandConverter g(this, NULL);
1442 // Dispatch on the source and destination operand kinds. Not all 1761 // Dispatch on the source and destination operand kinds. Not all
1443 // combinations are possible. 1762 // combinations are possible.
1444 if (source->IsRegister() && destination->IsRegister()) { 1763 if (source->IsRegister() && destination->IsRegister()) {
1445 // Register-register. 1764 // Register-register.
1446 Register src = g.ToRegister(source); 1765 Register src = g.ToRegister(source);
1447 Register dst = g.ToRegister(destination); 1766 Register dst = g.ToRegister(destination);
1448 __ xchg(dst, src); 1767 __ xchg(dst, src);
1449 } else if (source->IsRegister() && destination->IsStackSlot()) { 1768 } else if (source->IsRegister() && destination->IsStackSlot()) {
1450 // Register-memory. 1769 // Register-memory.
1451 __ xchg(g.ToRegister(source), g.ToOperand(destination)); 1770 __ xchg(g.ToRegister(source), g.ToOperand(destination));
1452 } else if (source->IsStackSlot() && destination->IsStackSlot()) { 1771 } else if (source->IsStackSlot() && destination->IsStackSlot()) {
1453 // Memory-memory. 1772 // Memory-memory.
1454 Operand src = g.ToOperand(source); 1773 Operand src = g.ToOperand(source);
1455 Operand dst = g.ToOperand(destination); 1774 Operand dst = g.ToOperand(destination);
1456 __ push(dst); 1775 __ push(dst);
1457 __ push(src); 1776 __ push(src);
1458 __ pop(dst); 1777 __ pop(dst);
1459 __ pop(src); 1778 __ pop(src);
1460 } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) { 1779 } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
1461 // XMM register-register swap. 1780 UNREACHABLE();
1462 XMMRegister src = g.ToDoubleRegister(source);
1463 XMMRegister dst = g.ToDoubleRegister(destination);
1464 __ movaps(kScratchDoubleReg, src);
1465 __ movaps(src, dst);
1466 __ movaps(dst, kScratchDoubleReg);
1467 } else if (source->IsDoubleRegister() && destination->IsDoubleStackSlot()) { 1781 } else if (source->IsDoubleRegister() && destination->IsDoubleStackSlot()) {
1468 // XMM register-memory swap. 1782 auto allocated = AllocatedOperand::cast(*source);
1469 XMMRegister reg = g.ToDoubleRegister(source); 1783 switch (allocated.machine_type()) {
1470 Operand other = g.ToOperand(destination); 1784 case kRepFloat32:
1471 __ movsd(kScratchDoubleReg, other); 1785 __ fld_s(g.ToOperand(destination));
1472 __ movsd(other, reg); 1786 __ fxch();
1473 __ movaps(reg, kScratchDoubleReg); 1787 __ fstp_s(g.ToOperand(destination));
1788 break;
1789 case kRepFloat64:
1790 __ fld_d(g.ToOperand(destination));
1791 __ fxch();
1792 __ fstp_d(g.ToOperand(destination));
1793 break;
1794 default:
1795 UNREACHABLE();
1796 }
1474 } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) { 1797 } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
1475 // Double-width memory-to-memory. 1798 auto allocated = AllocatedOperand::cast(*source);
1476 Operand src0 = g.ToOperand(source); 1799 switch (allocated.machine_type()) {
1477 Operand src1 = g.HighOperand(source); 1800 case kRepFloat32:
1478 Operand dst0 = g.ToOperand(destination); 1801 __ fld_s(g.ToOperand(source));
1479 Operand dst1 = g.HighOperand(destination); 1802 __ fld_s(g.ToOperand(destination));
1480 __ movsd(kScratchDoubleReg, dst0); // Save destination in scratch register. 1803 __ fstp_s(g.ToOperand(source));
1481 __ push(src0); // Then use stack to copy source to destination. 1804 __ fstp_s(g.ToOperand(destination));
1482 __ pop(dst0); 1805 break;
1483 __ push(src1); 1806 case kRepFloat64:
1484 __ pop(dst1); 1807 __ fld_d(g.ToOperand(source));
1485 __ movsd(src0, kScratchDoubleReg); 1808 __ fld_d(g.ToOperand(destination));
1809 __ fstp_d(g.ToOperand(source));
1810 __ fstp_d(g.ToOperand(destination));
1811 break;
1812 default:
1813 UNREACHABLE();
1814 }
1486 } else { 1815 } else {
1487 // No other combinations are possible. 1816 // No other combinations are possible.
1488 UNREACHABLE(); 1817 UNREACHABLE();
1489 } 1818 }
1490 } 1819 }
1491 1820
1492 1821
1493 void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) { 1822 void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) {
1494 for (size_t index = 0; index < target_count; ++index) { 1823 for (size_t index = 0; index < target_count; ++index) {
1495 __ dd(targets[index]); 1824 __ dd(targets[index]);
(...skipping 16 matching lines...) Expand all
1512 } 1841 }
1513 } 1842 }
1514 MarkLazyDeoptSite(); 1843 MarkLazyDeoptSite();
1515 } 1844 }
1516 1845
1517 #undef __ 1846 #undef __
1518 1847
1519 } // namespace compiler 1848 } // namespace compiler
1520 } // namespace internal 1849 } // namespace internal
1521 } // namespace v8 1850 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/x87/OWNERS ('k') | src/compiler/x87/instruction-codes-x87.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698