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
|
||||
!test*.eipa
|
||||
*.eipaimg
|
||||
build/*
|
||||
|
||||
#Code editor
|
||||
.vscode/*
|
||||
|
@ -67,4 +68,4 @@ compile_commands.json
|
|||
*.*~
|
||||
|
||||
#Code analysis
|
||||
softwipe*.*
|
||||
softwipe*.*
|
||||
|
|
2
Makefile
2
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)
|
||||
|
|
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
|
||||
|
||||
#ifndef WIN_COMPILE
|
||||
#include <argp.h>
|
||||
#else
|
||||
#include "../header/argp/argp.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.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;
|
||||
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;
|
||||
}
|
||||
|
|
BIN
test/loopprint.eimg
Normal file
BIN
test/loopprint.eimg
Normal file
Binary file not shown.
Loading…
Reference in a new issue