From 269a150926f36b17c60bdb5111288f2c412cee72 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 12 Jun 2024 00:49:25 +0100 Subject: [PATCH] Fix types, signatures, and arguments. --- src/assemble.c | 11 +- src/execute.c | 448 ------------------------------------------------- src/parser.c | 15 +- src/parser.h | 2 +- 4 files changed, 15 insertions(+), 461 deletions(-) delete mode 100644 src/execute.c diff --git a/src/assemble.c b/src/assemble.c index 967b02e..ef1b06d 100755 --- a/src/assemble.c +++ b/src/assemble.c @@ -14,19 +14,20 @@ int main(int argc, char **argv) { } // Load the source file into memory - char **source = readAssemblyFile(argv[1]); + int lineCount = countLines(argv[1]); + char **source = readAssemblyFile(argv[1], lineCount); // Parse the source file - a64inst_instruction *instructions = parse(source); + a64inst_instruction *instructions = parse(source, lineCount); // First Pass: Create the symbol table - st *table = firstPass(instructions, 1000); // 1000 is just a temp fix. + st *table = firstPass(instructions, lineCount); // Second Pass: Assemble the instructions - word *binary = secondPass(instructions, 1000, table); // 1000 is just a temp fix. + word *binary = secondPass(instructions, lineCount, table); // 1000 is just a temp fix. // Write the binary to the output file - writeBinaryFile(binary, argv[2], 1000); // 1000 is just a temp fix. + writeBinaryFile(binary, argv[2], lineCount); // 1000 is just a temp fix. /* TODO: FREE MEMORY!! */ diff --git a/src/execute.c b/src/execute.c deleted file mode 100644 index fc436af..0000000 --- a/src/execute.c +++ /dev/null @@ -1,448 +0,0 @@ -#include -#include -#include "execute.h" -#include "print.h" - -// Defines the maximum value that can be held in a register -#define MAX_REG_VAL ((1 << DWORD_BITS) - 1) - -// The number of bits to shift the immediate value in an arithmetic immediate data processing -// instruction if the shift flag is enabled. -#define DPI_ARITHM_SHIFT 12 - -// The number of bits to shift the immediate value in a wide move immediate data processing -// instruction if the shift flag is enabled. -#define DPI_WIDEMOV_SHIFT 16 - -// Prototypes -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); -} - -// 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); - state->conditionCodes.Zero = result == 0; -} - -// Execute a data processing immediate instruction -static void executeDPImmediate(Machine *state, a64inst_instruction *inst) { - assert(inst->type == a64inst_DPIMMEDIATE); - - a64inst_regType regType = inst->data.DPImmediateData.regType; - a64inst_regSpecifier dest = inst->data.DPImmediateData.dest; - switch(inst->data.DPImmediateData.DPIOpType) { - - // Execute an arithmetic immediate data processing instruction - case a64inst_DPI_ARITHM:; - - // If shift flag is enabled, logical left shift by the number of bits specified by the architecture - dword arithmImm = inst->data.DPImmediateData.processOpData.arithmData.immediate; - dword srcVal = state->registers[inst->data.DPImmediateData.processOpData.arithmData.src]; - if (inst->data.DPImmediateData.processOpData.arithmData.shiftImmediate) { - arithmImm = truncateValue(arithmImm << DPI_ARITHM_SHIFT, regType); - } - - switch(inst->data.DPImmediateData.processOp) { - - dword result; - case(a64inst_ADDS): - result = srcVal + arithmImm; - writeRegister(state, dest, regType, result); - - updateCondNZ(state, result, regType); - state->conditionCodes.Overflow = max(srcVal, arithmImm) > result; - state->conditionCodes.Carry = state->conditionCodes.Overflow; - break; - - case(a64inst_ADD): - writeRegister(state, dest, regType, srcVal + arithmImm); - break; - - case(a64inst_SUBS): - result = srcVal - arithmImm; - writeRegister(state, dest, regType, result); - - updateCondNZ(state, result, regType); - state->conditionCodes.Overflow = srcVal < result; - state->conditionCodes.Carry = state->conditionCodes.Overflow; - break; - - case(a64inst_SUB): - writeRegister(state, dest, regType, srcVal - arithmImm); - break; - - // Unknown opcode detected! - default: - fprintf(stderr, "Unknown opcode detected in a DPI arithmetic instruction!\n"); - break; - } - break; - - // Execute a wide move immediate data processing instruction - case a64inst_DPI_WIDEMOV:; - uint8_t shiftScalar = inst->data.DPImmediateData.processOpData.wideMovData.shiftScalar; - dword wideMovImm = inst->data.DPImmediateData.processOpData.wideMovData.immediate; - - // NOTE: Not checking that shiftScalar has valid value for 32bit registers. Possibly add explicit error. - //printf("%x\n", wideMovImm << (shiftScalar * DPI_WIDEMOV_SHIFT) & ); - wideMovImm = truncateValue(wideMovImm << (shiftScalar * DPI_WIDEMOV_SHIFT), regType); - switch(inst->data.DPImmediateData.processOp) { - - case(a64inst_MOVN): - writeRegister(state, dest, regType, ~wideMovImm); - break; - - case(a64inst_MOVZ): - writeRegister(state, dest, regType, wideMovImm); - break; - - case(a64inst_MOVK):; - dword result = readRegister(state, dest, regType); - result = (result & ~(((1lu << DPI_WIDEMOV_SHIFT) - 1) << shiftScalar * DPI_WIDEMOV_SHIFT)) | wideMovImm; - writeRegister(state, dest, regType, result); - break; - - default: - fprintf(stderr, "Unknown opcode detected in a DPI wide move instruction!\n"); - break; - } - break; - - // Unknown instruction detected! - default: - fprintf(stderr, "Attempting to execute instruction with unknown DPI operand type!\n"); - break; - } -} - -// Execute a data processing register instruction -static void executeDPRegister(Machine *state, a64inst_instruction *inst) { - assert(inst->type == a64inst_DPREGISTER); - - a64inst_regType regType = inst->data.DPRegisterData.regType; - a64inst_regSpecifier dest = inst->data.DPRegisterData.dest; - dword src1Val = readRegister(state, inst->data.DPRegisterData.src1, regType); - dword src2Val = readRegister(state, inst->data.DPRegisterData.src2, regType); - - switch(inst->data.DPRegisterData.DPROpType) { - - // Execute an arithmetic or logic register data processing instruction - case a64inst_DPR_ARITHMLOGIC:; - - // Apply shift to value held in second register - a64inst_DPRegister_ArithmLogicData *arithmLogicData = &inst->data.DPRegisterData.processOpData.arithmLogicData; - uint8_t shiftAmount = arithmLogicData->shiftAmount; - switch(arithmLogicData->shiftType) { - - case a64inst_LSL: - src2Val = truncateValue(src2Val << shiftAmount, regType); - break; - - case a64inst_LSR: - src2Val = truncateValue(src2Val >> shiftAmount, regType); - break; - - case a64inst_ASR: - if (regType == a64inst_X) { - src2Val = truncateValue((int64_t)src2Val >> shiftAmount, regType); - } else { - src2Val = truncateValue((int32_t)src2Val >> shiftAmount, regType); - } - break; - - case a64inst_ROR: - if (arithmLogicData->type != a64inst_DPR_LOGIC) { - fprintf(stderr, "Attempting to perform ROR shift on non-logic register data processing instruction!\n"); - } - src2Val = truncateValue(src2Val >> shiftAmount | src2Val << (getMSBPos(regType) - shiftAmount), regType); - break; - - default: - fprintf(stderr, "Attempting to execute arithmetic/logic register data processing instruction with invalid shift type!\n"); - break; - } - - // Negate second operand if negShiftedSrc2 flag is enabled - if (arithmLogicData->negShiftedSrc2) { - src2Val = truncateValue(~src2Val, regType); - } - - dword result; - switch(arithmLogicData->type) { - - case a64inst_DPR_ARITHM: - switch(inst->data.DPRegisterData.processOp) { - - case(a64inst_ADDS): - result = src1Val + src2Val; - writeRegister(state, dest, regType, result); - - updateCondNZ(state, result, regType); - state->conditionCodes.Overflow = max(src1Val, src2Val) > result; - state->conditionCodes.Carry = state->conditionCodes.Overflow; - break; - - case(a64inst_ADD): - writeRegister(state, dest, regType, src1Val + src2Val); - break; - - case(a64inst_SUBS): - result = src1Val - src2Val; - writeRegister(state, dest, regType, result); - - updateCondNZ(state, result, regType); - state->conditionCodes.Overflow = getMSB(src1Val, regType) != getMSB(src2Val, regType) && getMSB(src1Val, regType) != getMSB(result, regType); - state->conditionCodes.Carry = src1Val >= src2Val; - break; - - case(a64inst_SUB): - writeRegister(state, dest, regType, src1Val - src2Val); - break; - - // Unknown opcode detected! - default: - fprintf(stderr, "Unknown opcode detected in a DPI arithmetic instruction!\n"); - break; - } - break; - - case a64inst_DPR_LOGIC: - switch(inst->data.DPRegisterData.processOp) { - - case a64inst_AND: - writeRegister(state, dest, regType, src1Val & src2Val); - break; - - case a64inst_OR: - writeRegister(state, dest, regType, src1Val | src2Val); - break; - - case a64inst_XOR: - writeRegister(state, dest, regType, src1Val ^ src2Val); - break; - - case a64inst_AND_FLAGGED:; - result = src1Val & src2Val; - writeRegister(state, dest, regType, result); - state->conditionCodes.Overflow = 0; - state->conditionCodes.Carry = 0; - updateCondNZ(state, result, regType); - break; - } - break; - - default: - fprintf(stderr, "Attempting to execute an instruction with an unknown DPR arithmetic or logic subtype!\n"); - break; - } - break; - - // Execute a multiply register data processing instruction - case a64inst_DPR_MULTIPLY: - break; - - // Unknown instruction detected! - default: - fprintf(stderr, "Attempting to execute instruction with unknown DPR operand type!\n"); - break; - } -} - -void execute(Machine *state, a64inst_instruction *inst) { - - switch (inst->type) { - - // Halt the program - case a64inst_HALT: - break; - - // Execute a data processing immediate instruction - case a64inst_DPIMMEDIATE: - executeDPImmediate(state, inst); - break; - - // Execute a branch instruction - case a64inst_BRANCH: - execute_Branch(state, inst); - break; - - // Execute a data processing register instruction - case a64inst_DPREGISTER: - if (inst->data.DPRegisterData.DPROpType == a64inst_DPR_MULTIPLY) - executeMultiply(state, inst); - else - executeDPRegister(state, inst); - break; - - case a64inst_SINGLETRANSFER: - execute_SDT(state, inst); - break; - - // Unknown instruction - default: - break; - } - -} - -void execute_SDT(Machine *state, a64inst_instruction *inst) { - word address; - bool isLoad; - if (inst->data.SingleTransferData.SingleTransferOpType == a64inst_SINGLE_TRANSFER_LOAD_LITERAL) { - // Load Literal - isLoad = true; - address = state->pc + inst->data.SingleTransferData.processOpData.loadLiteralData.offset * 4; - } else { - address = state->registers[inst->data.SingleTransferData.processOpData.singleDataTransferData.base]; - isLoad = inst->data.SingleTransferData.processOpData.singleDataTransferData.transferType == a64inst_LOAD; - switch (inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode) { - case a64inst_UNSIGNED_OFFSET: - address += inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.unsignedOffset * (inst->data.SingleTransferData.regType == a64inst_W ? 4 : 8); - break; - case a64inst_REGISTER_OFFSET: - address += state->registers[inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.offsetReg]; - break; - case a64inst_PRE_INDEXED: - address += inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset; - state->registers[inst->data.SingleTransferData.processOpData.singleDataTransferData.base] = address; - break; - case a64inst_POST_INDEXED: - state->registers[inst->data.SingleTransferData.processOpData.singleDataTransferData.base] = address + inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset; - break; - } - } - - 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); - } - } else { - *(word *)(state->memory + address) = state->registers[inst->data.SingleTransferData.target]; - - // Update base register if post indexed - if (inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode == a64inst_POST_INDEXED) { - writeRegister(state, inst->data.SingleTransferData.processOpData.singleDataTransferData.base, inst->data.SingleTransferData.regType == a64inst_W, address + inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset); - } - } - -} - -static bool isConditionMet(Machine* state, a64inst_ConditionType cond) { - switch(cond) { - case EQ: - return state->conditionCodes.Zero; - case NE: - return !state->conditionCodes.Zero; - case GE: - return state->conditionCodes.Negative == state->conditionCodes.Overflow; - case LT: - return state->conditionCodes.Negative != state->conditionCodes.Overflow; - case GT: - return !state->conditionCodes.Zero && (state->conditionCodes.Negative == state->conditionCodes.Overflow); - case LE: - return state->conditionCodes.Zero || (state->conditionCodes.Negative != state->conditionCodes.Overflow); - case AL: - return true; - default: - fprintf(stderr, "Unknown condition specified!\n"); - exit(1); - } -} - -void execute_Branch(Machine *state, a64inst_instruction *inst) { - switch (inst->data.BranchData.BranchType) { - case a64inst_UNCONDITIONAL: - state->pc += signExtend(inst->data.BranchData.processOpData.unconditionalData.unconditionalOffset * 4, 26); - break; - - case a64inst_REGISTER: - state->pc = state->registers[inst->data.BranchData.processOpData.registerData.src]; - break; - - case a64inst_CONDITIONAL: - if (isConditionMet(state, inst->data.BranchData.processOpData.conditionalData.cond)) { - state->pc += signExtend(inst->data.BranchData.processOpData.conditionalData.offset * 4, 19); - } - break; - } -} - -void executeMultiply(Machine *state, a64inst_instruction *inst) { - dword product = state->registers[inst->data.DPRegisterData.src1] * state->registers[inst->data.DPRegisterData.src2]; - dword sum = readRegister(state, inst->data.DPRegisterData.processOpData.multiplydata.summand, inst->data.DPRegisterData.regType) + (inst->data.DPRegisterData.processOpData.multiplydata.negProd ? -product : product); - writeRegister(state, inst->data.DPRegisterData.dest, inst->data.DPRegisterData.regType, sum); -} diff --git a/src/parser.c b/src/parser.c index a66b6f3..31b5ffc 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -172,8 +173,9 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[ } void tokeniseOperands(char* str, int *operandCount, char *operands[], int *numOperands){ - char *operandsDupe = NULL; - operandsDupe = strcpy(operandsDupe, str); + assert(str != NULL); + char operandsDupe[strlen(str)+1]; + strcpy(operandsDupe, str); char *operand = strtok(operandsDupe, OPERAND_DELIMITER); operands[0] = operand; @@ -200,8 +202,8 @@ void parser_instruction(char asmLine[], a64inst_instruction *instr) { //"opcode operand1, {operand2}, ..." //duplicated as strtok modifies the input string - char *stringptr = NULL; - stringptr = strcpy(stringptr, asmLine); + char stringptr[strlen(asmLine) + 1]; + strcpy(stringptr, asmLine); char *opcode = strtok(stringptr, " "); char *operands = strtok(NULL, ""); @@ -254,9 +256,8 @@ void parser_instruction(char asmLine[], a64inst_instruction *instr) { // Takes an array of strings, each string representing an assembly instruction. // Returns an array of a64inst_instruction pointers, each representing an instruction. -// Note. The array of strings must be NULL-terminated???? -a64inst_instruction *parse(char **asmLines) { - a64inst_instruction *instructions = malloc(sizeof(a64inst_instruction) * 1000); +a64inst_instruction *parse(char **asmLines, int lineCount) { + a64inst_instruction *instructions = malloc(sizeof(a64inst_instruction) * lineCount); int i = 0; while (asmLines[i] != NULL) { diff --git a/src/parser.h b/src/parser.h index 1f7ab70..2d7f382 100644 --- a/src/parser.h +++ b/src/parser.h @@ -3,4 +3,4 @@ #define OPERAND_DELIMITER ", " #define HALT_ASM_CMD "and x0, x0, x0" -a64inst_instruction *parse(char **asmLines); +a64inst_instruction *parse(char **asmLines, int lineCount);