Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 77 additions & 8 deletions include/SASM/sasm_instructions.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
#include "univ_defs.h"

/**
* Meta flags for CPU state. F1-F7 are reserved for user-defined conditions.
* Users can assign custom meanings to these flags at runtime or via configuration.
* Example usage:
* setFlag(META_F1, cpu, true); // Set user-defined flag 1
* getFlag(META_F1, cpu); // Check user-defined flag 1
*/
typedef enum {
META_HALT = 1 << 0,
META_F1 = 1 << 1,
META_F2 = 1 << 2,
META_F3 = 1 << 3,
META_F4 = 1 << 4,
META_F5 = 1 << 5,
META_F6 = 1 << 6,
META_F7 = 1 << 7
META_HALT = 1 << 0, // System Halt
META_F1 = 1 << 1, // User-defined Flag 1
META_F2 = 1 << 2, // User-defined Flag 2
META_F3 = 1 << 3, // User-defined Flag 3
META_F4 = 1 << 4, // User-defined Flag 4
META_F5 = 1 << 5, // User-defined Flag 5
META_F6 = 1 << 6, // User-defined Flag 6
META_F7 = 1 << 7 // User-defined Flag 7
} Meta;

/**
* To assign a meaning to a user-defined flag, set up a mapping in your configuration or code:
* Example:
* // In your config or code
* #define USER_FLAG_CONDITION_1 "Interrupt Enabled"
* #define USER_FLAG_CONDITION_2 "Debug Mode"
* // ...
* Then use setFlag/getFlag to manipulate these flags as needed.
*/

typedef enum {

INST_DONOP = 0,
Expand Down Expand Up @@ -189,3 +206,55 @@ OpcodeDetails getOpcodeDetails(Opcode type);
void setFlag(Meta f, CPU* cpu, bool state);

bool getFlag(Meta f, const CPU* cpu);

#include <stddef.h>

#define USER_FLAG_COUNT 7

// Structure for user-defined flag metadata
typedef struct {
const char* name; // Human-readable name or meaning
int (*condition_cb)(const struct CPU* cpu); // Optional callback for dynamic condition
} UserFlagDef;

// Registry for user-defined flags (F1-F7)
extern UserFlagDef user_flag_registry[USER_FLAG_COUNT];

// Register a user-defined flag (index 0-6 for F1-F7)
void register_user_flag(int flag_index, const char* name, int (*condition_cb)(const struct CPU*));

// Get user-defined flag name
const char* get_user_flag_name(int flag_index);

// Evaluate user-defined flag condition (returns 0 if no callback)
int eval_user_flag_condition(int flag_index, const struct CPU* cpu);

/**
* === User-Defined Flag System ===
*
* This system allows you to assign semantic meaning and dynamic logic to each user flag (F1-F7).
*
* Example: Registering a flag for "Interrupt Enabled" with a dynamic condition.
*
* int interrupt_enabled_cb(const struct CPU* cpu) {
* // Custom logic: e.g., check a register or memory-mapped IO
* return (cpu->registers.I0 & 0x1) != 0;
* }
* register_user_flag(0, "Interrupt Enabled", interrupt_enabled_cb);
*
* // Query the flag's state (dynamic or static)
* if (getFlag(META_F1, cpu) || eval_user_flag_condition(0, cpu)) {
* // ... handle interrupt logic ...
* }
*
* You can use the provided macros for clarity:
* #define META_USER(n) (1 << ((n)+1)) // n in 0..6 for F1..F7
* #define USER_FLAG_INDEX(meta_flag) (__builtin_ctz(meta_flag) - 1)
*
* // Example usage:
* setFlag(META_USER(2), cpu, true); // Set F3
* int idx = USER_FLAG_INDEX(META_F3); // idx == 2
* const char* name = get_user_flag_name(idx);
*
* This pattern enables scalable, readable, and powerful user-driven flag logic.
*/
70 changes: 44 additions & 26 deletions include/VM/virex_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,30 +26,48 @@ enum Inputs
MAX_INPUTS
};

void OnInstructionExecution(Vm *vm, size_t instructionIndex, bool debug);

void OnStart();

void OnPause();

void OnExit();

int getUserInput();

void printOut(int id, const char *str, ...);

void printOutWithColor(int id, int colorPair, const char *str, ...);

void clearWindow(int id);

void moveCursorWithinWindow(int id, int y, int x);

char getChar(int id);

void refreshAllWindows();

void readFilePath(int id, const char *msg, const char **filePath);

void InputMenu(int *highlight, int *ch);
// UI Interface abstraction for modularity and future GUI support
/**
* UI_Interface: Abstract interface for all UI implementations (CLI, TUI, GUI, etc).
*
* To add a new UI (such as a GUI), simply implement all functions in this struct for your UI,
* and set the global UI pointer to your implementation (e.g., UI = &GUI_UI;).
* This enables seamless switching between CLI, TUI, and future GUI modes.
*/
typedef struct UI_Interface {
void (*OnInstructionExecution)(Vm *vm, size_t instructionIndex, bool debug);
void (*OnStart)();
void (*OnPause)();
void (*OnExit)();
int (*getUserInput)();
void (*printOut)(int id, const char *str, ...);
void (*printOutWithColor)(int id, int colorPair, const char *str, ...);
void (*clearWindow)(int id);
void (*moveCursorWithinWindow)(int id, int y, int x);
char (*getChar)(int id);
void (*refreshAllWindows)();
void (*readFilePath)(int id, const char *msg, const char **filePath);
void (*InputMenu)(int *highlight, int *ch);
void (*SetInputEnable)(bool enable);
};

