1/*
2 * Copyright (c) 2016 The University of Virginia
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Alec Roelke
29 */
30
31#include <cstdint>
32#include <limits>
33
34#include "insttest.h"
35#include "rv64a.h"
36
37int main()
38{
39    using namespace std;
40    using namespace insttest;
41
42    // Memory (LR.W, SC.W)
43    expect<pair<int64_t, int64_t>>({-1, 256}, []{
44            int32_t mem = -1;
45            int64_t rs2 = 256;
46            int64_t rd;
47            pair<int64_t, uint64_t> result;
48            do {
49                rd = A::lr_w(mem);
50                result = A::sc_w(rs2, mem);
51            } while (result.second == 1);
52            return pair<int64_t, uint64_t>(rd, result.first);
53        }, "lr.w/sc.w");
54    expect<pair<bool, int64_t>>({true, 200}, []{
55            int32_t mem = 200;
56            pair<int64_t, uint64_t> result = A::sc_w(50, mem);
57            return pair<bool, int64_t>(result.second == 1, mem);
58        }, "sc.w, no preceding lr.d");
59
60    // AMOSWAP.W
61    expect<pair<int64_t, int64_t>>({65535, 255},
62            []{return A::amoswap_w(255, 65535);}, "amoswap.w");
63    expect<pair<int64_t, int64_t>>({0xFFFFFFFF, -1},
64            []{return A::amoswap_w(0xFFFFFFFF, 0xFFFFFFFF);},
65            "amoswap.w, sign extend");
66    expect<pair<int64_t, int64_t>>({0x0000000180000000LL, -1},
67            []{return A::amoswap_w(0x00000001FFFFFFFFLL,
68                    0x7FFFFFFF80000000LL);},
69            "amoswap.w, truncate");
70
71    // AMOADD.W
72    expect<pair<int64_t, int64_t>>({256, 255},
73            []{return A::amoadd_w(255, 1);}, "amoadd.w");
74    expect<pair<int64_t, int64_t>>({0, -1},
75            []{return A::amoadd_w(0xFFFFFFFF, 1);},
76            "amoadd.w, truncate/overflow");
77    expect<pair<int64_t, int64_t>>({0xFFFFFFFF, 0x7FFFFFFF},
78            []{return A::amoadd_w(0x7FFFFFFF, 0x80000000);},
79            "amoadd.w, sign extend");
80
81    // AMOXOR.W
82    expect<pair<uint64_t, uint64_t>>({0xFFFFFFFFAAAAAAAALL, -1},
83            []{return A::amoxor_w(-1, 0x5555555555555555LL);},
84            "amoxor.w, truncate");
85    expect<pair<uint64_t, uint64_t>>({0x80000000, -1},
86            []{return A::amoxor_w(0xFFFFFFFF, 0x7FFFFFFF);},
87            "amoxor.w, sign extend");
88
89    // AMOAND.W
90    expect<pair<uint64_t, uint64_t>>({0xFFFFFFFF00000000LL, -1},
91            []{return A::amoand_w(-1, 0);}, "amoand.w, truncate");
92    expect<pair<uint64_t, uint64_t>>({0x0000000080000000LL, -1},
93            []{return A::amoand_w(0xFFFFFFFF,numeric_limits<int32_t>::min());},
94            "amoand.w, sign extend");
95
96    // AMOOR.W
97    expect<pair<uint64_t, uint64_t>>({0x00000000FFFFFFFFLL, 0},
98            []{return A::amoor_w(0, -1);}, "amoor.w, truncate");
99    expect<pair<uint64_t, uint64_t>>({0x0000000080000000LL, 0},
100            []{return A::amoor_w(0, numeric_limits<int32_t>::min());},
101            "amoor.w, sign extend");
102
103    // AMOMIN.W
104    expect<pair<int64_t, int64_t>>({0x7FFFFFFF00000001LL, 1},
105            []{return A::amomin_w(0x7FFFFFFF00000001LL, 0xFFFFFFFF000000FF);},
106            "amomin.w, truncate");
107    expect<pair<int64_t, int64_t>>({0x00000000FFFFFFFELL, -1},
108            []{return A::amomin_w(0xFFFFFFFF, -2);}, "amomin.w, sign extend");
109
110    // AMOMAX.W
111    expect<pair<int64_t, int64_t>>({0x70000000000000FFLL, 1},
112            []{return A::amomax_w(0x7000000000000001LL,0x7FFFFFFF000000FFLL);},
113            "amomax.w, truncate");
114    expect<pair<int64_t, int64_t>>({-1, numeric_limits<int32_t>::min()},
115            []{return A::amomax_w(numeric_limits<int32_t>::min(), -1);},
116            "amomax.w, sign extend");
117
118    // AMOMINU.W
119    expect<pair<uint64_t, uint64_t>>({0x0FFFFFFF000000FFLL, -1},
120            []{return A::amominu_w(0x0FFFFFFFFFFFFFFFLL, 0xFFFFFFFF000000FF);},
121            "amominu.w, truncate");
122    expect<pair<uint64_t, uint64_t>>({0x0000000080000000LL, -1},
123            []{return A::amominu_w(0x00000000FFFFFFFFLL, 0x80000000);},
124            "amominu.w, sign extend");
125
126    // AMOMAXU.W
127    expect<pair<uint64_t, uint64_t>>({-1, 0},
128            []{return A::amomaxu_w(0xFFFFFFFF00000000LL,
129                    0x00000000FFFFFFFFLL);},
130            "amomaxu.w, truncate");
131    expect<pair<uint64_t, uint64_t>>(
132            {0xFFFFFFFF, numeric_limits<int32_t>::min()},
133            []{return A::amomaxu_w(0x80000000, 0xFFFFFFFF);},
134            "amomaxu.w, sign extend");
135
136    // Memory (LR.D, SC.D)
137    expect<pair<int64_t, int64_t>>({-1, 256}, []{
138            int64_t mem = -1;
139            int64_t rs2 = 256;
140            int64_t rd;
141            pair<int64_t, uint64_t> result;
142            do {
143                rd = A::lr_d(mem);
144                result = A::sc_d(rs2, mem);
145            } while (result.second == 1);
146            return pair<int64_t, uint64_t>(rd, result.first);
147        }, "lr.d/sc.d");
148    expect<pair<bool, int64_t>>({true, 200}, []{
149            int64_t mem = 200;
150            pair<int64_t, uint64_t> result = A::sc_d(50, mem);
151            return pair<bool, int64_t>(result.second == 1, mem);
152        }, "sc.d, no preceding lr.d");
153
154    // AMOSWAP.D
155    expect<pair<int64_t, int64_t>>({1, -1}, []{return A::amoswap_d(-1, 1);},
156            "amoswap.d");
157
158    // AMOADD.D
159    expect<pair<int64_t, int64_t>>({0x7000000000000000LL,0x0FFFFFFFFFFFFFFFLL},
160            []{return A::amoadd_d(0x0FFFFFFFFFFFFFFFLL,0x6000000000000001LL);},
161            "amoadd.d");
162    expect<pair<int64_t, int64_t>>({0, 0x7FFFFFFFFFFFFFFFLL},
163            []{return A::amoadd_d(0x7FFFFFFFFFFFFFFFLL,0x8000000000000001LL);},
164            "amoadd.d, overflow");
165
166    // AMOXOR.D
167    expect<pair<int64_t, int64_t>>({-1, 0xAAAAAAAAAAAAAAAALL},
168            []{return A::amoxor_d(0xAAAAAAAAAAAAAAAALL,0x5555555555555555LL);},
169            "amoxor.d (1)");
170    expect<pair<int64_t, int64_t>>({0, 0xAAAAAAAAAAAAAAAALL},
171            []{return A::amoxor_d(0xAAAAAAAAAAAAAAAALL,0xAAAAAAAAAAAAAAAALL);},
172            "amoxor.d (0)");
173
174    // AMOAND.D
175    expect<pair<int64_t, int64_t>>({0xAAAAAAAAAAAAAAAALL, -1},
176            []{return A::amoand_d(-1, 0xAAAAAAAAAAAAAAAALL);}, "amoand.d");
177
178    // AMOOR.D
179    expect<pair<int64_t, int64_t>>({-1, 0xAAAAAAAAAAAAAAAALL},
180            []{return A::amoor_d(0xAAAAAAAAAAAAAAAALL, 0x5555555555555555LL);},
181            "amoor.d");
182
183    // AMOMIN.D
184    expect<pair<int64_t, int64_t>>({-1, -1},
185            []{return A::amomin_d(-1, 0);}, "amomin.d");
186
187    // AMOMAX.D
188    expect<pair<int64_t, int64_t>>({0, -1}, []{return A::amomax_d(-1, 0);},
189            "amomax.d");
190
191    // AMOMINU.D
192    expect<pair<uint64_t, uint64_t>>({0, -1},
193            []{return A::amominu_d(-1, 0);}, "amominu.d");
194
195    // AMOMAXU.D
196    expect<pair<uint64_t, uint64_t>>({-1, -1}, []{return A::amomaxu_d(-1, 0);},
197            "amomaxu.d");
198
199    return 0;
200}
201