1
0
mirror of https://github.com/pevans/erc-c.git synced 2024-06-11 20:29:26 +00:00

Add reflect system to virtual machine

This commit is contained in:
Peter Evans 2018-02-05 20:31:05 -06:00
parent 149df404ac
commit c1c42834ed
4 changed files with 210 additions and 0 deletions

69
include/vm_reflect.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef _VM_REFLECT_H_
#define _VM_REFLECT_H_
#include <stdio.h>
/*
* Some forward decls for vm_reflect
*/
struct vm_reflect;
typedef struct vm_reflect vm_reflect;
/*
* A reflect function, mostly helpful in the struct definition itself as
* well as a function decls and defns. A reflect function would accept a
* reflect object and use that to figure out what it's talking about.
*/
typedef void (*vm_reflect_fn)(vm_reflect *);
struct vm_reflect {
/*
* These are the machine and CPU objects that the reflect system
* would want to work with.
*/
void *machine;
void *cpu;
/*
* Where information that we print will go to.
*/
FILE *stream;
/*
* Print out information about the machine and CPU, respectively.
*/
vm_reflect_fn cpu_info;
vm_reflect_fn machine_info;
/*
* These functions pause or resume operation of the virtual machine.
*/
vm_reflect_fn pause;
vm_reflect_fn resume;
/*
* Turn on, or off, disassembly of the instructions being executed.
*/
vm_reflect_fn disasm_on;
vm_reflect_fn disasm_off;
/*
* Eventually we will have the ability to load and save state to a
* file mechanism (probably not the one defined as `stream` above).
*/
#if 0
vm_reflect_fn save_state;
vm_reflect_fn load_state;
#endif
};
extern int vm_reflect_cpu_info(vm_reflect *);
extern int vm_reflect_disasm_off(vm_reflect *);
extern int vm_reflect_disasm_on(vm_reflect *);
extern int vm_reflect_machine_info(vm_reflect *);
extern int vm_reflect_pause(vm_reflect *);
extern int vm_reflect_resume(vm_reflect *);
extern vm_reflect *vm_reflect_create(void *, void *, FILE *);
extern void vm_reflect_free(vm_reflect *);
#endif

View File

@ -25,6 +25,7 @@ set(erc_sources
vm_area.c
vm_bitfont.c
vm_event.c
vm_reflect.c
vm_screen.c
vm_segment.c
)

62
src/vm_reflect.c Normal file
View File

@ -0,0 +1,62 @@
/*
* vm_reflect.c
*/
#include <stdlib.h>
#include "log.h"
#include "vm_reflect.h"
/*
* Create a new vm_reflect struct with the given machine, cpu and
* stream.
*/
vm_reflect *
vm_reflect_create(void *mach, void *cpu, FILE *stream)
{
vm_reflect *ref;
ref = malloc(sizeof(vm_reflect));
if (ref == NULL) {
log_critical("Could not allocate memory for vm_reflect");
return NULL;
}
ref->machine = mach;
ref->cpu = cpu;
ref->stream = stream;
ref->cpu_info = NULL;
ref->machine_info = NULL;
ref->pause = NULL;
ref->resume = NULL;
ref->disasm_on = NULL;
ref->disasm_off = NULL;
return ref;
}
/*
* Free a vm_reflect struct that we created earlier
*/
void
vm_reflect_free(vm_reflect *ref)
{
// Not much to this--just going to free the main memory chunk
free(ref);
}
/*
* All of the reflect functions do essentially the same thing--at least,
* right now they do.
*/
#define REFLECT(x) \
int vm_reflect_##x(vm_reflect *ref) { \
if (ref->x == NULL) return ERR_INVALID; ref->x(ref); return OK; }
REFLECT(cpu_info);
REFLECT(machine_info);
REFLECT(pause);
REFLECT(resume);
REFLECT(disasm_on);
REFLECT(disasm_off);

78
tests/vm_reflect.c Normal file
View File

@ -0,0 +1,78 @@
#include <criterion/criterion.h>
#include "apple2.h"
#include "vm_reflect.h"
static vm_reflect *ref;
static apple2 *mach;
/*
* This is a tiny function we can use that will satisfy the
* vm_reflect_fn type so we can test that all of those are working in
* the vm_reflect struct.
*/
static void
fun(vm_reflect *ref)
{
return;
}
static void
have_fun()
{
ref->cpu_info = fun;
ref->machine_info = fun;
ref->pause = fun;
ref->resume = fun;
ref->disasm_on = fun;
ref->disasm_off = fun;
}
static void
setup()
{
mach = apple2_create(100, 100);
ref = vm_reflect_create(mach, mach->cpu, stdout);
}
static void
teardown()
{
vm_reflect_free(ref);
apple2_free(mach);
}
TestSuite(vm_reflect, .init = setup, .fini = teardown);
Test(vm_reflect, create)
{
cr_assert_neq(ref, NULL);
cr_assert_eq(ref->cpu_info, NULL);
cr_assert_eq(ref->machine_info, NULL);
cr_assert_eq(ref->pause, NULL);
cr_assert_eq(ref->resume, NULL);
cr_assert_eq(ref->disasm_on, NULL);
cr_assert_eq(ref->disasm_off, NULL);
}
// Not much to do here
/* Test(vm_reflect, free) */
/*
* Because all of the reflect functions (aside from create/free) do the
* same thing, one test can stand in for all of them; hence the skips
* you see below.
*/
Test(vm_reflect, cpu_info)
{
// We should always try to have fun
have_fun();
cr_assert_eq(vm_reflect_cpu_info(ref), OK);
}
/* Test(vm_reflect, machine_info) */
/* Test(vm_reflect, pause) */
/* Test(vm_reflect, resume) */
/* Test(vm_reflect, disasm_on) */
/* Test(vm_reflect, disasm_off) */