void SetInputEnable(bool enable);
// Externally accessible UI interface pointer
extern struct UI_Interface *UI;

// Default CLI/TUI implementations (to be defined in respective source files)
void CLI_OnInstructionExecution(Vm *vm, size_t instructionIndex, bool debug);
void CLI_OnStart();
void CLI_OnPause();
void CLI_OnExit();
int CLI_getUserInput();
void CLI_printOut(int id, const char *str, ...);
void CLI_printOutWithColor(int id, int colorPair, const char *str, ...);
void CLI_clearWindow(int id);
void CLI_moveCursorWithinWindow(int id, int y, int x);
char CLI_getChar(int id);
void CLI_refreshAllWindows();
void CLI_readFilePath(int id, const char *msg, const char **filePath);
void CLI_InputMenu(int *highlight, int *ch);
void CLI_SetInputEnable(bool enable);

// Add similar declarations for TUI/GUI as needed
37 changes: 37 additions & 0 deletions src/SASM/sasm_instructions.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,40 @@ inline bool getFlag(Meta f, const CPU* cpu)
{
return cpu->flags & f;
}

UserFlagDef user_flag_registry[USER_FLAG_COUNT] = {0};

void register_user_flag(int flag_index, const char* name, int (*condition_cb)(const CPU*)) {
if (flag_index < 0 || flag_index >= USER_FLAG_COUNT) return;
user_flag_registry[flag_index].name = name;
user_flag_registry[flag_index].condition_cb = condition_cb;
}

const char* get_user_flag_name(int flag_index) {
if (flag_index < 0 || flag_index >= USER_FLAG_COUNT) return NULL;
return user_flag_registry[flag_index].name;
}

int eval_user_flag_condition(int flag_index, const CPU* cpu) {
if (flag_index < 0 || flag_index >= USER_FLAG_COUNT) return 0;
if (user_flag_registry[flag_index].condition_cb)
return user_flag_registry[flag_index].condition_cb(cpu);
return 0;
}

// Example: Register a user-defined flag for "Interrupt Enabled" and use it in logic
static int interrupt_enabled_cb(const CPU* cpu) {
return (cpu->registers.I0 & 0x1) != 0;
}

void setup_user_flags(CPU* cpu) {
register_user_flag(0, "Interrupt Enabled", interrupt_enabled_cb);
setFlag(META_F1, cpu, false); // Start with interrupt disabled
}

void handle_interrupt(CPU* cpu) {
if (getFlag(META_F1, cpu) || eval_user_flag_condition(0, cpu)) {
// Interrupt logic here
setFlag(META_F1, cpu, false); // Clear after handling
}
}
38 changes: 38 additions & 0 deletions src/VM/virex_ui.c
Original file line number Diff line number Diff line change
Expand Up @@ -457,4 +457,42 @@ void InputMenu(int *highlight, int *ch)
default:
break;
}
}

// CLI implementation wrappers for UI_Interface
void CLI_OnInstructionExecution(Vm *vm, size_t instructionIndex, bool debug) { OnInstructionExecution(vm, instructionIndex, debug); }
void CLI_OnStart() { OnStart(); }
void CLI_OnPause() { OnPause(); }
void CLI_OnExit() { OnExit(); }
int CLI_getUserInput() { return getUserInput(); }
void CLI_printOut(int id, const char *str, ...) { va_list args; va_start(args, str); printOut(id, str, args); va_end(args); }
void CLI_printOutWithColor(int id, int colorPair, const char *str, ...) { va_list args; va_start(args, str); printOutWithColor(id, colorPair, str, args); va_end(args); }
void CLI_clearWindow(int id) { clearWindow(id); }
void CLI_moveCursorWithinWindow(int id, int y, int x) { moveCursorWithinWindow(id, y, x); }
char CLI_getChar(int id) { return getChar(id); }
void CLI_refreshAllWindows() { refreshAllWindows(); }
void CLI_readFilePath(int id, const char *msg, const char **filePath) { readFilePath(id, msg, filePath); }
void CLI_InputMenu(int *highlight, int *ch) { InputMenu(highlight, ch); }
void CLI_SetInputEnable(bool enable) { SetInputEnable(enable); }

// UI_Interface instance for CLI
struct UI_Interface CLI_UI = {
.OnInstructionExecution = CLI_OnInstructionExecution,
.OnStart = CLI_OnStart,
.OnPause = CLI_OnPause,
.OnExit = CLI_OnExit,
.getUserInput = CLI_getUserInput,
.printOut = CLI_printOut,
.printOutWithColor = CLI_printOutWithColor,
.clearWindow = CLI_clearWindow,
.moveCursorWithinWindow = CLI_moveCursorWithinWindow,
.getChar = CLI_getChar,
.refreshAllWindows = CLI_refreshAllWindows,
.readFilePath = CLI_readFilePath,
.InputMenu = CLI_InputMenu,
.SetInputEnable = CLI_SetInputEnable
};

// Global pointer to active UI
struct UI_Interface *UI = &CLI_UI;
}