diff --git a/.gitignore b/.gitignore index c155c8d..00ac722 100755 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ dkms.conf *.eipa !test*.eipa *.eipaimg +build/* #Code editor .vscode/* @@ -67,4 +68,4 @@ compile_commands.json *.*~ #Code analysis -softwipe*.* \ No newline at end of file +softwipe*.* diff --git a/Makefile b/Makefile index 82b7936..4479800 100755 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ LIBS := OBJECT_FILES := $(patsubst %.c, %.o, $(wildcard $(SRC_DIR)/*.c)) HEADER_FILES := $(wildcard $(HEADER_DIR)/*.h) OBJECT_FILES := $(patsubst $(SRC_DIR)/%, $(BUILD_DIR)/%, $(OBJECT_FILES)) -MAIN_EXE_NAME := eipaemulator +MAIN_EXE_NAME := eipaemu all build/eipaemulator: $(OBJECT_FILES) $(CC) $(CFLAGS) $^ $(LIBS) -o $(BUILD_DIR)/$(MAIN_EXE_NAME) diff --git a/build/eipaemulator b/build/eipaemulator deleted file mode 100755 index d408ffa..0000000 Binary files a/build/eipaemulator and /dev/null differ diff --git a/header/argp_commons.h b/header/argp_commons.h new file mode 100755 index 0000000..a481585 --- /dev/null +++ b/header/argp_commons.h @@ -0,0 +1,9 @@ +#ifndef _ARGP_COMMONS_H_ +#define _ARGP_COMMONS_H_ + +#include "../header/common.h" + +#define ARGUMENT_DOC "INPUT_FILE" +#define LONG_DOC "options:" + +#endif diff --git a/header/common.h b/header/common.h new file mode 100755 index 0000000..318569c --- /dev/null +++ b/header/common.h @@ -0,0 +1,41 @@ +/* +This code is part of the EIPA Platform + +Here, common macros are specified +*/ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +// Maximum Memory Adresses +#define MAX_MEMORY 268435456 + +// Intitial size and grow size for dynamic buffers +#define TABLE_INIT_SIZE 50 +#define TABLE_GROW_SIZE 30 + +#define VER_MAJOR "0" +#define VER_MINOR "0" +#define VER_PATCH "1" + +// alpha, beta or stable +#define TAG "alpha" + +#define INSTR_INP 0b0001 +#define INSTR_OUT 0b0010 +#define INSTR_LDA 0b0011 +#define INSTR_STA 0b0100 +#define INSTR_INC 0b0101 +#define INSTR_DEC 0b0110 +#define INSTR_JPP 0b0111 +#define INSTR_JPZ 0b1000 +#define INSTR_JPN 0b1001 +#define INSTR_JPU 0b1010 +#define INSTR_EOJ 0b1011 + +#define ADRESS_BITS 0b00001111111111111111111111111111 + +// const char *argp_program_bug_address = "eipabugs@outlook.com"; +#define EIPA_BUG_ADRESS "eipabugs@outlook.com" + +#endif diff --git a/header/execute.h b/header/execute.h new file mode 100644 index 0000000..8076118 --- /dev/null +++ b/header/execute.h @@ -0,0 +1,13 @@ +#ifndef _EXECUTE_H_ +#define _EXECUTE_H_ + +#include +#include +#include + +#include "common.h" + +// Executes given memory +int execute(uint32_t *memory); + +#endif diff --git a/header/helpers.h b/header/helpers.h new file mode 100644 index 0000000..03a3715 --- /dev/null +++ b/header/helpers.h @@ -0,0 +1,9 @@ +#ifndef _HELPER_H_ +#define _HELPER_H_ + +#include +#include + +void print_target_code(uint32_t *target_code); + +#endif diff --git a/src/execute.c b/src/execute.c new file mode 100644 index 0000000..16d39d3 --- /dev/null +++ b/src/execute.c @@ -0,0 +1,97 @@ +#include "../header/execute.h" + +int execute(uint32_t *memory) +{ + uint32_t instr_ptr = 0; + uint32_t instr_curr; + uint32_t cpu_register = 0; + while((instr_curr = memory[instr_ptr]) >> 28 != INSTR_EOJ) + { + uint8_t op_code = memory[instr_ptr] >> 28; // Get only the first 4 bits + uint32_t adress = memory[instr_ptr] & ADRESS_BITS; // Discard the first 4 bits + + // This check should be unnecessary when using the official EIPA Assembler, but + // some people might want to hand-craft their EIPA Images + if(adress > MAX_MEMORY) + { + printf("ERROR: Adress on instruction %u is too big\n", instr_ptr); + return 1; + } + + // Run the instruction + switch(op_code) + { + case INSTR_INP: + { + printf("Input: "); + int check = scanf("%u", memory + adress); + fflush(stdin); + if(!check) + { + printf("ERROR: Received invalid input on a INP instruction\n"); + return 1; + } + instr_ptr++; + break; + } + case INSTR_OUT: + printf("%u\n", memory[adress]); + instr_ptr++; + break; + case INSTR_LDA: + cpu_register = memory[adress]; + instr_ptr++; + break; + case INSTR_STA: + memory[adress] = cpu_register; + instr_ptr++; + break; + case INSTR_INC: + cpu_register++; + instr_ptr++; + break; + case INSTR_DEC: + cpu_register--; + instr_ptr++; + break; + case INSTR_JPP: + if(cpu_register > 0) + { + instr_ptr = adress; + } + else + { + instr_ptr++; + } + break; + case INSTR_JPZ: + if(cpu_register == 0) + { + instr_ptr = adress; + } + else + { + instr_ptr++; + } + break; + case INSTR_JPN: + if(cpu_register < 0) + { + instr_ptr = adress; + } + else + { + instr_ptr++; + } + break; + case INSTR_JPU: + instr_ptr = adress; + break; + default: + printf("ERROR: Unknown opcode %u\n", op_code); + } + + } + + return 0; +} diff --git a/src/helpers.c b/src/helpers.c new file mode 100644 index 0000000..ed94b88 --- /dev/null +++ b/src/helpers.c @@ -0,0 +1,16 @@ +#include "../header/helpers.h" + +void print_target_code(uint32_t *target_code) +{ + int instruction_index = 0; + while (target_code[instruction_index] != 0) + { + int i = 0; + for (i = (sizeof(target_code[instruction_index]) * 8) - 1; i >= 0; i--) + { + putchar(target_code[instruction_index] & (1u << i) ? '1' : '0'); + } + printf("\n"); + instruction_index++; + } +} diff --git a/src/main.c b/src/main.c index 682c079..f354d3f 100755 --- a/src/main.c +++ b/src/main.c @@ -2,40 +2,95 @@ // Read an EIPA image and print it out in Binary form +#ifndef WIN_COMPILE +#include +#else +#include "../header/argp/argp.h" +#endif + #include #include -#define MAX_MEMORY 268435456 +#include "../header/argp_commons.h" +#include "../header/common.h" +#include "../header/helpers.h" +#include "../header/execute.h" -void print_target_code(__uint32_t *target_code) +const char *argp_program_version = + VER_MAJOR "." VER_MINOR "." VER_PATCH " || " TAG; + +const char *argp_program_bug_address = EIPA_BUG_ADRESS; + +// Here, the argumets get stored by the parser, so acess them from here +struct cmd_arguments { - int instruction_index = 0; - while (target_code[instruction_index] != 0) + char *input_file; +}; + +// Parses the command line options & arguments +static error_t parser_function(int key, char *arg, struct argp_state *state) +{ + struct cmd_arguments *save_arguments = state->input; + + switch (key) { - int i = 0; - for (i = (sizeof(target_code[instruction_index]) * 8) - 1; i >= 0; i--) + case ARGP_KEY_ARG: + // If we got more than one non-option argument + if (state->arg_num >= 1) { - putchar(target_code[instruction_index] & (1u << i) ? '1' : '0'); + argp_usage(state); } - printf("\n"); - instruction_index++; + save_arguments->input_file = arg; + break; + case ARGP_KEY_END: + // If we didn't receive 1 Argument yet + if (state->arg_num < 1) + { + argp_usage(state); + } + break; + default: + return ARGP_ERR_UNKNOWN; } -} - -int main(int argc, char const *argv[]) -{ - if(argc < 2) - { - printf("Specify input file\n"); - } - FILE *input = fopen(argv[1], "r"); - if(input == NULL) return -1; - - __uint32_t *target_code = malloc(MAX_MEMORY*sizeof(target_code)); - - fread(target_code, sizeof(target_code), MAX_MEMORY, input); - - print_target_code(target_code); - + return 0; +} + +// This array stores structs containing information about the cli options +static struct argp_option argp_options[] = {{0}}; + +// Contains the neccesary stuff for argp +static struct argp argument_parser = + { + .options = argp_options, + .parser = parser_function, + .args_doc = ARGUMENT_DOC, + .doc = LONG_DOC}; + +int main(int argc, char **argv) +{ + // Parse CLI Arguments + // set defaults + struct cmd_arguments arguments; + arguments.input_file = ""; + + if (argp_parse(&argument_parser, argc, argv, 0, 0, &arguments) != 0) + { + printf("Error: Failed to parse CLI Arguments - Error code\n"); + return EXIT_FAILURE; + } + + FILE *input = fopen(arguments.input_file, "r"); + if (input == NULL) + return -1; + + // Allocate the memory of the Emulated device + uint32_t *memory = malloc(MAX_MEMORY * sizeof(memory)); + + // Load the binary into memory + fread(memory, sizeof(memory), MAX_MEMORY, input); + + execute(memory); + + free(memory); return 0; } diff --git a/test/loopprint.eimg b/test/loopprint.eimg new file mode 100644 index 0000000..3fb2260 Binary files /dev/null and b/test/loopprint.eimg differ