aboutsummaryrefslogtreecommitdiff
path: root/src/memory.c
diff options
context:
space:
mode:
authorPaul Oliver <contact@pauloliver.dev>2024-02-29 01:50:44 +0100
committerPaul Oliver <contact@pauloliver.dev>2024-02-29 01:50:44 +0100
commit2dc9d118efb64de6ea54a5a9eb4474f8e5ef3145 (patch)
tree74039957b10390da4875d676303a781bd0792e45 /src/memory.c
Initial commit
Diffstat (limited to 'src/memory.c')
-rw-r--r--src/memory.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/src/memory.c b/src/memory.c
new file mode 100644
index 0000000..4befd4f
--- /dev/null
+++ b/src/memory.c
@@ -0,0 +1,227 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "types.h"
+#include "instset.h"
+#include "memory.h"
+
+#define MEM_BLOCK_START_FLAG (0x80)
+#define ALLOCATED_FLAG (0x40)
+#define INSTRUCTION_MASK (0x3f)
+
+static sbool g_isInit;
+static sword g_order;
+static sword g_size;
+static sword g_memBlockCount;
+static sword g_allocated;
+static sword g_cap;
+static sbyte *g_data;
+
+void
+sm_init(sword order)
+{
+ assert(!g_isInit);
+ assert(INSTRUCTION_MASK == SINST_COUNT - 1);
+ g_isInit = STRUE;
+ g_order = order;
+ g_size = 1 << g_order;
+ g_cap = g_size / 2;
+ g_data = calloc(g_size, sizeof(sbyte));
+ assert(g_data);
+}
+
+void
+sm_quit(void)
+{
+ assert(g_isInit);
+ free(g_data);
+ g_isInit = SFALSE;
+ g_order = 0;
+ g_size = 0;
+ g_memBlockCount = 0;
+ g_allocated = 0;
+ g_cap = 0;
+ g_data = NULL;
+}
+
+void
+sm_load(FILE *file)
+{
+ assert(!g_isInit);
+ assert(file);
+ fread(&g_isInit, sizeof(sbool), 1, file);
+ fread(&g_order, sizeof(sword), 1, file);
+ fread(&g_size, sizeof(sword), 1, file);
+ fread(&g_memBlockCount, sizeof(sword), 1, file);
+ fread(&g_allocated, sizeof(sword), 1, file);
+ fread(&g_cap, sizeof(sword), 1, file);
+ g_data = calloc(g_size, sizeof(sbyte));
+ assert(g_data);
+ fread(g_data, sizeof(sbyte), g_size, file);
+}
+
+void
+sm_save(FILE *file)
+{
+ assert(g_isInit);
+ assert(file);
+ fwrite(&g_isInit, sizeof(sbool), 1, file);
+ fwrite(&g_order, sizeof(sword), 1, file);
+ fwrite(&g_size, sizeof(sword), 1, file);
+ fwrite(&g_memBlockCount, sizeof(sword), 1, file);
+ fwrite(&g_allocated, sizeof(sword), 1, file);
+ fwrite(&g_cap, sizeof(sword), 1, file);
+ fwrite(g_data, sizeof(sbyte), g_size, file);
+}
+
+sbool
+sm_isInit(void)
+{
+ return g_isInit;
+}
+
+sword
+sm_getOrder(void)
+{
+ return g_order;
+}
+
+sword
+sm_getSize(void)
+{
+ return g_size;
+}
+
+sword
+sm_getMemBlockCount(void)
+{
+ return g_memBlockCount;
+}
+
+sword
+sm_getAllocated(void)
+{
+ return g_allocated;
+}
+
+sword
+sm_getCap(void)
+{
+ return g_cap;
+}
+
+sbool
+sm_isOverCap(void)
+{
+ assert(g_isInit);
+ return g_allocated > g_cap;
+}
+
+sbool
+sm_isValidAt(sword addr)
+{
+ assert(g_isInit);
+ return addr < g_size;
+}
+
+sbool
+sm_isMemBlockStartAt(sword addr)
+{
+ assert(g_isInit);
+ assert(sm_isValidAt(addr));
+ return !!(g_data[addr] & MEM_BLOCK_START_FLAG);
+}
+
+sbool
+sm_isAllocatedAt(sword addr)
+{
+ assert(g_isInit);
+ assert(sm_isValidAt(addr));
+ return !!(g_data[addr] & ALLOCATED_FLAG);
+}
+
+void
+sm_setMemBlockStartAt(sword addr)
+{
+ assert(g_isInit);
+ assert(sm_isValidAt(addr));
+ assert(!sm_isMemBlockStartAt(addr));
+ g_data[addr] ^= MEM_BLOCK_START_FLAG;
+ g_memBlockCount++;
+ assert(sm_isMemBlockStartAt(addr));
+ assert(g_memBlockCount);
+ assert(g_memBlockCount <= g_size);
+}
+
+void
+sm_unsetMemBlockStartAt(sword addr)
+{
+ assert(g_isInit);
+ assert(g_memBlockCount);
+ assert(sm_isValidAt(addr));
+ assert(sm_isMemBlockStartAt(addr));
+ g_data[addr] ^= MEM_BLOCK_START_FLAG;
+ g_memBlockCount--;
+ assert(!sm_isMemBlockStartAt(addr));
+ assert(g_memBlockCount <= g_size);
+}
+
+void
+sm_allocateAt(sword addr)
+{
+ assert(g_isInit);
+ assert(sm_isValidAt(addr));
+ assert(!sm_isAllocatedAt(addr));
+ g_data[addr] ^= ALLOCATED_FLAG;
+ g_allocated++;
+ assert(sm_isAllocatedAt(addr));
+ assert(g_allocated);
+ assert(g_allocated <= g_size);
+}
+
+void
+sm_freeAt(sword addr)
+{
+ assert(g_isInit);
+ assert(g_allocated);
+ assert(sm_isValidAt(addr));
+ assert(sm_isAllocatedAt(addr));
+ g_data[addr] ^= ALLOCATED_FLAG;
+ g_allocated--;
+ assert(!sm_isAllocatedAt(addr));
+ assert(g_allocated <= g_size);
+}
+
+sbyte
+sm_getInstAt(sword addr)
+{
+ assert(g_isInit);
+ assert(sm_isValidAt(addr));
+ return g_data[addr] & INSTRUCTION_MASK;
+}
+
+void
+sm_setInstAt(sword addr, sbyte inst)
+{
+ assert(g_isInit);
+ assert(sm_isValidAt(addr));
+ assert(si_isInst(inst));
+ g_data[addr] &= (MEM_BLOCK_START_FLAG | ALLOCATED_FLAG);
+ g_data[addr] |= inst;
+}
+
+sbyte
+sm_getByteAt(sword addr)
+{
+ assert(g_isInit);
+ assert(sm_isValidAt(addr));
+ return g_data[addr];
+}
+
+void
+sm_setByteAt(sword addr, sbyte byte)
+{
+ assert(g_isInit);
+ assert(sm_isValidAt(addr));
+ g_data[addr] = byte;
+}