~swisschili/toolchain-6502

a4f49b5a14bf5e119a66633813deab5f594ee239 — swissChili 3 months ago ca0d2e2
Fixed bug in assembler parser
6 files changed, 60 insertions(+), 23 deletions(-)

M .build.yml
M as/as.c
M as/test/test.s
M cpu.c
M csv2h.awk
M instructions.h
M .build.yml => .build.yml +1 -0
@@ 19,3 19,4 @@ tasks:
      ./6502 -h
artifacts:
  - 6502/build/6502
  - 6502/build/as/6502-as

M as/as.c => as/as.c +36 -17
@@ 60,14 60,16 @@ void print_inst(inst_t *arg)

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 @@ char *parse_label(char **code)

	skip_ws(code);

	if (**code == ':')
	if (*code != start && **code == ':')
	{
		**code = 0;
		(*code)++;


@@ 127,12 129,19 @@ char *parse_inst(char **code)
	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 @@ bool is_eol(char c)
{
	return c == ';' ||
		c == '\n' ||
		c == '\r' ||
		c == '\0';
}



@@ 388,16 396,26 @@ uint32_t assemble(char *code, FILE *out)
	{
		skip_ws(&line);

		printf("\033[36m%.9s\033[0m\n", line);
		printf("line: \033[36m%.12s\033[0m  ", 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);
		
		char *label = parse_label(&line),
			*mn = parse_inst(&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 @@ uint32_t assemble(char *code, FILE *out)
			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

M as/test/test.s => as/test/test.s +17 -0
@@ 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

M cpu.c => cpu.c +0 -5
@@ 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

M csv2h.awk => csv2h.awk +5 -1
@@ 5,6 5,10 @@ BEGIN {
	print "#define INSTRUCTIONS \\"
}

/0x.+/ {
/0x/ {
	print "	INST(" $2 ", AM_" $3 ", " $1", " $4 ") \\"
}

END {
    print ""
}

M instructions.h => instructions.h +1 -0
@@ 159,3 159,4 @@
	INST(STY, AM_ZP, 0x84, 2) \
	INST(STY, AM_ZPX, 0x94, 2) \
	INST(STY, AM_ABS, 0x8c, 3) \