Fixed bug in assembler parser
diff --git a/.build.yml b/.build.yml
index 8a0b0fd..12d430e 100644
--- a/.build.yml
+++ b/.build.yml
@@ -19,3 +19,4 @@
./6502 -h
artifacts:
- 6502/build/6502
+ - 6502/build/as/6502-as
diff --git a/as/as.c b/as/as.c
index 36d9637..5f0a001 100644
--- a/as/as.c
+++ b/as/as.c
@@ -60,14 +60,16 @@
bool is_ident(char c)
{
- return c && (isalpha(c) || isdigit(c));
+ return c && (isalpha(c) || isdigit(c)
+ || c == '_' || c == '-'
+ || c == '$' || c == '.');
}
uint32_t skip_ws(char **code)
{
uint32_t len = 0;
- for (; isspace(**code); (*code)++, len++)
+ for (; **code == ' ' || **code == '\t'; (*code)++, len++)
{}
return len;
@@ -108,7 +110,7 @@
skip_ws(code);
- if (**code == ':')
+ if (*code != start && **code == ':')
{
**code = 0;
(*code)++;
@@ -127,12 +129,19 @@
for (; isalpha(**code); (*code)++)
{}
- **code = 0;
-
if (start == *code)
return NULL;
- (*code)++;
+ // If code is incremented when it points to \0, it will wrap to the next line
+ // returned by strtok(), which causes a bug where instructions followed immediately
+ // by a newline and no arguments causes the next instruction to parse the entire
+ // program as its argument (not good)
+ if (**code)
+ {
+ **code = 0;
+ (*code)++;
+ }
+
return start;
}
@@ -140,7 +149,6 @@
{
return c == ';' ||
c == '\n' ||
- c == '\r' ||
c == '\0';
}
@@ -388,16 +396,26 @@
{
skip_ws(&line);
- printf("\033[36m%.9s\033[0m\n", line);
+ printf("line: \033[36m%.12s\033[0m ", line);
- char *label = parse_label(&line),
- *mn = parse_inst(&line);
+ char *label = parse_label(&line);
+ char *mn = parse_inst(&line);
+ printf(" skipping %d ", skip_ws(&line));
+ //printf("\033[33m%s\033[0m\n", line);
+
+ bool no_argument = false;
+ printf("eol is %c ($%x)\n", *line, *line);
+ if (is_eol(*line))
+ {
+ no_argument = true;
+ printf("... no argument\n");
+ }
int32_t mnemonic = -1;
if (label)
{
map_set(labels, label, (void *)pc);
- printf("Set label %s at %lu\n", label, pc);
+ printf("Set label %s at $%lx\n", label, pc);
}
if (mn)
@@ -416,12 +434,13 @@
inst_t arg;
// printf("Parsing '%s'\n", line);
#define INST(_mn, am, op, len) \
- if (mnemonic == _mn && parse_arg(line, am, &arg)) \
- { \
- arg.opcode = op; \
- pc += len; \
- print_inst(&arg); \
- } \
+ if ((no_argument && (_mn == AM_IMP || _mn == AM_ACC)) \
+ || (mnemonic == _mn && parse_arg(line, am, &arg))) \
+ { \
+ arg.opcode = op; \
+ pc += len; \
+ print_inst(&arg); \
+ } \
else
INSTRUCTIONS
diff --git a/as/test/test.s b/as/test/test.s
index edca24a..66ca095 100644
--- a/as/test/test.s
+++ b/as/test/test.s
@@ -1,5 +1,22 @@
+;;; This file is meant to test the parsing capabilities of the assembler.
+;;; It should contain every address mode to its parsing, as well as a
+;;; range of instructions to test.
+
+;;; When the assembler supports macros, those will be tested here as well.
+
start:
lda #$32 ; Store $32 in a
tax ; Transfer a to x
stx $200 ; Store x at $200
jmp ($FFAA) ; Jump to the address at $FFAA
+second_label:
+ lda $30, X
+ inc
+ adc #$3
+ bne start
+ jsr another_subroutine
+ tax
+ hlt
+
+another_subroutine:
+ ret
diff --git a/cpu.c b/cpu.c
index ce489cc..ef544a7 100644
--- a/cpu.c
+++ b/cpu.c
@@ -1,8 +1,6 @@
#include "cpu.h"
#include "common.h"
#include "instructions.h"
-#define SCREEN_ONLY_SDL
-#include "screen.h"
#include "dbg.h"
#include <errno.h>
@@ -16,9 +14,6 @@
printf("\033[33m" m "\033[0m\n", ##__VA_ARGS__);
-sdl_screen_t *g_scr = NULL;
-
-
void reset(cpu_t *cpu)
{
cpu->regs[SP] = 0xFF; // stack at is 0x100 + SP
diff --git a/csv2h.awk b/csv2h.awk
index dfebaec..368cc48 100755
--- a/csv2h.awk
+++ b/csv2h.awk
@@ -5,6 +5,10 @@
print "#define INSTRUCTIONS \\"
}
-/0x.+/ {
+/0x/ {
print " INST(" $2 ", AM_" $3 ", " $1", " $4 ") \\"
}
+
+END {
+ print ""
+}
diff --git a/instructions.h b/instructions.h
index 082016f..c2c18d0 100644
--- a/instructions.h
+++ b/instructions.h
@@ -159,3 +159,4 @@
INST(STY, AM_ZP, 0x84, 2) \
INST(STY, AM_ZPX, 0x94, 2) \
INST(STY, AM_ABS, 0x8c, 3) \
+