OpenJDK / jdk / jdk
changeset 30705:9104b426a3e8
Merge
author | duke |
---|---|
date | Wed, 05 Jul 2017 20:34:59 +0200 |
parents | addfa81a8448 59bdf33a628b |
children | 803777172064 |
files | hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMap.java hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/bytecode.gif hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/link.gif hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/method.gif hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupOrganizer hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphCountGroupOrganizer.java hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/StructuredViewAction.java hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/diff.gif hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/folder.gif hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/graph.gif hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/import.gif hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/remove.gif hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/removeall.gif hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/save.gif hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/structure.gif hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupOrganizer.java hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupReceiver.java hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/META-INF/services/com.sun.hotspot.igv.filter.ScriptEngineAbstraction hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/JavaSE6ScriptEngine.java hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/NullScriptEngine.java hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ScriptEngineAbstraction.java hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/add.gif hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.gif hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.gif hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.gif hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.gif hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/up.gif hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Source.java hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/OldHierarchicalLayoutManager.java hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupReceiver hotspot/src/share/tools/IdealGraphVisualizer/README hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/build.xml hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/manifest.mf hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/build-impl.xml hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/genfiles.properties hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/project.properties hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/project.xml hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/suite.properties hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/META-INF/services/com.sun.hotspot.igv.filter.ScriptEngineAbstraction hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/Bundle.properties hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/RhinoScriptEngine.java hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/layer.xml hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupOrganizer hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/JavaGroupOrganizer.java hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/combine.filter hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/extendedColor.filter hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/linestyle.filter hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeMemory.filter hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeRootInputs.filter hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeSafepointInputs.filter hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeSelfLoops.filter hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/split.filter hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/settings.gif hotspot/src/share/tools/IdealGraphVisualizer/View/src/META-INF/services/com.sun.hotspot.igv.data.services.InputGraphProvider hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ConnectionAnchor.java hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedPanAction.java hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/FindPanel.java hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/PreferenceConstants.java hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/SlotLayout.java hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NodeFindAction.java hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/export.gif hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/overview.gif hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/search.gif hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoomin.gif hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoomout.gif hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/DiagramConnectionWidget.java hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/MultiConnectionWidget.java hotspot/test/testlibrary/com/oracle/java/testlibrary/Asserts.java hotspot/test/testlibrary/com/oracle/java/testlibrary/BuildHelper.java hotspot/test/testlibrary/com/oracle/java/testlibrary/ByteCodeLoader.java hotspot/test/testlibrary/com/oracle/java/testlibrary/DynamicVMOption.java hotspot/test/testlibrary/com/oracle/java/testlibrary/ExitCode.java hotspot/test/testlibrary/com/oracle/java/testlibrary/InMemoryJavaCompiler.java hotspot/test/testlibrary/com/oracle/java/testlibrary/InfiniteLoop.java hotspot/test/testlibrary/com/oracle/java/testlibrary/InputArguments.java hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolLauncher.java hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java hotspot/test/testlibrary/com/oracle/java/testlibrary/PerfCounter.java hotspot/test/testlibrary/com/oracle/java/testlibrary/PerfCounters.java hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java hotspot/test/testlibrary/com/oracle/java/testlibrary/TimeLimitedRunner.java hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/AndPredicate.java hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/CPUSpecificPredicate.java hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/NotPredicate.java hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/OrPredicate.java hotspot/test/testlibrary/com/oracle/java/testlibrary/dcmd/CommandExecutor.java hotspot/test/testlibrary/com/oracle/java/testlibrary/dcmd/CommandExecutorException.java hotspot/test/testlibrary/com/oracle/java/testlibrary/dcmd/FileJcmdExecutor.java hotspot/test/testlibrary/com/oracle/java/testlibrary/dcmd/JMXExecutor.java hotspot/test/testlibrary/com/oracle/java/testlibrary/dcmd/JcmdExecutor.java hotspot/test/testlibrary/com/oracle/java/testlibrary/dcmd/MainClassJcmdExecutor.java hotspot/test/testlibrary/com/oracle/java/testlibrary/dcmd/PidJcmdExecutor.java hotspot/test/testlibrary/com/oracle/java/testlibrary/dtrace/DtraceResultsAnalyzer.java hotspot/test/testlibrary/com/oracle/java/testlibrary/dtrace/DtraceRunner.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/Main.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/AbstractJavaHeapObjectVisitor.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/ArrayTypeCodes.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/HackJavaValue.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaBoolean.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaByte.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaChar.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaClass.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaDouble.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaField.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaFloat.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaHeapObject.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaHeapObjectVisitor.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaInt.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaLazyReadObject.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaLong.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaObject.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaObjectArray.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaObjectRef.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaShort.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaStatic.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaThing.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaValue.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/JavaValueArray.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/ReachableExcludes.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/ReachableExcludesImpl.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/ReachableObjects.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/ReferenceChain.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/Root.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/Snapshot.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/StackFrame.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/model/StackTrace.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/oql/OQLEngine.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/oql/OQLException.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/oql/OQLQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/oql/ObjectVisitor.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/parser/FileReadBuffer.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/parser/HprofReader.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/parser/MappedReadBuffer.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/parser/PositionDataInputStream.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/parser/PositionInputStream.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/parser/ReadBuffer.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/parser/Reader.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/AllRootsQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/FinalizerObjectsQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/FinalizerSummaryQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/HistogramQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/HttpReader.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/InstancesCountQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/InstancesQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/OQLHelp.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/OQLQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/ObjectQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/PlatformClasses.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/QueryHandler.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/QueryListener.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/ReachableQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/RefsByTypeQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/RootStackQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/server/RootsQuery.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/util/ArraySorter.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/util/Comparer.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/util/CompositeEnumeration.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/util/Misc.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/internal/util/VectorSorter.java jdk/src/jdk.dev/share/classes/com/sun/tools/hat/resources/hat.js jdk/src/jdk.dev/share/classes/com/sun/tools/hat/resources/oqlhelp.html jdk/src/jdk.dev/share/classes/com/sun/tools/hat/resources/platform_names.txt jdk/test/com/sun/management/HotSpotDiagnosticMXBean/DumpHeap.sh jdk/test/sun/tools/common/ApplicationSetup.sh jdk/test/sun/tools/common/CommonSetup.sh jdk/test/sun/tools/common/ShutdownSimpleApplication.java jdk/test/sun/tools/common/SimpleApplication.java jdk/test/sun/tools/common/SleeperApplication.java jdk/test/sun/tools/jhat/HatHeapDump1Test.java jdk/test/sun/tools/jhat/HelloWorld.java jdk/test/sun/tools/jhat/ParseTest.sh jdk/test/sun/tools/jhat/README.TXT |
diffstat | 1435 files changed, 37501 insertions(+), 31089 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags-top-repo Thu May 21 16:19:37 2015 -0700 +++ b/.hgtags-top-repo Wed Jul 05 20:34:59 2017 +0200 @@ -307,3 +307,4 @@ 105d045a69174d870b69bfe471b3f2d05a9f8ecc jdk9-b62 0b32ed628fa60e4ab99fb0b5866d648e16231f17 jdk9-b63 82cf9aab9a83e41c8194ba01af9666afdb856cbe jdk9-b64 +7c31f9d7b932f7924f1258d52885b1c7c3e078c2 jdk9-b65
--- a/common/bin/compare_exceptions.sh.incl Thu May 21 16:19:37 2015 -0700 +++ b/common/bin/compare_exceptions.sh.incl Wed Jul 05 20:34:59 2017 +0200 @@ -83,7 +83,6 @@ ./bin/jcmd ./bin/jconsole ./bin/jdb -./bin/jhat ./bin/jimage ./bin/jinfo ./bin/jjs @@ -163,7 +162,6 @@ ./bin/jcmd ./bin/jconsole ./bin/jdb -./bin/jhat ./bin/jimage ./bin/jinfo ./bin/jjs @@ -284,7 +282,6 @@ ./bin/jcmd ./bin/jconsole ./bin/jdb -./bin/jhat ./bin/jimage ./bin/jinfo ./bin/jjs @@ -420,7 +417,6 @@ ./bin/jcmd ./bin/jconsole ./bin/jdb -./bin/jhat ./bin/jimage ./bin/jinfo ./bin/jjs @@ -499,7 +495,6 @@ ./bin/jcmd.exe ./bin/jconsole.exe ./bin/jdb.exe -./bin/jhat.exe ./bin/jimage.exe ./bin/jinfo.exe ./bin/jjs.exe @@ -579,7 +574,6 @@ ./bin/jcmd ./bin/jconsole ./bin/jdb -./bin/jhat ./bin/jimage ./bin/jinfo ./bin/jjs
--- a/corba/.hgtags Thu May 21 16:19:37 2015 -0700 +++ b/corba/.hgtags Wed Jul 05 20:34:59 2017 +0200 @@ -307,3 +307,4 @@ d27f7e0a7aca129969de23e9934408a31b4abf4c jdk9-b62 0acac6937de7a0868f8c6f88b7d036d780abeee6 jdk9-b63 0a5e5a7c3539e8bde73d9fe55750e49a49cb8dac jdk9-b64 +afc1e295c4bf83f9a5dd539c29914edd4a754a3f jdk9-b65
--- a/hotspot/.hgignore Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/.hgignore Wed Jul 05 20:34:59 2017 +0200 @@ -6,5 +6,7 @@ ^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/ ^src/share/tools/IdealGraphVisualizer/build/ ^src/share/tools/IdealGraphVisualizer/dist/ +^src/share/tools/IdealGraphVisualizer/nbplatform/ +.igv.log ^.hgtip .DS_Store
--- a/hotspot/.hgtags Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/.hgtags Wed Jul 05 20:34:59 2017 +0200 @@ -467,3 +467,4 @@ 1eab877142cce6ca06e556e2ad0af688f993f00b jdk9-b62 2ac9b6b36689b50d1562627067c92d51781b5684 jdk9-b63 bf92b8db249cdfa5651ef954b6c0743a7e0ea4cd jdk9-b64 +e7ae94c4f35e940ea423fc1dd260435df34a77c0 jdk9-b65
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java Wed Jul 05 20:34:59 2017 +0200 @@ -27,9 +27,7 @@ import java.io.*; import java.awt.*; import java.awt.event.*; -import java.math.*; import javax.swing.*; -import javax.swing.tree.*; import java.util.*; import sun.jvm.hotspot.code.*; @@ -928,7 +926,7 @@ boolean shouldSkipOopMaps = false; if (curVFrame.isCompiledFrame()) { CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC()); - OopMapSet maps = cb.getOopMaps(); + ImmutableOopMapSet maps = cb.getOopMaps(); if ((maps == null) || (maps.getSize() == 0)) { shouldSkipOopMaps = true; } @@ -977,7 +975,7 @@ } while (nextVFrame != null && nextFrame.equals(curFrame)); if (shouldSkipOopMaps) { - anno = anno + "\nNOTE: null or empty OopMapSet found for this CodeBlob"; + anno = anno + "\nNOTE: null or empty ImmutableOopMapSet found for this CodeBlob"; } if (curFrame.getFP() != null) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java Wed Jul 05 20:34:59 2017 +0200 @@ -171,17 +171,17 @@ public boolean isLockedByVM() { return false; } /** OopMap for frame; can return null if none available */ - public OopMapSet getOopMaps() { + public ImmutableOopMapSet getOopMaps() { Address oopMapsAddr = oopMapsField.getValue(addr); if (oopMapsAddr == null) { return null; } - return new OopMapSet(oopMapsAddr); + return new ImmutableOopMapSet(oopMapsAddr); } // FIXME: not yet implementable - // void set_oop_maps(OopMapSet* p); + // void set_oop_maps(ImmutableOopMapSet* p); - public OopMap getOopMapForReturnAddress(Address returnAddress, boolean debugging) { + public ImmutableOopMap getOopMapForReturnAddress(Address returnAddress, boolean debugging) { Address pc = returnAddress; if (Assert.ASSERTS_ENABLED) { Assert.that(getOopMaps() != null, "nope");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMap.java Wed Jul 05 20:34:59 2017 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2000, 2004, 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 sun.jvm.hotspot.compiler; + +import java.util.*; + +import sun.jvm.hotspot.code.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; + +public class ImmutableOopMap extends VMObject { + private static CIntegerField countField; + private static long classSize; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static void initialize(TypeDataBase db) { + Type type = db.lookupType("ImmutableOopMap"); + countField = type.getCIntegerField("_count"); + classSize = type.getSize(); + } + + public ImmutableOopMap(Address addr) { + super(addr); + } + + //-------------------------------------------------------------------------------- + // Internals only below this point + // + + long getCount() { + return countField.getValue(addr); + } + + public Address getData() { + return addr.addOffsetTo(classSize); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapPair.java Wed Jul 05 20:34:59 2017 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.compiler; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.types.CIntegerField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +import java.util.Observable; +import java.util.Observer; + +public class ImmutableOopMapPair { + private static CIntegerField pcField; + private static CIntegerField offsetField; + private static long classSize; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private final Address address; + + public ImmutableOopMapPair(Address address) { + this.address = address; + } + + public static long classSize() { + return classSize; + } + + public int getPC() { + return (int) pcField.getValue(address); + } + + public int getOffset() { + return (int) offsetField.getValue(address); + } + + private static void initialize(TypeDataBase db) { + Type type = db.lookupType("ImmutableOopMapPair"); + + pcField = type.getCIntegerField("_pc_offset"); + offsetField = type.getCIntegerField("_oopmap_offset"); + classSize = type.getSize(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapSet.java Wed Jul 05 20:34:59 2017 +0200 @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2000, 2008, 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 sun.jvm.hotspot.compiler; + +import java.util.*; + +import sun.jvm.hotspot.code.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +public class ImmutableOopMapSet extends VMObject { + private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.ImmutableOopMapSet.DEBUG") != null; + + private static CIntegerField countField; + private static CIntegerField sizeField; + private static AddressField omDataField; + private static int REG_COUNT; + private static int SAVED_ON_ENTRY_REG_COUNT; + private static int C_SAVED_ON_ENTRY_REG_COUNT; + private static long classSize; + + private static class MyVisitor implements OopMapVisitor { + private AddressVisitor addressVisitor; + + public MyVisitor(AddressVisitor oopVisitor) { + setAddressVisitor(oopVisitor); + } + + public void setAddressVisitor(AddressVisitor addressVisitor) { + this.addressVisitor = addressVisitor; + } + + public void visitOopLocation(Address oopAddr) { + addressVisitor.visitAddress(oopAddr); + } + + public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) { + if (VM.getVM().isClientCompiler()) { + Assert.that(false, "should not reach here"); + } else if (VM.getVM().isServerCompiler() && + VM.getVM().useDerivedPointerTable()) { + Assert.that(false, "FIXME: add derived pointer table"); + } + } + + public void visitValueLocation(Address valueAddr) { + } + + public void visitNarrowOopLocation(Address narrowOopAddr) { + addressVisitor.visitCompOopAddress(narrowOopAddr); + } + } + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static void initialize(TypeDataBase db) { + Type type = db.lookupType("ImmutableOopMapSet"); + + countField = type.getCIntegerField("_count"); + sizeField = type.getCIntegerField("_size"); + classSize = type.getSize(); + + if (!VM.getVM().isCore()) { + REG_COUNT = db.lookupIntConstant("REG_COUNT").intValue(); + if (VM.getVM().isServerCompiler()) { + SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("SAVED_ON_ENTRY_REG_COUNT").intValue(); + C_SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("C_SAVED_ON_ENTRY_REG_COUNT").intValue(); + } + } + } + + public ImmutableOopMapSet(Address addr) { + super(addr); + } + + /** + * Returns the number of OopMaps in this ImmutableOopMapSet + */ + public long getSize() { + return countField.getValue(addr); + } + + public int getCount() { return (int) countField.getValue(addr); } + + private Address dataStart() { + return (addr.addOffsetTo(ImmutableOopMapSet.classSize * getCount())); + } + + public ImmutableOopMapPair pairAt(int index) { + Assert.that((index >= 0) && (index < getCount()), "bad index"); + return new ImmutableOopMapPair(addr.addOffsetTo(index * ImmutableOopMapPair.classSize())); + } + + /** + * returns the OopMap at a given index + */ + public ImmutableOopMap getMapAt(int index) { + if (Assert.ASSERTS_ENABLED) { + Assert.that((index >= 0) && (index <= getSize()), "bad index"); + } + + ImmutableOopMapPair immutableOopMapPair = pairAt(index); + return getMap(immutableOopMapPair); + } + + public ImmutableOopMap findMapAtOffset(long pcOffset, boolean debugging) { + int i; + int len = (int) getSize(); + if (Assert.ASSERTS_ENABLED) { + Assert.that(len > 0, "must have pointer maps"); + } + + // Scan through oopmaps. Stop when current offset is either equal or greater + // than the one we are looking for. + for (i = 0; i < len; i++) { + if (pairAt(i).getPC() >= pcOffset) { + break; + } + } + + if (!debugging) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(i < len, "oopmap not found for pcOffset = " + pcOffset + "; len = " + len); + Assert.that(pairAt(i).getPC() == pcOffset, "oopmap not found"); + } + } else { + if (i == len) { + if (DEBUG) { + System.out.println("can't find oopmap at " + pcOffset); + System.out.print("Oopmap offsets are [ "); + for (i = 0; i < len; i++) { + System.out.print(pairAt(i).getPC()); + } + System.out.println("]"); + } + i = len - 1; + return getMapAt(i); + } + } + + ImmutableOopMap m = getMapAt(i); + return m; + } + + /** + * Visitation -- iterates through the frame for a compiled method. + * This is a very generic mechanism that requires the Address to be + * dereferenced by the callee. Other, more specialized, visitation + * mechanisms are given below. + */ + public static void oopsDo(Frame fr, CodeBlob cb, RegisterMap regMap, AddressVisitor oopVisitor, boolean debugging) { + allDo(fr, cb, regMap, new MyVisitor(oopVisitor), debugging); + } + + /** + * Note that there are 4 required AddressVisitors: one for oops, + * one for derived oops, one for values, and one for dead values + */ + public static void allDo(Frame fr, CodeBlob cb, RegisterMap regMap, OopMapVisitor visitor, boolean debugging) { + if (Assert.ASSERTS_ENABLED) { + CodeBlob tmpCB = VM.getVM().getCodeCache().findBlob(fr.getPC()); + Assert.that(tmpCB != null && cb.equals(tmpCB), "wrong codeblob passed in"); + } + + ImmutableOopMapSet maps = cb.getOopMaps(); + ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging); + if (Assert.ASSERTS_ENABLED) { + Assert.that(map != null, "no ptr map found"); + } + + // handle derived pointers first (otherwise base pointer may be + // changed before derived pointer offset has been collected) + OopMapValue omv; + { + for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); !oms.isDone(); oms.next()) { + if (VM.getVM().isClientCompiler()) { + Assert.that(false, "should not reach here"); + } + omv = oms.getCurrent(); + Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap); + if (loc != null) { + Address baseLoc = fr.oopMapRegToLocation(omv.getContentReg(), regMap); + Address derivedLoc = loc; + visitor.visitDerivedOopLocation(baseLoc, derivedLoc); + } + } + } + + // We want narow oop, value and oop oop_types + OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[]{ + OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE + }; + + { + for (OopMapStream oms = new OopMapStream(map, values); !oms.isDone(); oms.next()) { + omv = oms.getCurrent(); + Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap); + if (loc != null) { + if (omv.getType() == OopMapValue.OopTypes.OOP_VALUE) { + // This assert commented out because this will be useful + // to detect in the debugging system + // assert(Universe::is_heap_or_null(*loc), "found non oop pointer"); + visitor.visitOopLocation(loc); + } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) { + visitor.visitValueLocation(loc); + } else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) { + visitor.visitNarrowOopLocation(loc); + } + } + } + } + } + + /** + * Update callee-saved register info for the following frame. + * Should only be called in non-core builds. + */ + public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(!VM.getVM().isCore(), "non-core builds only"); + } + + if (!VM.getVM().isDebugging()) { + if (Assert.ASSERTS_ENABLED) { + ImmutableOopMapSet maps = cb.getOopMaps(); + Assert.that((maps != null) && (maps.getSize() > 0), "found null or empty ImmutableOopMapSet for CodeBlob"); + } + } else { + // Hack for some topmost frames that have been found with empty + // OopMapSets. (Actually have not seen the null case, but don't + // want to take any chances.) See HSDB.showThreadStackMemory(). + ImmutableOopMapSet maps = cb.getOopMaps(); + if ((maps == null) || (maps.getSize() == 0)) { + return; + } + } + + // Check if caller must update oop argument + regMap.setIncludeArgumentOops(cb.callerMustGCArguments()); + + int nofCallee = 0; + Address[] locs = new Address[2 * REG_COUNT + 1]; + VMReg[] regs = new VMReg[2 * REG_COUNT + 1]; + // ("+1" because REG_COUNT might be zero) + + // Scan through oopmap and find location of all callee-saved registers + // (we do not do update in place, since info could be overwritten) + ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging); + if (Assert.ASSERTS_ENABLED) { + Assert.that(map != null, "no ptr map found"); + } + + OopMapValue omv = null; + for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); !oms.isDone(); oms.next()) { + omv = oms.getCurrent(); + if (Assert.ASSERTS_ENABLED) { + Assert.that(nofCallee < 2 * REG_COUNT, "overflow"); + } + regs[nofCallee] = omv.getContentReg(); + locs[nofCallee] = fr.oopMapRegToLocation(omv.getReg(), regMap); + nofCallee++; + } + + // Check that runtime stubs save all callee-saved registers + // After adapter frames were deleted C2 doesn't use callee save registers at present + if (Assert.ASSERTS_ENABLED) { + if (VM.getVM().isServerCompiler()) { + Assert.that(!cb.isRuntimeStub() || + (nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT), + "must save all"); + } + } + + // Copy found callee-saved register to reg_map + for (int i = 0; i < nofCallee; i++) { + regMap.setLocation(regs[i], locs[i]); + } + } + + public ImmutableOopMapPair getPairAt(int index) { + return pairAt(index); + } + + public ImmutableOopMap getMap(ImmutableOopMapPair pair) { + Assert.that(pair.getOffset() < (int) sizeField.getValue(), "boundary check"); + return new ImmutableOopMap(dataStart().addOffsetTo(pair.getOffset())); + } +}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMap.java Thu May 21 16:19:37 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2000, 2004, 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 sun.jvm.hotspot.compiler; - -import java.util.*; - -import sun.jvm.hotspot.code.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; - -public class OopMap extends VMObject { - private static CIntegerField pcOffsetField; - private static CIntegerField omvCountField; - private static CIntegerField omvDataSizeField; - private static AddressField omvDataField; - private static AddressField compressedWriteStreamField; - - // This is actually a field inside class CompressedStream - private static AddressField compressedStreamBufferField; - - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static void initialize(TypeDataBase db) { - Type type = db.lookupType("OopMap"); - - pcOffsetField = type.getCIntegerField("_pc_offset"); - omvCountField = type.getCIntegerField("_omv_count"); - omvDataSizeField = type.getCIntegerField("_omv_data_size"); - omvDataField = type.getAddressField("_omv_data"); - compressedWriteStreamField = type.getAddressField("_write_stream"); - - type = db.lookupType("CompressedStream"); - compressedStreamBufferField = type.getAddressField("_buffer"); - } - - public OopMap(Address addr) { - super(addr); - } - - public long getOffset() { - return pcOffsetField.getValue(addr); - } - - //-------------------------------------------------------------------------------- - // Internals only below this point - // - - // Accessors -- package private for now - Address getOMVData() { - return omvDataField.getValue(addr); - } - - long getOMVDataSize() { - return omvDataSizeField.getValue(addr); - } - - long getOMVCount() { - return omvCountField.getValue(addr); - } - - CompressedWriteStream getWriteStream() { - Address wsAddr = compressedWriteStreamField.getValue(addr); - if (wsAddr == null) { - return null; - } - Address bufferAddr = compressedStreamBufferField.getValue(wsAddr); - if (bufferAddr == null) { - return null; - } - return new CompressedWriteStream(bufferAddr); - } -}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java Thu May 21 16:19:37 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2000, 2008, 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 sun.jvm.hotspot.compiler; - -import java.util.*; - -import sun.jvm.hotspot.code.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.*; - -public class OopMapSet extends VMObject { - private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.OopMapSet.DEBUG") != null; - - private static CIntegerField omCountField; - private static CIntegerField omSizeField; - private static AddressField omDataField; - private static int REG_COUNT; - private static int SAVED_ON_ENTRY_REG_COUNT; - private static int C_SAVED_ON_ENTRY_REG_COUNT; - private static class MyVisitor implements OopMapVisitor { - private AddressVisitor addressVisitor; - - public MyVisitor(AddressVisitor oopVisitor) { - setAddressVisitor(oopVisitor); - } - - public void setAddressVisitor(AddressVisitor addressVisitor) { - this.addressVisitor = addressVisitor; - } - - public void visitOopLocation(Address oopAddr) { - addressVisitor.visitAddress(oopAddr); - } - - public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) { - if (VM.getVM().isClientCompiler()) { - Assert.that(false, "should not reach here"); - } else if (VM.getVM().isServerCompiler() && - VM.getVM().useDerivedPointerTable()) { - Assert.that(false, "FIXME: add derived pointer table"); - } - } - - public void visitValueLocation(Address valueAddr) { - } - - public void visitNarrowOopLocation(Address narrowOopAddr) { - addressVisitor.visitCompOopAddress(narrowOopAddr); - } - } - - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static void initialize(TypeDataBase db) { - Type type = db.lookupType("OopMapSet"); - - omCountField = type.getCIntegerField("_om_count"); - omSizeField = type.getCIntegerField("_om_size"); - omDataField = type.getAddressField("_om_data"); - - if (!VM.getVM().isCore()) { - REG_COUNT = db.lookupIntConstant("REG_COUNT").intValue(); - if (VM.getVM().isServerCompiler()) { - SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("SAVED_ON_ENTRY_REG_COUNT").intValue(); - C_SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("C_SAVED_ON_ENTRY_REG_COUNT").intValue(); - } - } - } - - public OopMapSet(Address addr) { - super(addr); - } - - /** Returns the number of OopMaps in this OopMapSet */ - public long getSize() { - return omCountField.getValue(addr); - } - - /** returns the OopMap at a given index */ - public OopMap getMapAt(int index) { - if (Assert.ASSERTS_ENABLED) { - Assert.that((index >= 0) && (index <= getSize()),"bad index"); - } - Address omDataAddr = omDataField.getValue(addr); - Address oopMapAddr = omDataAddr.getAddressAt(index * VM.getVM().getAddressSize()); - if (oopMapAddr == null) { - return null; - } - return new OopMap(oopMapAddr); - } - - public OopMap findMapAtOffset(long pcOffset, boolean debugging) { - int i; - int len = (int) getSize(); - if (Assert.ASSERTS_ENABLED) { - Assert.that(len > 0, "must have pointer maps"); - } - - // Scan through oopmaps. Stop when current offset is either equal or greater - // than the one we are looking for. - for (i = 0; i < len; i++) { - if (getMapAt(i).getOffset() >= pcOffset) { - break; - } - } - - if (!debugging) { - if (Assert.ASSERTS_ENABLED) { - Assert.that(i < len, "oopmap not found for pcOffset = " + pcOffset + "; len = " + len); - Assert.that(getMapAt(i).getOffset() == pcOffset, "oopmap not found"); - } - } else { - if (i == len) { - if (DEBUG) { - System.out.println("can't find oopmap at " + pcOffset); - System.out.print("Oopmap offsets are [ "); - for (i = 0; i < len; i++) { - System.out.print(getMapAt(i).getOffset()); - } - System.out.println("]"); - } - i = len - 1; - return getMapAt(i); - } - } - - OopMap m = getMapAt(i); - return m; - } - - /** Visitation -- iterates through the frame for a compiled method. - This is a very generic mechanism that requires the Address to be - dereferenced by the callee. Other, more specialized, visitation - mechanisms are given below. */ - public static void oopsDo(Frame fr, CodeBlob cb, RegisterMap regMap, AddressVisitor oopVisitor, boolean debugging) { - allDo(fr, cb, regMap, new MyVisitor(oopVisitor), debugging); - } - - /** Note that there are 4 required AddressVisitors: one for oops, - one for derived oops, one for values, and one for dead values */ - public static void allDo(Frame fr, CodeBlob cb, RegisterMap regMap, OopMapVisitor visitor, boolean debugging) { - if (Assert.ASSERTS_ENABLED) { - CodeBlob tmpCB = VM.getVM().getCodeCache().findBlob(fr.getPC()); - Assert.that(tmpCB != null && cb.equals(tmpCB), "wrong codeblob passed in"); - } - - OopMapSet maps = cb.getOopMaps(); - OopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging); - if (Assert.ASSERTS_ENABLED) { - Assert.that(map != null, "no ptr map found"); - } - - // handle derived pointers first (otherwise base pointer may be - // changed before derived pointer offset has been collected) - OopMapValue omv; - { - for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); !oms.isDone(); oms.next()) { - if (VM.getVM().isClientCompiler()) { - Assert.that(false, "should not reach here"); - } - omv = oms.getCurrent(); - Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap); - if (loc != null) { - Address baseLoc = fr.oopMapRegToLocation(omv.getContentReg(), regMap); - Address derivedLoc = loc; - visitor.visitDerivedOopLocation(baseLoc, derivedLoc); - } - } - } - - // We want narow oop, value and oop oop_types - OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[] { - OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE - }; - - { - for (OopMapStream oms = new OopMapStream(map, values); !oms.isDone(); oms.next()) { - omv = oms.getCurrent(); - Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap); - if (loc != null) { - if (omv.getType() == OopMapValue.OopTypes.OOP_VALUE) { - // This assert commented out because this will be useful - // to detect in the debugging system - // assert(Universe::is_heap_or_null(*loc), "found non oop pointer"); - visitor.visitOopLocation(loc); - } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) { - visitor.visitValueLocation(loc); - } else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) { - visitor.visitNarrowOopLocation(loc); - } - } - } - } - } - - /** Update callee-saved register info for the following frame. - Should only be called in non-core builds. */ - public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) { - if (Assert.ASSERTS_ENABLED) { - Assert.that(!VM.getVM().isCore(), "non-core builds only"); - } - - if (!VM.getVM().isDebugging()) { - if (Assert.ASSERTS_ENABLED) { - OopMapSet maps = cb.getOopMaps(); - Assert.that((maps != null) && (maps.getSize() > 0), "found null or empty OopMapSet for CodeBlob"); - } - } else { - // Hack for some topmost frames that have been found with empty - // OopMapSets. (Actually have not seen the null case, but don't - // want to take any chances.) See HSDB.showThreadStackMemory(). - OopMapSet maps = cb.getOopMaps(); - if ((maps == null) || (maps.getSize() == 0)) { - return; - } - } - - // Check if caller must update oop argument - regMap.setIncludeArgumentOops(cb.callerMustGCArguments()); - - int nofCallee = 0; - Address[] locs = new Address[2 * REG_COUNT + 1]; - VMReg [] regs = new VMReg [2 * REG_COUNT + 1]; - // ("+1" because REG_COUNT might be zero) - - // Scan through oopmap and find location of all callee-saved registers - // (we do not do update in place, since info could be overwritten) - OopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging); - if (Assert.ASSERTS_ENABLED) { - Assert.that(map != null, "no ptr map found"); - } - - OopMapValue omv = null; - for(OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); !oms.isDone(); oms.next()) { - omv = oms.getCurrent(); - if (Assert.ASSERTS_ENABLED) { - Assert.that(nofCallee < 2 * REG_COUNT, "overflow"); - } - regs[nofCallee] = omv.getContentReg(); - locs[nofCallee] = fr.oopMapRegToLocation(omv.getReg(), regMap); - nofCallee++; - } - - // Check that runtime stubs save all callee-saved registers - // After adapter frames were deleted C2 doesn't use callee save registers at present - if (Assert.ASSERTS_ENABLED) { - if (VM.getVM().isServerCompiler()) { - Assert.that(!cb.isRuntimeStub() || - (nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT), - "must save all"); - } - } - - // Copy found callee-saved register to reg_map - for (int i = 0; i < nofCallee; i++) { - regMap.setLocation(regs[i], locs[i]); - } - } -}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapStream.java Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapStream.java Wed Jul 05 20:34:59 2017 +0200 @@ -28,30 +28,26 @@ public class OopMapStream { private CompressedReadStream stream; - private OopMap oopMap; + private ImmutableOopMap oopMap; private int mask; private int size; private int position; private OopMapValue omv; private boolean omvValid; - public OopMapStream(OopMap oopMap) { + public OopMapStream(ImmutableOopMap oopMap) { this(oopMap, (OopMapValue.OopTypes[]) null); } - public OopMapStream(OopMap oopMap, OopMapValue.OopTypes type) { + public OopMapStream(ImmutableOopMap oopMap, OopMapValue.OopTypes type) { this(oopMap, (OopMapValue.OopTypes[]) null); mask = type.getValue(); } - public OopMapStream(OopMap oopMap, OopMapValue.OopTypes[] types) { - if (oopMap.getOMVData() == null) { - stream = new CompressedReadStream(oopMap.getWriteStream().getBuffer()); - } else { - stream = new CompressedReadStream(oopMap.getOMVData()); - } + public OopMapStream(ImmutableOopMap oopMap, OopMapValue.OopTypes[] types) { + stream = new CompressedReadStream(oopMap.getData()); mask = computeMask(types); - size = (int) oopMap.getOMVCount(); + size = (int) oopMap.getCount(); position = 0; omv = new OopMapValue(); omvValid = false;
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java Wed Jul 05 20:34:59 2017 +0200 @@ -26,14 +26,12 @@ import java.io.*; import java.util.*; -import sun.jvm.hotspot.*; + import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.compiler.*; -import sun.jvm.hotspot.c1.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.interpreter.*; import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.sparc.SPARCFrame; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; @@ -626,7 +624,7 @@ Assert.that(cb != null, "sanity check"); } if (cb.getOopMaps() != null) { - OopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging()); + ImmutableOopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging()); // FIXME: add in traversal of argument oops (skipping this for // now until we have the other stuff tested)
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java Wed Jul 05 20:34:59 2017 +0200 @@ -358,7 +358,7 @@ map.setIncludeArgumentOops(cb.callerMustGCArguments()); if (cb.getOopMaps() != null) { - OopMapSet.updateRegisterMap(this, cb, map, true); + ImmutableOopMapSet.updateRegisterMap(this, cb, map, true); } }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java Wed Jul 05 20:34:59 2017 +0200 @@ -24,8 +24,6 @@ package sun.jvm.hotspot.runtime.sparc; -import java.util.*; - import sun.jvm.hotspot.asm.sparc.*; import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.compiler.*; @@ -34,7 +32,6 @@ import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.runtime.posix.*; -import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; /** Specialization of and implementation of abstract methods of the @@ -592,7 +589,7 @@ map.setIncludeArgumentOops(true); } if (cb.getOopMaps() != null) { - OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging()); + ImmutableOopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging()); } } }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java Wed Jul 05 20:34:59 2017 +0200 @@ -385,7 +385,7 @@ map.setIncludeArgumentOops(cb.callerMustGCArguments()); if (cb.getOopMaps() != null) { - OopMapSet.updateRegisterMap(this, cb, map, true); + ImmutableOopMapSet.updateRegisterMap(this, cb, map, true); } // Since the prolog does the save and restore of EBP there is no oopmap
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Wed Jul 05 20:34:59 2017 +0200 @@ -31,11 +31,9 @@ import sun.jvm.hotspot.compiler.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.interpreter.*; -import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.tools.jcore.*; -import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; public class HTMLGenerator implements /* imports */ ClassConstants { @@ -887,7 +885,7 @@ private Formatter buf; private SymbolFinder symFinder = createSymbolFinder(); private long pc; - private OopMapSet oms; + private ImmutableOopMapSet oms; private CodeBlob blob; private NMethod nmethod; @@ -954,13 +952,13 @@ if (oms != null) { long base = addressToLong(blob.codeBegin()); - for (int i = 0, imax = (int)oms.getSize(); i < imax; i++) { - OopMap om = oms.getMapAt(i); - long omspc = base + om.getOffset(); + for (int i = 0, imax = oms.getCount(); i < imax; i++) { + ImmutableOopMapPair pair = oms.getPairAt(i); + long omspc = base + pair.getPC(); if (omspc > pc) { if (omspc <= endPc) { buf.br(); - buf.append(genOopMapInfo(om)); + buf.append(genOopMapInfo(oms.getMap(pair))); // st.move_to(column); // visitor.print("; "); // om.print_on(st); @@ -1167,7 +1165,7 @@ } } - protected String genHTMLForOopMap(OopMap map) { + protected String genHTMLForOopMap(ImmutableOopMap map) { final int stack0 = VMRegImpl.getStack0().getValue(); Formatter buf = new Formatter(genHTML); @@ -1237,11 +1235,11 @@ protected String genOopMapInfo(NMethod nmethod, PCDesc pcDesc) { - OopMapSet mapSet = nmethod.getOopMaps(); + ImmutableOopMapSet mapSet = nmethod.getOopMaps(); if (mapSet == null || (mapSet.getSize() <= 0)) return ""; int pcOffset = pcDesc.getPCOffset(); - OopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging()); + ImmutableOopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging()); if (map == null) { throw new IllegalArgumentException("no oopmap at safepoint!"); } @@ -1249,7 +1247,7 @@ return genOopMapInfo(map); } - protected String genOopMapInfo(OopMap map) { + protected String genOopMapInfo(ImmutableOopMap map) { Formatter buf = new Formatter(genHTML); buf.beginTag("pre"); buf.append("OopMap: ");
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Wed Jul 05 20:34:59 2017 +0200 @@ -421,7 +421,40 @@ ); // Class for all non-special integer registers -reg_class no_special_reg32( +reg_class no_special_reg32_no_fp( + R0, + R1, + R2, + R3, + R4, + R5, + R6, + R7, + R10, + R11, + R12, // rmethod + R13, + R14, + R15, + R16, + R17, + R18, + R19, + R20, + R21, + R22, + R23, + R24, + R25, + R26 + /* R27, */ // heapbase + /* R28, */ // thread + /* R29, */ // fp + /* R30, */ // lr + /* R31 */ // sp +); + +reg_class no_special_reg32_with_fp( R0, R1, R2, @@ -454,8 +487,43 @@ /* R31 */ // sp ); +reg_class_dynamic no_special_reg32(no_special_reg32_no_fp, no_special_reg32_with_fp, %{ PreserveFramePointer %}); + // Class for all non-special long integer registers -reg_class no_special_reg( +reg_class no_special_reg_no_fp( + R0, R0_H, + R1, R1_H, + R2, R2_H, + R3, R3_H, + R4, R4_H, + R5, R5_H, + R6, R6_H, + R7, R7_H, + R10, R10_H, + R11, R11_H, + R12, R12_H, // rmethod + R13, R13_H, + R14, R14_H, + R15, R15_H, + R16, R16_H, + R17, R17_H, + R18, R18_H, + R19, R19_H, + R20, R20_H, + R21, R21_H, + R22, R22_H, + R23, R23_H, + R24, R24_H, + R25, R25_H, + R26, R26_H, + /* R27, R27_H, */ // heapbase + /* R28, R28_H, */ // thread + /* R29, R29_H, */ // fp + /* R30, R30_H, */ // lr + /* R31, R31_H */ // sp +); + +reg_class no_special_reg_with_fp( R0, R0_H, R1, R1_H, R2, R2_H, @@ -488,6 +556,8 @@ /* R31, R31_H */ // sp ); +reg_class_dynamic no_special_reg(no_special_reg_no_fp, no_special_reg_with_fp, %{ PreserveFramePointer %}); + // Class for 64 bit register r0 reg_class r0_reg( R0, R0_H @@ -1637,12 +1707,7 @@ int MachCallStaticJavaNode::ret_addr_offset() { // call should be a simple bl - // unless this is a method handle invoke in which case it is - // mov(rfp, sp), bl, mov(sp, rfp) int off = 4; - if (_method_handle_invoke) { - off += 4; - } return off; } @@ -1753,14 +1818,13 @@ if (C->need_stack_bang(framesize)) st->print("# stack bang size=%d\n\t", framesize); - if (framesize == 0) { - // Is this even possible? - st->print("stp lr, rfp, [sp, #%d]!", -(2 * wordSize)); - } else if (framesize < ((1 << 9) + 2 * wordSize)) { + if (framesize < ((1 << 9) + 2 * wordSize)) { st->print("sub sp, sp, #%d\n\t", framesize); st->print("stp rfp, lr, [sp, #%d]", framesize - 2 * wordSize); + if (PreserveFramePointer) st->print("\n\tadd rfp, sp, #%d", framesize - 2 * wordSize); } else { st->print("stp lr, rfp, [sp, #%d]!\n\t", -(2 * wordSize)); + if (PreserveFramePointer) st->print("mov rfp, sp\n\t"); st->print("mov rscratch1, #%d\n\t", framesize - 2 * wordSize); st->print("sub sp, sp, rscratch1"); } @@ -3517,34 +3581,6 @@ } %} - enc_class aarch64_enc_java_handle_call(method meth) %{ - MacroAssembler _masm(&cbuf); - relocInfo::relocType reloc; - - // RFP is preserved across all calls, even compiled calls. - // Use it to preserve SP. - __ mov(rfp, sp); - - const int start_offset = __ offset(); - address addr = (address)$meth$$method; - if (!_method) { - // A call to a runtime wrapper, e.g. new, new_typeArray_Java, uncommon_trap. - __ trampoline_call(Address(addr, relocInfo::runtime_call_type), &cbuf); - } else if (_optimized_virtual) { - __ trampoline_call(Address(addr, relocInfo::opt_virtual_call_type), &cbuf); - } else { - __ trampoline_call(Address(addr, relocInfo::static_call_type), &cbuf); - } - - if (_method) { - // Emit stub for static call - CompiledStaticCall::emit_to_interp_stub(cbuf); - } - - // now restore sp - __ mov(sp, rfp); - %} - enc_class aarch64_enc_java_dynamic_call(method meth) %{ MacroAssembler _masm(&cbuf); __ ic_call((address)$meth$$method); @@ -12561,8 +12597,6 @@ effect(USE meth); - predicate(!((CallStaticJavaNode*)n)->is_method_handle_invoke()); - ins_cost(CALL_COST); format %{ "call,static $meth \t// ==> " %} @@ -12575,26 +12609,6 @@ // TO HERE -// Call Java Static Instruction (method handle version) - -instruct CallStaticJavaDirectHandle(method meth, iRegP_FP reg_mh_save) -%{ - match(CallStaticJava); - - effect(USE meth); - - predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke()); - - ins_cost(CALL_COST); - - format %{ "call,static $meth \t// (methodhandle) ==> " %} - - ins_encode( aarch64_enc_java_handle_call(meth), - aarch64_enc_call_epilog ); - - ins_pipe(pipe_class_call); -%} - // Call Java Dynamic Instruction instruct CallDynamicJavaDirect(method meth) %{
--- a/hotspot/src/cpu/aarch64/vm/c1_FrameMap_aarch64.cpp Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/c1_FrameMap_aarch64.cpp Wed Jul 05 20:34:59 2017 +0200 @@ -346,8 +346,7 @@ // JSR 292 LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() { - // assert(rfp == rbp_mh_SP_save, "must be same register"); - return rfp_opr; + return LIR_OprFact::illegalOpr; // Not needed on aarch64 }
--- a/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp Wed Jul 05 20:34:59 2017 +0200 @@ -443,18 +443,8 @@ restore_live_registers(sasm, id != handle_exception_nofpu_id); break; case handle_exception_from_callee_id: - // Pop the return address since we are possibly changing SP (restoring from BP). + // Pop the return address. __ leave(); - - // Restore SP from FP if the exception PC is a method handle call site. - { - Label nope; - __ ldrw(rscratch1, Address(rthread, JavaThread::is_method_handle_return_offset())); - __ cbzw(rscratch1, nope); - __ mov(sp, rfp); - __ bind(nope); - } - __ ret(lr); // jump to exception handler break; default: ShouldNotReachHere(); @@ -514,14 +504,6 @@ __ verify_not_null_oop(exception_oop); - { - Label foo; - __ ldrw(rscratch1, Address(rthread, JavaThread::is_method_handle_return_offset())); - __ cbzw(rscratch1, foo); - __ mov(sp, rfp); - __ bind(foo); - } - // continue at exception handler (return address removed) // note: do *not* remove arguments when unwinding the // activation since the caller assumes having
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp Wed Jul 05 20:34:59 2017 +0200 @@ -223,7 +223,8 @@ if (sender_blob->is_nmethod()) { nmethod* nm = sender_blob->as_nmethod_or_null(); if (nm != NULL) { - if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc)) { + if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) || + nm->method()->is_method_handle_intrinsic()) { return false; } } @@ -389,10 +390,9 @@ // frame::verify_deopt_original_pc // // Verifies the calculated original PC of a deoptimization PC for the -// given unextended SP. The unextended SP might also be the saved SP -// for MethodHandle call sites. +// given unextended SP. #ifdef ASSERT -void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return) { +void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) { frame fr; // This is ugly but it's better than to change {get,set}_original_pc @@ -402,33 +402,23 @@ address original_pc = nm->get_original_pc(&fr); assert(nm->insts_contains(original_pc), "original PC must be in nmethod"); - assert(nm->is_method_handle_return(original_pc) == is_method_handle_return, "must be"); } #endif //------------------------------------------------------------------------------ // frame::adjust_unextended_sp void frame::adjust_unextended_sp() { - // If we are returning to a compiled MethodHandle call site, the - // saved_fp will in fact be a saved value of the unextended SP. The - // simplest way to tell whether we are returning to such a call site - // is as follows: + // On aarch64, sites calling method handle intrinsics and lambda forms are treated + // as any other call site. Therefore, no special action is needed when we are + // returning to any of these call sites. nmethod* sender_nm = (_cb == NULL) ? NULL : _cb->as_nmethod_or_null(); if (sender_nm != NULL) { - // If the sender PC is a deoptimization point, get the original - // PC. For MethodHandle call site the unextended_sp is stored in - // saved_fp. - if (sender_nm->is_deopt_mh_entry(_pc)) { - DEBUG_ONLY(verify_deopt_mh_original_pc(sender_nm, _fp)); - _unextended_sp = _fp; - } - else if (sender_nm->is_deopt_entry(_pc)) { + // If the sender PC is a deoptimization point, get the original PC. + if (sender_nm->is_deopt_entry(_pc) || + sender_nm->is_deopt_mh_entry(_pc)) { DEBUG_ONLY(verify_deopt_original_pc(sender_nm, _unextended_sp)); } - else if (sender_nm->is_method_handle_return(_pc)) { - _unextended_sp = _fp; - } } }
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp Wed Jul 05 20:34:59 2017 +0200 @@ -167,10 +167,7 @@ #ifdef ASSERT // Used in frame::sender_for_{interpreter,compiled}_frame - static void verify_deopt_original_pc( nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return = false); - static void verify_deopt_mh_original_pc(nmethod* nm, intptr_t* unextended_sp) { - verify_deopt_original_pc(nm, unextended_sp, true); - } + static void verify_deopt_original_pc( nmethod* nm, intptr_t* unextended_sp); #endif public:
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp Wed Jul 05 20:34:59 2017 +0200 @@ -47,12 +47,6 @@ inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) { intptr_t a = intptr_t(sp); intptr_t b = intptr_t(fp); -#ifndef PRODUCT - if (fp) - if (sp > fp || (fp - sp > 0x100000)) - for(;;) - asm("nop"); -#endif _sp = sp; _unextended_sp = sp; _fp = fp;
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Wed Jul 05 20:34:59 2017 +0200 @@ -3788,14 +3788,14 @@ } void MacroAssembler::build_frame(int framesize) { - if (framesize == 0) { - // Is this even possible? - stp(rfp, lr, Address(pre(sp, -2 * wordSize))); - } else if (framesize < ((1 << 9) + 2 * wordSize)) { + assert(framesize > 0, "framesize must be > 0"); + if (framesize < ((1 << 9) + 2 * wordSize)) { sub(sp, sp, framesize); stp(rfp, lr, Address(sp, framesize - 2 * wordSize)); + if (PreserveFramePointer) add(rfp, sp, framesize - 2 * wordSize); } else { stp(rfp, lr, Address(pre(sp, -2 * wordSize))); + if (PreserveFramePointer) mov(rfp, sp); if (framesize < ((1 << 12) + 2 * wordSize)) sub(sp, sp, framesize - 2 * wordSize); else { @@ -3806,9 +3806,8 @@ } void MacroAssembler::remove_frame(int framesize) { - if (framesize == 0) { - ldp(rfp, lr, Address(post(sp, 2 * wordSize))); - } else if (framesize < ((1 << 9) + 2 * wordSize)) { + assert(framesize > 0, "framesize must be > 0"); + if (framesize < ((1 << 9) + 2 * wordSize)) { ldp(rfp, lr, Address(sp, framesize - 2 * wordSize)); add(sp, sp, framesize); } else {
--- a/hotspot/src/cpu/aarch64/vm/register_definitions_aarch64.cpp Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/register_definitions_aarch64.cpp Wed Jul 05 20:34:59 2017 +0200 @@ -149,7 +149,3 @@ REGISTER_DEFINITION(Register, rheapbase); REGISTER_DEFINITION(Register, r31_sp); - -// TODO : x86 uses rbp to save SP in method handle code -// we may need to do the same with fp -// REGISTER_DEFINITION(Register, rbp_mh_SP_save)
--- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Wed Jul 05 20:34:59 2017 +0200 @@ -2995,21 +2995,6 @@ // r0: exception handler - // Restore SP from BP if the exception PC is a MethodHandle call site. - __ ldrw(rscratch1, Address(rthread, JavaThread::is_method_handle_return_offset())); - // n.b. Intel uses special register rbp_mh_SP_save here but we will - // just hard wire rfp - __ cmpw(rscratch1, zr); - // the obvious way to conditionally copy rfp to sp if NE - // Label skip; - // __ br(Assembler::EQ, skip); - // __ mov(sp, rfp); - // __ bind(skip); - // same but branchless - __ mov(rscratch1, sp); - __ csel(rscratch1, rfp, rscratch1, Assembler::NE); - __ mov(sp, rscratch1); - // We have a handler in r0 (could be deopt blob). __ mov(r8, r0);
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Wed Jul 05 20:34:59 2017 +0200 @@ -1891,7 +1891,7 @@ address start = __ pc(); __ enter(); - __ mov(rscratch1, len_reg); + __ mov(rscratch2, len_reg); __ ldrw(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); __ ld1(v0, __ T16B, rvec);
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Jul 05 20:34:59 2017 +0200 @@ -629,7 +629,7 @@ // Print the detection code. if (PrintAssembly) { ttyLocker ttyl; - tty->print_cr("Decoding dscr configuration stub at " INTPTR_FORMAT " before execution:", code); + tty->print_cr("Decoding dscr configuration stub at " INTPTR_FORMAT " before execution:", p2i(code)); Disassembler::decode((u_char*)code, (u_char*)code_end, tty); }
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Thu May 21 16:19:37 2015 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Jul 05 20:34:59 2017 +0200 @@ -54,6 +54,36 @@ #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") // Implementation of AddressLiteral +// A 2-D table for managing compressed displacement(disp8) on EVEX enabled platforms. +unsigned char tuple_table[Assembler::EVEX_ETUP + 1][Assembler::AVX_512bit + 1] = { + // -----------------Table 4.5 -------------------- // + 16, 32, 64, // EVEX_FV(0) + 4, 4, 4, // EVEX_FV(1) - with Evex.b + 16, 32, 64, // EVEX_FV(2) - with Evex.w + 8, 8, 8, // EVEX_FV(3) - with Evex.w and Evex.b + 8, 16, 32, // EVEX_HV(0) + 4, 4, 4, // EVEX_HV(1) - with Evex.b + // -----------------Table 4.6 -------------------- // + 16, 32, 64, // EVEX_FVM(0) + 1, 1, 1, // EVEX_T1S(0) + 2, 2, 2, // EVEX_T1S(1) + 4, 4, 4, // EVEX_T1S(2) + 8, 8, 8, // EVEX_T1S(3) + 4, 4, 4, // EVEX_T1F(0) + 8, 8, 8, // EVEX_T1F(1) + 8, 8, 8, // EVEX_T2(0) + 0, 16, 16, // EVEX_T2(1) + 0, 16, 16, // EVEX_T4(0) + 0, 0, 32, // EVEX_T4(1) + 0, 0, 32, // EVEX_T8(0) + 8, 16, 32, // EVEX_HVM(0) + 4, 8, 16, // EVEX_QVM(0) + 2, 4, 8, // EVEX_OVM(0) + 16, 16, 16, // EVEX_M128(0) + 8, 32, 64, // EVEX_DUP(0) + 0, 0, 0 // EVEX_NTUP +}; + AddressLiteral::AddressLiteral(address target, relocInfo::relocType rtype) { _is_lval = false; _target = target; @@ -183,8 +213,9 @@ // make this go away someday void Assembler::emit_data(jint data, relocInfo::relocType rtype, int format) { if (rtype == relocInfo::none) - emit_int32(data); - else emit_data(data, Relocation::spec_simple(rtype), format); + emit_int32(data); + else + emit_data(data, Relocation::spec_simple(rtype), format); } void Assembler::emit_data(jint data, RelocationHolder const& rspec, int format) { @@ -273,6 +304,177 @@ } +bool Assembler::query_compressed_disp_byte(int disp, bool is_evex_inst, int vector_len, + int cur_tuple_type, int in_size_in_bits, int cur_encoding) { + int mod_idx = 0; + // We will test if the displacement fits the compressed format and if so + // apply the compression to the displacment iff the result is8bit. + if (VM_Version::supports_evex() && is_evex_inst) { + switch (cur_tuple_type) { + case EVEX_FV: + if ((cur_encoding & VEX_W) == VEX_W) { + mod_idx += 2 + ((cur_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0; + } else { + mod_idx = ((cur_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0; + } + break; + + case EVEX_HV: + mod_idx = ((cur_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0; + break; + + case EVEX_FVM: + break; + + case EVEX_T1S: + switch (in_size_in_bits) { + case EVEX_8bit: + break; + + case EVEX_16bit: + mod_idx = 1; + break; + + case EVEX_32bit: + mod_idx = 2; + break; + + case EVEX_64bit: + mod_idx = 3; + break; + } + break; + + case EVEX_T1F: + case EVEX_T2: + case EVEX_T4: + mod_idx = (in_size_in_bits == EVEX_64bit) ? 1 : 0; + break; + + case EVEX_T8: + break; + + case EVEX_HVM: + break; + + case EVEX_QVM: + break; + + case EVEX_OVM: + break; + + case EVEX_M128: + break; + + case EVEX_DUP: + break; + + default: + assert(0, "no valid evex tuple_table entry"); + break; + } + + if (vector_len >= AVX_128bit && vector_len <= AVX_512bit) { + int disp_factor = tuple_table[cur_tuple_type + mod_idx][vector_len]; + if ((disp % disp_factor) == 0) { + int new_disp = disp / disp_factor; + if ((-0x80 <= new_disp && new_disp < 0x80)) { + disp = new_disp; + } + } else { + return false; + } + } + } + return (-0x80 <= disp && disp < 0x80); +} + + +bool Assembler::emit_compressed_disp_byte(int &disp) { + int mod_idx = 0; + // We will test if the displacement fits the compressed format and if so + // apply the compression to the displacment iff the result is8bit. + if (VM_Version::supports_evex() && is_evex_instruction) { + switch (tuple_type) { + case EVEX_FV: + if ((evex_encoding & VEX_W) == VEX_W) { + mod_idx += 2 + ((evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0; + } else { + mod_idx = ((evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0; + } + break; + + case EVEX_HV: + mod_idx = ((evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0; + break; + + case EVEX_FVM: + break; + + case EVEX_T1S: + switch (input_size_in_bits) { + case EVEX_8bit: + break; + + case EVEX_16bit: + mod_idx = 1; + break; + + case EVEX_32bit: + mod_idx = 2; + break; + + case EVEX_64bit: + mod_idx = 3; + break; + } + break; + + case EVEX_T1F: + case EVEX_T2: + case EVEX_T4: + mod_idx = (input_size_in_bits == EVEX_64bit) ? 1 : 0; + break; + + case EVEX_T8: + break; + + case EVEX_HVM: + break; + + case EVEX_QVM: + break; + + case EVEX_OVM: + break; + + case EVEX_M128: + break; + + case EVEX_DUP: + break; + + default: + assert(0, "no valid evex tuple_table entry"); + break; + } + + if (avx_vector_len >= AVX_128bit && avx_vector_len <= AVX_512bit) { + int disp_factor = tuple_table[tuple_type + mod_idx][avx_vector_len]; + if ((disp % disp_factor) == 0) { + int new_disp = disp / disp_factor; + if (is8bit(new_disp)) { + disp = new_disp; + } + } else { + return false; + } + } + } + return is8bit(disp); +} + + void Assembler::emit_operand(Register reg, Register base, Register index, Address::ScaleFactor scale, int disp, RelocationHolder const& rspec, @@ -296,7 +498,7 @@ assert(index != rsp, "illegal addressing mode"); emit_int8(0x04 | regenc); emit_int8(scale << 6 | indexenc | baseenc); - } else if (is8bit(disp) && rtype == relocInfo::none) { + } else if (emit_compressed_disp_byte(disp) && rtype == relocInfo::none) { // [base + index*scale + imm8] // [01 reg 100][ss index base] imm8 assert(index != rsp, "illegal addressing mode"); @@ -318,7 +520,7 @@ // [00 reg 100][00 100 100] emit_int8(0x04 | regenc); emit_int8(0x24); - } else if (is8bit(disp) && rtype == relocInfo::none) { + } else if (emit_compressed_disp_byte(disp) && rtype == relocInfo::none) { // [rsp + imm8] // [01 reg 100][00 100 100] disp8 emit_int8(0x44 | regenc); @@ -339,7 +541,7 @@ // [base] // [00 reg base] emit_int8(0x00 | regenc | baseenc); - } else if (is8bit(disp) && rtype == relocInfo::none) { + } else if (emit_compressed_disp_byte(disp) && rtype == relocInfo::none) { // [base + disp8] // [01 reg base] disp8 emit_int8(0x40 | regenc | baseenc); @@ -389,11 +591,20 @@ emit_data(disp, rspec, disp32_operand); } } + is_evex_instruction = false; } void Assembler::emit_operand(XMMRegister reg, Register base, Register index, Address::ScaleFactor scale, int disp, RelocationHolder const& rspec) { + if (UseAVX > 2) { + int xreg_enc = reg->encoding(); + if (xreg_enc > 15) { + XMMRegister new_reg = as_XMMRegister(xreg_enc & 0xf); + emit_operand((Register)new_reg, base, index, scale, disp, rspec); + return; + } + } emit_operand((Register)reg, base, index, scale, disp, rspec); } @@ -686,6 +897,29 @@ debug_only(has_disp32 = true); // has both kinds of operands! break; + case 0x62: // EVEX_4bytes + assert((UseAVX > 0), "shouldn't have EVEX prefix"); + assert(ip == inst+1, "no prefixes allowed"); + // no EVEX collisions, all instructions that have 0x62 opcodes + // have EVEX versions and are subopcodes of 0x66 + ip++; // skip P0 and exmaine W in P1 + is_64bit = ((VEX_W & *ip) == VEX_W); + ip++; // move to P2 + ip++; // skip P2, move to opcode + // To find the end of instruction (which == end_pc_operand). + switch (0xFF & *ip) { + case 0x61: // pcmpestri r, r/a, #8 + case 0x70: // pshufd r, r/a, #8 + case 0x73: // psrldq r, #8 + tail_size = 1; // the imm8 + break; + default: + break; + } + ip++; // skip opcode + debug_only(has_disp32 = true); // has both kinds of operands! + break; + case 0xD1: // sal a, 1; sar a, 1; shl a, 1; shr a, 1 case 0xD3: // sal a, %cl; sar a, %cl; shl a, %cl; shr a, %cl case 0xD9: // fld_s a; fst_s a; fstp_s a; fldcw a @@ -985,12 +1219,22 @@ void Assembler::addsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x58, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0x58, dst, src, VEX_SIMD_F2); + } else { + emit_simd_arith(0x58, dst, src, VEX_SIMD_F2); + } } void Assembler::addsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x58, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + emit_simd_arith_q(0x58, dst, src, VEX_SIMD_F2); + } else { + emit_simd_arith(0x58, dst, src, VEX_SIMD_F2); + } } void Assembler::addss(XMMRegister dst, XMMRegister src) { @@ -1000,20 +1244,26 @@ void Assembler::addss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } emit_simd_arith(0x58, dst, src, VEX_SIMD_F3); } void Assembler::aesdec(XMMRegister dst, Address src) { assert(VM_Version::supports_aes(), ""); InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + simd_prefix(dst, dst, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_38, false, AVX_128bit, true); emit_int8((unsigned char)0xDE); emit_operand(dst, src); } void Assembler::aesdec(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_aes(), ""); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_38, false, AVX_128bit, true); emit_int8((unsigned char)0xDE); emit_int8(0xC0 | encode); } @@ -1021,14 +1271,16 @@ void Assembler::aesdeclast(XMMRegister dst, Address src) { assert(VM_Version::supports_aes(), ""); InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + simd_prefix(dst, dst, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_38, false, AVX_128bit, true); emit_int8((unsigned char)0xDF); emit_operand(dst, src); } void Assembler::aesdeclast(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_aes(), ""); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_38, false, AVX_128bit, true); emit_int8((unsigned char)0xDF); emit_int8((unsigned char)(0xC0 | encode)); } @@ -1036,14 +1288,16 @@ void Assembler::aesenc(XMMRegister dst, Address src) { assert(VM_Version::supports_aes(), ""); InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + simd_prefix(dst, dst, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_38, false, AVX_128bit, true); emit_int8((unsigned char)0xDC); emit_operand(dst, src); } void Assembler::aesenc(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_aes(), ""); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_38, false, AVX_128bit, true); emit_int8((unsigned char)0xDC); emit_int8(0xC0 | encode); } @@ -1051,14 +1305,16 @@ void Assembler::aesenclast(XMMRegister dst, Address src) { assert(VM_Version::supports_aes(), ""); InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + simd_prefix(dst, dst, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_38, false, AVX_128bit, true); emit_int8((unsigned char)0xDD); emit_operand(dst, src); } void Assembler::aesenclast(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_aes(), ""); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_38, false, AVX_128bit, true); emit_int8((unsigned char)0xDD); emit_int8((unsigned char)(0xC0 | encode)); } @@ -1091,7 +1347,7 @@ void Assembler::andnl(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - int encode = vex_prefix_0F38_and_encode(dst, src1, src2); + int encode = vex_prefix_0F38_and_encode(dst, src1, src2, false); emit_int8((unsigned char)0xF2); emit_int8((unsigned char)(0xC0 | encode)); } @@ -1099,7 +1355,7 @@ void Assembler::andnl(Register dst, Register src1, Address src2) { InstructionMark im(this); assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - vex_prefix_0F38(dst, src1, src2); + vex_prefix_0F38(dst, src1, src2, false); emit_int8((unsigned char)0xF2); emit_operand(dst, src2); } @@ -1126,7 +1382,7 @@ void Assembler::blsil(Register dst, Register src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - int encode = vex_prefix_0F38_and_encode(rbx, dst, src); + int encode = vex_prefix_0F38_and_encode(rbx, dst, src, false); emit_int8((unsigned char)0xF3); emit_int8((unsigned char)(0xC0 | encode)); } @@ -1134,14 +1390,14 @@ void Assembler::blsil(Register dst, Address src) { InstructionMark im(this); assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - vex_prefix_0F38(rbx, dst, src); + vex_prefix_0F38(rbx, dst, src, false); emit_int8((unsigned char)0xF3); emit_operand(rbx, src); } void Assembler::blsmskl(Register dst, Register src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - int encode = vex_prefix_0F38_and_encode(rdx, dst, src); + int encode = vex_prefix_0F38_and_encode(rdx, dst, src, false); emit_int8((unsigned char)0xF3); emit_int8((unsigned char)(0xC0 | encode)); } @@ -1149,14 +1405,14 @@ void Assembler::blsmskl(Register dst, Address src) { InstructionMark im(this); assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - vex_prefix_0F38(rdx, dst, src); + vex_prefix_0F38(rdx, dst, src, false); emit_int8((unsigned char)0xF3); emit_operand(rdx, src); } void Assembler::blsrl(Register dst, Register src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - int encode = vex_prefix_0F38_and_encode(rcx, dst, src); + int encode = vex_prefix_0F38_and_encode(rcx, dst, src, false); emit_int8((unsigned char)0xF3); emit_int8((unsigned char)(0xC0 | encode)); } @@ -1164,7 +1420,7 @@ void Assembler::blsrl(Register dst, Address src) { InstructionMark im(this); assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - vex_prefix_0F38(rcx, dst, src); + vex_prefix_0F38(rcx, dst, src, false); emit_int8((unsigned char)0xF3); emit_operand(rcx, src); } @@ -1312,22 +1568,36 @@ // NOTE: dbx seems to decode this as comiss even though the // 0x66 is there. Strangly ucomisd comes out correct NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + emit_simd_arith_nonds_q(0x2F, dst, src, VEX_SIMD_66, true); + } else { + emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_66); + } } void Assembler::comisd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + emit_simd_arith_nonds_q(0x2F, dst, src, VEX_SIMD_66, true); + } else { + emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_66); + } } void Assembler::comiss(XMMRegister dst, Address src) { + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE); + emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE, true); } void Assembler::comiss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE); + emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE, true); } void Assembler::cpuid() { @@ -1347,36 +1617,61 @@ void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x5A, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0x5A, dst, src, VEX_SIMD_F2); + } else { + emit_simd_arith(0x5A, dst, src, VEX_SIMD_F2); + } } void Assembler::cvtsd2ss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x5A, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1F; + input_size_in_bits = EVEX_64bit; + emit_simd_arith_q(0x5A, dst, src, VEX_SIMD_F2); + } else { + emit_simd_arith(0x5A, dst, src, VEX_SIMD_F2); + } } void Assembler::cvtsi2sdl(XMMRegister dst, Register src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); + int encode = 0; + if (VM_Version::supports_evex()) { + encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F2, true); + } else { + encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, false); + } emit_int8(0x2A); emit_int8((unsigned char)(0xC0 | encode)); } void Assembler::cvtsi2sdl(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x2A, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + emit_simd_arith_q(0x2A, dst, src, VEX_SIMD_F2, true); + } else { + emit_simd_arith(0x2A, dst, src, VEX_SIMD_F2); + } } void Assembler::cvtsi2ssl(XMMRegister dst, Register src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, true); emit_int8(0x2A); emit_int8((unsigned char)(0xC0 | encode)); } void Assembler::cvtsi2ssl(XMMRegister dst, Address src) { + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_simd_arith(0x2A, dst, src, VEX_SIMD_F3); + emit_simd_arith(0x2A, dst, src, VEX_SIMD_F3, true); } void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) { @@ -1385,6 +1680,10 @@ } void Assembler::cvtss2sd(XMMRegister dst, Address src) { + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } NOT_LP64(assert(VM_Version::supports_sse2(), "")); emit_simd_arith(0x5A, dst, src, VEX_SIMD_F3); } @@ -1392,14 +1691,14 @@ void Assembler::cvttsd2sil(Register dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F2); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, true); emit_int8(0x2C); emit_int8((unsigned char)(0xC0 | encode)); } void Assembler::cvttss2sil(Register dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F3); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, true); emit_int8(0x2C); emit_int8((unsigned char)(0xC0 | encode)); } @@ -1414,15 +1713,29 @@ void Assembler::divsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x5E, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + emit_simd_arith_q(0x5E, dst, src, VEX_SIMD_F2); + } else { + emit_simd_arith(0x5E, dst, src, VEX_SIMD_F2); + } } void Assembler::divsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x5E, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0x5E, dst, src, VEX_SIMD_F2); + } else { + emit_simd_arith(0x5E, dst, src, VEX_SIMD_F2); + } } void Assembler::divss(XMMRegister dst, Address src) { + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } NOT_LP64(assert(VM_Version::supports_sse(), "")); emit_simd_arith(0x5E, dst, src, VEX_SIMD_F3); } @@ -1675,7 +1988,11 @@ void Assembler::movapd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith_nonds(0x28, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + emit_simd_arith_nonds_q(0x28, dst, src, VEX_SIMD_66, true); + } else { + emit_simd_arith_nonds(0x28, dst, src, VEX_SIMD_66); + } } void Assembler::movaps(XMMRegister dst, XMMRegister src) { @@ -1685,7 +2002,8 @@ void Assembler::movlhps(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, src, src, VEX_SIMD_NONE); + int encode = simd_prefix_and_encode(dst, src, src, VEX_SIMD_NONE, true, VEX_OPCODE_0F, + false, AVX_128bit); emit_int8(0x16); emit_int8((unsigned char)(0xC0 | encode)); } @@ -1698,6 +2016,51 @@ emit_operand(dst, src); } +void Assembler::kmovq(KRegister dst, KRegister src) { + NOT_LP64(assert(VM_Version::supports_evex(), "")); + int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE, + true, VEX_OPCODE_0F, true); + emit_int8((unsigned char)0x90); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::kmovq(KRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_evex(), "")); + int dst_enc = dst->encoding(); + int nds_enc = 0; + vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_NONE, + VEX_OPCODE_0F, true, AVX_128bit, true, true); + emit_int8((unsigned char)0x90); + emit_operand((Register)dst, src); +} + +void Assembler::kmovq(Address dst, KRegister src) { + NOT_LP64(assert(VM_Version::supports_evex(), "")); + int src_enc = src->encoding(); + int nds_enc = 0; + vex_prefix(dst, nds_enc, src_enc, VEX_SIMD_NONE, + VEX_OPCODE_0F, true, AVX_128bit, true, true); + emit_int8((unsigned char)0x90); + emit_operand((Register)src, dst); +} + +void Assembler::kmovql(KRegister dst, Register src) { + NOT_LP64(assert(VM_Version::supports_evex(), "")); + bool supports_bw = VM_Version::supports_avx512bw(); + VexSimdPrefix pre = supports_bw ? VEX_SIMD_F2 : VEX_SIMD_NONE; + int encode = kreg_prefix_and_encode(dst, knoreg, src, pre, true, + VEX_OPCODE_0F, supports_bw); + emit_int8((unsigned char)0x92); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::kmovdl(KRegister dst, Register src) { + NOT_LP64(assert(VM_Version::supports_evex(), "")); + VexSimdPrefix pre = VM_Version::supports_avx512bw() ? VEX_SIMD_F2 : VEX_SIMD_NONE; + int encode = kreg_prefix_and_encode(dst, knoreg, src, pre, true, VEX_OPCODE_0F, false); + emit_int8((unsigned char)0x92); + emit_int8((unsigned char)(0xC0 | encode)); +} void Assembler::movb(Address dst, int imm8) { InstructionMark im(this); @@ -1718,7 +2081,7 @@ void Assembler::movdl(XMMRegister dst, Register src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); + int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66, true); emit_int8(0x6E); emit_int8((unsigned char)(0xC0 | encode)); } @@ -1726,23 +2089,31 @@ void Assembler::movdl(Register dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); // swap src/dst to get correct prefix - int encode = simd_prefix_and_encode(src, dst, VEX_SIMD_66); + int encode = simd_prefix_and_encode(src, dst, VEX_SIMD_66, true); emit_int8(0x7E); emit_int8((unsigned char)(0xC0 | encode)); } void Assembler::movdl(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_66, true, VEX_OPCODE_0F); emit_int8(0x6E); emit_operand(dst, src); } void Assembler::movdl(Address dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_66, true); emit_int8(0x7E); emit_operand(src, dst); } @@ -1754,11 +2125,17 @@ void Assembler::movdqa(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_66); } void Assembler::movdqu(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_F3); } @@ -1769,8 +2146,11 @@ void Assembler::movdqu(Address dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_F3); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_F3, false); emit_int8(0x7F); emit_operand(src, dst); } @@ -1778,28 +2158,77 @@ // Move Unaligned 256bit Vector void Assembler::vmovdqu(XMMRegister dst, XMMRegister src) { assert(UseAVX > 0, ""); - bool vector256 = true; - int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_F3, vector256); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } + int vector_len = AVX_256bit; + int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_F3, vector_len); emit_int8(0x6F); emit_int8((unsigned char)(0xC0 | encode)); } void Assembler::vmovdqu(XMMRegister dst, Address src) { assert(UseAVX > 0, ""); - InstructionMark im(this); - bool vector256 = true; - vex_prefix(dst, xnoreg, src, VEX_SIMD_F3, vector256); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } + InstructionMark im(this); + int vector_len = AVX_256bit; + vex_prefix(dst, xnoreg, src, VEX_SIMD_F3, vector_len, false); emit_int8(0x6F); emit_operand(dst, src); } void Assembler::vmovdqu(Address dst, XMMRegister src) { assert(UseAVX > 0, ""); - InstructionMark im(this); - bool vector256 = true; + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } + InstructionMark im(this); + int vector_len = AVX_256bit; // swap src<->dst for encoding assert(src != xnoreg, "sanity"); - vex_prefix(src, xnoreg, dst, VEX_SIMD_F3, vector256); + vex_prefix(src, xnoreg, dst, VEX_SIMD_F3, vector_len, false); + emit_int8(0x7F); + emit_operand(src, dst); +} + +// Move Unaligned EVEX enabled Vector (programmable : 8,16,32,64) +void Assembler::evmovdqu(XMMRegister dst, XMMRegister src, int vector_len) { + assert(UseAVX > 0, ""); + int src_enc = src->encoding(); + int dst_enc = dst->encoding(); + int encode = vex_prefix_and_encode(dst_enc, 0, src_enc, VEX_SIMD_F3, VEX_OPCODE_0F, + true, vector_len, false, false); + emit_int8(0x6F); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::evmovdqu(XMMRegister dst, Address src, int vector_len) { + assert(UseAVX > 0, ""); + InstructionMark im(this); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + vex_prefix_q(dst, xnoreg, src, VEX_SIMD_F3, vector_len, false); + } else { + vex_prefix(dst, xnoreg, src, VEX_SIMD_F3, vector_len, false); + } + emit_int8(0x6F); + emit_operand(dst, src); +} + +void Assembler::evmovdqu(Address dst, XMMRegister src, int vector_len) { + assert(UseAVX > 0, ""); + InstructionMark im(this); + assert(src != xnoreg, "sanity"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + // swap src<->dst for encoding + vex_prefix_q(src, xnoreg, dst, VEX_SIMD_F3, vector_len, false); + } else { + // swap src<->dst for encoding + vex_prefix(src, xnoreg, dst, VEX_SIMD_F3, vector_len, false); + } emit_int8(0x7F); emit_operand(src, dst); } @@ -1845,7 +2274,11 @@ // The selection is done in MacroAssembler::movdbl() and movflt(). void Assembler::movlpd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x12, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } + emit_simd_arith(0x12, dst, src, VEX_SIMD_66, true); } void Assembler::movq( MMXRegister dst, Address src ) { @@ -1871,7 +2304,13 @@ void Assembler::movq(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_F3); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + simd_prefix_q(dst, xnoreg, src, VEX_SIMD_F3, true); + } else { + simd_prefix(dst, src, VEX_SIMD_F3, true, VEX_OPCODE_0F); + } emit_int8(0x7E); emit_operand(dst, src); } @@ -1879,7 +2318,14 @@ void Assembler::movq(Address dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + simd_prefix(src, xnoreg, dst, VEX_SIMD_66, true, + VEX_OPCODE_0F, true, AVX_128bit); + } else { + simd_prefix(dst, src, VEX_SIMD_66, true); + } emit_int8((unsigned char)0xD6); emit_operand(src, dst); } @@ -1902,36 +2348,60 @@ void Assembler::movsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x10, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0x10, dst, src, VEX_SIMD_F2, true); + } else { + emit_simd_arith(0x10, dst, src, VEX_SIMD_F2); + } } void Assembler::movsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + emit_simd_arith_nonds_q(0x10, dst, src, VEX_SIMD_F2, true); + } else { + emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F2); + } } void Assembler::movsd(Address dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + simd_prefix_q(src, xnoreg, dst, VEX_SIMD_F2); + } else { + simd_prefix(src, xnoreg, dst, VEX_SIMD_F2, false); + } emit_int8(0x11); emit_operand(src, dst); } void Assembler::movss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_simd_arith(0x10, dst, src, VEX_SIMD_F3); + emit_simd_arith(0x10, dst, src, VEX_SIMD_F3, true); } void Assembler::movss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F3); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } + emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F3, true); } void Assembler::movss(Address dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_F3); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_F3, false); emit_int8(0x11); emit_operand(src, dst); } @@ -2023,16 +2493,30 @@ void Assembler::mulsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x59, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + emit_simd_arith_q(0x59, dst, src, VEX_SIMD_F2); + } else { + emit_simd_arith(0x59, dst, src, VEX_SIMD_F2); + } } void Assembler::mulsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x59, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0x59, dst, src, VEX_SIMD_F2); + } else { + emit_simd_arith(0x59, dst, src, VEX_SIMD_F2); + } } void Assembler::mulss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } emit_simd_arith(0x59, dst, src, VEX_SIMD_F3); } @@ -2332,22 +2816,30 @@ void Assembler::packuswb(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); - emit_simd_arith(0x67, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_simd_arith(0x67, dst, src, VEX_SIMD_66, + false, (VM_Version::supports_avx512dq() == false)); } void Assembler::packuswb(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x67, dst, src, VEX_SIMD_66); -} - -void Assembler::vpackuswb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0x67, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256) { + emit_simd_arith(0x67, dst, src, VEX_SIMD_66, + false, (VM_Version::supports_avx512dq() == false)); +} + +void Assembler::vpackuswb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "some form of AVX must be enabled"); + emit_vex_arith(0x67, dst, nds, src, VEX_SIMD_66, vector_len, + false, (VM_Version::supports_avx512dq() == false)); +} + +void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, int vector_len) { assert(VM_Version::supports_avx2(), ""); - int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector256); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_3A, true, vector_len); emit_int8(0x00); emit_int8(0xC0 | encode); emit_int8(imm8); @@ -2361,7 +2853,8 @@ void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { assert(VM_Version::supports_sse4_2(), ""); InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A); + simd_prefix(dst, xnoreg, src, VEX_SIMD_66, false, VEX_OPCODE_0F_3A, + false, AVX_128bit, true); emit_int8(0x61); emit_operand(dst, src); emit_int8(imm8); @@ -2369,7 +2862,8 @@ void Assembler::pcmpestri(XMMRegister dst, XMMRegister src, int imm8) { assert(VM_Version::supports_sse4_2(), ""); - int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_3A, false, AVX_128bit, true); emit_int8(0x61); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(imm8); @@ -2377,7 +2871,8 @@ void Assembler::pextrd(Register dst, XMMRegister src, int imm8) { assert(VM_Version::supports_sse4_1(), ""); - int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, false); + int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, true, VEX_OPCODE_0F_3A, + false, AVX_128bit, (VM_Version::supports_avx512dq() == false)); emit_int8(0x16); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(imm8); @@ -2385,7 +2880,8 @@ void Assembler::pextrq(Register dst, XMMRegister src, int imm8) { assert(VM_Version::supports_sse4_1(), ""); - int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, true); + int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, true, VEX_OPCODE_0F_3A, + false, AVX_128bit, (VM_Version::supports_avx512dq() == false)); emit_int8(0x16); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(imm8); @@ -2393,7 +2889,8 @@ void Assembler::pinsrd(XMMRegister dst, Register src, int imm8) { assert(VM_Version::supports_sse4_1(), ""); - int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, VEX_OPCODE_0F_3A, false); + int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, true, VEX_OPCODE_0F_3A, + false, AVX_128bit, (VM_Version::supports_avx512dq() == false)); emit_int8(0x22); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(imm8); @@ -2401,7 +2898,8 @@ void Assembler::pinsrq(XMMRegister dst, Register src, int imm8) { assert(VM_Version::supports_sse4_1(), ""); - int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, VEX_OPCODE_0F_3A, true); + int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, true, VEX_OPCODE_0F_3A, + false, AVX_128bit, (VM_Version::supports_avx512dq() == false)); emit_int8(0x22); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(imm8); @@ -2409,15 +2907,18 @@ void Assembler::pmovzxbw(XMMRegister dst, Address src) { assert(VM_Version::supports_sse4_1(), ""); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_HVM; + } + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38); emit_int8(0x30); emit_operand(dst, src); } void Assembler::pmovzxbw(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_sse4_1(), ""); - int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38); emit_int8(0x30); emit_int8((unsigned char)(0xC0 | encode)); } @@ -2520,15 +3021,20 @@ void Assembler::pshufb(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_ssse3(), ""); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38, + false, AVX_128bit, (VM_Version::supports_avx512bw() == false)); emit_int8(0x00); emit_int8((unsigned char)(0xC0 | encode)); } void Assembler::pshufb(XMMRegister dst, Address src) { assert(VM_Version::supports_ssse3(), ""); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } + InstructionMark im(this); + simd_prefix(dst, dst, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38, + false, AVX_128bit, (VM_Version::supports_avx512bw() == false)); emit_int8(0x00); emit_operand(dst, src); } @@ -2545,8 +3051,12 @@ assert(isByte(mode), "invalid value"); NOT_LP64(assert(VM_Version::supports_sse2(), "")); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + InstructionMark im(this); + simd_prefix(dst, src, VEX_SIMD_66, false); emit_int8(0x70); emit_operand(dst, src); emit_int8(mode & 0xFF); @@ -2555,7 +3065,8 @@ void Assembler::pshuflw(XMMRegister dst, XMMRegister src, int mode) { assert(isByte(mode), "invalid value"); NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith_nonds(0x70, dst, src, VEX_SIMD_F2); + emit_simd_arith_nonds(0x70, dst, src, VEX_SIMD_F2, false, + (VM_Version::supports_avx512bw() == false)); emit_int8(mode & 0xFF); } @@ -2563,8 +3074,12 @@ assert(isByte(mode), "invalid value"); NOT_LP64(assert(VM_Version::supports_sse2(), "")); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } + InstructionMark im(this); + simd_prefix(dst, xnoreg, src, VEX_SIMD_F2, false, VEX_OPCODE_0F, + false, AVX_128bit, (VM_Version::supports_avx512bw() == false)); emit_int8(0x70); emit_operand(dst, src); emit_int8(mode & 0xFF); @@ -2573,7 +3088,8 @@ void Assembler::psrldq(XMMRegister dst, int shift) { // Shift 128 bit value in xmm register by number of bytes. NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(xmm3, dst, dst, VEX_SIMD_66); + int encode = simd_prefix_and_encode(xmm3, dst, dst, VEX_SIMD_66, true, VEX_OPCODE_0F, + false, AVX_128bit, (VM_Version::supports_avx512bw() == false)); emit_int8(0x73); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(shift); @@ -2583,14 +3099,15 @@ assert(VM_Version::supports_sse4_1(), ""); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + simd_prefix(dst, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38); emit_int8(0x17); emit_operand(dst, src); } void Assembler::ptest(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_sse4_1(), ""); - int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, + false, VEX_OPCODE_0F_38); emit_int8(0x17); emit_int8((unsigned char)(0xC0 | encode)); } @@ -2598,19 +3115,20 @@ void Assembler::vptest(XMMRegister dst, Address src) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); - bool vector256 = true; + int vector_len = AVX_256bit; assert(dst != xnoreg, "sanity"); int dst_enc = dst->encoding(); // swap src<->dst for encoding - vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector256); + vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len); emit_int8(0x17); emit_operand(dst, src); } void Assembler::vptest(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - bool vector256 = true; - int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector256, VEX_OPCODE_0F_38); + int vector_len = AVX_256bit; + int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, + vector_len, VEX_OPCODE_0F_38); emit_int8(0x17); emit_int8((unsigned char)(0xC0 | encode)); } @@ -2618,6 +3136,9 @@ void Assembler::punpcklbw(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } emit_simd_arith(0x60, dst, src, VEX_SIMD_66); } @@ -2629,6 +3150,10 @@ void Assembler::punpckldq(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } emit_simd_arith(0x62, dst, src, VEX_SIMD_66); } @@ -2838,12 +3363,22 @@ void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x51, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0x51, dst, src, VEX_SIMD_F2); + } else { + emit_simd_arith(0x51, dst, src, VEX_SIMD_F2); + } } void Assembler::sqrtsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x51, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + emit_simd_arith_q(0x51, dst, src, VEX_SIMD_F2); + } else { + emit_simd_arith(0x51, dst, src, VEX_SIMD_F2); + } } void Assembler::sqrtss(XMMRegister dst, XMMRegister src) { @@ -2857,6 +3392,10 @@ void Assembler::sqrtss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } emit_simd_arith(0x51, dst, src, VEX_SIMD_F3); } @@ -2907,12 +3446,20 @@ void Assembler::subsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x5C, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0x5C, dst, src, VEX_SIMD_F2); + } else { + emit_simd_arith(0x5C, dst, src, VEX_SIMD_F2); + } } void Assembler::subsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x5C, dst, src, VEX_SIMD_F2); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + } + emit_simd_arith_q(0x5C, dst, src, VEX_SIMD_F2); } void Assembler::subss(XMMRegister dst, XMMRegister src) { @@ -2922,6 +3469,10 @@ void Assembler::subss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } emit_simd_arith(0x5C, dst, src, VEX_SIMD_F3); } @@ -2978,22 +3529,36 @@ void Assembler::ucomisd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + emit_simd_arith_nonds_q(0x2E, dst, src, VEX_SIMD_66, true); + } else { + emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66); + } } void Assembler::ucomisd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + emit_simd_arith_nonds_q(0x2E, dst, src, VEX_SIMD_66, true); + } else { + emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66); + } } void Assembler::ucomiss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } + emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE, true); } void Assembler::ucomiss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE); + emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE, true); } void Assembler::xabort(int8_t imm8) { @@ -3075,82 +3640,138 @@ void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0x58, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } else { + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } } void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0x58, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } else { + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } } void Assembler::vaddss(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F3, AVX_128bit); } void Assembler::vaddss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F3, AVX_128bit); } void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0x5E, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } else { + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } } void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0x5E, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } else { + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } } void Assembler::vdivss(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F3, AVX_128bit); } void Assembler::vdivss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F3, AVX_128bit); } void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0x59, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } else { + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } } void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0x59, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } else { + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } } void Assembler::vmulss(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F3, AVX_128bit); } void Assembler::vmulss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F3, AVX_128bit); } void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0x5C, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } else { + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } } void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0x5C, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } else { + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F2, AVX_128bit); + } } void Assembler::vsubss(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T1S; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F3, AVX_128bit); } void Assembler::vsubss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F3, AVX_128bit); } //====================VECTOR ARITHMETIC===================================== @@ -3159,7 +3780,11 @@ void Assembler::addpd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x58, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0x58, dst, src, VEX_SIMD_66); + } else { + emit_simd_arith(0x58, dst, src, VEX_SIMD_66); + } } void Assembler::addps(XMMRegister dst, XMMRegister src) { @@ -3167,29 +3792,47 @@ emit_simd_arith(0x58, dst, src, VEX_SIMD_NONE); } -void Assembler::vaddpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { +void Assembler::vaddpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vaddps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0x58, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_66, vector_len); + } +} + +void Assembler::vaddps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_NONE, vector256); -} - -void Assembler::vaddpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_NONE, vector_len); +} + +void Assembler::vaddpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vaddps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0x58, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_66, vector_len); + } +} + +void Assembler::vaddps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_NONE, vector256); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_NONE, vector_len); } void Assembler::subpd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x5C, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0x5C, dst, src, VEX_SIMD_66); + } else { + emit_simd_arith(0x5C, dst, src, VEX_SIMD_66); + } } void Assembler::subps(XMMRegister dst, XMMRegister src) { @@ -3197,29 +3840,47 @@ emit_simd_arith(0x5C, dst, src, VEX_SIMD_NONE); } -void Assembler::vsubpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { +void Assembler::vsubpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vsubps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0x5C, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_66, vector_len); + } +} + +void Assembler::vsubps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_NONE, vector256); -} - -void Assembler::vsubpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_NONE, vector_len); +} + +void Assembler::vsubpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vsubps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0x5C, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_66, vector_len); + } +} + +void Assembler::vsubps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_NONE, vector256); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_NONE, vector_len); } void Assembler::mulpd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x59, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0x59, dst, src, VEX_SIMD_66); + } else { + emit_simd_arith(0x59, dst, src, VEX_SIMD_66); + } } void Assembler::mulps(XMMRegister dst, XMMRegister src) { @@ -3227,29 +3888,47 @@ emit_simd_arith(0x59, dst, src, VEX_SIMD_NONE); } -void Assembler::vmulpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { +void Assembler::vmulpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vmulps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0x59, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_66, vector_len); + } +} + +void Assembler::vmulps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_NONE, vector256); -} - -void Assembler::vmulpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_NONE, vector_len); +} + +void Assembler::vmulpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vmulps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0x59, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_66, vector_len); + } +} + +void Assembler::vmulps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_NONE, vector256); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_NONE, vector_len); } void Assembler::divpd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x5E, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0x5E, dst, src, VEX_SIMD_66); + } else { + emit_simd_arith(0x5E, dst, src, VEX_SIMD_66); + } } void Assembler::divps(XMMRegister dst, XMMRegister src) { @@ -3257,118 +3936,199 @@ emit_simd_arith(0x5E, dst, src, VEX_SIMD_NONE); } -void Assembler::vdivpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { +void Assembler::vdivpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vdivps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0x5E, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_66, vector_len); + } +} + +void Assembler::vdivps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector256); -} - -void Assembler::vdivpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector_len); +} + +void Assembler::vdivpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vdivps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0x5E, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_66, vector_len); + } +} + +void Assembler::vdivps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector256); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector_len); } void Assembler::andpd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x54, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) { + emit_simd_arith_q(0x54, dst, src, VEX_SIMD_66); + } else { + emit_simd_arith(0x54, dst, src, VEX_SIMD_66, false, true); + } } void Assembler::andps(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE); + emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE, false, + (VM_Version::supports_avx512dq() == false)); } void Assembler::andps(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE, + false, (VM_Version::supports_avx512dq() == false)); } void Assembler::andpd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x54, dst, src, VEX_SIMD_66); -} - -void Assembler::vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_64bit; + emit_simd_arith_q(0x54, dst, src, VEX_SIMD_66); + } else { + emit_simd_arith(0x54, dst, src, VEX_SIMD_66, false, true); + } +} + +void Assembler::vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) { + emit_vex_arith_q(0x54, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector_len, true); + } +} + +void Assembler::vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector256); -} - -void Assembler::vandpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + bool legacy_mode = (VM_Version::supports_avx512dq() == false); + emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector_len, legacy_mode); +} + +void Assembler::vandpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vandps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0x54, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector_len, true); + } +} + +void Assembler::vandps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector256); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector_len, + (VM_Version::supports_avx512dq() == false)); } void Assembler::xorpd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x57, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) { + emit_simd_arith_q(0x57, dst, src, VEX_SIMD_66); + } else { + emit_simd_arith(0x57, dst, src, VEX_SIMD_66, false, true); + } } void Assembler::xorps(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE); + emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE, + false, (VM_Version::supports_avx512dq() == false)); } void Assembler::xorpd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0x57, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_64bit; + emit_simd_arith_q(0x57, dst, src, VEX_SIMD_66); + } else { + emit_simd_arith(0x57, dst, src, VEX_SIMD_66, false, true); + } } void Assembler::xorps(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE); -} - -void Assembler::vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE, false, + (VM_Version::supports_avx512dq() == false)); +} + +void Assembler::vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) { + emit_vex_arith_q(0x57, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector_len, true); + } +} + +void Assembler::vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector256); -} - -void Assembler::vxorpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector_len, + (VM_Version::supports_avx512dq() == false)); +} + +void Assembler::vxorpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vxorps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0x57, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector_len, true); + } +} + +void Assembler::vxorps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); - emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector256); -} - + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector_len, + (VM_Version::supports_avx512dq() == false)); +} // Integer vector arithmetic -void Assembler::vphaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256, VEX_OPCODE_0F_38); +void Assembler::vphaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx() && (vector_len == 0) || + VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, + VEX_OPCODE_0F_38, true, false); emit_int8(0x01); emit_int8((unsigned char)(0xC0 | encode)); } -void Assembler::vphaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256, VEX_OPCODE_0F_38); +void Assembler::vphaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx() && (vector_len == 0) || + VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, + VEX_OPCODE_0F_38, true, false); emit_int8(0x02); emit_int8((unsigned char)(0xC0 | encode)); } @@ -3390,61 +4150,89 @@ void Assembler::paddq(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0xD4, dst, src, VEX_SIMD_66); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0xD4, dst, src, VEX_SIMD_66); + } else { + emit_simd_arith(0xD4, dst, src, VEX_SIMD_66); + } } void Assembler::phaddw(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse3(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_38, false, AVX_128bit, true); emit_int8(0x01); emit_int8((unsigned char)(0xC0 | encode)); } void Assembler::phaddd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse3(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false, + VEX_OPCODE_0F_38, false, AVX_128bit, true); emit_int8(0x02); emit_int8((unsigned char)(0xC0 | encode)); } -void Assembler::vpaddb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xFE, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xD4, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpaddb(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpaddw(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpaddd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xFE, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xD4, dst, nds, src, VEX_SIMD_66, vector256); +void Assembler::vpaddb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); +} + +void Assembler::vpaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); +} + +void Assembler::vpaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xFE, dst, nds, src, VEX_SIMD_66, vector_len); +} + +void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0xD4, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0xD4, dst, nds, src, VEX_SIMD_66, vector_len); + } +} + +void Assembler::vpaddb(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } + emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector_len); +} + +void Assembler::vpaddw(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } + emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector_len); +} + +void Assembler::vpaddd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0xFE, dst, nds, src, VEX_SIMD_66, vector_len); +} + +void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0xD4, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0xD4, dst, nds, src, VEX_SIMD_66, vector_len); + } } void Assembler::psubb(XMMRegister dst, XMMRegister src) { @@ -3464,84 +4252,149 @@ void Assembler::psubq(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0xFB, dst, src, VEX_SIMD_66); -} - -void Assembler::vpsubb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpsubw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpsubd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xFA, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpsubq(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xFB, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpsubb(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpsubw(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpsubd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xFA, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpsubq(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xFB, dst, nds, src, VEX_SIMD_66, vector256); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0xFB, dst, src, VEX_SIMD_66); + } else { + emit_simd_arith(0xFB, dst, src, VEX_SIMD_66); + } +} + +void Assembler::vpsubb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); +} + +void Assembler::vpsubw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); +} + +void Assembler::vpsubd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xFA, dst, nds, src, VEX_SIMD_66, vector_len); +} + +void Assembler::vpsubq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0xFB, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0xFB, dst, nds, src, VEX_SIMD_66, vector_len); + } +} + +void Assembler::vpsubb(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } + emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); +} + +void Assembler::vpsubw(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } + emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); +} + +void Assembler::vpsubd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0xFA, dst, nds, src, VEX_SIMD_66, vector_len); +} + +void Assembler::vpsubq(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_64bit; + emit_vex_arith_q(0xFB, dst, nds, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0xFB, dst, nds, src, VEX_SIMD_66, vector_len); + } } void Assembler::pmullw(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0xD5, dst, src, VEX_SIMD_66); + emit_simd_arith(0xD5, dst, src, VEX_SIMD_66, + (VM_Version::supports_avx512bw() == false)); } void Assembler::pmulld(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_sse4_1(), ""); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, + false, VEX_OPCODE_0F_38); emit_int8(0x40); emit_int8((unsigned char)(0xC0 | encode)); } -void Assembler::vpmullw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpmulld(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256, VEX_OPCODE_0F_38); +void Assembler::vpmullw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); +} + +void Assembler::vpmulld(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, + vector_len, VEX_OPCODE_0F_38); emit_int8(0x40); emit_int8((unsigned char)(0xC0 | encode)); } -void Assembler::vpmullw(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpmulld(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - InstructionMark im(this); +void Assembler::vpmullq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 2, "requires some form of AVX"); + int src_enc = src->encoding(); int dst_enc = dst->encoding(); int nds_enc = nds->is_valid() ? nds->encoding() : 0; - vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector256); + int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66, + VEX_OPCODE_0F_38, true, vector_len, false, false); + emit_int8(0x40); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vpmullw(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FVM; + } + emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector_len); +} + +void Assembler::vpmulld(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + InstructionMark im(this); + int dst_enc = dst->encoding(); + int nds_enc = nds->is_valid() ? nds->encoding() : 0; + vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_66, + VEX_OPCODE_0F_38, false, vector_len); + emit_int8(0x40); + emit_operand(dst, src); +} + +void Assembler::vpmullq(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_64bit; + } + InstructionMark im(this); + int dst_enc = dst->encoding(); + int nds_enc = nds->is_valid() ? nds->encoding() : 0; + vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, true, vector_len); emit_int8(0x40); emit_operand(dst, src); } @@ -3550,7 +4403,8 @@ void Assembler::psllw(XMMRegister dst, int shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); // XMM6 is for /6 encoding: 66 0F 71 /6 ib - int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66); + int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F, + false, AVX_128bit, (VM_Version::supports_avx512bw() == false)); emit_int8(0x71); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(shift & 0xFF); @@ -3559,7 +4413,7 @@ void Assembler::pslld(XMMRegister dst, int shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); // XMM6 is for /6 encoding: 66 0F 72 /6 ib - int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66); + int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, false); emit_int8(0x72); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(shift & 0xFF); @@ -3568,7 +4422,7 @@ void Assembler::psllq(XMMRegister dst, int shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); // XMM6 is for /6 encoding: 66 0F 73 /6 ib - int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66); + int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F, true); emit_int8(0x73); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(shift & 0xFF); @@ -3576,7 +4430,8 @@ void Assembler::psllw(XMMRegister dst, XMMRegister shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0xF1, dst, shift, VEX_SIMD_66); + emit_simd_arith(0xF1, dst, shift, VEX_SIMD_66, false, + (VM_Version::supports_avx512bw() == false)); } void Assembler::pslld(XMMRegister dst, XMMRegister shift) { @@ -3586,50 +4441,65 @@ void Assembler::psllq(XMMRegister dst, XMMRegister shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0xF3, dst, shift, VEX_SIMD_66); -} - -void Assembler::vpsllw(XMMRegister dst, XMMRegister src, int shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0xF3, dst, shift, VEX_SIMD_66); + } else { + emit_simd_arith(0xF3, dst, shift, VEX_SIMD_66); + } +} + +void Assembler::vpsllw(XMMRegister dst, XMMRegister src, int shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); // XMM6 is for /6 encoding: 66 0F 71 /6 ib - emit_vex_arith(0x71, xmm6, dst, src, VEX_SIMD_66, vector256); + emit_vex_arith(0x71, xmm6, dst, src, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); emit_int8(shift & 0xFF); } -void Assembler::vpslld(XMMRegister dst, XMMRegister src, int shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); +void Assembler::vpslld(XMMRegister dst, XMMRegister src, int shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); // XMM6 is for /6 encoding: 66 0F 72 /6 ib - emit_vex_arith(0x72, xmm6, dst, src, VEX_SIMD_66, vector256); + emit_vex_arith(0x72, xmm6, dst, src, VEX_SIMD_66, vector_len); emit_int8(shift & 0xFF); } -void Assembler::vpsllq(XMMRegister dst, XMMRegister src, int shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); +void Assembler::vpsllq(XMMRegister dst, XMMRegister src, int shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); // XMM6 is for /6 encoding: 66 0F 73 /6 ib - emit_vex_arith(0x73, xmm6, dst, src, VEX_SIMD_66, vector256); + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0x73, xmm6, dst, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x73, xmm6, dst, src, VEX_SIMD_66, vector_len); + } emit_int8(shift & 0xFF); } -void Assembler::vpsllw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xF1, dst, src, shift, VEX_SIMD_66, vector256); -} - -void Assembler::vpslld(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xF2, dst, src, shift, VEX_SIMD_66, vector256); -} - -void Assembler::vpsllq(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xF3, dst, src, shift, VEX_SIMD_66, vector256); +void Assembler::vpsllw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xF1, dst, src, shift, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); +} + +void Assembler::vpslld(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xF2, dst, src, shift, VEX_SIMD_66, vector_len); +} + +void Assembler::vpsllq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0xF3, dst, src, shift, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0xF3, dst, src, shift, VEX_SIMD_66, vector_len); + } } // Shift packed integers logically right by specified number of bits. void Assembler::psrlw(XMMRegister dst, int shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); // XMM2 is for /2 encoding: 66 0F 71 /2 ib - int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66); + int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F, + (VM_Version::supports_avx512bw() == false)); emit_int8(0x71); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(shift & 0xFF); @@ -3638,7 +4508,7 @@ void Assembler::psrld(XMMRegister dst, int shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); // XMM2 is for /2 encoding: 66 0F 72 /2 ib - int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66); + int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, false); emit_int8(0x72); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(shift & 0xFF); @@ -3649,7 +4519,12 @@ // shifts 128 bit value in xmm register by number of bytes. NOT_LP64(assert(VM_Version::supports_sse2(), "")); // XMM2 is for /2 encoding: 66 0F 73 /2 ib - int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66); + int encode = 0; + if (VM_Version::supports_evex() && VM_Version::supports_avx512bw()) { + encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, true, VEX_OPCODE_0F, false); + } else { + encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F, true); + } emit_int8(0x73); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(shift & 0xFF); @@ -3657,7 +4532,8 @@ void Assembler::psrlw(XMMRegister dst, XMMRegister shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0xD1, dst, shift, VEX_SIMD_66); + emit_simd_arith(0xD1, dst, shift, VEX_SIMD_66, false, + (VM_Version::supports_avx512bw() == false)); } void Assembler::psrld(XMMRegister dst, XMMRegister shift) { @@ -3667,50 +4543,65 @@ void Assembler::psrlq(XMMRegister dst, XMMRegister shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0xD3, dst, shift, VEX_SIMD_66); -} - -void Assembler::vpsrlw(XMMRegister dst, XMMRegister src, int shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + if (VM_Version::supports_evex()) { + emit_simd_arith_q(0xD3, dst, shift, VEX_SIMD_66); + } else { + emit_simd_arith(0xD3, dst, shift, VEX_SIMD_66); + } +} + +void Assembler::vpsrlw(XMMRegister dst, XMMRegister src, int shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); // XMM2 is for /2 encoding: 66 0F 73 /2 ib - emit_vex_arith(0x71, xmm2, dst, src, VEX_SIMD_66, vector256); + emit_vex_arith(0x71, xmm2, dst, src, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); emit_int8(shift & 0xFF); } -void Assembler::vpsrld(XMMRegister dst, XMMRegister src, int shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); +void Assembler::vpsrld(XMMRegister dst, XMMRegister src, int shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); // XMM2 is for /2 encoding: 66 0F 73 /2 ib - emit_vex_arith(0x72, xmm2, dst, src, VEX_SIMD_66, vector256); + emit_vex_arith(0x72, xmm2, dst, src, VEX_SIMD_66, vector_len); emit_int8(shift & 0xFF); } -void Assembler::vpsrlq(XMMRegister dst, XMMRegister src, int shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); +void Assembler::vpsrlq(XMMRegister dst, XMMRegister src, int shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); // XMM2 is for /2 encoding: 66 0F 73 /2 ib - emit_vex_arith(0x73, xmm2, dst, src, VEX_SIMD_66, vector256); + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0x73, xmm2, dst, src, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0x73, xmm2, dst, src, VEX_SIMD_66, vector_len); + } emit_int8(shift & 0xFF); } -void Assembler::vpsrlw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xD1, dst, src, shift, VEX_SIMD_66, vector256); -} - -void Assembler::vpsrld(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xD2, dst, src, shift, VEX_SIMD_66, vector256); -} - -void Assembler::vpsrlq(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xD3, dst, src, shift, VEX_SIMD_66, vector256); +void Assembler::vpsrlw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xD1, dst, src, shift, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); +} + +void Assembler::vpsrld(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xD2, dst, src, shift, VEX_SIMD_66, vector_len); +} + +void Assembler::vpsrlq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + emit_vex_arith_q(0xD3, dst, src, shift, VEX_SIMD_66, vector_len); + } else { + emit_vex_arith(0xD3, dst, src, shift, VEX_SIMD_66, vector_len); + } } // Shift packed integers arithmetically right by specified number of bits. void Assembler::psraw(XMMRegister dst, int shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); // XMM4 is for /4 encoding: 66 0F 71 /4 ib - int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66); + int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F, + (VM_Version::supports_avx512bw() == false)); emit_int8(0x71); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(shift & 0xFF); @@ -3719,7 +4610,7 @@ void Assembler::psrad(XMMRegister dst, int shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); // XMM4 is for /4 encoding: 66 0F 72 /4 ib - int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66); + int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66, false); emit_int8(0x72); emit_int8((unsigned char)(0xC0 | encode)); emit_int8(shift & 0xFF); @@ -3727,7 +4618,8 @@ void Assembler::psraw(XMMRegister dst, XMMRegister shift) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - emit_simd_arith(0xE1, dst, shift, VEX_SIMD_66); + emit_simd_arith(0xE1, dst, shift, VEX_SIMD_66, + (VM_Version::supports_avx512bw() == false)); } void Assembler::psrad(XMMRegister dst, XMMRegister shift) { @@ -3735,28 +4627,30 @@ emit_simd_arith(0xE2, dst, shift, VEX_SIMD_66); } -void Assembler::vpsraw(XMMRegister dst, XMMRegister src, int shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); +void Assembler::vpsraw(XMMRegister dst, XMMRegister src, int shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); // XMM4 is for /4 encoding: 66 0F 71 /4 ib - emit_vex_arith(0x71, xmm4, dst, src, VEX_SIMD_66, vector256); + emit_vex_arith(0x71, xmm4, dst, src, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); emit_int8(shift & 0xFF); } -void Assembler::vpsrad(XMMRegister dst, XMMRegister src, int shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); +void Assembler::vpsrad(XMMRegister dst, XMMRegister src, int shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); // XMM4 is for /4 encoding: 66 0F 71 /4 ib - emit_vex_arith(0x72, xmm4, dst, src, VEX_SIMD_66, vector256); + emit_vex_arith(0x72, xmm4, dst, src, VEX_SIMD_66, vector_len); emit_int8(shift & 0xFF); } -void Assembler::vpsraw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xE1, dst, src, shift, VEX_SIMD_66, vector256); -} - -void Assembler::vpsrad(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xE2, dst, src, shift, VEX_SIMD_66, vector256); +void Assembler::vpsraw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xE1, dst, src, shift, VEX_SIMD_66, vector_len, + (VM_Version::supports_avx512bw() == false)); +} + +void Assembler::vpsrad(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xE2, dst, src, shift, VEX_SIMD_66, vector_len); } @@ -3766,14 +4660,18 @@ emit_simd_arith(0xDB, dst, src, VEX_SIMD_66); } -void Assembler::vpand(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xDB, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpand(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xDB, dst, nds, src, VEX_SIMD_66, vector256); +void Assembler::vpand(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xDB, dst, nds, src, VEX_SIMD_66, vector_len); +} + +void Assembler::vpand(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0xDB, dst, nds, src, VEX_SIMD_66, vector_len); } void Assembler::por(XMMRegister dst, XMMRegister src) { @@ -3781,14 +4679,18 @@ emit_simd_arith(0xEB, dst, src, VEX_SIMD_66); } -void Assembler::vpor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xEB, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpor(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xEB, dst, nds, src, VEX_SIMD_66, vector256); +void Assembler::vpor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xEB, dst, nds, src, VEX_SIMD_66, vector_len); +} + +void Assembler::vpor(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0xEB, dst, nds, src, VEX_SIMD_66, vector_len); } void Assembler::pxor(XMMRegister dst, XMMRegister src) { @@ -3796,21 +4698,25 @@ emit_simd_arith(0xEF, dst, src, VEX_SIMD_66); } -void Assembler::vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xEF, dst, nds, src, VEX_SIMD_66, vector256); -} - -void Assembler::vpxor(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - emit_vex_arith(0xEF, dst, nds, src, VEX_SIMD_66, vector256); +void Assembler::vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + emit_vex_arith(0xEF, dst, nds, src, VEX_SIMD_66, vector_len); +} + +void Assembler::vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_FV; + input_size_in_bits = EVEX_32bit; + } + emit_vex_arith(0xEF, dst, nds, src, VEX_SIMD_66, vector_len); } void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - bool vector256 = true; - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256, VEX_OPCODE_0F_3A); + int vector_len = AVX_256bit; + int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A); emit_int8(0x18); emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - insert into lower 128 bits @@ -3818,14 +4724,51 @@ emit_int8(0x01); } -void Assembler::vinsertf128h(XMMRegister dst, Address src) { +void Assembler::vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src) { + assert(VM_Version::supports_evex(), ""); + int vector_len = AVX_512bit; + int src_enc = src->encoding(); + int dst_enc = dst->encoding(); + int nds_enc = nds->is_valid() ? nds->encoding() : 0; + int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66, + VEX_OPCODE_0F_3A, true, vector_len, false, false); + emit_int8(0x1A); + emit_int8((unsigned char)(0xC0 | encode)); + // 0x00 - insert into lower 256 bits + // 0x01 - insert into upper 256 bits + emit_int8(0x01); +} + +void Assembler::vinsertf64x4h(XMMRegister dst, Address src) { assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - bool vector256 = true; + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T4; + input_size_in_bits = EVEX_64bit; + } + InstructionMark im(this); + int vector_len = AVX_512bit; assert(dst != xnoreg, "sanity"); int dst_enc = dst->encoding(); // swap src<->dst for encoding - vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector256); + vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector_len); + emit_int8(0x1A); + emit_operand(dst, src); + // 0x01 - insert into upper 128 bits + emit_int8(0x01); +} + +void Assembler::vinsertf128h(XMMRegister dst, Address src) { + assert(VM_Version::supports_avx(), ""); + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T4; + input_size_in_bits = EVEX_32bit; + } + InstructionMark im(this); + int vector_len = AVX_256bit; + assert(dst != xnoreg, "sanity"); + int dst_enc = dst->encoding(); + // swap src<->dst for encoding + vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len); emit_int8(0x18); emit_operand(dst, src); // 0x01 - insert into upper 128 bits @@ -3834,8 +4777,8 @@ void Assembler::vextractf128h(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - bool vector256 = true; - int encode = vex_prefix_and_encode(src, xnoreg, dst, VEX_SIMD_66, vector256, VEX_OPCODE_0F_3A); + int vector_len = AVX_256bit; + int encode = vex_prefix_and_encode(src, xnoreg, dst, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A); emit_int8(0x19); emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - insert into lower 128 bits @@ -3845,11 +4788,15 @@ void Assembler::vextractf128h(Address dst, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - bool vector256 = true; + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T4; + input_size_in_bits = EVEX_32bit; + } + InstructionMark im(this); + int vector_len = AVX_256bit; assert(src != xnoreg, "sanity"); int src_enc = src->encoding(); - vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector256); + vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len); emit_int8(0x19); emit_operand(src, dst); // 0x01 - extract from upper 128 bits @@ -3858,8 +4805,8 @@ void Assembler::vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx2(), ""); - bool vector256 = true; - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256, VEX_OPCODE_0F_3A); + int vector_len = AVX_256bit; + int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A); emit_int8(0x38); emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - insert into lower 128 bits @@ -3867,38 +4814,169 @@ emit_int8(0x01); } +void Assembler::vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src) { + assert(VM_Version::supports_evex(), ""); + int vector_len = AVX_512bit; + int src_enc = src->encoding(); + int dst_enc = dst->encoding(); + int nds_enc = nds->is_valid() ? nds->encoding() : 0; + int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, + VM_Version::supports_avx512dq(), vector_len, false, false); + emit_int8(0x38); + emit_int8((unsigned char)(0xC0 | encode)); + // 0x00 - insert into lower 256 bits + // 0x01 - insert into upper 256 bits + emit_int8(0x01); +} + void Assembler::vinserti128h(XMMRegister dst, Address src) { assert(VM_Version::supports_avx2(), ""); - InstructionMark im(this); - bool vector256 = true; + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T4; + input_size_in_bits = EVEX_32bit; + } + InstructionMark im(this); + int vector_len = AVX_256bit; assert(dst != xnoreg, "sanity"); int dst_enc = dst->encoding(); // swap src<->dst for encoding - vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector256); + vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len); emit_int8(0x38); emit_operand(dst, src); // 0x01 - insert into upper 128 bits emit_int8(0x01); } +void Assembler::vextracti128h(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_avx(), ""); + int vector_len = AVX_256bit; + int encode = vex_prefix_and_encode(src, xnoreg, dst, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A); + emit_int8(0x39); + emit_int8((unsigned char)(0xC0 | encode)); + // 0x00 - insert into lower 128 bits + // 0x01 - insert into upper 128 bits + emit_int8(0x01); +} + void Assembler::vextracti128h(Address dst, XMMRegister src) { assert(VM_Version::supports_avx2(), ""); - InstructionMark im(this); - bool vector256 = true; + if (VM_Version::supports_evex()) { + tuple_type = EVEX_T4; + input_size_in_bits = EVEX_32bit; + } + InstructionMark im(this); + int vector_len = AVX_256bit; assert(src != xnoreg, "sanity"); int src_enc = src->encoding(); - vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector256); + vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len); emit_int8(0x39); emit_operand(src, dst); // 0x01 - extract from upper 128 bits emit_int8(0x01); } +void Assembler::vextracti64x4h(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_evex(), ""); + int vector_len = AVX_512bit; + int src_enc = src->encoding(); + int dst_enc = dst->encoding(); + int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, + true, vector_len, false, false); + emit_int8(0x3B); + emit_int8((unsigned char)(0xC0 | encode));