tests: Delete authors lists from test files.
[gem5.git] / tests / test-progs / insttest / src / riscv / rv64i.cpp
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
29 #include <fcntl.h>
30 #include <sys/stat.h>
31 #include <sys/time.h>
32 #include <sys/times.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35
36 #include <cstdint>
37 #include <cstring>
38 #include <iostream>
39 #include <limits>
40
41 #include "insttest.h"
42 #include "rv64i.h"
43
44 int main()
45 {
46 using namespace std;
47 using namespace insttest;
48
49 // LUI
50 expect<int64_t>(4096, []{return I::lui(1);}, "lui");
51 expect<int64_t>(numeric_limits<int32_t>::min(),
52 []{return I::lui(0x80000);}, "lui, negative");
53
54 // AUIPC
55 expect<bool>(true, []{return I::auipc(3);}, "auipc");
56
57 // Jump (JAL, JALR)
58 expect<bool>(true, []{return I::jal();}, "jal");
59 expect<bool>(true, []{return I::jalr();}, "jalr");
60
61 // BEQ
62 expect<bool>(true, []{return I::beq(5, 5);}, "beq, equal");
63 expect<bool>(false, []{return I::beq(numeric_limits<int64_t>::max(),
64 numeric_limits<int64_t>::min());}, "beq, not equal");
65
66 // BNE
67 expect<bool>(false, []{return I::bne(5, 5);}, "bne, equal");
68 expect<bool>(true, []{return I::bne(numeric_limits<int64_t>::max(),
69 numeric_limits<int64_t>::min());}, "bne, not equal");
70
71 // BLT
72 expect<bool>(true, []{return I::blt(numeric_limits<int64_t>::min(),
73 numeric_limits<int64_t>::max());}, "blt, less");
74 expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::min(),
75 numeric_limits<int64_t>::min());}, "blt, equal");
76 expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::max(),
77 numeric_limits<int64_t>::min());}, "blt, greater");
78
79 // BGE
80 expect<bool>(false, []{return I::bge(numeric_limits<int64_t>::min(),
81 numeric_limits<int64_t>::max());}, "bge, less");
82 expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::min(),
83 numeric_limits<int64_t>::min());}, "bge, equal");
84 expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::max(),
85 numeric_limits<int64_t>::min());}, "bge, greater");
86
87 // BLTU
88 expect<bool>(true, []{return I::blt(numeric_limits<int64_t>::min(),
89 numeric_limits<int64_t>::max());}, "bltu, greater");
90 expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::min(),
91 numeric_limits<int64_t>::min());}, "bltu, equal");
92 expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::max(),
93 numeric_limits<int64_t>::min());}, "bltu, less");
94
95 // BGEU
96 expect<bool>(false, []{return I::bge(numeric_limits<int64_t>::min(),
97 numeric_limits<int64_t>::max());}, "bgeu, greater");
98 expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::min(),
99 numeric_limits<int64_t>::min());}, "bgeu, equal");
100 expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::max(),
101 numeric_limits<int64_t>::min());}, "bgeu, less");
102
103 // Load (LB, LH, LW, LBU, LHU)
104 expect<int64_t>(7, []{return I::load<int8_t, int64_t>(0x07);},
105 "lb, positive");
106 expect<int64_t>(numeric_limits<int8_t>::min(),
107 []{return I::load<int8_t, int64_t>(0x80);}, "lb, negative");
108 expect<int64_t>(1792, []{return I::load<int16_t, int64_t>(0x0700);},
109 "lh, positive");
110 expect<int64_t>(numeric_limits<int16_t>::min(),
111 []{return I::load<int16_t, int64_t>(0x8000);}, "lh, negative");
112 expect<int64_t>(458752, []{return I::load<int32_t, int64_t>(0x00070000);},
113 "lw, positive");
114 expect<int64_t>(numeric_limits<int32_t>::min(),
115 []{return I::load<int32_t, int64_t>(0x80000000);},
116 "lw, negative");
117 expect<uint64_t>(128, []{return I::load<uint8_t, uint64_t>(0x80);}, "lbu");
118 expect<uint64_t>(32768, []{return I::load<uint16_t, uint64_t>(0x8000);},
119 "lhu");
120
121 // Store (SB, SH, SW)
122 expect<uint8_t>(0xFF, []{return I::store<int8_t>(-1);}, "sb");
123 expect<uint16_t>(0xFFFF, []{return I::store<int16_t>(-1);}, "sh");
124 expect<uint32_t>(0xFFFFFFFF, []{return I::store<int32_t>(-1);}, "sw");
125
126 // ADDI
127 expect<int64_t>(1073742078, []{return I::addi(0x3FFFFFFF, 255);},
128 "addi");
129 expect<int64_t>(1, []{return I::addi(-1, 2);}, "addi, overflow");
130
131 // SLTI
132 expect<bool>(true, []{return I::slti(-1, 0);}, "slti, true");
133 expect<bool>(false, []{return I::slti(0, -1);}, "slti, false");
134
135 // SLTIU
136 expect<bool>(false, []{return I::sltiu(-1, 0);}, "sltiu, false");
137 expect<bool>(true, []{return I::sltiu(0, -1);}, "sltiu, true");
138 expect<bool>(true, []{return I::sltiu(0xFFFF, -1);}, "sltiu, sext");
139
140 // XORI
141 expect<uint64_t>(0xFF, []{return I::xori(0xAA, 0x55);}, "xori (1)");
142 expect<uint64_t>(0, []{return I::xori(0xAA, 0xAA);}, "xori (0)");
143
144 // ORI
145 expect<uint64_t>(0xFF, []{return I::ori(0xAA, 0x55);}, "ori (1)");
146 expect<uint64_t>(0xAA, []{return I::ori(0xAA, 0xAA);}, "ori (A)");
147
148 // ANDI
149 expect<uint64_t>(0, []{return I::andi(-1, 0);}, "andi (0)");
150 expect<uint64_t>(0x1234567812345678ULL,
151 []{return I::andi(0x1234567812345678ULL, -1);}, "andi (1)");
152
153 // SLLI
154 expect<int64_t>(65280, []{return I::slli(255, 8);}, "slli, general");
155 expect<int64_t>(numeric_limits<int64_t>::min(),
156 []{return I::slli(255, 63);}, "slli, erase");
157
158 // SRLI
159 expect<int64_t>(255, []{return I::srli(65280, 8);}, "srli, general");
160 expect<int64_t>(0, []{return I::srli(255, 8);}, "srli, erase");
161 expect<int64_t>(1, []{return I::srli(numeric_limits<int64_t>::min(), 63);},
162 "srli, negative");
163
164 // SRAI
165 expect<int64_t>(255, []{return I::srai(65280, 8);}, "srai, general");
166 expect<int64_t>(0, []{return I::srai(255, 8);}, "srai, erase");
167 expect<int64_t>(-1,
168 []{return I::srai(numeric_limits<int64_t>::min(), 63);},
169 "srai, negative");
170
171 // ADD
172 expect<int64_t>(1073742078, []{return I::add(0x3FFFFFFF, 255);}, "add");
173 expect<int64_t>(-1,
174 []{return I::add(0x7FFFFFFFFFFFFFFFLL, 0x8000000000000000LL);},
175 "add, overflow");
176
177 // SUB
178 expect<int64_t>(65535, []{return I::sub(65536, 1);}, "sub");
179 expect<int64_t>(-1,
180 []{return I::sub(0x7FFFFFFFFFFFFFFFLL, 0x8000000000000000LL);},
181 "sub, \"overflow\"");
182
183 // SLL
184 expect<int64_t>(65280, []{return I::sll(255, 8);}, "sll, general");
185 expect<int64_t>(numeric_limits<int64_t>::min(),
186 []{return I::sll(255, 63);}, "sll, erase");
187
188 // SLT
189 expect<bool>(true, []{return I::slt(-1, 0);}, "slt, true");
190 expect<bool>(false, []{return I::slt(0, -1);}, "slt, false");
191
192 // SLTU
193 expect<bool>(false, []{return I::sltu(-1, 0);}, "sltu, false");
194 expect<bool>(true, []{return I::sltu(0, -1);}, "sltu, true");
195
196 // XOR
197 expect<uint64_t>(-1,
198 []{return I::xor_inst(0xAAAAAAAAAAAAAAAAULL,
199 0x5555555555555555ULL);},
200 "xor (1)");
201 expect<uint64_t>(0,
202 []{return I::xor_inst(0xAAAAAAAAAAAAAAAAULL,
203 0xAAAAAAAAAAAAAAAAULL);},
204 "xor (0)");
205
206 // SRL
207 expect<uint64_t>(255, []{return I::srl(65280, 8);}, "srl, general");
208 expect<uint64_t>(0, []{return I::srl(255, 8);}, "srl, erase");
209 expect<uint64_t>(1, []{return I::srl(numeric_limits<int64_t>::min(), 63);},
210 "srl, negative");
211
212 // SRA
213 expect<int64_t>(255, []{return I::sra(65280, 8);}, "sra, general");
214 expect<int64_t>(0, []{return I::sra(255, 8);}, "sra, erase");
215 expect<int64_t>(-1, []{return I::sra(numeric_limits<int64_t>::min(), 63);},
216 "sra, negative");
217
218 // OR
219 expect<uint64_t>(-1,
220 []{return I::or_inst(0xAAAAAAAAAAAAAAAAULL,
221 0x5555555555555555ULL);},
222 "or (1)");
223 expect<uint64_t>(0xAAAAAAAAAAAAAAAAULL,
224 []{return I::or_inst(0xAAAAAAAAAAAAAAAAULL,
225 0xAAAAAAAAAAAAAAAAULL);},
226 "or (A)");
227
228 // AND
229 expect<uint64_t>(0, []{return I::and_inst(-1, 0);}, "and (0)");
230 expect<uint64_t>(0x1234567812345678ULL,
231 []{return I::and_inst(0x1234567812345678ULL, -1);}, "and (-1)");
232
233 // FENCE/FENCE.I
234 asm volatile("fence" : : );
235 asm volatile("fence.i" : : );
236
237 // ECALL
238 char fname[] = "test.txt";
239 char teststr[] = "this is a test";
240 expect<bool>(true, [=]{
241 int fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0644);
242 if (fd < 0) {
243 return false;
244 }
245 size_t n = write(fd, teststr, sizeof(teststr));
246 cout << "Bytes written: " << n << endl;
247 return close(fd) >= 0 && n > 0;
248 }, "open, write");
249 expect<int>(0, [=]{return access(fname, F_OK);}, "access F_OK");
250 expect<int>(0, [=]{return access(fname, R_OK);}, "access R_OK");
251 expect<int>(0, [=]{return access(fname, W_OK);}, "access W_OK");
252 // gem5's implementation of access is incorrect; it should return
253 // -1 on failure, not -errno. Account for this using an inequality.
254 expect<bool>(true, [=]{return access(fname, X_OK) != 0;}, "access X_OK");
255 expect<bool>(true, [=]{
256 struct stat stat_buf, fstat_buf;
257 int s = stat(fname, &stat_buf);
258 if (s < 0) {
259 return false;
260 } else {
261 cout << "stat:" << endl;
262 cout << "\tst_dev =\t" << stat_buf.st_dev << endl;
263 cout << "\tst_ino =\t" << stat_buf.st_ino << endl;
264 cout << "\tst_mode =\t" << stat_buf.st_mode << endl;
265 cout << "\tst_nlink =\t" << stat_buf.st_nlink << endl;
266 cout << "\tst_uid =\t" << stat_buf.st_uid << endl;
267 cout << "\tst_gid =\t" << stat_buf.st_gid << endl;
268 cout << "\tst_rdev =\t" << stat_buf.st_rdev << endl;
269 cout << "\tst_size =\t" << stat_buf.st_size << endl;
270 cout << "\tst_blksize =\t" << stat_buf.st_blksize << endl;
271 cout << "\tst_blocks =\t" << stat_buf.st_blocks << endl;
272 }
273 int fd = open(fname, O_RDONLY);
274 if (fd < 0) {
275 return false;
276 }
277 int f = fstat(fd, &fstat_buf);
278 if (f >= 0) {
279 cout << "fstat:" << endl;
280 cout << "\tst_dev =\t" << fstat_buf.st_dev << endl;
281 cout << "\tst_ino =\t" << fstat_buf.st_ino << endl;
282 cout << "\tst_mode =\t" << fstat_buf.st_mode << endl;
283 cout << "\tst_nlink =\t" << fstat_buf.st_nlink << endl;
284 cout << "\tst_uid =\t" << fstat_buf.st_uid << endl;
285 cout << "\tst_gid =\t" << fstat_buf.st_gid << endl;
286 cout << "\tst_rdev =\t" << fstat_buf.st_rdev << endl;
287 cout << "\tst_size =\t" << fstat_buf.st_size << endl;
288 cout << "\tst_blksize =\t" << fstat_buf.st_blksize << endl;
289 cout << "\tst_blocks =\t" << fstat_buf.st_blocks << endl;
290 }
291 return close(fd) >= 0 && f >= 0;
292 }, "open, stat");
293 expect<bool>(true, [=]{
294 int fd = open(fname, O_RDONLY);
295 if (fd < 0) {
296 return false;
297 }
298 char in[128];
299 size_t n = read(fd, in, sizeof(in));
300 cout << "Bytes read: " << n << endl;
301 cout << "String read: " << in << endl;
302 int cl = close(fd);
303 int un = unlink(fname);
304 return n > 0 && cl >= 0 && un >= 0 && strcmp(teststr, in) == 0;
305 }, "open, read, unlink");
306 expect<bool>(true, []{
307 struct tms buf;
308 clock_t t = times(&buf);
309 cout << "times:" << endl;
310 cout << "\ttms_utime =\t" << buf.tms_utime << endl;
311 cout << "\ttms_stime =\t" << buf.tms_stime << endl;
312 cout << "\ttms_cutime =\t" << buf.tms_cutime << endl;
313 cout << "\ttms_cstime =\t" << buf.tms_cstime << endl;
314 return t > 0;
315 }, "times");
316 expect<int>(0, []{
317 struct timeval time;
318 int res = gettimeofday(&time, nullptr);
319 cout << "timeval:" << endl;
320 cout << "\ttv_sec =\t" << time.tv_sec << endl;
321 cout << "\ttv_usec =\t" << time.tv_usec << endl;
322 return res;
323 }, "gettimeofday");
324
325 // EBREAK not tested because it only makes sense in FS mode or when
326 // using gdb
327
328 // ERET not tested because it only makes sense in FS mode and will cause
329 // a panic when used in SE mode
330
331 // CSRs (RDCYCLE, RDTIME, RDINSTRET)
332 expect<bool>(true, []{
333 uint64_t cycles = 0;
334 asm("rdcycle %0" : "=r" (cycles));
335 cout << "Cycles: " << cycles << endl;
336 return cycles > 0;
337 }, "rdcycle");
338 expect<bool>(true, []{
339 uint64_t time = 0;
340 asm("rdtime %0" : "=r" (time));
341 cout << "Time: " << time << endl;
342 return time > 0;
343 }, "rdtime");
344 expect<bool>(true, []{
345 uint64_t instret = 0;
346 asm("rdinstret %0" : "=r" (instret));
347 cout << "Instructions Retired: " << instret << endl;
348 return instret > 0;
349 }, "rdinstret");
350
351 // 64-bit memory (LWU, LD, SD)
352 expect<int64_t>(0xFFFFFFFF, []{return I::load<uint32_t, uint64_t>(-1);},
353 "lwu");
354 expect<int64_t>(30064771072,
355 []{return I::load<int64_t, int64_t>(30064771072);}, "ld");
356 expect<uint64_t>(-1, []{return I::store<int64_t>(-1);}, "sd");
357
358 // ADDIW
359 expect<int64_t>(268435710, []{return I::addiw(0x0FFFFFFF, 255);}, "addiw");
360 expect<int64_t>(-2147481602, []{return I::addiw(0x7FFFFFFF, 0x7FF);},
361 "addiw, overflow");
362 expect<int64_t>(0, []{return I::addiw(0x7FFFFFFFFFFFFFFFLL, 1);},
363 "addiw, truncate");
364
365 // SLLIW
366 expect<int64_t>(65280, []{return I::slliw(255, 8);}, "slliw, general");
367 expect<int64_t>(numeric_limits<int32_t>::min(),
368 []{return I::slliw(255, 31);}, "slliw, erase");
369 expect<int64_t>(numeric_limits<int32_t>::min(),
370 []{return I::slliw(0xFFFFFFFF00800000LL, 8);}, "slliw, truncate");
371
372 // SRLIW
373 expect<int64_t>(255, []{return I::srliw(65280, 8);}, "srliw, general");
374 expect<int64_t>(0, []{return I::srliw(255, 8);}, "srliw, erase");
375 expect<int64_t>(1,
376 []{return I::srliw(numeric_limits<int32_t>::min(), 31);},
377 "srliw, negative");
378 expect<int64_t>(1, []{return I::srliw(0xFFFFFFFF80000000LL, 31);},
379 "srliw, truncate");
380
381 // SRAIW
382 expect<int64_t>(255, []{return I::sraiw(65280, 8);}, "sraiw, general");
383 expect<int64_t>(0, []{return I::sraiw(255, 8);}, "sraiw, erase");
384 expect<int64_t>(-1,
385 []{return I::sraiw(numeric_limits<int32_t>::min(), 31);},
386 "sraiw, negative");
387 expect<int64_t>(-1, []{return I::sraiw(0x0000000180000000LL, 31);},
388 "sraiw, truncate");
389
390 // ADDW
391 expect<int64_t>(1073742078, []{return I::addw(0x3FFFFFFF, 255);}, "addw");
392 expect<int64_t>(-1, []{return I::addw(0x7FFFFFFF, 0x80000000);},
393 "addw, overflow");
394 expect<int64_t>(65536, []{return I::addw(0xFFFFFFFF0000FFFFLL, 1);},
395 "addw, truncate");
396
397 // SUBW
398 expect<int64_t>(65535, []{return I::subw(65536, 1);}, "subw");
399 expect<int64_t>(-1, []{return I::subw(0x7FFFFFFF, 0x80000000);},
400 "subw, \"overflow\"");
401 expect<int64_t>(0,
402 []{return I::subw(0xAAAAAAAAFFFFFFFFULL, 0x55555555FFFFFFFFULL);},
403 "subw, truncate");
404
405 // SLLW
406 expect<int64_t>(65280, []{return I::sllw(255, 8);}, "sllw, general");
407 expect<int64_t>(numeric_limits<int32_t>::min(),
408 []{return I::sllw(255, 31);}, "sllw, erase");
409 expect<int64_t>(numeric_limits<int32_t>::min(),
410 []{return I::sllw(0xFFFFFFFF00008000LL, 16);}, "sllw, truncate");
411
412 // SRLW
413 expect<uint64_t>(255, []{return I::srlw(65280, 8);}, "srlw, general");
414 expect<uint64_t>(0, []{return I::srlw(255, 8);}, "srlw, erase");
415 expect<uint64_t>(1,
416 []{return I::srlw(numeric_limits<int32_t>::min(), 31);},
417 "srlw, negative");
418 expect<uint64_t>(1, []{return I::srlw(0x0000000180000000LL, 31);},
419 "srlw, truncate");
420
421 // SRAW
422 expect<int64_t>(255, []{return I::sraw(65280, 8);}, "sraw, general");
423 expect<int64_t>(0, []{return I::sraw(255, 8);}, "sraw, erase");
424 expect<int64_t>(-1,
425 []{return I::sraw(numeric_limits<int32_t>::min(), 31);},
426 "sraw, negative");
427 expect<int64_t>(1, []{return I::sraw(0xFFFFFFFF40000000LL, 30);},
428 "sraw, truncate");
429
430 return 0;
431 }