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#pragma once
32
33#include <cstdint>
34#include <tuple>
35
36#include "insttest.h"
37
38namespace A
39{
40
41inline int64_t
42lr_w(int32_t& mem)
43{
44    int64_t r = 0;
45    uint64_t addr = (uint64_t)&mem;
46    asm volatile("lr.w %0,(%1)" : "=r" (r) : "r" (addr) : "memory");
47    return r;
48}
49
50inline std::pair<int64_t, uint64_t>
51sc_w(int64_t rs2, int32_t& mem)
52{
53    uint64_t addr = (uint64_t)&mem;
54    uint64_t rd = -1;
55    asm volatile("sc.w %0,%2,(%1)"
56            : "=r" (rd)
57            : "r" (addr), "r" (rs2)
58            : "memory");
59    return {mem, rd};
60}
61
62inline std::pair<int64_t, int64_t>
63amoswap_w(int64_t mem, int64_t rs2)
64{
65    int64_t rd = 0;
66    uint64_t addr = (uint64_t)&mem;
67    asm volatile("amoswap.w %0,%2,(%1)"
68            : "=r" (rd)
69            : "r" (addr), "r" (rs2)
70            : "memory");
71    return {mem, rd};
72}
73
74inline std::pair<int64_t, int64_t>
75amoadd_w(int64_t mem, int64_t rs2)
76{
77    int64_t rd = 0;
78    uint64_t addr = (uint64_t)&mem;
79    asm volatile("amoadd.w %0,%2,(%1)"
80            : "=r" (rd)
81            : "r" (addr), "r" (rs2)
82            : "memory");
83    return {mem, rd};
84}
85
86inline std::pair<uint64_t, uint64_t>
87amoxor_w(uint64_t mem, uint64_t rs2)
88{
89    uint64_t rd = 0;
90    uint64_t addr = (uint64_t)&mem;
91    asm volatile("amoxor.w %0,%2,(%1)"
92            : "=r" (rd)
93            : "r" (addr), "r" (rs2)
94            : "memory");
95    return {mem, rd};
96}
97
98inline std::pair<uint64_t, uint64_t>
99amoand_w(uint64_t mem, uint64_t rs2)
100{
101    uint64_t rd = 0;
102    uint64_t addr = (uint64_t)&mem;
103    asm volatile("amoand.w %0,%2,(%1)"
104            : "=r" (rd)
105            : "r" (addr), "r" (rs2)
106            : "memory");
107    return {mem, rd};
108}
109
110inline std::pair<uint64_t, uint64_t>
111amoor_w(uint64_t mem, uint64_t rs2)
112{
113    uint64_t rd = 0;
114    uint64_t addr = (uint64_t)&mem;
115    asm volatile("amoor.w %0,%2,(%1)"
116            : "=r" (rd)
117            : "r" (addr), "r" (rs2)
118            : "memory");
119    return {mem, rd};
120}
121
122inline std::pair<int64_t, int64_t>
123amomin_w(int64_t mem, int64_t rs2)
124{
125    int64_t rd = 0;
126    uint64_t addr = (uint64_t)&mem;
127    asm volatile("amomin.w %0,%2,(%1)"
128            : "=r" (rd)
129            : "r" (addr), "r" (rs2)
130            : "memory");
131    return {mem, rd};
132}
133
134inline std::pair<int64_t, int64_t>
135amomax_w(int64_t mem, int64_t rs2)
136{
137    int64_t rd = 0;
138    uint64_t addr = (uint64_t)&mem;
139    asm volatile("amomax.w %0,%2,(%1)"
140            : "=r" (rd)
141            : "r" (addr), "r" (rs2)
142            : "memory");
143    return {mem, rd};
144}
145
146inline std::pair<uint64_t, uint64_t>
147amominu_w(uint64_t mem, uint64_t rs2)
148{
149    uint64_t rd = 0;
150    uint64_t addr = (uint64_t)&mem;
151    asm volatile("amominu.w %0,%2,(%1)"
152            : "=r" (rd)
153            : "r" (addr), "r" (rs2)
154            : "memory");
155    return {mem, rd};
156}
157
158inline std::pair<uint64_t, uint64_t>
159amomaxu_w(uint64_t mem, uint64_t rs2)
160{
161    uint64_t rd = 0;
162    uint64_t addr = (uint64_t)&mem;
163    asm volatile("amomaxu.w %0,%2,(%1)"
164            : "=r" (rd)
165            : "r" (addr), "r" (rs2)
166            : "memory");
167    return {mem, rd};
168}
169
170inline int64_t
171lr_d(int64_t& mem)
172{
173    int64_t r = 0;
174    uint64_t addr = (uint64_t)&mem;
175    asm volatile("lr.d %0,(%1)" : "=r" (r) : "r" (addr) : "memory");
176    return r;
177}
178
179inline std::pair<int64_t, uint64_t>
180sc_d(int64_t rs2, int64_t& mem)
181{
182    uint64_t addr = (uint64_t)&mem;
183    uint64_t rd = -1;
184    asm volatile("sc.d %0,%2,(%1)"
185            : "=r" (rd)
186            : "r" (addr), "r" (rs2)
187            : "memory");
188    return {mem, rd};
189}
190
191inline std::pair<int64_t, int64_t>
192amoswap_d(int64_t mem, int64_t rs2)
193{
194    int64_t rd = 0;
195    uint64_t addr = (uint64_t)&mem;
196    asm volatile("amoswap.d %0,%2,(%1)"
197            : "=r" (rd)
198            : "r" (addr), "r" (rs2)
199            : "memory");
200    return {mem, rd};
201}
202
203inline std::pair<int64_t, int64_t>
204amoadd_d(int64_t mem, int64_t rs2)
205{
206    int64_t rd = 0;
207    uint64_t addr = (uint64_t)&mem;
208    asm volatile("amoadd.d %0,%2,(%1)"
209            : "=r" (rd)
210            : "r" (addr), "r" (rs2)
211            : "memory");
212    return {mem, rd};
213}
214
215inline std::pair<uint64_t, uint64_t>
216amoxor_d(uint64_t mem, uint64_t rs2)
217{
218    uint64_t rd = 0;
219    uint64_t addr = (uint64_t)&mem;
220    asm volatile("amoxor.d %0,%2,(%1)"
221            : "=r" (rd)
222            : "r" (addr), "r" (rs2)
223            : "memory");
224    return {mem, rd};
225}
226
227inline std::pair<uint64_t, uint64_t>
228amoand_d(uint64_t mem, uint64_t rs2)
229{
230    uint64_t rd = 0;
231    uint64_t addr = (uint64_t)&mem;
232    asm volatile("amoand.d %0,%2,(%1)"
233            : "=r" (rd)
234            : "r" (addr), "r" (rs2)
235            : "memory");
236    return {mem, rd};
237}
238
239inline std::pair<uint64_t, uint64_t>
240amoor_d(uint64_t mem, uint64_t rs2)
241{
242    uint64_t rd = 0;
243    uint64_t addr = (uint64_t)&mem;
244    asm volatile("amoor.d %0,%2,(%1)"
245            : "=r" (rd)
246            : "r" (addr), "r" (rs2)
247            : "memory");
248    return {mem, rd};
249}
250
251inline std::pair<int64_t, int64_t>
252amomin_d(int64_t mem, int64_t rs2)
253{
254    int64_t rd = 0;
255    uint64_t addr = (uint64_t)&mem;
256    asm volatile("amomin.d %0,%2,(%1)"
257            : "=r" (rd)
258            : "r" (addr), "r" (rs2)
259            : "memory");
260    return {mem, rd};
261}
262
263inline std::pair<int64_t, int64_t>
264amomax_d(int64_t mem, int64_t rs2)
265{
266    int64_t rd = 0;
267    uint64_t addr = (uint64_t)&mem;
268    asm volatile("amomax.d %0,%2,(%1)"
269            : "=r" (rd)
270            : "r" (addr), "r" (rs2)
271            : "memory");
272    return {mem, rd};
273}
274
275inline std::pair<uint64_t, uint64_t>
276amominu_d(uint64_t mem, uint64_t rs2)
277{
278    uint64_t rd = 0;
279    uint64_t addr = (uint64_t)&mem;
280    asm volatile("amominu.d %0,%2,(%1)"
281            : "=r" (rd)
282            : "r" (addr), "r" (rs2)
283            : "memory");
284    return {mem, rd};
285}
286
287inline std::pair<uint64_t, uint64_t>
288amomaxu_d(uint64_t mem, uint64_t rs2)
289{
290    uint64_t rd = 0;
291    uint64_t addr = (uint64_t)&mem;
292    asm volatile("amomaxu.d %0,%2,(%1)"
293            : "=r" (rd)
294            : "r" (addr), "r" (rs2)
295            : "memory");
296    return {mem, rd};
297}
298
299} // namespace A
300