1
0
mirror of https://github.com/pevans/erc-c.git synced 2025-02-21 04:29:10 +00:00
erc-c/src/vm_segment.c

136 lines
3.2 KiB
C
Raw Normal View History

2017-12-02 13:05:53 -06:00
/*
* vm_segment.c
*
2017-12-08 22:12:31 -06:00
* The functions here allow you to allocate generic blocks of memory (or
* "segments") for use anywhere else in the software. They can be used
* to represent machine memory, removable media (like floppy disks),
* etc.
2017-12-02 13:05:53 -06:00
*/
#include <stdio.h>
2017-11-21 23:24:51 -06:00
#include <stdlib.h>
#include <string.h>
#include "log.h"
#include "vm_segment.h"
2017-12-02 13:05:53 -06:00
/*
* Create a new segment, such that it contains a number of bytes indicated
* by `size`.
*/
2017-11-21 23:24:51 -06:00
vm_segment *
vm_segment_create(size_t size)
{
2017-12-02 13:05:53 -06:00
vm_segment *segment;
2017-11-21 23:24:51 -06:00
// Allocate memory for the current memory segment.
2017-12-02 13:05:53 -06:00
segment = malloc(sizeof(vm_segment));
2017-11-21 23:24:51 -06:00
// Ack! We couldn't get the memory we wanted. Let's bail.
2017-12-02 13:05:53 -06:00
if (segment == NULL) {
log_critical("Couldn't allocate enough space for vm_segment");
return NULL;
}
segment->memory = malloc(sizeof(vm_8bit) * size);
if (segment->memory == NULL) {
2017-11-21 23:24:51 -06:00
log_critical("Couldn't allocate enough space for vm_segment");
return NULL;
}
2017-12-02 13:05:53 -06:00
segment->size = size;
2017-11-21 23:24:51 -06:00
2017-12-02 13:05:53 -06:00
return segment;
2017-11-21 23:24:51 -06:00
}
2017-12-02 13:05:53 -06:00
/*
* Free the memory consumed by a given segment.
*/
2017-11-21 23:24:51 -06:00
void
2017-12-02 13:05:53 -06:00
vm_segment_free(vm_segment *segment)
{
free(segment->memory);
free(segment);
}
/*
* Set the byte in `segment`, at `index`, to the given `value`. Our
* bounds-checking here will _crash_ the program if we are
* out-of-bounds.
*/
void
vm_segment_set(vm_segment *segment, size_t index, vm_8bit value)
2017-11-21 23:24:51 -06:00
{
// Some bounds checking.
if (!vm_segment_bounds_check(segment, index)) {
log_critical(
"Attempt to set segment index (%d) greater than bounds (%d)",
index,
segment->size);
// We prefer to exit in this scenario, rather than try to
// "handle" it with an overflow, because we would rather a crash
// over ill-defined behavior.
exit(1);
}
segment->memory[index] = value;
}
2017-12-02 13:05:53 -06:00
/*
* Return the byte in `segment` at the given `index` point. Our
* bounds-checking will _crash_ the program if an index is requested out
* of bounds.
*/
vm_8bit
2017-11-21 23:24:51 -06:00
vm_segment_get(vm_segment *segment, size_t index)
{
if (!vm_segment_bounds_check(segment, index)) {
log_critical(
"Attempt to set segment index (%d) greater than bounds (%d)",
index,
segment->size);
// See vm_segment_set() for a justification of this behavior.
exit(1);
}
return segment->memory[index];
}
2017-12-02 13:05:53 -06:00
/*
* Copy a set of bytes from `src` (at `src_index`) to `dest` (at
* `dest_index`), such that the range is `length` bytes long.
*/
2017-11-21 23:24:51 -06:00
void
2017-12-02 13:05:53 -06:00
vm_segment_copy(vm_segment *dest,
vm_segment *src,
2017-11-21 23:24:51 -06:00
size_t dest_index,
2017-12-02 13:05:53 -06:00
size_t src_index,
2017-11-21 23:24:51 -06:00
size_t length)
{
if (src_index + length >= src->size) {
log_critical(
"Attempt to copy beyond bounds of vm_segment (%d + %d >= %d)",
src_index,
length,
src->size);
exit(1);
}
if (dest_index + length >= dest->size) {
log_critical(
"Attempt to copy beyond bounds of vm_segment (%d + %d >= %d)",
dest_index,
length,
dest->size);
exit(1);
}
memcpy(dest->memory + dest_index,
src->memory + src_index,
length * sizeof(src->memory[src_index]));
}