Include data structures for assembler
diff --git a/.gitignore b/.gitignore
index 9f27f48..0443fb7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
-.~*
+**/.~*
+**/.#*
build
-#*#
-*~
-~*
\ No newline at end of file
+**/#*#
+**/*~
+**/~*
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
index 747fb4d..6dc59b1 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
[submodule "nuklear"]
path = nuklear
url = https://github.com/Immediate-Mode-UI/Nuklear.git
-[submodule "as/libcollect"]
- path = as/libcollect
- url = https://github.com/swissChili/libcollect
diff --git a/as/CMakeLists.txt b/as/CMakeLists.txt
index e2062c2..70638fe 100644
--- a/as/CMakeLists.txt
+++ b/as/CMakeLists.txt
@@ -2,8 +2,4 @@
project(6502 VERSION 0.1.0 LANGUAGES C)
-subdirs(libcollect)
-include_directories(libcollect/include)
-
-add_executable(6502-as main.c as.h as.c)
-target_link_libraries(6502-as collect)
+add_executable(6502-as main.c as.h as.c map.h map.c hash.c hash.c)
diff --git a/as/as.c b/as/as.c
index 61ad6bd..36d9637 100644
--- a/as/as.c
+++ b/as/as.c
@@ -2,9 +2,8 @@
#include "../cpu.h"
#include "../instructions.h"
#include "../mnemonics.h"
+#include "map.h"
-#include <collect/map.h>
-#include <collect/vector.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
@@ -374,10 +373,10 @@
uint32_t assemble(char *code, FILE *out)
{
- uintptr_t num_insts = 0;
+ uintptr_t num_insts = 0,
+ pc = 0x600;
uint32_t line_no = 1;
- map *labels = new_map();
- vector *insts = new_vector();
+ map_t *labels = new_map();
char *line;
printf("Assembling File\n");
@@ -397,14 +396,16 @@
if (label)
{
- map_set(labels, label, (void *)num_insts);
- printf("Set label %s at %lu\n", label, num_insts);
+ map_set(labels, label, (void *)pc);
+ printf("Set label %s at %lu\n", label, pc);
}
if (mn)
{
#define MN(a) if (!strcasecmp(mn, #a)) \
+ { \
mnemonic = a; \
+ } \
else
MNEMONICS;
@@ -418,6 +419,7 @@
if (mnemonic == _mn && parse_arg(line, am, &arg)) \
{ \
arg.opcode = op; \
+ pc += len; \
print_inst(&arg); \
} \
else
@@ -429,7 +431,6 @@
#undef INST
}
- num_insts++;
line = strtok(NULL, "\r\n");
}
diff --git a/as/hash.c b/as/hash.c
new file mode 100644
index 0000000..df4fec0
--- /dev/null
+++ b/as/hash.c
@@ -0,0 +1,14 @@
+#include "hash.h"
+
+uint32_t hash(char *str)
+{
+ uint32_t hash = 5381;
+ char c;
+
+ while (c = *str++)
+ {
+ hash = (hash << 5) + hash + c;
+ }
+
+ return hash;
+}
diff --git a/as/hash.h b/as/hash.h
new file mode 100644
index 0000000..a1312cd
--- /dev/null
+++ b/as/hash.h
@@ -0,0 +1,9 @@
+#ifndef LIBASM_HASH_H
+#define LIBASM_HASH_H
+
+#include <stdint.h>
+
+uint32_t hash(char *str);
+
+
+#endif
diff --git a/as/libcollect b/as/libcollect
deleted file mode 160000
index e9ee522..0000000
--- a/as/libcollect
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit e9ee5221d307378150d2119939025b8709da178a
diff --git a/as/map.c b/as/map.c
new file mode 100644
index 0000000..e990af9
--- /dev/null
+++ b/as/map.c
@@ -0,0 +1,208 @@
+#include "map.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef MAP_DEBUG
+#define MAP_DEBUG_PRINTF printf
+#else
+#define MAP_DEBUG_PRINTF // nothing
+#endif
+
+map_t *new_map_sized(uint64_t size)
+{
+ map_t *m = malloc(sizeof(map_t));
+
+ /*
+ * Calloc zeroes the memory, which is what we want.
+ */
+
+ map_node empty = EMPTY_NODE;
+
+ m->items = calloc(size, sizeof(map_node));
+ m->len = MAP_ALLOC_SIZE;
+ m->full = 0;
+
+ for (int i = 0; i < m->len; i++)
+ {
+ m->items[i] = empty;
+ }
+
+ return m;
+}
+
+map_t *new_map()
+{
+ return new_map_sized(MAP_ALLOC_SIZE);
+}
+
+void free_map(map_t *m)
+{
+ free(m->items);
+ free(m);
+}
+
+void free_map_items(map_t *m)
+{
+ for (int i = 0; i < m->len; i++)
+ {
+ if (m->items[i].key != NULL)
+ {
+ free(m->items[i].key);
+ free(m->items[i].val);
+ }
+ }
+ free(m->items);
+ free(m);
+}
+
+void map_set(map_t *m, char *k, void *v)
+{
+ uint64_t h = hash(k);
+ uint32_t i = h % m->len;
+
+ MAP_DEBUG_PRINTF("hash %u i %u\n", h, i);
+
+ m->count++;
+
+ if (m->full++ < m->len)
+ {
+ map_node val =
+ {
+ malloc(strlen(k)),
+ v,
+ 1,
+ h,
+ };
+
+ strcpy(val.key, k);
+
+ uint32_t current = i;
+
+ while (MAP_USED_AT(m->items, current))
+ {
+ if (current == m->len - 1)
+ {
+ current = 0;
+ }
+ else
+ {
+ current++;
+ }
+ }
+
+ MAP_DEBUG_PRINTF("Current %d\n", current);
+
+ m->items[current] = val;
+
+ MAP_DEBUG_PRINTF("val %d\n", *(int *) m->items[current].val);
+ }
+ else
+ {
+ /* resize map */
+ map_t *n_m = new_map_sized(m->len * 2);
+
+ for (uint64_t j = 0; j < m->len; j++)
+ {
+ if (!MAP_USED_AT(m->items, j))
+ {
+ continue;
+ }
+
+ uint32_t current = m->items[j].h;
+
+ while (MAP_USED_AT(m->items, current))
+ {
+ if (current == m->len - 1)
+ {
+ current = 0;
+ }
+ else
+ {
+ current++;
+ }
+ }
+
+ n_m->items[current] = m->items[j];
+ }
+
+ free_map(m);
+ m = n_m;
+ }
+}
+
+int map_exists(map_t *m, char *k)
+{
+ uint64_t h = hash(k);
+ uint32_t i = h % m->len;
+
+ uint32_t current = i;
+
+ while (m->items[current].used)
+ {
+ if (strcmp(m->items[current].key, k) == 0)
+ {
+ return 1;
+ }
+
+ if (current >= m->len - 1)
+ {
+ current = 0;
+ MAP_DEBUG_PRINTF("Current reset to 0\n");
+ }
+ else
+ {
+ current++;
+ MAP_DEBUG_PRINTF("Incrementing current\n");
+ }
+ }
+
+ return 0;
+}
+
+void *map_get(map_t *m, char *k)
+{
+ uint64_t h = hash(k);
+ uint32_t i = h % m->len;
+
+ uint32_t current = i;
+
+ MAP_DEBUG_PRINTF("%s should be %s\n", m->items[current].key, k);
+ MAP_DEBUG_PRINTF("streq %d\n", strcmp(m->items[current].key, k));
+
+ MAP_DEBUG_PRINTF("Current get %d\n", current);
+
+ while (strcmp(m->items[current].key, k) != 0)
+ {
+ MAP_DEBUG_PRINTF("While at %d\n", current);
+ if (current >= m->len - 1)
+ {
+ current = 0;
+ MAP_DEBUG_PRINTF("Current reset to 0\n");
+ }
+ else
+ {
+ current++;
+ MAP_DEBUG_PRINTF("Incrementing current\n");
+ }
+ }
+
+ MAP_DEBUG_PRINTF("val %d\n", *(int *) m->items[current].val);
+
+ return m->items[current].val;
+
+ //return 1;
+}
+
+void map_debug(map_t *m)
+{
+ for (int i = 0; i < m->len; i++)
+ {
+ if (m->items[i].val != NULL)
+ {
+ MAP_DEBUG_PRINTF("i = %d, k = %s, v = %d\n",
+ i, m->items[i].key, *(int *) m->items[i].val);
+ }
+ }
+}
diff --git a/as/map.h b/as/map.h
new file mode 100644
index 0000000..fded428
--- /dev/null
+++ b/as/map.h
@@ -0,0 +1,119 @@
+#pragma once
+
+
+#include <stdint.h>
+#include <stdlib.h>
+#include "hash.h"
+
+/* 1kb seems reasonable doesn't it? */
+#define MAP_ALLOC_SIZE (1 * 1024)
+
+struct map_node
+{
+ char *key;
+ void *val;
+ int used : 1;
+ uint32_t h;
+};
+
+typedef struct map_node map_node;
+
+#define EMPTY_NODE { NULL, NULL, 0, 0 }
+
+/**
+ * @brief A simple hashmap.
+ *
+ * Allocate map with new_map() and free it with free_map(). Items can be added
+ * with map_set() or the MAP_SET() macro. map_exists() can be used to check if
+ * an item exists in the map, map_get() and MAP_GET() can be used to retrieve
+ * items.
+ */
+struct map
+{
+ uint64_t len;
+ map_node *items;
+ uint64_t full;
+ uint64_t count;
+};
+
+typedef struct map map_t;
+
+/**
+ * @deprecated Used map_exists instead
+ */
+#define MAP_USED_AT(m, i) (m[i].used)
+
+/**
+ * @brief Allocate a new map on the heap
+ * @return A pointer to the allocated map
+ */
+map_t *new_map();
+
+/**
+ * @brief Allocate a map on the heap with a specific capacity. Map will be
+ * reallocated if this capacity is exceeded.
+ * @return A pointer to the allocated map
+ */
+map_t *new_map_sized(uint64_t);
+
+/**
+ * @brief Free a map on the heap
+ * @param m The map to free
+ */
+void free_map(map_t *m);
+
+/**
+ * @brief Free a map and its items
+ * @param m The map to free
+ */
+void free_map_items(map_t *m);
+
+/**
+ * @brief Set a certain value in the map
+ * @param m The map
+ * @param k The key whose value should be changed
+ * @param v The new value
+ */
+void map_set(map_t *m, char *k, void *v);
+
+/**
+ * @brief Get the value in a map by it's key
+ * @param m The map
+ * @param k The key
+ * @return The value at k
+ */
+void *map_get(map_t *m, char *k);
+
+/**
+ * @brief Check if a key is used in a map
+ * @param m The map
+ * @param k The key
+ * @return 1 if the key is used, 0 otherwise
+ */
+int map_exists(map_t *m, char *k);
+
+/**
+ * @brief Print a map's contents to stdout
+ * @warning Should not be used in production
+ * @param m The map
+ */
+void map_debug(map_t *m);
+
+#define MAP_GET(t, m, k) *(t *)map_get(m, k)
+
+/**
+ * @brief Helper macro to allocate memory for a value on the heap and store it
+ * at a given key
+ * @warning This is unsafe and should be used with caution, especially for more
+ * complex types
+ * @param m The map
+ * @param k The key at which to insert the value
+ * @param v The value
+ */
+#define MAP_SET(m, k, v) \
+ { \
+ __typeof__(v) *__map_temp = malloc(sizeof(__typeof(v))); \
+ *__map_temp = v; \
+ map_set(m, k, __map_temp); \
+ }
+