001/*
002 * Copyright (c) 2015, 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 */
023package com.oracle.graal.asm.amd64.test;
024
025import com.oracle.graal.asm.amd64.*;
026import com.oracle.graal.asm.test.*;
027
028import static jdk.internal.jvmci.code.ValueUtil.*;
029import static jdk.internal.jvmci.common.UnsafeAccess.*;
030import static org.junit.Assume.*;
031
032import java.lang.reflect.*;
033
034import jdk.internal.jvmci.amd64.*;
035import jdk.internal.jvmci.code.*;
036import jdk.internal.jvmci.meta.*;
037
038import org.junit.*;
039
040public class IncrementDecrementMacroTest extends AssemblerTest {
041
042    @Before
043    public void checkAMD64() {
044        assumeTrue("skipping AMD64 specific test", codeCache.getTarget().arch instanceof AMD64);
045    }
046
047    public static class LongField {
048        public long x;
049
050        LongField(long x) {
051            this.x = x;
052        }
053    }
054
055    private static class IncrementCodeGenTest implements CodeGenTest {
056        final int value;
057
058        public IncrementCodeGenTest(int value) {
059            this.value = value;
060        }
061
062        @Override
063        public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) {
064            AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig);
065            Register ret = registerConfig.getReturnRegister(Kind.Int);
066            try {
067                Field f = LongField.class.getDeclaredField("x");
068                AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f));
069                asm.incrementq(arg, value);
070                asm.movq(ret, arg);
071                asm.ret(0);
072                return asm.close(true);
073            } catch (Exception e) {
074                throw new RuntimeException("exception while trying to generate field access:", e);
075            }
076        }
077    }
078
079    private void assertIncrement(long initValue, int increment) {
080        assertReturn("longFieldStubIncrement", new IncrementCodeGenTest(increment), initValue + increment, new LongField(initValue));
081    }
082
083    private void assertIncrements(int increment) {
084        assertIncrement(0x4242_4242_4242_4242L, increment);
085    }
086
087    @SuppressWarnings("unused")
088    public static long longFieldStubIncrement(LongField arg) {
089        return 0;
090    }
091
092    private static class DecrementCodeGenTest implements CodeGenTest {
093        final int value;
094
095        public DecrementCodeGenTest(int value) {
096            this.value = value;
097        }
098
099        @Override
100        public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) {
101            AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig);
102            Register ret = registerConfig.getReturnRegister(Kind.Int);
103            try {
104                Field f = LongField.class.getDeclaredField("x");
105                AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f));
106                asm.decrementq(arg, value);
107                asm.movq(ret, arg);
108                asm.ret(0);
109                return asm.close(true);
110            } catch (Exception e) {
111                throw new RuntimeException("exception while trying to generate field access:", e);
112            }
113        }
114    }
115
116    private void assertDecrement(long initValue, int increment) {
117        assertReturn("longFieldStubDecrement", new DecrementCodeGenTest(increment), initValue - increment, new LongField(initValue));
118    }
119
120    private void assertDecrements(int increment) {
121        assertDecrement(0x4242_4242_4242_4242L, increment);
122    }
123
124    @SuppressWarnings("unused")
125    public static long longFieldStubDecrement(LongField arg) {
126        return 0;
127    }
128
129    @Test
130    public void incrementMemTest0() {
131        int increment = 0;
132        assertIncrements(increment);
133    }
134
135    @Test
136    public void incrementMemTest1() {
137        int increment = 1;
138        assertIncrements(increment);
139    }
140
141    @Test
142    public void incrementMemTest2() {
143        int increment = 2;
144        assertIncrements(increment);
145    }
146
147    @Test
148    public void incrementMemTest3() {
149        int increment = Integer.MAX_VALUE;
150        assertIncrements(increment);
151    }
152
153    @Test
154    public void incrementMemTest4() {
155        int increment = Integer.MIN_VALUE;
156        assertIncrements(increment);
157    }
158
159    @Test
160    public void incrementMemTest5() {
161        int increment = -1;
162        assertIncrements(increment);
163    }
164
165    @Test
166    public void incrementMemTest6() {
167        int increment = -2;
168        assertIncrements(increment);
169    }
170
171    @Test
172    public void incrementMemTest7() {
173        int increment = -0x1000_0000;
174        assertIncrements(increment);
175    }
176
177    @Test
178    public void decrementMemTest0() {
179        int decrement = 0;
180        assertDecrements(decrement);
181    }
182
183    @Test
184    public void decrementMemTest1() {
185        int decrement = 1;
186        assertDecrements(decrement);
187    }
188
189    @Test
190    public void decrementMemTest2() {
191        int decrement = 2;
192        assertDecrements(decrement);
193    }
194
195    @Test
196    public void decrementMemTest3() {
197        int decrement = Integer.MAX_VALUE;
198        assertDecrements(decrement);
199    }
200
201    @Test
202    public void decrementMemTest4() {
203        int decrement = Integer.MIN_VALUE;
204        assertDecrements(decrement);
205    }
206
207    @Test
208    public void decrementMemTest5() {
209        int decrement = -1;
210        assertDecrements(decrement);
211    }
212
213    @Test
214    public void decrementMemTest6() {
215        int decrement = -2;
216        assertDecrements(decrement);
217    }
218
219    @Test
220    public void decrementMemTest7() {
221        int decrement = -0x1000_0000;
222        assertDecrements(decrement);
223    }
224
225}