From 32b4cab78eca46e219d2b85e4e79983c1fbc02df Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 29 May 2024 13:27:03 +0100 Subject: [PATCH 1/8] Add Object File Loader (objectloader) --- src/emulator/defs.h | 26 ++++++++++++++++++++++++++ src/emulator/objectloader.c | 34 ++++++++++++++++++++++++++++++++++ src/emulator/objectloader.h | 15 +++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 src/emulator/defs.h create mode 100644 src/emulator/objectloader.c create mode 100644 src/emulator/objectloader.h diff --git a/src/emulator/defs.h b/src/emulator/defs.h new file mode 100644 index 0000000..62cd9e5 --- /dev/null +++ b/src/emulator/defs.h @@ -0,0 +1,26 @@ +/** + ******************************************************************************** + * @file defs.h + * @brief Defines global constants and types used in the emulator. + ******************************************************************************** + */ + +#ifndef DEFS_H +#define DEFS_H +#include "../global.h" +#include + +/************************************ + * MACROS AND CONSTANTS + ************************************/ +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +/************************************ + * TYPEDEFS + ************************************/ + +typedef uint8_t Byte; + + + #endif \ No newline at end of file diff --git a/src/emulator/objectloader.c b/src/emulator/objectloader.c new file mode 100644 index 0000000..533d146 --- /dev/null +++ b/src/emulator/objectloader.c @@ -0,0 +1,34 @@ +/** + ******************************************************************************** + * @file objectloader.c + * @brief Object file loader for the emulator + ******************************************************************************** + */ + +#include +#include +#include +#include "objectloader.h" +#include "defs.h" + +void loadObjectFile(const char *filename, Byte *memoryAddress) { + FILE *file = fopen(filename, "rb"); + + // Check if the file exists + if (file == NULL) { + fprintf(stderr, "Error: Could not open file %s\n", filename); + exit(EXIT_FAILURE); + } + + // Load the object file into memory (or as much as possible) + size_t bytesRead = fread(memoryAddress, MEMORY_SIZE, 1, file); + if (bytesRead == 0) { + if (feof(file)) + exit(EXIT_SUCCESS); + + fprintf(stderr, "Error: Could not read from file %s\n", filename); + exit(EXIT_FAILURE); + } + + fclose(file); +} \ No newline at end of file diff --git a/src/emulator/objectloader.h b/src/emulator/objectloader.h new file mode 100644 index 0000000..c08cfaa --- /dev/null +++ b/src/emulator/objectloader.h @@ -0,0 +1,15 @@ +/** + * @file objectloader.h + * @brief Object file loader for the emulator + */ + +#include +#include "defs.h" + +/** + * @brief Loads an object file into memory starting at memoryAddress. + * + * @param filename The name of the file to be read + * @param memoryAddress The memory address to load the object file into + */ +void loadObjectFile(const char *filename, Byte *memoryAddress); \ No newline at end of file From f70ab669d69070f056c3cff1b4c4c1099475635a Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 29 May 2024 14:26:51 +0100 Subject: [PATCH 2/8] Update objectloader for consistency --- src/emulator/objectloader.c | 2 +- src/emulator/objectloader.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/emulator/objectloader.c b/src/emulator/objectloader.c index 533d146..da5889b 100644 --- a/src/emulator/objectloader.c +++ b/src/emulator/objectloader.c @@ -11,7 +11,7 @@ #include "objectloader.h" #include "defs.h" -void loadObjectFile(const char *filename, Byte *memoryAddress) { +void loadObjectFile(const char *filename, byte *memoryAddress) { FILE *file = fopen(filename, "rb"); // Check if the file exists diff --git a/src/emulator/objectloader.h b/src/emulator/objectloader.h index c08cfaa..21f0302 100644 --- a/src/emulator/objectloader.h +++ b/src/emulator/objectloader.h @@ -12,4 +12,4 @@ * @param filename The name of the file to be read * @param memoryAddress The memory address to load the object file into */ -void loadObjectFile(const char *filename, Byte *memoryAddress); \ No newline at end of file +void loadObjectFile(const char *filename, byte *memoryAddress); \ No newline at end of file From d7f56e47f79baa742bf1702c7f8d2969310e2adb Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 29 May 2024 14:27:52 +0100 Subject: [PATCH 3/8] Update defs.h: Define Machine, PSTATE --- src/emulator/defs.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/emulator/defs.h b/src/emulator/defs.h index 62cd9e5..5eca223 100644 --- a/src/emulator/defs.h +++ b/src/emulator/defs.h @@ -9,18 +9,30 @@ #define DEFS_H #include "../global.h" #include +#include /************************************ * MACROS AND CONSTANTS ************************************/ #define EXIT_FAILURE 1 -#define EXIT_SUCCESS 0 +#define HALT_INSTRUCTION 0x8a000000; /************************************ * TYPEDEFS ************************************/ - -typedef uint8_t Byte; +typedef uint8_t byte; +typedef struct { + bool Negative; + bool Zero; + bool Carry; + bool Overflow; +} PSTATE; +typedef struct { + word registers[REGISTER_COUNT]; + word PC; + byte memory[MEMORY_SIZE]; + PSTATE conditionCodes; +} Machine; #endif \ No newline at end of file From 4710c729388c0de2fe3df19885abaa79cd4d45be Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 29 May 2024 14:30:35 +0100 Subject: [PATCH 4/8] Update emulate.c to read binary file and initalise state --- src/emulate.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/emulate.c b/src/emulate.c index e2ad1c8..0868d32 100755 --- a/src/emulate.c +++ b/src/emulate.c @@ -1,5 +1,53 @@ #include +#include +#include +#include "emulator/defs.h" +#include "emulator/objectloader.h" int main(int argc, char **argv) { + + // Check the arguments + if (argc == 1) { + fprintf(stderr, "Error: An object file is required. Syntax: ./emulate []"); + return EXIT_FAILURE; + } + + FILE *out = stdout; + if (argc > 2) { + out = fopen(argv[2], "w"); + if (out == NULL) { + fprintf(stderr, "Error: Could not open file %s\n", argv[2]); + return EXIT_FAILURE; + } + } + + // Allocate Memory for the machine + Machine *state = malloc(sizeof(Machine)); + + // Read the binary file into the memory of the machine. + loadObjectFile(argv[1], state->memory); + + // Initialise memory state + memset(state->registers, 0, sizeof(state->registers)); + memset(state->memory, 0, sizeof(state->memory)); + state->PC = 0x0; + state->conditionCodes = (PSTATE){0, 0, 0, 0}; + + // Start Execution Cycle. + /** + * PIPELINE: WHILE(): + * FETCH() + * DECODE() + * EXECUTE() + */ + + /** + * PRINT_STATE(); + */ + + /** + * FREE MEMORY!!! + */ + return EXIT_SUCCESS; } From 46da019131566cf3a744d83385692486feab1946 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Fri, 7 Jun 2024 17:54:09 +0100 Subject: [PATCH 5/8] Remove No longer used files --- src/emulator/defs.h | 38 ------------------------------------- src/emulator/objectloader.c | 34 --------------------------------- src/emulator/objectloader.h | 15 --------------- 3 files changed, 87 deletions(-) delete mode 100644 src/emulator/defs.h delete mode 100644 src/emulator/objectloader.c delete mode 100644 src/emulator/objectloader.h diff --git a/src/emulator/defs.h b/src/emulator/defs.h deleted file mode 100644 index 5eca223..0000000 --- a/src/emulator/defs.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - ******************************************************************************** - * @file defs.h - * @brief Defines global constants and types used in the emulator. - ******************************************************************************** - */ - -#ifndef DEFS_H -#define DEFS_H -#include "../global.h" -#include -#include - -/************************************ - * MACROS AND CONSTANTS - ************************************/ -#define EXIT_FAILURE 1 -#define HALT_INSTRUCTION 0x8a000000; - -/************************************ - * TYPEDEFS - ************************************/ -typedef uint8_t byte; -typedef struct { - bool Negative; - bool Zero; - bool Carry; - bool Overflow; -} PSTATE; -typedef struct { - word registers[REGISTER_COUNT]; - word PC; - byte memory[MEMORY_SIZE]; - PSTATE conditionCodes; -} Machine; - - - #endif \ No newline at end of file diff --git a/src/emulator/objectloader.c b/src/emulator/objectloader.c deleted file mode 100644 index da5889b..0000000 --- a/src/emulator/objectloader.c +++ /dev/null @@ -1,34 +0,0 @@ -/** - ******************************************************************************** - * @file objectloader.c - * @brief Object file loader for the emulator - ******************************************************************************** - */ - -#include -#include -#include -#include "objectloader.h" -#include "defs.h" - -void loadObjectFile(const char *filename, byte *memoryAddress) { - FILE *file = fopen(filename, "rb"); - - // Check if the file exists - if (file == NULL) { - fprintf(stderr, "Error: Could not open file %s\n", filename); - exit(EXIT_FAILURE); - } - - // Load the object file into memory (or as much as possible) - size_t bytesRead = fread(memoryAddress, MEMORY_SIZE, 1, file); - if (bytesRead == 0) { - if (feof(file)) - exit(EXIT_SUCCESS); - - fprintf(stderr, "Error: Could not read from file %s\n", filename); - exit(EXIT_FAILURE); - } - - fclose(file); -} \ No newline at end of file diff --git a/src/emulator/objectloader.h b/src/emulator/objectloader.h deleted file mode 100644 index 21f0302..0000000 --- a/src/emulator/objectloader.h +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @file objectloader.h - * @brief Object file loader for the emulator - */ - -#include -#include "defs.h" - -/** - * @brief Loads an object file into memory starting at memoryAddress. - * - * @param filename The name of the file to be read - * @param memoryAddress The memory address to load the object file into - */ -void loadObjectFile(const char *filename, byte *memoryAddress); \ No newline at end of file From a42576b4ed18613e70a54957c378b83c5c2ad00e Mon Sep 17 00:00:00 2001 From: sBubshait Date: Fri, 7 Jun 2024 18:08:33 +0100 Subject: [PATCH 6/8] Restructing, keeping all emulator modules in emulator directory --- src/Makefile | 5 ++--- src/emulate.c | 12 ++++++------ src/{ => emulator/a64instruction}/a64instruction.h | 0 .../a64instruction}/a64instruction_Branch.h | 2 +- .../a64instruction}/a64instruction_DP.h | 0 .../a64instruction}/a64instruction_DPImmediate.h | 0 .../a64instruction}/a64instruction_DPRegister.h | 0 .../a64instruction}/a64instruction_Directive.h | 2 +- .../a64instruction}/a64instruction_Label.h | 0 .../a64instruction}/a64instruction_SingleTransfer.h | 2 +- .../a64instruction}/a64instruction_global.h | 0 src/{ => emulator}/decode.c | 0 src/{ => emulator}/decode.h | 4 ++-- src/{ => emulator}/emulator.h | 2 +- src/{ => emulator}/execute.c | 0 src/{ => emulator}/execute.h | 2 +- src/{ => emulator}/fileio.c | 2 +- src/{ => emulator}/fileio.h | 2 +- src/{ => emulator}/print.c | 1 - src/{ => emulator}/print.h | 0 test.sh | 0 21 files changed, 17 insertions(+), 19 deletions(-) rename src/{ => emulator/a64instruction}/a64instruction.h (100%) rename src/{ => emulator/a64instruction}/a64instruction_Branch.h (97%) rename src/{ => emulator/a64instruction}/a64instruction_DP.h (100%) rename src/{ => emulator/a64instruction}/a64instruction_DPImmediate.h (100%) rename src/{ => emulator/a64instruction}/a64instruction_DPRegister.h (100%) rename src/{ => emulator/a64instruction}/a64instruction_Directive.h (69%) rename src/{ => emulator/a64instruction}/a64instruction_Label.h (100%) rename src/{ => emulator/a64instruction}/a64instruction_SingleTransfer.h (97%) rename src/{ => emulator/a64instruction}/a64instruction_global.h (100%) rename src/{ => emulator}/decode.c (100%) rename src/{ => emulator}/decode.h (97%) rename src/{ => emulator}/emulator.h (96%) rename src/{ => emulator}/execute.c (100%) rename src/{ => emulator}/execute.h (74%) rename src/{ => emulator}/fileio.c (98%) rename src/{ => emulator}/fileio.h (87%) rename src/{ => emulator}/print.c (99%) rename src/{ => emulator}/print.h (100%) mode change 100644 => 100755 test.sh diff --git a/src/Makefile b/src/Makefile index 7106e44..dd827a8 100755 --- a/src/Makefile +++ b/src/Makefile @@ -10,8 +10,7 @@ CFLAGS ?= -std=c17 -g\ all: assemble emulate assemble: assemble.o -emulate: emulate.o +emulate: emulate.o emulator/fileio.o emulator/execute.o emulator/decode.o emulator/print.o clean: - $(RM) *.o assemble emulate - + $(RM) *.o assemble emulate emulator/fileio.o emulator/execute.o emulator/decode.o emulator/print.o diff --git a/src/emulate.c b/src/emulate.c index 82245e9..83c58d7 100755 --- a/src/emulate.c +++ b/src/emulate.c @@ -1,12 +1,12 @@ #include #include -#include "a64instruction.h" -#include "emulator.h" -#include "fileio.h" +#include "emulator/a64instruction/a64instruction.h" +#include "emulator/emulator.h" +#include "emulator/fileio.h" #include "global.h" -#include "print.h" -#include "decode.h" -#include "execute.h" +#include "emulator/print.h" +#include "emulator/decode.h" +#include "emulator/execute.h" extern a64inst_instruction *decode(word w); diff --git a/src/a64instruction.h b/src/emulator/a64instruction/a64instruction.h similarity index 100% rename from src/a64instruction.h rename to src/emulator/a64instruction/a64instruction.h diff --git a/src/a64instruction_Branch.h b/src/emulator/a64instruction/a64instruction_Branch.h similarity index 97% rename from src/a64instruction_Branch.h rename to src/emulator/a64instruction/a64instruction_Branch.h index b732d6d..7cfc7e8 100644 --- a/src/a64instruction_Branch.h +++ b/src/emulator/a64instruction/a64instruction_Branch.h @@ -1,6 +1,6 @@ #include #include "a64instruction_global.h" -#include "global.h" +#include "../../global.h" typedef enum { a64inst_UNCONDITIONAL = 0, diff --git a/src/a64instruction_DP.h b/src/emulator/a64instruction/a64instruction_DP.h similarity index 100% rename from src/a64instruction_DP.h rename to src/emulator/a64instruction/a64instruction_DP.h diff --git a/src/a64instruction_DPImmediate.h b/src/emulator/a64instruction/a64instruction_DPImmediate.h similarity index 100% rename from src/a64instruction_DPImmediate.h rename to src/emulator/a64instruction/a64instruction_DPImmediate.h diff --git a/src/a64instruction_DPRegister.h b/src/emulator/a64instruction/a64instruction_DPRegister.h similarity index 100% rename from src/a64instruction_DPRegister.h rename to src/emulator/a64instruction/a64instruction_DPRegister.h diff --git a/src/a64instruction_Directive.h b/src/emulator/a64instruction/a64instruction_Directive.h similarity index 69% rename from src/a64instruction_Directive.h rename to src/emulator/a64instruction/a64instruction_Directive.h index 5c70dd4..88a6536 100644 --- a/src/a64instruction_Directive.h +++ b/src/emulator/a64instruction/a64instruction_Directive.h @@ -1,4 +1,4 @@ -#include "global.h" +#include "../../global.h" typedef struct { dword value; diff --git a/src/a64instruction_Label.h b/src/emulator/a64instruction/a64instruction_Label.h similarity index 100% rename from src/a64instruction_Label.h rename to src/emulator/a64instruction/a64instruction_Label.h diff --git a/src/a64instruction_SingleTransfer.h b/src/emulator/a64instruction/a64instruction_SingleTransfer.h similarity index 97% rename from src/a64instruction_SingleTransfer.h rename to src/emulator/a64instruction/a64instruction_SingleTransfer.h index f661116..1b6e2b7 100644 --- a/src/a64instruction_SingleTransfer.h +++ b/src/emulator/a64instruction/a64instruction_SingleTransfer.h @@ -1,6 +1,6 @@ #include #include "a64instruction_global.h" -#include "global.h" +#include "../../global.h" typedef enum { a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER = 1, diff --git a/src/a64instruction_global.h b/src/emulator/a64instruction/a64instruction_global.h similarity index 100% rename from src/a64instruction_global.h rename to src/emulator/a64instruction/a64instruction_global.h diff --git a/src/decode.c b/src/emulator/decode.c similarity index 100% rename from src/decode.c rename to src/emulator/decode.c diff --git a/src/decode.h b/src/emulator/decode.h similarity index 97% rename from src/decode.h rename to src/emulator/decode.h index 132130e..5af7046 100644 --- a/src/decode.h +++ b/src/emulator/decode.h @@ -1,5 +1,5 @@ -#include "global.h" -#include "a64instruction.h" +#include "../global.h" +#include "a64instruction/a64instruction.h" #define HALT_WORD 0x8a000000 diff --git a/src/emulator.h b/src/emulator/emulator.h similarity index 96% rename from src/emulator.h rename to src/emulator/emulator.h index facbfd7..3a1e67d 100644 --- a/src/emulator.h +++ b/src/emulator/emulator.h @@ -1,6 +1,6 @@ #ifndef __EMULATOR__ #define __EMULATOR__ -#include "global.h" +#include "../global.h" #include /************************************ diff --git a/src/execute.c b/src/emulator/execute.c similarity index 100% rename from src/execute.c rename to src/emulator/execute.c diff --git a/src/execute.h b/src/emulator/execute.h similarity index 74% rename from src/execute.h rename to src/emulator/execute.h index fcf39ec..8b691e6 100644 --- a/src/execute.h +++ b/src/emulator/execute.h @@ -1,6 +1,6 @@ #ifndef __EXECUTE__ #define __EXECUTE__ -#include "a64instruction.h" +#include "a64instruction/a64instruction.h" #include "emulator.h" void execute(Machine *state, a64inst_instruction *inst); diff --git a/src/fileio.c b/src/emulator/fileio.c similarity index 98% rename from src/fileio.c rename to src/emulator/fileio.c index 1dcdd77..41df962 100644 --- a/src/fileio.c +++ b/src/emulator/fileio.c @@ -2,7 +2,7 @@ #include #include #include "fileio.h" -#include "global.h" +#include "../global.h" /* Loads a binary file located at filePath to memory, taking up a block of exactly memorySize bytes, and returns the starting address of the data. If memorySize is insufficient to store the entire file, diff --git a/src/fileio.h b/src/emulator/fileio.h similarity index 87% rename from src/fileio.h rename to src/emulator/fileio.h index a2d4262..47aa858 100644 --- a/src/fileio.h +++ b/src/emulator/fileio.h @@ -1,7 +1,7 @@ #ifndef __FILEIO__ #define __FILEIO__ #include -#include "global.h" +#include "../global.h" #define EXIT_FAILURE 1 diff --git a/src/print.c b/src/emulator/print.c similarity index 99% rename from src/print.c rename to src/emulator/print.c index 88ed6f9..0ec5210 100644 --- a/src/print.c +++ b/src/emulator/print.c @@ -1,7 +1,6 @@ #include #include #include -#include #include "print.h" #include "emulator.h" diff --git a/src/print.h b/src/emulator/print.h similarity index 100% rename from src/print.h rename to src/emulator/print.h diff --git a/test.sh b/test.sh old mode 100644 new mode 100755 From c4e3493fdc52965656d7aa8f4e29e987089ab452 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Tue, 11 Jun 2024 22:40:36 +0100 Subject: [PATCH 7/8] Split utils into machine_util and binary_util modules --- src/emulate.c | 4 +- src/emulator/binary_util.c | 57 ++++++++++++++++++++++++++ src/emulator/binary_util.h | 20 ++++++++++ src/emulator/decode.c | 14 +------ src/emulator/execute.c | 79 ++----------------------------------- src/emulator/machine_util.c | 50 +++++++++++++++++++++++ src/emulator/machine_util.h | 16 ++++++++ src/emulator/print.c | 30 ++------------ src/emulator/print.h | 3 -- 9 files changed, 153 insertions(+), 120 deletions(-) create mode 100644 src/emulator/binary_util.c create mode 100644 src/emulator/binary_util.h create mode 100644 src/emulator/machine_util.c create mode 100644 src/emulator/machine_util.h diff --git a/src/emulate.c b/src/emulate.c index 83c58d7..94f9254 100755 --- a/src/emulate.c +++ b/src/emulate.c @@ -1,12 +1,14 @@ #include #include #include "emulator/a64instruction/a64instruction.h" +#include "emulator/a64instruction/a64instruction_global.h" #include "emulator/emulator.h" #include "emulator/fileio.h" #include "global.h" #include "emulator/print.h" #include "emulator/decode.h" #include "emulator/execute.h" +#include "emulator/machine_util.h" extern a64inst_instruction *decode(word w); @@ -40,7 +42,7 @@ int main(int argc, char **argv) { do { // Step 1: Fetch instruction at PC's address - wrd = readWord(state.memory, state.pc); + wrd = readMemory(state.memory, state.pc, a64inst_W); // Step 2: Decode instruction to internal representation inst = decode(wrd); diff --git a/src/emulator/binary_util.c b/src/emulator/binary_util.c new file mode 100644 index 0000000..78bf11d --- /dev/null +++ b/src/emulator/binary_util.c @@ -0,0 +1,57 @@ +/** Binary Util */ +#include +#include "binary_util.h" + +word getBits(word wrd, uint8_t lsb, uint8_t msb) { + + // Ensure LSB and MSB are within range of word size, and in the correct order + assert(lsb < msb && msb <= WORD_BITS); + + wrd &= ((dword) 1 << msb) - 1; + return wrd >> lsb; +} + +dword max(dword a, dword b) { + return a > b ? a : b; +} + +dword truncateValue(dword value, a64inst_regType regType) { + if (regType == a64inst_X) { + return value; + } else { + return (word)value; + //return value & (dword)(((dword)1 << WORD_BITS) - 1); + } +} + +// Sign extend a given value to a 64-bit signed integer given the number of bits +int64_t signExtend(dword value, unsigned int n) { + if (n == 0 || n >= 64) { + // If n_bits is 0 or greater than or equal to 64, return the value as is + return (int64_t)value; + } + + uint64_t sign_bit_mask = (uint64_t)1 << (n - 1); + + // Mask to isolate the n-bit value + uint64_t n_bit_mask = (sign_bit_mask << 1) - 1; + + // Check if the sign bit is set + if (value & sign_bit_mask) { + // Sign bit is set, extend the sign + return (int64_t)(value | ~n_bit_mask); + } else { + // Sign bit is not set, return the value as is + return (int64_t)(value & n_bit_mask); + } +} + +// Returns the position of the MSB of the given register type +dword getMSBPos(a64inst_regType regType) { + return (regType ? DWORD_BITS : WORD_BITS) - 1; +} + +// Returns the MSB of the given value assuming it's of the size stored in the given register type +uint8_t getMSB(dword value, a64inst_regType regType) { + return (value >> getMSBPos(regType)) & 1u; +} diff --git a/src/emulator/binary_util.h b/src/emulator/binary_util.h new file mode 100644 index 0000000..97763a0 --- /dev/null +++ b/src/emulator/binary_util.h @@ -0,0 +1,20 @@ +#ifndef __BINARY_UTIL__ +#define __BINARY_UTIL__ + +#include "emulator.h" +#include "a64instruction/a64instruction_global.h" + + +word getBits(word wrd, uint8_t lsb, uint8_t msb); + +dword max(dword a, dword b); + +dword truncateValue(dword value, a64inst_regType regType); + +int64_t signExtend(dword value, unsigned int n); + +dword getMSBPos(a64inst_regType regType); + +uint8_t getMSB(dword value, a64inst_regType regType); + +#endif diff --git a/src/emulator/decode.c b/src/emulator/decode.c index ce69c35..17970af 100644 --- a/src/emulator/decode.c +++ b/src/emulator/decode.c @@ -1,19 +1,7 @@ -#include #include #include #include "decode.h" -#include "emulator.h" - -// Retrieve the bits between positions 'lsb' (inclusive) and 'msb' (exclusive) from a given word -// as a new zero-extended word. -static word getBits(word wrd, uint8_t lsb, uint8_t msb) { - - // Ensure LSB and MSB are within range of word size, and in the correct order - assert(lsb < msb && msb <= WORD_BITS); - - wrd &= ((dword) 1 << msb) - 1; - return wrd >> lsb; -} +#include "binary_util.h" // Given a binary word, return its internal representation as an a64instruction struct encoding the same // information. diff --git a/src/emulator/execute.c b/src/emulator/execute.c index d5e60a6..e2de20c 100644 --- a/src/emulator/execute.c +++ b/src/emulator/execute.c @@ -2,6 +2,8 @@ #include #include "execute.h" #include "print.h" +#include "binary_util.h" +#include "machine_util.h" // Defines the maximum value that can be held in a register #define MAX_REG_VAL ((1 << DWORD_BITS) - 1) @@ -19,76 +21,6 @@ void execute_SDT(Machine *state, a64inst_instruction *inst); void execute_Branch(Machine *state, a64inst_instruction *inst); void executeMultiply(Machine *state, a64inst_instruction *inst); -// Return maximum of two dwords -static dword max(dword a, dword b) { - return a > b ? a : b; -} - -// Truncate a given value to the size of a word or dword depending on the register type -static dword truncateValue(dword value, a64inst_regType regType) { - if (regType == a64inst_X) { - return value; - } else { - return (word)value; - //return value & (dword)(((dword)1 << WORD_BITS) - 1); - } -} - -// Sign extend a given value to a 64-bit signed integer given the number of bits -static int64_t signExtend(dword value, unsigned int n) { - if (n == 0 || n >= 64) { - // If n_bits is 0 or greater than or equal to 64, return the value as is - return (int64_t)value; - } - - uint64_t sign_bit_mask = (uint64_t)1 << (n - 1); - - // Mask to isolate the n-bit value - uint64_t n_bit_mask = (sign_bit_mask << 1) - 1; - - // Check if the sign bit is set - if (value & sign_bit_mask) { - // Sign bit is set, extend the sign - return (int64_t)(value | ~n_bit_mask); - } else { - // Sign bit is not set, return the value as is - return (int64_t)(value & n_bit_mask); - } -} - -// Read from processor register, ensuring that a valid register specifier is given -// and accounting for the case where the zero register is accessed. Truncate -// the 32 most significant bits stored in the R register when reading W register. -static dword readRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType) { - assert(reg <= REGISTER_COUNT); - if (reg == ZERO_REGISTER) { - return 0; - } else { - return truncateValue(state->registers[reg], regType); - } -} - -// TODO: - -// Write to a processor register, ensuring that a valid register specifier is given -// and truncating the value being written when it can't fit in the specified register -static void writeRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType, dword value) { - assert(reg <= REGISTER_COUNT); - if (reg != ZERO_REGISTER) { - state->registers[reg] = truncateValue(value, regType); - } -} - -// Returns the position of the MSB of the given register type -inline static dword getMSBPos(a64inst_regType regType) { - return (regType ? DWORD_BITS : WORD_BITS) - 1; -} - -// Returns the MSB of the given value assuming it's of the size stored in the given register type -inline static uint8_t getMSB(dword value, a64inst_regType regType) { - return (value >> getMSBPos(regType)) & 1u; -} - // Updates N and Z condition codes given the machine and a result value static void updateCondNZ(Machine *state, dword result, a64inst_regType regType) { state->conditionCodes.Negative = getMSB(result, regType); @@ -383,12 +315,7 @@ void execute_SDT(Machine *state, a64inst_instruction *inst) { } if (isLoad) { - if (inst->data.SingleTransferData.regType == a64inst_W) { - // 32 bit access - state->registers[inst->data.SingleTransferData.target] = readWord(state->memory, address); - } else { - state->registers[inst->data.SingleTransferData.target] = readDoubleWord(state->memory, address); - } + state->registers[inst->data.SingleTransferData.target] = readMemory(state->memory, address, inst->data.SingleTransferData.regType); // Update base register if post indexed bool isSDT = inst->data.SingleTransferData.SingleTransferOpType == a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER; diff --git a/src/emulator/machine_util.c b/src/emulator/machine_util.c new file mode 100644 index 0000000..9288c7b --- /dev/null +++ b/src/emulator/machine_util.c @@ -0,0 +1,50 @@ +/** Machine Util */ +#include "assert.h" +#include "machine_util.h" +#include "a64instruction/a64instruction_global.h" +#include "../global.h" +#include "emulator.h" +#include "binary_util.h" + +// Returns the dword starting at address. The value is truncated if regType is a 64-bit register. +dword readMemory(byte *memory, uint32_t address, a64inst_regType regType) { + dword result = 0; + int bytesPerWord = (regType == a64inst_W ? WORD_BITS : DWORD_BITS) / BYTE_BITS - 1; + for (int i = 0; i <= bytesPerWord; i++) { + if (regType == a64inst_W) { + result |= (word) memory[address + i] << (BYTE_BITS * i); + } else { + result |= (dword) memory[address + i] << (BYTE_BITS * i); + } + } + return result; +} + +// Store into memory starting at address the given dword. +void storeMemory(byte *memory, uint32_t address, dword data) { + int bytesPerDword = DWORD_BITS / BYTE_BITS - 1; + for (int i = 0; i <= bytesPerDword; i++) { + memory[address + i] = (byte)((data >> (BYTE_BITS * i)) & 0xFF); + } +} + +// Read from processor register, ensuring that a valid register specifier is given +// and accounting for the case where the zero register is accessed. Truncate +// the 32 most significant bits stored in the R register when reading W register. +dword readRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType) { + assert(reg <= REGISTER_COUNT); + if (reg == ZERO_REGISTER) { + return 0; + } else { + return truncateValue(state->registers[reg], regType); + } +} + +// Write to a processor register, ensuring that a valid register specifier is given +// and truncating the value being written when it can't fit in the specified register +void writeRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType, dword value) { + assert(reg <= REGISTER_COUNT); + if (reg != ZERO_REGISTER) { + state->registers[reg] = truncateValue(value, regType); + } +} diff --git a/src/emulator/machine_util.h b/src/emulator/machine_util.h new file mode 100644 index 0000000..90688e8 --- /dev/null +++ b/src/emulator/machine_util.h @@ -0,0 +1,16 @@ +#ifndef __MACHINE_UTIL__ +#define __MACHINE_UTIL__ +#include "../global.h" +#include "a64instruction/a64instruction_global.h" +#include "emulator.h" + + +dword readMemory(byte *memory, uint32_t address, a64inst_regType regType); + +void storeMemory(byte *memory, uint32_t address, dword data); + +dword readRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType); + +void writeRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType, dword value); + +#endif diff --git a/src/emulator/print.c b/src/emulator/print.c index 0ec5210..217535b 100644 --- a/src/emulator/print.c +++ b/src/emulator/print.c @@ -2,7 +2,9 @@ #include #include #include "print.h" +#include "a64instruction/a64instruction_global.h" #include "emulator.h" +#include "machine_util.h" #define UNSET_CONDITION_CODE_CHAR '-' @@ -25,39 +27,13 @@ void printRegisters(Machine *state, FILE *stream) { state->conditionCodes.Overflow ? 'V' : UNSET_CONDITION_CODE_CHAR); } -// Returns the word starting at the provided address -word readWord(byte *memory, uint32_t address) { - word result = 0; - int bytesPerWord = WORD_BITS / BYTE_BITS - 1; - for (int i = 0; i <= bytesPerWord; i++) - result |= (word) memory[address + i] << (BYTE_BITS * i); - return result; -} - -// Returns the double word starting at the provided address -dword readDoubleWord(byte *memory, uint32_t address) { - dword result = 0; - int bytesPerDword = DWORD_BITS / BYTE_BITS - 1; - for (int i = 0; i <= bytesPerDword; i++) - result |= (dword) memory[address + i] << (BYTE_BITS * i); - return result; -} - -// Store into memory starting at address the given dword. -void storeMemory(byte *memory, uint32_t address, dword data) { - int bytesPerDword = DWORD_BITS / BYTE_BITS - 1; - for (int i = 0; i <= bytesPerDword; i++) { - memory[address + i] = (byte)((data >> (BYTE_BITS * i)) & 0xFF); - } -} - // Prints all non-zero memory locations into the provided stream void printMemory(Machine *state, FILE *stream) { fprintf(stream, "\nNon-zero memory:\n"); // print memory 4 byte aligned for (int addr = 0; addr < MEMORY_SIZE; addr+= 4) { - word data = readWord(state->memory, addr); + word data = readMemory(state->memory, addr, a64inst_W); if (data != 0) { fprintf(stream, "0x%08x: %08x\n", addr, data); } diff --git a/src/emulator/print.h b/src/emulator/print.h index 5a64a4e..35001d9 100644 --- a/src/emulator/print.h +++ b/src/emulator/print.h @@ -3,9 +3,6 @@ #include #include "emulator.h" -word readWord(byte *memory, uint32_t address); -dword readDoubleWord(byte *memory, uint32_t address); -void storeMemory(byte *memory, uint32_t address, dword data); void printState(Machine *state, FILE *stream); void printRegisters(Machine *state, FILE *stream); void printMemory(Machine *state, FILE *stream); From 954be5f8f45cc6ca50bb19d67d7574e267c3fe30 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 12 Jun 2024 15:55:15 +0100 Subject: [PATCH 8/8] Update structure to a binary and machine util and a64inst modules --- src/emulate.c | 4 ++-- src/emulator/decode.c | 2 +- src/emulator/decode.h | 2 +- src/emulator/emulator.h | 8 -------- src/emulator/execute.c | 2 +- src/emulator/execute.h | 2 +- src/emulator/machine_util.c | 4 ++-- src/emulator/machine_util.h | 2 +- src/emulator/print.c | 2 +- src/global.h | 9 +++++++++ src/{emulator => shared}/a64instruction/a64instruction.h | 0 .../a64instruction/a64instruction_Branch.h | 1 - .../a64instruction/a64instruction_DP.h | 0 .../a64instruction/a64instruction_DPImmediate.h | 0 .../a64instruction/a64instruction_DPRegister.h | 0 .../a64instruction/a64instruction_Directive.h | 2 +- .../a64instruction/a64instruction_Label.h | 0 .../a64instruction/a64instruction_SingleTransfer.h | 1 - .../a64instruction/a64instruction_global.h | 1 + src/{emulator => shared}/binary_util.c | 0 src/{emulator => shared}/binary_util.h | 3 +-- 21 files changed, 22 insertions(+), 23 deletions(-) rename src/{emulator => shared}/a64instruction/a64instruction.h (100%) rename src/{emulator => shared}/a64instruction/a64instruction_Branch.h (97%) rename src/{emulator => shared}/a64instruction/a64instruction_DP.h (100%) rename src/{emulator => shared}/a64instruction/a64instruction_DPImmediate.h (100%) rename src/{emulator => shared}/a64instruction/a64instruction_DPRegister.h (100%) rename src/{emulator => shared}/a64instruction/a64instruction_Directive.h (61%) rename src/{emulator => shared}/a64instruction/a64instruction_Label.h (100%) rename src/{emulator => shared}/a64instruction/a64instruction_SingleTransfer.h (97%) rename src/{emulator => shared}/a64instruction/a64instruction_global.h (92%) rename src/{emulator => shared}/binary_util.c (100%) rename src/{emulator => shared}/binary_util.h (94%) diff --git a/src/emulate.c b/src/emulate.c index 94f9254..ba6bbea 100755 --- a/src/emulate.c +++ b/src/emulate.c @@ -1,7 +1,7 @@ #include #include -#include "emulator/a64instruction/a64instruction.h" -#include "emulator/a64instruction/a64instruction_global.h" +#include "shared/a64instruction/a64instruction.h" +#include "shared/a64instruction/a64instruction_global.h" #include "emulator/emulator.h" #include "emulator/fileio.h" #include "global.h" diff --git a/src/emulator/decode.c b/src/emulator/decode.c index 17970af..ad09429 100644 --- a/src/emulator/decode.c +++ b/src/emulator/decode.c @@ -1,7 +1,7 @@ #include #include #include "decode.h" -#include "binary_util.h" +#include "../shared/binary_util.h" // Given a binary word, return its internal representation as an a64instruction struct encoding the same // information. diff --git a/src/emulator/decode.h b/src/emulator/decode.h index 5af7046..b5982be 100644 --- a/src/emulator/decode.h +++ b/src/emulator/decode.h @@ -1,5 +1,5 @@ #include "../global.h" -#include "a64instruction/a64instruction.h" +#include "../shared/a64instruction/a64instruction.h" #define HALT_WORD 0x8a000000 diff --git a/src/emulator/emulator.h b/src/emulator/emulator.h index 3a1e67d..69d1408 100644 --- a/src/emulator/emulator.h +++ b/src/emulator/emulator.h @@ -3,14 +3,6 @@ #include "../global.h" #include -/************************************ - * DEFINITIONS - ************************************/ - -#define BYTE_BITS 8 -#define WORD_BITS (BYTE_BITS * sizeof(word)) -#define DWORD_BITS (BYTE_BITS * sizeof(dword)) - /************************************ * STRUCTS ************************************/ diff --git a/src/emulator/execute.c b/src/emulator/execute.c index e2de20c..fddd50f 100644 --- a/src/emulator/execute.c +++ b/src/emulator/execute.c @@ -2,7 +2,7 @@ #include #include "execute.h" #include "print.h" -#include "binary_util.h" +#include "../shared/binary_util.h" #include "machine_util.h" // Defines the maximum value that can be held in a register diff --git a/src/emulator/execute.h b/src/emulator/execute.h index 8b691e6..be82de6 100644 --- a/src/emulator/execute.h +++ b/src/emulator/execute.h @@ -1,6 +1,6 @@ #ifndef __EXECUTE__ #define __EXECUTE__ -#include "a64instruction/a64instruction.h" +#include "../shared/a64instruction/a64instruction.h" #include "emulator.h" void execute(Machine *state, a64inst_instruction *inst); diff --git a/src/emulator/machine_util.c b/src/emulator/machine_util.c index 9288c7b..9db8525 100644 --- a/src/emulator/machine_util.c +++ b/src/emulator/machine_util.c @@ -1,10 +1,10 @@ /** Machine Util */ #include "assert.h" #include "machine_util.h" -#include "a64instruction/a64instruction_global.h" +#include "../shared/a64instruction/a64instruction_global.h" #include "../global.h" #include "emulator.h" -#include "binary_util.h" +#include "../shared/binary_util.h" // Returns the dword starting at address. The value is truncated if regType is a 64-bit register. dword readMemory(byte *memory, uint32_t address, a64inst_regType regType) { diff --git a/src/emulator/machine_util.h b/src/emulator/machine_util.h index 90688e8..89733e6 100644 --- a/src/emulator/machine_util.h +++ b/src/emulator/machine_util.h @@ -1,7 +1,7 @@ #ifndef __MACHINE_UTIL__ #define __MACHINE_UTIL__ #include "../global.h" -#include "a64instruction/a64instruction_global.h" +#include "../shared/a64instruction/a64instruction_global.h" #include "emulator.h" diff --git a/src/emulator/print.c b/src/emulator/print.c index 217535b..457aa7e 100644 --- a/src/emulator/print.c +++ b/src/emulator/print.c @@ -2,7 +2,7 @@ #include #include #include "print.h" -#include "a64instruction/a64instruction_global.h" +#include "../shared/a64instruction/a64instruction_global.h" #include "emulator.h" #include "machine_util.h" diff --git a/src/global.h b/src/global.h index 1cf226e..5d792e4 100644 --- a/src/global.h +++ b/src/global.h @@ -9,6 +9,11 @@ #define __GLOBAL__ #include + +/************************************ + * DEFINITIONS + ************************************/ + // Number of General Purpose Registers. #define REGISTER_COUNT 31 // Register identifier interpreted as the 'zero register' @@ -27,4 +32,8 @@ typedef uint32_t word; // Double word is a 64-bit unsigned integer. typedef uint64_t dword; +#define BYTE_BITS 8 +#define WORD_BITS (BYTE_BITS * sizeof(word)) +#define DWORD_BITS (BYTE_BITS * sizeof(dword)) + #endif diff --git a/src/emulator/a64instruction/a64instruction.h b/src/shared/a64instruction/a64instruction.h similarity index 100% rename from src/emulator/a64instruction/a64instruction.h rename to src/shared/a64instruction/a64instruction.h diff --git a/src/emulator/a64instruction/a64instruction_Branch.h b/src/shared/a64instruction/a64instruction_Branch.h similarity index 97% rename from src/emulator/a64instruction/a64instruction_Branch.h rename to src/shared/a64instruction/a64instruction_Branch.h index 7cfc7e8..d280973 100644 --- a/src/emulator/a64instruction/a64instruction_Branch.h +++ b/src/shared/a64instruction/a64instruction_Branch.h @@ -1,6 +1,5 @@ #include #include "a64instruction_global.h" -#include "../../global.h" typedef enum { a64inst_UNCONDITIONAL = 0, diff --git a/src/emulator/a64instruction/a64instruction_DP.h b/src/shared/a64instruction/a64instruction_DP.h similarity index 100% rename from src/emulator/a64instruction/a64instruction_DP.h rename to src/shared/a64instruction/a64instruction_DP.h diff --git a/src/emulator/a64instruction/a64instruction_DPImmediate.h b/src/shared/a64instruction/a64instruction_DPImmediate.h similarity index 100% rename from src/emulator/a64instruction/a64instruction_DPImmediate.h rename to src/shared/a64instruction/a64instruction_DPImmediate.h diff --git a/src/emulator/a64instruction/a64instruction_DPRegister.h b/src/shared/a64instruction/a64instruction_DPRegister.h similarity index 100% rename from src/emulator/a64instruction/a64instruction_DPRegister.h rename to src/shared/a64instruction/a64instruction_DPRegister.h diff --git a/src/emulator/a64instruction/a64instruction_Directive.h b/src/shared/a64instruction/a64instruction_Directive.h similarity index 61% rename from src/emulator/a64instruction/a64instruction_Directive.h rename to src/shared/a64instruction/a64instruction_Directive.h index 88a6536..fa2faaa 100644 --- a/src/emulator/a64instruction/a64instruction_Directive.h +++ b/src/shared/a64instruction/a64instruction_Directive.h @@ -1,4 +1,4 @@ -#include "../../global.h" +#include "./a64instruction_global.h" typedef struct { dword value; diff --git a/src/emulator/a64instruction/a64instruction_Label.h b/src/shared/a64instruction/a64instruction_Label.h similarity index 100% rename from src/emulator/a64instruction/a64instruction_Label.h rename to src/shared/a64instruction/a64instruction_Label.h diff --git a/src/emulator/a64instruction/a64instruction_SingleTransfer.h b/src/shared/a64instruction/a64instruction_SingleTransfer.h similarity index 97% rename from src/emulator/a64instruction/a64instruction_SingleTransfer.h rename to src/shared/a64instruction/a64instruction_SingleTransfer.h index 1b6e2b7..3e3da2b 100644 --- a/src/emulator/a64instruction/a64instruction_SingleTransfer.h +++ b/src/shared/a64instruction/a64instruction_SingleTransfer.h @@ -1,6 +1,5 @@ #include #include "a64instruction_global.h" -#include "../../global.h" typedef enum { a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER = 1, diff --git a/src/emulator/a64instruction/a64instruction_global.h b/src/shared/a64instruction/a64instruction_global.h similarity index 92% rename from src/emulator/a64instruction/a64instruction_global.h rename to src/shared/a64instruction/a64instruction_global.h index ff748a6..629843d 100644 --- a/src/emulator/a64instruction/a64instruction_global.h +++ b/src/shared/a64instruction/a64instruction_global.h @@ -1,6 +1,7 @@ #ifndef __A64INSTRUCTION_GLOBAL__ #define __A64INSTRUCTION_GLOBAL__ #include +#include "../../global.h" // Specifies the register being referred to typedef uint8_t a64inst_regSpecifier; diff --git a/src/emulator/binary_util.c b/src/shared/binary_util.c similarity index 100% rename from src/emulator/binary_util.c rename to src/shared/binary_util.c diff --git a/src/emulator/binary_util.h b/src/shared/binary_util.h similarity index 94% rename from src/emulator/binary_util.h rename to src/shared/binary_util.h index 97763a0..8438ef9 100644 --- a/src/emulator/binary_util.h +++ b/src/shared/binary_util.h @@ -1,10 +1,9 @@ #ifndef __BINARY_UTIL__ #define __BINARY_UTIL__ -#include "emulator.h" +#include "../global.h" #include "a64instruction/a64instruction_global.h" - word getBits(word wrd, uint8_t lsb, uint8_t msb); dword max(dword a, dword b);