2017-11-22 05:24:51 +00:00
|
|
|
#ifndef _VM_SEGMENT_H_
|
|
|
|
#define _VM_SEGMENT_H_
|
|
|
|
|
2017-12-02 19:05:53 +00:00
|
|
|
#include "vm_bits.h"
|
2017-12-09 21:16:56 +00:00
|
|
|
#include "log.h"
|
2017-11-22 05:24:51 +00:00
|
|
|
|
2017-12-12 20:31:44 +00:00
|
|
|
/*
|
|
|
|
* Here we make a forward declaration of the vm_segment. (We also
|
|
|
|
* typedef that struct as `vm_segment`, so we don't have to say `struct
|
|
|
|
* vm_segment` everywhere.)
|
|
|
|
*/
|
|
|
|
struct vm_segment;
|
|
|
|
typedef struct vm_segment vm_segment;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The above forward declaration allows us to define the types for the
|
|
|
|
* read and write function signatures that we intend to use in the
|
|
|
|
* _definition_ of the vm_segment struct.
|
|
|
|
*
|
|
|
|
* C is fun! Don't let anyone tell you otherwise.
|
|
|
|
*/
|
2018-01-02 22:26:11 +00:00
|
|
|
typedef vm_8bit (*vm_segment_read_fn)(vm_segment *, size_t, void *);
|
|
|
|
typedef void (*vm_segment_write_fn)(vm_segment *, size_t, vm_8bit, void *);
|
2017-12-12 20:31:44 +00:00
|
|
|
|
2018-01-11 02:12:48 +00:00
|
|
|
#define SEGMENT_READER(x) \
|
|
|
|
vm_8bit x (vm_segment *segment, size_t addr, void *_mach)
|
|
|
|
|
|
|
|
#define SEGMENT_WRITER(x) \
|
|
|
|
void x (vm_segment *segment, size_t addr, vm_8bit value, void *_mach)
|
|
|
|
|
2017-12-07 03:37:14 +00:00
|
|
|
/*
|
|
|
|
* The bounds check is just some inline code to try and cut down on the
|
|
|
|
* cost of it.
|
|
|
|
*/
|
|
|
|
#define vm_segment_bounds_check(segment, index) \
|
|
|
|
(index == index % segment->size)
|
|
|
|
|
2017-12-12 20:31:44 +00:00
|
|
|
struct vm_segment {
|
|
|
|
|
2017-12-07 03:37:14 +00:00
|
|
|
/*
|
|
|
|
* The size of our memory segment. This is used for bounds checking.
|
|
|
|
*/
|
2017-11-22 05:24:51 +00:00
|
|
|
size_t size;
|
2017-12-07 03:37:14 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This is the actual chunk of memory we allocate.
|
|
|
|
*/
|
2017-12-02 19:05:53 +00:00
|
|
|
vm_8bit *memory;
|
2017-12-12 20:31:44 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* These are memory maps; if we have defined a non-NULL entry for a
|
|
|
|
* given address in read_table, then that is a function we will use
|
|
|
|
* to return the value for that address. Likewise, if we have a
|
|
|
|
* non-NULL entry in write_table, we will use that to "set" the
|
|
|
|
* value. As you may guess, these should conventionally be the
|
|
|
|
* exact size indicated by the size field.
|
|
|
|
*/
|
|
|
|
vm_segment_read_fn *read_table;
|
|
|
|
vm_segment_write_fn *write_table;
|
|
|
|
};
|
2017-11-22 05:24:51 +00:00
|
|
|
|
2017-12-09 21:16:56 +00:00
|
|
|
extern int vm_segment_copy(vm_segment *, vm_segment *, size_t, size_t, size_t);
|
2018-01-04 03:10:25 +00:00
|
|
|
extern int vm_segment_copy_buf(vm_segment *, const vm_8bit *, size_t, size_t, size_t);
|
2018-01-03 21:16:30 +00:00
|
|
|
extern int vm_segment_fread(vm_segment *, FILE *, size_t, size_t);
|
2018-02-04 02:50:08 +00:00
|
|
|
extern int vm_segment_fwrite(vm_segment *, FILE *, size_t, size_t);
|
2018-01-03 03:11:43 +00:00
|
|
|
extern int vm_segment_read_map(vm_segment *, size_t, vm_segment_read_fn);
|
2017-12-26 22:47:34 +00:00
|
|
|
extern int vm_segment_set(vm_segment *, size_t, vm_8bit);
|
2018-01-10 22:43:14 +00:00
|
|
|
extern int vm_segment_set16(vm_segment *, size_t, vm_16bit);
|
2018-01-03 03:11:43 +00:00
|
|
|
extern int vm_segment_write_map(vm_segment *, size_t, vm_segment_write_fn);
|
2018-01-05 22:14:51 +00:00
|
|
|
extern vm_16bit vm_segment_get16(vm_segment *, size_t);
|
2017-12-26 22:47:34 +00:00
|
|
|
extern vm_8bit vm_segment_get(vm_segment *, size_t);
|
|
|
|
extern vm_segment *vm_segment_create(size_t);
|
2018-01-08 02:00:09 +00:00
|
|
|
extern void *vm_segment_get_map_machine();
|
2017-12-26 22:47:34 +00:00
|
|
|
extern void vm_segment_free(vm_segment *);
|
2018-01-03 03:11:43 +00:00
|
|
|
extern void vm_segment_set_map_machine(void *);
|
2017-11-22 05:24:51 +00:00
|
|
|
|
|
|
|
#endif
|