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 }