rvemu

RISC-V RV32I execution engine
git clone git://mcdim.xyz/rvemu.git
Log | Files | Refs | README

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 }