# HG changeset patch # User Christian.Wimmer@Oracle.com # Date 1305331760 25200 # Node ID 0ea5f12e873ac7f567574b1d2c13ab56f2442b52 # Parent e0e89714e2f18da9ed9fb85ca05be1b5a15b6c3c use com.oracle.max.asm project for assembler diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/.classpath --- a/graal/GraalCompiler/.classpath Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/.classpath Fri May 13 17:09:20 2011 -0700 @@ -1,9 +1,10 @@ - - - - - - - - - + + + + + + + + + + diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java --- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java Fri May 13 17:09:20 2011 -0700 @@ -25,6 +25,7 @@ import java.util.*; +import com.oracle.max.asm.*; import com.oracle.graal.graph.*; import com.sun.c1x.alloc.*; import com.sun.c1x.asm.*; @@ -41,8 +42,6 @@ /** * This class encapsulates global information about the compilation of a particular method, * including a reference to the runtime, statistics about the compiled code, etc. - * - * @author Ben L. Titzer */ public final class C1XCompilation { @@ -71,7 +70,7 @@ private int nextID = 1; private FrameMap frameMap; - private AbstractAssembler assembler; + private TargetMethodAssembler assembler; private IR hir; @@ -187,9 +186,10 @@ return frameMap; } - public AbstractAssembler masm() { + public TargetMethodAssembler assembler() { if (assembler == null) { - assembler = compiler.backend.newAssembler(registerConfig); + AbstractAssembler asm = compiler.backend.newAssembler(registerConfig); + assembler = new TargetMethodAssembler(asm); assembler.setFrameSize(frameMap.frameSize()); assembler.targetMethod.setCustomStackAreaOffset(frameMap.offsetToCustomArea()); } @@ -280,7 +280,7 @@ // generate traps at the end of the method lirAssembler.emitTraps(); - CiTargetMethod targetMethod = masm().finishTargetMethod(method, runtime, lirAssembler.registerRestoreEpilogueOffset, false); + CiTargetMethod targetMethod = assembler().finishTargetMethod(method, runtime, lirAssembler.registerRestoreEpilogueOffset, false); if (assumptions.count() > 0) { targetMethod.setAssumptions(assumptions); } diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/asm/AbstractAssembler.java --- a/graal/GraalCompiler/src/com/sun/c1x/asm/AbstractAssembler.java Fri May 13 14:03:03 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2009, 2011, 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 com.sun.c1x.asm; - -import java.util.*; - -import com.sun.c1x.*; -import com.sun.c1x.debug.*; -import com.sun.c1x.ir.*; -import com.sun.c1x.lir.*; -import com.sun.c1x.util.*; -import com.sun.cri.ci.*; -import com.sun.cri.ci.CiTargetMethod.CodeComment; -import com.sun.cri.ci.CiTargetMethod.Mark; -import com.sun.cri.ri.*; - -/** - * @author Marcelo Cintra - * @author Thomas Wuerthinger - */ -public abstract class AbstractAssembler { - - public final Buffer codeBuffer; - public final CiTarget target; - public final CiTargetMethod targetMethod; - public List exceptionInfoList; - protected int lastSafepointPos; - - public AbstractAssembler(CiTarget target) { - this.target = target; - this.targetMethod = new CiTargetMethod(); - this.codeBuffer = new Buffer(target.arch.byteOrder); - } - - public final void bind(Label l) { - assert !l.isBound() : "can bind label only once"; - l.bind(codeBuffer.position()); - l.patchInstructions(this); - } - - public void setFrameSize(int frameSize) { - targetMethod.setFrameSize(frameSize); - } - - public CiTargetMethod finishTargetMethod(Object name, RiRuntime runtime, int registerRestoreEpilogueOffset, boolean isStub) { - // Install code, data and frame size - targetMethod.setTargetCode(codeBuffer.close(false), codeBuffer.position()); - targetMethod.setRegisterRestoreEpilogueOffset(registerRestoreEpilogueOffset); - - // Record exception handlers if they exist - if (exceptionInfoList != null) { - for (ExceptionInfo ei : exceptionInfoList) { - int codeOffset = ei.codeOffset; - for (ExceptionHandler handler : ei.exceptionHandlers) { - int entryOffset = handler.entryCodeOffset(); - RiType caughtType = handler.handler.catchType(); - targetMethod.recordExceptionHandler(codeOffset, ei.bci, 0, entryOffset, handler.handlerBCI(), caughtType); - } - } - } - - if (C1XOptions.PrintMetrics) { - C1XMetrics.TargetMethods++; - C1XMetrics.CodeBytesEmitted += targetMethod.targetCodeSize(); - C1XMetrics.SafepointsEmitted += targetMethod.safepoints.size(); - C1XMetrics.DirectCallSitesEmitted += targetMethod.directCalls.size(); - C1XMetrics.IndirectCallSitesEmitted += targetMethod.indirectCalls.size(); - C1XMetrics.DataPatches += targetMethod.dataReferences.size(); - C1XMetrics.ExceptionHandlersEmitted += targetMethod.exceptionHandlers.size(); - } - - if (C1XOptions.PrintAssembly && !TTY.isSuppressed() && !isStub) { - Util.printSection("Target Method", Util.SECTION_CHARACTER); - TTY.println("Name: " + name); - TTY.println("Frame size: " + targetMethod.frameSize()); - TTY.println("Register size: " + target.arch.registerReferenceMapBitCount); - - if (C1XOptions.PrintCodeBytes) { - Util.printSection("Code", Util.SUB_SECTION_CHARACTER); - TTY.println("Code: %d bytes", targetMethod.targetCodeSize()); - Util.printBytes(0L, targetMethod.targetCode(), 0, targetMethod.targetCodeSize(), C1XOptions.PrintAssemblyBytesPerLine); - } - - Util.printSection("Disassembly", Util.SUB_SECTION_CHARACTER); - String disassembly = runtime.disassemble(targetMethod); - TTY.println(disassembly); - boolean noDis = disassembly == null || disassembly.length() == 0; - - Util.printSection("Safepoints", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.Safepoint x : targetMethod.safepoints) { - TTY.println(x.toString()); - if (noDis && x.debugInfo != null) { - TTY.println(CiUtil.indent(x.debugInfo.toString(), " ")); - } - } - - Util.printSection("Direct Call Sites", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.Call x : targetMethod.directCalls) { - TTY.println(x.toString()); - if (noDis && x.debugInfo != null) { - TTY.println(CiUtil.indent(x.debugInfo.toString(), " ")); - } - } - - Util.printSection("Indirect Call Sites", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.Call x : targetMethod.indirectCalls) { - TTY.println(x.toString()); - if (noDis && x.debugInfo != null) { - TTY.println(CiUtil.indent(x.debugInfo.toString(), " ")); - } - } - - Util.printSection("Data Patches", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.DataPatch x : targetMethod.dataReferences) { - TTY.println(x.toString()); - } - - Util.printSection("Marks", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.Mark x : targetMethod.marks) { - TTY.println(x.toString()); - } - - Util.printSection("Exception Handlers", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.ExceptionHandler x : targetMethod.exceptionHandlers) { - TTY.println(x.toString()); - } - } - - return targetMethod; - } - - public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) { - if (info != null) { - if (info.exceptionHandlers != null) { - if (exceptionInfoList == null) { - exceptionInfoList = new ArrayList(4); - } - exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionHandlers, info.state.bci)); - } - } - } - - public void recordImplicitException(int pcOffset, LIRDebugInfo info) { - // record an implicit exception point - if (info != null) { - assert lastSafepointPos < pcOffset; - lastSafepointPos = pcOffset; - targetMethod.recordSafepoint(pcOffset, info.debugInfo()); - recordExceptionHandlers(pcOffset, info); - } - } - - protected void recordDirectCall(int posBefore, int posAfter, Object target, LIRDebugInfo info) { - CiDebugInfo debugInfo = info != null ? info.debugInfo() : null; - assert lastSafepointPos < posAfter; - lastSafepointPos = posAfter; - targetMethod.recordCall(posBefore, target, debugInfo, true); - } - - protected void recordIndirectCall(int posBefore, int posAfter, Object target, LIRDebugInfo info) { - CiDebugInfo debugInfo = info != null ? info.debugInfo() : null; - assert lastSafepointPos < posAfter; - lastSafepointPos = posAfter; - targetMethod.recordCall(posBefore, target, debugInfo, false); - } - - public void recordSafepoint(int pos, LIRDebugInfo info) { - // safepoints always need debug info - CiDebugInfo debugInfo = info.debugInfo(); - assert lastSafepointPos < pos; - lastSafepointPos = pos; - targetMethod.recordSafepoint(pos, debugInfo); - } - - public CiAddress recordDataReferenceInCode(CiConstant data) { - assert data != null; - - int pos = codeBuffer.position(); - - if (C1XOptions.TraceRelocation) { - TTY.print("Data reference in code: pos = %d, data = %s", pos, data.toString()); - } - - targetMethod.recordDataReference(pos, data); - return CiAddress.Placeholder; - } - - public Mark recordMark(Object id, Mark[] references) { - return targetMethod.recordMark(codeBuffer.position(), id, references); - } - - public abstract void nop(); - - public abstract void nullCheck(CiRegister r); - - public abstract void align(int codeEntryAlignment); - - public abstract void patchJumpTarget(int branch, int target); - - public final void emitByte(int x) { - codeBuffer.emitByte(x); - } - - public final void emitShort(int x) { - codeBuffer.emitShort(x); - } - - public final void emitInt(int x) { - codeBuffer.emitInt(x); - } - - public final void emitLong(long x) { - codeBuffer.emitLong(x); - } - - public void blockComment(String s) { - targetMethod.addAnnotation(new CodeComment(codeBuffer.position(), s)); - } - - public int lastSafepointPos() { - return lastSafepointPos; - } -} diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/asm/Buffer.java --- a/graal/GraalCompiler/src/com/sun/c1x/asm/Buffer.java Fri May 13 14:03:03 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2009, 2011, 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 com.sun.c1x.asm; - -import java.util.*; - -import com.sun.c1x.*; -import com.sun.cri.bytecode.*; -import com.sun.cri.ci.CiArchitecture.ByteOrder; - -/** - * - * @author Thomas Wuerthinger - */ -public final class Buffer { - - private byte[] data; - private int position; - private int mark = -1; - - private final ByteOrder byteOrder; - - public Buffer(ByteOrder byteOrder) { - this.byteOrder = byteOrder; - this.data = new byte[C1XOptions.InitialCodeBufferSize]; - } - - public void reset() { - position = 0; - mark = -1; - } - - /** - * Closes this buffer. No extra data can be written to this buffer after this call. - * - * @param trimmedCopy if {@code true}, then a copy of the underlying byte array up to (but not including) - * {@code position()} is returned - * @return the data in this buffer or a trimmed copy if {@code trimmedCopy} is {@code true} - */ - public byte[] close(boolean trimmedCopy) { - byte[] result = trimmedCopy ? Arrays.copyOf(data, position()) : data; - data = null; - return result; - } - - public int emitBytes(byte[] arr, int off, int len) { - assert data != null : "must not use buffer after calling finished!"; - int oldPos = position; - ensureSize(position + len); - System.arraycopy(arr, off, data, position, len); - position += len; - return oldPos; - } - - public int emitByte(int b) { - int oldPos = position; - position = emitByte(b, oldPos); - return oldPos; - } - - public int emitShort(int b) { - int oldPos = position; - position = emitShort(b, oldPos); - return oldPos; - } - - public int emitInt(int b) { - int oldPos = position; - position = emitInt(b, oldPos); - return oldPos; - } - - public int emitLong(long b) { - int oldPos = position; - position = emitLong(b, oldPos); - return oldPos; - } - - private boolean isByte(int b) { - return b == (b & 0xFF); - } - - private boolean isShort(int s) { - return s == (s & 0xFFFF); - } - - /** - * Places a bookmark at the {@linkplain #position() current position}. - * - * @return the previously placed bookmark or {@code -1} if there was no bookmark - */ - public int mark() { - int mark = this.mark; - this.mark = position; - return mark; - } - - private void ensureSize(int length) { - if (length >= data.length) { - data = Arrays.copyOf(data, data.length * 4); - C1XMetrics.CodeBufferCopies++; - } - } - - public int emitByte(int b, int pos) { - assert data != null : "must not use buffer after calling finished!"; - assert isByte(b); - ensureSize(pos + 1); - data[pos++] = (byte) b; - return pos; - } - - public int emitShort(int b, int pos) { - assert data != null : "must not use buffer after calling finished!"; - assert isShort(b); - ensureSize(pos + 2); - if (byteOrder == ByteOrder.BigEndian) { - data[pos++] = (byte) ((b >> 8) & 0xFF); - data[pos++] = (byte) (b & 0xFF); - - } else { - assert byteOrder == ByteOrder.LittleEndian; - data[pos++] = (byte) (b & 0xFF); - data[pos++] = (byte) ((b >> 8) & 0xFF); - } - return pos; - } - - public int emitInt(int b, int pos) { - assert data != null : "must not use buffer after calling finished!"; - ensureSize(pos + 4); - if (byteOrder == ByteOrder.BigEndian) { - data[pos++] = (byte) ((b >> 24) & 0xFF); - data[pos++] = (byte) ((b >> 16) & 0xFF); - data[pos++] = (byte) ((b >> 8) & 0xFF); - data[pos++] = (byte) (b & 0xFF); - } else { - assert byteOrder == ByteOrder.LittleEndian; - data[pos++] = (byte) (b & 0xFF); - data[pos++] = (byte) ((b >> 8) & 0xFF); - data[pos++] = (byte) ((b >> 16) & 0xFF); - data[pos++] = (byte) ((b >> 24) & 0xFF); - } - return pos; - } - - public int emitLong(long b, int pos) { - assert data != null : "must not use buffer after calling finished!"; - ensureSize(pos + 8); - - if (byteOrder == ByteOrder.BigEndian) { - data[pos++] = (byte) ((b >> 56) & 0xFF); - data[pos++] = (byte) ((b >> 48) & 0xFF); - data[pos++] = (byte) ((b >> 40) & 0xFF); - data[pos++] = (byte) ((b >> 32) & 0xFF); - data[pos++] = (byte) ((b >> 24) & 0xFF); - data[pos++] = (byte) ((b >> 16) & 0xFF); - data[pos++] = (byte) ((b >> 8) & 0xFF); - data[pos++] = (byte) (b & 0xFF); - } else { - assert byteOrder == ByteOrder.LittleEndian; - data[pos++] = (byte) (b & 0xFF); - data[pos++] = (byte) ((b >> 8) & 0xFF); - data[pos++] = (byte) ((b >> 16) & 0xFF); - data[pos++] = (byte) ((b >> 24) & 0xFF); - data[pos++] = (byte) ((b >> 32) & 0xFF); - data[pos++] = (byte) ((b >> 40) & 0xFF); - data[pos++] = (byte) ((b >> 48) & 0xFF); - data[pos++] = (byte) ((b >> 56) & 0xFF); - } - return pos; - } - - public int position() { - return position; - } - - public void setPosition(int position) { - assert position >= 0 && position <= data.length; - this.position = position; - } - - public int getByte(int pos) { - return Bytes.beU1(data, pos); - } - - public int getShort(int pos) { - if (byteOrder == ByteOrder.BigEndian) { - return - (data[pos + 0] & 0xff) << 8 | - (data[pos + 1] & 0xff) << 0; - } else { - assert byteOrder == ByteOrder.LittleEndian; - return - (data[pos + 1] & 0xff) << 8 | - (data[pos + 0] & 0xff) << 0; - } - } - - public int getInt(int pos) { - if (byteOrder == ByteOrder.BigEndian) { - return - (data[pos + 0] & 0xff) << 24 | - (data[pos + 1] & 0xff) << 16 | - (data[pos + 2] & 0xff) << 8 | - (data[pos + 3] & 0xff) << 0; - } else { - assert byteOrder == ByteOrder.LittleEndian; - return - (data[pos + 3] & 0xff) << 24 | - (data[pos + 2] & 0xff) << 16 | - (data[pos + 1] & 0xff) << 8 | - (data[pos + 0] & 0xff) << 0; - } - } - - public byte[] copyData(int start, int end) { - return Arrays.copyOfRange(data, start, end); - } - - /** - * Copies the data from this buffer into a given array. - * - * @param dst the destination array - * @param off starting position in {@code dst} - * @param len number of bytes to copy - */ - public void copyInto(byte[] dst, int off, int len) { - System.arraycopy(data, 0, dst, off, len); - } -} diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/asm/Label.java --- a/graal/GraalCompiler/src/com/sun/c1x/asm/Label.java Fri May 13 14:03:03 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2009, 2011, 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 com.sun.c1x.asm; - -import com.sun.c1x.util.*; - -/** - * This class represents a label within assembly code. - * - * @author Marcelo Cintra - */ -public final class Label { - - private int position = -1; - - /** - * References to instructions that jump to this unresolved label. - * These instructions need to be patched when the label is bound - * using the {@link #patchInstructions(AbstractAssembler)} method. - */ - private IntList patchPositions = new IntList(4); - - /** - * Returns the position of this label in the code buffer. - * @return the position - */ - public int position() { - assert position >= 0 : "Unbound label is being referenced"; - return position; - } - - public Label() { - } - - public Label(int position) { - bind(position); - } - - /** - * Binds the label to the specified position. - * @param pos the position - */ - public void bind(int pos) { - this.position = pos; - assert isBound(); - } - - public boolean isBound() { - return position >= 0; - } - - public void addPatchAt(int branchLocation) { - assert !isBound() : "Label is already bound"; - patchPositions.add(branchLocation); - } - - public void patchInstructions(AbstractAssembler masm) { - assert isBound() : "Label should be bound"; - int target = position; - for (int i = 0; i < patchPositions.size(); ++i) { - int pos = patchPositions.get(i); - masm.patchJumpTarget(pos, target); - } - } - - @Override - public String toString() { - return "label"; - } -} diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/asm/TargetMethodAssembler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/asm/TargetMethodAssembler.java Fri May 13 17:09:20 2011 -0700 @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2011, 2011, 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 com.sun.c1x.asm; + +import java.util.*; + +import com.oracle.max.asm.*; +import com.sun.c1x.*; +import com.sun.c1x.debug.*; +import com.sun.c1x.ir.*; +import com.sun.c1x.lir.*; +import com.sun.c1x.util.*; +import com.sun.cri.ci.*; +import com.sun.cri.ri.*; + +public class TargetMethodAssembler { + public final AbstractAssembler asm; + public final CiTargetMethod targetMethod; + public List exceptionInfoList; + protected int lastSafepointPos; + + public TargetMethodAssembler(AbstractAssembler asm) { + this.asm = asm; + this.targetMethod = new CiTargetMethod(); + } + + public void setFrameSize(int frameSize) { + targetMethod.setFrameSize(frameSize); + } + + public CiTargetMethod.Mark recordMark(Object id, CiTargetMethod.Mark[] references) { + return targetMethod.recordMark(asm.codeBuffer.position(), id, references); + } + + public void blockComment(String s) { + targetMethod.addAnnotation(new CiTargetMethod.CodeComment(asm.codeBuffer.position(), s)); + } + + public CiTargetMethod finishTargetMethod(Object name, RiRuntime runtime, int registerRestoreEpilogueOffset, boolean isStub) { + // Install code, data and frame size + targetMethod.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position()); + targetMethod.setRegisterRestoreEpilogueOffset(registerRestoreEpilogueOffset); + + // Record exception handlers if they exist + if (exceptionInfoList != null) { + for (ExceptionInfo ei : exceptionInfoList) { + int codeOffset = ei.codeOffset; + for (ExceptionHandler handler : ei.exceptionHandlers) { + int entryOffset = handler.entryCodeOffset(); + RiType caughtType = handler.handler.catchType(); + targetMethod.recordExceptionHandler(codeOffset, ei.bci, 0, entryOffset, handler.handlerBCI(), caughtType); + } + } + } + + if (C1XOptions.PrintMetrics) { + C1XMetrics.TargetMethods++; + C1XMetrics.CodeBytesEmitted += targetMethod.targetCodeSize(); + C1XMetrics.SafepointsEmitted += targetMethod.safepoints.size(); + C1XMetrics.DirectCallSitesEmitted += targetMethod.directCalls.size(); + C1XMetrics.IndirectCallSitesEmitted += targetMethod.indirectCalls.size(); + C1XMetrics.DataPatches += targetMethod.dataReferences.size(); + C1XMetrics.ExceptionHandlersEmitted += targetMethod.exceptionHandlers.size(); + } + + if (C1XOptions.PrintAssembly && !TTY.isSuppressed() && !isStub) { + Util.printSection("Target Method", Util.SECTION_CHARACTER); + TTY.println("Name: " + name); + TTY.println("Frame size: " + targetMethod.frameSize()); + TTY.println("Register size: " + asm.target.arch.registerReferenceMapBitCount); + + if (C1XOptions.PrintCodeBytes) { + Util.printSection("Code", Util.SUB_SECTION_CHARACTER); + TTY.println("Code: %d bytes", targetMethod.targetCodeSize()); + Util.printBytes(0L, targetMethod.targetCode(), 0, targetMethod.targetCodeSize(), C1XOptions.PrintAssemblyBytesPerLine); + } + + Util.printSection("Disassembly", Util.SUB_SECTION_CHARACTER); + String disassembly = runtime.disassemble(targetMethod); + TTY.println(disassembly); + boolean noDis = disassembly == null || disassembly.length() == 0; + + Util.printSection("Safepoints", Util.SUB_SECTION_CHARACTER); + for (CiTargetMethod.Safepoint x : targetMethod.safepoints) { + TTY.println(x.toString()); + if (noDis && x.debugInfo != null) { + TTY.println(CiUtil.indent(x.debugInfo.toString(), " ")); + } + } + + Util.printSection("Direct Call Sites", Util.SUB_SECTION_CHARACTER); + for (CiTargetMethod.Call x : targetMethod.directCalls) { + TTY.println(x.toString()); + if (noDis && x.debugInfo != null) { + TTY.println(CiUtil.indent(x.debugInfo.toString(), " ")); + } + } + + Util.printSection("Indirect Call Sites", Util.SUB_SECTION_CHARACTER); + for (CiTargetMethod.Call x : targetMethod.indirectCalls) { + TTY.println(x.toString()); + if (noDis && x.debugInfo != null) { + TTY.println(CiUtil.indent(x.debugInfo.toString(), " ")); + } + } + + Util.printSection("Data Patches", Util.SUB_SECTION_CHARACTER); + for (CiTargetMethod.DataPatch x : targetMethod.dataReferences) { + TTY.println(x.toString()); + } + + Util.printSection("Marks", Util.SUB_SECTION_CHARACTER); + for (CiTargetMethod.Mark x : targetMethod.marks) { + TTY.println(x.toString()); + } + + Util.printSection("Exception Handlers", Util.SUB_SECTION_CHARACTER); + for (CiTargetMethod.ExceptionHandler x : targetMethod.exceptionHandlers) { + TTY.println(x.toString()); + } + } + + return targetMethod; + } + + public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) { + if (info != null) { + if (info.exceptionHandlers != null) { + if (exceptionInfoList == null) { + exceptionInfoList = new ArrayList(4); + } + exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionHandlers, info.state.bci)); + } + } + } + + public void recordImplicitException(int pcOffset, LIRDebugInfo info) { + // record an implicit exception point + if (info != null) { + assert lastSafepointPos < pcOffset; + lastSafepointPos = pcOffset; + targetMethod.recordSafepoint(pcOffset, info.debugInfo()); + recordExceptionHandlers(pcOffset, info); + } + } + + public void recordDirectCall(int posBefore, int posAfter, Object target, LIRDebugInfo info) { + CiDebugInfo debugInfo = info != null ? info.debugInfo() : null; + assert lastSafepointPos < posAfter; + lastSafepointPos = posAfter; + targetMethod.recordCall(posBefore, target, debugInfo, true); + } + + public void recordIndirectCall(int posBefore, int posAfter, Object target, LIRDebugInfo info) { + CiDebugInfo debugInfo = info != null ? info.debugInfo() : null; + assert lastSafepointPos < posAfter; + lastSafepointPos = posAfter; + targetMethod.recordCall(posBefore, target, debugInfo, false); + } + + public void recordSafepoint(int pos, LIRDebugInfo info) { + // safepoints always need debug info + CiDebugInfo debugInfo = info.debugInfo(); + assert lastSafepointPos < pos; + lastSafepointPos = pos; + targetMethod.recordSafepoint(pos, debugInfo); + } + + public CiAddress recordDataReferenceInCode(CiConstant data) { + assert data != null; + + int pos = asm.codeBuffer.position(); + + if (C1XOptions.TraceRelocation) { + TTY.print("Data reference in code: pos = %d, data = %s", pos, data.toString()); + } + + targetMethod.recordDataReference(pos, data); + return CiAddress.Placeholder; + } + + public int lastSafepointPos() { + return lastSafepointPos; + } +} diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java --- a/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java Fri May 13 17:09:20 2011 -0700 @@ -29,10 +29,10 @@ import java.util.*; +import com.oracle.max.asm.*; import com.sun.c1x.*; import com.sun.c1x.alloc.*; import com.sun.c1x.alloc.OperandPool.VariableFlag; -import com.sun.c1x.asm.*; import com.sun.c1x.debug.*; import com.sun.c1x.globalstub.*; import com.sun.c1x.graph.*; diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java Fri May 13 17:09:20 2011 -0700 @@ -25,8 +25,8 @@ import java.util.*; import com.oracle.graal.graph.*; +import com.oracle.max.asm.*; import com.sun.c1x.*; -import com.sun.c1x.asm.*; import com.sun.c1x.debug.*; import com.sun.c1x.lir.*; import com.sun.c1x.util.*; diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/lir/FrameMap.java --- a/graal/GraalCompiler/src/com/sun/c1x/lir/FrameMap.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/FrameMap.java Fri May 13 17:09:20 2011 -0700 @@ -33,6 +33,7 @@ import com.sun.cri.ci.*; import com.sun.cri.ci.CiCallingConvention.Type; import com.sun.cri.ri.*; +import com.sun.cri.util.*; /** * This class is used to build the stack frame layout for a compiled method. @@ -133,7 +134,7 @@ incomingArguments = new CiCallingConvention(new CiValue[0], 0); } else { CiKind receiver = !isStatic(method.accessFlags()) ? method.holder().kind() : null; - incomingArguments = getCallingConvention(Util.signatureToKinds(method.signature(), receiver), JavaCallee); + incomingArguments = getCallingConvention(CRIUtil.signatureToKinds(method.signature(), receiver), JavaCallee); } } @@ -215,8 +216,8 @@ public CiAddress toStackAddress(CiStackSlot slot) { int size = compilation.target.sizeInBytes(slot.kind); if (slot.inCallerFrame()) { - int offset = slot.index() * compilation.target.spillSlotSize; - return new CiAddress(slot.kind, CiRegister.CallerFrame.asValue(), offset); + int offset = slot.index() * compilation.target.spillSlotSize + frameSize() + 8; + return new CiAddress(slot.kind, CiRegister.Frame.asValue(), offset); } else { int offset = offsetForOutgoingOrSpillSlot(slot.index(), size); return new CiAddress(slot.kind, CiRegister.Frame.asValue(), offset); diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java --- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java Fri May 13 17:09:20 2011 -0700 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.max.asm.*; import com.sun.c1x.*; import com.sun.c1x.asm.*; import com.sun.c1x.debug.*; @@ -38,14 +39,11 @@ /** * The {@code LIRAssembler} class definition. - * - * @author Marcelo Cintra - * @author Thomas Wuerthinger - * @author Ben L. Titzer */ public abstract class LIRAssembler { public final C1XCompilation compilation; + public final TargetMethodAssembler tasm; public final AbstractAssembler asm; public final FrameMap frameMap; public int registerRestoreEpilogueOffset = -1; @@ -69,7 +67,8 @@ public LIRAssembler(C1XCompilation compilation) { this.compilation = compilation; - this.asm = compilation.masm(); + this.tasm = compilation.assembler(); + this.asm = tasm.asm; this.frameMap = compilation.frameMap(); this.branchTargetBlocks = new ArrayList(); this.xirSlowPath = new ArrayList(); @@ -98,10 +97,10 @@ public abstract void emitTraps(); public void emitExceptionEntries() { - if (asm.exceptionInfoList == null) { + if (tasm.exceptionInfoList == null) { return; } - for (ExceptionInfo ilist : asm.exceptionInfoList) { + for (ExceptionInfo ilist : tasm.exceptionInfoList) { List handlers = ilist.exceptionHandlers; for (ExceptionHandler handler : handlers) { @@ -113,7 +112,7 @@ if (handler.entryCode() != null && handler.entryCode().instructionsList().size() > 1) { handler.setEntryCodeOffset(codePos()); if (C1XOptions.CommentedAssembly) { - asm.blockComment("Exception adapter block"); + tasm.blockComment("Exception adapter block"); } emitLirList(handler.entryCode()); } else { @@ -157,7 +156,7 @@ assert block.lir() != null : "must have LIR"; if (C1XOptions.CommentedAssembly) { String st = String.format(" block B%d [%d, %d]", block.blockID, block.bci(), block.end().bci()); - asm.blockComment(st); + tasm.blockComment(st); } emitLirList(block.lir()); @@ -170,7 +169,7 @@ if (C1XOptions.CommentedAssembly) { // Only print out branches if (op.code == LIROpcode.Branch) { - asm.blockComment(op.toStringWithIdPrefix()); + tasm.blockComment(op.toStringWithIdPrefix()); } } if (C1XOptions.PrintLIRWithAssembly && !TTY.isSuppressed()) { @@ -220,15 +219,15 @@ emitCallAlignment(op.code); // fall through case ConstDirectCall: - if (op.marks != null) { - op.marks.put(XirMark.CALLSITE, asm.recordMark(null, new Mark[0])); + if (op.marks != null) { + op.marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0])); } emitDirectCall(op.target, op.info); break; case IndirectCall: emitCallAlignment(op.code); if (op.marks != null) { - op.marks.put(XirMark.CALLSITE, asm.recordMark(null, new Mark[0])); + op.marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0])); } emitIndirectCall(op.target, op.info, op.targetAddress()); break; @@ -274,12 +273,7 @@ emitLea(op.operand(), op.result()); break; case NullCheck: - assert op.operand().isRegister(); - if (C1XOptions.NullCheckUniquePc) { - asm.nop(); - } - asm.recordImplicitException(codePos(), op.info); - asm.nullCheck(op.operand().asRegister()); + emitNullCheck(op.operand(), op.info); break; case Lsb: emitSignificantBitOp(false, op.operand(), op.result()); @@ -287,7 +281,7 @@ case Msb: emitSignificantBitOp(true, op.operand(), op.result()); break; - default: + default: throw Util.shouldNotReachHere(); } } @@ -448,6 +442,8 @@ protected abstract void emitLea(CiValue src, CiValue dst); + protected abstract void emitNullCheck(CiValue src, LIRDebugInfo info); + protected abstract void emitNegate(LIRNegate negate); protected abstract void emitHere(CiValue dst, LIRDebugInfo info, boolean infoOnly); diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/lir/LIRBlock.java --- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRBlock.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRBlock.java Fri May 13 17:09:20 2011 -0700 @@ -22,8 +22,8 @@ */ package com.sun.c1x.lir; +import com.oracle.max.asm.*; import com.sun.c1x.alloc.*; -import com.sun.c1x.asm.*; import com.sun.cri.ci.*; /** diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/lir/LIRBranch.java --- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRBranch.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRBranch.java Fri May 13 17:09:20 2011 -0700 @@ -22,7 +22,7 @@ */ package com.sun.c1x.lir; -import com.sun.c1x.asm.*; +import com.oracle.max.asm.*; import com.sun.c1x.ir.*; import com.sun.cri.ci.*; diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/lir/LIRLabel.java --- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRLabel.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRLabel.java Fri May 13 17:09:20 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, 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 @@ -22,7 +22,7 @@ */ package com.sun.c1x.lir; -import com.sun.c1x.asm.*; +import com.oracle.max.asm.*; import com.sun.cri.ci.*; /** diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/lir/LIRList.java --- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRList.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRList.java Fri May 13 17:09:20 2011 -0700 @@ -24,9 +24,9 @@ import java.util.*; +import com.oracle.max.asm.*; import com.sun.c1x.*; import com.sun.c1x.alloc.*; -import com.sun.c1x.asm.*; import com.sun.c1x.debug.*; import com.sun.c1x.gen.*; import com.sun.c1x.globalstub.*; @@ -41,10 +41,6 @@ /** * This class represents a list of LIR instructions and contains factory methods for creating and appending LIR * instructions to this list. - * - * @author Marcelo Cintra - * @author Thomas Wuerthinger - * @author Ben L. Titzer */ public final class LIRList { diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/target/Backend.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/Backend.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/target/Backend.java Fri May 13 17:09:20 2011 -0700 @@ -24,8 +24,8 @@ import java.lang.reflect.*; +import com.oracle.max.asm.*; import com.sun.c1x.*; -import com.sun.c1x.asm.*; import com.sun.c1x.gen.*; import com.sun.c1x.globalstub.*; import com.sun.c1x.lir.*; @@ -46,13 +46,13 @@ } public static Backend create(CiArchitecture arch, C1XCompiler compiler) { - String className = arch.getClass().getName() + "Backend"; + String className = arch.getClass().getName().replace("com.oracle.max.asm", "com.sun.c1x") + "Backend"; try { Class c = Class.forName(className); Constructor cons = c.getDeclaredConstructor(C1XCompiler.class); return (Backend) cons.newInstance(compiler); } catch (Exception e) { - throw new Error("Could instantiate " + className, e); + throw new Error("Could not instantiate " + className, e); } } diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64.java Fri May 13 14:03:03 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2009, 2010, 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 com.sun.c1x.target.amd64; - -import static com.sun.cri.bytecode.Bytecodes.MemoryBarriers.*; -import static com.sun.cri.ci.CiKind.*; -import static com.sun.cri.ci.CiRegister.RegisterFlag.*; - -import com.sun.cri.ci.*; -import com.sun.cri.ci.CiRegister.RegisterFlag; - -/** - * Represents the AMD64 architecture. - * - * @author Thomas Wuerthinger - */ -public class AMD64 extends CiArchitecture { - - // General purpose CPU registers - public static final CiRegister rax = new CiRegister(0, 0, 8, "rax", CPU, RegisterFlag.Byte); - public static final CiRegister rcx = new CiRegister(1, 1, 8, "rcx", CPU, RegisterFlag.Byte); - public static final CiRegister rdx = new CiRegister(2, 2, 8, "rdx", CPU, RegisterFlag.Byte); - public static final CiRegister rbx = new CiRegister(3, 3, 8, "rbx", CPU, RegisterFlag.Byte); - public static final CiRegister rsp = new CiRegister(4, 4, 8, "rsp", CPU, RegisterFlag.Byte); - public static final CiRegister rbp = new CiRegister(5, 5, 8, "rbp", CPU, RegisterFlag.Byte); - public static final CiRegister rsi = new CiRegister(6, 6, 8, "rsi", CPU, RegisterFlag.Byte); - public static final CiRegister rdi = new CiRegister(7, 7, 8, "rdi", CPU, RegisterFlag.Byte); - - public static final CiRegister r8 = new CiRegister(8, 8, 8, "r8", CPU, RegisterFlag.Byte); - public static final CiRegister r9 = new CiRegister(9, 9, 8, "r9", CPU, RegisterFlag.Byte); - public static final CiRegister r10 = new CiRegister(10, 10, 8, "r10", CPU, RegisterFlag.Byte); - public static final CiRegister r11 = new CiRegister(11, 11, 8, "r11", CPU, RegisterFlag.Byte); - public static final CiRegister r12 = new CiRegister(12, 12, 8, "r12", CPU, RegisterFlag.Byte); - public static final CiRegister r13 = new CiRegister(13, 13, 8, "r13", CPU, RegisterFlag.Byte); - public static final CiRegister r14 = new CiRegister(14, 14, 8, "r14", CPU, RegisterFlag.Byte); - public static final CiRegister r15 = new CiRegister(15, 15, 8, "r15", CPU, RegisterFlag.Byte); - - public static final CiRegister[] cpuRegisters = { - rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, - r8, r9, r10, r11, r12, r13, r14, r15 - }; - - // XMM registers - public static final CiRegister xmm0 = new CiRegister(16, 0, 8, "xmm0", FPU); - public static final CiRegister xmm1 = new CiRegister(17, 1, 8, "xmm1", FPU); - public static final CiRegister xmm2 = new CiRegister(18, 2, 8, "xmm2", FPU); - public static final CiRegister xmm3 = new CiRegister(19, 3, 8, "xmm3", FPU); - public static final CiRegister xmm4 = new CiRegister(20, 4, 8, "xmm4", FPU); - public static final CiRegister xmm5 = new CiRegister(21, 5, 8, "xmm5", FPU); - public static final CiRegister xmm6 = new CiRegister(22, 6, 8, "xmm6", FPU); - public static final CiRegister xmm7 = new CiRegister(23, 7, 8, "xmm7", FPU); - - public static final CiRegister xmm8 = new CiRegister(24, 8, 8, "xmm8", FPU); - public static final CiRegister xmm9 = new CiRegister(25, 9, 8, "xmm9", FPU); - public static final CiRegister xmm10 = new CiRegister(26, 10, 8, "xmm10", FPU); - public static final CiRegister xmm11 = new CiRegister(27, 11, 8, "xmm11", FPU); - public static final CiRegister xmm12 = new CiRegister(28, 12, 8, "xmm12", FPU); - public static final CiRegister xmm13 = new CiRegister(29, 13, 8, "xmm13", FPU); - public static final CiRegister xmm14 = new CiRegister(30, 14, 8, "xmm14", FPU); - public static final CiRegister xmm15 = new CiRegister(31, 15, 8, "xmm15", FPU); - - public static final CiRegister[] xmmRegisters = { - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; - - public static final CiRegister[] allRegisters = { - rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, - r8, r9, r10, r11, r12, r13, r14, r15, - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; - - public static final CiRegisterValue RSP = rsp.asValue(Word); - - public AMD64() { - super("AMD64", - 8, - ByteOrder.LittleEndian, - allRegisters, - LOAD_STORE | STORE_STORE, - 1, - r15.encoding + 1, - 8); - } - - @Override - public boolean isX86() { - return true; - } - - @Override - public boolean twoOperandMode() { - return true; - } - -} diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64Assembler.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64Assembler.java Fri May 13 14:03:03 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2878 +0,0 @@ -/* - * Copyright (c) 2009, 2011, 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 com.sun.c1x.target.amd64; - -import static com.sun.c1x.target.amd64.AMD64.*; -import static com.sun.cri.bytecode.Bytecodes.MemoryBarriers.*; -import static com.sun.cri.ci.CiKind.*; - -import com.sun.c1x.*; -import com.sun.c1x.asm.*; -import com.sun.c1x.lir.*; -import com.sun.c1x.util.*; -import com.sun.cri.ci.*; -import com.sun.cri.ri.*; - -/** - * This class implements an assembler that can encode most X86 instructions. - * - * @author Thomas Wuerthinger - */ -public class AMD64Assembler extends AbstractAssembler { - - private static final int MinEncodingNeedsRex = 8; - - /** - * The x86 condition codes used for conditional jumps/moves. - */ - public enum ConditionFlag { - zero(0x4), - notZero(0x5), - equal(0x4), - notEqual(0x5), - less(0xc), - lessEqual(0xe), - greater(0xf), - greaterEqual(0xd), - below(0x2), - belowEqual(0x6), - above(0x7), - aboveEqual(0x3), - overflow(0x0), - noOverflow(0x1), - carrySet(0x2), - carryClear(0x3), - negative(0x8), - positive(0x9), - parity(0xa), - noParity(0xb); - - public final int value; - - private ConditionFlag(int value) { - this.value = value; - } - - public static final ConditionFlag[] values = values(); - } - - /** - * Constants for X86 prefix bytes. - */ - private class Prefix { - private static final int REX = 0x40; - private static final int REXB = 0x41; - private static final int REXX = 0x42; - private static final int REXXB = 0x43; - private static final int REXR = 0x44; - private static final int REXRB = 0x45; - private static final int REXRX = 0x46; - private static final int REXRXB = 0x47; - private static final int REXW = 0x48; - private static final int REXWB = 0x49; - private static final int REXWX = 0x4A; - private static final int REXWXB = 0x4B; - private static final int REXWR = 0x4C; - private static final int REXWRB = 0x4D; - private static final int REXWRX = 0x4E; - private static final int REXWRXB = 0x4F; - } - - /** - * The register to which {@link CiRegister#Frame} and {@link CiRegister#CallerFrame} are bound. - */ - public final CiRegister frameRegister; - - /** - * Constructs an assembler for the AMD64 architecture. - * - * @param registerConfig the register configuration used to bind {@link CiRegister#Frame} and - * {@link CiRegister#CallerFrame} to physical registers. This value can be null if this assembler - * instance will not be used to assemble instructions using these logical registers. - */ - public AMD64Assembler(CiTarget target, RiRegisterConfig registerConfig) { - super(target); - this.frameRegister = registerConfig == null ? null : registerConfig.getFrameRegister(); - } - - private static int encode(CiRegister r) { - assert r.encoding < 16 && r.encoding >= 0 : "encoding out of range: " + r.encoding; - return r.encoding & 0x7; - } - - private void emitArithB(int op1, int op2, CiRegister dst, int imm8) { - assert dst.isByte() : "must have byte register"; - assert Util.isUByte(op1) && Util.isUByte(op2) : "wrong opcode"; - assert Util.isUByte(imm8) : "not a byte"; - assert (op1 & 0x01) == 0 : "should be 8bit operation"; - emitByte(op1); - emitByte(op2 | encode(dst)); - emitByte(imm8); - } - - private void emitArith(int op1, int op2, CiRegister dst, int imm32) { - assert Util.isUByte(op1) && Util.isUByte(op2) : "wrong opcode"; - assert (op1 & 0x01) == 1 : "should be 32bit operation"; - assert (op1 & 0x02) == 0 : "sign-extension bit should not be set"; - if (Util.isByte(imm32)) { - emitByte(op1 | 0x02); // set sign bit - emitByte(op2 | encode(dst)); - emitByte(imm32 & 0xFF); - } else { - emitByte(op1); - emitByte(op2 | encode(dst)); - emitInt(imm32); - } - } - - // immediate-to-memory forms - private void emitArithOperand(int op1, CiRegister rm, CiAddress adr, int imm32) { - assert (op1 & 0x01) == 1 : "should be 32bit operation"; - assert (op1 & 0x02) == 0 : "sign-extension bit should not be set"; - if (Util.isByte(imm32)) { - emitByte(op1 | 0x02); // set sign bit - emitOperandHelper(rm, adr); - emitByte(imm32 & 0xFF); - } else { - emitByte(op1); - emitOperandHelper(rm, adr); - emitInt(imm32); - } - } - - private void emitArith(int op1, int op2, CiRegister dst, CiRegister src) { - assert Util.isUByte(op1) && Util.isUByte(op2) : "wrong opcode"; - emitByte(op1); - emitByte(op2 | encode(dst) << 3 | encode(src)); - } - - private void emitOperandHelper(CiRegister reg, CiAddress addr) { - CiRegister base = addr.base(); - - CiRegister index = addr.index(); - CiAddress.Scale scale = addr.scale; - int disp = addr.displacement; - - if (base == CiRegister.Frame) { - assert frameRegister != null : "cannot use register " + CiRegister.Frame + " in assembler with null register configuration"; - base = frameRegister; - } else if (base == CiRegister.CallerFrame) { - assert frameRegister != null : "cannot use register " + CiRegister.Frame + " in assembler with null register configuration"; - base = frameRegister; - disp += targetMethod.frameSize() + 8; - } - - // Encode the registers as needed in the fields they are used in - - assert reg != CiRegister.None; - - int regenc = encode(reg) << 3; - int indexenc = index.isValid() ? encode(index) << 3 : 0; - int baseenc = base.isValid() ? encode(base) : 0; - - if (base.isValid()) { - if (index.isValid()) { - // [base + indexscale + disp] - if (disp == 0 && base != rbp && (base != r13)) { - // [base + indexscale] - // [00 reg 100][ss index base] - assert index != rsp : "illegal addressing mode"; - emitByte(0x04 | regenc); - emitByte(scale.log2 << 6 | indexenc | baseenc); - } else if (Util.isByte(disp)) { - // [base + indexscale + imm8] - // [01 reg 100][ss index base] imm8 - assert index != rsp : "illegal addressing mode"; - emitByte(0x44 | regenc); - emitByte(scale.log2 << 6 | indexenc | baseenc); - emitByte(disp & 0xFF); - } else { - // [base + indexscale + disp32] - // [10 reg 100][ss index base] disp32 - assert index != rsp : "illegal addressing mode"; - emitByte(0x84 | regenc); - emitByte(scale.log2 << 6 | indexenc | baseenc); - emitInt(disp); - } - } else if (base == rsp || (base == r12)) { - // [rsp + disp] - if (disp == 0) { - // [rsp] - // [00 reg 100][00 100 100] - emitByte(0x04 | regenc); - emitByte(0x24); - } else if (Util.isByte(disp)) { - // [rsp + imm8] - // [01 reg 100][00 100 100] disp8 - emitByte(0x44 | regenc); - emitByte(0x24); - emitByte(disp & 0xFF); - } else { - // [rsp + imm32] - // [10 reg 100][00 100 100] disp32 - emitByte(0x84 | regenc); - emitByte(0x24); - emitInt(disp); - } - } else { - // [base + disp] - assert base != rsp && (base != r12) : "illegal addressing mode"; - if (disp == 0 && base != rbp && (base != r13)) { - // [base] - // [00 reg base] - emitByte(0x00 | regenc | baseenc); - } else if (Util.isByte(disp)) { - // [base + disp8] - // [01 reg base] disp8 - emitByte(0x40 | regenc | baseenc); - emitByte(disp & 0xFF); - } else { - // [base + disp32] - // [10 reg base] disp32 - emitByte(0x80 | regenc | baseenc); - emitInt(disp); - } - } - } else { - if (index.isValid()) { - // [indexscale + disp] - // [00 reg 100][ss index 101] disp32 - assert index != rsp : "illegal addressing mode"; - emitByte(0x04 | regenc); - emitByte(scale.log2 << 6 | indexenc | 0x05); - emitInt(disp); - } else if (base == CiRegister.InstructionRelative) { - // Adjust disp which is currently relative to the start of the instruction - int instrStart = codeBuffer.mark(); - assert instrStart >= 0; - int instrSize = (codeBuffer.position() - instrStart) + 5; - disp = disp - instrSize; - // [00 000 101] disp32 - emitByte(0x05 | regenc); - emitInt(disp); - } else if (addr == CiAddress.Placeholder) { - // [00 000 101] disp32 - emitByte(0x05 | regenc); - emitInt(0); - } else { - // [disp] ABSOLUTE - // [00 reg 100][00 100 101] disp32 - emitByte(0x04 | regenc); - emitByte(0x25); - emitInt(disp); - } - } - } - - public final void addl(CiAddress dst, int imm32) { - prefix(dst); - emitArithOperand(0x81, rax, dst, imm32); - } - - public final void addl(CiAddress dst, CiRegister src) { - prefix(dst, src); - emitByte(0x01); - emitOperandHelper(src, dst); - } - - public final void addl(CiRegister dst, int imm32) { - prefix(dst); - emitArith(0x81, 0xC0, dst, imm32); - } - - public final void addl(CiRegister dst, CiAddress src) { - prefix(src, dst); - emitByte(0x03); - emitOperandHelper(dst, src); - } - - public final void addl(CiRegister dst, CiRegister src) { - prefixAndEncode(dst.encoding, src.encoding); - emitArith(0x03, 0xC0, dst, src); - } - - private void addrNop4() { - // 4 bytes: NOP DWORD PTR [EAX+0] - emitByte(0x0F); - emitByte(0x1F); - emitByte(0x40); // emitRm(cbuf, 0x1, EAXEnc, EAXEnc); - emitByte(0); // 8-bits offset (1 byte) - } - - private void addrNop5() { - // 5 bytes: NOP DWORD PTR [EAX+EAX*0+0] 8-bits offset - emitByte(0x0F); - emitByte(0x1F); - emitByte(0x44); // emitRm(cbuf, 0x1, EAXEnc, 0x4); - emitByte(0x00); // emitRm(cbuf, 0x0, EAXEnc, EAXEnc); - emitByte(0); // 8-bits offset (1 byte) - } - - private void addrNop7() { - // 7 bytes: NOP DWORD PTR [EAX+0] 32-bits offset - emitByte(0x0F); - emitByte(0x1F); - emitByte(0x80); // emitRm(cbuf, 0x2, EAXEnc, EAXEnc); - emitInt(0); // 32-bits offset (4 bytes) - } - - private void addrNop8() { - // 8 bytes: NOP DWORD PTR [EAX+EAX*0+0] 32-bits offset - emitByte(0x0F); - emitByte(0x1F); - emitByte(0x84); // emitRm(cbuf, 0x2, EAXEnc, 0x4); - emitByte(0x00); // emitRm(cbuf, 0x0, EAXEnc, EAXEnc); - emitInt(0); // 32-bits offset (4 bytes) - } - - public final void addsd(CiRegister dst, CiRegister src) { - assert dst.isFpu() && src.isFpu(); - emitByte(0xF2); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x58); - emitByte(0xC0 | encode); - } - - public final void addsd(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - emitByte(0xF2); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x58); - emitOperandHelper(dst, src); - } - - public final void addss(CiRegister dst, CiRegister src) { - assert dst.isFpu() && src.isFpu(); - emitByte(0xF3); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x58); - emitByte(0xC0 | encode); - } - - public final void addss(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - emitByte(0xF3); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x58); - emitOperandHelper(dst, src); - } - - public final void andl(CiRegister dst, int imm32) { - prefix(dst); - emitArith(0x81, 0xE0, dst, imm32); - } - - public final void andl(CiRegister dst, CiAddress src) { - prefix(src, dst); - emitByte(0x23); - emitOperandHelper(dst, src); - } - - public final void andl(CiRegister dst, CiRegister src) { - prefixAndEncode(dst.encoding, src.encoding); - emitArith(0x23, 0xC0, dst, src); - } - - public final void andpd(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - emitByte(0x66); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x54); - emitOperandHelper(dst, src); - } - - public final void bsfq(CiRegister dst, CiRegister src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xBC); - emitByte(0xC0 | encode); - } - - public final void bsfq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0xBC); - emitOperandHelper(dst, src); - } - - public final void bsrq(CiRegister dst, CiRegister src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xBD); - emitByte(0xC0 | encode); - } - - - public final void bsrq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0xBD); - emitOperandHelper(dst, src); - } - - public final void bswapl(CiRegister reg) { // bswap - int encode = prefixAndEncode(reg.encoding); - emitByte(0x0F); - emitByte(0xC8 | encode); - } - - public final void btli(CiAddress src, int imm8) { - prefixq(src); - emitByte(0x0F); - emitByte(0xBA); - emitOperandHelper(rsp, src); - emitByte(imm8); - } - - public final void nativeCall(CiRegister dst, String symbol, LIRDebugInfo info) { - int before = codeBuffer.position(); - int encode = prefixAndEncode(dst.encoding); - emitByte(0xFF); - emitByte(0xD0 | encode); - int after = codeBuffer.position(); - recordIndirectCall(before, after, symbol, info); - recordExceptionHandlers(after, info); - } - - public final int directCall(Object target, LIRDebugInfo info) { - int before = codeBuffer.position(); - emitByte(0xE8); - emitInt(0); - int after = codeBuffer.position(); - recordDirectCall(before, after, target, info); - recordExceptionHandlers(after, info); - return before; - } - - public final int directJmp(Object target) { - int before = codeBuffer.position(); - emitByte(0xE9); - emitInt(0); - int after = codeBuffer.position(); - recordDirectCall(before, after, target, null); - return before; - } - - public final int indirectCall(CiRegister dst, Object target, LIRDebugInfo info) { - int before = codeBuffer.position(); - int encode = prefixAndEncode(dst.encoding); - - emitByte(0xFF); - emitByte(0xD0 | encode); - int after = codeBuffer.position(); - recordIndirectCall(before, after, target, info); - recordExceptionHandlers(after, info); - return before; - } - - public final void cdql() { - emitByte(0x99); - } - - public final void cmovl(ConditionFlag cc, CiRegister dst, CiRegister src) { - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x40 | cc.value); - emitByte(0xC0 | encode); - } - - public final void cmovl(ConditionFlag cc, CiRegister dst, CiAddress src) { - prefix(src, dst); - emitByte(0x0F); - emitByte(0x40 | cc.value); - emitOperandHelper(dst, src); - } - - public final void cmpb(CiAddress dst, int imm8) { - prefix(dst); - emitByte(0x80); - emitOperandHelper(rdi, dst); - emitByte(imm8); - } - - public final void cmpl(CiAddress dst, int imm32) { - prefix(dst); - emitByte(0x81); - emitOperandHelper(rdi, dst); - emitInt(imm32); - } - - public final void cmpl(CiRegister dst, int imm32) { - prefix(dst); - emitArith(0x81, 0xF8, dst, imm32); - } - - public final void cmpl(CiRegister dst, CiRegister src) { - prefixAndEncode(dst.encoding, src.encoding); - emitArith(0x3B, 0xC0, dst, src); - } - - public final void cmpl(CiRegister dst, CiAddress src) { - prefix(src, dst); - emitByte(0x3B); - emitOperandHelper(dst, src); - } - - // The 32-bit cmpxchg compares the value at adr with the contents of X86.rax, - // and stores reg into adr if so; otherwise, the value at adr is loaded into X86.rax,. - // The ZF is set if the compared values were equal, and cleared otherwise. - public final void cmpxchgl(CiRegister reg, CiAddress adr) { // cmpxchg - if ((C1XOptions.Atomics & 2) != 0) { - // caveat: no instructionmark, so this isn't relocatable. - // Emit a synthetic, non-atomic, CAS equivalent. - // Beware. The synthetic form sets all ICCs, not just ZF. - // cmpxchg r,[m] is equivalent to X86.rax, = CAS (m, X86.rax, r) - cmpl(rax, adr); - movl(rax, adr); - if (reg != rax) { - Label l = new Label(); - jcc(ConditionFlag.notEqual, l); - movl(adr, reg); - bind(l); - } - } else { - - prefix(adr, reg); - emitByte(0x0F); - emitByte(0xB1); - emitOperandHelper(reg, adr); - } - } - - public final void comisd(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - // NOTE: dbx seems to decode this as comiss even though the - // 0x66 is there. Strangly ucomisd comes out correct - emitByte(0x66); - comiss(dst, src); - } - - public final void comiss(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - - prefix(src, dst); - emitByte(0x0F); - emitByte(0x2F); - emitOperandHelper(dst, src); - } - - public final void cvtdq2pd(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - - emitByte(0xF3); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xE6); - emitByte(0xC0 | encode); - } - - public final void cvtdq2ps(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x5B); - emitByte(0xC0 | encode); - } - - public final void cvtsd2ss(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0xF2); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x5A); - emitByte(0xC0 | encode); - } - - public final void cvtsi2sdl(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - emitByte(0xF2); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x2A); - emitByte(0xC0 | encode); - } - - public final void cvtsi2ssl(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - emitByte(0xF3); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x2A); - emitByte(0xC0 | encode); - } - - public final void cvtss2sd(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0xF3); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x5A); - emitByte(0xC0 | encode); - } - - public final void cvttsd2sil(CiRegister dst, CiRegister src) { - assert src.isFpu(); - emitByte(0xF2); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x2C); - emitByte(0xC0 | encode); - } - - public final void cvttss2sil(CiRegister dst, CiRegister src) { - assert src.isFpu(); - emitByte(0xF3); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x2C); - emitByte(0xC0 | encode); - } - - public final void decl(CiAddress dst) { - // Don't use it directly. Use Macrodecrement() instead. - prefix(dst); - emitByte(0xFF); - emitOperandHelper(rcx, dst); - } - - public final void divsd(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - emitByte(0xF2); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x5E); - emitOperandHelper(dst, src); - } - - public final void divsd(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0xF2); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x5E); - emitByte(0xC0 | encode); - } - - public final void divss(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - emitByte(0xF3); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x5E); - emitOperandHelper(dst, src); - } - - public final void divss(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0xF3); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x5E); - emitByte(0xC0 | encode); - } - - public final void hlt() { - emitByte(0xF4); - } - - public final void idivl(CiRegister src) { - int encode = prefixAndEncode(src.encoding); - emitByte(0xF7); - emitByte(0xF8 | encode); - } - - public final void imull(CiRegister dst, CiRegister src) { - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xAF); - emitByte(0xC0 | encode); - } - - public final void imull(CiRegister dst, CiRegister src, int value) { - int encode = prefixAndEncode(dst.encoding, src.encoding); - if (Util.isByte(value)) { - emitByte(0x6B); - emitByte(0xC0 | encode); - emitByte(value); - } else { - emitByte(0x69); - emitByte(0xC0 | encode); - emitInt(value); - } - } - - public final void incl(CiAddress dst) { - // Don't use it directly. Use Macroincrement() instead. - prefix(dst); - emitByte(0xFF); - emitOperandHelper(rax, dst); - } - - public final void jcc(ConditionFlag cc, int target, boolean forceDisp32) { - int shortSize = 2; - int longSize = 6; - long disp = target - codeBuffer.position(); - if (!forceDisp32 && Util.isByte(disp - shortSize)) { - // 0111 tttn #8-bit disp - emitByte(0x70 | cc.value); - emitByte((int) ((disp - shortSize) & 0xFF)); - } else { - // 0000 1111 1000 tttn #32-bit disp - assert Util.isInt(disp - longSize) : "must be 32bit offset (call4)"; - emitByte(0x0F); - emitByte(0x80 | cc.value); - emitInt((int) (disp - longSize)); - } - } - - public final void jcc(ConditionFlag cc, Label l) { - assert (0 <= cc.value) && (cc.value < 16) : "illegal cc"; - if (l.isBound()) { - jcc(cc, l.position(), false); - } else { - // Note: could eliminate cond. jumps to this jump if condition - // is the same however, seems to be rather unlikely case. - // Note: use jccb() if label to be bound is very close to get - // an 8-bit displacement - l.addPatchAt(codeBuffer.position()); - emitByte(0x0F); - emitByte(0x80 | cc.value); - emitInt(0); - } - - } - - public final void jccb(ConditionFlag cc, Label l) { - if (l.isBound()) { - int shortSize = 2; - int entry = l.position(); - assert Util.isByte(entry - (codeBuffer.position() + shortSize)) : "Dispacement too large for a short jmp"; - long disp = entry - codeBuffer.position(); - // 0111 tttn #8-bit disp - emitByte(0x70 | cc.value); - emitByte((int) ((disp - shortSize) & 0xFF)); - } else { - - l.addPatchAt(codeBuffer.position()); - emitByte(0x70 | cc.value); - emitByte(0); - } - } - - public final void jmp(CiAddress adr) { - prefix(adr); - emitByte(0xFF); - emitOperandHelper(rsp, adr); - } - - public final void jmp(int target, boolean forceDisp32) { - int shortSize = 2; - int longSize = 5; - long disp = target - codeBuffer.position(); - if (!forceDisp32 && Util.isByte(disp - shortSize)) { - emitByte(0xEB); - emitByte((int) ((disp - shortSize) & 0xFF)); - } else { - emitByte(0xE9); - emitInt((int) (disp - longSize)); - } - } - - public final void jmp(Label l) { - if (l.isBound()) { - jmp(l.position(), false); - } else { - // By default, forward jumps are always 32-bit displacements, since - // we can't yet know where the label will be bound. If you're sure that - // the forward jump will not run beyond 256 bytes, use jmpb to - // force an 8-bit displacement. - - l.addPatchAt(codeBuffer.position()); - emitByte(0xE9); - emitInt(0); - } - } - - public final void jmp(CiRegister entry) { - int encode = prefixAndEncode(entry.encoding); - emitByte(0xFF); - emitByte(0xE0 | encode); - } - - public final void jmpb(Label l) { - if (l.isBound()) { - int shortSize = 2; - int entry = l.position(); - assert Util.isByte((entry - codeBuffer.position()) + shortSize) : "Dispacement too large for a short jmp"; - long offs = entry - codeBuffer.position(); - emitByte(0xEB); - emitByte((int) ((offs - shortSize) & 0xFF)); - } else { - - l.addPatchAt(codeBuffer.position()); - emitByte(0xEB); - emitByte(0); - } - } - - public final void leaq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x8D); - emitOperandHelper(dst, src); - } - - public final void enter(int imm16, int imm8) { - emitByte(0xC8); - emitShort(imm16); - emitByte(imm8); - } - - public final void leave() { - emitByte(0xC9); - } - - public final void lock() { - if ((C1XOptions.Atomics & 1) != 0) { - // Emit either nothing, a NOP, or a NOP: prefix - emitByte(0x90); - } else { - emitByte(0xF0); - } - } - - // Emit mfence instruction - public final void mfence() { - emitByte(0x0F); - emitByte(0xAE); - emitByte(0xF0); - } - - public final void mov(CiRegister dst, CiRegister src) { - movq(dst, src); - } - - public final void movapd(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - int dstenc = dst.encoding; - int srcenc = src.encoding; - emitByte(0x66); - if (dstenc < 8) { - if (srcenc >= 8) { - emitByte(Prefix.REXB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - emitByte(Prefix.REXR); - } else { - emitByte(Prefix.REXRB); - srcenc -= 8; - } - dstenc -= 8; - } - emitByte(0x0F); - emitByte(0x28); - emitByte(0xC0 | dstenc << 3 | srcenc); - } - - public final void movaps(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - int dstenc = dst.encoding; - int srcenc = src.encoding; - if (dstenc < 8) { - if (srcenc >= 8) { - emitByte(Prefix.REXB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - emitByte(Prefix.REXR); - } else { - emitByte(Prefix.REXRB); - srcenc -= 8; - } - dstenc -= 8; - } - emitByte(0x0F); - emitByte(0x28); - emitByte(0xC0 | dstenc << 3 | srcenc); - } - - public final void movb(CiRegister dst, CiAddress src) { - prefix(src, dst); // , true) - emitByte(0x8A); - emitOperandHelper(dst, src); - } - - public final void movb(CiAddress dst, int imm8) { - prefix(dst); - emitByte(0xC6); - emitOperandHelper(rax, dst); - emitByte(imm8); - } - - public final void movb(CiAddress dst, CiRegister src) { - assert src.isByte() : "must have byte register"; - prefix(dst, src); // , true) - emitByte(0x88); - emitOperandHelper(src, dst); - } - - public final void movdl(CiRegister dst, CiRegister src) { - if (dst.isFpu()) { - assert !src.isFpu() : "does this hold?"; - emitByte(0x66); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x6E); - emitByte(0xC0 | encode); - } else if (src.isFpu()) { - assert !dst.isFpu(); - emitByte(0x66); - // swap src/dst to get correct prefix - int encode = prefixAndEncode(src.encoding, dst.encoding); - emitByte(0x0F); - emitByte(0x7E); - emitByte(0xC0 | encode); - } - } - - public final void movdqa(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - emitByte(0x66); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x6F); - emitOperandHelper(dst, src); - } - - public final void movdqa(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - emitByte(0x66); - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x6F); - emitByte(0xC0 | encode); - } - - public final void movdqa(CiAddress dst, CiRegister src) { - assert src.isFpu(); - emitByte(0x66); - prefix(dst, src); - emitByte(0x0F); - emitByte(0x7F); - emitOperandHelper(src, dst); - } - - public final void movdqu(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - emitByte(0xF3); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x6F); - emitOperandHelper(dst, src); - } - - public final void movdqu(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - - emitByte(0xF3); - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x6F); - emitByte(0xC0 | encode); - } - - public final void movdqu(CiAddress dst, CiRegister src) { - assert src.isFpu(); - - emitByte(0xF3); - prefix(dst, src); - emitByte(0x0F); - emitByte(0x7F); - emitOperandHelper(src, dst); - } - - public final void movl(CiRegister dst, int imm32) { - int encode = prefixAndEncode(dst.encoding); - emitByte(0xB8 | encode); - emitInt(imm32); - } - - public final void movl(CiRegister dst, CiRegister src) { - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x8B); - emitByte(0xC0 | encode); - } - - public final void movl(CiRegister dst, CiAddress src) { - prefix(src, dst); - emitByte(0x8B); - emitOperandHelper(dst, src); - } - - public final void movl(CiAddress dst, int imm32) { - prefix(dst); - emitByte(0xC7); - emitOperandHelper(rax, dst); - emitInt(imm32); - } - - public final void movl(CiAddress dst, CiRegister src) { - prefix(dst, src); - emitByte(0x89); - emitOperandHelper(src, dst); - } - - // New cpus require to use movsd and movss to avoid partial register stall - // when loading from memory. But for old Opteron use movlpd instead of movsd. - // The selection is done in Macromovdbl() and movflt(). - public final void movlpd(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - - emitByte(0x66); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x12); - emitOperandHelper(dst, src); - - } - - public final void movq(CiRegister dst, CiAddress src) { - if (dst.isFpu()) { - emitByte(0xF3); - prefixq(src, dst); - emitByte(0x0F); - emitByte(0x7E); - emitOperandHelper(dst, src); - } else { - prefixq(src, dst); - emitByte(0x8B); - emitOperandHelper(dst, src); - } - } - - public final void movq(CiRegister dst, CiRegister src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x8B); - emitByte(0xC0 | encode); - } - - public final void movq(CiAddress dst, CiRegister src) { - if (src.isFpu()) { - emitByte(0x66); - prefixq(dst, src); - emitByte(0x0F); - emitByte(0xD6); - emitOperandHelper(src, dst); - } else { - prefixq(dst, src); - emitByte(0x89); - emitOperandHelper(src, dst); - } - } - - public final void movsxb(CiRegister dst, CiAddress src) { // movsxb - prefix(src, dst); - emitByte(0x0F); - emitByte(0xBE); - emitOperandHelper(dst, src); - } - - public final void movsxb(CiRegister dst, CiRegister src) { // movsxb - int encode = prefixAndEncode(dst.encoding, src.encoding, true); - emitByte(0x0F); - emitByte(0xBE); - emitByte(0xC0 | encode); - } - - public final void movsd(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0xF2); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x10); - emitByte(0xC0 | encode); - } - - public final void movsd(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - emitByte(0xF2); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x10); - emitOperandHelper(dst, src); - } - - public final void movsd(CiAddress dst, CiRegister src) { - assert src.isFpu(); - emitByte(0xF2); - prefix(dst, src); - emitByte(0x0F); - emitByte(0x11); - emitOperandHelper(src, dst); - } - - public final void movss(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0xF3); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x10); - emitByte(0xC0 | encode); - } - - public final void movss(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - emitByte(0xF3); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x10); - emitOperandHelper(dst, src); - } - - public final void movss(CiAddress dst, CiRegister src) { - assert src.isFpu(); - emitByte(0xF3); - prefix(dst, src); - emitByte(0x0F); - emitByte(0x11); - emitOperandHelper(src, dst); - } - - public final void movswl(CiRegister dst, CiAddress src) { - prefix(src, dst); - emitByte(0x0F); - emitByte(0xBF); - emitOperandHelper(dst, src); - } - - public final void movsxw(CiRegister dst, CiRegister src) { // movsxw - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xBF); - emitByte(0xC0 | encode); - } - - public final void movsxw(CiRegister dst, CiAddress src) { // movsxw - prefix(src, dst); - emitByte(0x0F); - emitByte(0xBF); - emitOperandHelper(dst, src); - } - - public final void movzxd(CiRegister dst, CiRegister src) { // movzxd - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x63); - emitByte(0xC0 | encode); - } - - public final void movzxd(CiRegister dst, CiAddress src) { // movzxd - prefix(src, dst); - emitByte(0x63); - emitOperandHelper(dst, src); - } - - public final void movw(CiAddress dst, int imm16) { - emitByte(0x66); // switch to 16-bit mode - prefix(dst); - emitByte(0xC7); - emitOperandHelper(rax, dst); - emitShort(imm16); - } - - public final void movw(CiRegister dst, CiAddress src) { - emitByte(0x66); - prefix(src, dst); - emitByte(0x8B); - emitOperandHelper(dst, src); - } - - public final void movw(CiAddress dst, CiRegister src) { - emitByte(0x66); - prefix(dst, src); - emitByte(0x89); - emitOperandHelper(src, dst); - } - - public final void movzxb(CiRegister dst, CiAddress src) { // movzxb - prefix(src, dst); - emitByte(0x0F); - emitByte(0xB6); - emitOperandHelper(dst, src); - } - - public final void movzxb(CiRegister dst, CiRegister src) { // movzxb - int encode = prefixAndEncode(dst.encoding, src.encoding, true); - emitByte(0x0F); - emitByte(0xB6); - emitByte(0xC0 | encode); - } - - public final void movzxl(CiRegister dst, CiAddress src) { // movzxw - prefix(src, dst); - emitByte(0x0F); - emitByte(0xB7); - emitOperandHelper(dst, src); - } - - public final void movzxl(CiRegister dst, CiRegister src) { // movzxw - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xB7); - emitByte(0xC0 | encode); - } - - public final void mull(CiAddress src) { - prefix(src); - emitByte(0xF7); - emitOperandHelper(rsp, src); - } - - public final void mulsd(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - emitByte(0xF2); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x59); - emitOperandHelper(dst, src); - } - - public final void mulsd(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - - emitByte(0xF2); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x59); - emitByte(0xC0 | encode); - } - - public final void mulss(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - - emitByte(0xF3); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x59); - emitOperandHelper(dst, src); - } - - public final void mulss(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0xF3); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x59); - emitByte(0xC0 | encode); - } - - public final void negl(CiRegister dst) { - int encode = prefixAndEncode(dst.encoding); - emitByte(0xF7); - emitByte(0xD8 | encode); - } - - @Override - public final void nop() { - nop(1); - } - - public void nop(int i) { - if (C1XOptions.UseNormalNop) { - assert i > 0 : " "; - // The fancy nops aren't currently recognized by debuggers making it a - // pain to disassemble code while debugging. If assert are on clearly - // speed is not an issue so simply use the single byte traditional nop - // to do alignment. - - for (; i > 0; i--) { - emitByte(0x90); - } - return; - } - - if (C1XOptions.UseAddressNop) { - // - // Using multi-bytes nops "0x0F 0x1F [Address]" for AMD. - // 1: 0x90 - // 2: 0x66 0x90 - // 3: 0x66 0x66 0x90 (don't use "0x0F 0x1F 0x00" - need patching safe padding) - // 4: 0x0F 0x1F 0x40 0x00 - // 5: 0x0F 0x1F 0x44 0x00 0x00 - // 6: 0x66 0x0F 0x1F 0x44 0x00 0x00 - // 7: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 - // 8: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 - // 9: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 - // 10: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 - // 11: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 - - // The rest coding is AMD specific - use consecutive Address nops - - // 12: 0x66 0x0F 0x1F 0x44 0x00 0x00 0x66 0x0F 0x1F 0x44 0x00 0x00 - // 13: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 0x66 0x0F 0x1F 0x44 0x00 0x00 - // 14: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 - // 15: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 - // 16: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 - // Size prefixes (0x66) are added for larger sizes - - while (i >= 22) { - i -= 11; - emitByte(0x66); // size prefix - emitByte(0x66); // size prefix - emitByte(0x66); // size prefix - addrNop8(); - } - // Generate first nop for size between 21-12 - switch (i) { - case 21: - i -= 1; - emitByte(0x66); // size prefix - // fall through - case 20: - // fall through - case 19: - i -= 1; - emitByte(0x66); // size prefix - // fall through - case 18: - // fall through - case 17: - i -= 1; - emitByte(0x66); // size prefix - // fall through - case 16: - // fall through - case 15: - i -= 8; - addrNop8(); - break; - case 14: - case 13: - i -= 7; - addrNop7(); - break; - case 12: - i -= 6; - emitByte(0x66); // size prefix - addrNop5(); - break; - default: - assert i < 12; - } - - // Generate second nop for size between 11-1 - switch (i) { - case 11: - emitByte(0x66); // size prefix - emitByte(0x66); // size prefix - emitByte(0x66); // size prefix - addrNop8(); - break; - case 10: - emitByte(0x66); // size prefix - emitByte(0x66); // size prefix - addrNop8(); - break; - case 9: - emitByte(0x66); // size prefix - addrNop8(); - break; - case 8: - addrNop8(); - break; - case 7: - addrNop7(); - break; - case 6: - emitByte(0x66); // size prefix - addrNop5(); - break; - case 5: - addrNop5(); - break; - case 4: - addrNop4(); - break; - case 3: - // Don't use "0x0F 0x1F 0x00" - need patching safe padding - emitByte(0x66); // size prefix - emitByte(0x66); // size prefix - emitByte(0x90); // nop - break; - case 2: - emitByte(0x66); // size prefix - emitByte(0x90); // nop - break; - case 1: - emitByte(0x90); // nop - break; - default: - assert i == 0; - } - return; - } - - // Using nops with size prefixes "0x66 0x90". - // From AMD Optimization Guide: - // 1: 0x90 - // 2: 0x66 0x90 - // 3: 0x66 0x66 0x90 - // 4: 0x66 0x66 0x66 0x90 - // 5: 0x66 0x66 0x90 0x66 0x90 - // 6: 0x66 0x66 0x90 0x66 0x66 0x90 - // 7: 0x66 0x66 0x66 0x90 0x66 0x66 0x90 - // 8: 0x66 0x66 0x66 0x90 0x66 0x66 0x66 0x90 - // 9: 0x66 0x66 0x90 0x66 0x66 0x90 0x66 0x66 0x90 - // 10: 0x66 0x66 0x66 0x90 0x66 0x66 0x90 0x66 0x66 0x90 - // - while (i > 12) { - i -= 4; - emitByte(0x66); // size prefix - emitByte(0x66); - emitByte(0x66); - emitByte(0x90); // nop - } - // 1 - 12 nops - if (i > 8) { - if (i > 9) { - i -= 1; - emitByte(0x66); - } - i -= 3; - emitByte(0x66); - emitByte(0x66); - emitByte(0x90); - } - // 1 - 8 nops - if (i > 4) { - if (i > 6) { - i -= 1; - emitByte(0x66); - } - i -= 3; - emitByte(0x66); - emitByte(0x66); - emitByte(0x90); - } - switch (i) { - case 4: - emitByte(0x66); - emitByte(0x66); - emitByte(0x66); - emitByte(0x90); - break; - case 3: - emitByte(0x66); - emitByte(0x66); - emitByte(0x90); - break; - case 2: - emitByte(0x66); - emitByte(0x90); - break; - case 1: - emitByte(0x90); - break; - default: - assert i == 0; - } - } - - public final void notl(CiRegister dst) { - int encode = prefixAndEncode(dst.encoding); - emitByte(0xF7); - emitByte(0xD0 | encode); - } - - public final void orl(CiAddress dst, int imm32) { - prefix(dst); - emitByte(0x81); - emitOperandHelper(rcx, dst); - emitInt(imm32); - } - - public final void orl(CiRegister dst, int imm32) { - prefix(dst); - emitArith(0x81, 0xC8, dst, imm32); - } - - public final void orl(CiRegister dst, CiAddress src) { - prefix(src, dst); - emitByte(0x0B); - emitOperandHelper(dst, src); - } - - public final void orl(CiRegister dst, CiRegister src) { - prefixAndEncode(dst.encoding, src.encoding); - emitArith(0x0B, 0xC0, dst, src); - } - - // generic - public final void pop(CiRegister dst) { - int encode = prefixAndEncode(dst.encoding); - emitByte(0x58 | encode); - } - - public final void popl(CiAddress dst) { - // NOTE: this will adjust stack by 8byte on 64bits - prefix(dst); - emitByte(0x8F); - emitOperandHelper(rax, dst); - } - - public final void prefetchPrefix(CiAddress src) { - prefix(src); - emitByte(0x0F); - } - - public final void prefetchnta(CiAddress src) { - prefetchPrefix(src); - emitByte(0x18); - emitOperandHelper(rax, src); // 0, src - } - - public final void prefetchr(CiAddress src) { - prefetchPrefix(src); - emitByte(0x0D); - emitOperandHelper(rax, src); // 0, src - } - - public final void prefetcht0(CiAddress src) { - prefetchPrefix(src); - emitByte(0x18); - emitOperandHelper(rcx, src); // 1, src - - } - - public final void prefetcht1(CiAddress src) { - prefetchPrefix(src); - emitByte(0x18); - emitOperandHelper(rdx, src); // 2, src - } - - public final void prefetcht2(CiAddress src) { - prefetchPrefix(src); - emitByte(0x18); - emitOperandHelper(rbx, src); // 3, src - } - - public final void prefetchw(CiAddress src) { - prefetchPrefix(src); - emitByte(0x0D); - emitOperandHelper(rcx, src); // 1, src - } - - public final void pshufd(CiRegister dst, CiRegister src, int mode) { - assert dst.isFpu(); - assert src.isFpu(); - assert Util.isUByte(mode) : "invalid value"; - - emitByte(0x66); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x70); - emitByte(0xC0 | encode); - emitByte(mode & 0xFF); - } - - public final void pshufd(CiRegister dst, CiAddress src, int mode) { - assert dst.isFpu(); - assert Util.isUByte(mode) : "invalid value"; - - emitByte(0x66); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x70); - emitOperandHelper(dst, src); - emitByte(mode & 0xFF); - - } - - public final void pshuflw(CiRegister dst, CiRegister src, int mode) { - assert dst.isFpu(); - assert src.isFpu(); - assert Util.isUByte(mode) : "invalid value"; - - emitByte(0xF2); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x70); - emitByte(0xC0 | encode); - emitByte(mode & 0xFF); - } - - public final void pshuflw(CiRegister dst, CiAddress src, int mode) { - assert dst.isFpu(); - assert Util.isUByte(mode) : "invalid value"; - - emitByte(0xF2); - prefix(src, dst); // QQ new - emitByte(0x0F); - emitByte(0x70); - emitOperandHelper(dst, src); - emitByte(mode & 0xFF); - } - - public final void psrlq(CiRegister dst, int shift) { - assert dst.isFpu(); - // HMM Table D-1 says sse2 or mmx - - int encode = prefixqAndEncode(xmm2.encoding, dst.encoding); - emitByte(0x66); - emitByte(0x0F); - emitByte(0x73); - emitByte(0xC0 | encode); - emitByte(shift); - } - - public final void punpcklbw(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0x66); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x60); - emitByte(0xC0 | encode); - } - - public final void push(int imm32) { - // in 64bits we push 64bits onto the stack but only - // take a 32bit immediate - emitByte(0x68); - emitInt(imm32); - } - - public final void push(CiRegister src) { - int encode = prefixAndEncode(src.encoding); - emitByte(0x50 | encode); - } - - public final void pushf() { - emitByte(0x9C); - } - - public final void pushl(CiAddress src) { - // Note this will push 64bit on 64bit - prefix(src); - emitByte(0xFF); - emitOperandHelper(rsi, src); - } - - public final void pxor(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - - emitByte(0x66); - prefix(src, dst); - emitByte(0x0F); - emitByte(0xEF); - emitOperandHelper(dst, src); - } - - public final void pxor(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - - emitByte(0x66); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xEF); - emitByte(0xC0 | encode); - - } - - public final void rcll(CiRegister dst, int imm8) { - assert Util.isShiftCount(imm8) : "illegal shift count"; - int encode = prefixAndEncode(dst.encoding); - if (imm8 == 1) { - emitByte(0xD1); - emitByte(0xD0 | encode); - } else { - emitByte(0xC1); - emitByte(0xD0 | encode); - emitByte(imm8); - } - } - - public final void pause() { - emitByte(0xF3); - emitByte(0x90); - } - - // Copies data from [X86.rsi] to [X86.rdi] using X86.rcx heap words. - public final void repeatMoveWords() { - emitByte(0xF3); - emitByte(Prefix.REXW); - emitByte(0xA5); - } - - // Copies data from [X86.rsi] to [X86.rdi] using X86.rcx bytes. - public final void repeatMoveBytes() { - emitByte(0xF3); - emitByte(Prefix.REXW); - emitByte(0xA4); - } - - // sets X86.rcx pointer sized words with X86.rax, value at [edi] - // generic - public final void repSet() { // repSet - emitByte(0xF3); - // STOSQ - emitByte(Prefix.REXW); - emitByte(0xAB); - } - - // scans X86.rcx pointer sized words at [edi] for occurance of X86.rax, - // generic - public final void repneScan() { // repneScan - emitByte(0xF2); - // SCASQ - emitByte(Prefix.REXW); - emitByte(0xAF); - } - - // scans X86.rcx 4 byte words at [edi] for occurance of X86.rax, - // generic - public final void repneScanl() { // repneScan - emitByte(0xF2); - // SCASL - emitByte(0xAF); - } - - public final void ret(int imm16) { - if (imm16 == 0) { - emitByte(0xC3); - } else { - emitByte(0xC2); - emitShort(imm16); - } - } - - public final void sarl(CiRegister dst, int imm8) { - int encode = prefixAndEncode(dst.encoding); - assert Util.isShiftCount(imm8) : "illegal shift count"; - if (imm8 == 1) { - emitByte(0xD1); - emitByte(0xF8 | encode); - } else { - emitByte(0xC1); - emitByte(0xF8 | encode); - emitByte(imm8); - } - } - - public final void sarl(CiRegister dst) { - int encode = prefixAndEncode(dst.encoding); - emitByte(0xD3); - emitByte(0xF8 | encode); - } - - public final void sbbl(CiAddress dst, int imm32) { - prefix(dst); - emitArithOperand(0x81, rbx, dst, imm32); - } - - public final void sbbl(CiRegister dst, int imm32) { - prefix(dst); - emitArith(0x81, 0xD8, dst, imm32); - } - - public final void sbbl(CiRegister dst, CiAddress src) { - prefix(src, dst); - emitByte(0x1B); - emitOperandHelper(dst, src); - } - - public final void sbbl(CiRegister dst, CiRegister src) { - prefixAndEncode(dst.encoding, src.encoding); - emitArith(0x1B, 0xC0, dst, src); - } - - public final void setb(ConditionFlag cc, CiRegister dst) { - assert 0 <= cc.value && cc.value < 16 : "illegal cc"; - int encode = prefixAndEncode(dst.encoding, true); - emitByte(0x0F); - emitByte(0x90 | cc.value); - emitByte(0xC0 | encode); - } - - public final void shll(CiRegister dst, int imm8) { - assert Util.isShiftCount(imm8) : "illegal shift count"; - int encode = prefixAndEncode(dst.encoding); - if (imm8 == 1) { - emitByte(0xD1); - emitByte(0xE0 | encode); - } else { - emitByte(0xC1); - emitByte(0xE0 | encode); - emitByte(imm8); - } - } - - public final void shll(CiRegister dst) { - int encode = prefixAndEncode(dst.encoding); - emitByte(0xD3); - emitByte(0xE0 | encode); - } - - public final void shrl(CiRegister dst, int imm8) { - assert Util.isShiftCount(imm8) : "illegal shift count"; - int encode = prefixAndEncode(dst.encoding); - emitByte(0xC1); - emitByte(0xE8 | encode); - emitByte(imm8); - } - - public final void shrl(CiRegister dst) { - int encode = prefixAndEncode(dst.encoding); - emitByte(0xD3); - emitByte(0xE8 | encode); - } - - // copies a single word from [esi] to [edi] - public final void smovl() { - emitByte(0xA5); - } - - public final void sqrtsd(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - // HMM Table D-1 says sse2 - // assert is64 || target.supportsSSE(); - emitByte(0xF2); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x51); - emitByte(0xC0 | encode); - } - - public final void subl(CiAddress dst, int imm32) { - prefix(dst); - if (Util.isByte(imm32)) { - emitByte(0x83); - emitOperandHelper(rbp, dst); - emitByte(imm32 & 0xFF); - } else { - emitByte(0x81); - emitOperandHelper(rbp, dst); - emitInt(imm32); - } - } - - public final void subl(CiRegister dst, int imm32) { - prefix(dst); - emitArith(0x81, 0xE8, dst, imm32); - } - - public final void subl(CiAddress dst, CiRegister src) { - prefix(dst, src); - emitByte(0x29); - emitOperandHelper(src, dst); - } - - public final void subl(CiRegister dst, CiAddress src) { - prefix(src, dst); - emitByte(0x2B); - emitOperandHelper(dst, src); - } - - public final void subl(CiRegister dst, CiRegister src) { - prefixAndEncode(dst.encoding, src.encoding); - emitArith(0x2B, 0xC0, dst, src); - } - - public final void subsd(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0xF2); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x5C); - emitByte(0xC0 | encode); - } - - public final void subsd(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - - emitByte(0xF2); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x5C); - emitOperandHelper(dst, src); - } - - public final void subss(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0xF3); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x5C); - emitByte(0xC0 | encode); - } - - public final void subss(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - - emitByte(0xF3); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x5C); - emitOperandHelper(dst, src); - } - - public final void testb(CiRegister dst, int imm8) { - prefixAndEncode(dst.encoding, true); - emitArithB(0xF6, 0xC0, dst, imm8); - } - - public final void testl(CiRegister dst, int imm32) { - // not using emitArith because test - // doesn't support sign-extension of - // 8bit operands - int encode = dst.encoding; - if (encode == 0) { - emitByte(0xA9); - } else { - encode = prefixAndEncode(encode); - emitByte(0xF7); - emitByte(0xC0 | encode); - } - emitInt(imm32); - } - - public final void testl(CiRegister dst, CiRegister src) { - prefixAndEncode(dst.encoding, src.encoding); - emitArith(0x85, 0xC0, dst, src); - } - - public final void testl(CiRegister dst, CiAddress src) { - prefix(src, dst); - emitByte(0x85); - emitOperandHelper(dst, src); - } - - public final void ucomisd(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - emitByte(0x66); - ucomiss(dst, src); - } - - public final void ucomisd(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0x66); - ucomiss(dst, src); - } - - public final void ucomiss(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - - prefix(src, dst); - emitByte(0x0F); - emitByte(0x2E); - emitOperandHelper(dst, src); - } - - public final void ucomiss(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x2E); - emitByte(0xC0 | encode); - } - - public final void xaddl(CiAddress dst, CiRegister src) { - assert src.isFpu(); - - prefix(dst, src); - emitByte(0x0F); - emitByte(0xC1); - emitOperandHelper(src, dst); - } - - public final void xchgl(CiRegister dst, CiAddress src) { // xchg - prefix(src, dst); - emitByte(0x87); - emitOperandHelper(dst, src); - } - - public final void xchgl(CiRegister dst, CiRegister src) { - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x87); - emitByte(0xc0 | encode); - } - - public final void xorl(CiRegister dst, int imm32) { - prefix(dst); - emitArith(0x81, 0xF0, dst, imm32); - } - - public final void xorl(CiRegister dst, CiAddress src) { - prefix(src, dst); - emitByte(0x33); - emitOperandHelper(dst, src); - } - - public final void xorl(CiRegister dst, CiRegister src) { - prefixAndEncode(dst.encoding, src.encoding); - emitArith(0x33, 0xC0, dst, src); - } - - public final void xorpd(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0x66); - xorps(dst, src); - } - - public final void xorpd(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - - emitByte(0x66); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x57); - emitOperandHelper(dst, src); - } - - public final void xorps(CiRegister dst, CiRegister src) { - - assert dst.isFpu(); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x57); - emitByte(0xC0 | encode); - } - - public final void xorps(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - - prefix(src, dst); - emitByte(0x0F); - emitByte(0x57); - emitOperandHelper(dst, src); - } - - // 32bit only pieces of the assembler - - public final void decl(CiRegister dst) { - // Don't use it directly. Use Macrodecrementl() instead. - // Use two-byte form (one-byte form is a REX prefix in 64-bit mode) - int encode = prefixAndEncode(dst.encoding); - emitByte(0xFF); - emitByte(0xC8 | encode); - } - - public final void incl(CiRegister dst) { - // Don't use it directly. Use Macroincrementl() instead. - // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) - int encode = prefixAndEncode(dst.encoding); - emitByte(0xFF); - emitByte(0xC0 | encode); - } - - int prefixAndEncode(int regEnc) { - return prefixAndEncode(regEnc, false); - } - - int prefixAndEncode(int regEnc, boolean byteinst) { - if (regEnc >= 8) { - emitByte(Prefix.REXB); - regEnc -= 8; - } else if (byteinst && regEnc >= 4) { - emitByte(Prefix.REX); - } - return regEnc; - } - - int prefixqAndEncode(int regEnc) { - if (regEnc < 8) { - emitByte(Prefix.REXW); - } else { - emitByte(Prefix.REXWB); - regEnc -= 8; - } - return regEnc; - } - - int prefixAndEncode(int dstEnc, int srcEnc) { - return prefixAndEncode(dstEnc, srcEnc, false); - } - - int prefixAndEncode(int dstEnc, int srcEnc, boolean byteinst) { - if (dstEnc < 8) { - if (srcEnc >= 8) { - emitByte(Prefix.REXB); - srcEnc -= 8; - } else if (byteinst && srcEnc >= 4) { - emitByte(Prefix.REX); - } - } else { - if (srcEnc < 8) { - emitByte(Prefix.REXR); - } else { - emitByte(Prefix.REXRB); - srcEnc -= 8; - } - dstEnc -= 8; - } - return dstEnc << 3 | srcEnc; - } - - /** - * Creates prefix and the encoding of the lower 6 bits of the ModRM-Byte. It emits an operand prefix. If the given - * operands exceed 3 bits, the 4th bit is encoded in the prefix. - * - * @param regEnc the encoding of the register part of the ModRM-Byte - * @param rmEnc the encoding of the r/m part of the ModRM-Byte - * @return the lower 6 bits of the ModRM-Byte that should be emitted - */ - private int prefixqAndEncode(int regEnc, int rmEnc) { - if (regEnc < 8) { - if (rmEnc < 8) { - emitByte(Prefix.REXW); - } else { - emitByte(Prefix.REXWB); - rmEnc -= 8; - } - } else { - if (rmEnc < 8) { - emitByte(Prefix.REXWR); - } else { - emitByte(Prefix.REXWRB); - rmEnc -= 8; - } - regEnc -= 8; - } - return regEnc << 3 | rmEnc; - } - - private void prefix(CiRegister reg) { - if (reg.encoding >= 8) { - emitByte(Prefix.REXB); - } - } - - private void prefix(CiAddress adr) { - if (adr.base().encoding >= MinEncodingNeedsRex) { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXXB); - } else { - emitByte(Prefix.REXB); - } - } else { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXX); - } - } - } - - private void prefixq(CiAddress adr) { - if (adr.base().encoding >= MinEncodingNeedsRex) { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXWXB); - } else { - emitByte(Prefix.REXWB); - } - } else { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXWX); - } else { - emitByte(Prefix.REXW); - } - } - } - - private void prefix(CiAddress adr, CiRegister reg) { - if (reg.encoding < 8) { - if (adr.base().encoding >= MinEncodingNeedsRex) { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXXB); - } else { - emitByte(Prefix.REXB); - } - } else { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXX); - } else if (reg.encoding >= 4) { - emitByte(Prefix.REX); - } - } - } else { - if (adr.base().encoding >= MinEncodingNeedsRex) { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXRXB); - } else { - emitByte(Prefix.REXRB); - } - } else { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXRX); - } else { - emitByte(Prefix.REXR); - } - } - } - } - - private void prefixq(CiAddress adr, CiRegister src) { - if (src.encoding < 8) { - if (adr.base().encoding >= MinEncodingNeedsRex) { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXWXB); - } else { - emitByte(Prefix.REXWB); - } - } else { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXWX); - } else { - emitByte(Prefix.REXW); - } - } - } else { - if (adr.base().encoding >= MinEncodingNeedsRex) { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXWRXB); - } else { - emitByte(Prefix.REXWRB); - } - } else { - if (adr.index().encoding >= MinEncodingNeedsRex) { - emitByte(Prefix.REXWRX); - } else { - emitByte(Prefix.REXWR); - } - } - } - } - - public final void addq(CiAddress dst, int imm32) { - prefixq(dst); - emitArithOperand(0x81, rax, dst, imm32); - } - - public final void addq(CiAddress dst, CiRegister src) { - prefixq(dst, src); - emitByte(0x01); - emitOperandHelper(src, dst); - } - - public final void addq(CiRegister dst, int imm32) { - prefixqAndEncode(dst.encoding); - emitArith(0x81, 0xC0, dst, imm32); - } - - public final void addq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x03); - emitOperandHelper(dst, src); - } - - public final void addq(CiRegister dst, CiRegister src) { - prefixqAndEncode(dst.encoding, src.encoding); - emitArith(0x03, 0xC0, dst, src); - } - - public final void andq(CiRegister dst, int imm32) { - prefixqAndEncode(dst.encoding); - emitArith(0x81, 0xE0, dst, imm32); - } - - public final void andq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x23); - emitOperandHelper(dst, src); - } - - public final void andq(CiRegister dst, CiRegister src) { - prefixqAndEncode(dst.encoding, src.encoding); - emitArith(0x23, 0xC0, dst, src); - } - - public final void bswapq(CiRegister reg) { - int encode = prefixqAndEncode(reg.encoding); - emitByte(0x0F); - emitByte(0xC8 | encode); - } - - public final void cdqq() { - emitByte(Prefix.REXW); - emitByte(0x99); - } - - public final void cmovq(ConditionFlag cc, CiRegister dst, CiRegister src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x40 | cc.value); - emitByte(0xC0 | encode); - } - - public final void cmovq(ConditionFlag cc, CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x0F); - emitByte(0x40 | cc.value); - emitOperandHelper(dst, src); - } - - public final void cmpq(CiAddress dst, int imm32) { - prefixq(dst); - emitByte(0x81); - emitOperandHelper(rdi, dst); - emitInt(imm32); - } - - public final void cmpq(CiRegister dst, int imm32) { - prefixqAndEncode(dst.encoding); - emitArith(0x81, 0xF8, dst, imm32); - } - - public final void cmpq(CiAddress dst, CiRegister src) { - prefixq(dst, src); - emitByte(0x3B); - emitOperandHelper(src, dst); - } - - public final void cmpq(CiRegister dst, CiRegister src) { - prefixqAndEncode(dst.encoding, src.encoding); - emitArith(0x3B, 0xC0, dst, src); - } - - public final void cmpq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x3B); - emitOperandHelper(dst, src); - } - - public final void cmpxchgq(CiRegister reg, CiAddress adr) { - prefixq(adr, reg); - emitByte(0x0F); - emitByte(0xB1); - emitOperandHelper(reg, adr); - } - - public final void cvtsi2sdq(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - emitByte(0xF2); - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x2A); - emitByte(0xC0 | encode); - } - - public final void cvtsi2ssq(CiRegister dst, CiRegister src) { - assert dst.isFpu(); - emitByte(0xF3); - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x2A); - emitByte(0xC0 | encode); - } - - public final void cvttsd2siq(CiRegister dst, CiRegister src) { - assert src.isFpu(); - emitByte(0xF2); - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x2C); - emitByte(0xC0 | encode); - } - - public final void cvttss2siq(CiRegister dst, CiRegister src) { - assert src.isFpu(); - emitByte(0xF3); - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x2C); - emitByte(0xC0 | encode); - } - - public final void decq(CiRegister dst) { - // Don't use it directly. Use Macrodecrementq() instead. - // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xFF); - emitByte(0xC8 | encode); - } - - public final void decq(CiAddress dst) { - // Don't use it directly. Use Macrodecrementq() instead. - prefixq(dst); - emitByte(0xFF); - emitOperandHelper(rcx, dst); - } - - public final void divq(CiRegister src) { - int encode = prefixqAndEncode(src.encoding); - emitByte(0xF7); - emitByte(0xF0 | encode); - } - - public final void idivq(CiRegister src) { - int encode = prefixqAndEncode(src.encoding); - emitByte(0xF7); - emitByte(0xF8 | encode); - } - - public final void imulq(CiRegister dst, CiRegister src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xAF); - emitByte(0xC0 | encode); - } - - public final void imulq(CiRegister dst, CiRegister src, int value) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - if (Util.isByte(value)) { - emitByte(0x6B); - emitByte(0xC0 | encode); - emitByte(value); - } else { - emitByte(0x69); - emitByte(0xC0 | encode); - emitInt(value); - } - } - - public final void incq(CiRegister dst) { - // Don't use it directly. Use Macroincrementq() instead. - // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xFF); - emitByte(0xC0 | encode); - } - - public final void incq(CiAddress dst) { - // Don't use it directly. Use Macroincrementq() instead. - prefixq(dst); - emitByte(0xFF); - emitOperandHelper(rax, dst); - } - - public final void movq(CiRegister dst, long imm64) { - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xB8 | encode); - emitLong(imm64); - } - - public final void movdq(CiRegister dst, CiRegister src) { - - // table D-1 says MMX/SSE2 - emitByte(0x66); - - if (dst.isFpu()) { - assert dst.isFpu(); - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x6E); - emitByte(0xC0 | encode); - } else if (src.isFpu()) { - - // swap src/dst to get correct prefix - int encode = prefixqAndEncode(src.encoding, dst.encoding); - emitByte(0x0F); - emitByte(0x7E); - emitByte(0xC0 | encode); - } else { - Util.shouldNotReachHere(); - } - } - - public final void movsbq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x0F); - emitByte(0xBE); - emitOperandHelper(dst, src); - } - - public final void movsbq(CiRegister dst, CiRegister src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xBE); - emitByte(0xC0 | encode); - } - - public final void movslq(CiRegister dst, int imm32) { - // dbx shows movslq(X86.rcx, 3) as movq $0x0000000049000000,(%X86.rbx) - // and movslq(X86.r8, 3); as movl $0x0000000048000000,(%X86.rbx) - // as a result we shouldn't use until tested at runtime... - Util.shouldNotReachHere(); - - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xC7 | encode); - emitInt(imm32); - } - - public final void movslq(CiAddress dst, int imm32) { - prefixq(dst); - emitByte(0xC7); - emitOperandHelper(rax, dst); - emitInt(imm32); - } - - public final void movslq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x63); - emitOperandHelper(dst, src); - } - - public final void movslq(CiRegister dst, CiRegister src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x63); - emitByte(0xC0 | encode); - } - - public final void movswq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x0F); - emitByte(0xBF); - emitOperandHelper(dst, src); - } - - public final void movswq(CiRegister dst, CiRegister src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xBF); - emitByte(0xC0 | encode); - } - - public final void movzbq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x0F); - emitByte(0xB6); - emitOperandHelper(dst, src); - } - - public final void movzbq(CiRegister dst, CiRegister src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xB6); - emitByte(0xC0 | encode); - } - - public final void movzwq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x0F); - emitByte(0xB7); - emitOperandHelper(dst, src); - } - - public final void movzwq(CiRegister dst, CiRegister src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xB7); - emitByte(0xC0 | encode); - } - - public final void negq(CiRegister dst) { - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xF7); - emitByte(0xD8 | encode); - } - - public final void notq(CiRegister dst) { - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xF7); - emitByte(0xD0 | encode); - } - - public final void orq(CiAddress dst, int imm32) { - prefixq(dst); - emitByte(0x81); - emitOperandHelper(rcx, dst); - emitInt(imm32); - } - - public final void orq(CiRegister dst, int imm32) { - prefixqAndEncode(dst.encoding); - emitArith(0x81, 0xC8, dst, imm32); - } - - public final void orq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x0B); - emitOperandHelper(dst, src); - } - - public final void orq(CiRegister dst, CiRegister src) { - prefixqAndEncode(dst.encoding, src.encoding); - emitArith(0x0B, 0xC0, dst, src); - } - - public final void popq(CiAddress dst) { - prefixq(dst); - emitByte(0x8F); - emitOperandHelper(rax, dst); - } - - public final void pushq(CiAddress src) { - prefixq(src); - emitByte(0xFF); - emitOperandHelper(rsi, src); - } - - public final void rclq(CiRegister dst, int imm8) { - assert Util.isShiftCount(imm8 >> 1) : "illegal shift count"; - int encode = prefixqAndEncode(dst.encoding); - if (imm8 == 1) { - emitByte(0xD1); - emitByte(0xD0 | encode); - } else { - emitByte(0xC1); - emitByte(0xD0 | encode); - emitByte(imm8); - } - } - - public final void sarq(CiRegister dst, int imm8) { - assert Util.isShiftCount(imm8 >> 1) : "illegal shift count"; - int encode = prefixqAndEncode(dst.encoding); - if (imm8 == 1) { - emitByte(0xD1); - emitByte(0xF8 | encode); - } else { - emitByte(0xC1); - emitByte(0xF8 | encode); - emitByte(imm8); - } - } - - public final void sarq(CiRegister dst) { - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xD3); - emitByte(0xF8 | encode); - } - - public final void shlq(CiRegister dst, int imm8) { - assert Util.isShiftCount(imm8 >> 1) : "illegal shift count"; - int encode = prefixqAndEncode(dst.encoding); - if (imm8 == 1) { - emitByte(0xD1); - emitByte(0xE0 | encode); - } else { - emitByte(0xC1); - emitByte(0xE0 | encode); - emitByte(imm8); - } - } - - public final void shlq(CiRegister dst) { - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xD3); - emitByte(0xE0 | encode); - } - - public final void shrq(CiRegister dst, int imm8) { - assert Util.isShiftCount(imm8 >> 1) : "illegal shift count"; - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xC1); - emitByte(0xE8 | encode); - emitByte(imm8); - } - - public final void shrq(CiRegister dst) { - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xD3); - emitByte(0xE8 | encode); - } - - public final void sqrtsd(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - - emitByte(0xF2); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x51); - emitOperandHelper(dst, src); - } - - public final void subq(CiAddress dst, int imm32) { - prefixq(dst); - if (Util.isByte(imm32)) { - emitByte(0x83); - emitOperandHelper(rbp, dst); - emitByte(imm32 & 0xFF); - } else { - emitByte(0x81); - emitOperandHelper(rbp, dst); - emitInt(imm32); - } - } - - public final void subq(CiRegister dst, int imm32) { - prefixqAndEncode(dst.encoding); - emitArith(0x81, 0xE8, dst, imm32); - } - - public final void subq(CiAddress dst, CiRegister src) { - prefixq(dst, src); - emitByte(0x29); - emitOperandHelper(src, dst); - } - - public final void subq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x2B); - emitOperandHelper(dst, src); - } - - public final void subq(CiRegister dst, CiRegister src) { - prefixqAndEncode(dst.encoding, src.encoding); - emitArith(0x2B, 0xC0, dst, src); - } - - public final void testq(CiRegister dst, int imm32) { - // not using emitArith because test - // doesn't support sign-extension of - // 8bit operands - int encode = dst.encoding; - if (encode == 0) { - emitByte(Prefix.REXW); - emitByte(0xA9); - } else { - encode = prefixqAndEncode(encode); - emitByte(0xF7); - emitByte(0xC0 | encode); - } - emitInt(imm32); - } - - public final void testq(CiRegister dst, CiRegister src) { - prefixqAndEncode(dst.encoding, src.encoding); - emitArith(0x85, 0xC0, dst, src); - } - - public final void xaddq(CiAddress dst, CiRegister src) { - prefixq(dst, src); - emitByte(0x0F); - emitByte(0xC1); - emitOperandHelper(src, dst); - } - - public final void xchgq(CiRegister dst, CiAddress src) { - prefixq(src, dst); - emitByte(0x87); - emitOperandHelper(dst, src); - } - - public final void xchgq(CiRegister dst, CiRegister src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x87); - emitByte(0xc0 | encode); - } - - public final void xorq(CiRegister dst, CiRegister src) { - prefixqAndEncode(dst.encoding, src.encoding); - emitArith(0x33, 0xC0, dst, src); - } - - public final void xorq(CiRegister dst, CiAddress src) { - - prefixq(src, dst); - emitByte(0x33); - emitOperandHelper(dst, src); - - } - - public final void membar(int barriers) { - if (target.isMP) { - // We only have to handle StoreLoad - if ((barriers & STORE_LOAD) != 0) { - // All usable chips support "locked" instructions which suffice - // as barriers, and are much faster than the alternative of - // using cpuid instruction. We use here a locked add [rsp],0. - // This is conveniently otherwise a no-op except for blowing - // flags. - // Any change to this code may need to revisit other places in - // the code where this idiom is used, in particular the - // orderAccess code. - lock(); - addl(new CiAddress(CiKind.Word, RSP, 0), 0); // Assert the lock# signal here - } - } - } - - @Override - public final void patchJumpTarget(int branch, int branchTarget) { - int op = codeBuffer.getByte(branch); - assert op == 0xE8 // call - || op == 0x00 // jump table entry - || op == 0xE9 // jmp - || op == 0xEB // short jmp - || (op & 0xF0) == 0x70 // short jcc - || op == 0x0F && (codeBuffer.getByte(branch + 1) & 0xF0) == 0x80 // jcc - : "Invalid opcode at patch point branch=" + branch + ", branchTarget=" + branchTarget + ", op=" + op; - - if (op == 0x00) { - int offsetToJumpTableBase = codeBuffer.getShort(branch + 1); - int jumpTableBase = branch - offsetToJumpTableBase; - int imm32 = branchTarget - jumpTableBase; - codeBuffer.emitInt(imm32, branch); - } else if (op == 0xEB || (op & 0xF0) == 0x70) { - - // short offset operators (jmp and jcc) - int imm8 = branchTarget - (branch + 2); - codeBuffer.emitByte(imm8, branch + 1); - - } else { - - int off = 1; - if (op == 0x0F) { - off = 2; - } - - int imm32 = branchTarget - (branch + 4 + off); - codeBuffer.emitInt(imm32, branch + off); - } - } - - @Override - public void nullCheck(CiRegister r) { - testl(AMD64.rax, new CiAddress(CiKind.Word, r.asValue(Word), 0)); - } - - @Override - public void align(int modulus) { - if (codeBuffer.position() % modulus != 0) { - nop(modulus - (codeBuffer.position() % modulus)); - } - } -} diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64Backend.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64Backend.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64Backend.java Fri May 13 17:09:20 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, 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 @@ -24,8 +24,9 @@ import static com.sun.c1x.C1XCompilation.*; +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; import com.sun.c1x.*; -import com.sun.c1x.asm.*; import com.sun.c1x.gen.*; import com.sun.c1x.globalstub.*; import com.sun.c1x.lir.*; @@ -69,7 +70,7 @@ } @Override public AbstractAssembler newAssembler(RiRegisterConfig registerConfig) { - return new AMD64MacroAssembler.WithCompiler(compiler, registerConfig); + return new AMD64MacroAssembler(compiler.target, registerConfig); } @Override diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64GlobalStubEmitter.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64GlobalStubEmitter.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64GlobalStubEmitter.java Fri May 13 17:09:20 2011 -0700 @@ -26,10 +26,12 @@ import java.util.*; +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.asm.target.amd64.AMD64Assembler.*; import com.sun.c1x.*; import com.sun.c1x.asm.*; import com.sun.c1x.globalstub.*; -import com.sun.c1x.target.amd64.AMD64Assembler.ConditionFlag; import com.sun.cri.ci.*; import com.sun.cri.ci.CiRegister.RegisterFlag; import com.sun.cri.ri.*; @@ -52,6 +54,7 @@ private static final CiRegister negateArgument = AMD64.xmm0; private static final CiRegister negateTemp = AMD64.xmm1; + private TargetMethodAssembler tasm; private AMD64MacroAssembler asm; private final CiTarget target; private int argsSize; @@ -73,7 +76,8 @@ } private void reset(CiKind resultKind, CiKind[] argTypes) { - asm = new AMD64MacroAssembler.WithCompiler(compiler, compiler.globalStubRegisterConfig); + asm = new AMD64MacroAssembler(compiler.target, compiler.globalStubRegisterConfig); + tasm = new TargetMethodAssembler(asm); saveSize = 0; argsSize = 0; argOffsets = new int[argTypes.length]; @@ -98,7 +102,7 @@ reset(runtimeCall.resultKind, runtimeCall.arguments); emitStandardForward(null, runtimeCall); String name = "stub-" + runtimeCall; - CiTargetMethod targetMethod = asm.finishTargetMethod(name, runtime, registerRestoreEpilogueOffset, true); + CiTargetMethod targetMethod = tasm.finishTargetMethod(name, runtime, registerRestoreEpilogueOffset, true); Object stubObject = runtime.registerGlobalStub(targetMethod, name); return new GlobalStub(null, runtimeCall.resultKind, stubObject, argsSize, argOffsets, resultOffset); } @@ -128,7 +132,7 @@ } String name = "stub-" + stub; - CiTargetMethod targetMethod = asm.finishTargetMethod(name, runtime, registerRestoreEpilogueOffset, true); + CiTargetMethod targetMethod = tasm.finishTargetMethod(name, runtime, registerRestoreEpilogueOffset, true); Object stubObject = runtime.registerGlobalStub(targetMethod, name); return new GlobalStub(stub, stub.resultKind, stubObject, argsSize, argOffsets, resultOffset); } @@ -171,6 +175,7 @@ compilation.frameMap().setFrameSize(frameSize()); AMD64LIRAssembler assembler = new AMD64LIRAssembler(compilation); asm = assembler.masm; + tasm = assembler.tasm; ArrayList allocatableRegisters = new ArrayList(Arrays.asList(compiler.globalStubRegisterConfig.getCategorizedAllocatableRegisters().get(RegisterFlag.CPU))); for (XirTemp t : template.temps) { @@ -237,7 +242,7 @@ assert template.marks.length == 0 : "marks not supported in global stubs"; assembler.emitXirInstructions(null, template.fastPath, labels, operands, null); epilogue(); - CiTargetMethod targetMethod = asm.finishTargetMethod(template.name, runtime, registerRestoreEpilogueOffset, true); + CiTargetMethod targetMethod = tasm.finishTargetMethod(template.name, runtime, registerRestoreEpilogueOffset, true); Object stubObject = runtime.registerGlobalStub(targetMethod, template.name); return new GlobalStub(null, template.resultOperand.kind, stubObject, argsSize, argOffsets, resultOffset); } @@ -263,14 +268,14 @@ private void emitDNEG() { negatePrologue(); - asm.movsd(negateTemp, asm.recordDataReferenceInCode(CiConstant.forLong(DoubleSignFlip))); + asm.movsd(negateTemp, tasm.recordDataReferenceInCode(CiConstant.forLong(DoubleSignFlip))); asm.xorpd(negateArgument, negateTemp); negateEpilogue(); } private void emitFNEG() { negatePrologue(); - asm.movsd(negateTemp, asm.recordDataReferenceInCode(CiConstant.forLong(FloatSignFlip))); + asm.movsd(negateTemp, tasm.recordDataReferenceInCode(CiConstant.forLong(FloatSignFlip))); asm.xorps(negateArgument, negateTemp); negateEpilogue(); } @@ -304,9 +309,9 @@ private void emitCOMISSD(boolean isDouble, boolean isInt) { convertPrologue(); if (isDouble) { - asm.ucomisd(convertArgument, asm.recordDataReferenceInCode(CiConstant.DOUBLE_0)); + asm.ucomisd(convertArgument, tasm.recordDataReferenceInCode(CiConstant.DOUBLE_0)); } else { - asm.ucomiss(convertArgument, asm.recordDataReferenceInCode(CiConstant.FLOAT_0)); + asm.ucomiss(convertArgument, tasm.recordDataReferenceInCode(CiConstant.FLOAT_0)); } Label nan = new Label(); Label ret = new Label(); @@ -372,7 +377,7 @@ index++; } - asm.setFrameSize(frameSize()); + tasm.setFrameSize(frameSize()); this.savedAllRegisters = false; } @@ -385,7 +390,7 @@ asm.nop(entryCodeOffset); } asm.subq(AMD64.rsp, frameSize()); - asm.setFrameSize(frameSize()); + tasm.setFrameSize(frameSize()); int frameToCSA = 0; asm.save(csa, frameToCSA); this.savedAllRegisters = true; @@ -426,7 +431,10 @@ } // Call to the runtime - asm.directCall(call, null); + int before = asm.codeBuffer.position(); + asm.call(); + int after = asm.codeBuffer.position(); + tasm.recordDirectCall(before, after, call, null); if (call.resultKind != CiKind.Void) { CiRegister returnRegister = compiler.globalStubRegisterConfig.getReturnRegister(call.resultKind); diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRAssembler.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRAssembler.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRAssembler.java Fri May 13 17:09:20 2011 -0700 @@ -31,30 +31,25 @@ import java.util.*; +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.asm.target.amd64.AMD64Assembler.*; import com.sun.c1x.*; -import com.sun.c1x.asm.*; import com.sun.c1x.debug.*; -import com.sun.c1x.gen.LIRGenerator.DeoptimizationStub; +import com.sun.c1x.gen.LIRGenerator.*; +import com.sun.c1x.globalstub.*; import com.sun.c1x.ir.*; -import com.sun.c1x.lir.FrameMap.StackBlock; import com.sun.c1x.lir.*; -import com.sun.c1x.target.amd64.AMD64Assembler.ConditionFlag; +import com.sun.c1x.lir.FrameMap.*; import com.sun.c1x.util.*; import com.sun.cri.ci.*; -import com.sun.cri.ci.CiAddress.Scale; -import com.sun.cri.ci.CiTargetMethod.JumpTable; -import com.sun.cri.ci.CiTargetMethod.Mark; +import com.sun.cri.ci.CiAddress.*; +import com.sun.cri.ci.CiTargetMethod.*; import com.sun.cri.xir.*; -import com.sun.cri.xir.CiXirAssembler.RuntimeCallInformation; -import com.sun.cri.xir.CiXirAssembler.XirInstruction; -import com.sun.cri.xir.CiXirAssembler.XirLabel; -import com.sun.cri.xir.CiXirAssembler.XirMark; +import com.sun.cri.xir.CiXirAssembler.*; /** * This class implements the x86-specific code generation for LIR. - * - * @author Thomas Wuerthinger - * @author Ben L. Titzer */ public final class AMD64LIRAssembler extends LIRAssembler { @@ -71,7 +66,7 @@ public AMD64LIRAssembler(C1XCompilation compilation) { super(compilation); - masm = (AMD64MacroAssembler) compilation.masm(); + masm = (AMD64MacroAssembler) asm; target = compilation.target; wordSize = target.wordSize; rscratch1 = compilation.registerConfig.getScratchRegister(); @@ -103,9 +98,9 @@ @Override protected void emitHere(CiValue dst, LIRDebugInfo info, boolean infoOnly) { - masm.recordSafepoint(codePos(), info); + tasm.recordSafepoint(codePos(), info); if (!infoOnly) { - masm.codeBuffer.mark(); + masm.codeBuffer.putMark(); masm.leaq(dst.asRegister(), new CiAddress(CiKind.Word, InstructionRelative.asValue(), 0)); } } @@ -163,10 +158,10 @@ if (constant.isNull()) { masm.movq(dst, 0x0L); } else if (target.inlineObjects) { - masm.recordDataReferenceInCode(constant); + tasm.recordDataReferenceInCode(constant); masm.movq(dst, 0xDEADDEADDEADDEADL); } else { - masm.movq(dst, masm.recordDataReferenceInCode(constant)); + masm.movq(dst, tasm.recordDataReferenceInCode(constant)); } } @@ -181,7 +176,7 @@ if (constant == 0.0f) { masm.xorps(dst, dst); } else { - masm.movflt(dst, masm.recordDataReferenceInCode(CiConstant.forFloat(constant))); + masm.movflt(dst, tasm.recordDataReferenceInCode(CiConstant.forFloat(constant))); } } @@ -189,7 +184,7 @@ if (constant == 0.0f) { masm.xorpd(dst, dst); } else { - masm.movdbl(dst, masm.recordDataReferenceInCode(CiConstant.forDouble(constant))); + masm.movdbl(dst, tasm.recordDataReferenceInCode(CiConstant.forDouble(constant))); } } @@ -199,6 +194,7 @@ assert dest.isRegister(); CiConstant c = (CiConstant) src; + // Checkstyle: off switch (c.kind) { case Boolean : case Byte : @@ -213,6 +209,7 @@ case Double : const2reg(asXmmDoubleReg(dest), c.asDouble()); break; default : throw Util.shouldNotReachHere(); } + // Checkstyle: on } @Override @@ -222,6 +219,7 @@ CiStackSlot slot = (CiStackSlot) dst; CiConstant c = (CiConstant) src; + // Checkstyle: off switch (c.kind) { case Boolean : case Byte : @@ -230,11 +228,12 @@ case Jsr : case Int : masm.movl(frameMap.toStackAddress(slot), c.asInt()); break; case Float : masm.movl(frameMap.toStackAddress(slot), floatToRawIntBits(c.asFloat())); break; - case Object : masm.movoop(frameMap.toStackAddress(slot), c); break; + case Object : movoop(frameMap.toStackAddress(slot), c); break; case Long : masm.mov64(frameMap.toStackAddress(slot), c.asLong()); break; case Double : masm.mov64(frameMap.toStackAddress(slot), doubleToRawLongBits(c.asDouble())); break; default : throw Util.shouldNotReachHere("Unknown constant kind for const2stack: " + c.kind); } + // Checkstyle: on } @Override @@ -245,6 +244,7 @@ CiAddress addr = asAddress(dst); int nullCheckHere = codePos(); + // Checkstyle: off switch (kind) { case Boolean : case Byte : masm.movb(addr, constant.asInt() & 0xFF); break; @@ -253,7 +253,7 @@ case Jsr : case Int : masm.movl(addr, constant.asInt()); break; case Float : masm.movl(addr, floatToRawIntBits(constant.asFloat())); break; - case Object : masm.movoop(addr, constant); break; + case Object : movoop(addr, constant); break; case Word: case Long : masm.movq(rscratch1, constant.asLong()); nullCheckHere = codePos(); @@ -263,9 +263,10 @@ masm.movq(addr, rscratch1); break; default : throw Util.shouldNotReachHere(); } + // Checkstyle: on if (info != null) { - asm.recordImplicitException(nullCheckHere, info); + tasm.recordImplicitException(nullCheckHere, info); } } @@ -287,8 +288,9 @@ protected void reg2stack(CiValue src, CiValue dst, CiKind kind) { assert src.isRegister(); assert dst.isStackSlot(); - CiAddress addr = frameMap.toStackAddress(((CiStackSlot) dst)); + CiAddress addr = frameMap.toStackAddress((CiStackSlot) dst); + // Checkstyle: off switch (src.kind) { case Boolean : case Byte : @@ -303,6 +305,7 @@ case Double : masm.movsd(addr, asXmmDoubleReg(src)); break; default : throw Util.shouldNotReachHere(); } + // Checkstyle: on } @Override @@ -310,9 +313,10 @@ CiAddress toAddr = (CiAddress) dest; if (info != null) { - asm.recordImplicitException(codePos(), info); + tasm.recordImplicitException(codePos(), info); } + // Checkstyle: off switch (kind) { case Float : masm.movflt(toAddr, asXmmFloatReg(src)); break; case Double : masm.movsd(toAddr, asXmmDoubleReg(src)); break; @@ -327,6 +331,7 @@ case Boolean : masm.movb(toAddr, src.asRegister()); break; default : throw Util.shouldNotReachHere(); } + // Checkstyle: on } private static CiRegister asXmmFloatReg(CiValue src) { @@ -341,8 +346,9 @@ assert src.isStackSlot(); assert dest.isRegister(); - CiAddress addr = frameMap.toStackAddress(((CiStackSlot) src)); + CiAddress addr = frameMap.toStackAddress((CiStackSlot) src); + // Checkstyle: off switch (dest.kind) { case Boolean : case Byte : @@ -357,38 +363,39 @@ case Double : masm.movdbl(asXmmDoubleReg(dest), addr); break; default : throw Util.shouldNotReachHere(); } + // Checkstyle: on } @Override protected void mem2mem(CiValue src, CiValue dest, CiKind kind) { if (dest.kind.isInt()) { - masm.pushl(((CiAddress) src)); - masm.popl(((CiAddress) dest)); + masm.pushl((CiAddress) src); + masm.popl((CiAddress) dest); } else { - masm.pushptr(((CiAddress) src)); - masm.popptr(((CiAddress) dest)); + masm.pushptr((CiAddress) src); + masm.popptr((CiAddress) dest); } } @Override protected void mem2stack(CiValue src, CiValue dest, CiKind kind) { if (dest.kind.isInt()) { - masm.pushl(((CiAddress) src)); - masm.popl(frameMap.toStackAddress(((CiStackSlot) dest))); + masm.pushl((CiAddress) src); + masm.popl(frameMap.toStackAddress((CiStackSlot) dest)); } else { - masm.pushptr(((CiAddress) src)); - masm.popptr(frameMap.toStackAddress(((CiStackSlot) dest))); + masm.pushptr((CiAddress) src); + masm.popptr(frameMap.toStackAddress((CiStackSlot) dest)); } } @Override protected void stack2stack(CiValue src, CiValue dest, CiKind kind) { if (src.kind.isInt()) { - masm.pushl(frameMap.toStackAddress(((CiStackSlot) src))); - masm.popl(frameMap.toStackAddress(((CiStackSlot) dest))); + masm.pushl(frameMap.toStackAddress((CiStackSlot) src)); + masm.popl(frameMap.toStackAddress((CiStackSlot) dest)); } else { - masm.pushptr(frameMap.toStackAddress(((CiStackSlot) src))); - masm.popptr(frameMap.toStackAddress(((CiStackSlot) dest))); + masm.pushptr(frameMap.toStackAddress((CiStackSlot) src)); + masm.popptr(frameMap.toStackAddress((CiStackSlot) dest)); } } @@ -399,9 +406,10 @@ CiAddress addr = (CiAddress) src; if (info != null) { - asm.recordImplicitException(codePos(), info); + tasm.recordImplicitException(codePos(), info); } + // Checkstyle: off switch (kind) { case Float : masm.movflt(asXmmFloatReg(dest), addr); break; case Double : masm.movdbl(asXmmDoubleReg(dest), addr); break; @@ -415,21 +423,25 @@ case Short : masm.movswl(dest.asRegister(), addr); break; default : throw Util.shouldNotReachHere(); } + // Checkstyle: on } @Override protected void emitReadPrefetch(CiValue src) { CiAddress addr = (CiAddress) src; + // Checkstyle: off switch (C1XOptions.ReadPrefetchInstr) { case 0 : masm.prefetchnta(addr); break; case 1 : masm.prefetcht0(addr); break; case 2 : masm.prefetcht2(addr); break; default : throw Util.shouldNotReachHere(); } + // Checkstyle: on } @Override protected void emitOp3(LIROp3 op) { + // Checkstyle: off switch (op.code) { case Idiv : case Irem : arithmeticIdiv(op.code, op.opr1(), op.opr2(), op.result(), op.info); break; @@ -441,6 +453,7 @@ case Wremi : arithmeticWdiv(op.code, op.opr1(), op.opr2(), op.result(), op.info); break; default : throw Util.shouldNotReachHere(); } + // Checkstyle: on } private boolean assertEmitBranch(LIRBranch op) { @@ -487,7 +500,7 @@ // Set scratch to address of jump table int leaPos = buf.position(); - buf.mark(); + buf.putMark(); masm.leaq(rscratch1, new CiAddress(CiKind.Word, InstructionRelative.asValue(), 0)); // Load jump table entry into scratch and jump to it @@ -503,7 +516,7 @@ // Patch LEA instruction above now that we know the position of the jump table int jumpTablePos = buf.position(); buf.setPosition(leaPos); - buf.mark(); + buf.putMark(); masm.leaq(rscratch1, new CiAddress(CiKind.Word, InstructionRelative.asValue(), jumpTablePos - leaPos)); buf.setPosition(jumpTablePos); @@ -524,7 +537,7 @@ } JumpTable jt = new JumpTable(jumpTablePos, op.lowKey, highKey, 4); - masm.targetMethod.addAnnotation(jt); + tasm.targetMethod.addAnnotation(jt); } @Override @@ -535,8 +548,8 @@ if (op.cond() == Condition.TRUE) { if (op.info != null) { int codePos = codePos(); - if (codePos > asm.lastSafepointPos()) { - asm.recordImplicitException(codePos, op.info); + if (codePos > tasm.lastSafepointPos()) { + tasm.recordImplicitException(codePos, op.info); } } masm.jmp(op.label()); @@ -545,6 +558,7 @@ if (op.code == LIROpcode.CondFloatBranch) { assert op.unorderedBlock() != null : "must have unordered successor"; masm.jcc(ConditionFlag.parity, op.unorderedBlock().label()); + // Checkstyle: off switch (op.cond()) { case EQ : acond = ConditionFlag.equal; break; case NE : acond = ConditionFlag.notEqual; break; @@ -566,8 +580,9 @@ case AE : acond = ConditionFlag.aboveEqual; break; default : throw Util.shouldNotReachHere(); } + // Checkstyle: on } - masm.jcc(acond, (op.label())); + masm.jcc(acond, op.label()); } } @@ -622,7 +637,7 @@ masm.cvttss2sil(dest.asRegister(), srcRegister); masm.cmp32(dest.asRegister(), Integer.MIN_VALUE); masm.jcc(ConditionFlag.notEqual, endLabel); - masm.callGlobalStub(op.globalStub, null, dest.asRegister(), src); + callGlobalStub(op.globalStub, null, dest.asRegister(), src); // cannot cause an exception masm.bind(endLabel); break; @@ -632,7 +647,7 @@ masm.cvttsd2sil(dest.asRegister(), asXmmDoubleReg(src)); masm.cmp32(dest.asRegister(), Integer.MIN_VALUE); masm.jcc(ConditionFlag.notEqual, endLabel); - masm.callGlobalStub(op.globalStub, null, dest.asRegister(), src); + callGlobalStub(op.globalStub, null, dest.asRegister(), src); // cannot cause an exception masm.bind(endLabel); break; @@ -651,7 +666,7 @@ masm.movq(rscratch1, java.lang.Long.MIN_VALUE); masm.cmpq(dest.asRegister(), rscratch1); masm.jcc(ConditionFlag.notEqual, endLabel); - masm.callGlobalStub(op.globalStub, null, dest.asRegister(), src); + callGlobalStub(op.globalStub, null, dest.asRegister(), src); masm.bind(endLabel); break; } @@ -662,7 +677,7 @@ masm.movq(rscratch1, java.lang.Long.MIN_VALUE); masm.cmpq(dest.asRegister(), rscratch1); masm.jcc(ConditionFlag.notEqual, endLabel); - masm.callGlobalStub(op.globalStub, null, dest.asRegister(), src); + callGlobalStub(op.globalStub, null, dest.asRegister(), src); masm.bind(endLabel); break; } @@ -824,6 +839,7 @@ assert left.equals(dest) : "left and dest must be equal"; CiKind kind = left.kind; + // Checkstyle: off if (left.isRegister()) { CiRegister lreg = left.asRegister(); @@ -891,7 +907,7 @@ raddr = frameMap.toStackAddress(((CiStackSlot) right)); } else { assert right.isConstant(); - raddr = masm.recordDataReferenceInCode(CiConstant.forFloat(((CiConstant) right).asFloat())); + raddr = tasm.recordDataReferenceInCode(CiConstant.forFloat(((CiConstant) right).asFloat())); } switch (code) { case Add : masm.addss(lreg, raddr); break; @@ -907,7 +923,7 @@ raddr = frameMap.toStackAddress(((CiStackSlot) right)); } else { assert right.isConstant(); - raddr = masm.recordDataReferenceInCode(CiConstant.forDouble(((CiConstant) right).asDouble())); + raddr = tasm.recordDataReferenceInCode(CiConstant.forDouble(((CiConstant) right).asDouble())); } switch (code) { case Add : masm.addsd(lreg, raddr); break; @@ -930,7 +946,7 @@ // register - constant assert right.isConstant(); long c = ((CiConstant) right).asLong(); - if (Util.isInt(c)) { + if (NumUtil.isInt(c)) { switch (code) { case Add : masm.addq(lreg, (int) c); break; case Sub : masm.subq(lreg, (int) c); break; @@ -968,6 +984,7 @@ } } } + // Checkstyle: on } @Override @@ -978,7 +995,7 @@ if (asXmmDoubleReg(dest) != asXmmDoubleReg(value)) { masm.movdbl(asXmmDoubleReg(dest), asXmmDoubleReg(value)); } - masm.andpd(asXmmDoubleReg(dest), masm.recordDataReferenceInCode(CiConstant.forLong(DoubleSignMask))); + masm.andpd(asXmmDoubleReg(dest), tasm.recordDataReferenceInCode(CiConstant.forLong(DoubleSignMask))); break; case Sqrt: @@ -993,6 +1010,7 @@ @Override protected void emitLogicOp(LIROpcode code, CiValue left, CiValue right, CiValue dst) { assert left.isRegister(); + // Checkstyle: off if (left.kind.isInt()) { CiRegister reg = left.asRegister(); if (right.isConstant()) { @@ -1047,6 +1065,7 @@ CiRegister dreg = dst.asRegister(); moveRegs(lreg, dreg); } + // Checkstyle: on } void arithmeticIdiv(LIROpcode code, CiValue left, CiValue right, CiValue result, LIRDebugInfo info) { @@ -1113,7 +1132,7 @@ // normal and special case exit masm.bind(continuation); - asm.recordImplicitException(offset, info); + tasm.recordImplicitException(offset, info); if (code == LIROpcode.Irem) { moveRegs(AMD64.rdx, dreg); // result is in rdx } else { @@ -1162,7 +1181,7 @@ // normal and special case exit masm.bind(continuation); - asm.recordImplicitException(offset, info); + tasm.recordImplicitException(offset, info); if (code == LIROpcode.Lrem) { moveRegs(AMD64.rdx, dreg); } else { @@ -1195,7 +1214,7 @@ int offset = masm.codeBuffer.position(); masm.divq(rreg); - asm.recordImplicitException(offset, info); + tasm.recordImplicitException(offset, info); if (code == LIROpcode.Wrem || code == LIROpcode.Wremi) { moveRegs(AMD64.rdx, dreg); } else { @@ -1206,6 +1225,7 @@ @Override protected void emitCompare(Condition condition, CiValue opr1, CiValue opr2, LIROp2 op) { + // Checkstyle: off assert Util.archKindsEqual(opr1.kind.stackKind(), opr2.kind.stackKind()) || (opr1.kind == CiKind.Word && opr2.kind == CiKind.Int) : "nonmatching stack kinds (" + condition + "): " + opr1.kind.stackKind() + "==" + opr2.kind.stackKind(); if (opr1.isConstant()) { @@ -1257,8 +1277,8 @@ case Char : case Short : case Int : masm.cmpl(reg1, c.asInt()); break; - case Float : masm.ucomiss(reg1, masm.recordDataReferenceInCode(CiConstant.forFloat(((CiConstant) opr2).asFloat()))); break; - case Double : masm.ucomisd(reg1, masm.recordDataReferenceInCode(CiConstant.forDouble(((CiConstant) opr2).asDouble()))); break; + case Float : masm.ucomiss(reg1, tasm.recordDataReferenceInCode(CiConstant.forFloat(((CiConstant) opr2).asFloat()))); break; + case Double : masm.ucomisd(reg1, tasm.recordDataReferenceInCode(CiConstant.forDouble(((CiConstant) opr2).asDouble()))); break; case Long : case Word : { if (c.asLong() == 0) { @@ -1271,7 +1291,7 @@ break; } case Object : { - masm.movoop(rscratch1, c); + movoop(rscratch1, c); masm.cmpq(reg1, rscratch1); break; } @@ -1292,7 +1312,7 @@ case Short : case Int : masm.cmpl(left, right.asInt()); break; case Long : - case Word : assert Util.isInt(right.asLong()); + case Word : assert NumUtil.isInt(right.asLong()); masm.cmpq(left, right.asInt()); break; case Object : assert right.isNull(); masm.cmpq(left, 0); break; @@ -1305,6 +1325,7 @@ } else { throw Util.shouldNotReachHere(opr1.toString() + " opr2 = " + opr2); } + // Checkstyle: on } @Override @@ -1359,12 +1380,12 @@ } else { moveOp(callAddress, reg.asValue(callAddress.kind), callAddress.kind, null, false); } - masm.indirectCall(reg, target, info); + indirectCall(reg, target, info); } @Override protected void emitDirectCall(Object target, LIRDebugInfo info) { - masm.directCall(target, info); + directCall(target, info); } @Override @@ -1375,13 +1396,13 @@ } else { moveOp(callAddress, reg.asValue(callAddress.kind), callAddress.kind, null, false); } - masm.nativeCall(reg, symbol, info); + indirectCall(reg, symbol, info); } @Override protected void emitTemplateCall(CiValue address) { if (address == null) { - masm.directCall(null, null); + directCall(null, null); return; } @@ -1391,7 +1412,7 @@ } else { moveOp(address, reg.asValue(address.kind), address.kind, null, false); } - masm.indirectCall(reg, null, null); + indirectCall(reg, null, null); } @Override @@ -1399,9 +1420,9 @@ // exception object is not added to oop map by LinearScan // (LinearScan assumes that no oops are in fixed registers) // info.addRegisterOop(exceptionOop); - masm.directCall(CiRuntimeCall.HandleException, info); + directCall(CiRuntimeCall.HandleException, info); // enough room for two byte trap - masm.shouldNotReachHere(); + shouldNotReachHere(); } private void emitXIRShiftOp(LIROpcode code, CiValue left, CiValue count, CiValue dest) { @@ -1427,6 +1448,7 @@ CiRegister value = left.asRegister(); assert value != SHIFTCount : "left cannot be ECX"; + // Checkstyle: off switch (code) { case Shl : masm.shll(value); break; case Shr : masm.sarl(value); break; @@ -1443,6 +1465,7 @@ case Ushr : masm.shrq(lreg); break; default : throw Util.shouldNotReachHere(); } + // Checkstyle: on } } @@ -1455,6 +1478,7 @@ count = count & 0x1F; // Java spec moveRegs(left.asRegister(), value); + // Checkstyle: off switch (code) { case Shl : masm.shll(value, count); break; case Shr : masm.sarl(value, count); break; @@ -1474,6 +1498,7 @@ case Ushr : masm.shrq(value, count); break; default : throw Util.shouldNotReachHere(); } + // Checkstyle: on } } @@ -1519,14 +1544,14 @@ if (asXmmFloatReg(left) != asXmmFloatReg(dest)) { masm.movflt(asXmmFloatReg(dest), asXmmFloatReg(left)); } - masm.callGlobalStub(op.globalStub, null, asXmmFloatReg(dest), dest); + callGlobalStub(op.globalStub, null, asXmmFloatReg(dest), dest); } else if (dest.kind.isDouble()) { if (asXmmDoubleReg(left) != asXmmDoubleReg(dest)) { masm.movdbl(asXmmDoubleReg(dest), asXmmDoubleReg(left)); } - masm.callGlobalStub(op.globalStub, null, asXmmDoubleReg(dest), dest); + callGlobalStub(op.globalStub, null, asXmmDoubleReg(dest), dest); } else { CiRegister lreg = left.asRegister(); CiRegister dreg = dest.asRegister(); @@ -1542,29 +1567,39 @@ } @Override + protected void emitNullCheck(CiValue src, LIRDebugInfo info) { + assert src.isRegister(); + if (C1XOptions.NullCheckUniquePc) { + masm.nop(); + } + tasm.recordImplicitException(codePos(), info); + masm.nullCheck(src.asRegister()); + } + + @Override protected void emitVolatileMove(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info) { assert kind == CiKind.Long : "only for volatile long fields"; if (info != null) { - asm.recordImplicitException(codePos(), info); + tasm.recordImplicitException(codePos(), info); } if (src.kind.isDouble()) { if (dest.isRegister()) { masm.movdq(dest.asRegister(), asXmmDoubleReg(src)); } else if (dest.isStackSlot()) { - masm.movsd(frameMap.toStackAddress(((CiStackSlot) dest)), asXmmDoubleReg(src)); + masm.movsd(frameMap.toStackAddress((CiStackSlot) dest), asXmmDoubleReg(src)); } else { assert dest.isAddress(); - masm.movsd(((CiAddress) dest), asXmmDoubleReg(src)); + masm.movsd((CiAddress) dest, asXmmDoubleReg(src)); } } else { assert dest.kind.isDouble(); if (src.isStackSlot()) { - masm.movdbl(asXmmDoubleReg(dest), frameMap.toStackAddress(((CiStackSlot) src))); + masm.movdbl(asXmmDoubleReg(dest), frameMap.toStackAddress((CiStackSlot) src)); } else { assert src.isAddress(); - masm.movdbl(asXmmDoubleReg(dest), ((CiAddress) src)); + masm.movdbl(asXmmDoubleReg(dest), (CiAddress) src); } } } @@ -1681,7 +1716,7 @@ case PointerLoad: { if ((Boolean) inst.extra && info != null) { - asm.recordImplicitException(codePos(), info); + tasm.recordImplicitException(codePos(), info); } CiValue result = operands[inst.result.index]; @@ -1693,7 +1728,7 @@ case PointerStore: { if ((Boolean) inst.extra && info != null) { - asm.recordImplicitException(codePos(), info); + tasm.recordImplicitException(codePos(), info); } CiValue value = operands[inst.y().index]; @@ -1726,7 +1761,7 @@ src = new CiAddress(inst.kind, pointer, index, scale, displacement); } - moveOp(src, result, inst.kind, (canTrap) ? info : null, false); + moveOp(src, result, inst.kind, canTrap ? info : null, false); break; } @@ -1770,7 +1805,7 @@ dst = new CiAddress(inst.kind, pointer, index, scale, displacement); } - moveOp(value, dst, inst.kind, (canTrap) ? info : null, false); + moveOp(value, dst, inst.kind, canTrap ? info : null, false); break; } @@ -1791,7 +1826,7 @@ case PointerCAS: if ((Boolean) inst.extra && info != null) { - asm.recordImplicitException(codePos(), info); + tasm.recordImplicitException(codePos(), info); } assert operands[inst.x().index].asRegister().equals(AMD64.rax) : "wrong input x: " + operands[inst.x().index]; @@ -1813,7 +1848,7 @@ for (int i = 0; i < args.length; i++) { args[i] = operands[inst.arguments[i].index]; } - masm.callGlobalStub(stubId, info, result, args); + callGlobalStub(stubId, info, result, args); break; } case CallRuntime: { @@ -1832,7 +1867,7 @@ } RuntimeCallInformation runtimeCallInformation = (RuntimeCallInformation) inst.extra; - masm.directCall(runtimeCallInformation.target, (runtimeCallInformation.useInfoAfter) ? infoAfter : info); + directCall(runtimeCallInformation.target, (runtimeCallInformation.useInfoAfter) ? infoAfter : info); if (inst.result != null && inst.result.kind != CiKind.Illegal && inst.result.kind != CiKind.Void) { CiRegister returnRegister = compilation.registerConfig.getReturnRegister(inst.result.kind); @@ -1846,7 +1881,7 @@ Label label = labels[((XirLabel) inst.extra).index]; masm.jmp(label); } else { - masm.directJmp(inst.extra); + directJmp(inst.extra); } break; } @@ -1925,17 +1960,17 @@ } case Safepoint: { assert info != null : "Must have debug info in order to create a safepoint."; - asm.recordSafepoint(codePos(), info); + tasm.recordSafepoint(codePos(), info); break; } case NullCheck: { - asm.recordImplicitException(codePos(), info); + tasm.recordImplicitException(codePos(), info); CiValue pointer = operands[inst.x().index]; - asm.nullCheck(pointer.asRegister()); + masm.nullCheck(pointer.asRegister()); break; } case Align: { - asm.align((Integer) inst.extra); + masm.align((Integer) inst.extra); break; } case StackOverflowCheck: { @@ -2002,7 +2037,7 @@ references[i] = marks.get(xmark.references[i]); assert references[i] != null; } - Mark mark = asm.recordMark(xmark.id, references); + Mark mark = tasm.recordMark(xmark.id, references); marks.put(xmark, mark); break; } @@ -2014,15 +2049,15 @@ } case RawBytes: { for (byte b : (byte[]) inst.extra) { - masm.emitByte(b & 0xff); + masm.codeBuffer.emitByte(b & 0xff); } break; } case ShouldNotReachHere: { if (inst.extra == null) { - masm.stop("should not reach here"); + stop("should not reach here"); } else { - masm.stop("should not reach here: " + inst.extra); + stop("should not reach here: " + inst.extra); } break; } @@ -2039,7 +2074,7 @@ * a slot "up" the stack above RSP). */ private void bangStackWithOffset(int offset) { - masm.movq(new CiAddress(CiKind.Word, AMD64.RSP, (-offset)), AMD64.rax); + masm.movq(new CiAddress(CiKind.Word, AMD64.RSP, -offset), AMD64.rax); } private CiRegisterValue assureInRegister(CiValue pointer) { @@ -2063,7 +2098,128 @@ @Override public void emitDeoptizationStub(DeoptimizationStub stub) { masm.bind(stub.label); - masm.directCall(CiRuntimeCall.Deoptimize, stub.info); - masm.shouldNotReachHere(); + directCall(CiRuntimeCall.Deoptimize, stub.info); + shouldNotReachHere(); + } + + public GlobalStub lookupGlobalStub(XirTemplate template) { + return compilation.compiler.lookupGlobalStub(template); + } + + public void callGlobalStub(XirTemplate stub, LIRDebugInfo info, CiRegister result, CiValue... args) { + callGlobalStubHelper(lookupGlobalStub(stub), stub.resultOperand.kind, info, result, args); + } + + public void callGlobalStub(GlobalStub stub, LIRDebugInfo info, CiRegister result, CiValue... args) { + callGlobalStubHelper(stub, stub.resultKind, info, result, args); + } + + private void callGlobalStubHelper(GlobalStub stub, CiKind resultKind, LIRDebugInfo info, CiRegister result, CiValue... args) { + assert args.length == stub.argOffsets.length; + + for (int i = 0; i < args.length; i++) { + storeParameter(args[i], stub.argOffsets[i]); + } + + directCall(stub.stubObject, info); + + if (result != CiRegister.None) { + loadResult(result, stub.resultOffset, resultKind); + } + + // Clear out parameters + if (C1XOptions.GenAssertionCode) { + for (int i = 0; i < args.length; i++) { + masm.movptr(new CiAddress(CiKind.Word, AMD64.RSP, stub.argOffsets[i]), 0); + } + } + } + + private void loadResult(CiRegister r, int offset, CiKind kind) { + if (kind == CiKind.Int || kind == CiKind.Boolean) { + masm.movl(r, new CiAddress(CiKind.Int, AMD64.RSP, offset)); + } else if (kind == CiKind.Float) { + masm.movss(r, new CiAddress(CiKind.Float, AMD64.RSP, offset)); + } else if (kind == CiKind.Double) { + masm.movsd(r, new CiAddress(CiKind.Double, AMD64.RSP, offset)); + } else { + masm.movq(r, new CiAddress(CiKind.Word, AMD64.RSP, offset)); + } + } + + private void storeParameter(CiValue registerOrConstant, int offset) { + CiKind k = registerOrConstant.kind; + if (registerOrConstant.isConstant()) { + CiConstant c = (CiConstant) registerOrConstant; + if (c.kind == CiKind.Object) { + movoop(new CiAddress(CiKind.Word, AMD64.RSP, offset), c); + } else { + masm.movptr(new CiAddress(CiKind.Word, AMD64.RSP, offset), c.asInt()); + } + } else if (registerOrConstant.isRegister()) { + if (k.isFloat()) { + masm.movss(new CiAddress(CiKind.Float, AMD64.RSP, offset), registerOrConstant.asRegister()); + } else if (k.isDouble()) { + masm.movsd(new CiAddress(CiKind.Double, AMD64.RSP, offset), registerOrConstant.asRegister()); + } else { + masm.movq(new CiAddress(CiKind.Word, AMD64.RSP, offset), registerOrConstant.asRegister()); + } + } else { + throw new InternalError("should not reach here"); + } + } + + public void movoop(CiRegister dst, CiConstant obj) { + assert obj.kind == CiKind.Object; + if (obj.isNull()) { + masm.xorq(dst, dst); + } else { + if (target.inlineObjects) { + tasm.recordDataReferenceInCode(obj); + masm.movq(dst, 0xDEADDEADDEADDEADL); + } else { + masm.movq(dst, tasm.recordDataReferenceInCode(obj)); + } + } + } + + public void movoop(CiAddress dst, CiConstant obj) { + movoop(rscratch1, obj); + masm.movq(dst, rscratch1); + } + + public void directCall(Object target, LIRDebugInfo info) { + int before = masm.codeBuffer.position(); + masm.call(); + int after = masm.codeBuffer.position(); + tasm.recordDirectCall(before, after, target, info); + tasm.recordExceptionHandlers(after, info); + } + + public void directJmp(Object target) { + int before = masm.codeBuffer.position(); + masm.jmp(0, true); + int after = masm.codeBuffer.position(); + tasm.recordDirectCall(before, after, target, null); + } + + public void indirectCall(CiRegister dst, Object target, LIRDebugInfo info) { + int before = masm.codeBuffer.position(); + masm.call(dst); + int after = masm.codeBuffer.position(); + tasm.recordIndirectCall(before, after, target, info); + tasm.recordExceptionHandlers(after, info); + } + + protected void stop(String msg) { + if (C1XOptions.GenAssertionCode) { + // TODO: pass a pointer to the message + directCall(CiRuntimeCall.Debug, null); + masm.hlt(); + } + } + + public void shouldNotReachHere() { + stop("should not reach here"); } } diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java Fri May 13 17:09:20 2011 -0700 @@ -23,6 +23,8 @@ package com.sun.c1x.target.amd64; +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; import com.sun.c1x.*; import com.sun.c1x.gen.*; import com.sun.c1x.globalstub.*; @@ -34,9 +36,6 @@ /** * This class implements the X86-specific portion of the LIR generator. - * - * @author Thomas Wuerthinger - * @author Ben L. Titzer */ public class AMD64LIRGenerator extends LIRGenerator { @@ -74,7 +73,7 @@ @Override protected boolean canInlineAsConstant(Value v) { if (v.kind == CiKind.Long) { - if (v.isConstant() && Util.isInt(v.asConstant().asLong())) { + if (v.isConstant() && NumUtil.isInt(v.asConstant().asLong())) { return true; } return false; @@ -150,7 +149,7 @@ LIRItem left = new LIRItem(x.x(), this); LIRItem right = new LIRItem(x.y(), this); assert !left.isStack() || !right.isStack() : "can't both be memory operands"; - boolean mustLoadBoth = (x.opcode == Bytecodes.FREM || x.opcode == Bytecodes.DREM); + boolean mustLoadBoth = x.opcode == Bytecodes.FREM || x.opcode == Bytecodes.DREM; // Both are in register, swap operands such that the short-living one is on the left side. if (x.isCommutative() && left.isRegisterOrVariable() && right.isRegisterOrVariable()) { @@ -433,7 +432,7 @@ } else if (x.x().kind.isFloat() || x.x().kind.isDouble()) { CiValue reg = createResultVariable(x); int code = x.opcode; - lir.fcmp2int(left.result(), right.result(), reg, (code == Bytecodes.FCMPL || code == Bytecodes.DCMPL)); + lir.fcmp2int(left.result(), right.result(), reg, code == Bytecodes.FCMPL || code == Bytecodes.DCMPL); } else if (x.x().kind.isLong() || x.x().kind.isWord()) { CiValue reg = createResultVariable(x); lir.lcmp2int(left.result(), right.result(), reg); @@ -448,12 +447,14 @@ CiVariable result = newVariable(x.kind); // arguments of lirConvert GlobalStub globalStub = null; + // Checkstyle: off switch (x.opcode) { case Bytecodes.F2I: globalStub = stubFor(GlobalStub.Id.f2i); break; case Bytecodes.F2L: globalStub = stubFor(GlobalStub.Id.f2l); break; case Bytecodes.D2I: globalStub = stubFor(GlobalStub.Id.d2i); break; case Bytecodes.D2L: globalStub = stubFor(GlobalStub.Id.d2l); break; } + // Checkstyle: on if (globalStub != null) { // Force result to be rax to match global stubs expectation. CiValue stubResult = x.kind == CiKind.Int ? RAX_I : RAX_L; diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64MacroAssembler.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64MacroAssembler.java Fri May 13 14:03:03 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,506 +0,0 @@ -/* - * Copyright (c) 2009, 2011, 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 com.sun.c1x.target.amd64; - -import com.sun.c1x.*; -import com.sun.c1x.asm.*; -import com.sun.c1x.globalstub.*; -import com.sun.c1x.lir.*; -import com.sun.c1x.util.*; -import com.sun.cri.ci.*; -import com.sun.cri.ri.*; -import com.sun.cri.xir.*; - -/** - * This class implements the AMD64-specific portion of the macro assembler. - * - * @author Thomas Wuerthinger - * @author Ben L. Titzer - */ -public class AMD64MacroAssembler extends AMD64Assembler { - - private final CiRegister rscratch1; - - public static class WithCompiler extends AMD64MacroAssembler { - - private final C1XCompiler compiler; - - public WithCompiler(C1XCompiler compiler, RiRegisterConfig registerConfig) { - super(compiler.target, registerConfig); - this.compiler = compiler; - } - - @Override - public GlobalStub lookupGlobalStub(XirTemplate template) { - return compiler.lookupGlobalStub(template); - } - } - - public AMD64MacroAssembler(CiTarget target, RiRegisterConfig registerConfig) { - super(target, registerConfig); - this.rscratch1 = registerConfig.getScratchRegister(); - } - - /** - * Must be overridden if compiling code that makes calls to global stubs. - */ - public GlobalStub lookupGlobalStub(XirTemplate template) { - throw new IllegalArgumentException("This assembler does not support compiling calls to global stubs"); - } - - public final int callGlobalStub(XirTemplate stub, LIRDebugInfo info, CiRegister result, CiValue... args) { - assert args.length == stub.parameters.length; - return callGlobalStubHelper(lookupGlobalStub(stub), stub.resultOperand.kind, info, result, args); - } - - public final int callGlobalStub(GlobalStub stub, LIRDebugInfo info, CiRegister result, CiValue... args) { - assert args.length == stub.argOffsets.length; - return callGlobalStubHelper(stub, stub.resultKind, info, result, args); - } - - private int callGlobalStubHelper(GlobalStub stub, CiKind resultKind, LIRDebugInfo info, CiRegister result, CiValue... args) { - for (int i = 0; i < args.length; i++) { - storeParameter(args[i], stub.argOffsets[i]); - } - - int pos = directCall(stub.stubObject, info); - - if (result != CiRegister.None) { - loadResult(result, stub.resultOffset, resultKind); - } - - // Clear out parameters - if (C1XOptions.GenAssertionCode) { - for (int i = 0; i < args.length; i++) { - movptr(new CiAddress(CiKind.Word, AMD64.RSP, stub.argOffsets[i]), 0); - } - } - return pos; - } - - private void loadResult(CiRegister r, int offset, CiKind kind) { - if (kind == CiKind.Int || kind == CiKind.Boolean) { - movl(r, new CiAddress(CiKind.Int, AMD64.RSP, offset)); - } else if (kind == CiKind.Float) { - movss(r, new CiAddress(CiKind.Float, AMD64.RSP, offset)); - } else if (kind == CiKind.Double) { - movsd(r, new CiAddress(CiKind.Double, AMD64.RSP, offset)); - } else { - movq(r, new CiAddress(CiKind.Word, AMD64.RSP, offset)); - } - } - - private void storeParameter(CiValue registerOrConstant, int offset) { - CiKind k = registerOrConstant.kind; - if (registerOrConstant.isConstant()) { - CiConstant c = (CiConstant) registerOrConstant; - if (c.kind == CiKind.Object) { - movoop(new CiAddress(CiKind.Word, AMD64.RSP, offset), c); - } else { - movptr(new CiAddress(CiKind.Word, AMD64.RSP, offset), c.asInt()); - } - } else if (registerOrConstant.isRegister()) { - if (k.isFloat()) { - movss(new CiAddress(CiKind.Float, AMD64.RSP, offset), registerOrConstant.asRegister()); - } else if (k.isDouble()) { - movsd(new CiAddress(CiKind.Double, AMD64.RSP, offset), registerOrConstant.asRegister()); - } else { - movq(new CiAddress(CiKind.Word, AMD64.RSP, offset), registerOrConstant.asRegister()); - } - } else { - Util.shouldNotReachHere(); - } - } - - void movoop(CiRegister dst, CiConstant obj) { - assert obj.kind == CiKind.Object; - if (obj.isNull()) { - xorq(dst, dst); - } else { - if (target.inlineObjects) { - recordDataReferenceInCode(obj); - movq(dst, 0xDEADDEADDEADDEADL); - } else { - movq(dst, recordDataReferenceInCode(obj)); - } - } - } - - void movoop(CiAddress dst, CiConstant obj) { - movoop(rscratch1, obj); - movq(dst, rscratch1); - } - - void mov64(CiAddress dst, long src) { - movq(rscratch1, src); - movq(dst, rscratch1); - } - - void pushptr(CiAddress src) { - pushq(src); - } - - void popptr(CiAddress src) { - popq(src); - } - - void xorptr(CiRegister dst, CiRegister src) { - xorq(dst, src); - } - - void xorptr(CiRegister dst, CiAddress src) { - xorq(dst, src); - } - - // 64 bit versions - - int correctedIdivq(CiRegister reg) { - // Full implementation of Java ldiv and lrem; checks for special - // case as described in JVM spec. : p.243 & p.271. The function - // returns the (pc) offset of the idivl instruction - may be needed - // for implicit exceptions. - // - // normal case special case - // - // input : X86Register.rax: dividend minLong - // reg: divisor (may not be eax/edx) -1 - // - // output: X86Register.rax: quotient (= X86Register.rax idiv reg) minLong - // X86Register.rdx: remainder (= X86Register.rax irem reg) 0 - assert reg != AMD64.rax && reg != AMD64.rdx : "reg cannot be X86Register.rax or X86Register.rdx register"; - final long minLong = 0x8000000000000000L; - Label normalCase = new Label(); - Label specialCase = new Label(); - - // check for special case - cmpq(AMD64.rax, recordDataReferenceInCode(CiConstant.forLong(minLong))); - jcc(AMD64Assembler.ConditionFlag.notEqual, normalCase); - xorl(AMD64.rdx, AMD64.rdx); // prepare X86Register.rdx for possible special case (where - // remainder = 0) - cmpq(reg, -1); - jcc(AMD64Assembler.ConditionFlag.equal, specialCase); - - // handle normal case - bind(normalCase); - cdqq(); - int idivqOffset = codeBuffer.position(); - idivq(reg); - - // normal and special case exit - bind(specialCase); - - return idivqOffset; - } - - void decrementq(CiRegister 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 && C1XOptions.UseIncDec) { - decq(reg); - } else { - subq(reg, value); - } - } - - void incrementq(CiRegister 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 && C1XOptions.UseIncDec) { - incq(reg); - } else { - addq(reg, value); - } - } - - // These are mostly for initializing null - void movptr(CiAddress dst, int src) { - movslq(dst, src); - } - - void stop(String msg) { - if (C1XOptions.GenAssertionCode) { - // TODO: pass a pointer to the message - directCall(CiRuntimeCall.Debug, null); - hlt(); - } - } - - public final void cmp32(CiRegister src1, int imm) { - cmpl(src1, imm); - } - - public final void cmp32(CiRegister src1, CiAddress src2) { - cmpl(src1, src2); - } - - void cmpsd2int(CiRegister opr1, CiRegister opr2, CiRegister dst, boolean unorderedIsLess) { - assert opr1.isFpu() && opr2.isFpu(); - ucomisd(opr1, opr2); - - Label l = new Label(); - if (unorderedIsLess) { - movl(dst, -1); - jcc(AMD64Assembler.ConditionFlag.parity, l); - jcc(AMD64Assembler.ConditionFlag.below, l); - movl(dst, 0); - jcc(AMD64Assembler.ConditionFlag.equal, l); - incrementl(dst, 1); - } else { // unordered is greater - movl(dst, 1); - jcc(AMD64Assembler.ConditionFlag.parity, l); - jcc(AMD64Assembler.ConditionFlag.above, l); - movl(dst, 0); - jcc(AMD64Assembler.ConditionFlag.equal, l); - decrementl(dst, 1); - } - bind(l); - } - - void cmpss2int(CiRegister opr1, CiRegister opr2, CiRegister dst, boolean unorderedIsLess) { - assert opr1.isFpu(); - assert opr2.isFpu(); - ucomiss(opr1, opr2); - - Label l = new Label(); - if (unorderedIsLess) { - movl(dst, -1); - jcc(AMD64Assembler.ConditionFlag.parity, l); - jcc(AMD64Assembler.ConditionFlag.below, l); - movl(dst, 0); - jcc(AMD64Assembler.ConditionFlag.equal, l); - incrementl(dst, 1); - } else { // unordered is greater - movl(dst, 1); - jcc(AMD64Assembler.ConditionFlag.parity, l); - jcc(AMD64Assembler.ConditionFlag.above, l); - movl(dst, 0); - jcc(AMD64Assembler.ConditionFlag.equal, l); - decrementl(dst, 1); - } - bind(l); - } - - void cmpptr(CiRegister src1, CiRegister src2) { - cmpq(src1, src2); - } - - void cmpptr(CiRegister src1, CiAddress src2) { - cmpq(src1, src2); - } - - void cmpptr(CiRegister src1, int src2) { - cmpq(src1, src2); - } - - void cmpptr(CiAddress src1, int src2) { - cmpq(src1, src2); - } - - void decrementl(CiRegister 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 && C1XOptions.UseIncDec) { - decl(reg); - } else { - subl(reg, value); - } - } - - void decrementl(CiAddress 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 && C1XOptions.UseIncDec) { - decl(dst); - } else { - subl(dst, value); - } - } - - void incrementl(CiRegister 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 && C1XOptions.UseIncDec) { - incl(reg); - } else { - addl(reg, value); - } - } - - void incrementl(CiAddress 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 && C1XOptions.UseIncDec) { - incl(dst); - } else { - addl(dst, value); - } - } - - void signExtendByte(CiRegister reg) { - if (reg.isByte()) { - movsxb(reg, reg); // movsxb - } else { - shll(reg, 24); - sarl(reg, 24); - } - } - - void signExtendShort(CiRegister reg) { - movsxw(reg, reg); // movsxw - } - - // Support optimal SSE move instructions. - void movflt(CiRegister dst, CiRegister src) { - assert dst.isFpu() && src.isFpu(); - if (C1XOptions.UseXmmRegToRegMoveAll) { - movaps(dst, src); - } else { - movss(dst, src); - } - } - - void movflt(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - movss(dst, src); - } - - void movflt(CiAddress dst, CiRegister src) { - assert src.isFpu(); - movss(dst, src); - } - - void movdbl(CiRegister dst, CiRegister src) { - assert dst.isFpu() && src.isFpu(); - if (C1XOptions.UseXmmRegToRegMoveAll) { - movapd(dst, src); - } else { - movsd(dst, src); - } - } - - void movdbl(CiRegister dst, CiAddress src) { - assert dst.isFpu(); - if (C1XOptions.UseXmmLoadAndClearUpper) { - movsd(dst, src); - } else { - movlpd(dst, src); - } - } - - void xchgptr(CiRegister src1, CiRegister src2) { - xchgq(src1, src2); - } - - public void shouldNotReachHere() { - stop("should not reach here"); - } - - public void enter(short imm16, byte imm8) { - emitByte(0xC8); - // appended: - emitByte(imm16 & 0xff); - imm16 >>= 8; - emitByte(imm16 & 0xff); - emitByte(imm8); - } - - /** - * Emit code to save a given set of callee save registers to the - * {@linkplain CiCalleeSaveArea CSA} within the frame. - * @param csa the description of the CSA - * @param frameToCSA offset from the frame pointer to the CSA - */ - public void save(CiCalleeSaveArea csa, int frameToCSA) { - CiRegisterValue frame = frameRegister.asValue(); - for (CiRegister r : csa.registers) { - int offset = csa.offsetOf(r); - movq(new CiAddress(CiKind.Word, frame, frameToCSA + offset), r); - } - } - - public void restore(CiCalleeSaveArea csa, int frameToCSA) { - CiRegisterValue frame = frameRegister.asValue(); - for (CiRegister r : csa.registers) { - int offset = csa.offsetOf(r); - movq(r, new CiAddress(CiKind.Word, frame, frameToCSA + offset)); - } - } - - public void int3() { - emitByte(0xCC); - } -} diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64XirAssembler.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64XirAssembler.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64XirAssembler.java Fri May 13 17:09:20 2011 -0700 @@ -26,6 +26,7 @@ import java.util.*; +import com.oracle.max.asm.target.amd64.*; import com.sun.c1x.util.*; import com.sun.cri.ci.*; import com.sun.cri.xir.*; diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalRuntime/.classpath --- a/graal/GraalRuntime/.classpath Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalRuntime/.classpath Fri May 13 17:09:20 2011 -0700 @@ -1,10 +1,11 @@ - - - - - - - - - - + + + + + + + + + + + diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalRuntime/src/com/oracle/graal/runtime/CompilerImpl.java --- a/graal/GraalRuntime/src/com/oracle/graal/runtime/CompilerImpl.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalRuntime/src/com/oracle/graal/runtime/CompilerImpl.java Fri May 13 17:09:20 2011 -0700 @@ -28,8 +28,8 @@ import com.oracle.graal.runtime.logging.*; import com.oracle.graal.runtime.server.*; +import com.oracle.max.asm.target.amd64.*; import com.sun.c1x.*; -import com.sun.c1x.target.amd64.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; import com.sun.cri.xir.*; diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalRuntime/src/com/oracle/graal/runtime/HotSpotRegisterConfig.java --- a/graal/GraalRuntime/src/com/oracle/graal/runtime/HotSpotRegisterConfig.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalRuntime/src/com/oracle/graal/runtime/HotSpotRegisterConfig.java Fri May 13 17:09:20 2011 -0700 @@ -22,11 +22,11 @@ */ package com.oracle.graal.runtime; -import static com.sun.c1x.target.amd64.AMD64.*; +import static com.oracle.max.asm.target.amd64.AMD64.*; import java.util.*; -import com.sun.c1x.target.amd64.*; +import com.oracle.max.asm.target.amd64.*; import com.sun.c1x.util.*; import com.sun.cri.ci.*; import com.sun.cri.ci.CiCallingConvention.Type; diff -r e0e89714e2f1 -r 0ea5f12e873a graal/GraalRuntime/src/com/oracle/graal/runtime/HotSpotXirGenerator.java --- a/graal/GraalRuntime/src/com/oracle/graal/runtime/HotSpotXirGenerator.java Fri May 13 14:03:03 2011 -0700 +++ b/graal/GraalRuntime/src/com/oracle/graal/runtime/HotSpotXirGenerator.java Fri May 13 17:09:20 2011 -0700 @@ -29,17 +29,14 @@ import java.util.*; import java.util.concurrent.*; -import com.sun.c1x.target.amd64.*; -import com.sun.cri.ci.CiAddress.Scale; +import com.oracle.max.asm.target.amd64.*; +import com.sun.cri.ci.*; +import com.sun.cri.ci.CiAddress.*; import com.sun.cri.ci.CiRegister.*; -import com.sun.cri.ci.*; import com.sun.cri.ri.*; -import com.sun.cri.ri.RiType.Representation; +import com.sun.cri.ri.RiType.*; import com.sun.cri.xir.*; -import com.sun.cri.xir.CiXirAssembler.XirLabel; -import com.sun.cri.xir.CiXirAssembler.XirMark; -import com.sun.cri.xir.CiXirAssembler.XirOperand; -import com.sun.cri.xir.CiXirAssembler.XirParameter; +import com.sun.cri.xir.CiXirAssembler.*; public class HotSpotXirGenerator implements RiXirGenerator { diff -r e0e89714e2f1 -r 0ea5f12e873a src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Fri May 13 14:03:03 2011 -0700 +++ b/src/share/vm/runtime/arguments.cpp Fri May 13 17:09:20 2011 -0700 @@ -2688,6 +2688,8 @@ scp_p->add_prefix(temp); sprintf(temp, "%s/Assembler/bin", maxine_dir); scp_p->add_prefix(temp); + sprintf(temp, "%s/com.oracle.max.asm/bin", maxine_dir); + scp_p->add_prefix(temp); sprintf(temp, "%s/graal/GraalCompiler/bin", graal_dir); scp_p->add_prefix(temp); sprintf(temp, "%s/graal/GraalRuntime/bin", graal_dir);