rtests.c (33640B)
1 #include <stdint.h> 2 #include <inttypes.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <stdint.h> 7 8 #include "exec.h" 9 #include "mem.h" 10 #include "disasm.h" 11 #include "test.h" 12 13 /**** TESTS ****/ 14 15 test_t tests[] = { 16 { 17 .name = "upper immediate instructions", 18 .program = { 19 0xaaaaa3b7, // lui x7, 0xaaaaa -> rd:aaaaa000 20 0x00001397, // auipc x7 0x1 -> rd 1004 21 0x00000013, // nop 22 0x0ff0000f, // fence 23 0x00100073, // ebreak 24 }, 25 .program_len = 5, 26 .exp = { 27 .x[7] = 0x1004, 28 .x_check_mask = (UINT32_C(1) << 7), 29 .pc = 16, 30 .cause = TRAP_EBREAK, 31 }, 32 }, 33 { 34 .name = "negative I-type immediates", 35 .program = { 36 0xfff00093, // addi x1, x0, -1 37 0xfff04113, // xori x2, x0, -1 38 0xfff06193, // ori x3, x0, -1 39 0xfff17213, // andi x4, x2, -1 40 0xfff02293, // slti x5, x0, -1 41 0xfff03313, // sltiu x6, x0, -1 42 0x00100073, // ebreak 43 }, 44 .program_len = 7, 45 .exp = { 46 .x = { 47 [1] = 0xffffffff, 48 [2] = 0xffffffff, 49 [3] = 0xffffffff, 50 [4] = 0xffffffff, 51 [5] = 0x0, 52 [6] = 0x1, 53 }, 54 .x_check_mask = (UINT32_C(1) << 6) | 55 (UINT32_C(1) << 5) | 56 (UINT32_C(1) << 4) | 57 (UINT32_C(1) << 3) | 58 (UINT32_C(1) << 2) | 59 (UINT32_C(1) << 1), 60 .pc = 0x18, 61 .cause = TRAP_EBREAK, 62 } 63 }, 64 { 65 .name = "I-type immediates", 66 .program = { 67 0x00700513, // addi x10, x0, 7 68 0x00451513, // slli x10, x10, 4 69 0x00d50513, // addi x10, x10, 13 70 0x05554513, // xori x10, x10, 0x55 71 0xff750513, // addi x10, x10, -9 72 0x00100073 // ebreak 73 }, 74 .program_len = 6, 75 .exp = { 76 .x[10] = 0x0000001f, 77 .x_check_mask = (UINT32_C(1) << 10), 78 .pc = 0x14, 79 .cause = TRAP_EBREAK, 80 } 81 }, 82 { 83 .name = "branches, loads and stores", 84 .program = { 85 0x00a00093, //li ra,10 86 0x00000113, //li sp,0 87 0x00100193, //li gp,1 88 0x00310133, //add sp,sp,gp 89 0x00118193, //addi gp,gp,1 90 0xfff08093, //addi ra,ra,-1 91 0xfe009ae3, //bnez ra,c <loop> 92 0x10000513, //li a0,256 93 0x00252023, //sw sp,0(a0) 94 0x00350223, //sb gp,4(a0) 95 0x00052203, //lw tp,0(a0) 96 0x00450283, //lb t0,4(a0) 97 0x00121313, //slli t1,tp,0x1 98 0x004343b3, //xor t2,t1,tp 99 0x03822413, //slti s0,tp,56 100 0xfff23493, //sltiu s1,tp,-1 101 0x00c005ef, //jal a1,4c <subroutine> 102 0x00c52423, //sw a2,8(a0) 103 0x00100073, //ebreak 104 0x00720613, //addi a2,tp,7 # 7 <_start+0x7> 105 0x00058067 //jr a1 106 }, 107 .program_len = 21, 108 .exp = { 109 .x = { 110 [0] = 0x00000000, 111 [1] = 0x00000000, 112 [2] = 0x00000037, 113 [3] = 0x0000000b, 114 [4] = 0x00000037, 115 [5] = 0x0000000b, 116 [6] = 0x0000006e, 117 [7] = 0x00000059, 118 [8] = 0x00000001, 119 [9] = 0x00000001, 120 [10] = 0x00000100, 121 [11] = 0x00000044, 122 [12] = 0x0000003e, 123 124 }, 125 .x_check_mask = ((UINT32_C(1) << 12) | 126 (UINT32_C(1) << 11) | 127 (UINT32_C(1) << 10) | 128 (UINT32_C(1) << 9) | 129 (UINT32_C(1) << 8) | 130 (UINT32_C(1) << 7) | 131 (UINT32_C(1) << 6) | 132 (UINT32_C(1) << 5) | 133 (UINT32_C(1) << 4) | 134 (UINT32_C(1) << 3) | 135 (UINT32_C(1) << 2) | 136 (UINT32_C(1) << 1) | 137 (UINT32_C(1))), 138 .pc = 0x48, 139 .cause = TRAP_EBREAK, 140 } 141 }, 142 { 143 .name = "loads and stores", 144 .program = { 145 0x10000593, //li a1,256 146 0xfff00513, //li a0,-1 147 0x00a58023, //sb a0,0(a1) 148 0x0005c503, //lbu a0,0(a1) 149 0x00150513, //addi a0,a0,1 150 0x00a59123, //sh a0,2(a1) 151 0x00259503, //lh a0,2(a1) 152 0xeff50513, //addi a0,a0,-257 153 0x00a58223, //sb a0,4(a1) 154 0x00458503, //lb a0,4(a1) 155 0x00a59323, //sh a0,6(a1) 156 0x00659503, //lh a0,6(a1) 157 0x0065d503, //lhu a0,6(a1) 158 0x00150513, //addi a0,a0,1 159 0x00a5a423, //sw a0,8(a1) 160 0x00000513, //li a0,0 161 0x0085a503, //lw a0,8(a1) 162 0x00000593, //li a1,0 163 0x00100073 //ebreak 164 }, 165 .program_len = 19, 166 .exp = { 167 .x = { 168 [10] = 0x00010000, 169 [11] = 0x0, 170 }, 171 .x_check_mask = ((UINT32_C(1) << 10) | 172 (UINT32_C(1) << 11)), 173 .pc = 0x48, 174 .cause = TRAP_EBREAK, 175 .mem = { 176 { .address = 0x100, .expected = 0xff }, 177 { .address = 0x101, .expected = 0x00 }, 178 { .address = 0x102, .expected = 0x00 }, 179 { .address = 0x103, .expected = 0x01 }, 180 181 { .address = 0x104, .expected = 0xff }, 182 { .address = 0x105, .expected = 0x00 }, 183 { .address = 0x106, .expected = 0xff }, 184 { .address = 0x107, .expected = 0xff }, 185 186 { .address = 0x108, .expected = 0x00 }, 187 { .address = 0x109, .expected = 0x00 }, 188 { .address = 0x10a, .expected = 0x01 }, 189 { .address = 0x10b, .expected = 0x00 }, 190 }, 191 .mem_len = 12, 192 } 193 }, 194 { 195 .name = "Fibonacci sequence", 196 .program = { 197 0x01400513, //li a0,20 198 0x00000293, //li t0,0 199 0x00100313, //li t1,1 200 0x00000393, //li t2,0 201 0x00a38c63, //beq t2,a0,28 <done> 202 0x00628e33, //add t3,t0,t1 203 0x00030293, //mv t0,t1 204 0x000e0313, //mv t1,t3 205 0x00138393, //addi t2,t2,1 206 0xfedff06f, //j 10 <loop> 207 0x00028513, //mv a0,t0 208 0x00100073, //ebreak 209 }, 210 .program_len = 12, 211 .exp = { 212 .x = { 213 [5] = 0x1a6d, 214 [6] = 0x2ac2, 215 [7] = 0x14, 216 [10] = 0x1a6d, 217 [28] = 0x2ac2, 218 }, 219 .x_check_mask = ((UINT32_C(1) << 5) | 220 (UINT32_C(1) << 6) | 221 (UINT32_C(1) << 7) | 222 (UINT32_C(1) << 10) | 223 (UINT32_C(1) << 28)), 224 .pc = 0x2c, 225 .cause = TRAP_EBREAK, 226 } 227 }, 228 { 229 .name = "load/store edge values", 230 .program = { 231 0x20000a13, // addi x20,x0,0x200 232 0x00001ab7, // lui x21,0x1 233 0xffca8a93, // addi x21,x21,-4 -> 0xffc 234 0xfff00093, // addi x1,x0,-1 -> 0xffffffff 235 0x07f00113, // addi x2,x0,0x7f 236 0x08000193, // addi x3,x0,0x80 237 0x00008237, // lui x4,0x8 -> 0x8000 238 0xfff20213, // addi x4,x4,-1 -> 0x7fff 239 0x000082b7, // lui x5,0x8 -> 0x8000 240 0x12345337, // lui x6,0x12345 241 0x67830313, // addi x6,x6,0x678 -> 0x12345678 242 0x002a0023, // sb x2,0(x20) -> 0x7f 243 0x003a00a3, // sb x3,1(x20) -> 0x80 244 0x004a1123, // sh x4,2(x20) -> 0x7fff 245 0x005a1223, // sh x5,4(x20) -> 0x8000 246 0x001a2423, // sw x1,8(x20) -> 0xffffffff 247 0x006a2623, // sw x6,12(x20) -> 0x12345678 248 0x000a2823, // sw x0,16(x20) -> 0 249 0x006aa023, // sw x6,0(x21) -> mem[0xffc] 250 0x000a0403, // lb x8,0(x20) -> 0x0000007f 251 0x001a0483, // lb x9,1(x20) -> 0xffffff80 252 0x001a4503, // lbu x10,1(x20) -> 0x00000080 253 0x002a1583, // lh x11,2(x20) -> 0x00007fff 254 0x004a1603, // lh x12,4(x20) -> 0xffff8000 255 0x004a5683, // lhu x13,4(x20) -> 0x00008000 256 0x008a2703, // lw x14,8(x20) -> 0xffffffff 257 0x00ca2783, // lw x15,12(x20) -> 0x12345678 258 0x000aa803, // lw x16,0(x21) -> 0x12345678 259 0x010a2883, // lw x17,16(x20) -> 0 260 0x00100073, // ebreak 261 }, 262 .program_len = 30, 263 .exp = { 264 .x = { 265 [1] = 0xffffffff, 266 [2] = 0x0000007f, 267 [3] = 0x00000080, 268 [4] = 0x00007fff, 269 [5] = 0x00008000, 270 [6] = 0x12345678, 271 [8] = 0x0000007f, 272 [9] = 0xffffff80, 273 [10] = 0x00000080, 274 [11] = 0x00007fff, 275 [12] = 0xffff8000, 276 [13] = 0x00008000, 277 [14] = 0xffffffff, 278 [15] = 0x12345678, 279 [16] = 0x12345678, 280 [17] = 0x00000000, 281 [20] = 0x00000200, 282 [21] = 0x00000ffc, 283 }, 284 .x_check_mask = 285 (UINT32_C(1) << 1) | 286 (UINT32_C(1) << 2) | 287 (UINT32_C(1) << 3) | 288 (UINT32_C(1) << 4) | 289 (UINT32_C(1) << 5) | 290 (UINT32_C(1) << 6) | 291 (UINT32_C(1) << 8) | 292 (UINT32_C(1) << 9) | 293 (UINT32_C(1) << 10) | 294 (UINT32_C(1) << 11) | 295 (UINT32_C(1) << 12) | 296 (UINT32_C(1) << 13) | 297 (UINT32_C(1) << 14) | 298 (UINT32_C(1) << 15) | 299 (UINT32_C(1) << 16) | 300 (UINT32_C(1) << 17) | 301 (UINT32_C(1) << 20) | 302 (UINT32_C(1) << 21), 303 .pc = 0x74, 304 .cause = TRAP_EBREAK, 305 .mem = { 306 { .address = 0x200, .expected = 0x7f }, 307 { .address = 0x201, .expected = 0x80 }, 308 { .address = 0x202, .expected = 0xff }, 309 { .address = 0x203, .expected = 0x7f }, 310 { .address = 0x204, .expected = 0x00 }, 311 { .address = 0x205, .expected = 0x80 }, 312 { .address = 0x208, .expected = 0xff }, 313 { .address = 0x209, .expected = 0xff }, 314 { .address = 0x20a, .expected = 0xff }, 315 { .address = 0x20b, .expected = 0xff }, 316 { .address = 0x20c, .expected = 0x78 }, 317 { .address = 0x20d, .expected = 0x56 }, 318 { .address = 0x20e, .expected = 0x34 }, 319 { .address = 0x20f, .expected = 0x12 }, 320 { .address = 0x210, .expected = 0x00 }, 321 { .address = 0x211, .expected = 0x00 }, 322 { .address = 0x212, .expected = 0x00 }, 323 { .address = 0x213, .expected = 0x00 }, 324 { .address = 0xffc, .expected = 0x78 }, 325 { .address = 0xffd, .expected = 0x56 }, 326 { .address = 0xffe, .expected = 0x34 }, 327 { .address = 0xfff, .expected = 0x12 }, 328 }, 329 .mem_len = 22, 330 } 331 }, 332 { 333 .name = "branches and jumps", 334 .program = { 335 /* Operands */ 336 0x00500093, // addi x1,x0,5 337 0x00500113, // addi x2,x0,5 338 0xfff00193, // addi x3,x0,-1 339 0x00100213, // addi x4,x0,1 340 341 /* BEQ taken */ 342 0x00100513, // addi x10,x0,1 343 0x00208463, // beq x1,x2,+8 344 0x00000513, // addi x10,x0,0 skipped 345 346 /* BEQ not taken */ 347 0x00408463, // beq x1,x4,+8 348 0x00100593, // addi x11,x0,1 349 350 /* BNE taken */ 351 0x00100613, // addi x12,x0,1 352 0x00409463, // bne x1,x4,+8 353 0x00000613, // addi x12,x0,0 skipped 354 355 /* BNE not taken */ 356 0x00209463, // bne x1,x2,+8 357 0x00100693, // addi x13,x0,1 358 359 /* BLT taken: -1 < 1 */ 360 0x00100713, // addi x14,x0,1 361 0x0041c463, // blt x3,x4,+8 362 0x00000713, // addi x14,x0,0 skipped 363 364 /* BLT not taken: 1 < -1 is false */ 365 0x00324463, // blt x4,x3,+8 366 0x00100793, // addi x15,x0,1 367 368 /* BGE taken: 1 >= -1 */ 369 0x00100813, // addi x16,x0,1 370 0x00325463, // bge x4,x3,+8 371 0x00000813, // addi x16,x0,0 skipped 372 373 /* BGE not taken: -1 >= 1 is false */ 374 0x0041d463, // bge x3,x4,+8 375 0x00100893, // addi x17,x0,1 376 377 /* BLTU taken: 1 < 5 */ 378 0x00100913, // addi x18,x0,1 379 0x00126463, // bltu x4,x1,+8 380 0x00000913, // addi x18,x0,0 skipped 381 382 /* BLTU not taken: 0xffffffff < 1 is false */ 383 0x0041e463, // bltu x3,x4,+8 384 0x00100993, // addi x19,x0,1 385 386 /* BGEU taken: 0xffffffff >= 1 */ 387 0x00100a13, // addi x20,x0,1 388 0x0041f463, // bgeu x3,x4,+8 389 0x00000a13, // addi x20,x0,0 skipped 390 391 /* BGEU not taken: 1 >= 0xffffffff is false */ 392 0x00327463, // bgeu x4,x3,+8 393 0x00100a93, // addi x21,x0,1 394 395 /* 396 * JAL at 0x8c: 397 * link x22 = 0x90 398 * target = 0x94 399 */ 400 0x00100b93, // addi x23,x0,1 401 0x00800b6f, // jal x22,+8 402 0x00000b93, // addi x23,x0,0 skipped 403 404 /* 405 * Construct the odd address 0xa9. 406 * JALR must clear bit zero and jump to 0xa8. 407 */ 408 0x00000c17, // auipc x24,0 -> 0x94 409 0x015c0c13, // addi x24,x24,21 -> 0xa9 410 0x00100c93, // addi x25,x0,1 411 0x000c0d67, // jalr x26,0(x24) 412 0x00000c93, // addi x25,x0,0 skipped 413 414 0x00100073, // ebreak at 0xa8 415 }, 416 .program_len = 43, 417 .exp = { 418 .x = { 419 [1] = 0x00000005, 420 [2] = 0x00000005, 421 [3] = 0xffffffff, 422 [4] = 0x00000001, 423 424 [10] = 0x00000001, // BEQ taken 425 [11] = 0x00000001, // BEQ not taken 426 [12] = 0x00000001, // BNE taken 427 [13] = 0x00000001, // BNE not taken 428 [14] = 0x00000001, // BLT taken 429 [15] = 0x00000001, // BLT not taken 430 [16] = 0x00000001, // BGE taken 431 [17] = 0x00000001, // BGE not taken 432 [18] = 0x00000001, // BLTU taken 433 [19] = 0x00000001, // BLTU not taken 434 [20] = 0x00000001, // BGEU taken 435 [21] = 0x00000001, // BGEU not taken 436 437 [22] = 0x00000090, // JAL return address 438 [23] = 0x00000001, // JAL skipped failure 439 [24] = 0x000000a9, // odd JALR base 440 [25] = 0x00000001, // JALR skipped failure 441 [26] = 0x000000a4, // JALR return address 442 }, 443 .x_check_mask = 444 (UINT32_C(1) << 1) | 445 (UINT32_C(1) << 2) | 446 (UINT32_C(1) << 3) | 447 (UINT32_C(1) << 4) | 448 (UINT32_C(0x1ffff) << 10), 449 450 .pc = 0xa8, 451 .cause = TRAP_EBREAK, 452 } 453 }, 454 { 455 .name = "R-type arithmetic edge cases", 456 .program = { 457 0xfff00093, // addi x1,x0,-1 458 0x00100113, // addi x2,x0,1 459 0x01f00193, // addi x3,x0,31 460 0x80000237, // lui x4,0x80000 -> INT32_MIN 461 0x800002b7, // lui x5,0x80000 462 0xfff28293, // addi x5,x5,-1 -> INT32_MAX 463 464 0x00228533, // add x10,x5,x2 -> 0x80000000 465 0x402005b3, // sub x11,x0,x2 -> 0xffffffff 466 0x00311633, // sll x12,x2,x3 -> 0x80000000 467 0x002226b3, // slt x13,x4,x2 -> 1 468 0x00223733, // sltu x14,x4,x2 -> 0 469 0x0050c7b3, // xor x15,x1,x5 -> 0x80000000 470 0x00225833, // srl x16,x4,x2 -> 0x40000000 471 0x402258b3, // sra x17,x4,x2 -> 0xc0000000 472 0x00526933, // or x18,x4,x5 -> 0xffffffff 473 0x005279b3, // and x19,x4,x5 -> 0x00000000 474 475 0x00111a33, // sll x20,x2,x1 -> shift by 31 476 0x00125ab3, // srl x21,x4,x1 -> shift by 31 477 0x40125b33, // sra x22,x4,x1 -> shift by 31 478 479 0x00208033, // add x0,x1,x2 -> x0 must remain zero 480 0x40220bb3, // sub x23,x4,x2 -> 0x7fffffff 481 0x00100073, // ebreak 482 }, 483 .program_len = 22, 484 .exp = { 485 .x = { 486 [0] = 0x00000000, 487 [1] = 0xffffffff, 488 [2] = 0x00000001, 489 [3] = 0x0000001f, 490 [4] = 0x80000000, 491 [5] = 0x7fffffff, 492 493 [10] = 0x80000000, 494 [11] = 0xffffffff, 495 [12] = 0x80000000, 496 [13] = 0x00000001, 497 [14] = 0x00000000, 498 [15] = 0x80000000, 499 [16] = 0x40000000, 500 [17] = 0xc0000000, 501 [18] = 0xffffffff, 502 [19] = 0x00000000, 503 [20] = 0x80000000, 504 [21] = 0x00000001, 505 [22] = 0xffffffff, 506 [23] = 0x7fffffff, 507 }, 508 .x_check_mask = 509 UINT32_C(0x3f) | 510 (UINT32_C(0x3fff) << 10), 511 512 .pc = 0x54, 513 .cause = TRAP_EBREAK, 514 } 515 }, 516 { 517 .name = "JAL misaligned target", 518 .program = { 519 0x05500293, // addi x5,x0,0x55 520 0x002002ef, // jal x5,+2 521 }, 522 .program_len = 2, 523 .exp = { 524 .x = { 525 [5] = 0x00000055, 526 }, 527 .x_check_mask = (UINT32_C(1) << 5), 528 .pc = 0x4, 529 .cause = TRAP_INSTRUCTION_MISALIGNED, 530 } 531 }, 532 { 533 .name = "JAL target above memory", 534 .program = { 535 0x05500293, // addi x5,x0,0x55 536 0x000012ef, // jal x5,+4096 537 }, 538 .program_len = 2, 539 .exp = { 540 .x = { 541 [5] = 0x00000055, 542 }, 543 .x_check_mask = (UINT32_C(1) << 5), 544 .pc = 0x4, 545 .cause = TRAP_INSTRUCTION_ACCESS_FAULT, 546 } 547 }, 548 { 549 .name = "JAL target below memory", 550 .program = { 551 0x05500293, // addi x5,x0,0x55 552 0xff9ff2ef, // jal x5,-8: 0x4 - 8 553 }, 554 .program_len = 2, 555 .exp = { 556 .x = { 557 [5] = 0x00000055, 558 }, 559 .x_check_mask = (UINT32_C(1) << 5), 560 .pc = 0x4, 561 .cause = TRAP_INSTRUCTION_ACCESS_FAULT, 562 } 563 }, 564 { 565 .name = "JALR misaligned target", 566 .program = { 567 0x05500293, // addi x5,x0,0x55 568 0x00200093, // addi x1,x0,2 569 0x000082e7, // jalr x5,0(x1): target 0x2 570 }, 571 .program_len = 3, 572 .exp = { 573 .x = { 574 [1] = 0x00000002, 575 [5] = 0x00000055, 576 }, 577 .x_check_mask = 578 (UINT32_C(1) << 1) | 579 (UINT32_C(1) << 5), 580 .pc = 0x8, 581 .cause = TRAP_INSTRUCTION_MISALIGNED, 582 } 583 }, 584 { 585 .name = "JALR target above memory", 586 .program = { 587 0x05500293, // addi x5,x0,0x55 588 0x000010b7, // lui x1,0x1: 0x1000 589 0x000082e7, // jalr x5,0(x1) 590 }, 591 .program_len = 3, 592 .exp = { 593 .x = { 594 [1] = 0x00001000, 595 [5] = 0x00000055, 596 }, 597 .x_check_mask = 598 (UINT32_C(1) << 1) | 599 (UINT32_C(1) << 5), 600 .pc = 0x8, 601 .cause = TRAP_INSTRUCTION_ACCESS_FAULT, 602 } 603 }, 604 { 605 .name = "JALR wrapped negative target", 606 .program = { 607 0x05500293, // addi x5,x0,0x55 608 0x00000093, // addi x1,x0,0 609 0xffc082e7, // jalr x5,-4(x1) 610 }, 611 .program_len = 3, 612 .exp = { 613 .x = { 614 [1] = 0x00000000, 615 [5] = 0x00000055, 616 }, 617 .x_check_mask = 618 (UINT32_C(1) << 1) | 619 (UINT32_C(1) << 5), 620 .pc = 0x8, 621 .cause = TRAP_INSTRUCTION_ACCESS_FAULT, 622 } 623 }, 624 { 625 .name = "illegal JALR funct3", 626 .program = { 627 0x05500293, // addi x5,x0,0x55 628 0x000012e7, // Illegal JALR, funct3=1 629 }, 630 .program_len = 2, 631 .exp = { 632 .x = { 633 [5] = 0x00000055, 634 }, 635 .x_check_mask = (UINT32_C(1) << 5), 636 .pc = 0x4, 637 .cause = TRAP_ILLEGAL_INSTRUCTION, 638 } 639 }, 640 { 641 .name = "taken branch misaligned target", 642 .program = { 643 0x00100093, // addi x1,x0,1 644 0x05500293, // addi x5,x0,0x55 645 0x00108163, // beq x1,x1,+2 646 }, 647 .program_len = 3, 648 .exp = { 649 .x = { 650 [1] = 0x00000001, 651 [5] = 0x00000055, 652 }, 653 .x_check_mask = 654 (UINT32_C(1) << 1) | 655 (UINT32_C(1) << 5), 656 .pc = 0x8, 657 .cause = TRAP_INSTRUCTION_MISALIGNED, 658 } 659 }, 660 { 661 .name = "taken branch target above memory", 662 .program = { 663 0x00100093, // addi x1,x0,1 664 0x05500293, // addi x5,x0,0x55 665 0x7e108ee3, // beq x1,x1,+4092 666 }, 667 .program_len = 3, 668 .exp = { 669 .x = { 670 [1] = 0x00000001, 671 [5] = 0x00000055, 672 }, 673 .x_check_mask = 674 (UINT32_C(1) << 1) | 675 (UINT32_C(1) << 5), 676 .pc = 0x8, 677 .cause = TRAP_INSTRUCTION_ACCESS_FAULT, 678 } 679 }, 680 { 681 .name = "taken branch target below memory", 682 .program = { 683 0x00100093, // addi x1,x0,1 684 0x05500293, // addi x5,x0,0x55 685 0xfe108ae3, // beq x1,x1,-12: 0x8 - 12 686 }, 687 .program_len = 3, 688 .exp = { 689 .x = { 690 [1] = 0x00000001, 691 [5] = 0x00000055, 692 }, 693 .x_check_mask = 694 (UINT32_C(1) << 1) | 695 (UINT32_C(1) << 5), 696 .pc = 0x8, 697 .cause = TRAP_INSTRUCTION_ACCESS_FAULT, 698 } 699 }, 700 { 701 .name = "illegal branch funct3 2", 702 .program = { 703 0x00002063, // branch opcode with reserved funct3=2 704 }, 705 .program_len = 1, 706 .exp = { 707 .pc = 0x0, 708 .cause = TRAP_ILLEGAL_INSTRUCTION, 709 } 710 }, 711 { 712 .name = "illegal branch funct3 3", 713 .program = { 714 0x00003063, // branch opcode with reserved funct3=3 715 }, 716 .program_len = 1, 717 .exp = { 718 .pc = 0x0, 719 .cause = TRAP_ILLEGAL_INSTRUCTION, 720 } 721 }, 722 { 723 .name = "not-taken branch ignores misaligned target", 724 .program = { 725 0x00100093, // addi x1,x0,1 726 0x00200113, // addi x2,x0,2 727 0x00208163, // beq x1,x2,+2: false, target would be 0xa 728 0x00100193, // addi x3,x0,1: must execute 729 0x00100073, // ebreak 730 }, 731 .program_len = 5, 732 .exp = { 733 .x = { 734 [3] = 0x00000001, 735 }, 736 .x_check_mask = (UINT32_C(1) << 3), 737 .pc = 0x10, 738 .cause = TRAP_EBREAK, // use your EBREAK cause name 739 } 740 }, 741 { 742 .name = "LH misaligned address", 743 .program = { 744 0x05500293, // addi x5,x0,0x55 745 0x00100093, // addi x1,x0,1 746 0x00009283, // lh x5,0(x1) 747 }, 748 .program_len = 3, 749 .exp = { 750 .x = { 751 [5] = 0x00000055, 752 }, 753 .x_check_mask = (UINT32_C(1) << 5), 754 .pc = 0x8, 755 .cause = TRAP_LOAD_MISALIGNED, 756 } 757 }, 758 { 759 .name = "LHU misaligned address", 760 .program = { 761 0x05500293, // addi x5,x0,0x55 762 0x00100093, // addi x1,x0,1 763 0x0000d283, // lhu x5,0(x1) 764 }, 765 .program_len = 3, 766 .exp = { 767 .x = { 768 [5] = 0x00000055, 769 }, 770 .x_check_mask = (UINT32_C(1) << 5), 771 .pc = 0x8, 772 .cause = TRAP_LOAD_MISALIGNED, 773 } 774 }, 775 { 776 .name = "LW misaligned address", 777 .program = { 778 0x05500293, // addi x5,x0,0x55 779 0x00200093, // addi x1,x0,2 780 0x0000a283, // lw x5,0(x1) 781 }, 782 .program_len = 3, 783 .exp = { 784 .x = { 785 [5] = 0x00000055, 786 }, 787 .x_check_mask = (UINT32_C(1) << 5), 788 .pc = 0x8, 789 .cause = TRAP_LOAD_MISALIGNED, 790 } 791 }, 792 { 793 .name = "SH misaligned address", 794 .program = { 795 0x20000093, // addi x1,x0,0x200 796 0x05500293, // addi x5,x0,0x55 797 0x005090a3, // sh x5,1(x1) 798 }, 799 .program_len = 3, 800 .exp = { 801 .pc = 0x8, 802 .cause = TRAP_STORE_MISALIGNED, 803 .mem = { 804 { .address = 0x201, .expected = 0x00 }, 805 { .address = 0x202, .expected = 0x00 }, 806 }, 807 .mem_len = 2, 808 } 809 }, 810 { 811 .name = "SW misaligned address", 812 .program = { 813 0x20000093, // addi x1,x0,0x200 814 0x05500293, // addi x5,x0,0x55 815 0x0050a123, // sw x5,2(x1) 816 }, 817 .program_len = 3, 818 .exp = { 819 .pc = 0x8, 820 .cause = TRAP_STORE_MISALIGNED, 821 .mem = { 822 { .address = 0x202, .expected = 0x00 }, 823 { .address = 0x203, .expected = 0x00 }, 824 { .address = 0x204, .expected = 0x00 }, 825 { .address = 0x205, .expected = 0x00 }, 826 }, 827 .mem_len = 4, 828 } 829 }, 830 { 831 .name = "LB address above memory", 832 .program = { 833 0x05500293, // addi x5,x0,0x55 834 0x000010b7, // lui x1,0x1 -> 0x1000 835 0x00008283, // lb x5,0(x1) 836 }, 837 .program_len = 3, 838 .exp = { 839 .x = { 840 [5] = 0x00000055, 841 }, 842 .x_check_mask = (UINT32_C(1) << 5), 843 .pc = 0x8, 844 .cause = TRAP_LOAD_ACCESS_FAULT, 845 } 846 }, 847 { 848 .name = "LBU address above memory", 849 .program = { 850 0x05500293, // addi x5,x0,0x55 851 0x000010b7, // lui x1,0x1 -> 0x1000 852 0x0000c283, // lbu x5,0(x1) 853 }, 854 .program_len = 3, 855 .exp = { 856 .x = { 857 [5] = 0x00000055, 858 }, 859 .x_check_mask = (UINT32_C(1) << 5), 860 .pc = 0x8, 861 .cause = TRAP_LOAD_ACCESS_FAULT, 862 } 863 }, 864 { 865 .name = "LH address above memory", 866 .program = { 867 0x05500293, // addi x5,x0,0x55 868 0x000010b7, // lui x1,0x1 -> 0x1000 869 0x00009283, // lh x5,0(x1) 870 }, 871 .program_len = 3, 872 .exp = { 873 .x = { 874 [5] = 0x00000055, 875 }, 876 .x_check_mask = (UINT32_C(1) << 5), 877 .pc = 0x8, 878 .cause = TRAP_LOAD_ACCESS_FAULT, 879 } 880 }, 881 { 882 .name = "LHU address above memory", 883 .program = { 884 0x05500293, // addi x5,x0,0x55 885 0x000010b7, // lui x1,0x1 -> 0x1000 886 0x0000d283, // lhu x5,0(x1) 887 }, 888 .program_len = 3, 889 .exp = { 890 .x = { 891 [5] = 0x00000055, 892 }, 893 .x_check_mask = (UINT32_C(1) << 5), 894 .pc = 0x8, 895 .cause = TRAP_LOAD_ACCESS_FAULT, 896 } 897 }, 898 { 899 .name = "LW address above memory", 900 .program = { 901 0x05500293, // addi x5,x0,0x55 902 0x000010b7, // lui x1,0x1 -> 0x1000 903 0x0000a283, // lw x5,0(x1) 904 }, 905 .program_len = 3, 906 .exp = { 907 .x = { 908 [5] = 0x00000055, 909 }, 910 .x_check_mask = (UINT32_C(1) << 5), 911 .pc = 0x8, 912 .cause = TRAP_LOAD_ACCESS_FAULT, 913 } 914 }, 915 { 916 .name = "SB address above memory", 917 .program = { 918 0x000010b7, // lui x1,0x1 -> 0x1000 919 0x05500293, // addi x5,x0,0x55 920 0x00508023, // sb x5,0(x1) 921 }, 922 .program_len = 3, 923 .exp = { 924 .pc = 0x8, 925 .cause = TRAP_STORE_ACCESS_FAULT, 926 } 927 }, 928 { 929 .name = "SH address above memory", 930 .program = { 931 0x000010b7, // lui x1,0x1 -> 0x1000 932 0x05500293, // addi x5,x0,0x55 933 0x00509023, // sh x5,0(x1) 934 }, 935 .program_len = 3, 936 .exp = { 937 .pc = 0x8, 938 .cause = TRAP_STORE_ACCESS_FAULT, 939 } 940 }, 941 { 942 .name = "SW address above memory", 943 .program = { 944 0x000010b7, // lui x1,0x1 -> 0x1000 945 0x05500293, // addi x5,x0,0x55 946 0x0050a023, // sw x5,0(x1) 947 }, 948 .program_len = 3, 949 .exp = { 950 .pc = 0x8, 951 .cause = TRAP_STORE_ACCESS_FAULT, 952 } 953 }, 954 { 955 .name = "load wrapped negative address", 956 .program = { 957 0x05500293, // addi x5,x0,0x55 958 0xfff00283, // lb x5,-1(x0) -> 0xffffffff 959 }, 960 .program_len = 2, 961 .exp = { 962 .x = { 963 [5] = 0x00000055, 964 }, 965 .x_check_mask = (UINT32_C(1) << 5), 966 .pc = 0x4, 967 .cause = TRAP_LOAD_ACCESS_FAULT, 968 } 969 }, 970 { 971 .name = "I-type arithmetic edge cases", 972 .program = { 973 0x800000b7, // lui x1,0x80000 974 0xfff08093, // addi x1,x1,-1 -> INT32_MAX 975 0x80000137, // lui x2,0x80000 -> INT32_MIN 976 977 0x00108513, // addi x10,x1,1 -> 0x80000000 978 0xfff10593, // addi x11,x2,-1 -> 0x7fffffff 979 0xfff12613, // slti x12,x2,-1 -> 1 980 0xfff0a693, // slti x13,x1,-1 -> 0 981 0xfff03713, // sltiu x14,x0,-1 -> 1 982 0xfff13793, // sltiu x15,x2,-1 -> 1 983 0xfff04813, // xori x16,x0,-1 -> 0xffffffff 984 0x80006893, // ori x17,x0,-2048 -> 0xfffff800 985 0x55587913, // andi x18,x16,0x555 -> 0x00000555 986 0xfff17993, // andi x19,x2,-1 -> 0x80000000 987 988 0x00100073, // ebreak 989 }, 990 .program_len = 14, 991 .exp = { 992 .x = { 993 [1] = 0x7fffffff, 994 [2] = 0x80000000, 995 996 [10] = 0x80000000, 997 [11] = 0x7fffffff, 998 [12] = 0x00000001, 999 [13] = 0x00000000, 1000 [14] = 0x00000001, 1001 [15] = 0x00000001, 1002 [16] = 0xffffffff, 1003 [17] = 0xfffff800, 1004 [18] = 0x00000555, 1005 [19] = 0x80000000, 1006 }, 1007 .x_check_mask = 1008 (UINT32_C(1) << 1) | 1009 (UINT32_C(1) << 2) | 1010 (UINT32_C(0x3ff) << 10), 1011 1012 .pc = 0x34, 1013 .cause = TRAP_EBREAK, 1014 } 1015 }, 1016 { 1017 .name = "I-type shift boundary amounts", 1018 .program = { 1019 0x00100093, // addi x1,x0,1 1020 0x80000137, // lui x2,0x80000 1021 1022 0x00009513, // slli x10,x1,0 -> 0x00000001 1023 0x01f09593, // slli x11,x1,31 -> 0x80000000 1024 0x00015613, // srli x12,x2,0 -> 0x80000000 1025 0x01f15693, // srli x13,x2,31 -> 0x00000001 1026 0x40115713, // srai x14,x2,1 -> 0xc0000000 1027 0x41f15793, // srai x15,x2,31 -> 0xffffffff 1028 1029 0x00100073, // ebreak 1030 }, 1031 .program_len = 9, 1032 .exp = { 1033 .x = { 1034 [1] = 0x00000001, 1035 [2] = 0x80000000, 1036 [10] = 0x00000001, 1037 [11] = 0x80000000, 1038 [12] = 0x80000000, 1039 [13] = 0x00000001, 1040 [14] = 0xc0000000, 1041 [15] = 0xffffffff, 1042 }, 1043 .x_check_mask = 1044 (UINT32_C(1) << 1) | 1045 (UINT32_C(1) << 2) | 1046 (UINT32_C(0x3f) << 10), 1047 1048 .pc = 0x20, 1049 .cause = TRAP_EBREAK, 1050 } 1051 }, 1052 { 1053 .name = "illegal SLLI upper immediate bits", 1054 .program = { 1055 0x00100093, // addi x1,x0,1 1056 0x05500113, // addi x2,x0,0x55 1057 0x02009113, // illegal SLLI: imm[11:5]=0x01 1058 }, 1059 .program_len = 3, 1060 .exp = { 1061 .x = { 1062 [2] = 0x00000055, 1063 }, 1064 .x_check_mask = (UINT32_C(1) << 2), 1065 .pc = 0x8, 1066 .cause = TRAP_ILLEGAL_INSTRUCTION, 1067 } 1068 }, 1069 { 1070 .name = "illegal right-shift immediate encoding", 1071 .program = { 1072 0x800000b7, // lui x1,0x80000 1073 0x05500113, // addi x2,x0,0x55 1074 0x0200d113, // illegal SRLI/SRAI: imm[11:5]=0x01 1075 }, 1076 .program_len = 3, 1077 .exp = { 1078 .x = { 1079 [2] = 0x00000055, 1080 }, 1081 .x_check_mask = (UINT32_C(1) << 2), 1082 .pc = 0x8, 1083 .cause = TRAP_ILLEGAL_INSTRUCTION, 1084 } 1085 }, 1086 { 1087 .name = "LUI and AUIPC at nonzero PC", 1088 .program = { 1089 0x00000013, // nop 1090 0x00000013, // nop 1091 0x12345297, // auipc x5,0x12345 -> 0x12345008 1092 0x12345337, // lui x6,0x12345 -> 0x12345000 1093 0x00100073, // ebreak 1094 }, 1095 .program_len = 5, 1096 .exp = { 1097 .x = { 1098 [5] = 0x12345008, 1099 [6] = 0x12345000, 1100 }, 1101 .x_check_mask = 1102 (UINT32_C(1) << 5) | 1103 (UINT32_C(1) << 6), 1104 1105 .pc = 0x10, 1106 .cause = TRAP_EBREAK, 1107 } 1108 }, 1109 { 1110 .name = "negative load and store offsets", 1111 .program = { 1112 0x20400093, // addi x1,x0,0x204 1113 0x12300113, // addi x2,x0,0x123 1114 0xfe20ae23, // sw x2,-4(x1) -> address 0x200 1115 0xffc0a183, // lw x3,-4(x1) 1116 0x00100073, // ebreak 1117 }, 1118 .program_len = 5, 1119 .exp = { 1120 .x = { 1121 [2] = 0x00000123, 1122 [3] = 0x00000123, 1123 }, 1124 .x_check_mask = 1125 (UINT32_C(1) << 2) | 1126 (UINT32_C(1) << 3), 1127 1128 .pc = 0x10, 1129 .cause = TRAP_EBREAK, 1130 1131 .mem = { 1132 { .address = 0x200, .expected = 0x23 }, 1133 { .address = 0x201, .expected = 0x01 }, 1134 { .address = 0x202, .expected = 0x00 }, 1135 { .address = 0x203, .expected = 0x00 }, 1136 }, 1137 .mem_len = 4, 1138 } 1139 }, 1140 { 1141 .name = "illegal R-type funct7", 1142 .program = { 1143 0x00100093, // addi x1,x0,1 1144 0x00200113, // addi x2,x0,2 1145 0x05500293, // addi x5,x0,0x55 1146 0x022082b3, // illegal ADD-like instruction: funct7=1 1147 }, 1148 .program_len = 4, 1149 .exp = { 1150 .x = { 1151 [5] = 0x00000055, 1152 }, 1153 .x_check_mask = (UINT32_C(1) << 5), 1154 .pc = 0xc, 1155 .cause = TRAP_ILLEGAL_INSTRUCTION, 1156 } 1157 }, 1158 { 1159 .name = "illegal load funct3", 1160 .program = { 1161 0x05500293, // addi x5,x0,0x55 1162 0x0000b283, // load opcode with reserved funct3=3 1163 }, 1164 .program_len = 2, 1165 .exp = { 1166 .x = { 1167 [5] = 0x00000055, 1168 }, 1169 .x_check_mask = (UINT32_C(1) << 5), 1170 .pc = 0x4, 1171 .cause = TRAP_ILLEGAL_INSTRUCTION, 1172 } 1173 }, 1174 { 1175 .name = "illegal store funct3", 1176 .program = { 1177 0x20000093, // addi x1,x0,0x200 1178 0x05500293, // addi x5,x0,0x55 1179 0x0050b023, // store opcode with reserved funct3=3 1180 }, 1181 .program_len = 3, 1182 .exp = { 1183 .pc = 0x8, 1184 .cause = TRAP_ILLEGAL_INSTRUCTION, 1185 .mem = { 1186 { .address = 0x200, .expected = 0x00 }, 1187 { .address = 0x201, .expected = 0x00 }, 1188 { .address = 0x202, .expected = 0x00 }, 1189 { .address = 0x203, .expected = 0x00 }, 1190 }, 1191 .mem_len = 4, 1192 } 1193 }, 1194 { 1195 .name = "illegal SYSTEM instruction", 1196 .program = { 1197 0x00200073, // neither ECALL nor EBREAK 1198 }, 1199 .program_len = 1, 1200 .exp = { 1201 .pc = 0x0, 1202 .cause = TRAP_ILLEGAL_INSTRUCTION, 1203 } 1204 }, 1205 { 1206 .name = "Compiled freestanding C Fibonacci", 1207 .program = { 1208 0x00001137, //lui sp,0x1 1209 0x008000ef, //jal c <main> 1210 0x00100073, //ebreak 1211 0xfe010113, //addi sp,sp,-32 # fe0 <main+0xfd4> 1212 0x00112e23, //sw ra,28(sp) 1213 0x00812c23, //sw s0,24(sp) 1214 0x02010413, //addi s0,sp,32 1215 0xfe042623, //sw zero,-20(s0) 1216 0x00100793, //li a5,1 1217 0xfef42423, //sw a5,-24(s0) 1218 0xfe042223, //sw zero,-28(s0) 1219 0x0300006f, //j 5c <main+0x50> 1220 0xfec42703, //lw a4,-20(s0) 1221 0xfe842783, //lw a5,-24(s0) 1222 0x00f707b3, //add a5,a4,a5 1223 0xfef42023, //sw a5,-32(s0) 1224 0xfe842783, //lw a5,-24(s0) 1225 0xfef42623, //sw a5,-20(s0) 1226 0xfe042783, //lw a5,-32(s0) 1227 0xfef42423, //sw a5,-24(s0) 1228 0xfe442783, //lw a5,-28(s0) 1229 0x00178793, //addi a5,a5,1 1230 0xfef42223, //sw a5,-28(s0) 1231 0xfe442703, //lw a4,-28(s0) 1232 0x01300793, //li a5,19 1233 0xfce7d6e3, //bge a5,a4,30 <main+0x24> 1234 0xfec42783, //lw a5,-20(s0) 1235 0x00078513, //mv a0,a5 1236 0x01c12083, //lw ra,28(sp) 1237 0x01812403, //lw s0,24(sp) 1238 0x02010113, //addi sp,sp,32 1239 0x00008067, //ret 1240 }, 1241 .program_len = 32, 1242 .exp = { 1243 .pc = 0x8, 1244 .cause = TRAP_EBREAK, 1245 .x = { 1246 [1] = 0x8, 1247 [2] = 0x1000, 1248 [10] = 0x1a6d, /* F(20) = 6765 */ 1249 }, 1250 .x_check_mask = (UINT32_C(1) | 1251 (UINT32_C(1) << 2) | 1252 (UINT32_C(1) << 10)), 1253 }, 1254 }, 1255 }; 1256 1257 static void 1258 load_program(uint8_t *mem, uint32_t arr[], size_t len) 1259 { 1260 int b = 0; /*byte*/ 1261 for (size_t i=0; i<len; i++) { 1262 1263 mem[b+0] = (uint8_t)(arr[i] >> 0); 1264 mem[b+1] = (uint8_t)(arr[i] >> 8); 1265 mem[b+2] = (uint8_t)(arr[i] >> 16); 1266 mem[b+3] = (uint8_t)(arr[i] >> 24); 1267 1268 b+=4; 1269 } 1270 } 1271 1272 static void 1273 print_trap(cpu_state_t *cpu) 1274 { 1275 if (cpu->status == CPU_TRAPPED) { 1276 switch(cpu->trap.cause) { 1277 case TRAP_EBREAK: 1278 printf("Code reached breakpoint\n"); 1279 break; 1280 case TRAP_ECALL: 1281 printf("Code ECALL\n"); 1282 break; 1283 case TRAP_ILLEGAL_INSTRUCTION: 1284 printf("Illegal instruction\n"); 1285 break; 1286 case TRAP_INSTRUCTION_MISALIGNED: 1287 printf("Instruction misaligned\n"); 1288 break; 1289 case TRAP_INSTRUCTION_ACCESS_FAULT: 1290 printf("Instruction access fault\n"); 1291 break; 1292 case TRAP_LOAD_MISALIGNED: 1293 printf("Load misaligned\n"); 1294 break; 1295 case TRAP_LOAD_ACCESS_FAULT: 1296 printf("Load access fault\n"); 1297 break; 1298 case TRAP_STORE_MISALIGNED: 1299 printf("Store misaligned\n"); 1300 break; 1301 case TRAP_STORE_ACCESS_FAULT: 1302 printf("Store access fault\n"); 1303 break; 1304 case TRAP_NONE: 1305 printf("No trap cause\n"); 1306 break; 1307 } 1308 } 1309 } 1310 1311 static void 1312 check_reg(cpu_state_t *cpu, size_t i, int pr) 1313 { 1314 for (int j=0; j<32; j++) { 1315 if ((UINT32_C(1) << j) == tests[i].exp.x_check_mask) { 1316 if (cpu->x[j] != tests[i].exp.x[j]) { 1317 tests[i].result = TEST_FAILURE; 1318 if (pr) 1319 printf( " bad register %d. Expected %x, got %x\n", 1320 j, tests[i].exp.x[j], cpu->x[j]); 1321 } 1322 } 1323 } 1324 } 1325 1326 static void 1327 check_mem(uint8_t *mem, size_t i, int pr) 1328 { 1329 for (int j=0; j<tests[i].exp.mem_len; j++) { 1330 uint32_t address = tests[i].exp.mem[j].address; 1331 uint32_t expected = tests[i].exp.mem[j].expected; 1332 uint8_t real = mem[address]; 1333 1334 if (real != expected) { 1335 tests[i].result = TEST_FAILURE; 1336 if (pr) 1337 printf( " bad memory x%x. Expected x%x, got x%x\n", 1338 tests[i].exp.mem[j].address, expected, real); 1339 } 1340 } 1341 } 1342 1343 static void 1344 check_pc(uint32_t pc, size_t i, int pr) 1345 { 1346 if (pc != tests[i].exp.pc) { 1347 tests[i].result = TEST_FAILURE; 1348 if (pr) 1349 printf( " bad pc, expected x%x, got x%x\n", 1350 tests[i].exp.pc, pc); 1351 } 1352 } 1353 1354 static void 1355 check_cause(cpu_state_t *cpu, size_t i, int pr) 1356 { 1357 if (cpu->trap.cause != tests[i].exp.cause) { 1358 tests[i].result = TEST_FAILURE; 1359 if (pr) 1360 printf( " bad cause. Expected %x, got %x\n", 1361 tests[i].exp.cause, cpu->trap.cause); 1362 } 1363 } 1364 1365 int 1366 main() 1367 { 1368 size_t n = sizeof(tests) / sizeof(test_t); 1369 1370 int n_p = 0; 1371 int n_f = 0; 1372 for (size_t i=0; i<n; i++) { 1373 1374 cpu_state_t cpu = {0}; 1375 uint8_t mem[MEMSIZE] = {0}; 1376 1377 load_program(mem, tests[i].program, tests[i].program_len); 1378 1379 /* fetch & run */ 1380 while (1) { 1381 cpu_step(&cpu, mem); 1382 if (cpu.status == CPU_TRAPPED) { 1383 break; 1384 } 1385 } 1386 1387 /* check registers */ 1388 check_reg(&cpu, i, 0); 1389 1390 /* check mem */ 1391 check_mem(mem, i, 0); 1392 1393 /* check pc */ 1394 check_pc(cpu.pc, i, 0); 1395 1396 /* check trap cause */ 1397 check_cause(&cpu, i, 0); 1398 1399 if (tests[i].result != TEST_FAILURE) { 1400 printf("ok - %s (%zu)\n", tests[i].name, i); 1401 n_p++; 1402 } else { 1403 printf("not ok - %s (%zu)\n ", tests[i].name, i); 1404 print_trap(&cpu); 1405 1406 check_reg(&cpu, i, 1); 1407 check_mem(mem, i, 1); 1408 check_pc(cpu.pc, i, 1); 1409 check_cause(&cpu, i, 1); 1410 1411 n_f++; 1412 } 1413 1414 } 1415 printf("\n%d passed, %d failed\n", n_p, n_f); 1416 1417 return 0; 1418 }