M as/CMakeLists.txt => as/CMakeLists.txt +1 -1
@@ 13,6 13,6 @@ else()
endif()
-add_executable(6502-as main.c as.h as.c map.h map.c hash.c hash.c)
+add_executable(6502-as main.c as.h as.c pp.c map.h map.c hash.c hash.c)
install(TARGETS 6502-as)
M as/as.c => as/as.c +6 -6
@@ 20,9 20,6 @@ enum
ARG_IMP, /* Implied argument */
};
-#define ERR "\033[31m"
-#define GREEN "\033[32m"
-#define RESET "\033[0m"
#define MAX_LEN (0xFFFF - 0x600)
#define MAX_INSTS (MAX_LEN / 2)
@@ 583,7 580,8 @@ uint32_t assemble(char *code, FILE *out)
uint16_t lbl;
if (!(lbl = ll_find(last_node, insts[i]->label)))
{
- printf(ERR "Error on line %d: label '%s' is not defined" RESET "\n", insts[i]->line, insts[i]->label);
+ printf(ERR "Error on line %d: label '%s' is not defined" RESET "\n",
+ insts[i]->line, insts[i]->label);
goto cleanup;
}
curr_pc += 3;
@@ 596,7 594,8 @@ uint32_t assemble(char *code, FILE *out)
uint16_t lbl;
if (!(lbl = ll_find(last_node, insts[i]->label)))
{
- printf(ERR "Error on line %d: label '%s' is not defined" RESET "\n", insts[i]->line, insts[i]->label);
+ printf(ERR "Error on line %d: label '%s' is not defined" RESET "\n",
+ insts[i]->line, insts[i]->label);
goto cleanup;
}
curr_pc += 2;
@@ 604,7 603,8 @@ uint32_t assemble(char *code, FILE *out)
printf("ARG_REL, pc (after) == %x, diff = %hx\n", curr_pc, (uint8_t) diff);
if ((diff < 0 ? -diff : diff) > 0xFF)
{
- printf(ERR "Error on line %d: label '%s' is too far away for a relative jump" RESET "\n", insts[i]->line, insts[i]->label);
+ printf(ERR "Error on line %d: label '%s' is too far away for a relative jump" RESET "\n",
+ insts[i]->line, insts[i]->label);
printf("pc == %hx, label is at %hx\n", curr_pc, lbl);
goto cleanup;
}
M as/as.h => as/as.h +18 -1
@@ 1,9 1,26 @@
#pragma once
+#include "map.h"
+
#include <stdio.h>
#include <stdint.h>
+#include <stdbool.h>
+
+#define ERR "\033[31m"
+#define GREEN "\033[32m"
+#define RESET "\033[0m"
+
+char *strtok_fix(char *string, const char *token);
+uint32_t skip_ws(char **code);
+char *parse_label_name(char **code);
+bool ws_end(char **code);
+
+/**
+ * @returns 0 on success, error code otherwise
+ */
+int preproc(char *code, FILE *out, map_t *macros, int flags);
-/*
+/**
* @returns NULL on failure, printing info to stderr
*/
uint32_t assemble(char *code, FILE *out);
M as/main.c => as/main.c +18 -1
@@ 1,10 1,12 @@
#include "as.h"
+#include "map.h"
#include <stdio.h>
#include <stdlib.h>
#include <bits/getopt_core.h>
#include <unistd.h>
+// TODO: handle all the possible IO errors
int main(int argc, char **argv)
{
char c;
@@ 38,7 40,22 @@ int main(int argc, char **argv)
fread(text, len, 1, in);
text[len] = 0;
- uint32_t built = assemble(text, out);
+ FILE *temp = tmpfile();
+
+ map_t *macros = new_map();
+ uint32_t processed = preproc(text, temp, macros, 0);
+ free_map_items(macros);
+
+ fseek(temp, 0, SEEK_END);
+ ssize_t temp_len = ftell(in);
+ fseek(temp, 0, SEEK_SET);
+
+ char *processed_text = malloc(len + 1);
+ fread(processed_text, len, 1, in);
+ text[temp_len] = 0;
+
+ uint32_t built = assemble(processed_text, out);
free(text);
+ free(processed_text);
}
A as/pp.c => as/pp.c +77 -0
@@ 0,0 1,77 @@
+#include "as.h"
+#include "map.h"
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+enum /* State */
+{
+ NORMAL, /* Default State */
+ MACRO_DEF /* In Macro Definition */
+};
+
+enum /* Flags */
+{
+ PRESERVE_MACRO_ARGS,
+};
+
+int preproc(char *in, FILE *out, map_t *macros, int flags)
+{
+ int line_no = 1,
+ err = 0,
+ state = NORMAL;
+ char *line = strtok_fix(in, "\n"),
+ *macro_name = NULL;
+
+ while (line)
+ {
+ skip_ws(&line);
+
+ if (*line == '%')
+ {
+ // Line is preprocessor directive
+
+ char *directive = parse_label_name(&line);
+ if (!directive)
+ {
+ fprintf(stderr, ERR "Expected preprocessor directive on line %d\n" RESET,
+ line_no);
+ err = EINVAL;
+ goto cleanup;
+ }
+ else
+ {
+ if (!strcasecmp(directive, "macro"))
+ {
+ skip_ws(&line);
+ macro_name = parse_label_name(&line);
+ if (!macro_name)
+ {
+ fprintf(stderr, ERR "Expected name after %%macro on line %d\n" RESET,
+ line_no);
+ err = EINVAL;
+ goto cleanup;
+ }
+
+ if (!ws_end(&line))
+ {
+ fprintf(stderr, ERR "Expected new line after macro definition\n" RESET);
+ err = EINVAL;
+ goto cleanup;
+ }
+
+ state = MACRO_DEF;
+ }
+ }
+ }
+
+ fprintf(out, "%s\n", line);
+
+ line = strtok_fix(NULL, "\n");
+ line_no++;
+ }
+
+cleanup:
+ return err;
+}
A as/test/test-abs-jump.s => as/test/test-abs-jump.s +16 -0
@@ 0,0 1,16 @@
+;;; This program should test for a bug involving endianness.
+
+start:
+ lda #$FF
+ sta $200 ; Put something on the screen, just to see
+ jmp second-pixel
+ brk
+
+second-pixel:
+ lda #$E0 ; Red
+ sta $201
+ sta $220
+ sta $221 ; Draw a box around the white pixel
+
+loop: ; Infinite loop
+ jmp loop
A docs/.sass-cache/e3a0acadbd5d6bc6cf7ba6a2321a4fa55d361330/styles.scssc => docs/.sass-cache/e3a0acadbd5d6bc6cf7ba6a2321a4fa55d361330/styles.scssc +0 -0
M docs/build.lua => docs/build.lua +1 -1
@@ 4,7 4,7 @@ site = Site
-- site.processors.md = markdownProcessor
site.processors.scss = {
- process = cmdProcessor("sass -"),
+ process = cmdProcessor("sass"),
extension = "css"
}
site.processors.webm = {
M docs/content/demo.webm => docs/content/demo.webm +0 -0
M docs/templates/page.html => docs/templates/page.html +1 -1
@@ 14,7 14,7 @@
</p>
<ul>
- <li><a href="https://github.com/swissChili/6502">Git</a></li>
+ <li><a href="https://git.sr.ht/~swisschili/toolchain-6502">Git</a></li>
<li><a href="https://builds.sr.ht/~swisschili/6502">
<img src="https://builds.sr.ht/~swisschili/6502.svg"></a>
</li>
A test-abs-jump.bin => test-abs-jump.bin +0 -0