1 /* 2 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package com.oracle.graal.asm.amd64.test; 25 26 import static com.oracle.graal.api.code.ValueUtil.*; 27 import static com.oracle.graal.compiler.common.UnsafeAccess.*; 28 import static org.junit.Assume.*; 29 30 import org.junit.*; 31 32 import java.lang.reflect.*; 33 import java.util.*; 34 35 import com.oracle.graal.amd64.*; 36 import com.oracle.graal.amd64.AMD64.*; 37 import com.oracle.graal.api.code.*; 38 import com.oracle.graal.api.meta.*; 39 import com.oracle.graal.asm.amd64.*; 40 import com.oracle.graal.asm.test.*; 41 42 public class BitOpsTest extends AssemblerTest { 43 private static boolean lzcntSupported; 44 private static boolean tzcntSupported; 45 46 @Before 47 public void checkAMD64() { 48 assumeTrue("skipping AMD64 specific test", codeCache.getTarget().arch instanceof AMD64); 49 EnumSet<CPUFeature> features = ((AMD64) codeCache.getTarget().arch).getFeatures(); 50 lzcntSupported = features.contains(CPUFeature.LZCNT); 51 tzcntSupported = features.contains(CPUFeature.BMI1); 52 } 53 54 @Test 55 public void lzcntlTest() { 56 if (lzcntSupported) { 57 CodeGenTest test = new CodeGenTest() { 58 59 @Override 60 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 61 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 62 Register ret = registerConfig.getReturnRegister(Kind.Int); 63 Register arg = asRegister(cc.getArgument(0)); 64 asm.lzcntl(ret, arg); 65 asm.ret(0); 66 return asm.close(true); 67 } 68 }; 69 assertReturn("intStub", test, 31, 1); 70 } 71 } 72 73 @Test 74 public void lzcntlMemTest() { 75 if (lzcntSupported) { 76 CodeGenTest test = new CodeGenTest() { 77 78 @Override 79 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 80 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 81 Register ret = registerConfig.getReturnRegister(Kind.Int); 82 try { 83 Field f = IntField.class.getDeclaredField("x"); 84 AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); 85 asm.lzcntl(ret, arg); 86 asm.ret(0); 87 return asm.close(true); 88 } catch (Exception e) { 89 throw new RuntimeException("exception while trying to generate field access:", e); 90 } 91 } 92 }; 93 assertReturn("intFieldStub", test, 31, new IntField(1)); 94 } 95 } 96 97 @Test 98 public void lzcntqTest() { 99 if (lzcntSupported) { 100 CodeGenTest test = new CodeGenTest() { 101 102 @Override 103 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 104 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 105 Register ret = registerConfig.getReturnRegister(Kind.Int); 106 Register arg = asRegister(cc.getArgument(0)); 107 asm.lzcntq(ret, arg); 108 asm.ret(0); 109 return asm.close(true); 110 } 111 }; 112 assertReturn("longStub", test, 63, 1L); 113 } 114 } 115 116 @Test 117 public void lzcntqMemTest() { 118 if (lzcntSupported) { 119 CodeGenTest test = new CodeGenTest() { 120 121 @Override 122 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 123 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 124 Register ret = registerConfig.getReturnRegister(Kind.Int); 125 try { 126 Field f = LongField.class.getDeclaredField("x"); 127 AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); 128 asm.lzcntq(ret, arg); 129 asm.ret(0); 130 return asm.close(true); 131 } catch (Exception e) { 132 throw new RuntimeException("exception while trying to generate field access:", e); 133 } 134 } 135 }; 136 assertReturn("longFieldStub", test, 63, new LongField(1)); 137 } 138 } 139 140 @Test 141 public void tzcntlTest() { 142 if (tzcntSupported) { 143 CodeGenTest test = new CodeGenTest() { 144 145 @Override 146 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 147 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 148 Register ret = registerConfig.getReturnRegister(Kind.Int); 149 Register arg = asRegister(cc.getArgument(0)); 150 asm.tzcntl(ret, arg); 151 asm.ret(0); 152 return asm.close(true); 153 } 154 }; 155 assertReturn("intStub", test, 31, 0x8000_0000); 156 } 157 } 158 159 @Test 160 public void tzcntlMemTest() { 161 if (tzcntSupported) { 162 CodeGenTest test = new CodeGenTest() { 163 164 @Override 165 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 166 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 167 Register ret = registerConfig.getReturnRegister(Kind.Int); 168 try { 169 Field f = IntField.class.getDeclaredField("x"); 170 AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); 171 asm.tzcntl(ret, arg); 172 asm.ret(0); 173 return asm.close(true); 174 } catch (Exception e) { 175 throw new RuntimeException("exception while trying to generate field access:", e); 176 } 177 } 178 }; 179 assertReturn("intFieldStub", test, 31, new IntField(0x8000_0000)); 180 } 181 } 182 183 @Test 184 public void tzcntqTest() { 185 if (tzcntSupported) { 186 CodeGenTest test = new CodeGenTest() { 187 188 @Override 189 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 190 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 191 Register ret = registerConfig.getReturnRegister(Kind.Int); 192 Register arg = asRegister(cc.getArgument(0)); 193 asm.tzcntq(ret, arg); 194 asm.ret(0); 195 return asm.close(true); 196 } 197 }; 198 assertReturn("longStub", test, 63, 0x8000_0000_0000_0000L); 199 } 200 } 201 202 @Test 203 public void tzcntqMemTest() { 204 if (tzcntSupported) { 205 CodeGenTest test = new CodeGenTest() { 206 207 @Override 208 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 209 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 210 Register ret = registerConfig.getReturnRegister(Kind.Int); 211 try { 212 Field f = LongField.class.getDeclaredField("x"); 213 AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); 214 asm.tzcntq(ret, arg); 215 asm.ret(0); 216 return asm.close(true); 217 } catch (Exception e) { 218 throw new RuntimeException("exception while trying to generate field access:", e); 219 } 220 } 221 }; 222 assertReturn("longFieldStub", test, 63, new LongField(0x8000_0000_0000_0000L)); 223 } 224 } 225 226 @SuppressWarnings("unused") 227 public static int intStub(int arg) { 228 return 0; 229 } 230 231 @SuppressWarnings("unused") 232 public static int longStub(long arg) { 233 return 0; 234 } 235 236 public static class IntField { 237 public int x; 238 239 IntField(int x) { 240 this.x = x; 241 } 242 } 243 244 public static class LongField { 245 public long x; 246 247 LongField(long x) { 248 this.x = x; 249 } 250 } 251 252 @SuppressWarnings("unused") 253 public static int intFieldStub(IntField arg) { 254 return 0; 255 } 256 257 @SuppressWarnings("unused") 258 public static int longFieldStub(LongField arg) { 259 return 0; 260 } 261 }