--- /dev/null 2016-05-31 09:42:47.975716356 -0700 +++ new/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java 2016-12-07 13:47:34.261381944 -0800 @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.asm.amd64; + +import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseIncDec; +import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmLoadAndClearUpper; +import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmRegToRegMoveAll; + +import org.graalvm.compiler.asm.NumUtil; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.amd64.AMD64Kind; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.TargetDescription; + +/** + * This class implements commonly used X86 code patterns. + */ +public class AMD64MacroAssembler extends AMD64Assembler { + + public AMD64MacroAssembler(TargetDescription target) { + super(target); + } + + public final void decrementq(Register reg, int value) { + if (value == Integer.MIN_VALUE) { + subq(reg, value); + return; + } + if (value < 0) { + incrementq(reg, -value); + return; + } + if (value == 0) { + return; + } + if (value == 1 && UseIncDec) { + decq(reg); + } else { + subq(reg, value); + } + } + + public final void decrementq(AMD64Address dst, int value) { + if (value == Integer.MIN_VALUE) { + subq(dst, value); + return; + } + if (value < 0) { + incrementq(dst, -value); + return; + } + if (value == 0) { + return; + } + if (value == 1 && UseIncDec) { + decq(dst); + } else { + subq(dst, value); + } + } + + public void incrementq(Register reg, int value) { + if (value == Integer.MIN_VALUE) { + addq(reg, value); + return; + } + if (value < 0) { + decrementq(reg, -value); + return; + } + if (value == 0) { + return; + } + if (value == 1 && UseIncDec) { + incq(reg); + } else { + addq(reg, value); + } + } + + public final void incrementq(AMD64Address dst, int value) { + if (value == Integer.MIN_VALUE) { + addq(dst, value); + return; + } + if (value < 0) { + decrementq(dst, -value); + return; + } + if (value == 0) { + return; + } + if (value == 1 && UseIncDec) { + incq(dst); + } else { + addq(dst, value); + } + } + + public final void movptr(Register dst, AMD64Address src) { + movq(dst, src); + } + + public final void movptr(AMD64Address dst, Register src) { + movq(dst, src); + } + + public final void movptr(AMD64Address dst, int src) { + movslq(dst, src); + } + + public final void cmpptr(Register src1, Register src2) { + cmpq(src1, src2); + } + + public final void cmpptr(Register src1, AMD64Address src2) { + cmpq(src1, src2); + } + + public final void decrementl(Register reg, int value) { + if (value == Integer.MIN_VALUE) { + subl(reg, value); + return; + } + if (value < 0) { + incrementl(reg, -value); + return; + } + if (value == 0) { + return; + } + if (value == 1 && UseIncDec) { + decl(reg); + } else { + subl(reg, value); + } + } + + public final void decrementl(AMD64Address dst, int value) { + if (value == Integer.MIN_VALUE) { + subl(dst, value); + return; + } + if (value < 0) { + incrementl(dst, -value); + return; + } + if (value == 0) { + return; + } + if (value == 1 && UseIncDec) { + decl(dst); + } else { + subl(dst, value); + } + } + + public final void incrementl(Register reg, int value) { + if (value == Integer.MIN_VALUE) { + addl(reg, value); + return; + } + if (value < 0) { + decrementl(reg, -value); + return; + } + if (value == 0) { + return; + } + if (value == 1 && UseIncDec) { + incl(reg); + } else { + addl(reg, value); + } + } + + public final void incrementl(AMD64Address dst, int value) { + if (value == Integer.MIN_VALUE) { + addl(dst, value); + return; + } + if (value < 0) { + decrementl(dst, -value); + return; + } + if (value == 0) { + return; + } + if (value == 1 && UseIncDec) { + incl(dst); + } else { + addl(dst, value); + } + } + + public void movflt(Register dst, Register src) { + assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM); + if (UseXmmRegToRegMoveAll) { + movaps(dst, src); + } else { + movss(dst, src); + } + } + + public void movflt(Register dst, AMD64Address src) { + assert dst.getRegisterCategory().equals(AMD64.XMM); + movss(dst, src); + } + + public void movflt(AMD64Address dst, Register src) { + assert src.getRegisterCategory().equals(AMD64.XMM); + movss(dst, src); + } + + public void movdbl(Register dst, Register src) { + assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM); + if (UseXmmRegToRegMoveAll) { + movapd(dst, src); + } else { + movsd(dst, src); + } + } + + public void movdbl(Register dst, AMD64Address src) { + assert dst.getRegisterCategory().equals(AMD64.XMM); + if (UseXmmLoadAndClearUpper) { + movsd(dst, src); + } else { + movlpd(dst, src); + } + } + + public void movdbl(AMD64Address dst, Register src) { + assert src.getRegisterCategory().equals(AMD64.XMM); + movsd(dst, src); + } + + /** + * Non-atomic write of a 64-bit constant to memory. Do not use if the address might be a + * volatile field! + */ + public final void movlong(AMD64Address dst, long src) { + if (NumUtil.isInt(src)) { + AMD64MIOp.MOV.emit(this, OperandSize.QWORD, dst, (int) src); + } else { + AMD64Address high = new AMD64Address(dst.getBase(), dst.getIndex(), dst.getScale(), dst.getDisplacement() + 4); + movl(dst, (int) (src & 0xFFFFFFFF)); + movl(high, (int) (src >> 32)); + } + + } + + public final void flog(Register dest, Register value, boolean base10) { + if (base10) { + fldlg2(); + } else { + fldln2(); + } + AMD64Address tmp = trigPrologue(value); + fyl2x(); + trigEpilogue(dest, tmp); + } + + public final void fsin(Register dest, Register value) { + AMD64Address tmp = trigPrologue(value); + fsin(); + trigEpilogue(dest, tmp); + } + + public final void fcos(Register dest, Register value) { + AMD64Address tmp = trigPrologue(value); + fcos(); + trigEpilogue(dest, tmp); + } + + public final void ftan(Register dest, Register value) { + AMD64Address tmp = trigPrologue(value); + fptan(); + fstp(0); // ftan pushes 1.0 in addition to the actual result, pop + trigEpilogue(dest, tmp); + } + + public final void fpop() { + ffree(0); + fincstp(); + } + + private AMD64Address trigPrologue(Register value) { + assert value.getRegisterCategory().equals(AMD64.XMM); + AMD64Address tmp = new AMD64Address(AMD64.rsp); + subq(AMD64.rsp, AMD64Kind.DOUBLE.getSizeInBytes()); + movdbl(tmp, value); + fldd(tmp); + return tmp; + } + + private void trigEpilogue(Register dest, AMD64Address tmp) { + assert dest.getRegisterCategory().equals(AMD64.XMM); + fstpd(tmp); + movdbl(dest, tmp); + addq(AMD64.rsp, AMD64Kind.DOUBLE.getSizeInBytes()); + } +}