| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |