Add argp, and executing functionality
This commit is contained in:
parent
0c8d7b57cb
commit
b42d5e7e67
11 changed files with 269 additions and 28 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -57,6 +57,7 @@ dkms.conf
|
||||||
*.eipa
|
*.eipa
|
||||||
!test*.eipa
|
!test*.eipa
|
||||||
*.eipaimg
|
*.eipaimg
|
||||||
|
build/*
|
||||||
|
|
||||||
#Code editor
|
#Code editor
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|
@ -67,4 +68,4 @@ compile_commands.json
|
||||||
*.*~
|
*.*~
|
||||||
|
|
||||||
#Code analysis
|
#Code analysis
|
||||||
softwipe*.*
|
softwipe*.*
|
||||||
|
|
|
||||||
2
Makefile
2
Makefile
|
|
@ -7,7 +7,7 @@ LIBS :=
|
||||||
OBJECT_FILES := $(patsubst %.c, %.o, $(wildcard $(SRC_DIR)/*.c))
|
OBJECT_FILES := $(patsubst %.c, %.o, $(wildcard $(SRC_DIR)/*.c))
|
||||||
HEADER_FILES := $(wildcard $(HEADER_DIR)/*.h)
|
HEADER_FILES := $(wildcard $(HEADER_DIR)/*.h)
|
||||||
OBJECT_FILES := $(patsubst $(SRC_DIR)/%, $(BUILD_DIR)/%, $(OBJECT_FILES))
|
OBJECT_FILES := $(patsubst $(SRC_DIR)/%, $(BUILD_DIR)/%, $(OBJECT_FILES))
|
||||||
MAIN_EXE_NAME := eipaemulator
|
MAIN_EXE_NAME := eipaemu
|
||||||
|
|
||||||
all build/eipaemulator: $(OBJECT_FILES)
|
all build/eipaemulator: $(OBJECT_FILES)
|
||||||
$(CC) $(CFLAGS) $^ $(LIBS) -o $(BUILD_DIR)/$(MAIN_EXE_NAME)
|
$(CC) $(CFLAGS) $^ $(LIBS) -o $(BUILD_DIR)/$(MAIN_EXE_NAME)
|
||||||
|
|
|
||||||
Binary file not shown.
9
header/argp_commons.h
Executable file
9
header/argp_commons.h
Executable file
|
|
@ -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
|
||||||
41
header/common.h
Executable file
41
header/common.h
Executable file
|
|
@ -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
|
||||||
13
header/execute.h
Normal file
13
header/execute.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef _EXECUTE_H_
|
||||||
|
#define _EXECUTE_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
// Executes given memory
|
||||||
|
int execute(uint32_t *memory);
|
||||||
|
|
||||||
|
#endif
|
||||||
9
header/helpers.h
Normal file
9
header/helpers.h
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef _HELPER_H_
|
||||||
|
#define _HELPER_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void print_target_code(uint32_t *target_code);
|
||||||
|
|
||||||
|
#endif
|
||||||
97
src/execute.c
Normal file
97
src/execute.c
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
16
src/helpers.c
Normal file
16
src/helpers.c
Normal file
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
107
src/main.c
107
src/main.c
|
|
@ -2,40 +2,95 @@
|
||||||
|
|
||||||
// Read an EIPA image and print it out in Binary form
|
// Read an EIPA image and print it out in Binary form
|
||||||
|
|
||||||
|
#ifndef WIN_COMPILE
|
||||||
|
#include <argp.h>
|
||||||
|
#else
|
||||||
|
#include "../header/argp/argp.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#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;
|
char *input_file;
|
||||||
while (target_code[instruction_index] != 0)
|
};
|
||||||
|
|
||||||
|
// 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;
|
case ARGP_KEY_ARG:
|
||||||
for (i = (sizeof(target_code[instruction_index]) * 8) - 1; i >= 0; i--)
|
// 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");
|
save_arguments->input_file = arg;
|
||||||
instruction_index++;
|
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;
|
||||||
}
|
}
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
int main(int argc, char const *argv[])
|
|
||||||
{
|
// This array stores structs containing information about the cli options
|
||||||
if(argc < 2)
|
static struct argp_option argp_options[] = {{0}};
|
||||||
{
|
|
||||||
printf("Specify input file\n");
|
// Contains the neccesary stuff for argp
|
||||||
}
|
static struct argp argument_parser =
|
||||||
FILE *input = fopen(argv[1], "r");
|
{
|
||||||
if(input == NULL) return -1;
|
.options = argp_options,
|
||||||
|
.parser = parser_function,
|
||||||
__uint32_t *target_code = malloc(MAX_MEMORY*sizeof(target_code));
|
.args_doc = ARGUMENT_DOC,
|
||||||
|
.doc = LONG_DOC};
|
||||||
fread(target_code, sizeof(target_code), MAX_MEMORY, input);
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
print_target_code(target_code);
|
{
|
||||||
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
test/loopprint.eimg
Normal file
BIN
test/loopprint.eimg
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue