1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "gtest/gtest.h"
18
19 #include <unistd.h>
20
21 #include <cstdint>
22 #include <initializer_list>
23 #include <tuple>
24 #include <type_traits>
25
26 #include "berberis/base/bit_util.h"
27 #include "berberis/guest_state/guest_addr.h"
28 #include "berberis/guest_state/guest_state_riscv64.h"
29 #include "berberis/interpreter/riscv64/interpreter.h"
30 #include "berberis/intrinsics/guest_fpstate.h"
31
32 namespace berberis {
33
34 namespace {
35
36 class Riscv64InterpreterTest : public ::testing::Test {
37 public:
38 template <RegisterType register_type, uint64_t expected_result>
InterpretCompressedStore(uint16_t insn_bytes,uint64_t offset)39 void InterpretCompressedStore(uint16_t insn_bytes, uint64_t offset) {
40 auto code_start = ToGuestAddr(&insn_bytes);
41 state_.cpu.insn_addr = code_start;
42 store_area_ = 0;
43 SetXReg<8>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&store_area_) - offset));
44 SetReg<register_type, 9>(state_.cpu, kDataToLoad);
45 InterpretInsn(&state_);
46 EXPECT_EQ(store_area_, expected_result);
47 }
48
49 template <RegisterType register_type, uint64_t expected_result>
InterpretCompressedLoad(uint16_t insn_bytes,uint64_t offset)50 void InterpretCompressedLoad(uint16_t insn_bytes, uint64_t offset) {
51 auto code_start = ToGuestAddr(&insn_bytes);
52 state_.cpu.insn_addr = code_start;
53 SetXReg<8>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&kDataToLoad) - offset));
54 InterpretInsn(&state_);
55 EXPECT_EQ((GetReg<register_type, 9>(state_.cpu)), expected_result);
56 }
57
InterpretCAddi4spn(uint16_t insn_bytes,uint64_t expected_offset)58 void InterpretCAddi4spn(uint16_t insn_bytes, uint64_t expected_offset) {
59 auto code_start = ToGuestAddr(&insn_bytes);
60 state_.cpu.insn_addr = code_start;
61 SetXReg<2>(state_.cpu, 1);
62 InterpretInsn(&state_);
63 EXPECT_EQ(GetXReg<9>(state_.cpu), 1 + expected_offset);
64 }
65
InterpretCAddi(uint16_t insn_bytes,uint64_t expected_increment)66 void InterpretCAddi(uint16_t insn_bytes, uint64_t expected_increment) {
67 auto code_start = ToGuestAddr(&insn_bytes);
68 state_.cpu.insn_addr = code_start;
69 SetXReg<2>(state_.cpu, 1);
70 InterpretInsn(&state_);
71 EXPECT_EQ(GetXReg<2>(state_.cpu), 1 + expected_increment);
72 }
73
InterpretCJ(uint16_t insn_bytes,int16_t expected_offset)74 void InterpretCJ(uint16_t insn_bytes, int16_t expected_offset) {
75 auto code_start = ToGuestAddr(&insn_bytes);
76 state_.cpu.insn_addr = code_start;
77 InterpretInsn(&state_);
78 EXPECT_EQ(state_.cpu.insn_addr, code_start + expected_offset);
79 }
80
InterpretCsr(uint32_t insn_bytes,uint8_t expected_rm)81 void InterpretCsr(uint32_t insn_bytes, uint8_t expected_rm) {
82 auto code_start = ToGuestAddr(&insn_bytes);
83 state_.cpu.insn_addr = code_start;
84 state_.cpu.frm = 0b001u;
85 InterpretInsn(&state_);
86 EXPECT_EQ(GetXReg<2>(state_.cpu), 0b001u);
87 EXPECT_EQ(state_.cpu.frm, expected_rm);
88 }
89
InterpretOp(uint32_t insn_bytes,std::initializer_list<std::tuple<uint64_t,uint64_t,uint64_t>> args)90 void InterpretOp(uint32_t insn_bytes,
91 std::initializer_list<std::tuple<uint64_t, uint64_t, uint64_t>> args) {
92 for (auto [arg1, arg2, expected_result] : args) {
93 state_.cpu.insn_addr = ToGuestAddr(&insn_bytes);
94 SetXReg<2>(state_.cpu, arg1);
95 SetXReg<3>(state_.cpu, arg2);
96 InterpretInsn(&state_);
97 EXPECT_EQ(GetXReg<1>(state_.cpu), expected_result);
98 }
99 }
100
InterpretOpFp(uint32_t insn_bytes,std::initializer_list<std::tuple<uint64_t,uint64_t,uint64_t>> args)101 void InterpretOpFp(uint32_t insn_bytes,
102 std::initializer_list<std::tuple<uint64_t, uint64_t, uint64_t>> args) {
103 for (auto [arg1, arg2, expected_result] : args) {
104 state_.cpu.insn_addr = ToGuestAddr(&insn_bytes);
105 SetFReg<2>(state_.cpu, arg1);
106 SetFReg<3>(state_.cpu, arg2);
107 InterpretInsn(&state_);
108 EXPECT_EQ(GetFReg<1>(state_.cpu), expected_result);
109 }
110 }
111
InterpretFence(uint32_t insn_bytes)112 void InterpretFence(uint32_t insn_bytes) {
113 state_.cpu.insn_addr = ToGuestAddr(&insn_bytes);
114 InterpretInsn(&state_);
115 }
116
InterpretAmo(uint32_t insn_bytes,uint64_t arg1,uint64_t arg2,uint64_t expected_result,uint64_t expected_memory)117 void InterpretAmo(uint32_t insn_bytes, uint64_t arg1, uint64_t arg2, uint64_t expected_result,
118 uint64_t expected_memory) {
119 state_.cpu.insn_addr = ToGuestAddr(&insn_bytes);
120 // Copy arg1 into store_area_
121 store_area_ = arg1;
122 SetXReg<2>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&store_area_)));
123 SetXReg<3>(state_.cpu, arg2);
124 InterpretInsn(&state_);
125 EXPECT_EQ(GetXReg<1>(state_.cpu), expected_result);
126 EXPECT_EQ(store_area_, expected_memory);
127 }
128
InterpretAmo(uint32_t insn_bytes32,uint32_t insn_bytes64,uint64_t expected_memory)129 void InterpretAmo(uint32_t insn_bytes32, uint32_t insn_bytes64, uint64_t expected_memory) {
130 InterpretAmo(insn_bytes32, 0xffff'eeee'dddd'ccccULL, 0xaaaa'bbbb'cccc'ddddULL,
131 0xffff'ffff'dddd'ccccULL, 0xffff'eeee'0000'0000 | uint32_t(expected_memory));
132 InterpretAmo(insn_bytes64, 0xffff'eeee'dddd'ccccULL, 0xaaaa'bbbb'cccc'ddddULL,
133 0xffff'eeee'dddd'ccccULL, expected_memory);
134 }
135
InterpretLui(uint32_t insn_bytes,uint64_t expected_result)136 void InterpretLui(uint32_t insn_bytes, uint64_t expected_result) {
137 auto code_start = ToGuestAddr(&insn_bytes);
138 state_.cpu.insn_addr = code_start;
139 InterpretInsn(&state_);
140 EXPECT_EQ(GetXReg<1>(state_.cpu), expected_result);
141 }
142
InterpretAuipc(uint32_t insn_bytes,uint64_t expected_offset)143 void InterpretAuipc(uint32_t insn_bytes, uint64_t expected_offset) {
144 auto code_start = ToGuestAddr(&insn_bytes);
145 state_.cpu.insn_addr = code_start;
146 InterpretInsn(&state_);
147 EXPECT_EQ(GetXReg<1>(state_.cpu), expected_offset + code_start);
148 }
149
InterpretOpImm(uint32_t insn_bytes,std::initializer_list<std::tuple<uint64_t,uint16_t,uint64_t>> args)150 void InterpretOpImm(uint32_t insn_bytes,
151 std::initializer_list<std::tuple<uint64_t, uint16_t, uint64_t>> args) {
152 for (auto [arg1, imm, expected_result] : args) {
153 CHECK_LE(imm, 63);
154 uint32_t insn_bytes_with_immediate = insn_bytes | imm << 20;
155 state_.cpu.insn_addr = bit_cast<GuestAddr>(&insn_bytes_with_immediate);
156 SetXReg<2>(state_.cpu, arg1);
157 InterpretInsn(&state_);
158 EXPECT_EQ(GetXReg<1>(state_.cpu), expected_result);
159 }
160 }
161
InterpretLoad(uint32_t insn_bytes,uint64_t expected_result)162 void InterpretLoad(uint32_t insn_bytes, uint64_t expected_result) {
163 state_.cpu.insn_addr = ToGuestAddr(&insn_bytes);
164 // Offset is always 8.
165 SetXReg<2>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&kDataToLoad) - 8));
166 InterpretInsn(&state_);
167 EXPECT_EQ(GetXReg<1>(state_.cpu), expected_result);
168 }
169
InterpretLoadFp(uint32_t insn_bytes,uint64_t expected_result)170 void InterpretLoadFp(uint32_t insn_bytes, uint64_t expected_result) {
171 state_.cpu.insn_addr = ToGuestAddr(&insn_bytes);
172 // Offset is always 8.
173 SetXReg<2>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&kDataToLoad) - 8));
174 InterpretInsn(&state_);
175 EXPECT_EQ(GetFReg<1>(state_.cpu), expected_result);
176 }
177
InterpretStore(uint32_t insn_bytes,uint64_t expected_result)178 void InterpretStore(uint32_t insn_bytes, uint64_t expected_result) {
179 state_.cpu.insn_addr = ToGuestAddr(&insn_bytes);
180 // Offset is always 8.
181 SetXReg<1>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&store_area_) - 8));
182 SetXReg<2>(state_.cpu, kDataToStore);
183 store_area_ = 0;
184 InterpretInsn(&state_);
185 EXPECT_EQ(store_area_, expected_result);
186 }
187
InterpretStoreFp(uint32_t insn_bytes,uint64_t expected_result)188 void InterpretStoreFp(uint32_t insn_bytes, uint64_t expected_result) {
189 state_.cpu.insn_addr = ToGuestAddr(&insn_bytes);
190 // Offset is always 8.
191 SetXReg<1>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&store_area_) - 8));
192 SetFReg<2>(state_.cpu, kDataToStore);
193 store_area_ = 0;
194 InterpretInsn(&state_);
195 EXPECT_EQ(store_area_, expected_result);
196 }
197
InterpretBranch(uint32_t insn_bytes,std::initializer_list<std::tuple<uint64_t,uint64_t,int8_t>> args)198 void InterpretBranch(uint32_t insn_bytes,
199 std::initializer_list<std::tuple<uint64_t, uint64_t, int8_t>> args) {
200 auto code_start = ToGuestAddr(&insn_bytes);
201 for (auto [arg1, arg2, expected_offset] : args) {
202 state_.cpu.insn_addr = code_start;
203 SetXReg<1>(state_.cpu, arg1);
204 SetXReg<2>(state_.cpu, arg2);
205 InterpretInsn(&state_);
206 EXPECT_EQ(state_.cpu.insn_addr, code_start + expected_offset);
207 }
208 }
209
InterpretJumpAndLink(uint32_t insn_bytes,int8_t expected_offset)210 void InterpretJumpAndLink(uint32_t insn_bytes, int8_t expected_offset) {
211 auto code_start = ToGuestAddr(&insn_bytes);
212 state_.cpu.insn_addr = code_start;
213 InterpretInsn(&state_);
214 EXPECT_EQ(state_.cpu.insn_addr, code_start + expected_offset);
215 EXPECT_EQ(GetXReg<1>(state_.cpu), code_start + 4);
216 }
217
InterpretJumpAndLinkRegister(uint32_t insn_bytes,uint64_t base_disp,int64_t expected_offset)218 void InterpretJumpAndLinkRegister(uint32_t insn_bytes, uint64_t base_disp,
219 int64_t expected_offset) {
220 auto code_start = ToGuestAddr(&insn_bytes);
221 state_.cpu.insn_addr = code_start;
222 SetXReg<2>(state_.cpu, code_start + base_disp);
223 InterpretInsn(&state_);
224 EXPECT_EQ(state_.cpu.insn_addr, code_start + expected_offset);
225 }
226
227 protected:
228 static constexpr uint64_t kDataToLoad{0xffffeeeeddddccccULL};
229 static constexpr uint64_t kDataToStore = kDataToLoad;
230 uint64_t store_area_;
231 ThreadState state_;
232 };
233
TEST_F(Riscv64InterpreterTest,CLw)234 TEST_F(Riscv64InterpreterTest, CLw) {
235 union {
236 uint16_t offset;
237 struct {
238 uint8_t : 2;
239 uint8_t i2 : 1;
240 uint8_t i3_i5 : 3;
241 uint8_t i6 : 1;
242 } i_bits;
243 };
244 for (offset = uint8_t{0}; offset < uint8_t{128}; offset += 4) {
245 union {
246 int16_t parcel;
247 struct {
248 uint8_t low_opcode : 2;
249 uint8_t rd : 3;
250 uint8_t i6 : 1;
251 uint8_t i2 : 1;
252 uint8_t rs : 3;
253 uint8_t i3_i5 : 3;
254 uint8_t high_opcode : 3;
255 } __attribute__((__packed__));
256 } o_bits = {
257 .low_opcode = 0b00,
258 .rd = 1,
259 .i6 = i_bits.i6,
260 .i2 = i_bits.i2,
261 .rs = 0,
262 .i3_i5 = i_bits.i3_i5,
263 .high_opcode = 0b010,
264 };
265 InterpretCompressedLoad<RegisterType::kReg,
266 static_cast<uint64_t>(static_cast<int32_t>(kDataToLoad))>(o_bits.parcel,
267 offset);
268 }
269 }
270
271 template <uint16_t opcode, auto execute_instruction_func>
TestCompressedLoadOrStore(Riscv64InterpreterTest * that)272 void TestCompressedLoadOrStore(Riscv64InterpreterTest* that) {
273 union {
274 uint16_t offset;
275 struct {
276 uint8_t : 3;
277 uint8_t i3_i5 : 3;
278 uint8_t i6_i7 : 2;
279 } i_bits;
280 };
281 for (offset = int16_t{0}; offset < int16_t{256}; offset += 8) {
282 union {
283 int16_t parcel;
284 struct [[gnu::packed]] {
285 uint8_t low_opcode : 2;
286 uint8_t rd : 3;
287 uint8_t i6_i7 : 2;
288 uint8_t rs : 3;
289 uint8_t i3_i5 : 3;
290 uint8_t high_opcode : 3;
291 };
292 } o_bits = {
293 .low_opcode = 0b00,
294 .rd = 1,
295 .i6_i7 = i_bits.i6_i7,
296 .rs = 0,
297 .i3_i5 = i_bits.i3_i5,
298 .high_opcode = 0b000,
299 };
300 (that->*execute_instruction_func)(o_bits.parcel | opcode, offset);
301 }
302 }
303
TEST_F(Riscv64InterpreterTest,CompressedLoadAndStores)304 TEST_F(Riscv64InterpreterTest, CompressedLoadAndStores) {
305 // c.Fld
306 TestCompressedLoadOrStore<
307 0b001'000'000'00'000'00,
308 &Riscv64InterpreterTest::InterpretCompressedLoad<RegisterType::kFpReg, kDataToLoad>>(this);
309 // c.Ld
310 TestCompressedLoadOrStore<
311 0b011'000'000'00'000'00,
312 &Riscv64InterpreterTest::InterpretCompressedLoad<RegisterType::kReg, kDataToLoad>>(this);
313 // c.Fsd
314 TestCompressedLoadOrStore<
315 0b101'000'000'00'000'00,
316 &Riscv64InterpreterTest::InterpretCompressedStore<RegisterType::kFpReg, kDataToLoad>>(this);
317 // c.Sd
318 TestCompressedLoadOrStore<
319 0b111'000'000'00'000'00,
320 &Riscv64InterpreterTest::InterpretCompressedStore<RegisterType::kReg, kDataToLoad>>(this);
321 }
322
TEST_F(Riscv64InterpreterTest,CAddi)323 TEST_F(Riscv64InterpreterTest, CAddi) {
324 union {
325 int8_t offset;
326 struct {
327 uint8_t i4_i0 : 5;
328 uint8_t i5 : 1;
329 } i_bits;
330 };
331 for (offset = int8_t{-32}; offset < int8_t{31}; offset++) {
332 union {
333 int16_t parcel;
334 struct {
335 uint8_t low_opcode : 2;
336 uint8_t i4_i0 : 5;
337 uint8_t r : 5;
338 uint8_t i5 : 1;
339 uint8_t high_opcode : 3;
340 } __attribute__((__packed__));
341 } o_bits = {
342 .low_opcode = 0b01,
343 .i4_i0 = i_bits.i4_i0,
344 .r = 2,
345 .i5 = i_bits.i5,
346 .high_opcode = 0b000,
347 };
348 InterpretCAddi(o_bits.parcel, offset);
349 }
350 }
351
TEST_F(Riscv64InterpreterTest,CAddi4spn)352 TEST_F(Riscv64InterpreterTest, CAddi4spn) {
353 union {
354 int16_t offset;
355 struct {
356 uint8_t : 2;
357 uint8_t i2 : 1;
358 uint8_t i3 : 1;
359 uint8_t i4 : 1;
360 uint8_t i5 : 1;
361 uint8_t i6 : 1;
362 uint8_t i7 : 1;
363 uint8_t i8 : 1;
364 uint8_t i9 : 1;
365 } i_bits;
366 };
367 for (offset = int16_t{4}; offset < int16_t{1024}; offset += 4) {
368 union {
369 int16_t parcel;
370 struct {
371 uint8_t low_opcode : 2;
372 uint8_t rd : 3;
373 uint8_t i3 : 1;
374 uint8_t i2 : 1;
375 uint8_t i6 : 1;
376 uint8_t i7 : 1;
377 uint8_t i8 : 1;
378 uint8_t i9 : 1;
379 uint8_t i4 : 1;
380 uint8_t i5 : 1;
381 uint8_t high_opcode : 3;
382 };
383 } o_bits = {
384 .low_opcode = 0b00,
385 .rd = 1,
386 .i3 = i_bits.i3,
387 .i2 = i_bits.i2,
388 .i6 = i_bits.i6,
389 .i7 = i_bits.i7,
390 .i8 = i_bits.i8,
391 .i9 = i_bits.i9,
392 .i4 = i_bits.i4,
393 .i5 = i_bits.i5,
394 .high_opcode = 0b000,
395 };
396 InterpretCAddi4spn(o_bits.parcel, offset);
397 }
398 }
399
TEST_F(Riscv64InterpreterTest,CJ)400 TEST_F(Riscv64InterpreterTest, CJ) {
401 union {
402 int16_t offset;
403 struct {
404 uint8_t : 1;
405 uint8_t i1 : 1;
406 uint8_t i2 : 1;
407 uint8_t i3 : 1;
408 uint8_t i4 : 1;
409 uint8_t i5 : 1;
410 uint8_t i6 : 1;
411 uint8_t i7 : 1;
412 uint8_t i8 : 1;
413 uint8_t i9 : 1;
414 uint8_t i10 : 1;
415 uint8_t i11 : 1;
416 } i_bits;
417 };
418 for (offset = int16_t{-2048}; offset < int16_t{2048}; offset += 2) {
419 union {
420 int16_t parcel;
421 struct {
422 uint8_t low_opcode : 2;
423 uint8_t i5 : 1;
424 uint8_t i1 : 1;
425 uint8_t i2 : 1;
426 uint8_t i3 : 1;
427 uint8_t i7 : 1;
428 uint8_t i6 : 1;
429 uint8_t i10 : 1;
430 uint8_t i8 : 1;
431 uint8_t i9 : 1;
432 uint8_t i4 : 1;
433 uint8_t i11 : 1;
434 uint8_t high_opcode : 3;
435 };
436 } o_bits = {
437 .low_opcode = 0b01,
438 .i5 = i_bits.i5,
439 .i1 = i_bits.i1,
440 .i2 = i_bits.i2,
441 .i3 = i_bits.i3,
442 .i7 = i_bits.i7,
443 .i6 = i_bits.i6,
444 .i10 = i_bits.i10,
445 .i8 = i_bits.i8,
446 .i9 = i_bits.i9,
447 .i4 = i_bits.i4,
448 .i11 = i_bits.i11,
449 .high_opcode = 0b101,
450 };
451 InterpretCJ(o_bits.parcel, offset);
452 }
453 }
454
TEST_F(Riscv64InterpreterTest,CsrInstrctuion)455 TEST_F(Riscv64InterpreterTest, CsrInstrctuion) {
456 ScopedRoundingMode scoped_rounding_mode;
457 // Csrrw x2, frm, 2
458 InterpretCsr(0x00215173, 2);
459 // Csrrsi x2, frm, 2
460 InterpretCsr(0x00216173, 3);
461 // Csrrci x2, frm, 1
462 InterpretCsr(0x0020f173, 0);
463 }
464
TEST_F(Riscv64InterpreterTest,FenceInstructions)465 TEST_F(Riscv64InterpreterTest, FenceInstructions) {
466 // Fence
467 InterpretFence(0x0ff0000f);
468 // FenceTso
469 InterpretFence(0x8330000f);
470 // FenceI
471 InterpretFence(0x0000100f);
472 }
473
TEST_F(Riscv64InterpreterTest,OpInstructions)474 TEST_F(Riscv64InterpreterTest, OpInstructions) {
475 // Add
476 InterpretOp(0x003100b3, {{19, 23, 42}});
477 // Sub
478 InterpretOp(0x403100b3, {{42, 23, 19}});
479 // And
480 InterpretOp(0x003170b3, {{0b0101, 0b0011, 0b0001}});
481 // Or
482 InterpretOp(0x003160b3, {{0b0101, 0b0011, 0b0111}});
483 // Xor
484 InterpretOp(0x003140b3, {{0b0101, 0b0011, 0b0110}});
485 // Sll
486 InterpretOp(0x003110b3, {{0b1010, 3, 0b1010'000}});
487 // Srl
488 InterpretOp(0x003150b3, {{0xf000'0000'0000'0000ULL, 12, 0x000f'0000'0000'0000ULL}});
489 // Sra
490 InterpretOp(0x403150b3, {{0xf000'0000'0000'0000ULL, 12, 0xffff'0000'0000'0000ULL}});
491 // Slt
492 InterpretOp(0x003120b3, {
493 {19, 23, 1},
494 {23, 19, 0},
495 {~0ULL, 0, 1},
496 });
497 // Sltu
498 InterpretOp(0x003130b3, {
499 {19, 23, 1},
500 {23, 19, 0},
501 {~0ULL, 0, 0},
502 });
503
504 // Mul
505 InterpretOp(0x023100b3, {{0x9999'9999'9999'9999, 0x9999'9999'9999'9999, 0x0a3d'70a3'd70a'3d71}});
506 // Mulh
507 InterpretOp(0x23110b3, {{0x9999'9999'9999'9999, 0x9999'9999'9999'9999, 0x28f5'c28f'5c28'f5c3}});
508 // Mulhsu
509 InterpretOp(0x23120b3, {{0x9999'9999'9999'9999, 0x9999'9999'9999'9999, 0xc28f'5c28'f5c2'8f5c}});
510 // Mulhu
511 InterpretOp(0x23130b3, {{0x9999'9999'9999'9999, 0x9999'9999'9999'9999, 0x5c28'f5c2'8f5c'28f5}});
512 // Div
513 InterpretOp(0x23140b3, {{0x9999'9999'9999'9999, 0x3333, 0xfffd'fffd'fffd'fffe}});
514 // Div
515 InterpretOp(0x23150b3, {{0x9999'9999'9999'9999, 0x3333, 0x0003'0003'0003'0003}});
516 // Rem
517 InterpretOp(0x23160b3, {{0x9999'9999'9999'9999, 0x3333, 0xffff'ffff'ffff'ffff}});
518 // Remu
519 InterpretOp(0x23170b3, {{0x9999'9999'9999'9999, 0x3333, 0}});
520 }
521
TEST_F(Riscv64InterpreterTest,Op32Instructions)522 TEST_F(Riscv64InterpreterTest, Op32Instructions) {
523 // Addw
524 InterpretOp(0x003100bb, {{19, 23, 42}});
525 // Subw
526 InterpretOp(0x403100bb, {{42, 23, 19}});
527 // Sllw
528 InterpretOp(0x003110bb, {{0b1010, 3, 0b1010'000}});
529 // Srlw
530 InterpretOp(0x003150bb, {{0x0000'0000'f000'0000ULL, 12, 0x0000'0000'000f'0000ULL}});
531 // Sraw
532 InterpretOp(0x403150bb, {{0x0000'0000'f000'0000ULL, 12, 0xffff'ffff'ffff'0000ULL}});
533 // Mulw
534 InterpretOp(0x023100bb, {{0x9999'9999'9999'9999, 0x9999'9999'9999'9999, 0xffff'ffff'd70a'3d71}});
535 // Divw
536 InterpretOp(0x23140bb, {{0x9999'9999'9999'9999, 0x3333, 0xffff'ffff'fffd'fffe}});
537 // Divuw
538 InterpretOp(0x23150bb, {{0x9999'9999'9999'9999, 0x3333, 0x0000'0000'0003'0003}});
539 // Remw
540 InterpretOp(0x23160bb, {{0x9999'9999'9999'9999, 0x3333, 0xffff'ffff'ffff'ffff}});
541 // Remuw
542 InterpretOp(0x23170bb, {{0x9999'9999'9999'9999, 0x3333, 0}});
543 }
544
TEST_F(Riscv64InterpreterTest,AmoInstructions)545 TEST_F(Riscv64InterpreterTest, AmoInstructions) {
546 // Verifying that all aq and rl combinations work for Amoswap, but only test relaxed one for most
547 // other instructions for brevity.
548
549 // AmoswaoW/AmoswaoD
550 InterpretAmo(0x083120af, 0x083130af, 0xaaaa'bbbb'cccc'ddddULL);
551
552 // AmoswapWAq/AmoswapDAq
553 InterpretAmo(0x0c3120af, 0x0c3130af, 0xaaaa'bbbb'cccc'ddddULL);
554
555 // AmoswapWRl/AmoswapDRl
556 InterpretAmo(0x0a3120af, 0x0a3130af, 0xaaaa'bbbb'cccc'ddddULL);
557
558 // AmoswapWAqrl/AmoswapDAqrl
559 InterpretAmo(0x0e3120af, 0x0e3130af, 0xaaaa'bbbb'cccc'ddddULL);
560
561 // AmoaddW/AmoaddD
562 InterpretAmo(0x003120af, 0x003130af, 0xaaaa'aaaa'aaaa'aaa9);
563
564 // AmoxorW/AmoxorD
565 InterpretAmo(0x203120af, 0x203130af, 0x5555'5555'1111'1111);
566
567 // AmoandW/AmoandD
568 InterpretAmo(0x603120af, 0x603130af, 0xaaaa'aaaa'cccc'cccc);
569
570 // AmoorW/AmoorD
571 InterpretAmo(0x403120af, 0x403130af, 0xffff'ffff'dddd'dddd);
572
573 // AmominW/AmominD
574 InterpretAmo(0x803120af, 0x803130af, 0xaaaa'bbbb'cccc'ddddULL);
575
576 // AmomaxW/AmomaxD
577 InterpretAmo(0xa03120af, 0xa03130af, 0xffff'eeee'dddd'ccccULL);
578
579 // AmominuW/AmominuD
580 InterpretAmo(0xc03120af, 0xc03130af, 0xaaaa'bbbb'cccc'ddddULL);
581
582 // AmomaxuW/AmomaxuD
583 InterpretAmo(0xe03120af, 0xe03130af, 0xffff'eeee'dddd'ccccULL);
584 }
585
TEST_F(Riscv64InterpreterTest,UpperImmArgs)586 TEST_F(Riscv64InterpreterTest, UpperImmArgs) {
587 // Lui
588 InterpretLui(0xfedcb0b7, 0xffff'ffff'fedc'b000);
589 // Auipc
590 InterpretAuipc(0xfedcb097, 0xffff'ffff'fedc'b000);
591 }
592
TEST_F(Riscv64InterpreterTest,OpImmInstructions)593 TEST_F(Riscv64InterpreterTest, OpImmInstructions) {
594 // Addi
595 InterpretOpImm(0x00010093, {{19, 23, 42}});
596 // Slli
597 InterpretOpImm(0x00011093, {{0b1010, 3, 0b1010'000}});
598 // Slti
599 InterpretOpImm(0x00012093, {
600 {19, 23, 1},
601 {23, 19, 0},
602 {~0ULL, 0, 1},
603 });
604 // Sltiu
605 InterpretOpImm(0x00013093, {
606 {19, 23, 1},
607 {23, 19, 0},
608 {~0ULL, 0, 0},
609 });
610 // Xori
611 InterpretOpImm(0x00014093, {{0b0101, 0b0011, 0b0110}});
612 // Srli
613 InterpretOpImm(0x00015093, {{0xf000'0000'0000'0000ULL, 12, 0x000f'0000'0000'0000ULL}});
614 // Srai
615 InterpretOpImm(0x40015093, {{0xf000'0000'0000'0000ULL, 12, 0xffff'0000'0000'0000ULL}});
616 // Ori
617 InterpretOpImm(0x00016093, {{0b0101, 0b0011, 0b0111}});
618 // Andi
619 InterpretOpImm(0x00017093, {{0b0101, 0b0011, 0b0001}});
620 }
621
TEST_F(Riscv64InterpreterTest,OpImm32Instructions)622 TEST_F(Riscv64InterpreterTest, OpImm32Instructions) {
623 // Addiw
624 InterpretOpImm(0x0001009b, {{19, 23, 42}});
625 // Slliw
626 InterpretOpImm(0x0001109b, {{0b1010, 3, 0b1010'000}});
627 // Srliw
628 InterpretOpImm(0x0001509b, {{0x0000'0000'f000'0000ULL, 12, 0x0000'0000'000f'0000ULL}});
629 // Sraiw
630 InterpretOpImm(0x4001509b, {{0x0000'0000'f000'0000ULL, 12, 0xffff'ffff'ffff'0000ULL}});
631 }
632
TEST_F(Riscv64InterpreterTest,OpFpInstructions)633 TEST_F(Riscv64InterpreterTest, OpFpInstructions) {
634 // FAdd.S
635 InterpretOpFp(0x003100d3,
636 {{bit_cast<uint32_t>(1.0f) | 0xffff'ffff'0000'0000,
637 bit_cast<uint32_t>(2.0f) | 0xffff'ffff'0000'0000,
638 bit_cast<uint32_t>(3.0f) | 0xffff'ffff'0000'0000}});
639 // FAdd.D
640 InterpretOpFp(0x023100d3,
641 {{bit_cast<uint64_t>(1.0), bit_cast<uint64_t>(2.0), bit_cast<uint64_t>(3.0)}});
642 }
643
TEST_F(Riscv64InterpreterTest,RoundingModeTest)644 TEST_F(Riscv64InterpreterTest, RoundingModeTest) {
645 // FAdd.S
646 InterpretOpFp(0x003100d3,
647 // Test RNE
648 {{bit_cast<uint32_t>(1.0000001f) | 0xffff'ffff'0000'0000,
649 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
650 bit_cast<uint32_t>(1.0000002f) | 0xffff'ffff'0000'0000},
651 {bit_cast<uint32_t>(1.0000002f) | 0xffff'ffff'0000'0000,
652 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
653 bit_cast<uint32_t>(1.0000002f) | 0xffff'ffff'0000'0000},
654 {bit_cast<uint32_t>(1.0000004f) | 0xffff'ffff'0000'0000,
655 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
656 bit_cast<uint32_t>(1.0000005f) | 0xffff'ffff'0000'0000},
657 {bit_cast<uint32_t>(-1.0000001f) | 0xffff'ffff'0000'0000,
658 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
659 bit_cast<uint32_t>(-1.0000002f) | 0xffff'ffff'0000'0000},
660 {bit_cast<uint32_t>(-1.0000002f) | 0xffff'ffff'0000'0000,
661 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
662 bit_cast<uint32_t>(-1.0000002f) | 0xffff'ffff'0000'0000},
663 {bit_cast<uint32_t>(-1.0000004f) | 0xffff'ffff'0000'0000,
664 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
665 bit_cast<uint32_t>(-1.0000005f) | 0xffff'ffff'0000'0000}});
666 // FAdd.S
667 InterpretOpFp(0x003110d3,
668 // Test RTZ
669 {{bit_cast<uint32_t>(1.0000001f) | 0xffff'ffff'0000'0000,
670 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
671 bit_cast<uint32_t>(1.0000001f) | 0xffff'ffff'0000'0000},
672 {bit_cast<uint32_t>(1.0000002f) | 0xffff'ffff'0000'0000,
673 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
674 bit_cast<uint32_t>(1.0000002f) | 0xffff'ffff'0000'0000},
675 {bit_cast<uint32_t>(1.0000004f) | 0xffff'ffff'0000'0000,
676 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
677 bit_cast<uint32_t>(1.0000004f) | 0xffff'ffff'0000'0000},
678 {bit_cast<uint32_t>(-1.0000001f) | 0xffff'ffff'0000'0000,
679 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
680 bit_cast<uint32_t>(-1.0000001f) | 0xffff'ffff'0000'0000},
681 {bit_cast<uint32_t>(-1.0000002f) | 0xffff'ffff'0000'0000,
682 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
683 bit_cast<uint32_t>(-1.0000002f) | 0xffff'ffff'0000'0000},
684 {bit_cast<uint32_t>(-1.0000004f) | 0xffff'ffff'0000'0000,
685 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
686 bit_cast<uint32_t>(-1.0000004f) | 0xffff'ffff'0000'0000}});
687 // FAdd.S
688 InterpretOpFp(0x003120d3,
689 // Test RDN
690 {{bit_cast<uint32_t>(1.0000001f) | 0xffff'ffff'0000'0000,
691 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
692 bit_cast<uint32_t>(1.0000001f) | 0xffff'ffff'0000'0000},
693 {bit_cast<uint32_t>(1.0000002f) | 0xffff'ffff'0000'0000,
694 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
695 bit_cast<uint32_t>(1.0000002f) | 0xffff'ffff'0000'0000},
696 {bit_cast<uint32_t>(1.0000004f) | 0xffff'ffff'0000'0000,
697 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
698 bit_cast<uint32_t>(1.0000004f) | 0xffff'ffff'0000'0000},
699 {bit_cast<uint32_t>(-1.0000001f) | 0xffff'ffff'0000'0000,
700 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
701 bit_cast<uint32_t>(-1.0000002f) | 0xffff'ffff'0000'0000},
702 {bit_cast<uint32_t>(-1.0000002f) | 0xffff'ffff'0000'0000,
703 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
704 bit_cast<uint32_t>(-1.0000004f) | 0xffff'ffff'0000'0000},
705 {bit_cast<uint32_t>(-1.0000004f) | 0xffff'ffff'0000'0000,
706 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
707 bit_cast<uint32_t>(-1.0000005f) | 0xffff'ffff'0000'0000}});
708 // FAdd.S
709 InterpretOpFp(0x003130d3,
710 // Test RUP
711 {{bit_cast<uint32_t>(1.0000001f) | 0xffff'ffff'0000'0000,
712 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
713 bit_cast<uint32_t>(1.0000002f) | 0xffff'ffff'0000'0000},
714 {bit_cast<uint32_t>(1.0000002f) | 0xffff'ffff'0000'0000,
715 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
716 bit_cast<uint32_t>(1.0000004f) | 0xffff'ffff'0000'0000},
717 {bit_cast<uint32_t>(1.0000004f) | 0xffff'ffff'0000'0000,
718 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
719 bit_cast<uint32_t>(1.0000005f) | 0xffff'ffff'0000'0000},
720 {bit_cast<uint32_t>(-1.0000001f) | 0xffff'ffff'0000'0000,
721 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
722 bit_cast<uint32_t>(-1.0000001f) | 0xffff'ffff'0000'0000},
723 {bit_cast<uint32_t>(-1.0000002f) | 0xffff'ffff'0000'0000,
724 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
725 bit_cast<uint32_t>(-1.0000002f) | 0xffff'ffff'0000'0000},
726 {bit_cast<uint32_t>(-1.0000004f) | 0xffff'ffff'0000'0000,
727 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
728 bit_cast<uint32_t>(-1.0000004f) | 0xffff'ffff'0000'0000}});
729 // FAdd.S
730 InterpretOpFp(0x003140d3,
731 // Test RMM
732 {{bit_cast<uint32_t>(1.0000001f) | 0xffff'ffff'0000'0000,
733 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
734 bit_cast<uint32_t>(1.0000002f) | 0xffff'ffff'0000'0000},
735 {bit_cast<uint32_t>(1.0000002f) | 0xffff'ffff'0000'0000,
736 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
737 bit_cast<uint32_t>(1.0000004f) | 0xffff'ffff'0000'0000},
738 {bit_cast<uint32_t>(1.0000004f) | 0xffff'ffff'0000'0000,
739 bit_cast<uint32_t>(0.000000059604645f) | 0xffff'ffff'0000'0000,
740 bit_cast<uint32_t>(1.0000005f) | 0xffff'ffff'0000'0000},
741 {bit_cast<uint32_t>(-1.0000001f) | 0xffff'ffff'0000'0000,
742 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
743 bit_cast<uint32_t>(-1.0000002f) | 0xffff'ffff'0000'0000},
744 {bit_cast<uint32_t>(-1.0000002f) | 0xffff'ffff'0000'0000,
745 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
746 bit_cast<uint32_t>(-1.0000004f) | 0xffff'ffff'0000'0000},
747 {bit_cast<uint32_t>(-1.0000004f) | 0xffff'ffff'0000'0000,
748 bit_cast<uint32_t>(-0.000000059604645f) | 0xffff'ffff'0000'0000,
749 bit_cast<uint32_t>(-1.0000005f) | 0xffff'ffff'0000'0000}});
750
751 // FAdd.D
752 InterpretOpFp(0x023100d3,
753 // Test RNE
754 {{bit_cast<uint64_t>(1.0000000000000002),
755 bit_cast<uint64_t>(0.00000000000000011102230246251565),
756 bit_cast<uint64_t>(1.0000000000000004)},
757 {bit_cast<uint64_t>(1.0000000000000004),
758 bit_cast<uint64_t>(0.00000000000000011102230246251565),
759 bit_cast<uint64_t>(1.0000000000000004)},
760 {bit_cast<uint64_t>(1.0000000000000007),
761 bit_cast<uint64_t>(0.00000000000000011102230246251565),
762 bit_cast<uint64_t>(1.0000000000000009)},
763 {bit_cast<uint64_t>(-1.0000000000000002),
764 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
765 bit_cast<uint64_t>(-1.0000000000000004)},
766 {bit_cast<uint64_t>(-1.0000000000000004),
767 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
768 bit_cast<uint64_t>(-1.0000000000000004)},
769 {bit_cast<uint64_t>(-1.0000000000000007),
770 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
771 bit_cast<uint64_t>(-1.0000000000000009)}});
772 // FAdd.D
773 InterpretOpFp(0x023110d3,
774 // Test RTZ
775 {{bit_cast<uint64_t>(1.0000000000000002),
776 bit_cast<uint64_t>(0.00000000000000011102230246251565),
777 bit_cast<uint64_t>(1.0000000000000002)},
778 {bit_cast<uint64_t>(1.0000000000000004),
779 bit_cast<uint64_t>(0.00000000000000011102230246251565),
780 bit_cast<uint64_t>(1.0000000000000004)},
781 {bit_cast<uint64_t>(1.0000000000000007),
782 bit_cast<uint64_t>(0.00000000000000011102230246251565),
783 bit_cast<uint64_t>(1.0000000000000007)},
784 {bit_cast<uint64_t>(-1.0000000000000002),
785 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
786 bit_cast<uint64_t>(-1.0000000000000002)},
787 {bit_cast<uint64_t>(-1.0000000000000004),
788 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
789 bit_cast<uint64_t>(-1.0000000000000004)},
790 {bit_cast<uint64_t>(-1.0000000000000007),
791 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
792 bit_cast<uint64_t>(-1.0000000000000007)}});
793 // FAdd.D
794 InterpretOpFp(0x023120d3,
795 // Test RDN
796 {{bit_cast<uint64_t>(1.0000000000000002),
797 bit_cast<uint64_t>(0.00000000000000011102230246251565),
798 bit_cast<uint64_t>(1.0000000000000002)},
799 {bit_cast<uint64_t>(1.0000000000000004),
800 bit_cast<uint64_t>(0.00000000000000011102230246251565),
801 bit_cast<uint64_t>(1.0000000000000004)},
802 {bit_cast<uint64_t>(1.0000000000000007),
803 bit_cast<uint64_t>(0.00000000000000011102230246251565),
804 bit_cast<uint64_t>(1.0000000000000007)},
805 {bit_cast<uint64_t>(-1.0000000000000002),
806 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
807 bit_cast<uint64_t>(-1.0000000000000004)},
808 {bit_cast<uint64_t>(-1.0000000000000004),
809 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
810 bit_cast<uint64_t>(-1.0000000000000007)},
811 {bit_cast<uint64_t>(-1.0000000000000007),
812 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
813 bit_cast<uint64_t>(-1.0000000000000009)}});
814 // FAdd.D
815 InterpretOpFp(0x023130d3,
816 // Test RUP
817 {{bit_cast<uint64_t>(1.0000000000000002),
818 bit_cast<uint64_t>(0.00000000000000011102230246251565),
819 bit_cast<uint64_t>(1.0000000000000004)},
820 {bit_cast<uint64_t>(1.0000000000000004),
821 bit_cast<uint64_t>(0.00000000000000011102230246251565),
822 bit_cast<uint64_t>(1.0000000000000007)},
823 {bit_cast<uint64_t>(1.0000000000000007),
824 bit_cast<uint64_t>(0.00000000000000011102230246251565),
825 bit_cast<uint64_t>(1.0000000000000009)},
826 {bit_cast<uint64_t>(-1.0000000000000002),
827 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
828 bit_cast<uint64_t>(-1.0000000000000002)},
829 {bit_cast<uint64_t>(-1.0000000000000004),
830 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
831 bit_cast<uint64_t>(-1.0000000000000004)},
832 {bit_cast<uint64_t>(-1.0000000000000007),
833 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
834 bit_cast<uint64_t>(-1.0000000000000007)}});
835 // FAdd.D
836 InterpretOpFp(0x023140d3,
837 // Test RMM
838 {{bit_cast<uint64_t>(1.0000000000000002),
839 bit_cast<uint64_t>(0.00000000000000011102230246251565),
840 bit_cast<uint64_t>(1.0000000000000004)},
841 {bit_cast<uint64_t>(1.0000000000000004),
842 bit_cast<uint64_t>(0.00000000000000011102230246251565),
843 bit_cast<uint64_t>(1.0000000000000007)},
844 {bit_cast<uint64_t>(1.0000000000000007),
845 bit_cast<uint64_t>(0.00000000000000011102230246251565),
846 bit_cast<uint64_t>(1.0000000000000009)},
847 {bit_cast<uint64_t>(-1.0000000000000002),
848 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
849 bit_cast<uint64_t>(-1.0000000000000004)},
850 {bit_cast<uint64_t>(-1.0000000000000004),
851 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
852 bit_cast<uint64_t>(-1.0000000000000007)},
853 {bit_cast<uint64_t>(-1.0000000000000007),
854 bit_cast<uint64_t>(-0.00000000000000011102230246251565),
855 bit_cast<uint64_t>(-1.0000000000000009)}});
856 }
857
TEST_F(Riscv64InterpreterTest,LoadInstructions)858 TEST_F(Riscv64InterpreterTest, LoadInstructions) {
859 // Offset is always 8.
860 // Lbu
861 InterpretLoad(0x00814083, kDataToLoad & 0xffULL);
862 // Lhu
863 InterpretLoad(0x00815083, kDataToLoad & 0xffffULL);
864 // Lwu
865 InterpretLoad(0x00816083, kDataToLoad & 0xffff'ffffULL);
866 // Ldu
867 InterpretLoad(0x00813083, kDataToLoad);
868 // Lb
869 InterpretLoad(0x00810083, int64_t{int8_t(kDataToLoad)});
870 // Lh
871 InterpretLoad(0x00811083, int64_t{int16_t(kDataToLoad)});
872 // Lw
873 InterpretLoad(0x00812083, int64_t{int32_t(kDataToLoad)});
874 }
875
TEST_F(Riscv64InterpreterTest,LoadFpInstructions)876 TEST_F(Riscv64InterpreterTest, LoadFpInstructions) {
877 // Offset is always 8.
878 // Flw
879 InterpretLoadFp(0x00812087, kDataToLoad | 0xffffffff00000000ULL);
880 // Fld
881 InterpretLoadFp(0x00813087, kDataToLoad);
882 }
883
TEST_F(Riscv64InterpreterTest,StoreInstructions)884 TEST_F(Riscv64InterpreterTest, StoreInstructions) {
885 // Offset is always 8.
886 // Sb
887 InterpretStore(0x00208423, kDataToStore & 0xffULL);
888 // Sh
889 InterpretStore(0x00209423, kDataToStore & 0xffffULL);
890 // Sw
891 InterpretStore(0x0020a423, kDataToStore & 0xffff'ffffULL);
892 // Sd
893 InterpretStore(0x0020b423, kDataToStore);
894 }
895
TEST_F(Riscv64InterpreterTest,StoreFpInstructions)896 TEST_F(Riscv64InterpreterTest, StoreFpInstructions) {
897 // Offset is always 8.
898 // Fsw
899 InterpretStoreFp(0x0020a427, kDataToStore & 0xffff'ffffULL);
900 // Fsd
901 InterpretStoreFp(0x0020b427, kDataToStore);
902 }
903
TEST_F(Riscv64InterpreterTest,BranchInstructions)904 TEST_F(Riscv64InterpreterTest, BranchInstructions) {
905 // Beq
906 InterpretBranch(0x00208463, {
907 {42, 42, 8},
908 {41, 42, 4},
909 {42, 41, 4},
910 });
911 // Bne
912 InterpretBranch(0x00209463, {
913 {42, 42, 4},
914 {41, 42, 8},
915 {42, 41, 8},
916 });
917 // Blt
918 InterpretBranch(0x0020c463, {
919 {41, 42, 8},
920 {42, 42, 4},
921 {42, 41, 4},
922 {0xf000'0000'0000'0000ULL, 42, 8},
923 {42, 0xf000'0000'0000'0000ULL, 4},
924 });
925 // Bltu
926 InterpretBranch(0x0020e463, {
927 {41, 42, 8},
928 {42, 42, 4},
929 {42, 41, 4},
930 {0xf000'0000'0000'0000ULL, 42, 4},
931 {42, 0xf000'0000'0000'0000ULL, 8},
932 });
933 // Bge
934 InterpretBranch(0x0020d463, {
935 {42, 41, 8},
936 {42, 42, 8},
937 {41, 42, 4},
938 {0xf000'0000'0000'0000ULL, 42, 4},
939 {42, 0xf000'0000'0000'0000ULL, 8},
940 });
941 // Bgeu
942 InterpretBranch(0x0020f463, {
943 {42, 41, 8},
944 {42, 42, 8},
945 {41, 42, 4},
946 {0xf000'0000'0000'0000ULL, 42, 8},
947 {42, 0xf000'0000'0000'0000ULL, 4},
948 });
949 // Beq with negative offset.
950 InterpretBranch(0xfe208ee3, {
951 {42, 42, -4},
952 });
953 }
954
TEST_F(Riscv64InterpreterTest,JumpAndLinkInstructions)955 TEST_F(Riscv64InterpreterTest, JumpAndLinkInstructions) {
956 // Jal
957 InterpretJumpAndLink(0x008000ef, 8);
958 // Jal with negative offset.
959 InterpretJumpAndLink(0xffdff0ef, -4);
960 }
961
TEST_F(Riscv64InterpreterTest,JumpAndLinkRegisterInstructions)962 TEST_F(Riscv64InterpreterTest, JumpAndLinkRegisterInstructions) {
963 // Jalr offset=4.
964 InterpretJumpAndLinkRegister(0x004100e7, 38, 42);
965 // Jalr offset=-4.
966 InterpretJumpAndLinkRegister(0xffc100e7, 42, 38);
967 // Jalr offset=5 - must properly align the target to even.
968 InterpretJumpAndLinkRegister(0x005100e7, 38, 42);
969 }
970
TEST_F(Riscv64InterpreterTest,SyscallWrite)971 TEST_F(Riscv64InterpreterTest, SyscallWrite) {
972 const char message[] = "Hello";
973 // Prepare a pipe to write to.
974 int pipefd[2];
975 ASSERT_EQ(0, pipe(pipefd));
976
977 // SYS_write
978 SetXReg<17>(state_.cpu, 0x40);
979 // File descriptor
980 SetXReg<10>(state_.cpu, pipefd[1]);
981 // String
982 SetXReg<11>(state_.cpu, bit_cast<uint64_t>(&message[0]));
983 // Size
984 SetXReg<12>(state_.cpu, sizeof(message));
985
986 uint32_t insn_bytes = 0x00000073;
987 state_.cpu.insn_addr = ToGuestAddr(&insn_bytes);
988 InterpretInsn(&state_);
989
990 // Check number of bytes written.
991 EXPECT_EQ(GetXReg<10>(state_.cpu), sizeof(message));
992
993 // Check the message was written to the pipe.
994 char buf[sizeof(message)] = {};
995 read(pipefd[0], &buf, sizeof(buf));
996 EXPECT_EQ(0, strcmp(message, buf));
997 close(pipefd[0]);
998 close(pipefd[1]);
999 }
1000
1001 } // namespace
1002
1003 } // namespace berberis
1004