Generated Documentation#
-
namespace mizu#
Typedefs
-
using reg_t = uint16_t#
-
using instruction_t = void *(*)(struct opcode *pc, uint64_t *registers, struct registers_and_stack *env, uint8_t *sp)#
Function pointer type representing the interface every instruction is expected to have
Functions
-
constexpr reg_t x(std::size_t i)#
Generic register lookup
- Parameters:
i – The register’s index
- Returns:
constexpr reg_t associated value to store in an opcode
-
constexpr reg_t t(std::size_t i)#
Temporary register lookup
- Parameters:
i – The temporary register’s index
- Returns:
constexpr reg_t associated value to store in an opcode
-
constexpr reg_t a(std::size_t i)#
Argument register lookup
- Parameters:
i – The argument register’s index
- Returns:
constexpr reg_t associated value to store in an opcode
-
inline fp::dynarray<std::byte> to_portable(fp::view<const opcode> program, fp::view<std::byte> data = {nullptr, 0})#
Converts a Mizu
programand somedatainto a portable program that can executed anywhereNote
This function makes no account of different machine endianness or pointer sizes.
- Parameters:
program – The program to serialize
data – The data to put at the bottom of the program’s stack
- Returns:
fp::dynarray<std::byte> a dynamically allocated array of bytes representing the serialized program
-
inline fp::dynarray<std::byte> to_portable(fp::view<const opcode> program, registers_and_stack &env)#
Converts a Mizu
programand anenvinto a snapshot of a portable program that can executed anywhereNote
This function makes no account of different machine endianness or pointer sizes.
- Parameters:
program – The program to snapshot
env – The program enviornment to snapshot
- Returns:
fp::dynarray<std::byte> a dynamically allocated array of bytes representing the serialized program
-
inline std::pair<fp::dynarray<opcode>, registers_and_stack> from_portable(fp::view<const std::byte> binary)#
Converts a blob of
binarydata storing a portable Mizu program and stack data back into a Mizu program.Note
This function makes no account of different machine endianness or pointer sizes.
- Parameters:
binary – The binary blob to deserialize
- Returns:
std::pair<fp::dynarray<opcode>, registers_and_stack> a dynamically allocated Mizu program and its enviornment
-
inline fp::string generate_header_file(fp::view<opcode> program, registers_and_stack &env, fp::string_view extra_includes = fp::string_view::from_cstr(""))#
Generates a C++ header file representing the provided Mizu
programandenv.- Parameters:
program – The program to generate a header for.
env – The enviornment the program should begin executing in.
extra_includes – If the program requires extra instruction headers (like SIMD or custom) they should be listed (one per line, including the #include) here
- Returns:
fp::string a string storing the resulting headerfile.
-
inline fp::dynarray<std::byte> to_binary(fp::view<const opcode> _program)#
Converts a Mizu
programinto a byte array ready to be written to a file or sent over the network.Note
This function makes no account of different machine endianness or pointer sizes.
- Parameters:
program – The program to serialize
- Returns:
fp::dynarray<std::byte> a dynamically allocated array of bytes representing the serialized program
-
inline fp::dynarray<opcode> from_binary(fp::view<const std::byte> binary)#
Converts a blob of
binarydata into a Mizu programNote
This function makes no account of different machine endianness or pointer sizes.
- Parameters:
binary – The binary blob to deserialize
- Returns:
fp::dynarray<opcode> a dynamically allocated Mizu program
-
constexpr uint32_t label2immediate(const fp_string_view label)#
Converts a string label to an immediate value
Note
Only the first 4 characters of the label are relevant.
- Parameters:
label – string_view to be converted
- Returns:
constexpr uint32_t the immediate
-
constexpr uint32_t label2immediate(const fp_string label)#
Converts a string label to an immediate value
Note
Only the first 4 characters of the label are relevant.
- Parameters:
label – string to be converted
- Returns:
constexpr uint32_t the immediate
-
void *label(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Noop which marks a label that can be found using mizu::find_label and then jumped to using mizu::jump_to
Note
mizu::label2int can convert a string into an immediate for this function
- Parameters:
immediate – Integer label value
-
void *find_label(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Finds the provided label and stores a pointer to it in
outNote
Unlike every other assembly this is a runtime function, time is spent scanning the program to find the label. It is this recommended to cluster these instructions near the beginning of the program where they won’t be executed multiple times.
Note
This function first searches below it in the program then searches above it if the label can’t be found. The closest matching label following these rules will be found if there is any ambiguity.
- Parameters:
out – register to store the label pointer in
immediate – the label to search for
-
void *halt(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Ends execution of the program or thread.
-
void *debug_print(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Prints the value stored in a register in several formats
- Parameters:
a – the register to print the value of
-
void *debug_print_binary(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Prints the value stored in a register in several formats including binary
- Parameters:
a – the register to print the value of
-
void *load_immediate(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Stores an immediate value into a register
Note
Since immediate are only 32bit numbers this function sets the bottom 32 bits of our 64 bit registers.
- Parameters:
out – the register to update
immediate – the value to store in
out
-
void *load_upper_immediate(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Stores an immediate value into a register shifting it so that its content fills the upper 32bits.
Warning
The load immediate instruction overwrites the entire register, thus it should be called before load_upper_immediate!
- Parameters:
out – the register to update
immediate – the value to store in
out
-
void *convert_to_u64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Converts a register to a 64 bit integer.
- Parameters:
out – register to store the result in
a – register whose value to convert
-
void *convert_to_u32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Converts a register to a 32 bit integer.
- Parameters:
out – register to store the result in
a – register whose value to convert
-
void *convert_to_u16(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Converts a register to a 16 bit integer.
- Parameters:
out – register to store the result in
a – register whose value to convert
-
void *convert_to_u8(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Converts a register to an 8 bit integer.
- Parameters:
out – register to store the result in
a – register whose value to convert
-
void *stack_load_u64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Loads a 64 bit integer from the stack
- Parameters:
out – register to store the result in
a – register storing an offset to the current stack pointer (defaults to zero bytes)
-
void *stack_store_u64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Copies a 64 bit integer from a register to the stack.
- Parameters:
out – register to store another copy in
a – register storing the value to copy
b – register storing an offset to the current stack pointer (defaults to zero bytes)
-
void *stack_load_u32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Loads a 32 bit integer from the stack
- Parameters:
out – register to store the result in
a – register storing an offset to the current stack pointer (defaults to zero bytes)
-
void *stack_store_u32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Copies a 32 bit integer from a register to the stack.
- Parameters:
out – register to store another copy in
a – register storing the value to copy
b – register storing an offset to the current stack pointer (defaults to zero bytes)
-
void *stack_load_u16(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Loads a 16 bit integer from the stack
- Parameters:
out – register to store the result in
a – register storing an offset to the current stack pointer (defaults to zero bytes)
-
void *stack_store_u16(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Copies a 16 bit integer from a register to the stack.
- Parameters:
out – register to store another copy in
a – register storing the value to copy
b – register storing an offset to the current stack pointer (defaults to zero bytes)
-
void *stack_load_u8(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Loads an 8 bit integer from the stack
- Parameters:
out – register to store the result in
a – register storing an offset to the current stack pointer (defaults to zero bytes)
-
void *stack_store_u8(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Copies a 8 bit integer from a register to the stack.
- Parameters:
out – register to store another copy in
a – register storing the value to copy
b – register storing an offset to the current stack pointer (defaults to zero bytes)
-
void *stack_push(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Subtracts a value from the stack pointer. In other words reserves some additional memory on the stack.
- Parameters:
a – register storing how many bytes to reserve
-
void *stack_push_immediate(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Subtracts a value from the stack pointer. In other words reserves some additional memory on the stack.
- Parameters:
immediate – how many bytes to reserve
-
void *stack_pop(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds a value to stack pointer. In other words releases reserved memory on the stack.
- Parameters:
a – register storing how many bytes to release
-
void *stack_pop_immediate(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds a value to stack pointer. In other words releases reserved memory on the stack.
- Parameters:
immediate – how many bytes to release
-
void *offset_of_stack_bottom(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Returns the offset needed to load/store to the bottom of the stack
- Parameters:
out – register to store the calculated offset in
a – register storing a signed offset relative to the bottom of the stack
-
void *jump_relative(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Moves the program counter by an offset. If the offset is zero this instruction is executed again. If it is one the next instruction is executed as usual. If it is negative a previous instruction is executed.
Note
ais interpreted as a signed integer, allowing for negative jumps- Parameters:
out – register to store the address of the instruction that should be executed next.
a – register storing how many instructions to jump
-
void *jump_relative_immediate(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Moves the program counter by an offset. If the offset is zero this instruction is executed again. If it is one the next instruction is executed as usual. If it is negative a previous instruction is executed.
Note
immediateis interpreted as a signed integer, allowing for negative jumps- Parameters:
out – register to store the address of the instruction that should be executed next.
immediate – how many instructions to jump
-
void *jump_to(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Sets the program counter to a value (usually the output of another jump)
- Parameters:
out – register to store the address of the instruction that should be executed next.
a – register storing the address of the instruction to jump to.
-
void *branch_relative(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Moves the program counter by an offset similar to a jump, however only does so if the condition register is not zero
Note
bis interpreted as a signed integer, allowing for negative jumps- Parameters:
out – register to store the address of the instruction that should be executed next.
a – register storing a condition, zero indicates no jump while any other number indicates that a jump should occur
b – register storing how many instructions to jump
-
void *branch_relative_immediate(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Moves the program counter by an offset similar to a jump, however only does so if the condition register is not zero
Note
bis interpreted as a signed integer, allowing for negative jumps- Parameters:
out – register to store the address of the instruction that should be executed next.
a – register storing a condition, zero indicates no jump while any other number indicates that a jump should occur
b – (branch immediate) how many instructions to jump
-
void *branch_to(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Sets the program counter to a value (usually the output of another jump), however only does so if the condition register is not zero
- Parameters:
out – register to store the address of the instruction that should be executed next.
a – register storing a condition, zero indicates no jump while any other number indicates that a jump should occur
b – register storing the address of the instruction to jump to.
-
void *set_if_equal(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if two registers are equal
- Parameters:
out – register to be set to one if
a==bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_not_equal(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if two registers are not equal
- Parameters:
out – register to be set to one if
a!=bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_less(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a register is less than another
- Parameters:
out – register to be set to one if
a<bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_less_signed(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a register is less than another
Note
Both
aandbare treated as being signed- Parameters:
out – register to be set to one if
a==bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_greater_equal(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a register is greater or equal to another
- Parameters:
out – register to be set to one if
a>=bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_greater_equal_signed(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a register is greater or equal to another
Note
Both
aandbare treated as being signed- Parameters:
out – register to be set to one if
a>=bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *add(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds two numbers
- Parameters:
out – register to store
a+bina – register storing first value
b – register storing second value
-
void *subtract(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Subtracts two numbers
- Parameters:
out – register to store
a-bina – register storing first value
b – register storing second value
-
void *multiply(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Multiplies two numbers
- Parameters:
out – register to store
a*bina – register storing first value
b – register storing second value
-
void *divide(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Divides two numbers
- Parameters:
out – register to store
a/bina – register storing first value
b – register storing second value
-
void *modulus(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Finds the remainder of the division of two numbers
- Parameters:
out – register to store
a%bina – register storing first value
b – register storing second value
-
void *shift_left(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Shifts one number left by another
- Parameters:
out – register to store
a<<bina – register storing first value
b – register storing second value
-
void *shift_right_logical(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Shifts one number right by another
- Parameters:
out – register to store
a>>bina – register storing first value
b – register storing second value
-
void *shift_right_arithmetic(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Shifts one number right by another, sign extending it
- Parameters:
out – register to store
a>>bina – register storing first value
b – register storing second value
-
void *bitwise_xor(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Xor’s two numbers
- Parameters:
out – register to store
a^bina – register storing first value
b – register storing second value
-
void *bitwise_and(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
And’s two numbers
- Parameters:
out – register to store
a&bina – register storing first value
b – register storing second value
-
void *bitwise_or(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Or’s two numbers
- Parameters:
out – register to store
a|bina – register storing first value
b – register storing second value
-
void *convert_to_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Converts the provided register into a float register
- Parameters:
out – Register to store the result of the conversion in
a – Register to convert to an f32
-
void *convert_signed_to_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Converts the provided (signed) register into a float register
- Parameters:
out – Register to store the result of the conversion in
a – Register to convert to an f32
-
void *convert_from_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Truncates the provided float register and stores it in the given register (as an unsigned number)
- Parameters:
out – Register to store the result of the conversion in
a – Float register to convert to a u64
-
void *convert_signed_from_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Truncates the provided float register and stores it in the given register
- Parameters:
out – Register to store the result of the conversion in
a – Float register to convert to an i64
-
void *add_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds two f32 numbers
Note
Both
aandbmust be f32s. If they aren’t they should be converted first- Parameters:
out – register to store
a+bina – register storing first value
b – register storing second value
-
void *subtract_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Subtracts two f32 numbers
Note
Both
aandbmust be f32s. If they aren’t they should be converted first- Parameters:
out – register to store
a-bina – register storing first value
b – register storing second value
-
void *multiply_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Multiplies two f32 numbers
Note
Both
aandbmust be f32s. If they aren’t they should be converted first- Parameters:
out – register to store
a*bina – register storing first value
b – register storing second value
-
void *divide_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Divides two f32 numbers
Note
Both
aandbmust be f32s. If they aren’t they should be converted first- Parameters:
out – register to store
a/bina – register storing first value
b – register storing second value
-
void *max_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Finds the max of two f32 numbers
Note
Both
aandbmust be f32s. If they aren’t they should be converted first- Parameters:
out – register to store max(
a,b) ina – register storing first value
b – register storing second value
-
void *min_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Finds the min of two f32 numbers
Note
Both
aandbmust be f32s. If they aren’t they should be converted first- Parameters:
out – register to store min(
a,b) ina – register storing first value
b – register storing second value
-
void *sqrt_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Finds the square root of a f32 number
- Parameters:
out – register to store sqrt(
a) ina – register storing the value
-
void *set_if_equal_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if two f32 registers are equal
Note
Both
aandbmust be f32s. If they aren’t they should be converted first- Parameters:
out – register to be set to one if
a==bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_not_equal_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if two f32 registers are not equal
Note
Both
aandbmust be f32s. If they aren’t they should be converted first- Parameters:
out – register to be set to one if
a!=bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_less_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if one f32 register is less than another
Note
Both
aandbmust be f32s. If they aren’t they should be converted first- Parameters:
out – register to be set to one if
a<bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_greater_equal_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if one f32 register is greater or equal to another
Note
Both
aandbmust be f32s. If they aren’t they should be converted first- Parameters:
out – register to be set to one if
a>=bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_negative_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a f32 register is negative
- Parameters:
out – register to be set to one if
a< 0 or zero otherwisea – register storing the value to compare
-
void *set_if_positive_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a f32 register is positive
- Parameters:
out – register to be set to one if
a> 0 or zero otherwisea – register storing the value to compare
-
void *set_if_infinity_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a f32 register is an infinity
- Parameters:
out – register to be set to one if
a== +/- infinity or zero otherwisea – register storing the value to compare
-
void *set_if_nan_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a f32 register is nan
- Parameters:
out – register to be set to one if
a== nan or zero otherwisea – register storing the value to compare
-
void *convert_f32_to_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Converts the provided f32 register to an f64 register
- Parameters:
out – Register to store the f64 result in
a – Register storing the f32 to convert
-
void *convert_f64_to_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Converts the provided f64 register to an f32 register
- Parameters:
out – Register to store the f32 result in
a – Register storing the f64 to convert
-
void *convert_to_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Converts the provided register into a float register
- Parameters:
out – Register to store the result of the conversion in
a – Register to convert to an f64
-
void *convert_signed_to_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Converts the provided (signed) register into a float register
- Parameters:
out – Register to store the result of the conversion in
a – Register to convert to an f64
-
void *convert_from_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Truncates the provided float register and stores it in the given register (as an unsigned number)
- Parameters:
out – Register to store the result of the conversion in
a – Float register to convert to a u64
-
void *convert_signed_from_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Truncates the provided float register and stores it in the given register
- Parameters:
out – Register to store the result of the conversion in
a – Float register to convert to an i64
-
void *add_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds two f64 numbers
Note
Both
aandbmust be f64s. If they aren’t they should be converted first- Parameters:
out – register to store
a+bina – register storing first value
b – register storing second value
-
void *subtract_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Subtracts two f64 numbers
Note
Both
aandbmust be f64s. If they aren’t they should be converted first- Parameters:
out – register to store
a-bina – register storing first value
b – register storing second value
-
void *multiply_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Multiplies two f64 numbers
Note
Both
aandbmust be f64s. If they aren’t they should be converted first- Parameters:
out – register to store
a*bina – register storing first value
b – register storing second value
-
void *divide_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Divides two f64 numbers
Note
Both
aandbmust be f64s. If they aren’t they should be converted first- Parameters:
out – register to store
a/bina – register storing first value
b – register storing second value
-
void *max_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Finds the max of two f64 numbers
Note
Both
aandbmust be f64s. If they aren’t they should be converted first- Parameters:
out – register to store max(
a,b) ina – register storing first value
b – register storing second value
-
void *min_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Finds the min of two f64 numbers
Note
Both
aandbmust be f64s. If they aren’t they should be converted first- Parameters:
out – register to store min(
a,b) ina – register storing first value
b – register storing second value
-
void *sqrt_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Finds the square root of a f64 number
- Parameters:
out – register to store sqrt(
a) ina – register storing the value
-
void *set_if_equal_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if two f64 registers are equal
Note
Both
aandbmust be f64s. If they aren’t they should be converted first- Parameters:
out – register to be set to one if
a==bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_not_equal_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if two f64 registers are not equal
Note
Both
aandbmust be f64s. If they aren’t they should be converted first- Parameters:
out – register to be set to one if
a!=bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_less_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if one f64 register is less than another
Note
Both
aandbmust be f64s. If they aren’t they should be converted first- Parameters:
out – register to be set to one if
a<bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_greater_equal_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if one f64 register is greater or equal to another
Note
Both
aandbmust be f64s. If they aren’t they should be converted first- Parameters:
out – register to be set to one if
a>=bor zero otherwisea – register storing the first value to compare
b – register storing the second value to compare
-
void *set_if_negative_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a f64 register is negative
- Parameters:
out – register to be set to one if
a< 0 or zero otherwisea – register storing the value to compare
-
void *set_if_positive_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a f64 register is positive
- Parameters:
out – register to be set to one if
a> 0 or zero otherwisea – register storing the value to compare
-
void *set_if_infinity_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a f64 register is an infinity
- Parameters:
out – register to be set to one if
a== +/- infinity or zero otherwisea – register storing the value to compare
-
void *set_if_nan_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Checks if a f64 register is nan
- Parameters:
out – register to be set to one if
a== nan or zero otherwisea – register storing the value to compare
-
inline uint64_t new_thread(opcode *pc, registers_and_stack *env, uint8_t *sp)#
-
void *fork_relative(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Forks a new thread moving its program counter by an offset relative to the current thread’s program counter. If the offset is zero this instruction is executed again. If it is one the next instruction is executed as usual. If it is negative a previous instruction is executed.
Note
A new set of registers (copied from the current thread) are created for the new thread.
Note
ais interpreted as a signed integer, allowing for negative jumps- Parameters:
out – register to store the thread reference in
a – register storing how many instructions to jump
-
void *fork_relative_immediate(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Forks a new thread moving its program counter by an offset relative to the current thread’s program counter. If the offset is zero this instruction is executed again. If it is one the next instruction is executed as usual. If it is negative a previous instruction is executed.
Note
A new set of registers (copied from the current thread) are created for the new thread.
Note
immediateis interpreted as a signed integer, allowing for negative jumps- Parameters:
out – register to store the thread reference in
immediate – how many instructions to jump
-
void *fork_to(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Forks a new thread with its program counter set to a value (usually the output of another jump)
Note
A new set of registers (copied from the current thread) are created for the new thread.
- Parameters:
out – register to store the thread reference in
a – register storing the address of the instruction to jump to.
-
void *join_thread(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Waits for the provided thread to finish and frees its reference
- Parameters:
a – Register storing the thread to wait for
b – Register storing a value to overwrite
awith (defaults to zero)
-
void *sleep_microseconds(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Sleeps the provided number of micro seconds
- Parameters:
a – Register storing the number of microseconds to sleep
-
void *channel_create(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Creates an inter-thread communication channel. This channel can keep a buffer of values or a single value.
Note
Channels send and receive register sized binary blobs.
- Parameters:
out – Register to store the channel reference in
a – Register storing the capacity of the channel buffer (defaults to a single item)
-
void *channel_close(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Closes the provided channel and frees its reference
- Parameters:
a – Register storing the channel to free
b – Register storing a value to overwrite
awith (defaults to zero)
-
void *channel_receive(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Blocks the current thread until there is an item to receive from the channel.
- Parameters:
out – Register to store the binary blob read from the channel in.
a – Register storing the channel to read from.
-
void *channel_send(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Blocks the current thread until the channel has room to receive a new value.
- Parameters:
a – Register storing the channel to send a message to
b – Register storing the binary blob to send to the channel.
-
void *mutex_create(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Creates a read/write lockable mutex
- Parameters:
out – Register to store the mutex reference in
-
void *mutex_free(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Frees a mutex.
- Parameters:
a – Register storing the mutex to free.
b – Register storing a value to overwrite
awith (defaults to zero)
-
void *mutex_write_lock(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Blocks the current thread until an exclusive (writing) lock can be taken on the mutex
- Parameters:
a – Register storing the mutex to lock.
-
void *mutex_try_write_lock(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Attemps to take an exclusive (writing) lock on the mutex
- Parameters:
out – Register to store weather (1) or not (0) the lock was successfully taken in
a – Register storing the mutex to lock.
-
void *mutex_write_unlock(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Releases an exclusive (writing) lock on a mutex so that another thread can lock it.
- Parameters:
a – Register storing the mutex to unlock.
-
void *mutex_read_lock(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Blocks the current thread until a shared (reading) lock can be taken on the mutex
Note
any number of threads can take a reading lock at the same time, but only one thread can have a writing lock.
- Parameters:
a – Register storing the mutex to lock.
-
void *mutex_try_read_lock(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Attemps to take an shared (reading) lock on the mutex
Note
any number of threads can take a reading lock at the same time, but only one thread can have a writing lock.
- Parameters:
out – Register to store weather (1) or not (0) the lock was successfully taken in
a – Register storing the mutex to lock.
-
void *mutex_read_unlock(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Releases a shared (reading) lock on a mutex so that another thread can lock it.
- Parameters:
a – Register storing the mutex to unlock.
Variables
-
static constexpr reg_t ra = return_address#
-
static constexpr size_t memory_size = 1024 * MIZU_STACK_SIZE / sizeof(uint64_t)#
How many registers long the memory space is.
Note
set using the MIZU_STACK_SIZE (measured in kilobytes) config option.
-
static constexpr size_t memory_size_bytes = memory_size * sizeof(uint64_t)#
How many bytes the memory space is.
Note
set using the MIZU_STACK_SIZE (measured in kilobytes) config option.
-
constexpr auto program_end = nullptr#
-
struct opcode#
- #include <opcode.hpp>
Type which holds an instruction and (upto) 3 registers for it to act upon.
Note
Since instruction_t is a pointer, this struct will have different sizes on different machines. Thus Mizu binaries are only compatible with machines of the same pointer size and endianness.
-
struct registers_and_stack#
- #include <opcode.hpp>
Type representing holding the registers and stack space for a Mizu program or thread.
-
struct serialization_opcode#
- #include <serialize.hpp>
A version of the opcode which has fixed sizes for serialization purposes.
-
namespace debug#
Functions
-
void *breakpoint(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Noop which can be used to add breakpoints into code
-
namespace instructions#
-
void *breakpoint(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
-
namespace detail#
Typedefs
-
using id_t = size_t#
Functions
-
inline id_t register_instruction(std::string_view name, mizu::instruction_t ptr)#
Variables
-
std::unordered_map<mizu::instruction_t, id_t> reverse_function_lookup#
-
std::unordered_map<id_t, std::pair<std::string_view, mizu::instruction_t>> lookup#
-
using id_t = size_t#
-
namespace ffi#
Functions
-
template<bool has_return>
void *call_impl(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
-
void *push_type_void(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds void to the current type stack.
-
void *push_type_pointer(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds void* to the current type stack.
-
void *push_type_i32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds int32_t to the current type stack.
-
void *push_type_u32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds uint32_t to the current type stack.
-
void *push_type_i64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds int64_t to the current type stack.
-
void *push_type_u64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds uint64_t to the current type stack.
-
void *push_type_f32(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds
floatto the current type stack.
-
void *push_type_f64(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Adds
doubleto the current type stack.
-
void *clear_type_stack(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Clears the current type stack.
-
void *create_interface(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Converts the current type stack into a interface that tells the ffi subsystem what the types of each argument are.
Note
The first type on the stack is interpreted as the return type, any types after that are parameters (that one return type is required! Use push_type_void to indicate no return.)
- Parameters:
out – Register to store the resulting interface in
-
void *free_interface(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Frees the provided interface and overwrites it with the value in
b(defaults to zero)- Parameters:
a – Register storing the interface to free.
b – Register storing the value to overwrite a with (defaults to zero)
-
void *call(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Calls an ffi function, the functions arguments are expected to be in the argument registers (a0, a1, etc…)
- Parameters:
a – Register storing a pointer to the function to call.
b – Register storing the interface defining how the function’s arguments should be interpreted.
-
void *call_with_return(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Calls an ffi function with a returned value, the functions arguments are expected to be in the argument registers (a0, a1, etc…)
- Parameters:
out – Register storing
a – Register storing a pointer to the function to call.
b – Register storing the interface defining how the function’s arguments should be interpreted.
-
void *load_library(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Loads a DLL (or platform equivalent) with the provided path.
Note
most platforms will search some set of library path for the given path
- Parameters:
out – Register to store the resulting library pointer in
a – Register storing a null-terminated c-string pointer representing the path to search for the library.
-
void *load_first_library_that_exists(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Expects a list of null terminated c-string library paths in the first
immediateargument registers. Tries to load each library and stores a pointer to the first to load inout- Parameters:
out – Register to store the resulting library in.
immediate – number of argument (a0, a1, etc…) registers storing paths to search
-
void *load_library_function(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Loads a function pointer from a library.
- Parameters:
out – Register to store the resulting function pointer in
a – Register storing a pointer to the library to load the function from.
b – Register storing a null-terminated c-string pointer representing the (mangled) name of the function to load.
-
namespace instructions#
-
template<bool has_return>
-
namespace instructions#
-
namespace loader#
Functions
-
inline library *load_dynamic(std::string_view path, bool append_platform_decorator = false)#
-
inline library *load_library(std::string_view path, bool append_platform_decorator = false)#
-
inline library *load_first_that_exists(fp::view<const std::string_view> paths, bool append_platform_decorator = false)#
-
inline library *load_current_executable()#
-
inline void *lookup(std::string_view name, library *lib = nullptr)#
-
inline void close(library *lib)#
-
struct error : public std::runtime_error#
-
inline library *load_dynamic(std::string_view path, bool append_platform_decorator = false)#
-
namespace portable#
-
namespace registers#
x0 (zero) is always zero
x1-x20 (t0-t19) are temporary registers which are expected to be saved by the caller if necessary
x21 (ra) is the return address (callee saved)
x22-x256 (a0-a234) are the argument registers (callee saved)
Note
x22/a0 and x23/a1 are the canonical return registers
Functions
-
constexpr reg_t x(std::size_t i)#
Generic register lookup
- Parameters:
i – The register’s index
- Returns:
constexpr reg_t associated value to store in an opcode
-
namespace serialization#
-
struct serialization_opcode#
- #include <serialize.hpp>
A version of the opcode which has fixed sizes for serialization purposes.
-
struct serialization_opcode#
-
namespace unsafe#
Functions
-
void *allocate(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Allocates new memory on the host application heap.
- Parameters:
out – Register in which a pointer to the allocated memory will be stored
a – Register storing how many bytes to allocate
-
void *free_allocated(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Frees an allocation alloacted with allocate.
- Parameters:
a – Register storing the allocation to free
b – Register storing a value to overwrite
awith (defaults to zero)
-
void *allocate_fat_pointer(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Allocates new memory on the host application heap. This memory knows how many element are stored in it.
Note
The total size of this allocation is a * b
- Parameters:
out – Register in which a pointer to the allocated memory will be stored
a – Register storing the size of each element
b – Register storing how many elements there are
-
void *free_fat_pointer(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Frees an allocation alloacted with allocate_fat_pointer.
- Parameters:
a – Register storing the allocation to free
b – Register storing a value to overwrite
awith (defaults to zero)
-
void *pointer_to_stack(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Generates a pointer to memory on Mizu’s stack.
- Parameters:
out – Register to store the pointer in
a – Register storing a (signed) offset from the current stack pointer.
-
void *pointer_to_stack_bottom(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Generates a pointer to memory on the bottom of Mizu’s stack.
- Parameters:
out – Register to store the pointer in
a – Register storing a (signed) offset from the current stack pointer.
-
void *pointer_to_register(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Generates a pointer to one of Mizu’s registers
- Parameters:
a – Register to take a pointer to.
out – Register to store the pointer in
-
void *copy_memory(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Copies memory from one pointer to another
- Parameters:
out – Register storing a pointer that data should be copied to
a – Register storing a pointer that data should be copied from
b – Register storing how many bytes should be copied.
-
void *copy_memory_immediate(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Copies memory from one pointer to another
- Parameters:
out – Register storing a pointer that data should be copied to
a – Register storing a pointer that data should be copied from
b – (branch immediate) number of bytes that should be copied
-
void *set_memory(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Sets all of the given memory to the provided byte
- Parameters:
out – Register storing a pointer to what should be overwritten
a – Register storing a u8 to overwrite
outwithb – Register storing how many bytes should be overwritten
-
void *set_memory_immediate(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
Sets all of the given memory to the provided byte
- Parameters:
out – Register storing a pointer to what should be overwritten
a – Register storing a u8 to overwrite
outwithb – (branch immediate) how many bytes should be overwritten
-
namespace instructions#
-
void *allocate(opcode *pc, uint64_t *registers, registers_and_stack *env, uint8_t *sp)#
-
using reg_t = uint16_t#