Changed fill-column to 80, so more space for comments.
This commit is contained in:
55
lib/base.h
55
lib/base.h
@@ -91,8 +91,7 @@ typedef union
|
||||
} data_t;
|
||||
|
||||
/**
|
||||
@brief Enum of type tags for the data_t structure to provide
|
||||
context.
|
||||
@brief Enum of type tags for the data_t structure to provide context.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
@@ -116,11 +115,10 @@ static const hword_t __i = 0xFFFF0000;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@brief Safely subtract SUB from W, where both are words (64 bit
|
||||
integers).
|
||||
@brief Safely subtract SUB from W, where both are words (64 bit integers).
|
||||
|
||||
@details In case of underflow (i.e. where W - SUB < 0) returns 0
|
||||
instead of the underflowed result.
|
||||
@details In case of underflow (i.e. where W - SUB < 0) returns 0 instead of
|
||||
the underflowed result.
|
||||
*/
|
||||
#define WORD_SAFE_SUB(W, SUB) ((W) > (SUB) ? ((W) - (SUB)) : 0)
|
||||
|
||||
@@ -141,17 +139,15 @@ static const hword_t __i = 0xFFFF0000;
|
||||
/**
|
||||
@brief Return the Nth half word of WORD.
|
||||
|
||||
@details N should range from 0 to 1 as there are 2 half words in a
|
||||
word
|
||||
@details N should range from 0 to 1 as there are 2 half words in a word
|
||||
*/
|
||||
#define WORD_NTH_HWORD(WORD, N) (((WORD) >> ((N) * 32)) & 0xFFFFFFFF)
|
||||
|
||||
/**
|
||||
@brief Convert a buffer of bytes to a short
|
||||
|
||||
@details It is assumed that the buffer of bytes are in virtual
|
||||
machine byte code format (little endian) and that they are at least
|
||||
SHORT_SIZE in size.
|
||||
@details It is assumed that the buffer of bytes are in virtual machine byte
|
||||
code format (little endian) and that they are at least SHORT_SIZE in size.
|
||||
*/
|
||||
short_t convert_bytes_to_short(const byte_t *buffer);
|
||||
|
||||
@@ -161,17 +157,16 @@ short_t convert_bytes_to_short(const byte_t *buffer);
|
||||
|
||||
@param s: Short to convert
|
||||
|
||||
@param buffer: Buffer to store into. It is assumed that the buffer
|
||||
has at least SHORT_SIZE space.
|
||||
@param buffer: Buffer to store into. It is assumed that the buffer has at
|
||||
least SHORT_SIZE space.
|
||||
*/
|
||||
void convert_short_to_bytes(const short_t s, byte_t *buffer);
|
||||
|
||||
/**
|
||||
@brief Convert a buffer of bytes to a half word.
|
||||
|
||||
@details It is assumed that the buffer of bytes are in virtual
|
||||
machine byte code format (little endian) and that they are at least
|
||||
HWORD_SIZE in size.
|
||||
@details It is assumed that the buffer of bytes are in virtual machine byte
|
||||
code format (little endian) and that they are at least HWORD_SIZE in size.
|
||||
*/
|
||||
hword_t convert_bytes_to_hword(const byte_t *buffer);
|
||||
|
||||
@@ -181,36 +176,34 @@ hword_t convert_bytes_to_hword(const byte_t *buffer);
|
||||
|
||||
@param h: Half word to convert
|
||||
|
||||
@param buffer: Buffer to store into. It is assumed that the buffer
|
||||
has at least HWORD_SIZE space.
|
||||
@param buffer: Buffer to store into. It is assumed that the buffer has at
|
||||
least HWORD_SIZE space.
|
||||
*/
|
||||
void convert_hword_to_bytes(const hword_t h, byte_t *buffer);
|
||||
|
||||
/**
|
||||
@brief Convert a buffer of bytes to a word.
|
||||
|
||||
@details It is assumed that the buffer of bytes are in virtual
|
||||
machine byte code format (little endian) and that they are at least
|
||||
WORD_SIZE in size.
|
||||
@details It is assumed that the buffer of bytes are in virtual machine byte
|
||||
code format (little endian) and that they are at least WORD_SIZE in size.
|
||||
*/
|
||||
word_t convert_bytes_to_word(const byte_t *);
|
||||
|
||||
/**
|
||||
@brief Convert a word into a VM byte code format bytes (little
|
||||
endian)
|
||||
@brief Convert a word into a VM byte code format bytes (little endian)
|
||||
|
||||
@param w: Word to convert
|
||||
|
||||
@param buffer: Buffer to store into. It is assumed that the buffer
|
||||
has at least WORD_SIZE space.
|
||||
@param buffer: Buffer to store into. It is assumed that the buffer has at
|
||||
least WORD_SIZE space.
|
||||
*/
|
||||
void convert_word_to_bytes(const word_t w, byte_t *buffer);
|
||||
|
||||
/**
|
||||
@brief Swap the ordering of bytes within an short
|
||||
|
||||
@details The ordering of the bytes in the short are reversed (2
|
||||
bytes in a short).
|
||||
@details The ordering of the bytes in the short are reversed (2 bytes in a
|
||||
short).
|
||||
|
||||
@param s: short to swap
|
||||
*/
|
||||
@@ -219,8 +212,8 @@ short_t short_byteswap(const short_t s);
|
||||
/**
|
||||
@brief Swap the ordering of bytes within an half word
|
||||
|
||||
@details The ordering of the bytes in the half word are reversed (4
|
||||
bytes in a half word).
|
||||
@details The ordering of the bytes in the half word are reversed (4 bytes in
|
||||
a half word).
|
||||
|
||||
@param h: Half word to swap
|
||||
*/
|
||||
@@ -229,8 +222,8 @@ hword_t hword_byteswap(const hword_t h);
|
||||
/**
|
||||
@brief Swap the ordering of bytes within an word
|
||||
|
||||
@details The ordering of the bytes in the word are reversed (8
|
||||
bytes in a word).
|
||||
@details The ordering of the bytes in the word are reversed (8 bytes in a
|
||||
word).
|
||||
|
||||
@param w: Word to swap
|
||||
*/
|
||||
|
||||
63
lib/darr.h
63
lib/darr.h
@@ -42,10 +42,10 @@ typedef struct
|
||||
/**
|
||||
@brief Get the `IND`th item of type `TYPE` in `DARR_DATA`
|
||||
|
||||
@details Cast `DARR_DATA` to `TYPE`, taking the `IND`th item.
|
||||
NOTE: This is unsafe as bound checks are not done i.e. if
|
||||
`DARR_DATA` has at least space for `IND` * sizeof(`TYPE`) items.
|
||||
It is presumed the caller will check themselves.
|
||||
@details Cast `DARR_DATA` to `TYPE`, taking the `IND`th item. NOTE: This is
|
||||
unsafe as bound checks are not done i.e. if `DARR_DATA` has at least space
|
||||
for `IND` * sizeof(`TYPE`) items. It is presumed the caller will check
|
||||
themselves.
|
||||
|
||||
@param[TYPE] Type to cast internal byte array
|
||||
@param[DARR_DATA] Byte array of darr
|
||||
@@ -58,24 +58,23 @@ typedef struct
|
||||
/**
|
||||
@brief Initialise a dynamic array `darr` with n bytes of space.
|
||||
|
||||
@details All properties of `darr` are initialised. `darr`.used is
|
||||
set to 0, `darr`.available is set to `n` and `darr`.data is set to
|
||||
a pointer of `n` bytes. NOTE: If `n` = 0 then it is set to
|
||||
DARR_DEFAULT_SIZE
|
||||
@details All properties of `darr` are initialised. `darr`.used is set to 0,
|
||||
`darr`.available is set to `n` and `darr`.data is set to a pointer of `n`
|
||||
bytes. NOTE: If `n` = 0 then it is set to DARR_DEFAULT_SIZE
|
||||
|
||||
@param[darr] Pointer to darr_t object to initialise
|
||||
@param[n] Number of bytes to allocate. If equal to 0 then
|
||||
considered treated as DARR_DEFAULT_SIZE
|
||||
@param[n] Number of bytes to allocate. If equal to 0 then considered treated
|
||||
as DARR_DEFAULT_SIZE
|
||||
*/
|
||||
void darr_init(darr_t *darr, size_t n);
|
||||
|
||||
/**
|
||||
@brief Ensure a dynamic array has at least n bytes of space free.
|
||||
|
||||
@details If `darr` has n or more bytes free, nothing occurs.
|
||||
Otherwise, the byte array in `darr` is reallocated such that it has
|
||||
at least `n` bytes of free space. NOTE: `darr` has at least `n`
|
||||
bytes free if and only if `darr`.used + `n` <= `darr`.available
|
||||
@details If `darr` has n or more bytes free, nothing occurs. Otherwise, the
|
||||
byte array in `darr` is reallocated such that it has at least `n` bytes of
|
||||
free space. NOTE: `darr` has at least `n` bytes free if and only if
|
||||
`darr`.used + `n` <= `darr`.available
|
||||
|
||||
@param[darr] Dynamic array to check
|
||||
@param[n] Number of bytes
|
||||
@@ -85,10 +84,9 @@ void darr_ensure_capacity(darr_t *darr, size_t n);
|
||||
/**
|
||||
@brief Append a byte to a dynamic array.
|
||||
|
||||
@details Append a byte to the end of the byte buffer in a dyamic
|
||||
array. If the dynamic array doesn't have enough free space to fit
|
||||
the byte, it will reallocate to ensure it can fit it in via
|
||||
darr_ensure_capacity().
|
||||
@details Append a byte to the end of the byte buffer in a dyamic array. If
|
||||
the dynamic array doesn't have enough free space to fit the byte, it will
|
||||
reallocate to ensure it can fit it in via darr_ensure_capacity().
|
||||
|
||||
@param[darr] Dynamic arrary to append to
|
||||
@param[b] Byte to append
|
||||
@@ -98,10 +96,9 @@ void darr_append_byte(darr_t *darr, byte_t b);
|
||||
/**
|
||||
@brief Append an array of n bytes to a dynamic array.
|
||||
|
||||
@details Append an array of bytes to the end of a byte buffer. If
|
||||
the dynamic array doesn't have enough free space to fit all n bytes
|
||||
it will reallocate to ensure it can fit it in via
|
||||
darr_ensure_capacity().
|
||||
@details Append an array of bytes to the end of a byte buffer. If the
|
||||
dynamic array doesn't have enough free space to fit all n bytes it will
|
||||
reallocate to ensure it can fit it in via darr_ensure_capacity().
|
||||
|
||||
@param[darr] Dynamic array to append to
|
||||
@param[b] Array of bytes to append
|
||||
@@ -112,9 +109,9 @@ void darr_append_bytes(darr_t *darr, byte_t *b, size_t n);
|
||||
/**
|
||||
@brief Get the nth byte of a dynamic array
|
||||
|
||||
@details Get the nth byte of the dynamic array. 0 based. NOTE: If
|
||||
the dynamic array has less than n bytes used, it will return 0 as a
|
||||
default value, so this is a safe alternative to DARR_AT().
|
||||
@details Get the nth byte of the dynamic array. 0 based. NOTE: If the
|
||||
dynamic array has less than n bytes used, it will return 0 as a default
|
||||
value, so this is a safe alternative to DARR_AT().
|
||||
|
||||
@param[darr] Dynamic array to index
|
||||
@param[n] Index to get byte at
|
||||
@@ -126,9 +123,9 @@ byte_t *darr_at(darr_t *darr, size_t n);
|
||||
/**
|
||||
@brief Write the bytes of a dynamic array to a file pointer
|
||||
|
||||
@details Given a dynamic array and a file pointer, write the
|
||||
internal buffer of bytes to the file pointer. NOTE: The file
|
||||
pointer is assumed to be open and suitable for writing.
|
||||
@details Given a dynamic array and a file pointer, write the internal buffer
|
||||
of bytes to the file pointer. NOTE: The file pointer is assumed to be open
|
||||
and suitable for writing.
|
||||
|
||||
@param[darr] Dynamic array to write
|
||||
@param[fp] File pointer to write on
|
||||
@@ -138,14 +135,14 @@ void darr_write_file(darr_t *darr, FILE *fp);
|
||||
/**
|
||||
@brief Read a file pointer in its entirety into a dynamic array
|
||||
|
||||
@details Read a file pointer as a buffer of bytes then return that
|
||||
buffer wrapped in a darr_t structure. NOTE: the file pointer is
|
||||
assumed to be open and suitable for reading.
|
||||
@details Read a file pointer as a buffer of bytes then return that buffer
|
||||
wrapped in a darr_t structure. NOTE: the file pointer is assumed to be open
|
||||
and suitable for reading.
|
||||
|
||||
@param[fp]: File pointer to read
|
||||
|
||||
@return Dynamic array structure with available set to the size of
|
||||
the `buffer` read and `data` set to the buffer of bytes.
|
||||
@return Dynamic array structure with available set to the size of the
|
||||
`buffer` read and `data` set to the buffer of bytes.
|
||||
*/
|
||||
darr_t darr_read_file(FILE *fp);
|
||||
|
||||
|
||||
@@ -59,8 +59,7 @@ bool heap_free(heap_t *heap, page_t *page)
|
||||
if (cur == page)
|
||||
{
|
||||
page_delete(cur);
|
||||
// TODO: When does this fragmentation become a performance
|
||||
// issue?
|
||||
// TODO: When does this fragmentation become a performance issue?
|
||||
DARR_AT(page_t *, heap->page_vec.data, i) = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
34
lib/heap.h
34
lib/heap.h
@@ -26,8 +26,8 @@
|
||||
/**
|
||||
@brief Some fixed portion of bytes allocated on the heap.
|
||||
|
||||
@details A fixed allocation of bytes. Cannot be resized nor can it
|
||||
be stack allocated (the usual way) due to flexible array attached.
|
||||
@details A fixed allocation of bytes. Cannot be resized nor can it be stack
|
||||
allocated (the usual way) due to flexible array attached.
|
||||
|
||||
@prop[next] Next page in the linked list
|
||||
@prop[available] Available number of bytes in page
|
||||
@@ -42,9 +42,8 @@ typedef struct Page
|
||||
/**
|
||||
@brief Allocate a new page on the heap with the given properties.
|
||||
|
||||
@details Allocates a new page using malloc with the given size and
|
||||
pointer to next page. NOTE: all memory is 0 initialised by
|
||||
default.
|
||||
@details Allocates a new page using malloc with the given size and pointer to
|
||||
next page. NOTE: all memory is 0 initialised by default.
|
||||
|
||||
@param[max] Maximum available memory in page
|
||||
*/
|
||||
@@ -53,9 +52,8 @@ page_t *page_create(size_t max);
|
||||
/**
|
||||
@brief Delete a page, freeing its memory
|
||||
|
||||
@details Free's the memory associated with the page via free().
|
||||
NOTE: any pointers to the page's memory are considered invalid once
|
||||
this is called.
|
||||
@details Free's the memory associated with the page via free(). NOTE: any
|
||||
pointers to the page's memory are considered invalid once this is called.
|
||||
|
||||
@param[page] Page to delete
|
||||
*/
|
||||
@@ -65,8 +63,8 @@ void page_delete(page_t *page);
|
||||
@brief A collection of pages through which generic allocations can
|
||||
occur.
|
||||
|
||||
@details Collection of pages maintained through a vector of
|
||||
pointers to pages.
|
||||
@details Collection of pages maintained through a vector of pointers to
|
||||
pages.
|
||||
|
||||
@prop[page_vec] Vector of pages
|
||||
*/
|
||||
@@ -80,9 +78,8 @@ typedef struct
|
||||
/**
|
||||
@brief Instantiate a new heap structure
|
||||
|
||||
@details Initialises the heap structure given. No heap allocation
|
||||
occurs here until a new page is created, so this may be called
|
||||
safely.
|
||||
@details Initialises the heap structure given. No heap allocation occurs
|
||||
here until a new page is created, so this may be called safely.
|
||||
|
||||
@param[heap] Pointer to heap to initialise
|
||||
*/
|
||||
@@ -91,8 +88,8 @@ void heap_create(heap_t *heap);
|
||||
/**
|
||||
@brief Allocate a new page on the heap
|
||||
|
||||
@details Creates and joins a new page onto the linked list
|
||||
maintained by the heap. heap.end is set to this new page.
|
||||
@details Creates and joins a new page onto the linked list maintained by the
|
||||
heap. heap.end is set to this new page.
|
||||
|
||||
@param[heap] Heap to create a new page on
|
||||
@param[size] Size of page to allocate
|
||||
@@ -104,10 +101,9 @@ page_t *heap_allocate(heap_t *heap, size_t size);
|
||||
/**
|
||||
@brief Free a page of memory from the heap
|
||||
|
||||
@details The page given is removed from the linked list of pages
|
||||
then freed from the heap via page_delete(). If the page does not
|
||||
belong to this heap (O(heap.pages) time) then false is returned,
|
||||
otherwise true.
|
||||
@details The page given is removed from the linked list of pages then freed
|
||||
from the heap via page_delete(). If the page does not belong to this heap
|
||||
(O(heap.pages) time) then false is returned, otherwise true.
|
||||
|
||||
@param[heap] Heap to free page from
|
||||
@param[page] Page to delete
|
||||
|
||||
26
lib/inst.h
26
lib/inst.h
@@ -210,10 +210,10 @@ typedef struct
|
||||
/**
|
||||
@brief Serialise an instruction into a byte buffer
|
||||
|
||||
@details Given an instruction and a suitably sized byte buffer,
|
||||
write the bytecode for the instruction into the buffer. NOTE: This
|
||||
function does NOT check the bounds of `bytes` i.e. we assume the
|
||||
caller has created a suitably sized buffer.
|
||||
@details Given an instruction and a suitably sized byte buffer, write the
|
||||
bytecode for the instruction into the buffer. NOTE: This function does NOT
|
||||
check the bounds of `bytes` i.e. we assume the caller has created a suitably
|
||||
sized buffer.
|
||||
|
||||
@param[inst] Instruction to serialise
|
||||
@param[bytes] Buffer to write on
|
||||
@@ -233,21 +233,19 @@ typedef enum
|
||||
/**
|
||||
@brief Deserialise an instruction from a bytecode buffer
|
||||
|
||||
@details Given a buffer of bytes, deserialise an instruction,
|
||||
storing the result in the pointer given. The number of bytes read
|
||||
in the buffer is returned, which should be opcode_bytecode_size().
|
||||
NOTE: If bytes is not suitably sized for the instruction expected
|
||||
or it is not well formed i.e. not the right schema then a negative
|
||||
number is returned.
|
||||
@details Given a buffer of bytes, deserialise an instruction, storing the
|
||||
result in the pointer given. The number of bytes read in the buffer is
|
||||
returned, which should be opcode_bytecode_size(). NOTE: If bytes is not
|
||||
suitably sized for the instruction expected or it is not well formed i.e. not
|
||||
the right schema then a negative number is returned.
|
||||
|
||||
@param[inst] Pointer to instruction which will store result
|
||||
@param[bytes] Bytecode buffer to deserialise
|
||||
@param[size_bytes] Number of bytes in buffer
|
||||
|
||||
@return[int] Number of bytes read. If negative then an error
|
||||
occurred in deserialisation (either buffer was not suitably sized
|
||||
or instruction was not well formed) so any result must be
|
||||
considered invalid.
|
||||
@return[int] Number of bytes read. If negative then an error occurred in
|
||||
deserialisation (either buffer was not suitably sized or instruction was not
|
||||
well formed) so any result must be considered invalid.
|
||||
*/
|
||||
int inst_read_bytecode(inst_t *inst, byte_t *bytes, size_t size_bytes);
|
||||
|
||||
|
||||
@@ -70,8 +70,8 @@ void test_lib_darr_ensure_capacity_expands(void)
|
||||
{10, 10, 10, 20},
|
||||
{50, 100, 300, 350},
|
||||
{1 << 20, 2 << 20, 2 << 20, 3 << 20},
|
||||
// When we reallocate we allocate MORE than needed (for
|
||||
// amortized constant)
|
||||
// When we reallocate we allocate MORE than needed (for amortized
|
||||
// constant)
|
||||
{1, 5, 5, 10},
|
||||
{85, 100, 40, 200},
|
||||
{4 << 20, 5 << 20, 1 << 23, 5 << 21},
|
||||
|
||||
@@ -60,8 +60,7 @@ int main(int argc, char *argv[])
|
||||
else if (program.count == 0)
|
||||
return 0;
|
||||
|
||||
// After reading header, we can allocate the buffer of instrutions
|
||||
// exactly
|
||||
// After reading header, we can allocate the buffer of instrutions exactly
|
||||
program.instructions = calloc(program.count, sizeof(*program.instructions));
|
||||
size_t bytes_read = 0;
|
||||
read_err_prog_t read_err =
|
||||
|
||||
16
vm/runtime.c
16
vm/runtime.c
@@ -98,11 +98,10 @@ err_t vm_execute(vm_t *vm)
|
||||
"Code using OPCODE_DATA_TYPE for quick same type opcode "
|
||||
"conversion may be out of date.");
|
||||
|
||||
// NOTE: We always use the first register to hold the result of
|
||||
// this pop.
|
||||
// NOTE: We always use the first register to hold the result of this pop.
|
||||
|
||||
// Here we add OP_MOV_BYTE and the data_type_t of the opcode to
|
||||
// get the right typed OP_MOV opcode.
|
||||
// Here we add OP_MOV_BYTE and the data_type_t of the opcode to get the
|
||||
// right typed OP_MOV opcode.
|
||||
opcode_t mov_opcode =
|
||||
OPCODE_DATA_TYPE(instruction.opcode, OP_POP) + OP_MOV_BYTE;
|
||||
|
||||
@@ -152,8 +151,8 @@ err_t vm_execute(vm_t *vm)
|
||||
"conversion may be out of date.");
|
||||
|
||||
data_t datum = {0};
|
||||
// Here we add OP_POP_BYTE and the data_type_t of the opcode to
|
||||
// get the right OP_POP opcode.
|
||||
// Here we add OP_POP_BYTE and the data_type_t of the opcode to get the
|
||||
// right OP_POP opcode.
|
||||
opcode_t pop_opcode =
|
||||
OPCODE_DATA_TYPE(instruction.opcode, OP_JUMP_IF) + OP_POP_BYTE;
|
||||
|
||||
@@ -228,9 +227,8 @@ err_t vm_execute(vm_t *vm)
|
||||
|
||||
// 2) create a format string for each datum type possible
|
||||
|
||||
// TODO: Figure out a way to ensure the ordering of OP_PRINT_* is
|
||||
// exactly BYTE, SBYTE, SHORT, SSHORT, HWORD, SHWORD, WORD, SWORD
|
||||
// via static_assert
|
||||
// TODO: Figure out a way to ensure the ordering of OP_PRINT_* is exactly
|
||||
// BYTE, SBYTE, SHORT, SSHORT, HWORD, SHWORD, WORD, SWORD via static_assert
|
||||
|
||||
// lookup table
|
||||
const char *format_strings[] = {
|
||||
|
||||
Reference in New Issue
Block a user