001/* 002 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023 024package com.oracle.graal.asm.amd64.test; 025 026import com.oracle.graal.asm.amd64.*; 027import com.oracle.graal.asm.test.*; 028 029import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.*; 030import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.*; 031import static jdk.internal.jvmci.code.ValueUtil.*; 032import static jdk.internal.jvmci.common.UnsafeAccess.*; 033import static org.junit.Assume.*; 034 035import java.lang.reflect.*; 036import java.util.*; 037 038import jdk.internal.jvmci.amd64.*; 039import jdk.internal.jvmci.amd64.AMD64.*; 040import jdk.internal.jvmci.code.*; 041import jdk.internal.jvmci.meta.*; 042 043import org.junit.*; 044 045public class BitOpsTest extends AssemblerTest { 046 private static boolean lzcntSupported; 047 private static boolean tzcntSupported; 048 049 @Before 050 public void checkAMD64() { 051 assumeTrue("skipping AMD64 specific test", codeCache.getTarget().arch instanceof AMD64); 052 EnumSet<CPUFeature> features = ((AMD64) codeCache.getTarget().arch).getFeatures(); 053 lzcntSupported = features.contains(CPUFeature.LZCNT); 054 tzcntSupported = features.contains(CPUFeature.BMI1); 055 } 056 057 @Test 058 public void lzcntlTest() { 059 if (lzcntSupported) { 060 CodeGenTest test = new CodeGenTest() { 061 062 @Override 063 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 064 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 065 Register ret = registerConfig.getReturnRegister(Kind.Int); 066 Register arg = asRegister(cc.getArgument(0)); 067 LZCNT.emit(asm, DWORD, ret, arg); 068 asm.ret(0); 069 return asm.close(true); 070 } 071 }; 072 assertReturn("intStub", test, 31, 1); 073 } 074 } 075 076 @Test 077 public void lzcntlMemTest() { 078 if (lzcntSupported) { 079 CodeGenTest test = new CodeGenTest() { 080 081 @Override 082 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 083 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 084 Register ret = registerConfig.getReturnRegister(Kind.Int); 085 try { 086 Field f = IntField.class.getDeclaredField("x"); 087 AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); 088 LZCNT.emit(asm, DWORD, ret, arg); 089 asm.ret(0); 090 return asm.close(true); 091 } catch (Exception e) { 092 throw new RuntimeException("exception while trying to generate field access:", e); 093 } 094 } 095 }; 096 assertReturn("intFieldStub", test, 31, new IntField(1)); 097 } 098 } 099 100 @Test 101 public void lzcntqTest() { 102 if (lzcntSupported) { 103 CodeGenTest test = new CodeGenTest() { 104 105 @Override 106 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 107 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 108 Register ret = registerConfig.getReturnRegister(Kind.Int); 109 Register arg = asRegister(cc.getArgument(0)); 110 LZCNT.emit(asm, QWORD, ret, arg); 111 asm.ret(0); 112 return asm.close(true); 113 } 114 }; 115 assertReturn("longStub", test, 63, 1L); 116 } 117 } 118 119 @Test 120 public void lzcntqMemTest() { 121 if (lzcntSupported) { 122 CodeGenTest test = new CodeGenTest() { 123 124 @Override 125 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 126 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 127 Register ret = registerConfig.getReturnRegister(Kind.Int); 128 try { 129 Field f = LongField.class.getDeclaredField("x"); 130 AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); 131 LZCNT.emit(asm, QWORD, ret, arg); 132 asm.ret(0); 133 return asm.close(true); 134 } catch (Exception e) { 135 throw new RuntimeException("exception while trying to generate field access:", e); 136 } 137 } 138 }; 139 assertReturn("longFieldStub", test, 63, new LongField(1)); 140 } 141 } 142 143 @Test 144 public void tzcntlTest() { 145 if (tzcntSupported) { 146 CodeGenTest test = new CodeGenTest() { 147 148 @Override 149 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 150 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 151 Register ret = registerConfig.getReturnRegister(Kind.Int); 152 Register arg = asRegister(cc.getArgument(0)); 153 TZCNT.emit(asm, DWORD, ret, arg); 154 asm.ret(0); 155 return asm.close(true); 156 } 157 }; 158 assertReturn("intStub", test, 31, 0x8000_0000); 159 } 160 } 161 162 @Test 163 public void tzcntlMemTest() { 164 if (tzcntSupported) { 165 CodeGenTest test = new CodeGenTest() { 166 167 @Override 168 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 169 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 170 Register ret = registerConfig.getReturnRegister(Kind.Int); 171 try { 172 Field f = IntField.class.getDeclaredField("x"); 173 AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); 174 TZCNT.emit(asm, DWORD, ret, arg); 175 asm.ret(0); 176 return asm.close(true); 177 } catch (Exception e) { 178 throw new RuntimeException("exception while trying to generate field access:", e); 179 } 180 } 181 }; 182 assertReturn("intFieldStub", test, 31, new IntField(0x8000_0000)); 183 } 184 } 185 186 @Test 187 public void tzcntqTest() { 188 if (tzcntSupported) { 189 CodeGenTest test = new CodeGenTest() { 190 191 @Override 192 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 193 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 194 Register ret = registerConfig.getReturnRegister(Kind.Int); 195 Register arg = asRegister(cc.getArgument(0)); 196 TZCNT.emit(asm, QWORD, ret, arg); 197 asm.ret(0); 198 return asm.close(true); 199 } 200 }; 201 assertReturn("longStub", test, 63, 0x8000_0000_0000_0000L); 202 } 203 } 204 205 @Test 206 public void tzcntqMemTest() { 207 if (tzcntSupported) { 208 CodeGenTest test = new CodeGenTest() { 209 210 @Override 211 public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { 212 AMD64Assembler asm = new AMD64Assembler(target, registerConfig); 213 Register ret = registerConfig.getReturnRegister(Kind.Int); 214 try { 215 Field f = LongField.class.getDeclaredField("x"); 216 AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); 217 TZCNT.emit(asm, QWORD, ret, arg); 218 asm.ret(0); 219 return asm.close(true); 220 } catch (Exception e) { 221 throw new RuntimeException("exception while trying to generate field access:", e); 222 } 223 } 224 }; 225 assertReturn("longFieldStub", test, 63, new LongField(0x8000_0000_0000_0000L)); 226 } 227 } 228 229 @SuppressWarnings("unused") 230 public static int intStub(int arg) { 231 return 0; 232 } 233 234 @SuppressWarnings("unused") 235 public static int longStub(long arg) { 236 return 0; 237 } 238 239 public static class IntField { 240 public int x; 241 242 IntField(int x) { 243 this.x = x; 244 } 245 } 246 247 public static class LongField { 248 public long x; 249 250 LongField(long x) { 251 this.x = x; 252 } 253 } 254 255 @SuppressWarnings("unused") 256 public static int intFieldStub(IntField arg) { 257 return 0; 258 } 259 260 @SuppressWarnings("unused") 261 public static int longFieldStub(LongField arg) { 262 return 0; 263 } 264}