From 2dc9d118efb64de6ea54a5a9eb4474f8e5ef3145 Mon Sep 17 00:00:00 2001 From: Paul Oliver Date: Thu, 29 Feb 2024 01:50:44 +0100 Subject: Initial commit --- src/memory.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 src/memory.c (limited to 'src/memory.c') 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 +#include +#include +#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; +} -- cgit v1.2.1