1 /* 2 * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.lir.amd64; 24 25 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; 26 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; 27 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; 28 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; 29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.UNINITIALIZED; 30 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; 31 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; 32 import static java.lang.Double.doubleToRawLongBits; 33 import static java.lang.Float.floatToRawIntBits; 34 import static jdk.vm.ci.code.ValueUtil.asRegister; 35 import static jdk.vm.ci.code.ValueUtil.isRegister; 36 import static jdk.vm.ci.code.ValueUtil.isStackSlot; 37 38 import org.graalvm.compiler.asm.NumUtil; 39 import org.graalvm.compiler.asm.amd64.AMD64Address; 40 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; 41 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp; 42 import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize; 43 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; 44 import org.graalvm.compiler.core.common.type.DataPointerConstant; 45 import org.graalvm.compiler.debug.GraalError; 46 import org.graalvm.compiler.lir.LIRFrameState; 47 import org.graalvm.compiler.lir.LIRInstructionClass; 48 import org.graalvm.compiler.lir.Opcode; 49 import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; 50 import org.graalvm.compiler.lir.StandardOp.NullCheck; 51 import org.graalvm.compiler.lir.StandardOp.ValueMoveOp; 52 import org.graalvm.compiler.lir.VirtualStackSlot; 53 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 54 55 import jdk.vm.ci.amd64.AMD64; 56 import jdk.vm.ci.amd64.AMD64Kind; 57 import jdk.vm.ci.code.Register; 58 import jdk.vm.ci.code.StackSlot; 59 import jdk.vm.ci.meta.AllocatableValue; 60 import jdk.vm.ci.meta.Constant; 61 import jdk.vm.ci.meta.JavaConstant; 62 import jdk.vm.ci.meta.Value; 63 64 public class AMD64Move { 65 66 private abstract static class AbstractMoveOp extends AMD64LIRInstruction implements ValueMoveOp { 67 public static final LIRInstructionClass<AbstractMoveOp> TYPE = LIRInstructionClass.create(AbstractMoveOp.class); 68 69 private AMD64Kind moveKind; 70 71 protected AbstractMoveOp(LIRInstructionClass<? extends AbstractMoveOp> c, AMD64Kind moveKind) { 72 super(c); 73 this.moveKind = moveKind; 74 } 75 76 @Override 77 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 78 move(moveKind, crb, masm, getResult(), getInput()); 79 } 80 } 81 82 @Opcode("MOVE") 83 public static final class MoveToRegOp extends AbstractMoveOp { 84 public static final LIRInstructionClass<MoveToRegOp> TYPE = LIRInstructionClass.create(MoveToRegOp.class); 85 86 @Def({REG, HINT}) protected AllocatableValue result; 87 @Use({REG, STACK}) protected AllocatableValue input; 88 89 public MoveToRegOp(AMD64Kind moveKind, AllocatableValue result, AllocatableValue input) { 90 super(TYPE, moveKind); 91 this.result = result; 92 this.input = input; 93 } 94 95 @Override 96 public AllocatableValue getInput() { 97 return input; 98 } 99 100 @Override 101 public AllocatableValue getResult() { 102 return result; 103 } 104 } 105 106 @Opcode("MOVE") 107 public static final class MoveFromRegOp extends AbstractMoveOp { 108 public static final LIRInstructionClass<MoveFromRegOp> TYPE = LIRInstructionClass.create(MoveFromRegOp.class); 109 110 @Def({REG, STACK}) protected AllocatableValue result; 111 @Use({REG, HINT}) protected AllocatableValue input; 112 113 public MoveFromRegOp(AMD64Kind moveKind, AllocatableValue result, AllocatableValue input) { 114 super(TYPE, moveKind); 115 this.result = result; 116 this.input = input; 117 } 118 119 @Override 120 public AllocatableValue getInput() { 121 return input; 122 } 123 124 @Override 125 public AllocatableValue getResult() { 126 return result; 127 } 128 } 129 130 @Opcode("MOVE") 131 public static class MoveFromConstOp extends AMD64LIRInstruction implements LoadConstantOp { 132 public static final LIRInstructionClass<MoveFromConstOp> TYPE = LIRInstructionClass.create(MoveFromConstOp.class); 133 134 @Def({REG, STACK}) protected AllocatableValue result; 135 private final JavaConstant input; 136 137 public MoveFromConstOp(AllocatableValue result, JavaConstant input) { 138 super(TYPE); 139 this.result = result; 140 this.input = input; 141 } 142 143 @Override 144 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 145 if (isRegister(result)) { 146 const2reg(crb, masm, asRegister(result), input); 147 } else { 148 assert isStackSlot(result); 149 const2stack(crb, masm, result, input); 150 } 151 } 152 153 @Override 154 public Constant getConstant() { 155 return input; 156 } 157 158 @Override 159 public AllocatableValue getResult() { 160 return result; 161 } 162 } 163 164 @Opcode("STACKMOVE") 165 public static final class AMD64StackMove extends AMD64LIRInstruction implements ValueMoveOp { 166 public static final LIRInstructionClass<AMD64StackMove> TYPE = LIRInstructionClass.create(AMD64StackMove.class); 167 168 @Def({STACK}) protected AllocatableValue result; 169 @Use({STACK, HINT}) protected AllocatableValue input; 170 @Alive({OperandFlag.STACK, OperandFlag.UNINITIALIZED}) private AllocatableValue backupSlot; 171 172 private Register scratch; 173 174 public AMD64StackMove(AllocatableValue result, AllocatableValue input, Register scratch, AllocatableValue backupSlot) { 175 super(TYPE); 176 this.result = result; 177 this.input = input; 178 this.backupSlot = backupSlot; 179 this.scratch = scratch; 180 } 181 182 @Override 183 public AllocatableValue getInput() { 184 return input; 185 } 186 187 @Override 188 public AllocatableValue getResult() { 189 return result; 190 } 191 192 public Register getScratchRegister() { 193 return scratch; 194 } 195 196 public AllocatableValue getBackupSlot() { 197 return backupSlot; 198 } 199 200 @Override 201 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 202 AMD64Kind backupKind = (AMD64Kind) backupSlot.getPlatformKind(); 203 if (backupKind.isXMM()) { 204 // graal doesn't use vector values, so it's safe to backup using DOUBLE 205 backupKind = AMD64Kind.DOUBLE; 206 } 207 208 // backup scratch register 209 reg2stack(backupKind, crb, masm, backupSlot, scratch); 210 // move stack slot 211 stack2reg((AMD64Kind) getInput().getPlatformKind(), crb, masm, scratch, getInput()); 212 reg2stack((AMD64Kind) getResult().getPlatformKind(), crb, masm, getResult(), scratch); 213 // restore scratch register 214 stack2reg(backupKind, crb, masm, scratch, backupSlot); 215 } 216 } 217 218 @Opcode("MULTISTACKMOVE") 219 public static final class AMD64MultiStackMove extends AMD64LIRInstruction { 220 public static final LIRInstructionClass<AMD64MultiStackMove> TYPE = LIRInstructionClass.create(AMD64MultiStackMove.class); 221 222 @Def({STACK}) protected AllocatableValue[] results; 223 @Use({STACK}) protected Value[] inputs; 224 @Alive({OperandFlag.STACK, OperandFlag.UNINITIALIZED}) private AllocatableValue backupSlot; 225 226 private Register scratch; 227 228 public AMD64MultiStackMove(AllocatableValue[] results, Value[] inputs, Register scratch, AllocatableValue backupSlot) { 229 super(TYPE); 230 this.results = results; 231 this.inputs = inputs; 232 this.backupSlot = backupSlot; 233 this.scratch = scratch; 234 } 235 236 @Override 237 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 238 AMD64Kind backupKind = (AMD64Kind) backupSlot.getPlatformKind(); 239 if (backupKind.isXMM()) { 240 // graal doesn't use vector values, so it's safe to backup using DOUBLE 241 backupKind = AMD64Kind.DOUBLE; 242 } 243 244 // backup scratch register 245 move(backupKind, crb, masm, backupSlot, scratch.asValue(backupSlot.getValueKind())); 246 for (int i = 0; i < results.length; i++) { 247 Value input = inputs[i]; 248 AllocatableValue result = results[i]; 249 // move stack slot 250 move((AMD64Kind) input.getPlatformKind(), crb, masm, scratch.asValue(input.getValueKind()), input); 251 move((AMD64Kind) result.getPlatformKind(), crb, masm, result, scratch.asValue(result.getValueKind())); 252 } 253 // restore scratch register 254 move(backupKind, crb, masm, scratch.asValue(backupSlot.getValueKind()), backupSlot); 255 } 256 } 257 258 @Opcode("STACKMOVE") 259 public static final class AMD64PushPopStackMove extends AMD64LIRInstruction implements ValueMoveOp { 260 public static final LIRInstructionClass<AMD64PushPopStackMove> TYPE = LIRInstructionClass.create(AMD64PushPopStackMove.class); 261 262 @Def({STACK}) protected AllocatableValue result; 263 @Use({STACK, HINT}) protected AllocatableValue input; 264 private final OperandSize size; 265 266 public AMD64PushPopStackMove(OperandSize size, AllocatableValue result, AllocatableValue input) { 267 super(TYPE); 268 this.result = result; 269 this.input = input; 270 this.size = size; 271 } 272 273 @Override 274 public AllocatableValue getInput() { 275 return input; 276 } 277 278 @Override 279 public AllocatableValue getResult() { 280 return result; 281 } 282 283 @Override 284 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 285 AMD64MOp.PUSH.emit(masm, size, (AMD64Address) crb.asAddress(input)); 286 AMD64MOp.POP.emit(masm, size, (AMD64Address) crb.asAddress(result)); 287 } 288 } 289 290 public static final class LeaOp extends AMD64LIRInstruction { 291 public static final LIRInstructionClass<LeaOp> TYPE = LIRInstructionClass.create(LeaOp.class); 292 293 @Def({REG}) protected AllocatableValue result; 294 @Use({COMPOSITE, UNINITIALIZED}) protected AMD64AddressValue address; 295 296 public LeaOp(AllocatableValue result, AMD64AddressValue address) { 297 super(TYPE); 298 this.result = result; 299 this.address = address; 300 } 301 302 @Override 303 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 304 masm.leaq(asRegister(result, AMD64Kind.QWORD), address.toAddress()); 305 } 306 } 307 308 public static final class LeaDataOp extends AMD64LIRInstruction { 309 public static final LIRInstructionClass<LeaDataOp> TYPE = LIRInstructionClass.create(LeaDataOp.class); 310 311 @Def({REG}) protected AllocatableValue result; 312 private final DataPointerConstant data; 313 314 public LeaDataOp(AllocatableValue result, DataPointerConstant data) { 315 super(TYPE); 316 this.result = result; 317 this.data = data; 318 } 319 320 @Override 321 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 322 masm.leaq(asRegister(result), (AMD64Address) crb.recordDataReferenceInCode(data)); 323 } 324 } 325 326 public static final class StackLeaOp extends AMD64LIRInstruction { 327 public static final LIRInstructionClass<StackLeaOp> TYPE = LIRInstructionClass.create(StackLeaOp.class); 328 329 @Def({REG}) protected AllocatableValue result; 330 @Use({STACK, UNINITIALIZED}) protected AllocatableValue slot; 331 332 public StackLeaOp(AllocatableValue result, AllocatableValue slot) { 333 super(TYPE); 334 this.result = result; 335 this.slot = slot; 336 assert slot instanceof VirtualStackSlot || slot instanceof StackSlot; 337 } 338 339 @Override 340 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 341 masm.leaq(asRegister(result, AMD64Kind.QWORD), (AMD64Address) crb.asAddress(slot)); 342 } 343 } 344 345 public static final class MembarOp extends AMD64LIRInstruction { 346 public static final LIRInstructionClass<MembarOp> TYPE = LIRInstructionClass.create(MembarOp.class); 347 348 private final int barriers; 349 350 public MembarOp(final int barriers) { 351 super(TYPE); 352 this.barriers = barriers; 353 } 354 355 @Override 356 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 357 masm.membar(barriers); 358 } 359 } 360 361 public static final class NullCheckOp extends AMD64LIRInstruction implements NullCheck { 362 public static final LIRInstructionClass<NullCheckOp> TYPE = LIRInstructionClass.create(NullCheckOp.class); 363 364 @Use({COMPOSITE}) protected AMD64AddressValue address; 365 @State protected LIRFrameState state; 366 367 public NullCheckOp(AMD64AddressValue address, LIRFrameState state) { 368 super(TYPE); 369 this.address = address; 370 this.state = state; 371 } 372 373 @Override 374 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 375 crb.recordImplicitException(masm.position(), state); 376 masm.nullCheck(address.toAddress()); 377 } 378 379 @Override 380 public Value getCheckedValue() { 381 return address.base; 382 } 383 384 @Override 385 public LIRFrameState getState() { 386 return state; 387 } 388 } 389 390 @Opcode("CAS") 391 public static final class CompareAndSwapOp extends AMD64LIRInstruction { 392 public static final LIRInstructionClass<CompareAndSwapOp> TYPE = LIRInstructionClass.create(CompareAndSwapOp.class); 393 394 private final AMD64Kind accessKind; 395 396 @Def protected AllocatableValue result; 397 @Use({COMPOSITE}) protected AMD64AddressValue address; 398 @Use protected AllocatableValue cmpValue; 399 @Use protected AllocatableValue newValue; 400 401 public CompareAndSwapOp(AMD64Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { 402 super(TYPE); 403 this.accessKind = accessKind; 404 this.result = result; 405 this.address = address; 406 this.cmpValue = cmpValue; 407 this.newValue = newValue; 408 } 409 410 @Override 411 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 412 assert asRegister(cmpValue).equals(AMD64.rax) && asRegister(result).equals(AMD64.rax); 413 414 if (crb.target.isMP) { 415 masm.lock(); 416 } 417 switch (accessKind) { 418 case DWORD: 419 masm.cmpxchgl(asRegister(newValue), address.toAddress()); 420 break; 421 case QWORD: 422 masm.cmpxchgq(asRegister(newValue), address.toAddress()); 423 break; 424 default: 425 throw GraalError.shouldNotReachHere(); 426 } 427 } 428 } 429 430 @Opcode("ATOMIC_READ_AND_ADD") 431 public static final class AtomicReadAndAddOp extends AMD64LIRInstruction { 432 public static final LIRInstructionClass<AtomicReadAndAddOp> TYPE = LIRInstructionClass.create(AtomicReadAndAddOp.class); 433 434 private final AMD64Kind accessKind; 435 436 @Def protected AllocatableValue result; 437 @Alive({COMPOSITE}) protected AMD64AddressValue address; 438 @Use protected AllocatableValue delta; 439 440 public AtomicReadAndAddOp(AMD64Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue delta) { 441 super(TYPE); 442 this.accessKind = accessKind; 443 this.result = result; 444 this.address = address; 445 this.delta = delta; 446 } 447 448 @Override 449 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 450 move(accessKind, crb, masm, result, delta); 451 if (crb.target.isMP) { 452 masm.lock(); 453 } 454 switch (accessKind) { 455 case DWORD: 456 masm.xaddl(address.toAddress(), asRegister(result)); 457 break; 458 case QWORD: 459 masm.xaddq(address.toAddress(), asRegister(result)); 460 break; 461 default: 462 throw GraalError.shouldNotReachHere(); 463 } 464 } 465 } 466 467 @Opcode("ATOMIC_READ_AND_WRITE") 468 public static final class AtomicReadAndWriteOp extends AMD64LIRInstruction { 469 public static final LIRInstructionClass<AtomicReadAndWriteOp> TYPE = LIRInstructionClass.create(AtomicReadAndWriteOp.class); 470 471 private final AMD64Kind accessKind; 472 473 @Def protected AllocatableValue result; 474 @Alive({COMPOSITE}) protected AMD64AddressValue address; 475 @Use protected AllocatableValue newValue; 476 477 public AtomicReadAndWriteOp(AMD64Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue newValue) { 478 super(TYPE); 479 this.accessKind = accessKind; 480 this.result = result; 481 this.address = address; 482 this.newValue = newValue; 483 } 484 485 @Override 486 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 487 move(accessKind, crb, masm, result, newValue); 488 switch (accessKind) { 489 case DWORD: 490 masm.xchgl(asRegister(result), address.toAddress()); 491 break; 492 case QWORD: 493 masm.xchgq(asRegister(result), address.toAddress()); 494 break; 495 default: 496 throw GraalError.shouldNotReachHere(); 497 } 498 } 499 } 500 501 public static void move(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) { 502 move((AMD64Kind) result.getPlatformKind(), crb, masm, result, input); 503 } 504 505 public static void move(AMD64Kind moveKind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) { 506 if (isRegister(input)) { 507 if (isRegister(result)) { 508 reg2reg(moveKind, masm, result, input); 509 } else if (isStackSlot(result)) { 510 reg2stack(moveKind, crb, masm, result, asRegister(input)); 511 } else { 512 throw GraalError.shouldNotReachHere(); 513 } 514 } else if (isStackSlot(input)) { 515 if (isRegister(result)) { 516 stack2reg(moveKind, crb, masm, asRegister(result), input); 517 } else { 518 throw GraalError.shouldNotReachHere(); 519 } 520 } else if (isJavaConstant(input)) { 521 if (isRegister(result)) { 522 const2reg(crb, masm, asRegister(result), asJavaConstant(input)); 523 } else if (isStackSlot(result)) { 524 const2stack(crb, masm, result, asJavaConstant(input)); 525 } else { 526 throw GraalError.shouldNotReachHere(); 527 } 528 } else { 529 throw GraalError.shouldNotReachHere(); 530 } 531 } 532 533 private static void reg2reg(AMD64Kind kind, AMD64MacroAssembler masm, Value result, Value input) { 534 if (asRegister(input).equals(asRegister(result))) { 535 return; 536 } 537 switch (kind) { 538 case BYTE: 539 case WORD: 540 case DWORD: 541 masm.movl(asRegister(result), asRegister(input)); 542 break; 543 case QWORD: 544 masm.movq(asRegister(result), asRegister(input)); 545 break; 546 case SINGLE: 547 masm.movflt(asRegister(result, AMD64Kind.SINGLE), asRegister(input, AMD64Kind.SINGLE)); 548 break; 549 case DOUBLE: 550 masm.movdbl(asRegister(result, AMD64Kind.DOUBLE), asRegister(input, AMD64Kind.DOUBLE)); 551 break; 552 default: 553 throw GraalError.shouldNotReachHere("kind=" + kind); 554 } 555 } 556 557 public static void reg2stack(AMD64Kind kind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Register input) { 558 AMD64Address dest = (AMD64Address) crb.asAddress(result); 559 switch (kind) { 560 case BYTE: 561 masm.movb(dest, input); 562 break; 563 case WORD: 564 masm.movw(dest, input); 565 break; 566 case DWORD: 567 masm.movl(dest, input); 568 break; 569 case QWORD: 570 masm.movq(dest, input); 571 break; 572 case SINGLE: 573 masm.movflt(dest, input); 574 break; 575 case DOUBLE: 576 masm.movsd(dest, input); 577 break; 578 default: 579 throw GraalError.shouldNotReachHere(); 580 } 581 } 582 583 public static void stack2reg(AMD64Kind kind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Register result, Value input) { 584 AMD64Address src = (AMD64Address) crb.asAddress(input); 585 switch (kind) { 586 case BYTE: 587 masm.movsbl(result, src); 588 break; 589 case WORD: 590 masm.movswl(result, src); 591 break; 592 case DWORD: 593 masm.movl(result, src); 594 break; 595 case QWORD: 596 masm.movq(result, src); 597 break; 598 case SINGLE: 599 masm.movflt(result, src); 600 break; 601 case DOUBLE: 602 masm.movdbl(result, src); 603 break; 604 default: 605 throw GraalError.shouldNotReachHere(); 606 } 607 } 608 609 public static void const2reg(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register result, JavaConstant input) { 610 /* 611 * Note: we use the kind of the input operand (and not the kind of the result operand) 612 * because they don't match in all cases. For example, an object constant can be loaded to a 613 * long register when unsafe casts occurred (e.g., for a write barrier where arithmetic 614 * operations are then performed on the pointer). 615 */ 616 switch (input.getJavaKind().getStackKind()) { 617 case Int: 618 // Do not optimize with an XOR as this instruction may be between 619 // a CMP and a Jcc in which case the XOR will modify the condition 620 // flags and interfere with the Jcc. 621 masm.movl(result, input.asInt()); 622 623 break; 624 case Long: 625 // Do not optimize with an XOR as this instruction may be between 626 // a CMP and a Jcc in which case the XOR will modify the condition 627 // flags and interfere with the Jcc. 628 if (input.asLong() == (int) input.asLong()) { 629 // Sign extended to long 630 masm.movslq(result, (int) input.asLong()); 631 } else if ((input.asLong() & 0xFFFFFFFFL) == input.asLong()) { 632 // Zero extended to long 633 masm.movl(result, (int) input.asLong()); 634 } else { 635 masm.movq(result, input.asLong()); 636 } 637 break; 638 case Float: 639 // This is *not* the same as 'constant == 0.0f' in the case where constant is -0.0f 640 if (Float.floatToRawIntBits(input.asFloat()) == Float.floatToRawIntBits(0.0f)) { 641 masm.xorps(result, result); 642 } else { 643 masm.movflt(result, (AMD64Address) crb.asFloatConstRef(input)); 644 } 645 break; 646 case Double: 647 // This is *not* the same as 'constant == 0.0d' in the case where constant is -0.0d 648 if (Double.doubleToRawLongBits(input.asDouble()) == Double.doubleToRawLongBits(0.0d)) { 649 masm.xorpd(result, result); 650 } else { 651 masm.movdbl(result, (AMD64Address) crb.asDoubleConstRef(input)); 652 } 653 break; 654 case Object: 655 // Do not optimize with an XOR as this instruction may be between 656 // a CMP and a Jcc in which case the XOR will modify the condition 657 // flags and interfere with the Jcc. 658 if (input.isNull()) { 659 masm.movq(result, 0x0L); 660 } else if (crb.target.inlineObjects) { 661 crb.recordInlineDataInCode(input); 662 masm.movq(result, 0xDEADDEADDEADDEADL); 663 } else { 664 masm.movq(result, (AMD64Address) crb.recordDataReferenceInCode(input, 0)); 665 } 666 break; 667 default: 668 throw GraalError.shouldNotReachHere(); 669 } 670 } 671 672 public static void const2stack(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, JavaConstant input) { 673 AMD64Address dest = (AMD64Address) crb.asAddress(result); 674 final long imm; 675 switch (input.getJavaKind().getStackKind()) { 676 case Int: 677 imm = input.asInt(); 678 break; 679 case Long: 680 imm = input.asLong(); 681 break; 682 case Float: 683 imm = floatToRawIntBits(input.asFloat()); 684 break; 685 case Double: 686 imm = doubleToRawLongBits(input.asDouble()); 687 break; 688 case Object: 689 if (input.isNull()) { 690 imm = 0; 691 } else { 692 throw GraalError.shouldNotReachHere("Non-null object constants must be in register"); 693 } 694 break; 695 default: 696 throw GraalError.shouldNotReachHere(); 697 } 698 699 switch ((AMD64Kind) result.getPlatformKind()) { 700 case BYTE: 701 assert NumUtil.isByte(imm) : "Is not in byte range: " + imm; 702 AMD64MIOp.MOVB.emit(masm, OperandSize.BYTE, dest, (int) imm); 703 break; 704 case WORD: 705 assert NumUtil.isShort(imm) : "Is not in short range: " + imm; 706 AMD64MIOp.MOV.emit(masm, OperandSize.WORD, dest, (int) imm); 707 break; 708 case DWORD: 709 case SINGLE: 710 assert NumUtil.isInt(imm) : "Is not in int range: " + imm; 711 masm.movl(dest, (int) imm); 712 break; 713 case QWORD: 714 case DOUBLE: 715 masm.movlong(dest, imm); 716 break; 717 default: 718 throw GraalError.shouldNotReachHere("Unknown result Kind: " + result.getPlatformKind()); 719 } 720 } 721 }