mirror of
https://github.com/pevans/erc-c.git
synced 2024-11-30 08:51:53 +00:00
Add reflect system to virtual machine
This commit is contained in:
parent
149df404ac
commit
c1c42834ed
69
include/vm_reflect.h
Normal file
69
include/vm_reflect.h
Normal 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
|
@ -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
62
src/vm_reflect.c
Normal 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
78
tests/vm_reflect.c
Normal 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) */
|
Loading…
Reference in New Issue
Block a user