lli

A small emulated asm like lang
Log | Files | Refs

lliasm.c (7613B)


      1 #include <stdlib.h>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <ctype.h>
      5 #include <unistd.h>
      6 #include <stdbool.h>
      7 
      8 #include "arg.h"
      9 char *argv0;
     10 #include "lli.h"
     11 
     12 #define SAME(s1, s2) (strcmp(s1, s2) == 0)
     13 
     14 struct dict {
     15 	char *label;
     16 	int address;
     17 } label_table[1024] = {
     18 };
     19 
     20 int label_count = 0;
     21 
     22 char buffer[INT16_MAX] = {0};
     23 int len = 0;
     24 
     25 bool commentmode = false;
     26 
     27 char *
     28 drainfile(FILE *f) {
     29 	char *contents; 
     30 
     31 	fseek(f, 0, SEEK_END);
     32 	int len = ftell(f);
     33 	rewind(f);
     34 
     35 	contents = malloc(len + 1);
     36 	contents[len] = 0;
     37 
     38 	fread(contents, 1, len, f);
     39 
     40 	return contents;
     41 }
     42 
     43 char 
     44 *stripcomments(char *in) {
     45 	int len = strlen(in);
     46 	char *out = malloc(len + 1);
     47 	int i = 0;
     48 	for (char *s = in; *s != 0; s++) {
     49 		if (*s == '(') {
     50 			do { s++; } while (*s != ')');
     51 			s++;
     52 		}
     53 		out[i] = *s;
     54 		i++;
     55 	}
     56 	out[len] = 0;
     57 	free(in);
     58 	return out;
     59 }
     60 
     61 char *
     62 readword(char *in) {
     63 	char *input;
     64 	if (!in) input = NULL;
     65 	else input = in;
     66 
     67 	char *tok = strtok(input, " \t\n\0");
     68 	while (tok && *tok && isblank(*tok)) tok++;
     69 	return tok;
     70 }
     71 
     72 tval *
     73 tokenize(char *word, int *size) {
     74 	tval *val = malloc(sizeof(tval));
     75 	struct dict label;
     76 	if (isdigit(word[1]) && (*word == 'b' || *word == 's' || *word == 'i')) {
     77 		for (char *c = word + 1; *c != 0; c++)
     78 			if (!isdigit(*c)) goto notnum;
     79 		if (*word == 'b') { 
     80 			val->type = BLIT;	
     81 			val->val = word + 1;
     82 			*size += sizeof(uint32_t);
     83 			return val;
     84 		}
     85 		else if (*word == 's') {
     86 			val->type = SLIT;	
     87 			val->val = word + 1;
     88 			*size += sizeof(uint16_t);
     89 			return val;
     90 		}
     91 		else if (*word == 'i') { 
     92 			val->type = ILIT;	
     93 			val->val = word + 1;
     94 			*size += sizeof(int);
     95 			return val;
     96 		}
     97 	}
     98 notnum:
     99 	if (*word == '\"') { /* hard coded string */
    100 		val->type = STRLIT;	
    101 		val->val = word + 1;
    102 		*size += strlen(word + 1);
    103 		return val;
    104 	}
    105 	else if (*word == '@') { /* label */
    106 		val->type = LABEL;	
    107 		val->val = word + 1;
    108 
    109 		label.label = val->val;
    110 		label.address = *size;
    111 
    112 		for (int i = 0; i < label_count; i++) {
    113 			if (SAME(label_table[i].label, val->val)) {
    114 				memcpy(&label_table[i], &label, sizeof(struct dict));
    115 				return val;
    116 			}
    117 		}
    118 
    119 		memcpy(&label_table[label_count], &label, sizeof(struct dict));
    120 		label_count++;
    121 		return val;
    122 	}
    123 	else if (*word == '|') { /* align data */ 
    124 		val->type = PAD;	
    125 		val->val = word + 1;
    126 		*size = strtol(word + 1, NULL, 0);
    127 		return val;
    128 	}
    129 	else if (*word == '#') { /* push int */
    130 		val->type = PUSH;	
    131 		val->val = word + 1;
    132 		*size += sizeof(int) + sizeof(uint8_t);
    133 		return val;
    134 	}
    135 	else if (*word == '&') { /* location of label */
    136 		val->type = PUSHA;	
    137 		val->val = word + 1;
    138 		*size += sizeof(int) + sizeof(uint8_t);
    139 
    140 		label.label = val->val;
    141 		label.address = 0;
    142 
    143 		for (int i = 0; i < label_count; i++) {
    144 			if (SAME(label_table[i].label, val->val)) 
    145 				return val;
    146 		}
    147 		memcpy(&label_table[label_count], &label, sizeof(struct dict));
    148 		label_count++;
    149 
    150 		return val;
    151 	}
    152 
    153 	/* removing data */
    154 	else if (SAME(word, "deli")) 
    155 		val->type = DELI;
    156 	else if (SAME(word, "dels")) 
    157 		val->type = DELS;
    158 	else if (SAME(word, "delb")) 
    159 		val->type = DELB;
    160 
    161 	/* loading data */
    162 	else if (SAME(word, "loadi")) 
    163 		val->type = LOADI;
    164 	else if (SAME(word, "loads")) 
    165 		val->type = LOADS;
    166 	else if (SAME(word, "loadb")) 
    167 		val->type = LOADB;
    168 
    169 	/* storing data */
    170 	else if (SAME(word, "storei")) 
    171 		val->type = STOREI;
    172 	else if (SAME(word, "stores")) 
    173 		val->type = STORES;
    174 	else if (SAME(word, "storeb")) 
    175 		val->type = STOREB;
    176 
    177 	/* dups */
    178 	else if (SAME(word, "dupi")) 
    179 		val->type = DUPI;
    180 	else if (SAME(word, "dups")) 
    181 		val->type = DUPS;
    182 	else if (SAME(word, "dupb")) 
    183 		val->type = DUPB;
    184 
    185 	/* jumps */
    186 	else if (SAME(word, "jmp")) 
    187 		val->type = JMP;
    188 	else if (SAME(word, "jnz")) 
    189 		val->type = JNZ;
    190 	else if (SAME(word, "call")) 
    191 		val->type = CALL;
    192 	else if (SAME(word, "callnz")) 
    193 		val->type = CALLNZ;
    194 	else if (SAME(word, "ret")) 
    195 		val->type = RET;
    196 
    197 	/* maths */
    198 	else if (SAME(word, "add")) 
    199 		val->type = ADD;
    200 	else if (SAME(word, "sub")) 
    201 		val->type = SUB;
    202 	else if (SAME(word, "div")) 
    203 		val->type = DIV;
    204 	else if (SAME(word, "mul")) 
    205 		val->type = MUL;
    206 	
    207 	/* casts */
    208 	else if (SAME(word, "b2s")) 
    209 		val->type = B2S;
    210 	else if (SAME(word, "b2i")) 
    211 		val->type = B2I;
    212 	else if (SAME(word, "s2b")) 
    213 		val->type = S2B;
    214 	else if (SAME(word, "s2i")) 
    215 		val->type = S2I;
    216 	else if (SAME(word, "i2b")) 
    217 		val->type = I2B;
    218 	else if (SAME(word, "i2s")) 
    219 		val->type = I2S;
    220 
    221 	/* comparisons */
    222 	else if (SAME(word, "equ")) 
    223 		val->type = EQU;
    224 	else if (SAME(word, "neq")) 
    225 		val->type = NEQ;
    226 	else if (SAME(word, "lt")) 
    227 		val->type = LT;
    228 	else if (SAME(word, "gt")) 
    229 		val->type = GT;
    230 	else if (SAME(word, "lte")) 
    231 		val->type = LTE;
    232 	else if (SAME(word, "gte")) 
    233 		val->type = GTE;
    234 
    235 	/* misc */
    236 	else if (SAME(word, "halt")) 
    237 		val->type = HALT;
    238 
    239 	else if (*word == 0) return NULL;
    240 	else {
    241 		fprintf(stderr, "Unknown cmd: %s\n", word);
    242 		exit(1);
    243 	}
    244 	*size += sizeof(uint8_t);
    245 	val->val = word;
    246 
    247 	return val;
    248 }
    249 
    250 int
    251 appendbuf(const void *data, int size) {
    252 	memcpy(&buffer[len], data, size);
    253 	len += size;
    254 	return size;
    255 }
    256 
    257 int
    258 compile(tval *val, int bytesdeep) {
    259 	if (!val) return bytesdeep;
    260 	uint32_t ilit, ZERO = 0;
    261 	uint16_t u16lit;
    262 	uint8_t u8lit;
    263 	struct dict label = {val->val, bytesdeep};
    264 	switch (val->type) {
    265 	case BLIT: 
    266 		u8lit = strtol(val->val, NULL, 0);
    267 		bytesdeep += appendbuf(&u8lit, sizeof(uint8_t));
    268 		break;
    269 	case SLIT: 
    270 		u16lit = strtol(val->val, NULL, 0);
    271 		bytesdeep += appendbuf(&u16lit, sizeof(uint16_t));
    272 		break;
    273 	case ILIT: 
    274 		ilit = strtol(val->val, NULL, 0);
    275 		bytesdeep += appendbuf(&ilit, sizeof(int));
    276 		break;
    277 	case STRLIT: 
    278 		bytesdeep += appendbuf(val->val, strlen(val->val));
    279 		break;
    280 	case LABEL: 
    281 		memcpy(&label_table[label_count], &label, sizeof(struct dict));
    282 		label_count++;
    283 		break;
    284 	case PAD:
    285 		while (bytesdeep != strtol(val->val, NULL, 0)) 
    286 			bytesdeep += appendbuf(&ZERO, 1);
    287 		break;
    288 	case PUSH:
    289 		u8lit = (uint8_t)val->type;
    290 		bytesdeep += appendbuf(&u8lit, sizeof(uint8_t));
    291 		ilit = strtol(val->val, NULL, 0);
    292 		bytesdeep += appendbuf(&ilit, sizeof(int));
    293 		break;
    294 	case PUSHA:
    295 		u8lit = (uint8_t)val->type;
    296 		bytesdeep += appendbuf(&u8lit, sizeof(uint8_t));
    297 
    298 		for (int i = 0; i < label_count; i++) {
    299 			if (SAME(label_table[i].label , val->val))
    300 				ilit = label_table[i].address;
    301 		}
    302 		bytesdeep += appendbuf(&ilit, sizeof(int));
    303 		break;
    304 	default:
    305 		u8lit = (uint8_t)val->type;
    306 		bytesdeep += appendbuf(&u8lit, sizeof(uint8_t));
    307 		break;
    308 	}
    309 		
    310 	return bytesdeep;
    311 }
    312 
    313 void
    314 usage() {
    315 	fprintf(stderr, "usage: %s [-ch] [-o out] in.ll\n", argv0);
    316 	exit(1);
    317 }
    318 
    319 int
    320 main(int argc, char **argv) {
    321 	FILE *in, *out;
    322 	ARGBEGIN {
    323 		case 'c': commentmode = true; break;
    324 		case 'h': usage(); break;
    325 		case 'o': 
    326 			  out = fopen(EARGF(usage), "wb");
    327 			  if (!out) {
    328 				  perror("failed to open output");
    329 				  return 1;
    330 			  }
    331 			  break;
    332 		default: usage();
    333 	} ARGEND;
    334 
    335 	if (!*argv) usage();
    336 	if (!(in = fopen(*argv, "r"))) {
    337 		perror("failed to open input");
    338 		return 1;
    339 	}
    340 	if (!out) {
    341 		if (commentmode) out = stdout;
    342 		else out = fopen("a.rom", "wb");
    343 	}
    344 	argv++;
    345 	if (*argv) usage();
    346 
    347 
    348 	int size;
    349 	char *input = stripcomments(drainfile(in)), *swp = strdup(input), *tmp = input;
    350 	if (commentmode) {
    351 		fprintf(out, "%s", input);
    352 		return 0;
    353 	}
    354 	char *word;
    355 	tval *val;
    356 	int bytesdeep;
    357 
    358 again:
    359 	size = 0;
    360 	word = readword(tmp);
    361 	val = tokenize(word, &size);
    362 	if (tmp != input) bytesdeep = compile(val, 0);
    363 
    364 	while ((word = readword(NULL))) {
    365 		val = tokenize(word, &size);
    366 		if (tmp != input) bytesdeep = compile(val, bytesdeep);
    367 	}
    368 
    369 	if (tmp != swp) {
    370 		tmp = swp;
    371 		goto again;
    372 	}
    373 
    374 	fwrite(buffer, 1, len, out);
    375 
    376 	fclose(out);
    377 	free(input);
    378 	free(swp);
    379 
    380 	return 0;
    381 }