lli

A small emulated asm like lang
Log | Files | Refs

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 }