BitOpsTest.java revision 12651:6ef01bd40ce2
1169689Skan/* 2169689Skan * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. 3169689Skan * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4169689Skan * 5169689Skan * This code is free software; you can redistribute it and/or modify it 6169689Skan * under the terms of the GNU General Public License version 2 only, as 7169689Skan * published by the Free Software Foundation. 8169689Skan * 9169689Skan * This code is distributed in the hope that it will be useful, but WITHOUT 10169689Skan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11169689Skan * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12169689Skan * version 2 for more details (a copy is included in the LICENSE file that 13169689Skan * accompanied this code). 14169689Skan * 15169689Skan * You should have received a copy of the GNU General Public License version 16169689Skan * 2 along with this work; if not, write to the Free Software Foundation, 17169689Skan * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18169689Skan * 19169689Skan * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20169689Skan * or visit www.oracle.com if you need additional information or have any 21169689Skan * questions. 22169689Skan */ 23169689Skan 24169689Skanpackage org.graalvm.compiler.asm.amd64.test; 25169689Skan 26169689Skanimport static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.LZCNT; 27169689Skanimport static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.TZCNT; 28169689Skanimport static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD; 29169689Skanimport static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; 30169689Skanimport static jdk.vm.ci.code.ValueUtil.asRegister; 31169689Skanimport static org.junit.Assume.assumeTrue; 32169689Skan 33169689Skanimport java.lang.reflect.Field; 34169689Skanimport java.util.EnumSet; 35169689Skan 36169689Skanimport jdk.vm.ci.amd64.AMD64; 37169689Skanimport jdk.vm.ci.amd64.AMD64.CPUFeature; 38169689Skanimport jdk.vm.ci.code.CallingConvention; 39169689Skanimport jdk.vm.ci.code.Register; 40169689Skanimport jdk.vm.ci.code.RegisterConfig; 41169689Skanimport jdk.vm.ci.code.TargetDescription; 42169689Skanimport jdk.vm.ci.meta.JavaKind; 43169689Skan 44169689Skanimport org.junit.Before; 45169689Skanimport org.junit.Test; 46169689Skan 47169689Skanimport org.graalvm.compiler.asm.amd64.AMD64Address; 48169689Skanimport org.graalvm.compiler.asm.amd64.AMD64Assembler; 49169689Skanimport org.graalvm.compiler.asm.test.AssemblerTest; 50169689Skanimport org.graalvm.compiler.code.CompilationResult; 51169689Skan 52169689Skanpublic class BitOpsTest extends AssemblerTest { 53169689Skan private static boolean lzcntSupported; 54169689Skan private static boolean tzcntSupported; 55169689Skan 56169689Skan @Before 57169689Skan public void checkAMD64() { 58169689Skan assumeTrue("skipping AMD64 specific test", codeCache.getTarget().arch instanceof AMD64); 59169689Skan EnumSet<CPUFeature> features = ((AMD64) codeCache.getTarget().arch).getFeatures(); 60169689Skan lzcntSupported = features.contains(CPUFeature.LZCNT); 61169689Skan tzcntSupported = features.contains(CPUFeature.BMI1); 62169689Skan } 63169689Skan 64169689Skan @Test 65169689Skan public void lzcntlTest() { 66169689Skan if (lzcntSupported) { 67169689Skan CodeGenTest test = new CodeGenTest() { 68169689Skan 69169689Skan @Override 70169689Skan public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 71169689Skan AMD64Assembler asm = new AMD64Assembler(target); 72169689Skan Register ret = registerConfig.getReturnRegister(JavaKind.Int); 73169689Skan Register arg = asRegister(cc.getArgument(0)); 74169689Skan LZCNT.emit(asm, DWORD, ret, arg); 75169689Skan asm.ret(0); 76169689Skan return asm.close(true); 77169689Skan } 78169689Skan }; 79169689Skan assertReturn("intStub", test, 31, 1); 80169689Skan } 81169689Skan } 82169689Skan 83169689Skan @Test 84169689Skan public void lzcntlMemTest() { 85169689Skan if (lzcntSupported) { 86169689Skan CodeGenTest test = new CodeGenTest() { 87169689Skan 88169689Skan @Override 89169689Skan public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 90169689Skan AMD64Assembler asm = new AMD64Assembler(target); 91169689Skan Register ret = registerConfig.getReturnRegister(JavaKind.Int); 92169689Skan try { 93169689Skan Field f = IntField.class.getDeclaredField("x"); 94169689Skan AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) UNSAFE.objectFieldOffset(f)); 95169689Skan LZCNT.emit(asm, DWORD, ret, arg); 96169689Skan asm.ret(0); 97169689Skan return asm.close(true); 98169689Skan } catch (Exception e) { 99169689Skan throw new RuntimeException("exception while trying to generate field access:", e); 100169689Skan } 101169689Skan } 102169689Skan }; 103169689Skan assertReturn("intFieldStub", test, 31, new IntField(1)); 104169689Skan } 105169689Skan } 106169689Skan 107169689Skan @Test 108169689Skan public void lzcntqTest() { 109169689Skan if (lzcntSupported) { 110169689Skan CodeGenTest test = new CodeGenTest() { 111169689Skan 112169689Skan @Override 113169689Skan public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 114169689Skan AMD64Assembler asm = new AMD64Assembler(target); 115169689Skan Register ret = registerConfig.getReturnRegister(JavaKind.Int); 116169689Skan Register arg = asRegister(cc.getArgument(0)); 117169689Skan LZCNT.emit(asm, QWORD, ret, arg); 118169689Skan asm.ret(0); 119169689Skan return asm.close(true); 120169689Skan } 121169689Skan }; 122169689Skan assertReturn("longStub", test, 63, 1L); 123169689Skan } 124169689Skan } 125169689Skan 126169689Skan @Test 127169689Skan public void lzcntqMemTest() { 128169689Skan if (lzcntSupported) { 129169689Skan CodeGenTest test = new CodeGenTest() { 130169689Skan 131169689Skan @Override 132169689Skan public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 133169689Skan AMD64Assembler asm = new AMD64Assembler(target); 134169689Skan Register ret = registerConfig.getReturnRegister(JavaKind.Int); 135169689Skan try { 136169689Skan Field f = LongField.class.getDeclaredField("x"); 137169689Skan AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) UNSAFE.objectFieldOffset(f)); 138169689Skan LZCNT.emit(asm, QWORD, ret, arg); 139169689Skan asm.ret(0); 140169689Skan return asm.close(true); 141169689Skan } catch (Exception e) { 142169689Skan throw new RuntimeException("exception while trying to generate field access:", e); 143169689Skan } 144169689Skan } 145169689Skan }; 146169689Skan assertReturn("longFieldStub", test, 63, new LongField(1)); 147169689Skan } 148169689Skan } 149169689Skan 150169689Skan @Test 151169689Skan public void tzcntlTest() { 152169689Skan if (tzcntSupported) { 153169689Skan CodeGenTest test = new CodeGenTest() { 154169689Skan 155169689Skan @Override 156169689Skan public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 157169689Skan AMD64Assembler asm = new AMD64Assembler(target); 158169689Skan Register ret = registerConfig.getReturnRegister(JavaKind.Int); 159169689Skan Register arg = asRegister(cc.getArgument(0)); 160169689Skan TZCNT.emit(asm, DWORD, ret, arg); 161169689Skan asm.ret(0); 162169689Skan return asm.close(true); 163169689Skan } 164169689Skan }; 165169689Skan assertReturn("intStub", test, 31, 0x8000_0000); 166169689Skan } 167169689Skan } 168169689Skan 169169689Skan @Test 170169689Skan public void tzcntlMemTest() { 171169689Skan if (tzcntSupported) { 172169689Skan CodeGenTest test = new CodeGenTest() { 173169689Skan 174169689Skan @Override 175169689Skan public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 176169689Skan AMD64Assembler asm = new AMD64Assembler(target); 177169689Skan Register ret = registerConfig.getReturnRegister(JavaKind.Int); 178169689Skan try { 179169689Skan Field f = IntField.class.getDeclaredField("x"); 180169689Skan AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) UNSAFE.objectFieldOffset(f)); 181169689Skan TZCNT.emit(asm, DWORD, ret, arg); 182169689Skan asm.ret(0); 183169689Skan return asm.close(true); 184169689Skan } catch (Exception e) { 185169689Skan throw new RuntimeException("exception while trying to generate field access:", e); 186169689Skan } 187169689Skan } 188169689Skan }; 189169689Skan assertReturn("intFieldStub", test, 31, new IntField(0x8000_0000)); 190169689Skan } 191169689Skan } 192169689Skan 193169689Skan @Test 194169689Skan public void tzcntqTest() { 195169689Skan if (tzcntSupported) { 196169689Skan CodeGenTest test = new CodeGenTest() { 197169689Skan 198169689Skan @Override 199169689Skan public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 200169689Skan AMD64Assembler asm = new AMD64Assembler(target); 201169689Skan Register ret = registerConfig.getReturnRegister(JavaKind.Int); 202169689Skan Register arg = asRegister(cc.getArgument(0)); 203169689Skan TZCNT.emit(asm, QWORD, ret, arg); 204169689Skan asm.ret(0); 205169689Skan return asm.close(true); 206169689Skan } 207169689Skan }; 208169689Skan assertReturn("longStub", test, 63, 0x8000_0000_0000_0000L); 209169689Skan } 210169689Skan } 211169689Skan 212169689Skan @Test 213169689Skan public void tzcntqMemTest() { 214169689Skan if (tzcntSupported) { 215169689Skan CodeGenTest test = new CodeGenTest() { 216169689Skan 217169689Skan @Override 218169689Skan public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 219169689Skan AMD64Assembler asm = new AMD64Assembler(target); 220169689Skan Register ret = registerConfig.getReturnRegister(JavaKind.Int); 221169689Skan try { 222169689Skan Field f = LongField.class.getDeclaredField("x"); 223169689Skan AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) UNSAFE.objectFieldOffset(f)); 224169689Skan TZCNT.emit(asm, QWORD, ret, arg); 225169689Skan asm.ret(0); 226169689Skan return asm.close(true); 227169689Skan } catch (Exception e) { 228169689Skan throw new RuntimeException("exception while trying to generate field access:", e); 229169689Skan } 230169689Skan } 231169689Skan }; 232169689Skan assertReturn("longFieldStub", test, 63, new LongField(0x8000_0000_0000_0000L)); 233169689Skan } 234169689Skan } 235169689Skan 236169689Skan @SuppressWarnings("unused") 237169689Skan public static int intStub(int arg) { 238169689Skan return 0; 239169689Skan } 240169689Skan 241169689Skan @SuppressWarnings("unused") 242169689Skan public static int longStub(long arg) { 243169689Skan return 0; 244169689Skan } 245169689Skan 246169689Skan public static class IntField { 247169689Skan public int x; 248169689Skan 249169689Skan IntField(int x) { 250169689Skan this.x = x; 251169689Skan } 252169689Skan } 253169689Skan 254169689Skan public static class LongField { 255169689Skan public long x; 256169689Skan 257169689Skan LongField(long x) { 258169689Skan this.x = x; 259169689Skan } 260169689Skan } 261169689Skan 262169689Skan @SuppressWarnings("unused") 263169689Skan public static int intFieldStub(IntField arg) { 264169689Skan return 0; 265169689Skan } 266169689Skan 267169689Skan @SuppressWarnings("unused") 268169689Skan public static int longFieldStub(LongField arg) { 269169689Skan return 0; 270169689Skan } 271169689Skan} 272169689Skan