From 5fe9a6363cf75d842e1432ac42b3350a040aab26 Mon Sep 17 00:00:00 2001 From: "Juan J. Martinez" Date: Wed, 3 May 2023 21:06:25 +0100 Subject: Add incbin and check memory overflow in output --- tr8as.c | 272 ++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 145 insertions(+), 127 deletions(-) (limited to 'tr8as.c') diff --git a/tr8as.c b/tr8as.c index 6c9bd27..5b525ba 100644 --- a/tr8as.c +++ b/tr8as.c @@ -84,7 +84,7 @@ typedef struct typedef struct { - char id[5]; + char id[7]; uint8_t (*parse)(As *, char *); } InstParse; @@ -110,6 +110,29 @@ static char * skip_whitespace(char *c) return c; } +static char * next_string(char *c, char *word, uint8_t *wlen) +{ + c = skip_whitespace(c); + + *wlen = 0; + if (*c != '"') + return c; + c++; + + while (*c && *c != '"') + { + word[(*wlen)++] = *c++; + if (*wlen == MAX_ID) + { + *wlen = 0; + break; + } + } + word[*wlen] = 0; + + return c + 1; +} + static uint8_t isspecial(char c) { return c == '$' || c == '_' || c == '.' || c == '#' || c == '<' || c == '>'; @@ -313,20 +336,30 @@ static uint8_t resolve(As *as) * p2: either FHx or r2 * p3: either FL, r3 or immediate */ -static void emit(As *as, uint8_t instr, uint8_t p1, uint8_t p2, uint8_t p3) +static uint8_t emit(As *as, uint8_t instr, uint8_t p1, uint8_t p2, uint8_t p3) { + if (as->addr + 2 > UINT16_MAX) + return error_l("Memory overflow", &as->loc, "output is more than 65535 bytes"); + as->out[as->addr++] = p3; as->out[as->addr++] = (instr << 4) | (p1 << 2) | p2; if (as->addr > as->size) as->size = as->addr; + + return 1; } -static void emit_imm(As *as, uint16_t imm) +static uint8_t emit_imm(As *as, uint16_t imm) { + if (as->addr + 2 > UINT16_MAX) + return error_l("Memory overflow", &as->loc, "output is more than 65535 bytes"); + as->out[as->addr++] = imm & 0xff; as->out[as->addr++] = imm >> 8; if (as->addr > as->size) as->size = as->addr; + + return 1; } static uint8_t parse_org(As *as, char *c) @@ -349,6 +382,51 @@ static uint8_t parse_org(As *as, char *c) return 1; } +static uint8_t parse_incbin(As *as, char *c) +{ + /* XXX: may be support longer filenames */ + char word[MAX_ID + 1]; + uint8_t wlen; + FILE *fd; + size_t size; + + /* .incbin "filename" */ + + next_string(c, word, &wlen); + if (wlen == 0) + return error_l("Syntax error", &as->loc, "expected string"); + + fd = fopen(word, "rb"); + if (!fd) + { + error_l("Failed to open incbin", &as->loc, word); + return 1; + } + + fseek(fd, 0, SEEK_END); + size = ftell(fd); + if (size + as->addr > UINT16_MAX) + { + fclose(fd); + error_l("Overflow in incbin", &as->loc, word); + return 1; + } + fseek(fd, 0, SEEK_SET); + if (fread(as->out + as->addr, 1, size, fd) != size) + { + fclose(fd); + error_l("Read error in incbin", &as->loc, word); + return 1; + } + fclose(fd); + + as->addr += size; + if (as->addr > as->size) + as->size = as->addr; + + return 1; +} + static uint8_t parse_equ(As *as, char *c) { char label[MAX_ID + 1]; @@ -458,71 +536,61 @@ static uint8_t parse_dw(As *as, char *c) static uint8_t parse_nop(As *as, char *c) { /* NOP */ - emit(as, 0, 0, 0, 0); - return 1; + return emit(as, 0, 0, 0, 0); } static uint8_t parse_sif(As *as, char *c) { /* SIF */ - emit(as, 11, 0, FHL, 0); - return 1; + return emit(as, 11, 0, FHL, 0); } static uint8_t parse_cif(As *as, char *c) { /* CIF */ - emit(as, 11, 0, 0, 0); - return 1; + return emit(as, 11, 0, 0, 0); } static uint8_t parse_ccf(As *as, char *c) { /* CCF */ - emit(as, 13, 0, FHH | FHL, 0); - return 1; + return emit(as, 13, 0, FHH | FHL, 0); } static uint8_t parse_scf(As *as, char *c) { /* SCF */ - emit(as, 13, 0, FHH, 0); - return 1; + return emit(as, 13, 0, FHH, 0); } static uint8_t parse_sof(As *as, char *c) { /* SOF */ - emit(as, 13, 0, FHL, 0); - return 1; + return emit(as, 13, 0, FHL, 0); } static uint8_t parse_cof(As *as, char *c) { /* COF */ - emit(as, 13, 0, 0, 0); - return 1; + return emit(as, 13, 0, 0, 0); } static uint8_t parse_halt(As *as, char *c) { /* HALT */ - emit(as, 0, 0, FHH | FHL, 0); - return 1; + return emit(as, 0, 0, FHH | FHL, 0); } static uint8_t parse_iret(As *as, char *c) { /* IRET */ - emit(as, 0, 0, FHL, 0); - return 1; + return emit(as, 0, 0, FHL, 0); } static uint8_t parse_ret(As *as, char *c) { /* RET */ - emit(as, 0, 0, 0, FL); - return 1; + return emit(as, 0, 0, 0, FL); } static uint8_t parse_r1_r2_or_imm(As *as, char *c, uint8_t *r1, uint8_t *r2, uint16_t *imm) @@ -613,12 +681,10 @@ static uint8_t parse_and(As *as, char *c) if (r2 != 0xff) /* AND r1, r2 */ - emit(as, 4, r1, FHH | FHL, (r2 << 6)); - else - /* AND r1, imm */ - emit(as, 4, r1, FHH, imm); + return emit(as, 4, r1, FHH | FHL, (r2 << 6)); - return 1; + /* AND r1, imm */ + return emit(as, 4, r1, FHH, imm); } static uint8_t parse_or(As *as, char *c) @@ -631,12 +697,10 @@ static uint8_t parse_or(As *as, char *c) if (r2 != 0xff) /* OR r1, r2 */ - emit(as, 4, r1, FHL, (r2 << 6)); - else - /* OR r1, imm */ - emit(as, 4, r1, 0, imm); + return emit(as, 4, r1, FHL, (r2 << 6)); - return 1; + /* OR r1, imm */ + return emit(as, 4, r1, 0, imm); } static uint8_t parse_xor(As *as, char *c) @@ -649,12 +713,10 @@ static uint8_t parse_xor(As *as, char *c) if (r2 != 0xff) /* XOR r1, r2 */ - emit(as, 5, r1, FHH | FHL, (r2 << 6)); - else - /* XOR r1, imm */ - emit(as, 5, r1, FHH, imm); + return emit(as, 5, r1, FHH | FHL, (r2 << 6)); - return 1; + /* XOR r1, imm */ + return emit(as, 5, r1, FHH, imm); } static uint8_t parse_cmp(As *as, char *c) @@ -667,12 +729,10 @@ static uint8_t parse_cmp(As *as, char *c) if (r2 != 0xff) /* CMP r1, r2 */ - emit(as, 5, r1, FHL, (r2 << 6)); - else - /* CMP r1, imm */ - emit(as, 5, r1, 0, imm); + return emit(as, 5, r1, FHL, (r2 << 6)); - return 1; + /* CMP r1, imm */ + return emit(as, 5, r1, 0, imm); } static uint8_t parse_add(As *as, char *c) @@ -685,12 +745,10 @@ static uint8_t parse_add(As *as, char *c) if (r2 != 0xff) /* ADD r1, r2 */ - emit(as, 6, r1, FHH | FHL, (r2 << 6)); - else - /* ADD r1, imm */ - emit(as, 6, r1, FHH, imm); + return emit(as, 6, r1, FHH | FHL, (r2 << 6)); - return 1; + /* ADD r1, imm */ + return emit(as, 6, r1, FHH, imm); } static uint8_t parse_sub(As *as, char *c) @@ -703,12 +761,10 @@ static uint8_t parse_sub(As *as, char *c) if (r2 != 0xff) /* SUB r1, r2 */ - emit(as, 6, r1, FHL, (r2 << 6)); - else - /* SUB r1, imm */ - emit(as, 6, r1, 0, imm); + return emit(as, 6, r1, FHL, (r2 << 6)); - return 1; + /* SUB r1, imm */ + return emit(as, 6, r1, 0, imm); } static uint8_t parse_bit(As *as, char *c) @@ -723,8 +779,7 @@ static uint8_t parse_bit(As *as, char *c) if (imm > 7) return error_l("Immediate out of range", &as->loc, "expected bit (0-7)"); - emit(as, 7, r1, FHH, imm); - return 1; + return emit(as, 7, r1, FHH, imm); } static uint8_t parse_shl(As *as, char *c) @@ -739,8 +794,7 @@ static uint8_t parse_shl(As *as, char *c) if (imm > 7) return error_l("Immediate out of range", &as->loc, "expected bit (0-7)"); - emit(as, 7, r1, FHL, imm); - return 1; + return emit(as, 7, r1, FHL, imm); } static uint8_t parse_shr(As *as, char *c) @@ -755,8 +809,7 @@ static uint8_t parse_shr(As *as, char *c) if (imm > 7) return error_l("Immediate out of range", &as->loc, "expected bit (0-7)"); - emit(as, 7, r1, 0, imm); - return 1; + return emit(as, 7, r1, 0, imm); } static uint8_t parse_ror(As *as, char *c) @@ -771,8 +824,7 @@ static uint8_t parse_ror(As *as, char *c) if (imm > 7) return error_l("Immediate out of range", &as->loc, "expected bit (0-7)"); - emit(as, 8, r1, 0, imm); - return 1; + return emit(as, 8, r1, 0, imm); } static uint8_t parse_rol(As *as, char *c) @@ -787,8 +839,7 @@ static uint8_t parse_rol(As *as, char *c) if (imm > 7) return error_l("Immediate out of range", &as->loc, "expected bit (0-7)"); - emit(as, 8, r1, FHH, imm); - return 1; + return emit(as, 8, r1, FHH, imm); } static uint8_t parse_push(As *as, char *c) @@ -807,15 +858,11 @@ static uint8_t parse_push(As *as, char *c) { /* PUSH F */ if (*word == 'f' || *word == 'F') - { - emit(as, 3, 0, FHH | FHL, 0); - return 1; - } + return emit(as, 3, 0, FHH | FHL, 0); return error_l("Syntax error", &as->loc, word); } - emit(as, 3, r1, FHL, 0); - return 1; + return emit(as, 3, r1, FHL, 0); } static uint8_t parse_port(As *as, char *c) @@ -841,8 +888,7 @@ static uint8_t parse_port(As *as, char *c) if (r2 == 0xff) return error_l("Syntax error", &as->loc, word); - emit(as, 0, r1, FHH, r2); - return 1; + return emit(as, 0, r1, FHH, r2); } static uint8_t parse_pop(As *as, char *c) @@ -861,15 +907,11 @@ static uint8_t parse_pop(As *as, char *c) { /* POP F */ if (*word == 'f' || *word == 'F') - { - emit(as, 3, 0, FHH, 0); - return 1; - } + return emit(as, 3, 0, FHH, 0); return error_l("Syntax error", &as->loc, word); } - emit(as, 3, r1, 0, 0); - return 1; + return emit(as, 3, r1, 0, 0); } static uint8_t parse_xsp(As *as, char *c) @@ -887,8 +929,7 @@ static uint8_t parse_xsp(As *as, char *c) if (r1 == 0xff) return error_l("Syntax error", &as->loc, word); - emit(as, 3, r1, 0, FL); - return 1; + return emit(as, 3, r1, 0, FL); } static uint8_t parse_inc(As *as, char *c) @@ -906,8 +947,7 @@ static uint8_t parse_inc(As *as, char *c) if (r1 == 0xff) return error_l("Syntax error", &as->loc, word); - emit(as, 11, r1, FHH | FHL, 0); - return 1; + return emit(as, 11, r1, FHH | FHL, 0); } static uint8_t parse_dec(As *as, char *c) @@ -925,78 +965,67 @@ static uint8_t parse_dec(As *as, char *c) if (r1 == 0xff) return error_l("Syntax error", &as->loc, word); - emit(as, 11, r1, FHH, 0); - return 1; + return emit(as, 11, r1, FHH, 0); } static uint8_t parse_bz(As *as, char *c) { /* BZ */ - emit(as, 10, 0, 0, 0); - return 1; + return emit(as, 10, 0, 0, 0); } static uint8_t parse_bnz(As *as, char *c) { /* BNZ */ - emit(as, 10, 0, FHH, 0); - return 1; + return emit(as, 10, 0, FHH, 0); } static uint8_t parse_bc(As *as, char *c) { /* BC */ - emit(as, 10, 0, 0, 1); - return 1; + return emit(as, 10, 0, 0, 1); } static uint8_t parse_bnc(As *as, char *c) { /* BNC */ - emit(as, 10, 0, FHH, 1); - return 1; + return emit(as, 10, 0, FHH, 1); } static uint8_t parse_bo(As *as, char *c) { /* BO */ - emit(as, 10, 0, 0, 2); - return 1; + return emit(as, 10, 0, 0, 2); } static uint8_t parse_bno(As *as, char *c) { /* BNO */ - emit(as, 10, 0, FHH, 2); - return 1; + return emit(as, 10, 0, FHH, 2); } static uint8_t parse_bs(As *as, char *c) { /* BS */ - emit(as, 10, 0, 0, 3); - return 1; + return emit(as, 10, 0, 0, 3); } static uint8_t parse_bns(As *as, char *c) { /* BNS */ - emit(as, 10, 0, FHH, 3); - return 1; + return emit(as, 10, 0, FHH, 3); } static uint8_t parse_bi(As *as, char *c) { /* BI */ - emit(as, 10, 0, 0, 4); - return 1; + return emit(as, 10, 0, 0, 4); } static uint8_t parse_bni(As *as, char *c) { /* BNI */ - emit(as, 10, 0, FHH, 4); - return 1; + return emit(as, 10, 0, FHH, 4); } static uint8_t parse_indirect(As *as, char **c, uint8_t *r1, uint8_t *r2, uint16_t *imm) @@ -1084,8 +1113,7 @@ static uint8_t parse_jmp(As *as, char *c) if (!parse_indirect(as, &pt, &r1, &r2, NULL)) return 0; - emit(as, 9, r1, 0, (r2 << 6) | FL); - return 1; + return emit(as, 9, r1, 0, (r2 << 6) | FL); } next_word(pt, word, &wlen); @@ -1102,9 +1130,7 @@ static uint8_t parse_jmp(As *as, char *c) else if (!new_ref(as, word, 0xffff, as->addr + 2)) return 0; - emit(as, 9, 0, FHH, FL); - emit_imm(as, imm); - return 1; + return (emit(as, 9, 0, FHH, FL) && emit_imm(as, imm)); } static uint8_t parse_call(As *as, char *c) @@ -1124,8 +1150,7 @@ static uint8_t parse_call(As *as, char *c) if (!parse_indirect(as, &pt, &r1, &r2, NULL)) return 0; - emit(as, 9, r1, 0, (r2 << 6)); - return 1; + return emit(as, 9, r1, 0, (r2 << 6)); } next_word(pt, word, &wlen); @@ -1142,9 +1167,7 @@ static uint8_t parse_call(As *as, char *c) else if (!new_ref(as, word, 0xffff, as->addr + 2)) return 0; - emit(as, 9, 0, FHH, 0); - emit_imm(as, imm); - return 1; + return (emit(as, 9, 0, FHH, 0) && emit_imm(as, imm)); } static uint8_t parse_ld(As *as, char *c) @@ -1179,10 +1202,9 @@ static uint8_t parse_ld(As *as, char *c) return error_l("Syntax error", &as->loc, word); if (r1 == 0xff) - emit(as, 12, r3, FHH, imm); - else - emit(as, 2, r1, r2, (r3 << 6) | FL); - return 1; + return emit(as, 12, r3, FHH, imm); + + return emit(as, 2, r1, r2, (r3 << 6) | FL); } /* LD r1, ? */ @@ -1209,10 +1231,9 @@ static uint8_t parse_ld(As *as, char *c) return 0; if (r2 == 0xff) - emit(as, 12, r1, 0, imm); - else - emit(as, 2, r2, r3, r1 << 6); - return 1; + return emit(as, 12, r1, 0, imm); + + return emit(as, 2, r2, r3, r1 << 6); } pt = next_word(pt, word, &wlen); @@ -1222,10 +1243,7 @@ static uint8_t parse_ld(As *as, char *c) /* LD r1, r2 */ r2 = parse_register(word); if (r2 != 0xff) - { - emit(as, 1, r1, FHH, (r2 << 6)); - return 1; - } + return emit(as, 1, r1, FHH, (r2 << 6)); /* LD r1, imm */ if (isdigit(*word)) @@ -1240,11 +1258,11 @@ static uint8_t parse_ld(As *as, char *c) else if (!new_ref(as, word, 0xff, as->addr)) return 0; - emit(as, 1, r1, 0, imm); - return 1; + return emit(as, 1, r1, 0, imm); } static InstParse insts[] = { + { ".incbin", parse_incbin }, { ".org", parse_org }, { ".equ", parse_equ }, { ".db", parse_db }, -- cgit v1.2.3