aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2023-05-03 21:06:25 +0100
committerJuan J. Martinez <jjm@usebox.net>2023-05-03 21:06:25 +0100
commit5fe9a6363cf75d842e1432ac42b3350a040aab26 (patch)
treede62a37b2ece7c8eb28406edce60640f031b24a2
parent0bf740232b8864d378c9557dc374dc1543a2cd99 (diff)
downloadtr8vm-5fe9a6363cf75d842e1432ac42b3350a040aab26.tar.gz
tr8vm-5fe9a6363cf75d842e1432ac42b3350a040aab26.zip
Add incbin and check memory overflow in output
-rw-r--r--README.md3
-rw-r--r--tr8as.c272
2 files changed, 148 insertions, 127 deletions
diff --git a/README.md b/README.md
index 18f474f..ce9f8de 100644
--- a/README.md
+++ b/README.md
@@ -228,6 +228,9 @@ Literal word.
.equ label imm
Define a label assigning an arbitrary immediate.
+.incbin "filename"
+Read the file and add the content to the output.
+
#### Load and Store
LD r1, r2
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 },