#include #include #include #include "sp_vm.h" #define CELLBOUNDMAX (INT_MAX/sizeof(cell_t)) #define STACKMARGIN ((cell_t)(16*sizeof(cell_t))) int main() { /** temporary testing area */ sp_context_t ctx; cell_t l, *p; ctx.data = (uint8_t *)malloc(50000); ctx.memory = 50000; ctx.heapbase = 200; ctx.hp = ctx.heapbase; ctx.sp = 45000; assert(SP_HeapAlloc(&ctx, 500, &l, &p) == SP_ERR_NONE); assert(SP_HeapPop(&ctx, l) == SP_ERR_NONE); assert(SP_HeapRelease(&ctx, l) == SP_ERR_NONE); assert(SP_HeapRelease(&ctx, 4) == SP_ERR_INVALID_ADDRESS); assert(SP_HeapAlloc(&ctx, 500, &l, &p) == SP_ERR_NONE); assert(SP_HeapRelease(&ctx, l) == SP_ERR_NONE); return 0; } int SP_HeapAlloc(sp_context_t *ctx, unsigned int cells, cell_t *local_addr, cell_t **phys_addr) { cell_t *addr; ucell_t realmem; #if 0 if (cells > CELLBOUNDMAX) { return SP_ERR_PARAM; } #else assert(cells < CELLBOUNDMAX); #endif realmem = cells * sizeof(cell_t); /** * Check if the space between the heap and stack is sufficient. */ if ((cell_t)(ctx->sp - ctx->hp - realmem) < STACKMARGIN) { return SP_ERR_HEAPLOW; } addr = (cell_t *)(ctx->data + ctx->hp); /* store size of allocation in cells */ *addr = (cell_t)cells; addr++; ctx->hp += sizeof(cell_t); *local_addr = ctx->hp; if (phys_addr) { *phys_addr = addr; } ctx->hp += realmem; return SP_ERR_NONE; } int SP_HeapPop(sp_context_t *ctx, cell_t local_addr) { cell_t cellcount; cell_t *addr; /* check the bounds of this address */ local_addr -= sizeof(cell_t); if (local_addr < ctx->heapbase || local_addr >= ctx->sp) { return SP_ERR_INVALID_ADDRESS; } addr = (cell_t *)(ctx->data + local_addr); cellcount = (*addr) * sizeof(cell_t); /* check if this memory count looks valid */ if (ctx->hp - cellcount - sizeof(cell_t) != local_addr) { return SP_ERR_INVALID_ADDRESS; } ctx->hp = local_addr; return SP_ERR_NONE; } int SP_HeapRelease(sp_context_t *ctx, cell_t local_addr) { if (local_addr < ctx->heapbase) { return SP_ERR_INVALID_ADDRESS; } ctx->hp = local_addr - sizeof(cell_t); return SP_ERR_NONE; } int SP_FindNativeByName(sp_context_t *ctx, const char *name, uint32_t *index) { uint32_t mid, low, high, diff; high = ctx->plugin->info.natives_num - 1; low = 0; while (low <= high) { mid = (low + high) / 2; diff = strcmp(ctx->natives[mid].name, name); if (diff == 0) { if (index) *index = mid; return SP_ERR_NONE; } else if (diff < 0) { low = mid + 1; } else { high = mid - 1; } } return SP_ERR_NOT_FOUND; } int SP_GetNativeByIndex(sp_context_t *ctx, uint32_t index, sp_native_t **native) { if (index >= ctx->plugin->info.natives_num) return SP_ERR_INDEX; if (native) *native = &(ctx->natives[index]); return SP_ERR_NONE; } int SP_GetNativesNum(sp_context_t *ctx, uint32_t *num) { *num = ctx->plugin->info.natives_num; return SP_ERR_NONE; } int SP_FindPublicByName(sp_context_t *ctx, const char *name, uint32_t *index) { uint32_t mid, low, high, diff; high = ctx->plugin->info.publics_num - 1; low = 0; while (low <= high) { mid = (low + high) / 2; diff = strcmp(ctx->publics[mid].name, name); if (diff == 0) { if (index) *index = mid; return SP_ERR_NONE; } else if (diff < 0) { low = mid + 1; } else { high = mid - 1; } } return SP_ERR_NOT_FOUND; } int SP_GetPublicByIndex(sp_context_t *ctx, uint32_t index, sp_public_t **pblic) { if (index >= ctx->plugin->info.publics_num) return SP_ERR_INDEX; if (pblic) *pblic = &(ctx->publics[index]); return SP_ERR_NONE; } int SP_GetPublicsNum(sp_context_t *ctx, uint32_t *num) { *num = ctx->plugin->info.publics_num; return SP_ERR_NONE; } int SP_GetPubvarByIndex(sp_context_t *ctx, uint32_t index, sp_pubvar_t **pubvar) { if (index >= ctx->plugin->info.pubvars_num) return SP_ERR_INDEX; if (pubvar) *pubvar = &(ctx->pubvars[index]); return SP_ERR_NONE; } int SP_FindPubvarByName(sp_context_t *ctx, const char *name, uint32_t *index) { uint32_t mid, low, high, diff; high = ctx->plugin->info.pubvars_num - 1; low = 0; while (low <= high) { mid = (low + high) / 2; diff = strcmp(ctx->pubvars[mid].name, name); if (diff == 0) { if (index) *index = mid; return SP_ERR_NONE; } else if (diff < 0) { low = mid + 1; } else { high = mid - 1; } } return SP_ERR_NOT_FOUND; } int SP_GetPubvarAddrs(sp_context_t *ctx, uint32_t index, cell_t *local_addr, cell_t **phys_addr) { if (index >= ctx->plugin->info.pubvars_num) return SP_ERR_INDEX; *local_addr = ctx->plugin->info.pubvars[index].address; *phys_addr = ctx->pubvars[index].offs; return SP_ERR_NONE; } int SP_GetPubVarsNum(sp_context_t *ctx, uint32_t *num) { *num = ctx->plugin->info.pubvars_num; return SP_ERR_NONE; }