~swisschili/toolchain-6502

ca0d2e2f773470994ff7e1807a379e6289cb7713 — swissChili 3 months ago 97b5d8b
Include data structures for assembler
9 files changed, 365 insertions(+), 21 deletions(-)

M .gitignore
M .gitmodules
M as/CMakeLists.txt
M as/as.c
A as/hash.c
A as/hash.h
D as/libcollect
A as/map.c
A as/map.h
M .gitignore => .gitignore +5 -4
@@ 1,5 1,6 @@
.~*
**/.~*
**/.#*
build
#*#
*~
~*
\ No newline at end of file
**/#*#
**/*~
**/~*
\ No newline at end of file

M .gitmodules => .gitmodules +0 -3
@@ 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

M as/CMakeLists.txt => as/CMakeLists.txt +1 -5
@@ 2,8 2,4 @@ cmake_minimum_required(VERSION 3.0)

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)

M as/as.c => as/as.c +9 -8
@@ 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 @@ bool parse_arg(char *code, int am, inst_t *inst)

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 @@ uint32_t assemble(char *code, FILE *out)

		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 @@ uint32_t assemble(char *code, FILE *out)
			if (mnemonic == _mn && parse_arg(line, am, &arg)) \
			{												  \
				arg.opcode = op;							  \
				pc += len;									  \
				print_inst(&arg);							  \
			}												  \
			else


@@ 429,7 431,6 @@ uint32_t assemble(char *code, FILE *out)
#undef INST
		}

		num_insts++;
		line = strtok(NULL, "\r\n");
	}


A as/hash.c => as/hash.c +14 -0
@@ 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;
}

A as/hash.h => as/hash.h +9 -0
@@ 0,0 1,9 @@
#ifndef LIBASM_HASH_H
#define LIBASM_HASH_H

#include <stdint.h>

uint32_t hash(char *str);


#endif

D as/libcollect => as/libcollect +0 -1
@@ 1,1 0,0 @@
Subproject commit e9ee5221d307378150d2119939025b8709da178a

A as/map.c => as/map.c +208 -0
@@ 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);
		}
	}
}

A as/map.h => as/map.h +119 -0
@@ 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);								 \
	}