prog_t no longer has a header
This "header" is now embedded directly into the struct. The semantic of a header never really matters in the actual runtime anyway, it's only for bytecode (de)serialising.
This commit is contained in:
49
lib/inst.c
49
lib/inst.c
@@ -436,61 +436,54 @@ void insts_write_bytecode_file(inst_t *instructions, size_t size, FILE *fp)
|
|||||||
free(darr.data);
|
free(darr.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prog_header_write_bytecode(prog_header_t header, darr_t *buffer)
|
static_assert(sizeof(prog_t) == WORD_SIZE * 2,
|
||||||
{
|
"prog_{write|read}_* is out of date");
|
||||||
word start = word_htobc(header.start_address);
|
|
||||||
darr_append_bytes(buffer, (byte *)&start, sizeof(start));
|
|
||||||
word count = word_htobc(header.count);
|
|
||||||
darr_append_bytes(buffer, (byte *)&count, sizeof(count));
|
|
||||||
}
|
|
||||||
|
|
||||||
void prog_write_bytecode(prog_t *program, darr_t *buffer)
|
void prog_write_bytecode(prog_t *program, darr_t *buffer)
|
||||||
{
|
{
|
||||||
// Write program header
|
// Write program header i.e. the start and count
|
||||||
prog_header_write_bytecode(program->header, buffer);
|
word start = word_htobc(program->start_address);
|
||||||
|
darr_append_bytes(buffer, (byte *)&start, sizeof(start));
|
||||||
|
word count = word_htobc(program->count);
|
||||||
|
darr_append_bytes(buffer, (byte *)&count, sizeof(count));
|
||||||
|
|
||||||
// Write instructions
|
// Write instructions
|
||||||
insts_write_bytecode(program->instructions, program->header.count, buffer);
|
insts_write_bytecode(program->instructions, program->count, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prog_append_bytecode(prog_t *program, darr_t *buffer)
|
void prog_append_bytecode(prog_t *program, darr_t *buffer)
|
||||||
{
|
{
|
||||||
insts_write_bytecode(program->instructions, program->header.count, buffer);
|
insts_write_bytecode(program->instructions, program->count, buffer);
|
||||||
}
|
|
||||||
|
|
||||||
prog_header_t prog_header_read_bytecode(darr_t *buffer)
|
|
||||||
{
|
|
||||||
prog_header_t header = {0};
|
|
||||||
header.start_address = convert_bytes_to_word(buffer->data + buffer->used);
|
|
||||||
buffer->used += sizeof(header.start_address);
|
|
||||||
header.count = convert_bytes_to_word(buffer->data + buffer->used);
|
|
||||||
buffer->used += sizeof(header.count);
|
|
||||||
return header;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prog_t *prog_read_bytecode(darr_t *buffer)
|
prog_t *prog_read_bytecode(darr_t *buffer)
|
||||||
{
|
{
|
||||||
// TODO: Error (not enough space for program header)
|
// TODO: Error (not enough space for program header)
|
||||||
if ((buffer->available - buffer->used) < sizeof(prog_header_t))
|
if ((buffer->available - buffer->used) < sizeof(prog_t))
|
||||||
return NULL;
|
return NULL;
|
||||||
// Read program header
|
// Read program header
|
||||||
prog_header_t header = prog_header_read_bytecode(buffer);
|
word start_address = convert_bytes_to_word(buffer->data + buffer->used);
|
||||||
|
buffer->used += sizeof(start_address);
|
||||||
|
word count = convert_bytes_to_word(buffer->data + buffer->used);
|
||||||
|
buffer->used += sizeof(word);
|
||||||
|
|
||||||
// TODO: Error (not enough space for program instruction count)
|
// TODO: Error (not enough space for program instruction count)
|
||||||
if ((buffer->available - buffer->used) < WORD_SIZE)
|
if ((buffer->available - buffer->used) < WORD_SIZE)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
prog_t *program = malloc(sizeof(*program) + (sizeof(inst_t) * header.count));
|
prog_t *program = malloc(sizeof(*program) + (sizeof(inst_t) * count));
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < header.count && (buffer->used < buffer->available); ++i)
|
for (i = 0; i < count && (buffer->used < buffer->available); ++i)
|
||||||
program->instructions[i] = inst_read_bytecode(buffer);
|
program->instructions[i] = inst_read_bytecode(buffer);
|
||||||
|
|
||||||
// TODO: Error (Expected more instructions)
|
// TODO: Error (Expected more instructions)
|
||||||
if (i < header.count - 1)
|
if (i < count - 1)
|
||||||
{
|
{
|
||||||
free(program);
|
free(program);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
program->header = header;
|
program->start_address = start_address;
|
||||||
|
program->count = count;
|
||||||
|
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ const char *opcode_as_cstr(opcode_t);
|
|||||||
: ((OPCODE) == OP_TYPE##_HWORD) ? DATA_TYPE_HWORD \
|
: ((OPCODE) == OP_TYPE##_HWORD) ? DATA_TYPE_HWORD \
|
||||||
: DATA_TYPE_WORD)
|
: DATA_TYPE_WORD)
|
||||||
|
|
||||||
|
// OPCODE_DATA_TYPE: opcode_t -> data_type_t. data_type_t acts as
|
||||||
|
// a map between types and their offsets from the first type of
|
||||||
|
// instruction. That means for opcode_type A and data_type u,
|
||||||
|
// OP_<A>_BYTE + u = OP_<A>_<u>.
|
||||||
|
|
||||||
void inst_print(inst_t, FILE *);
|
void inst_print(inst_t, FILE *);
|
||||||
|
|
||||||
size_t inst_bytecode_size(inst_t);
|
size_t inst_bytecode_size(inst_t);
|
||||||
|
|||||||
@@ -165,11 +165,6 @@ typedef struct
|
|||||||
{
|
{
|
||||||
word start_address;
|
word start_address;
|
||||||
word count;
|
word count;
|
||||||
} prog_header_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
prog_header_t header;
|
|
||||||
inst_t instructions[];
|
inst_t instructions[];
|
||||||
} prog_t;
|
} prog_t;
|
||||||
|
|
||||||
|
|||||||
10
vm/runtime.c
10
vm/runtime.c
@@ -59,7 +59,7 @@ err_t vm_execute(vm_t *vm)
|
|||||||
static_assert(NUMBER_OF_OPCODES == 98, "vm_execute: Out of date");
|
static_assert(NUMBER_OF_OPCODES == 98, "vm_execute: Out of date");
|
||||||
struct Program *prog = &vm->program;
|
struct Program *prog = &vm->program;
|
||||||
prog_t *program_data = prog->data;
|
prog_t *program_data = prog->data;
|
||||||
if (prog->ptr >= program_data->header.count)
|
if (prog->ptr >= program_data->count)
|
||||||
return ERR_END_OF_PROGRAM;
|
return ERR_END_OF_PROGRAM;
|
||||||
inst_t instruction = program_data->instructions[prog->ptr];
|
inst_t instruction = program_data->instructions[prog->ptr];
|
||||||
|
|
||||||
@@ -279,10 +279,10 @@ err_t vm_execute(vm_t *vm)
|
|||||||
err_t vm_execute_all(vm_t *vm)
|
err_t vm_execute_all(vm_t *vm)
|
||||||
{
|
{
|
||||||
struct Program *program = &vm->program;
|
struct Program *program = &vm->program;
|
||||||
const size_t count = program->data->header.count;
|
const size_t count = program->data->count;
|
||||||
err_t err = ERR_OK;
|
err_t err = ERR_OK;
|
||||||
// Setup the initial address according to the program
|
// Setup the initial address according to the program
|
||||||
program->ptr = program->data->header.start_address;
|
program->ptr = program->data->start_address;
|
||||||
#if VERBOSE >= 1
|
#if VERBOSE >= 1
|
||||||
size_t cycles = 0;
|
size_t cycles = 0;
|
||||||
#endif
|
#endif
|
||||||
@@ -495,7 +495,7 @@ void vm_print_stack(vm_t *vm, FILE *fp)
|
|||||||
void vm_print_program(vm_t *vm, FILE *fp)
|
void vm_print_program(vm_t *vm, FILE *fp)
|
||||||
{
|
{
|
||||||
struct Program program = vm->program;
|
struct Program program = vm->program;
|
||||||
const size_t count = program.data->header.count;
|
const size_t count = program.data->count;
|
||||||
fprintf(fp,
|
fprintf(fp,
|
||||||
"Program.max = %lu\nProgram.ptr = "
|
"Program.max = %lu\nProgram.ptr = "
|
||||||
"%lu\nProgram.instructions = [\n",
|
"%lu\nProgram.instructions = [\n",
|
||||||
@@ -607,7 +607,7 @@ void vm_print_all(vm_t *vm, FILE *fp)
|
|||||||
|
|
||||||
err_t vm_jump(vm_t *vm, word w)
|
err_t vm_jump(vm_t *vm, word w)
|
||||||
{
|
{
|
||||||
if (w >= vm->program.data->header.count)
|
if (w >= vm->program.data->count)
|
||||||
return ERR_INVALID_PROGRAM_ADDRESS;
|
return ERR_INVALID_PROGRAM_ADDRESS;
|
||||||
vm->program.ptr = w;
|
vm->program.ptr = w;
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user