#include #include "fh_print.h" #include "fh_error.h" #include "fh_runtime.h" #include "fh_mem.h" void fh_setbase(struct fh_thread_s *fh, uint32_t base) { LOG("BASE = %d", base); fh->base = base; } enum fh_error fh_fetch(struct fh_thread_s *fh, uint32_t addr, uint32_t *dst) { switch (addr) { case MAGICADDR_BASE: *dst = fh->base; break; // TODO more magic default: if (addr & 3) { LOGE("Address 0x%08x is not aligned!", addr); return FH_ERR_ILLEGAL_FETCH; } if (addr < HEAP_SIZE - 4) { *dst = *((uint32_t*)&fh->heap[addr]); } else { LOGE("Address 0x%08x too high!", addr); return FH_ERR_ILLEGAL_FETCH; } } return FH_OK; } enum fh_error fh_fetch_char(struct fh_thread_s *fh, uint32_t addr, char *dst) { if (addr < HEAP_SIZE - 4) { *dst = (char) fh->heap[addr]; } else { LOGE("Address 0x%08x too high!", addr); return FH_ERR_ILLEGAL_FETCH; } return FH_OK; } enum fh_error fh_store(struct fh_thread_s *fh, uint32_t addr, uint32_t val) { switch (addr) { case MAGICADDR_BASE: fh_setbase(fh, val); break; // TODO more magic default: if (addr & 3) { LOGE("Address 0x%08x is not aligned!", addr); return FH_ERR_ILLEGAL_FETCH; } if (addr <= HEAP_SIZE - 4) { *((uint32_t*)&fh->heap[addr]) = val; } else { LOGE("Address 0x%08x too high!", addr); return FH_ERR_ILLEGAL_FETCH; } } return FH_OK; } enum fh_error fh_store_char(struct fh_thread_s *fh, uint32_t addr, char val) { if (addr < HEAP_SIZE) { fh->heap[addr] = val; } else { LOGE("Address 0x%08x too high!", addr); return FH_ERR_ILLEGAL_FETCH; } return FH_OK; } /** Allocate a heap region, e.g. for a string. The address is stored to `addr` */ enum fh_error fh_heap_reserve( struct fh_thread_s *fh, size_t len, uint32_t *addr ) { uint32_t p = fh->heap_top; if (p + len > HEAP_SIZE) { return FH_ERR_HEAP_FULL; } *addr = p; fh->heap_top = WORDALIGNED(p + len); return FH_OK; } /** Write bytes to heap at a given location. The region must have been previously allocated! */ void fh_heap_write(struct fh_thread_s *fh, uint32_t addr, const void *src, uint32_t len) { memcpy(&fh->heap[addr], src, len); } /** Allocate heap region and write bytes to it */ enum fh_error fh_heap_put(struct fh_thread_s *fh, const void *src, uint32_t len) { enum fh_error rv; uint32_t addr; TRY(fh_heap_reserve(fh, len, &addr)); fh_heap_write(fh, addr, src, len); return FH_OK; } /** Copy bytes from compile area to heap. The region must have been previously allocated! */ void fh_heap_copy_from_compile(struct fh_thread_s *fh, uint32_t addr, uint32_t srcaddr, uint32_t len) { memcpy(&fh->heap[addr], &fh->compile[srcaddr], len); } /** Reserve space in the compile memory area */ enum fh_error fh_compile_reserve( struct fh_thread_s *fh, size_t len, uint32_t *addr ) { uint32_t p = fh->compile_top; // FIXME this shouldn't be needed if (p + len > COMPILED_BUFFER_SIZE) { return FH_ERR_HEAP_FULL; } *addr = p; fh->compile_top = WORDALIGNED(p + len); return FH_OK; } /** Write bytes to compile area at a given location. The region must have been previously allocated! */ void fh_compile_write(struct fh_thread_s *fh, uint32_t addr, const void *src, uint32_t len) { memcpy(&fh->compile[addr], src, len); } /** Allocate compile region and write bytes to it */ enum fh_error fh_compile_put(struct fh_thread_s *fh, const void *src, uint32_t len) { enum fh_error rv; uint32_t addr; TRY(fh_compile_reserve(fh, len, &addr)); fh_compile_write(fh, addr, src, len); return FH_OK; }