lli.c (7530B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <stdbool.h> 5 #include <dlfcn.h> 6 7 #include "arg.h" 8 char *argv0; 9 #include "lli.h" 10 11 #define mkpop(type) \ 12 type pop_##type(stack *s) {\ 13 if (s->sptr == s->arr) \ 14 errormsg("Stack underflow"); \ 15 s->sptr -= sizeof(type); \ 16 return *(type *)s->sptr; \ 17 } 18 19 #define mkpeek(type) \ 20 type peek_##type(stack *s) {\ 21 if (s->sptr == s->arr) \ 22 errormsg("Stack underflow"); \ 23 return *(type *)(s->sptr - sizeof(type)); \ 24 } 25 26 27 #define mkpush(type) \ 28 type push_##type(stack *s, type *v) { \ 29 if (((s->sptr + sizeof(type)) - s->arr) > s->cap) \ 30 errormsg("Stack overflow"); \ 31 memcpy(s->sptr, v, sizeof(type)); \ 32 s->sptr += sizeof(type); \ 33 } 34 35 #define SAME(s1, s2) (strcmp(s1, s2) == 0) 36 37 bool debug = false; 38 39 mkpop(uint32_t); 40 mkpop(uint16_t); 41 mkpop(uint8_t); 42 43 mkpeek(uint32_t); 44 mkpeek(uint16_t); 45 mkpeek(uint8_t); 46 47 mkpush(uint32_t); 48 mkpush(uint16_t); 49 mkpush(uint8_t); 50 51 void *corehandles[8] = {0}; 52 void (*onread[8])(char *, char *); 53 void (*onwrite[8])(char *); 54 int (*getsize[8])(); 55 int address[8] = {0}; 56 int corecount = 0; 57 58 char memory[INT32_MAX] = {0}; 59 char *pc = &memory[0x1000]; 60 61 void 62 debug_console(stack *s, stack *cs) { 63 char word[64]; 64 for (;;) { 65 memset(word, 0, 64); 66 printf("(0x%x) ", pc - memory); 67 scanf("%s", word); 68 while (getchar() != '\n') continue; 69 if (SAME(word, "stack") || SAME(word, "s")) { 70 if ((s->sptr - s->arr) == 0) 71 fprintf(stderr, "Stack is empty\n"); 72 else { 73 for (int i = 0; i < (s->sptr - s->arr); i++) 74 printf("%d: 0x%x %d\n", i, s->arr[i], s->arr[i]); 75 } 76 } 77 else if (SAME(word, "print") || SAME(word, "p")) { 78 if ((s->sptr - s->arr) == 0) 79 fprintf(stderr, "Stack is empty\n"); 80 else 81 printf("0x%x %d\n", *(s->sptr - 1) , *(s->sptr - 1)); 82 } 83 else if (SAME(word, "next") || SAME(word, "n")) 84 return; 85 else if (SAME(word, "quit") || SAME(word, "q")) 86 exit(0); 87 else 88 fprintf(stderr, "unknown cmd\n"); 89 } 90 } 91 92 void 93 lliexec() { 94 stack s = { 95 .cap = 512, 96 .arr = malloc(512), 97 }; 98 s.sptr = s.arr; 99 100 stack cs = { 101 .cap = 512, 102 .arr = malloc(512), 103 }; 104 cs.sptr = cs.arr; 105 106 107 step: 108 if (debug) 109 debug_console(&s, &cs); 110 111 uint8_t opcode = *(uint8_t *)pc, val8; 112 uint16_t val16; 113 uint32_t loc, val32, operand1, operand2; 114 115 switch (opcode) { 116 117 case LOADB: 118 case LOADS: 119 case LOADI: 120 loc = pop_uint32_t(&s); 121 for (int i = 0; i < corecount; i++) 122 onread[i](&memory[address[i]], &memory[loc]); 123 switch (opcode) { 124 case LOADB: push_uint8_t(&s, (void*)&memory[loc]); break; 125 case LOADS: push_uint16_t(&s, (void*)&memory[loc]); break; 126 case LOADI: push_uint32_t(&s, (void*)&memory[loc]); break; 127 } 128 break; 129 130 case STOREB: 131 case STORES: 132 case STOREI: 133 loc = pop_uint32_t(&s); 134 switch (opcode) { 135 case STOREB: 136 val8 = pop_uint8_t(&s); 137 memcpy(&memory[loc], &val8, sizeof(uint8_t)); 138 break; 139 case STORES: 140 val16 = pop_uint16_t(&s); 141 memcpy(&memory[loc], &val16, sizeof(uint16_t)); 142 break; 143 case STOREI: 144 val32 = pop_uint32_t(&s); 145 memcpy(&memory[loc], &val32, sizeof(uint32_t)); 146 break; 147 } 148 for (int i = 0; i < corecount; i++) 149 onwrite[i](&memory[address[i]]); 150 break; 151 152 case DUPB: 153 case DUPS: 154 case DUPI: 155 switch (opcode) { 156 case DUPB: 157 val8 = peek_uint8_t(&s); 158 push_uint8_t(&s, &val8); 159 break; 160 case DUPS: 161 val16 = peek_uint16_t(&s); 162 push_uint16_t(&s, &val16); 163 break; 164 case DUPI: 165 val32 = peek_uint32_t(&s); 166 push_uint32_t(&s, &val32); 167 break; 168 } 169 break; 170 171 172 case JMP: 173 loc = pop_uint32_t(&s); 174 pc = &memory[loc]; 175 goto step; 176 case JNZ: 177 loc = pop_uint32_t(&s); 178 val8 = pop_uint8_t(&s); 179 if (!val8) break; 180 pc = &memory[loc]; 181 goto step; 182 case CALL: 183 loc = pop_uint32_t(&s); 184 val32 = (pc - &memory[0]) + 1; 185 push_uint32_t(&cs, &val32); 186 pc = &memory[loc]; 187 goto step; 188 case CALLNZ: 189 loc = pop_uint32_t(&s); 190 val8 = pop_uint8_t(&s); 191 if (!val8) break; 192 val32 = (pc - &memory[0]) + 1; 193 push_uint32_t(&cs, &val32); 194 pc = &memory[loc]; 195 goto step; 196 197 case RET: 198 pc = &memory[pop_uint32_t(&cs)]; 199 goto step; 200 201 case PUSHA: 202 case PUSH: 203 pc++; 204 push_uint32_t(&s, (uint32_t *)pc); 205 pc += sizeof(uint32_t); 206 goto step; 207 208 case ADD: 209 case SUB: 210 case DIV: 211 case MUL: 212 case EQU: 213 case NEQ: 214 case LT: 215 case GT: 216 case LTE: 217 case GTE: 218 operand2 = pop_uint32_t(&s); 219 operand1 = pop_uint32_t(&s); 220 switch (opcode) { 221 case ADD: 222 val32 = operand1 + operand2; 223 push_uint32_t(&s, &val32); 224 break; 225 case SUB: 226 val32 = operand1 - operand2; 227 push_uint32_t(&s, &val32); 228 break; 229 case DIV: 230 val32 = operand1 / operand2; 231 push_uint32_t(&s, &val32); 232 break; 233 case MUL: 234 val32 = operand1 * operand2; 235 push_uint32_t(&s, &val32); 236 break; 237 238 case EQU: 239 val8 = (operand1 == operand2); 240 push_uint8_t(&s, &val8); 241 break; 242 case NEQ: 243 val8 = (operand1 != operand2); 244 push_uint8_t(&s, &val8); 245 break; 246 case LT: 247 val8 = (operand1 < operand2); 248 push_uint8_t(&s, &val8); 249 break; 250 case GT: 251 val8 = (operand1 < operand2); 252 push_uint8_t(&s, &val8); 253 break; 254 case LTE: 255 val8 = (operand1 <= operand2); 256 push_uint8_t(&s, &val8); 257 break; 258 case GTE: 259 val8 = (operand1 <= operand2); 260 push_uint8_t(&s, &val8); 261 break; 262 } 263 break; 264 265 case B2S: 266 case B2I: 267 val8 = pop_uint8_t(&s); 268 switch (opcode) { 269 case B2S: val16 = val8; push_uint16_t(&s, &val16); break; 270 case B2I: val32 = val8; push_uint32_t(&s, &val32); break; 271 } 272 break; 273 case S2B: 274 case S2I: 275 val16 = pop_uint16_t(&s); 276 switch (opcode) { 277 case S2B: val8 = (uint8_t)val16; push_uint8_t(&s, &val8); break; 278 case S2I: val32 = val16; push_uint32_t(&s, &val32); break; 279 } 280 break; 281 case I2B: 282 case I2S: 283 val32 = pop_uint32_t(&s); 284 switch (opcode) { 285 case I2B: val8 = (uint8_t)val32; push_uint8_t(&s, &val8); break; 286 case I2S: val16 = (uint16_t)val32; push_uint16_t(&s, &val16); break; 287 } 288 break; 289 290 291 case HALT: goto end; 292 case DELB: pop_uint8_t(&s); break; 293 case DELS: pop_uint16_t(&s); break; 294 case DELI: pop_uint32_t(&s); break; 295 } 296 pc++; 297 goto step; 298 299 end: 300 free(s.arr); 301 free(cs.arr); 302 } 303 304 void 305 usage() { 306 fprintf(stderr, "usage: %s [-dh] [-c core address] file\n", argv0); 307 exit(1); 308 } 309 310 int 311 main(int argc, char **argv) { 312 FILE *f; 313 int len, pos = 0; 314 char *tmp; 315 ARGBEGIN { 316 case 'd': debug = true; break; 317 case 'h': usage(); break; 318 case 'c': 319 corehandles[corecount] = dlopen(EARGF(usage()), RTLD_LAZY); 320 argv++; 321 if (!corehandles[corecount]) { 322 fprintf(stderr, "%s\n", dlerror()); 323 exit(1); 324 } 325 tmp = *argv; 326 if (!tmp) usage(); 327 address[corecount] = strtol(tmp, NULL, 0); 328 if (!(onread[corecount] = dlsym(corehandles[corecount], "onread"))) { 329 fprintf(stderr, "failed to open function: onread\n"); 330 exit(1); 331 } 332 if (!(onwrite[corecount] = dlsym(corehandles[corecount], "onwrite"))) { 333 fprintf(stderr, "failed to open function: onwrite\n"); 334 exit(1); 335 } 336 if (!(getsize[corecount] = dlsym(corehandles[corecount], "getsize"))) { 337 fprintf(stderr, "failed to open function: getsize\n"); 338 exit(1); 339 } 340 if (address[corecount] < pos - 1) { 341 fprintf(stderr, "failed to load core: alignment is not possible\n"); 342 exit(1); 343 } 344 pos += getsize[corecount](); 345 corecount++; 346 347 break; 348 default: usage(); 349 } ARGEND; 350 351 if (!*argv) 352 usage(); 353 354 f = fopen(*argv, "rb"); 355 if (!f) { 356 perror("failed to open file"); 357 exit(1); 358 } 359 argv++; 360 if (*argv) usage(); 361 362 363 fseek(f, 0, SEEK_END); 364 len = ftell(f); 365 rewind(f); 366 367 368 if (len > INT32_MAX) exit(1); 369 fread(memory, 1, INT32_MAX, f); 370 fclose(f); 371 372 lliexec(); 373 }