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.CONST; 26 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; 27 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; 28 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; 29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; 30 import static jdk.vm.ci.code.ValueUtil.asRegister; 31 import static jdk.vm.ci.code.ValueUtil.isRegister; 32 33 import org.graalvm.compiler.asm.Label; 34 import org.graalvm.compiler.core.common.NumUtil; 35 import org.graalvm.compiler.asm.amd64.AMD64Address; 36 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; 37 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; 38 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; 39 import org.graalvm.compiler.code.CompilationResult.JumpTable; 40 import org.graalvm.compiler.core.common.calc.Condition; 41 import org.graalvm.compiler.debug.GraalError; 42 import org.graalvm.compiler.lir.LIRInstructionClass; 43 import org.graalvm.compiler.lir.LabelRef; 44 import org.graalvm.compiler.lir.Opcode; 45 import org.graalvm.compiler.lir.StandardOp; 46 import org.graalvm.compiler.lir.StandardOp.BlockEndOp; 47 import org.graalvm.compiler.lir.SwitchStrategy; 48 import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure; 49 import org.graalvm.compiler.lir.Variable; 50 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 51 52 import jdk.vm.ci.amd64.AMD64; 53 import jdk.vm.ci.amd64.AMD64.CPUFeature; 54 import jdk.vm.ci.amd64.AMD64Kind; 55 import jdk.vm.ci.code.Register; 56 import jdk.vm.ci.meta.AllocatableValue; 57 import jdk.vm.ci.meta.Constant; 58 import jdk.vm.ci.meta.JavaConstant; 59 import jdk.vm.ci.meta.Value; 295 for (LabelRef target : targets) { 296 Label label = target.label(); 297 int offsetToJumpTableBase = masm.position() - jumpTablePos; 298 if (label.isBound()) { 299 int imm32 = label.position() - jumpTablePos; 300 masm.emitInt(imm32); 301 } else { 302 label.addPatchAt(masm.position()); 303 304 masm.emitByte(0); // pseudo-opcode for jump table entry 305 masm.emitShort(offsetToJumpTableBase); 306 masm.emitByte(0); // padding to make jump table entry 4 bytes wide 307 } 308 } 309 310 JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4); 311 crb.compilationResult.addAnnotation(jt); 312 } 313 } 314 315 @Opcode("CMOVE") 316 public static final class CondMoveOp extends AMD64LIRInstruction { 317 public static final LIRInstructionClass<CondMoveOp> TYPE = LIRInstructionClass.create(CondMoveOp.class); 318 @Def({REG, HINT}) protected Value result; 319 @Alive({REG}) protected Value trueValue; 320 @Use({REG, STACK, CONST}) protected Value falseValue; 321 private final ConditionFlag condition; 322 323 public CondMoveOp(Variable result, Condition condition, AllocatableValue trueValue, Value falseValue) { 324 super(TYPE); 325 this.result = result; 326 this.condition = intCond(condition); 327 this.trueValue = trueValue; 328 this.falseValue = falseValue; 329 } 330 331 @Override 332 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 333 cmove(crb, masm, result, false, condition, false, trueValue, falseValue); 334 } 401 default: 402 throw GraalError.shouldNotReachHere(); 403 } 404 } else { 405 AMD64Address addr = (AMD64Address) crb.asAddress(other); 406 switch ((AMD64Kind) other.getPlatformKind()) { 407 case BYTE: 408 case WORD: 409 case DWORD: 410 masm.cmovl(cond, asRegister(result), addr); 411 break; 412 case QWORD: 413 masm.cmovq(cond, asRegister(result), addr); 414 break; 415 default: 416 throw GraalError.shouldNotReachHere(); 417 } 418 } 419 } 420 421 private static ConditionFlag intCond(Condition cond) { 422 switch (cond) { 423 case EQ: 424 return ConditionFlag.Equal; 425 case NE: 426 return ConditionFlag.NotEqual; 427 case LT: 428 return ConditionFlag.Less; 429 case LE: 430 return ConditionFlag.LessEqual; 431 case GE: 432 return ConditionFlag.GreaterEqual; 433 case GT: 434 return ConditionFlag.Greater; 435 case BE: 436 return ConditionFlag.BelowEqual; 437 case AE: 438 return ConditionFlag.AboveEqual; 439 case AT: 440 return ConditionFlag.Above; 445 } 446 } 447 448 private static ConditionFlag floatCond(Condition cond) { 449 switch (cond) { 450 case EQ: 451 return ConditionFlag.Equal; 452 case NE: 453 return ConditionFlag.NotEqual; 454 case LT: 455 return ConditionFlag.Below; 456 case LE: 457 return ConditionFlag.BelowEqual; 458 case GE: 459 return ConditionFlag.AboveEqual; 460 case GT: 461 return ConditionFlag.Above; 462 default: 463 throw GraalError.shouldNotReachHere(); 464 } 465 } 466 467 private static boolean trueOnUnordered(ConditionFlag condition) { 468 switch (condition) { 469 case AboveEqual: 470 case NotEqual: 471 case Above: 472 case Less: 473 case Overflow: 474 return false; 475 case Equal: 476 case BelowEqual: 477 case Below: 478 case GreaterEqual: 479 case NoOverflow: 480 return true; 481 default: 482 throw GraalError.shouldNotReachHere(); 483 } 484 } | 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 jdk.vm.ci.code.ValueUtil.asRegister; 26 import static jdk.vm.ci.code.ValueUtil.isRegister; 27 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST; 28 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; 29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; 30 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; 31 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; 32 33 import org.graalvm.compiler.asm.Label; 34 import org.graalvm.compiler.asm.amd64.AMD64Address; 35 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; 36 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; 37 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; 38 import org.graalvm.compiler.code.CompilationResult.JumpTable; 39 import org.graalvm.compiler.core.common.NumUtil; 40 import org.graalvm.compiler.core.common.calc.Condition; 41 import org.graalvm.compiler.debug.GraalError; 42 import org.graalvm.compiler.lir.LIRInstructionClass; 43 import org.graalvm.compiler.lir.LabelRef; 44 import org.graalvm.compiler.lir.Opcode; 45 import org.graalvm.compiler.lir.StandardOp; 46 import org.graalvm.compiler.lir.StandardOp.BlockEndOp; 47 import org.graalvm.compiler.lir.SwitchStrategy; 48 import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure; 49 import org.graalvm.compiler.lir.Variable; 50 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 51 52 import jdk.vm.ci.amd64.AMD64; 53 import jdk.vm.ci.amd64.AMD64.CPUFeature; 54 import jdk.vm.ci.amd64.AMD64Kind; 55 import jdk.vm.ci.code.Register; 56 import jdk.vm.ci.meta.AllocatableValue; 57 import jdk.vm.ci.meta.Constant; 58 import jdk.vm.ci.meta.JavaConstant; 59 import jdk.vm.ci.meta.Value; 295 for (LabelRef target : targets) { 296 Label label = target.label(); 297 int offsetToJumpTableBase = masm.position() - jumpTablePos; 298 if (label.isBound()) { 299 int imm32 = label.position() - jumpTablePos; 300 masm.emitInt(imm32); 301 } else { 302 label.addPatchAt(masm.position()); 303 304 masm.emitByte(0); // pseudo-opcode for jump table entry 305 masm.emitShort(offsetToJumpTableBase); 306 masm.emitByte(0); // padding to make jump table entry 4 bytes wide 307 } 308 } 309 310 JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4); 311 crb.compilationResult.addAnnotation(jt); 312 } 313 } 314 315 @Opcode("SETcc") 316 public static final class CondSetOp extends AMD64LIRInstruction { 317 public static final LIRInstructionClass<CondSetOp> TYPE = LIRInstructionClass.create(CondSetOp.class); 318 @Def({REG, HINT}) protected Value result; 319 private final ConditionFlag condition; 320 321 public CondSetOp(Variable result, Condition condition) { 322 super(TYPE); 323 this.result = result; 324 this.condition = intCond(condition); 325 } 326 327 @Override 328 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 329 setcc(masm, result, condition); 330 } 331 } 332 333 @Opcode("SETcc") 334 public static final class FloatCondSetOp extends AMD64LIRInstruction { 335 public static final LIRInstructionClass<FloatCondSetOp> TYPE = LIRInstructionClass.create(FloatCondSetOp.class); 336 @Def({REG, HINT}) protected Value result; 337 private final ConditionFlag condition; 338 339 public FloatCondSetOp(Variable result, Condition condition) { 340 super(TYPE); 341 this.result = result; 342 this.condition = floatCond(condition); 343 } 344 345 @Override 346 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 347 setcc(masm, result, condition); 348 } 349 } 350 351 @Opcode("CMOVE") 352 public static final class CondMoveOp extends AMD64LIRInstruction { 353 public static final LIRInstructionClass<CondMoveOp> TYPE = LIRInstructionClass.create(CondMoveOp.class); 354 @Def({REG, HINT}) protected Value result; 355 @Alive({REG}) protected Value trueValue; 356 @Use({REG, STACK, CONST}) protected Value falseValue; 357 private final ConditionFlag condition; 358 359 public CondMoveOp(Variable result, Condition condition, AllocatableValue trueValue, Value falseValue) { 360 super(TYPE); 361 this.result = result; 362 this.condition = intCond(condition); 363 this.trueValue = trueValue; 364 this.falseValue = falseValue; 365 } 366 367 @Override 368 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 369 cmove(crb, masm, result, false, condition, false, trueValue, falseValue); 370 } 437 default: 438 throw GraalError.shouldNotReachHere(); 439 } 440 } else { 441 AMD64Address addr = (AMD64Address) crb.asAddress(other); 442 switch ((AMD64Kind) other.getPlatformKind()) { 443 case BYTE: 444 case WORD: 445 case DWORD: 446 masm.cmovl(cond, asRegister(result), addr); 447 break; 448 case QWORD: 449 masm.cmovq(cond, asRegister(result), addr); 450 break; 451 default: 452 throw GraalError.shouldNotReachHere(); 453 } 454 } 455 } 456 457 private static void setcc(AMD64MacroAssembler masm, Value result, ConditionFlag cond) { 458 switch ((AMD64Kind) result.getPlatformKind()) { 459 case BYTE: 460 case WORD: 461 case DWORD: 462 masm.setl(cond, asRegister(result)); 463 break; 464 case QWORD: 465 masm.setq(cond, asRegister(result)); 466 break; 467 default: 468 throw GraalError.shouldNotReachHere(); 469 } 470 } 471 472 private static ConditionFlag intCond(Condition cond) { 473 switch (cond) { 474 case EQ: 475 return ConditionFlag.Equal; 476 case NE: 477 return ConditionFlag.NotEqual; 478 case LT: 479 return ConditionFlag.Less; 480 case LE: 481 return ConditionFlag.LessEqual; 482 case GE: 483 return ConditionFlag.GreaterEqual; 484 case GT: 485 return ConditionFlag.Greater; 486 case BE: 487 return ConditionFlag.BelowEqual; 488 case AE: 489 return ConditionFlag.AboveEqual; 490 case AT: 491 return ConditionFlag.Above; 496 } 497 } 498 499 private static ConditionFlag floatCond(Condition cond) { 500 switch (cond) { 501 case EQ: 502 return ConditionFlag.Equal; 503 case NE: 504 return ConditionFlag.NotEqual; 505 case LT: 506 return ConditionFlag.Below; 507 case LE: 508 return ConditionFlag.BelowEqual; 509 case GE: 510 return ConditionFlag.AboveEqual; 511 case GT: 512 return ConditionFlag.Above; 513 default: 514 throw GraalError.shouldNotReachHere(); 515 } 516 } 517 518 public static boolean trueOnUnordered(Condition condition) { 519 return trueOnUnordered(floatCond(condition)); 520 } 521 522 private static boolean trueOnUnordered(ConditionFlag condition) { 523 switch (condition) { 524 case AboveEqual: 525 case NotEqual: 526 case Above: 527 case Less: 528 case Overflow: 529 return false; 530 case Equal: 531 case BelowEqual: 532 case Below: 533 case GreaterEqual: 534 case NoOverflow: 535 return true; 536 default: 537 throw GraalError.shouldNotReachHere(); 538 } 539 } |