Adds push/pop/peek to VM. Corrects some mistakes in the instructions.

This commit is contained in:
Felix Queißner 2016-05-19 13:19:38 +02:00
parent 29bea1a335
commit 8b84163c56
4 changed files with 88 additions and 3 deletions

View file

@ -17,6 +17,7 @@ control stack access or control flow.
|----------|---------------|-------------------------------------------------|
| SP | Stack Pointer | Stores the current 'top' position of the stack. |
| BP | Base Pointer | Stores the current stack frame position. |
| CP | Code Pointer | Stores the instruction which is executed next. |
| FG | Flag Register | Stores the state of the flags. |
### Stack Pointer

View file

@ -3,10 +3,38 @@
#include <stdlib.h>
#include <stdio.h>
Instruction code[] =
{
{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD, 0 },
};
void dump_proc(Process *process)
{
printf("[ ");
for(int i = 1; i <= process->stackPointer; i++) {
printf("%d ", process->stack[i]);
}
printf("]\n");
}
void vm_assert(int assertion, const char *msg)
{
if(assertion != 0)
return;
printf("Assertion failed: %s\n", msg);
exit(1);
}
int main(int argc, const char **argv)
{
Module module = { code, 1 };
Process process = { &module, 0, 0, 0, 0 };
Process *p = &process;
int stillAlive = vm_step_process(p);
printf("Process %s.\n", (stillAlive ? "still running" : "terminated"));
return 0;
}

View file

@ -1 +1,34 @@
#include "vm.h"
#include "vm.h"
int vm_step_process(Process *process)
{
vm_assert(process != NULL, "process must not be NULL.");
Instruction instr = process->module->code[process->codePointer];
return 0;
}
void vm_push(Process *process, uint32_t value)
{
vm_assert(process != NULL, "process must not be NULL.");
vm_assert(process->stackPointer < VM_STACKSIZE, "Stack overflow");
process->stack[++process->stackPointer] = value;
}
uint32_t vm_pop(Process *process)
{
vm_assert(process != NULL, "process must not be NULL.");
uint32_t psp = process->stackPointer;
uint32_t val = process->stack[process->stackPointer--];
// Underflow check works because unsigned overflow is defined ;)
vm_assert(psp >= process->stackPointer, "Stack underflow");
return val;
}
uint32_t vm_peek(Process *process)
{
vm_assert(process != NULL, "process must not be NULL.");
return process->stack[process->stackPointer];
}

View file

@ -72,8 +72,16 @@ typedef struct
_Static_assert(sizeof(Instruction) == 8, "Instruction must be 8 bytes large.");
_Static_assert(offsetof(Instruction, argument) == 4, "Argument must be must be 8 bytes large.");
typedef struct
{
Instruction *code;
uint32_t length;
} Module;
typedef struct
{
Module *module;
uint32_t codePointer;
uint32_t stackPointer;
uint32_t basePointer;
@ -82,8 +90,23 @@ typedef struct
uint32_t stack[VM_STACKSIZE];
} Process;
/**
* @brief Steps a given process.
*
* Executes a single instruction and processes input and output.
*
* @param process The process to be stepped.
* @returns 1 if the process is still running or 0 if the process is terminated.
*/
int vm_step_process(Process *process);
void vm_push(Process *process, uint32_t value);
uint32_t vm_pop(Process *process);
uint32_t vm_peek(Process *process);
void vm_assert(int assertion, const char *msg);
#if defined(__cplusplus)
}