2 * Copyright (c) 2016 The University of Virginia
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.
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.
32 #include <sys/times.h>
33 #include <sys/types.h>
47 using namespace insttest
;
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");
55 expect
<bool>(true, []{return I::auipc(3);}, "auipc");
58 expect
<bool>(true, []{return I::jal();}, "jal");
59 expect
<bool>(true, []{return I::jalr();}, "jalr");
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");
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");
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");
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");
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");
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");
103 // Load (LB, LH, LW, LBU, LHU)
104 expect
<int64_t>(7, []{return I::load
<int8_t, int64_t>(0x07);},
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);},
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);},
114 expect
<int64_t>(numeric_limits
<int32_t>::min(),
115 []{return I::load
<int32_t, int64_t>(0x80000000);},
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);},
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");
127 expect
<int64_t>(1073742078, []{return I::addi(0x3FFFFFFF, 255);},
129 expect
<int64_t>(1, []{return I::addi(-1, 2);}, "addi, overflow");
132 expect
<bool>(true, []{return I::slti(-1, 0);}, "slti, true");
133 expect
<bool>(false, []{return I::slti(0, -1);}, "slti, false");
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");
141 expect
<uint64_t>(0xFF, []{return I::xori(0xAA, 0x55);}, "xori (1)");
142 expect
<uint64_t>(0, []{return I::xori(0xAA, 0xAA);}, "xori (0)");
145 expect
<uint64_t>(0xFF, []{return I::ori(0xAA, 0x55);}, "ori (1)");
146 expect
<uint64_t>(0xAA, []{return I::ori(0xAA, 0xAA);}, "ori (A)");
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)");
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");
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);},
165 expect
<int64_t>(255, []{return I::srai(65280, 8);}, "srai, general");
166 expect
<int64_t>(0, []{return I::srai(255, 8);}, "srai, erase");
168 []{return I::srai(numeric_limits
<int64_t>::min(), 63);},
172 expect
<int64_t>(1073742078, []{return I::add(0x3FFFFFFF, 255);}, "add");
174 []{return I::add(0x7FFFFFFFFFFFFFFFLL
, 0x8000000000000000LL
);},
178 expect
<int64_t>(65535, []{return I::sub(65536, 1);}, "sub");
180 []{return I::sub(0x7FFFFFFFFFFFFFFFLL
, 0x8000000000000000LL
);},
181 "sub, \"overflow\"");
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");
189 expect
<bool>(true, []{return I::slt(-1, 0);}, "slt, true");
190 expect
<bool>(false, []{return I::slt(0, -1);}, "slt, false");
193 expect
<bool>(false, []{return I::sltu(-1, 0);}, "sltu, false");
194 expect
<bool>(true, []{return I::sltu(0, -1);}, "sltu, true");
198 []{return I::xor_inst(0xAAAAAAAAAAAAAAAAULL
,
199 0x5555555555555555ULL
);},
202 []{return I::xor_inst(0xAAAAAAAAAAAAAAAAULL
,
203 0xAAAAAAAAAAAAAAAAULL
);},
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);},
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);},
220 []{return I::or_inst(0xAAAAAAAAAAAAAAAAULL
,
221 0x5555555555555555ULL
);},
223 expect
<uint64_t>(0xAAAAAAAAAAAAAAAAULL
,
224 []{return I::or_inst(0xAAAAAAAAAAAAAAAAULL
,
225 0xAAAAAAAAAAAAAAAAULL
);},
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)");
234 asm volatile("fence" : : );
235 asm volatile("fence.i" : : );
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);
245 size_t n
= write(fd
, teststr
, sizeof(teststr
));
246 cout
<< "Bytes written: " << n
<< endl
;
247 return close(fd
) >= 0 && n
> 0;
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
);
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
;
273 int fd
= open(fname
, O_RDONLY
);
277 int f
= fstat(fd
, &fstat_buf
);
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
;
291 return close(fd
) >= 0 && f
>= 0;
293 expect
<bool>(true, [=]{
294 int fd
= open(fname
, O_RDONLY
);
299 size_t n
= read(fd
, in
, sizeof(in
));
300 cout
<< "Bytes read: " << n
<< endl
;
301 cout
<< "String read: " << in
<< endl
;
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, []{
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
;
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
;
325 // EBREAK not tested because it only makes sense in FS mode or when
328 // ERET not tested because it only makes sense in FS mode and will cause
329 // a panic when used in SE mode
331 // CSRs (RDCYCLE, RDTIME, RDINSTRET)
332 expect
<bool>(true, []{
334 asm("rdcycle %0" : "=r" (cycles
));
335 cout
<< "Cycles: " << cycles
<< endl
;
338 expect
<bool>(true, []{
340 asm("rdtime %0" : "=r" (time
));
341 cout
<< "Time: " << time
<< endl
;
344 expect
<bool>(true, []{
345 uint64_t instret
= 0;
346 asm("rdinstret %0" : "=r" (instret
));
347 cout
<< "Instructions Retired: " << instret
<< endl
;
351 // 64-bit memory (LWU, LD, SD)
352 expect
<int64_t>(0xFFFFFFFF, []{return I::load
<uint32_t, uint64_t>(-1);},
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");
359 expect
<int64_t>(268435710, []{return I::addiw(0x0FFFFFFF, 255);}, "addiw");
360 expect
<int64_t>(-2147481602, []{return I::addiw(0x7FFFFFFF, 0x7FF);},
362 expect
<int64_t>(0, []{return I::addiw(0x7FFFFFFFFFFFFFFFLL
, 1);},
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");
373 expect
<int64_t>(255, []{return I::srliw(65280, 8);}, "srliw, general");
374 expect
<int64_t>(0, []{return I::srliw(255, 8);}, "srliw, erase");
376 []{return I::srliw(numeric_limits
<int32_t>::min(), 31);},
378 expect
<int64_t>(1, []{return I::srliw(0xFFFFFFFF80000000LL
, 31);},
382 expect
<int64_t>(255, []{return I::sraiw(65280, 8);}, "sraiw, general");
383 expect
<int64_t>(0, []{return I::sraiw(255, 8);}, "sraiw, erase");
385 []{return I::sraiw(numeric_limits
<int32_t>::min(), 31);},
387 expect
<int64_t>(-1, []{return I::sraiw(0x0000000180000000LL
, 31);},
391 expect
<int64_t>(1073742078, []{return I::addw(0x3FFFFFFF, 255);}, "addw");
392 expect
<int64_t>(-1, []{return I::addw(0x7FFFFFFF, 0x80000000);},
394 expect
<int64_t>(65536, []{return I::addw(0xFFFFFFFF0000FFFFLL
, 1);},
398 expect
<int64_t>(65535, []{return I::subw(65536, 1);}, "subw");
399 expect
<int64_t>(-1, []{return I::subw(0x7FFFFFFF, 0x80000000);},
400 "subw, \"overflow\"");
402 []{return I::subw(0xAAAAAAAAFFFFFFFFULL
, 0x55555555FFFFFFFFULL
);},
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");
413 expect
<uint64_t>(255, []{return I::srlw(65280, 8);}, "srlw, general");
414 expect
<uint64_t>(0, []{return I::srlw(255, 8);}, "srlw, erase");
416 []{return I::srlw(numeric_limits
<int32_t>::min(), 31);},
418 expect
<uint64_t>(1, []{return I::srlw(0x0000000180000000LL
, 31);},
422 expect
<int64_t>(255, []{return I::sraw(65280, 8);}, "sraw, general");
423 expect
<int64_t>(0, []{return I::sraw(255, 8);}, "sraw, erase");
425 []{return I::sraw(numeric_limits
<int32_t>::min(), 31);},
427 expect
<int64_t>(1, []{return I::sraw(0xFFFFFFFF40000000LL
, 30);},