rtests.c (4978B)
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 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 } 62 }, 63 { 64 .name = "I-type immediates", 65 .program = { 66 0x00700513, // addi x10, x0, 7 67 0x00451513, // slli x10, x10, 4 68 0x00d50513, // addi x10, x10, 13 69 0x05554513, // xori x10, x10, 0x55 70 0xff750513, // addi x10, x10, -9 71 0x00100073 // ebreak 72 }, 73 .program_len = 6, 74 .exp = { 75 .x[10] = 0x0000001f, 76 .x_check_mask = (UINT32_C(1) << 10), 77 .pc = 0x14, 78 } 79 }, 80 { 81 .name = "basic loads and stores", 82 .program = { 83 0x00a00093, //li ra,10 84 0x00000113, //li sp,0 85 0x00100193, //li gp,1 86 0x00310133, //add sp,sp,gp 87 0x00118193, //addi gp,gp,1 88 0xfff08093, //addi ra,ra,-1 89 0xfe009ae3, //bnez ra,c <loop> 90 0x10000513, //li a0,256 91 0x00252023, //sw sp,0(a0) 92 0x00350223, //sb gp,4(a0) 93 0x00052203, //lw tp,0(a0) 94 0x00450283, //lb t0,4(a0) 95 0x00121313, //slli t1,tp,0x1 96 0x004343b3, //xor t2,t1,tp 97 0x03822413, //slti s0,tp,56 98 0xfff23493, //sltiu s1,tp,-1 99 0x00c005ef, //jal a1,4c <subroutine> 100 0x00c52423, //sw a2,8(a0) 101 0x00100073, //ebreak 102 0x00720613, //addi a2,tp,7 # 7 <_start+0x7> 103 0x00058067 //jr a1 104 }, 105 .program_len = 21, 106 .exp = { 107 .x = { 108 [0] = 0x00000000, 109 [1] = 0x00000000, 110 [2] = 0x00000037, 111 [3] = 0x0000000b, 112 [4] = 0x00000037, 113 [5] = 0x0000000b, 114 [6] = 0x0000006e, 115 [7] = 0x00000059, 116 [8] = 0x00000001, 117 [9] = 0x00000001, 118 [10] = 0x00000100, 119 [11] = 0x00000044, 120 [12] = 0x0000003e, 121 122 }, 123 .x_check_mask = ((UINT32_C(1) << 12) | 124 (UINT32_C(1) << 11) | 125 (UINT32_C(1) << 10) | 126 (UINT32_C(1) << 9) | 127 (UINT32_C(1) << 8) | 128 (UINT32_C(1) << 7) | 129 (UINT32_C(1) << 6) | 130 (UINT32_C(1) << 5) | 131 (UINT32_C(1) << 4) | 132 (UINT32_C(1) << 3) | 133 (UINT32_C(1) << 2) | 134 (UINT32_C(1) << 1) | 135 (UINT32_C(1))), 136 .pc = 0x48 137 } 138 }, 139 }; 140 141 static void 142 load_program(uint8_t *mem, uint32_t arr[], size_t len) 143 { 144 int b = 0; /*byte*/ 145 for (size_t i=0; i<len; i++) { 146 147 mem[b+0] = (uint8_t)(arr[i] >> 0); 148 mem[b+1] = (uint8_t)(arr[i] >> 8); 149 mem[b+2] = (uint8_t)(arr[i] >> 16); 150 mem[b+3] = (uint8_t)(arr[i] >> 24); 151 152 b+=4; 153 } 154 } 155 156 static void 157 print_trap(cpu_state_t *cpu) 158 { 159 if (cpu->status == CPU_TRAPPED) { 160 switch(cpu->trap.cause) { 161 case TRAP_EBREAK: 162 printf("Code reached breakpoint\n"); 163 break; 164 case TRAP_ECALL: 165 printf("Code ECALL\n"); 166 break; 167 case TRAP_ILLEGAL_INSTRUCTION: 168 printf("Illegal instruction\n"); 169 break; 170 case TRAP_INSTRUCTION_MISALIGNED: 171 printf("Instruction misaligned\n"); 172 break; 173 case TRAP_INSTRUCTION_ACCESS_FAULT: 174 printf("Instruction access fault\n"); 175 break; 176 case TRAP_NONE: 177 printf("No trap cause\n"); 178 break; 179 } 180 } 181 } 182 183 int 184 main() 185 { 186 size_t n = sizeof(tests) / sizeof(test_t); 187 188 int n_p = 0; 189 int n_f = 0; 190 for (size_t i=0; i<n; i++) { 191 192 cpu_state_t cpu = {0}; 193 uint8_t mem[MEMSIZE] = {0}; 194 195 load_program(mem, tests[i].program, tests[i].program_len); 196 197 /* fetch & run */ 198 while (1) { 199 cpu_step(&cpu, mem); 200 if (cpu.status == CPU_TRAPPED) { 201 break; 202 } 203 } 204 205 for (int j=0; j<32; j++) { 206 if ((UINT32_C(1) << j) == tests[i].exp.x_check_mask) { 207 if (cpu.x[j] != tests[i].exp.x[j]) { 208 tests[i].result = TEST_FAILURE; 209 printf( "bad register %d. Expected %x, got %x\n", 210 j, tests[i].exp.x[j], cpu.x[j]); 211 } 212 } 213 214 if (cpu.pc != tests[i].exp.pc) { 215 tests[i].result = TEST_FAILURE; 216 puts("bad pc\n"); 217 } 218 } 219 if (tests[i].result != TEST_FAILURE) { 220 printf("ok - %s (%zu)\n", tests[i].name, i); 221 n_p++; 222 } else { 223 printf("not ok - %s (%zu)\n ", tests[i].name, i); 224 print_trap(&cpu); 225 n_f++; 226 } 227 228 } 229 printf("\n%d passed, %d failed\n", n_p, n_f); 230 231 return 0; 232 }