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