coming again from previous questions on this, I've expanded the virtual machine a little bit in terms of a direct API to read and write data to the VM.I've attempted to add a callback system so that host apps can add callable code that can be used by the scripts though I have no clue how to implement this.This may or may not be my last review for this VM code since it's going to be very complex with each improvement or feature I add. I'm only asking these two questions:How could I add a form of addressing? This VM MUST run C code that's compiled to bytecode, what changes must I do so the VM can fully support pointers?After resolving the issue of dealing with pointers, what's the best way to implement the C/C++ call back system so that the C scripts can call C/C++ functions?Github (if necessary)vm.h#ifndef VM_H_INCLUDED#define VM_H_INCLUDED#include <stdbool.h>#ifdef __cplusplusextern C {#endif#define WORD_SIZE       4#define STK_SIZE        (512 * WORD_SIZE)       // 2,048 bytes or 2kb#define CALLSTK_SIZE    256                     // 1,024 bytes#define MEM_SIZE        (16384 * WORD_SIZE)     // 65,536 bytes or 65kb of memorytypedef     unsigned char       uchar;typedef     uchar               bytecode[];typedef     unsigned short      ushort;typedef     unsigned int        uint;typedef     unsigned long long  ulong;// Bytecode header to store important info for our code.// this will be entirely read as an unsigned chartypedef struct {    uint    uiSize;     //     ushort  uiMagic;    // verify bytecode ==> 0xfa 0xce    uint    ipstart;    // where does 'main' begin?} CVMHeader;typedef struct vm_cpu {    uint        bCallstack[CALLSTK_SIZE];   // 1024 bytes    CVMHeader   *pHeader;    uchar       *pbMemory, *pbDataStack, *pInstrStream;    uint        ip, sp, callsp/*, bp*/;     // 16 bytes} CVM_t;union conv_union {    uint    ui;    int     i;    float   f;    ushort  us;    short   s;    uchar   c[WORD_SIZE];};// Safe mode enables bounds checking.// this might slow down the interpreter on a smaller level since we're always checking// if pointers or memory addresses go out of bounds but it does help.#define SAFEMODE    1void        vm_init(CVM_t *vm);void        vm_load_code(CVM_t *restrict vm, uchar *restrict program);void        vm_reset(CVM_t *vm);void        vm_free(CVM_t *vm);void        vm_exec(CVM_t *vm);void        vm_debug_print_ptrs(const CVM_t *vm);void        vm_debug_print_callstack(const CVM_t *vm);void        vm_debug_print_stack(const CVM_t *vm);void        vm_debug_print_memory(const CVM_t *vm);uint        vm_pop_word(CVM_t *vm);ushort      vm_pop_short(CVM_t *vm);uchar       vm_pop_byte(CVM_t *vm);float       vm_pop_float32(CVM_t *vm);void        vm_push_word(CVM_t *restrict vm, const uint val);void        vm_push_short(CVM_t *restrict vm, const ushort val);void        vm_push_byte(CVM_t *restrict vm, const uchar val);void        vm_push_float(CVM_t *restrict vm, const float val);void        vm_write_word(CVM_t *restrict vm, const uint val, const uint address);void        vm_write_short(CVM_t *restrict vm, const ushort val, const uint address);void        vm_write_byte(CVM_t *restrict vm, const uchar val, const uint address);void        vm_write_float(CVM_t *restrict vm, const float val, const uint address);void        vm_write_bytearray(CVM_t *restrict vm, uchar *restrict val, const uint size, const uint address);uint        vm_read_word(CVM_t *restrict vm, const uint address);ushort      vm_read_short(CVM_t *restrict vm, const uint address);uchar       vm_read_byte(CVM_t *restrict vm, const uint address);float       vm_read_float(CVM_t *restrict vm, const uint address);void        vm_read_bytearray(CVM_t *restrict vm, uchar *restrict buffer, const uint size, const uint address);//  API to call C/C++ functions from scripts. Supports up to 5 params//  Realistically, if you require more than 5 arguments, you could just group everything into a struct and pass its pointer.typedef     void (*fnNative0)(CVM_t *restrict vm);typedef     void (*fnNative1)(CVM_t *restrict vm, void *restrict param1);typedef     void (*fnNative2)(CVM_t *restrict vm, void *restrict param1, void *restrict param2);typedef     void (*fnNative3)(CVM_t *restrict vm, void *restrict param1, void *restrict param2, void *restrict param3);typedef     void (*fnNative4)(CVM_t *restrict vm, void *restrict param1, void *restrict param2, void *restrict param3, void *restrict param4);typedef     void (*fnNative5)(CVM_t *restrict vm, void *restrict param1, void *restrict param2, void *restrict param3, void *restrict param4, void *restrict param5);typedef struct {    union {        fnNative0   fnNoArgs;        fnNative1   fnOneArg;        fnNative2   fnTwoArgs;        fnNative3   fnTreArgs;        fnNative4   fnFourArgs;        fnNative5   fnPentaArgs;    };    uchar ucArgs;    const char  *strName;} NativeInfo;int     vm_register_funcs(CVM_t *restrict vm, NativeInfo *arrNatives);#ifdef __cplusplus}#endif#endif  // VM_H_INCLUDEDvm.c#include <stdio.h>#include <stdbool.h>#include <stdlib.h>#include <inttypes.h>#include <assert.h>#include vm.h/*  here's the deal ok? make an opcode for each and erry n-bytes! * 'q' = int64 * 'l' - int32 * 's' - int16 * 'b' - byte | push and pop do not take bytes * 'f' - float32 * 'df' - float64 * 'a' - address*/// this vm is designed to run C programs. Vastly, if not all C expressions are int32, uint32 if bigger than int// this is why the arithmetic and bit operations are all int32 sized.// there's 2 byte and single byte memory storage for the sake of dealing with structs and unions.#define INSTR_SET   \    X(halt) \    X(pushl) X(pushs) X(pushb) X(pushsp) X(puship) \    X(popl) X(pops) X(popb) X(popsp) \    X(wrtl) X(wrts) X(wrtb) \    X(storel) X(stores) X(storeb) \    X(loadl) X(loads) X(loadb) \    X(copyl) X(copys) X(copyb) \    X(addl) X(uaddl) X(addf) \    X(subl) X(usubl) X(subf) \    X(mull) X(umull) X(mulf) \    X(divl) X(udivl) X(divf) \    X(modl) X(umodl) \    X(andl) X(orl) X(xorl) \    X(notl) X(shll) X(shrl) \    X(incl) X(decl) X(negl) \    X(ltl) X(ultl) X(ltf) \    X(gtl) X(ugtl) X(gtf) \    X(cmpl) X(ucmpl) X(compf) \    X(leql) X(uleql) X(leqf) \    X(geql) X(ugeql) X(geqf) \    X(jmp) X(jzl) X(jnzl) \    X(call) X(ret) X(reset) \    X(nop) \#define X(x) x,enum InstrSet { INSTR_SET };#undef Xvoid vm_init(CVM_t *restrict vm){    if( !vm )        return;    vm->pbMemory = NULL;    vm->pbDataStack = NULL;    uint i;    for( i=0 ; i<CALLSTK_SIZE ; i++ )        vm->bCallstack[i] = 0;    vm->ip = 0;    vm->sp = 0;    vm->callsp = 0;    vm->pInstrStream = NULL;}void vm_load_code(CVM_t *restrict vm, uchar *restrict program){    if( !vm )        return;    vm->pbDataStack = calloc(STK_SIZE, sizeof(uchar)); //&(uchar[STK_SIZE]){0};    assert(vm->pbDataStack);    vm->pbMemory = calloc(MEM_SIZE, sizeof(uchar)); //&(uchar[MEM_SIZE]){0};    assert(vm->pbMemory);    vm->pInstrStream = program;}void vm_free(CVM_t *vm){    if( !vm )        return;    if( vm->pbDataStack )        free(vm->pbDataStack);    vm->pbDataStack = NULL;    if( vm->pbMemory )        free(vm->pbMemory);    vm->pbMemory = NULL;    vm_init(vm);}void vm_reset(CVM_t *vm){    if( !vm )        return;    uint i;    for( i=0 ; i<MEM_SIZE ; i++ )        vm->pbMemory[i] = 0;    for( i=0 ; i<STK_SIZE ; i++ )        vm->pbDataStack[i] = 0;    for( i=0 ; i<CALLSTK_SIZE ; i++ )        vm->bCallstack[i] = 0;    vm->ip = 0;    vm->sp = 0;    vm->callsp = 0;}// returns index of func ptrint vm_register_func(CVM_t *restrict vm, NativeInfo *arrNatives){    if( !vm || !arrNatives )        return -1;    return 0;}uint vm_pop_word(CVM_t *vm){    if( !vm )        return 0;#ifdef SAFEMODE    if( (vm->sp-4) >= STK_SIZE ) {  // we're subtracting, did we integer underflow?        printf(vm_pop_word reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-4);        exit(1);    }#endif    union conv_union conv;    conv.c[3] = vm->pbDataStack[vm->sp--];    conv.c[2] = vm->pbDataStack[vm->sp--];    conv.c[1] = vm->pbDataStack[vm->sp--];    conv.c[0] = vm->pbDataStack[vm->sp--];    return conv.ui;}ushort vm_pop_short(CVM_t *vm){    if( !vm )        return 0;#ifdef SAFEMODE    if( (vm->sp-2) >= STK_SIZE ) {  // we're subtracting, did we integer underflow?        printf(vm_pop_short reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-2);        exit(1);    }#endif    union conv_union conv;    conv.c[1] = vm->pbDataStack[vm->sp--];    conv.c[0] = vm->pbDataStack[vm->sp--];    return conv.us;}uchar vm_pop_byte(CVM_t *vm){    if( !vm )        return 0;#ifdef SAFEMODE    if( (vm->sp-1) >= STK_SIZE ) {  // we're subtracting, did we integer underflow?        printf(vm_pop_byte reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-1);        exit(1);    }#endif    return vm->pbDataStack[vm->sp--];}float vm_pop_float32(CVM_t *vm){    if( !vm )        return 0;#ifdef SAFEMODE    if( (vm->sp-4) >= STK_SIZE ) {  // we're subtracting, did we integer underflow?        printf(vm_pop_float32 reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-4);        exit(1);    }#endif    union conv_union conv;    conv.c[3] = vm->pbDataStack[vm->sp--];    conv.c[2] = vm->pbDataStack[vm->sp--];    conv.c[1] = vm->pbDataStack[vm->sp--];    conv.c[0] = vm->pbDataStack[vm->sp--];    return conv.f;}void vm_push_word(CVM_t *restrict vm, const uint val){    if( !vm )        return;#ifdef SAFEMODE    if( (vm->sp+4) >= STK_SIZE ) {        printf(vm_push_word reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+4);        exit(1);    }#endif    union conv_union conv;    conv.ui = val;    vm->pbDataStack[++vm->sp] = conv.c[0];    vm->pbDataStack[++vm->sp] = conv.c[1];    vm->pbDataStack[++vm->sp] = conv.c[2];    vm->pbDataStack[++vm->sp] = conv.c[3];}void vm_push_short(CVM_t *restrict vm, const ushort val){    if( !vm )        return;#ifdef SAFEMODE    if( (vm->sp+2) >= STK_SIZE ) {        printf(vm_push_short reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+2);        exit(1);    }#endif    union conv_union conv;    conv.us = val;    vm->pbDataStack[++vm->sp] = conv.c[0];    vm->pbDataStack[++vm->sp] = conv.c[1];}void vm_push_byte(CVM_t *restrict vm, const uchar val){    if( !vm )        return;#ifdef SAFEMODE    if( (vm->sp+1) >= STK_SIZE ) {        printf(vm_push_byte reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+1);        exit(1);    }#endif    vm->pbDataStack[++vm->sp] = val;}void vm_push_float(CVM_t *restrict vm, const float val){    if( !vm )        return;#ifdef SAFEMODE    if( (vm->sp+4) >= STK_SIZE ) {        printf(vm_push_float reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+4);        exit(1);    }#endif    union conv_union conv;    conv.f = val;    vm->pbDataStack[++vm->sp] = conv.c[0];    vm->pbDataStack[++vm->sp] = conv.c[1];    vm->pbDataStack[++vm->sp] = conv.c[2];    vm->pbDataStack[++vm->sp] = conv.c[3];}void vm_write_word(CVM_t *restrict vm, const uint val, const uint address){    if( !vm )        return;#ifdef SAFEMODE    if( address+3 >= MEM_SIZE ) {        printf(vm_write_word reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, address+3);        exit(1);    }#endif    union conv_union conv;    conv.ui = val;    vm->pbMemory[address] = conv.c[0];    vm->pbMemory[address+1] = conv.c[1];    vm->pbMemory[address+2] = conv.c[2];    vm->pbMemory[address+3] = conv.c[3];}void vm_write_short(CVM_t *restrict vm, const ushort val, const uint address){    if( !vm )        return;#ifdef SAFEMODE    if( address+1 >= MEM_SIZE ) {        printf(vm_write_short reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, address+1);        exit(1);    }#endif    union conv_union conv;    conv.us = val;    vm->pbMemory[address] = conv.c[0];    vm->pbMemory[address+1] = conv.c[1];}void vm_write_byte(CVM_t *restrict vm, const uchar val, const uint address){    if( !vm )        return;#ifdef SAFEMODE    if( address >= MEM_SIZE ) {        printf(vm_write_byte reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, address);        exit(1);    }#endif    vm->pbMemory[address] = val;}void vm_write_float(CVM_t *restrict vm, const float val, const uint address){    if( !vm )        return;#ifdef SAFEMODE    if( address+3 >= MEM_SIZE ) {        printf(vm_write_float reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, address+3);        exit(1);    }#endif    union conv_union conv;    conv.f = val;    vm->pbMemory[address] = conv.c[0];    vm->pbMemory[address+1] = conv.c[1];    vm->pbMemory[address+2] = conv.c[2];    vm->pbMemory[address+3] = conv.c[3];}void vm_write_bytearray(CVM_t *restrict vm, uchar *restrict val, const uint size, const uint address){    if( !vm )        return;    uint addr = address;    uint i = 0;    while( i<size ) {#ifdef SAFEMODE        if( addr >= MEM_SIZE ) {            printf(vm_write_array reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, addr);            exit(1);        }#endif        vm->pbMemory[addr++] = val[i++];    }}uint vm_read_word(CVM_t *restrict vm, const uint address){    if( !vm )        return 0;#ifdef SAFEMODE    if( address+3 >= MEM_SIZE ) {        printf(vm_read_word reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, address+3);        exit(1);    }#endif    union conv_union conv;    conv.c[0] = vm->pbMemory[address];    conv.c[1] = vm->pbMemory[address+1];    conv.c[2] = vm->pbMemory[address+2];    conv.c[3] = vm->pbMemory[address+3];    return conv.ui;}ushort vm_read_short(CVM_t *restrict vm, const uint address){    if( !vm )        return 0;#ifdef SAFEMODE    if( address+1 >= MEM_SIZE ) {        printf(vm_read_short reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, address+1);        exit(1);    }#endif    union conv_union conv;    conv.c[0] = vm->pbMemory[address];    conv.c[1] = vm->pbMemory[address+1];    return conv.f;}uchar vm_read_byte(CVM_t *restrict vm, const uint address){    if( !vm )        return 0;#ifdef SAFEMODE    if( address >= MEM_SIZE ) {        printf(vm_read_byte reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, address);        exit(1);    }#endif    return vm->pbMemory[address];}float vm_read_float(CVM_t *restrict vm, const uint address){    if( !vm )        return 0;#ifdef SAFEMODE    if( address+3 >= MEM_SIZE ) {        printf(vm_read_float reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, address+3);        exit(1);    }#endif    union conv_union conv;    conv.c[0] = vm->pbMemory[address];    conv.c[1] = vm->pbMemory[address+1];    conv.c[2] = vm->pbMemory[address+2];    conv.c[3] = vm->pbMemory[address+3];    return conv.f;}void vm_read_bytearray(CVM_t *restrict vm, uchar *restrict buffer, const uint size, const uint address){    if( !vm )        return;    uint addr = address;    uint i = 0;    while( i<size ) {#ifdef SAFEMODE        if( addr >= MEM_SIZE ) {            printf(vm_read_array reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, addr);            exit(1);        }#endif        buffer[i++] = vm->pbMemory[addr++];    }}void vm_debug_print_memory(const CVM_t *vm){    if( !vm )        return;    if( !vm->pbMemory )        return;    printf(DEBUG ...---===---... Printing Memory...\n);    uint i;    for( i=0 ; i<MEM_SIZE ; i++ )        if( vm->pbMemory[i] )            printf(Memory Index: 0x%x | data: % PRIu32 \n, i, vm->pbMemory[i]);    printf(\n);}void vm_debug_print_stack(const CVM_t *vm){    if( !vm )        return;    if( !vm->pbDataStack )        return;    printf(DEBUG ...---===---... Printing Stack...\n);    uint i;    for( i=0 ; i<STK_SIZE ; i++ )        if( vm->pbDataStack[i] )            printf(Stack Index: 0x%x | data: % PRIu32 \n, i, vm->pbDataStack[i]);    printf(\n);}void vm_debug_print_callstack(const CVM_t *vm){    if( !vm )        return;    printf(DEBUG ...---===---... Printing Call Stack...\n);    uint i;    for( i=0 ; i<CALLSTK_SIZE ; i++ )        if( vm->bCallstack[i] )            printf(Call Stack Index: 0x%x | data: % PRIu32 \n, i, vm->bCallstack[i]);    printf(\n);}void vm_debug_print_ptrs(const CVM_t *vm){    if( !vm )        return;    printf(DEBUG ...---===---... Printing Pointers...\n);    printf(Instruction Pointer: % PRIu32 \            \nStack Pointer: % PRIu32 \            \nCall Stack Pointer: % PRIu32             /*\nCall Stack Frame Pointer: % PRIu32 \n*/, vm->ip, vm->sp, vm->callsp/*, vm->bp*/);    printf(\n);}static inline uint vm_get_imm4(CVM_t *restrict vm){    if( !vm )        return 0;    union conv_union conv;    conv.c[0] = vm->pInstrStream[++vm->ip];    conv.c[1] = vm->pInstrStream[++vm->ip];    conv.c[2] = vm->pInstrStream[++vm->ip];    conv.c[3] = vm->pInstrStream[++vm->ip];    return conv.ui;}static inline ushort vm_get_imm2(CVM_t *restrict vm){    if( !vm )        return 0;    union conv_union conv;    conv.c[0] = vm->pInstrStream[++vm->ip];    conv.c[1] = vm->pInstrStream[++vm->ip];    return conv.us;}static inline uint _vm_pop_word(CVM_t *vm){    if( !vm )        return 0;#ifdef SAFEMODE    if( (vm->sp-4) >= STK_SIZE ) {  // we're subtracting, did we integer underflow?        printf(vm_pop_word reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-4);        exit(1);    }#endif    union conv_union conv;    conv.c[3] = vm->pbDataStack[vm->sp--];    conv.c[2] = vm->pbDataStack[vm->sp--];    conv.c[1] = vm->pbDataStack[vm->sp--];    conv.c[0] = vm->pbDataStack[vm->sp--];    return conv.ui;}static inline float _vm_pop_float32(CVM_t *vm){    if( !vm )        return 0;#ifdef SAFEMODE    if( (vm->sp-4) >= STK_SIZE ) {  // we're subtracting, did we integer underflow?        printf(vm_pop_float32 reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-4);        exit(1);    }#endif    union conv_union conv;    conv.c[3] = vm->pbDataStack[vm->sp--];    conv.c[2] = vm->pbDataStack[vm->sp--];    conv.c[1] = vm->pbDataStack[vm->sp--];    conv.c[0] = vm->pbDataStack[vm->sp--];    return conv.f;}static inline ushort _vm_pop_short(CVM_t *vm){    if( !vm )        return 0;#ifdef SAFEMODE    if( (vm->sp-2) >= STK_SIZE ) {  // we're subtracting, did we integer underflow?        printf(vm_pop_word reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-2);        exit(1);    }#endif    union conv_union conv;    conv.c[1] = vm->pbDataStack[vm->sp--];    conv.c[0] = vm->pbDataStack[vm->sp--];    return conv.us;}static inline uchar _vm_pop_byte(CVM_t *vm){    if( !vm )        return 0;#ifdef SAFEMODE    if( (vm->sp-1) >= STK_SIZE ) {  // we're subtracting, did we integer underflow?        printf(vm_pop_word reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-1);        exit(1);    }#endif    return vm->pbDataStack[vm->sp--];}static inline void _vm_push_word(CVM_t *restrict vm, const uint val){    if( !vm )        return;#ifdef SAFEMODE    if( (vm->sp+4) >= STK_SIZE ) {        printf(vm_push_word reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+4);        exit(1);    }#endif    union conv_union conv;    conv.ui = val;    vm->pbDataStack[++vm->sp] = conv.c[0];    vm->pbDataStack[++vm->sp] = conv.c[1];    vm->pbDataStack[++vm->sp] = conv.c[2];    vm->pbDataStack[++vm->sp] = conv.c[3];}static inline void _vm_push_float(CVM_t *restrict vm, const float val){    if( !vm )        return;#ifdef SAFEMODE    if( (vm->sp+4) >= STK_SIZE ) {        printf(vm_push_float reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+4);        exit(1);    }#endif    union conv_union conv;    conv.f = val;    vm->pbDataStack[++vm->sp] = conv.c[0];    vm->pbDataStack[++vm->sp] = conv.c[1];    vm->pbDataStack[++vm->sp] = conv.c[2];    vm->pbDataStack[++vm->sp] = conv.c[3];}void _vm_push_short(CVM_t *restrict vm, const ushort val){    if( !vm )        return;#ifdef SAFEMODE    if( (vm->sp+2) >= STK_SIZE ) {        printf(vm_push_short reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+2);        exit(1);    }#endif    union conv_union conv;    conv.us = val;    vm->pbDataStack[++vm->sp] = conv.c[0];    vm->pbDataStack[++vm->sp] = conv.c[1];}static inline void _vm_push_byte(CVM_t *restrict vm, const uchar val){    if( !vm )        return;#ifdef SAFEMODE    if( (vm->sp+1) >= STK_SIZE ) {        printf(vm_push_byte reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+1);        exit(1);    }#endif    vm->pbDataStack[++vm->sp] = val;}//#include <unistd.h>   // sleep() funcvoid vm_exec(CVM_t *restrict vm){    if( !vm )        return;    else if( !vm->pInstrStream )        return;    union conv_union conv;    uint b,a;    float fb,fa;    ushort sb,sa;    uchar cb,ca;#define X(x) #x ,    const char *opcode2str[] = { INSTR_SET };#undef X#define X(x) &&exec_##x ,    static const void *dispatch[] = { INSTR_SET };#undef X#undef INSTR_SET    if( vm->pInstrStream[vm->ip] > nop) {        printf(illegal instruction exception! instruction == \'% PRIu32 \' @ % PRIu32 \n, vm->pInstrStream[vm->ip], vm->ip);        goto *dispatch[halt];        return;    }    //printf( current instruction == \%s\ @ ip == % PRIu32 \n, opcode2str[vm->pInstrStream[vm->ip]], vm->ip );#ifdef _UNISTD_H    #define DISPATCH()  sleep(1); goto *dispatch[ vm->pInstrStream[++vm->ip] ]#else    #define DISPATCH()  goto *dispatch[ vm->pInstrStream[++vm->ip] ]#endif    goto *dispatch[ vm->pInstrStream[vm->ip] ];exec_nop:;    DISPATCH();exec_halt:;    printf(===================== vm done\n\n);    return;// opcodes for longsexec_pushl:;    // push 4 bytes onto the stack    conv.ui = vm_get_imm4(vm);    _vm_push_word(vm, conv.ui);    printf(pushl: pushed % PRIu32 \n, conv.ui);    DISPATCH();exec_pushs:;    // push 2 bytes onto the stack    conv.us = vm_get_imm2(vm);#ifdef SAFEMODE    if( vm->sp+2 >= STK_SIZE ) {        printf(exec_pushs reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+2);        goto *dispatch[halt];    }#endif    //conv.c[0] = code[++vm->ip];    //conv.c[1] = code[++vm->ip];    vm->pbDataStack[++vm->sp] = conv.c[0];    vm->pbDataStack[++vm->sp] = conv.c[1];    printf(pushs: pushed % PRIu32 \n, conv.us);    DISPATCH();exec_pushb:;    // push a byte onto the stack#ifdef SAFEMODE    if( vm->sp+1 >= STK_SIZE ) {        printf(exec_pushb reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+1);        goto *dispatch[halt];    }#endif    vm->pbDataStack[++vm->sp] = vm->pInstrStream[++vm->ip];    printf(pushb: pushed % PRIu32 \n, vm->pbDataStack[vm->sp]);    DISPATCH();exec_pushsp:;   // push sp onto the stack, uses 4 bytes since 'sp' is uint32    conv.ui = vm->sp;    _vm_push_word(vm, conv.ui);    printf(pushsp: pushed sp index: % PRIu32 \n, conv.ui);    DISPATCH();exec_puship:;    conv.ui = vm->ip;    _vm_push_word(vm, conv.ui);    printf(puship: pushed ip index: % PRIu32 \n, conv.ui);    DISPATCH();exec_popl:;     // pop 4 bytes to eventually be overwritten#ifdef SAFEMODE    if( vm->sp-4 >= STK_SIZE ) {        printf(exec_popl reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-4);        goto *dispatch[halt];    }#endif    vm->sp -= 4;    printf(popl\n);    DISPATCH();exec_pops:;     // pop 2 bytes#ifdef SAFEMODE    if( vm->sp-2 >= STK_SIZE ) {        printf(exec_pops reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-2);        goto *dispatch[halt];    }#endif    vm->sp -= 2;    printf(pops\n);    DISPATCH();exec_popb:;     // pop a byte#ifdef SAFEMODE    if( vm->sp-1 >= STK_SIZE ) {        printf(exec_popb reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-1);        goto *dispatch[halt];    }#endif    --vm->sp;    printf(popb\n);    DISPATCH();exec_popsp:;        // pop n bytes#ifdef SAFEMODE    if( vm->sp-1 >= STK_SIZE ) {        printf(exec_popsp reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-1);        goto *dispatch[halt];    }#endif    vm->sp = vm->pbDataStack[vm->sp];    printf(popsp: sp is now % PRIu32  bytes.\n, vm->sp);    DISPATCH();exec_wrtl:; // writes an int to memory, First operand is the memory address as 4 byte number, second is the int of data.    a = vm_get_imm4(vm);#ifdef SAFEMODE    if( a+3 >= MEM_SIZE ) {        printf(exec_wrtl reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, a+3);        goto *dispatch[halt];    }#endif    vm->pbMemory[a] = vm->pInstrStream[++vm->ip];    vm->pbMemory[a+1] = vm->pInstrStream[++vm->ip];    vm->pbMemory[a+2] = vm->pInstrStream[++vm->ip];    vm->pbMemory[a+3] = vm->pInstrStream[++vm->ip];    conv.c[0] = vm->pbMemory[a];    conv.c[1] = vm->pbMemory[a+1];    conv.c[2] = vm->pbMemory[a+2];    conv.c[3] = vm->pbMemory[a+3];    printf(wrote int data - % PRIu32  @ address 0x%x\n, conv.ui, a);    DISPATCH();exec_wrts:; // writes a short to memory. First operand is the memory address as 4 byte number, second is the short of data.    a = vm_get_imm4(vm);#ifdef SAFEMODE    if( a+1 >= MEM_SIZE ) {        printf(exec_wrts reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, a+1);        goto *dispatch[halt];    }#endif    vm->pbMemory[a] = vm->pInstrStream[++vm->ip];    vm->pbMemory[a+1] = vm->pInstrStream[++vm->ip];    conv.c[0] = vm->pbMemory[a];    conv.c[1] = vm->pbMemory[a+1];    printf(wrote short data - % PRIu32  @ address 0x%x\n, conv.us, a);    DISPATCH();exec_wrtb:; // writes a byte to memory. First operand is the memory address as 32-bit number, second is the byte of data.    conv.ui = vm_get_imm4(vm);#ifdef SAFEMODE    if( conv.ui >= MEM_SIZE ) {        printf(exec_wrtb reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, conv.ui);        goto *dispatch[halt];    }#endif    vm->pbMemory[conv.ui] = vm->pInstrStream[++vm->ip];    printf(wrote byte data - % PRIu32  @ address 0x%x\n, vm->pbMemory[conv.ui], conv.ui);    DISPATCH();exec_storel:;   // pops 4-byte value off stack and into a memory address.    a = vm_get_imm4(vm);#ifdef SAFEMODE    if( a+3 >= MEM_SIZE ) {        printf(exec_storel reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, a+3);        goto *dispatch[halt];    }    else if( vm->sp-4 >= STK_SIZE ) {        printf(exec_storel reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-4);        goto *dispatch[halt];    }#endif    vm->pbMemory[a+3] = vm->pbDataStack[vm->sp--];    vm->pbMemory[a+2] = vm->pbDataStack[vm->sp--];    vm->pbMemory[a+1] = vm->pbDataStack[vm->sp--];    vm->pbMemory[a] = vm->pbDataStack[vm->sp--];    conv.c[0] = vm->pbMemory[a];    conv.c[1] = vm->pbMemory[a+1];    conv.c[2] = vm->pbMemory[a+2];    conv.c[3] = vm->pbMemory[a+3];    printf(stored int data - % PRIu32  @ address 0x%x\n, conv.ui, a);    DISPATCH();exec_stores:;   // pops 2-byte value off stack and into a memory address.    a = vm_get_imm4(vm);#ifdef SAFEMODE    if( a+1 >= MEM_SIZE ) {        printf(exec_stores reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, a+1);        goto *dispatch[halt];    }    else if( vm->sp-2 >= STK_SIZE ) {        printf(exec_stores reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-2);        goto *dispatch[halt];    }#endif    vm->pbMemory[a+1] = vm->pbDataStack[vm->sp--];    vm->pbMemory[a] = vm->pbDataStack[vm->sp--];    conv.c[0] = vm->pbMemory[a];    conv.c[1] = vm->pbMemory[a+1];    printf(stored short data - % PRIu32  @ address 0x%x\n, conv.us, a);    DISPATCH();exec_storeb:;   // pops byte value off stack and into a memory address.    a = vm_get_imm4(vm);#ifdef SAFEMODE    if( a >= MEM_SIZE ) {        printf(exec_storeb reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, a);        goto *dispatch[halt];    }    else if( vm->sp-1 >= STK_SIZE ) {        printf(exec_storeb reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-1);        goto *dispatch[halt];    }#endif    vm->pbMemory[a] = vm->pbDataStack[vm->sp--];    conv.c[0] = vm->pbMemory[a];    printf(stored byte data - % PRIu32  @ address 0x%x\n, conv.c[0], a);    DISPATCH();exec_loadl:;    a = vm_get_imm4(vm);#ifdef SAFEMODE    if( a+3 >= MEM_SIZE ) {        printf(exec_loadl reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, a+3);        goto *dispatch[halt];    }    else if( vm->sp+4 >= STK_SIZE ) {        printf(exec_loadl reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+4);        goto *dispatch[halt];    }#endif    vm->pbDataStack[++vm->sp] = vm->pbMemory[a];    vm->pbDataStack[++vm->sp] = vm->pbMemory[a+1];    vm->pbDataStack[++vm->sp] = vm->pbMemory[a+2];    vm->pbDataStack[++vm->sp] = vm->pbMemory[a+3];    conv.c[0] = vm->pbMemory[a];    conv.c[1] = vm->pbMemory[a+1];    conv.c[2] = vm->pbMemory[a+2];    conv.c[3] = vm->pbMemory[a+3];    printf(loaded int data to T.O.S. - % PRIu32  from address 0x%x\n, conv.ui, a);    DISPATCH();exec_loads:;    a = vm_get_imm4(vm);#ifdef SAFEMODE    if( a+1 >= MEM_SIZE ) {        printf(exec_loads reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, a+1);        goto *dispatch[halt];    }    else if( vm->sp+2 >= STK_SIZE ) {        printf(exec_loads reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+2);        goto *dispatch[halt];    }#endif    vm->pbDataStack[++vm->sp] = vm->pbMemory[a];    vm->pbDataStack[++vm->sp] = vm->pbMemory[a+1];    conv.c[0] = vm->pbMemory[a];    conv.c[1] = vm->pbMemory[a+1];    printf(loaded short data to T.O.S. - % PRIu32  from address 0x%x\n, conv.us, a);    DISPATCH();exec_loadb:;    a = vm_get_imm4(vm);#ifdef SAFEMODE    if( a >= MEM_SIZE ) {        printf(exec_loadb reported: Invalid Memory Access! Current instruction address: % PRIu32  | Stack index: % PRIu32 \nInvalid Memory Address: % PRIu32 \n, vm->ip, vm->sp, a);        goto *dispatch[halt];    }    else if( vm->sp+1 >= STK_SIZE ) {        printf(exec_loadb reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+1);        goto *dispatch[halt];    }#endif    vm->pbDataStack[++vm->sp] = vm->pbMemory[a];    printf(loaded byte data to T.O.S. - % PRIu32  from address 0x%x\n, vm->pbDataStack[vm->sp], a);    DISPATCH();exec_copyl:;    // copy 4 bytes of top of stack and put as new top of stack.#ifdef SAFEMODE    if( vm->sp-3 >= STK_SIZE ) {        printf(exec_copyl reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-3);        goto *dispatch[halt];    }#endif    conv.c[0] = vm->pbDataStack[vm->sp-3];    conv.c[1] = vm->pbDataStack[vm->sp-2];    conv.c[2] = vm->pbDataStack[vm->sp-1];    conv.c[3] = vm->pbDataStack[vm->sp];    printf(copied int data from T.O.S. - % PRIu32 \n, conv.ui);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_copys:;#ifdef SAFEMODE    if( vm->sp-1 >= STK_SIZE ) {        printf(exec_copys reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-1);        goto *dispatch[halt];    }#endif    conv.c[0] = vm->pbDataStack[vm->sp-1];    conv.c[1] = vm->pbDataStack[vm->sp];    vm->pbDataStack[++vm->sp] = conv.c[0];    vm->pbDataStack[++vm->sp] = conv.c[1];    printf(copied short data from T.O.S. - % PRIu32 \n, conv.us);    DISPATCH();exec_copyb:;#ifdef SAFEMODE    if( vm->sp+1 >= STK_SIZE ) {        printf(exec_copys reported: stack overflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp+1);        goto *dispatch[halt];    }#endif    conv.c[0] = vm->pbDataStack[vm->sp];    vm->pbDataStack[++vm->sp] = conv.c[0];    printf(copied byte data from T.O.S. - % PRIu32 \n, conv.c[0]);    DISPATCH();exec_addl:;     // pop 8 bytes, signed addition, and push 4 byte result to top of stack    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.i = (int)a + (int)b;    printf(signed 4 byte addition result: %i == %i + %i\n, conv.i, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_uaddl:;    // In C, all integers in an expression are promoted to int32, if number is bigger then uint32 or int64    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a+b;    printf(unsigned 4 byte addition result: %u == %u + %u\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_addf:;    fb = _vm_pop_float32(vm);    fa = _vm_pop_float32(vm);    conv.f = fa+fb;    printf(float addition result: %f == %f + %f\n, conv.f, fa,fb);    _vm_push_float(vm, conv.f);    DISPATCH();exec_subl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.i = (int)a - (int)b;    printf(signed 4 byte subtraction result: %i == %i - %i\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_usubl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a-b;    printf(unsigned 4 byte subtraction result: % PRIu32  == % PRIu32  - % PRIu32 \n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_subf:;    fb = _vm_pop_float32(vm);    fa = _vm_pop_float32(vm);    conv.f = fa-fb;    printf(float subtraction result: %f == %f - %f\n, conv.f, fa,fb);    _vm_push_float(vm, conv.f);    DISPATCH();exec_mull:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.i = (int)a * (int)b;    printf(signed 4 byte mult result: %i == %i * %i\n, conv.i, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_umull:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a*b;    printf(unsigned 4 byte mult result: % PRIu32  == % PRIu32  * % PRIu32 \n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_mulf:;    fb = _vm_pop_float32(vm);    fa = _vm_pop_float32(vm);    conv.f = fa*fb;    printf(float mul result: %f == %f * %f\n, conv.f, fa,fb);    _vm_push_float(vm, conv.f);    DISPATCH();exec_divl:;    b = _vm_pop_word(vm);    if( !b ) {        printf(divl: divide by 0 error.\n);        goto *dispatch[halt];    }    a = _vm_pop_word(vm);    conv.i = (int)a / (int)b;    printf(signed 4 byte division result: %i == %i / %i\n, conv.i, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_udivl:;    b = _vm_pop_word(vm);    if( !b ) {        printf(udivl: divide by 0 error.\n);        goto *dispatch[halt];    }    a = _vm_pop_word(vm);    conv.ui = a/b;    printf(unsigned 4 byte division result: % PRIu32  == % PRIu32  / % PRIu32 \n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_divf:;    fb = _vm_pop_float32(vm);    if( !fb ) {        printf(divf: divide by 0.0 error.\n);        goto *dispatch[halt];    }    fa = _vm_pop_float32(vm);    conv.f = fa/fb;    printf(float division result: %f == %f / %f\n, conv.f, fa,fb);    _vm_push_float(vm, conv.f);    DISPATCH();exec_modl:;    b = _vm_pop_word(vm);    if( !b ) {        printf(modl: divide by 0 error.\n);        goto *dispatch[halt];    }    a = _vm_pop_word(vm);    conv.i = (int)a % (int)b;    printf(signed 4 byte modulo result: %i == %i %% %i\n, conv.i, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_umodl:;    b = _vm_pop_word(vm);    if( !b ) {        printf(umodl: divide by 0 error.\n);        goto *dispatch[halt];    }    a = _vm_pop_word(vm);    conv.ui = a%b;    printf(unsigned 4 byte modulo result: % PRIu32  == % PRIu32  %% % PRIu32 \n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_andl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a & b;    printf(4 byte AND result: % PRIu32  == %u & %u\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_orl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a | b;    printf(4 byte OR result: % PRIu32  == %u | %u\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_xorl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a ^ b;    printf(4 byte XOR result: % PRIu32  == %u ^ %u\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_notl:;    a = _vm_pop_word(vm);    conv.ui = ~a;    printf(4 byte NOT result: % PRIu32 \n, conv.ui);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_shll:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a << b;    printf(4 byte Shift Left result: % PRIu32  == %u << %u\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_shrl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a >> b;    printf(4 byte Shift Right result: % PRIu32  == %u >> %u\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_incl:;    a = _vm_pop_word(vm);    conv.ui = ++a;    printf(4 byte Increment result: % PRIu32 \n, conv.ui);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_decl:;    a = _vm_pop_word(vm);    conv.ui = --a;    printf(4 byte Decrement result: % PRIu32 \n, conv.ui);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_negl:;    a = _vm_pop_word(vm);    conv.ui = -a;    printf(4 byte Decrement result: % PRIu32 \n, conv.ui);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_ltl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = (int)a < (int)b;    printf(4 byte Signed Less Than result: % PRIu32  == %i < %i\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_ultl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a < b;    printf(4 byte Unsigned Less Than result: % PRIu32  == % PRIu32  < % PRIu32 \n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_ltf:;    fb = _vm_pop_float32(vm);    fa = _vm_pop_float32(vm);    conv.ui = fa < fb;    printf(4 byte Less Than Float result: % PRIu32  == %f < %f\n, conv.ui, fa,fb);    _vm_push_float(vm, conv.f);    DISPATCH();exec_gtl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = (int)a > (int)b;    printf(4 byte Signed Greater Than result: % PRIu32  == %i > %i\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_ugtl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a > b;    printf(4 byte Signed Greater Than result: % PRIu32  == % PRIu32  > % PRIu32 \n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_gtf:;    fb = _vm_pop_float32(vm);    fa = _vm_pop_float32(vm);    conv.ui = fa > fb;    printf(4 byte Greater Than Float result: % PRIu32  == %f > %f\n, conv.ui, fa,fb);    _vm_push_float(vm, conv.f);    DISPATCH();exec_cmpl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = (int)a == (int)b;    printf(4 byte Signed Compare result: % PRIu32  == %i == %i\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_ucmpl:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a == b;    printf(4 byte Unsigned Compare result: % PRIu32  == % PRIu32  == % PRIu32 \n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_compf:;    fb = _vm_pop_float32(vm);    fa = _vm_pop_float32(vm);    conv.ui = fa == fb;    printf(4 byte Compare Float result: % PRIu32  == %f == %f\n, conv.ui, fa,fb);    _vm_push_float(vm, conv.f);    DISPATCH();exec_leql:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = (int)a <= (int)b;    printf(4 byte Signed Less Equal result: % PRIu32  == %i <= %i\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_uleql:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a <= b;    printf(4 byte Unsigned Less Equal result: % PRIu32  == % PRIu32  <= % PRIu32 \n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_leqf:;    fb = _vm_pop_float32(vm);    fa = _vm_pop_float32(vm);    conv.ui = fa <= fb;    printf(4 byte Less Equal Float result: % PRIu32  == %f <= %f\n, conv.ui, fa, fb);    _vm_push_float(vm, conv.f);    DISPATCH();exec_geql:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = (int)a >= (int)b;    printf(4 byte Signed Greater Equal result: % PRIu32  == %i >= %i\n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_ugeql:;    b = _vm_pop_word(vm);    a = _vm_pop_word(vm);    conv.ui = a >= b;    printf(4 byte Unsigned Greater Equal result: % PRIu32  == % PRIu32  >= % PRIu32 \n, conv.ui, a,b);    _vm_push_word(vm, conv.ui);    DISPATCH();exec_geqf:;    fb = _vm_pop_float32(vm);    fa = _vm_pop_float32(vm);    conv.ui = fa >= fb;    printf(4 byte Greater Equal Float result: % PRIu32  == %f >= %f\n, conv.ui, fa, fb);    _vm_push_float(vm, conv.f);    DISPATCH();exec_jmp:;      // addresses are word sized bytes.    conv.ui = vm_get_imm4(vm);    vm->ip = conv.ui;    printf(jmping to instruction address: % PRIu32 \n, vm->ip);    goto *dispatch[ vm->pInstrStream[vm->ip] ];exec_jzl:;      // check if the first 4 bytes on stack are zero, if yes then jump it.#ifdef SAFEMODE    if( vm->sp-3 >= STK_SIZE ) {        printf(exec_jzl reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-3);        goto *dispatch[halt];    }#endif    conv.c[3] = vm->pbDataStack[vm->sp];    conv.c[2] = vm->pbDataStack[vm->sp-1];    conv.c[1] = vm->pbDataStack[vm->sp-2];    conv.c[0] = vm->pbDataStack[vm->sp-3];    a = conv.ui;    conv.ui = vm_get_imm4(vm);    vm->ip = (!a) ? conv.ui : vm->ip+1 ;    printf(jzl'ing to instruction address: % PRIu32 \n, vm->ip);    //opcode2str[vm->pInstrStream[vm->ip]]    goto *dispatch[ vm->pInstrStream[vm->ip] ];exec_jnzl:;#ifdef SAFEMODE    if( vm->sp-3 >= STK_SIZE ) {        printf(exec_jnzl reported: stack underflow! Current instruction address: % PRIu32  | Stack index: % PRIu32 \n, vm->ip, vm->sp-3);        goto *dispatch[halt];    }#endif    conv.c[3] = vm->pbDataStack[vm->sp];    conv.c[2] = vm->pbDataStack[vm->sp-1];    conv.c[1] = vm->pbDataStack[vm->sp-2];    conv.c[0] = vm->pbDataStack[vm->sp-3];    a = conv.ui;    conv.ui = vm_get_imm4(vm);    vm->ip = (a) ? conv.ui : vm->ip+1 ;    printf(jnzl'ing to instruction address: % PRIu32 \n, vm->ip);    goto *dispatch[ vm->pInstrStream[vm->ip] ];exec_call:;    conv.ui = vm_get_imm4(vm);    printf(calling address: % PRIu32 \n, conv.ui);#ifdef SAFEMODE    if( vm->callsp+1 >= CALLSTK_SIZE ) {        printf(exec_call reported: callstack overflow! Current instruction address: % PRIu32  | Call Stack index: % PRIu32 \n, vm->ip, vm->callsp+1);        goto *dispatch[halt];    }#endif    vm->bCallstack[++vm->callsp] = vm->ip+1;    //vm->bp = vm->callsp;    vm->ip = conv.ui;    printf(call return addr: % PRIu32 \n, vm->bCallstack[vm->callsp]);    goto *dispatch[ vm->pInstrStream[vm->ip] ];exec_ret:;    //vm->callsp = vm->bp;    //printf(callsp set to bp, callsp == % PRIu32 \n, vm->callsp);#ifdef SAFEMODE    if( vm->callsp-1 >= CALLSTK_SIZE ) {        printf(exec_ret reported: callstack underflow! Current instruction address: % PRIu32  | Call Stack index: % PRIu32 \n, vm->ip, vm->callsp-1);        goto *dispatch[halt];    }#endif    vm->ip = vm->bCallstack[vm->callsp--];    //vm->bp = vm->callsp;    printf(returning to address: % PRIu32 \n, vm->ip);    goto *dispatch[ vm->pInstrStream[vm->ip] ];exec_reset:;    vm_reset(vm);    return;}unsigned long long int get_file_size(FILE *pFile){    unsigned long long int size = 0;    if( !pFile )        return size;    if( !fseek(pFile, 0, SEEK_END) ) {        size = (unsigned long long int)ftell(pFile);        rewind(pFile);    }    return size;}int main(void){    /*    FILE *pFile = fopen(./myfile.original_lang_file_ext, rb);    if( !pFile )        return 0;    unsigned long long int size = get_file_size(pFile);    uchar *program = malloc(sizeof(uchar)*size);    fread(program, sizeof(uchar), size, pFile);    fclose(pFile); pFile=NULL;    */    bytecode test1 = {        nop,        //pushl, 255, 1, 0, 0x0,        //pushs, 0xDD, 0xDD,        pushb, 0xAA,        pushb, 0xFF,        halt    };    bytecode float_test = {        nop,        //jmp, 17,0,0,0,        // -16776961        //pushl, 255,0,0,255,        //pushl, 1,0,0,0,        // -855637761        pushl, 255,0,0,205,        pushl, 255,255,0,0,        uaddl, popl,        // 10.f in 4 bytes form        pushl, 0,0,32,65,        jzl, 17,0,0,0,        // 2.f in 4 bytes form        pushl, 0,0,0,64,        addf,   // 12.f        //leqf,        halt    };    bytecode nested_func_calls = {        nop,        call, 7,0,0,0,  // 1        halt,           // 6    // func1:        pushl, 9,0,0,0, // 7        call, 18,0,0,0, // 12        ret,    // 17    // func2:        pushl, 5,0,0,0, // 18        pushl, 10,0,0,0,    // 23        mull,   // 28        mull,        call, 36,0,0,0, // 30        ret,        // func3:        pushl, 40,0,0,0,    // 36        divl,   // 41        ret,    };    // Fibonnaci sequence to test performance!    /*  int fib(int n)        {            int a = 0;            int b = 1;            while (n-- > 1) {                int t = a;                a = b;                b += t;            }            return b;        }    */    bytecode fibonacci = {        nop, // calc fibonnaci number        wrtl, 0,0,0,0, 30,0,0,0,    // write n to address 0        call, 16,0,0,0,        halt,        // a = 0;        wrtl, 4,0,0,0, 0,0,0,0,     // 16        // b = 1;        wrtl, 8,0,0,0, 1,0,0,0,     // 25        // while( n-- > 1 ) {        loadl, 0,0,0,0,     // load param n     // 34        pushl, 1,0,0,0,     // push 1        gtl,        loadl, 0,0,0,0,     // load param n        decl,               // decrement address 0        storel, 0,0,0,0,    // store decrement result to memory address        jzl, 103,0,0,0,     // jmp to storing b and returning.        popl,        // int t = a;        loadl, 4,0,0,0,     // load a's value.        storel, 12,0,0,0,   // store a's value into another address as 't'        // a = b;        loadl, 8,0,0,0,     // load b.        storel, 4,0,0,0,    // store b's value into a's address.        // b += t;        loadl, 12,0,0,0,    // load t.        loadl, 8,0,0,0,     // load b.        uaddl,              // add b and t        storel, 8,0,0,0,    // store addition value to b's address.        jmp, 34,0,0,0,      // jmp back to start of loop.   // 98        // }        ret     // b has been fully 'mathemized' and is stored into memory for reuse.    };    bytecode hello_world = {        nop,        wrtb, 0,0,0,0,  72,     // H        wrtb, 1,0,0,0,  101,    // e        wrtb, 2,0,0,0,  108,    // l        wrtb, 3,0,0,0,  108,    // l        wrtb, 4,0,0,0,  111,    // o        wrtb, 5,0,0,0,  32,     // space        wrtb, 6,0,0,0,  87,     // W        wrtb, 7,0,0,0,  111,    // o        wrtb, 8,0,0,0,  114,    // r        wrtb, 9,0,0,0,  108,    // l        wrtb, 10,0,0,0, 100,    // d        halt,    };    CVM_t *vm = &(CVM_t){ 0 };    vm_init(vm);    vm_load_code(vm, test1);                vm_exec(vm); vm_free(vm);    vm_load_code(vm, float_test);           vm_exec(vm); vm_free(vm);    vm_load_code(vm, nested_func_calls);    vm_exec(vm); vm_free(vm);    vm_load_code(vm, fibonacci);            vm_exec(vm); vm_free(vm);    vm_load_code(vm, hello_world); vm_exec(vm);    uchar buffer[12] = {0};    vm_read_bytearray(vm, buffer, 12, 0x0);    printf(buffer == \'%s\'\n, buffer);    //printf(instruction set amount == %u\n, nop);    vm_debug_print_memory(vm);    vm_debug_print_stack(vm);    vm_free(vm);    //vm_debug_print_callstack(p_vm);    //vm_debug_print_ptrs(p_vm);    //free(program); program=NULL;    return 0;}
C virtual machine 3rd follow up
c;virtual machine
Unsafe bounds checkThis kind of bounds check:if( address+3 >= MEM_SIZE ) {doesn't work if address is 0xffffffff.  It would be better to rewrite that check as this:if( address >= MEM_SIZE-3 ) {Better yet, I would change it to this:if( address > MEM_SIZE-4 ) {so that the 4 matches the number of bytes you are accessing.Pointer supportCurrently, the only instructions you have to load/store from an address are like loadl and storel, which specify their address as part of the instruction.  In order to support pointers, I think you will need to add new instructions such as loadindl and storeindl (where ind means indirect).loadindl would pop a 4 byte address from the stack and use that address to load 4 bytes from memory onto the stack.  storeindl would pop a 4 byte address from the stack, then pop a 4 byte value from the stack, then store that value to that address.So the way you would load from a pointer would be something like:loadl <ptr address>loadindlThe way you wuold store to a pointer would be something like:pushl <value to store>loadl <ptr address>storeindl