Restructre first pass, Reimplement symboltable
This commit is contained in:
parent
fd165aae47
commit
59871d7a0e
@ -7,7 +7,7 @@ CFLAGS ?= -std=c17 -g\
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: assemble emulate
|
||||
all: assemble
|
||||
|
||||
assemble: assemble.o parser.o fileio.o
|
||||
emulate: emulate.o
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
#include "parser.h"
|
||||
#include "encode.c"
|
||||
|
||||
static symbol_table *firstPass(a64inst_instruction *instructions, int lineCount);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// Check the arguments
|
||||
if (argc < 3) {
|
||||
@ -21,7 +23,7 @@ int main(int argc, char **argv) {
|
||||
a64inst_instruction *instructions = parse(source, lineCount);
|
||||
|
||||
// First Pass: Create the symbol table
|
||||
st *table = firstPass(instructions, lineCount);
|
||||
symbol_table *table = firstPass(instructions, lineCount);
|
||||
|
||||
// Second Pass: Encode the instructions into binary
|
||||
word *binary = encode(instructions, lineCount, table);
|
||||
@ -33,3 +35,17 @@ int main(int argc, char **argv) {
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static symbol_table *firstPass(a64inst_instruction *instructions, int lineCount) {
|
||||
symbol_table *table = st_init();
|
||||
int labelCount = 0;
|
||||
|
||||
for (int i = 0; i < lineCount; i++) {
|
||||
a64inst_instruction inst = instructions[i];
|
||||
if (inst.type == a64inst_LABEL) {
|
||||
st_insert(table, inst.data.LabelData.label, 4 * (i - (labelCount++)));
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
169
src/decode.c
169
src/decode.c
@ -1,169 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
// Given a binary word, return its internal representation as an a64instruction struct encoding the same
|
||||
// information.
|
||||
a64inst_instruction *decode(word wrd) {
|
||||
|
||||
a64inst_instruction *inst = malloc(sizeof(a64inst_instruction));
|
||||
if (inst == NULL) {
|
||||
fprintf(stderr, "Ran out of memory while attempting to decode an instruction!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
word typeId = getBits(wrd, TYPE_ID_LSB, TYPE_ID_MSB);
|
||||
// Halt interpretation
|
||||
if (wrd == HALT_WORD) {
|
||||
inst->type = a64inst_HALT;
|
||||
|
||||
// Data Processing Immediate interpretation
|
||||
} else if (typeId == DP_IMM_ID) {
|
||||
inst->type = a64inst_DPIMMEDIATE;
|
||||
inst->data.DPImmediateData.regType = getBits(wrd, DP_WIDTH_LSB, DP_WIDTH_MSB);
|
||||
inst->data.DPImmediateData.processOp = getBits(wrd, DP_OP_LSB, DP_OP_MSB);
|
||||
inst->data.DPImmediateData.dest = getBits(wrd, DP_DEST_LSB, DP_DEST_MSB);
|
||||
|
||||
switch(getBits(wrd, DP_IMM_OPTYPE_LSB, DP_IMM_OPTYPE_MSB)) {
|
||||
|
||||
case DP_IMM_OPTYPE_ARITHM:
|
||||
inst->data.DPImmediateData.DPIOpType = a64inst_DPI_ARITHM;
|
||||
inst->data.DPImmediateData.processOpData.arithmData.shiftImmediate = getBits(wrd, DP_IMM_ARITHM_SHIFTFLAG_LSB, DP_IMM_ARITHM_SHIFTFLAG_MSB);
|
||||
inst->data.DPImmediateData.processOpData.arithmData.immediate = getBits(wrd, DP_IMM_ARITHM_IMMVAL_LSB, DP_IMM_ARITHM_IMMVAL_MSB);
|
||||
inst->data.DPImmediateData.processOpData.arithmData.src = getBits(wrd, DP_IMM_ARITHM_DEST_LSB, DP_IMM_ARITHM_DEST_MSB);
|
||||
break;
|
||||
|
||||
case DP_IMM_OPTYPE_WIDEMOV:
|
||||
inst->data.DPImmediateData.DPIOpType = a64inst_DPI_WIDEMOV;
|
||||
inst->data.DPImmediateData.processOpData.wideMovData.shiftScalar = getBits(wrd, DP_IMM_WIDEMOV_SHIFTSCALAR_LSB, DP_IMM_WIDEMOV_SHIFTSCALAR_MSB);
|
||||
inst->data.DPImmediateData.processOpData.wideMovData.immediate = getBits(wrd, DP_IMM_WIDEMOV_IMMVAL_LSB, DP_IMM_WIDEMOV_IMMVAL_MSB);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown immediate data processing operation type found!\n");
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (typeId == BRANCH_ID) {
|
||||
inst->type = a64inst_BRANCH;
|
||||
word branchTypeFlag = getBits(wrd, BRANCH_TYPE_LSB, BRANCH_TYPE_MSB);
|
||||
|
||||
inst->data.BranchData.BranchType = branchTypeFlag;
|
||||
|
||||
switch (branchTypeFlag) {
|
||||
case a64inst_UNCONDITIONAL:
|
||||
inst->data.BranchData.processOpData.unconditionalData.unconditionalOffset = getBits(wrd, BRANCH_UNCONDITIONAL_OFFSET_LSB, BRANCH_UNCONDITIONAL_OFFSET_MSB);
|
||||
break;
|
||||
|
||||
case a64inst_CONDITIONAL:
|
||||
inst->data.BranchData.processOpData.conditionalData.offset = getBits(wrd, BRANCH_CONDITIONAL_OFFSET_LSB, BRANCH_CONDITIONAL_OFFSET_MSB);
|
||||
|
||||
word conditionFlag = getBits(wrd, BRANCH_CONDITIONAL_COND_LSB, BRANCH_CONDITIONAL_COND_MSB);
|
||||
|
||||
if(conditionFlag <= 1 || (conditionFlag >= 10 && conditionFlag <= 14)) {
|
||||
inst->data.BranchData.processOpData.conditionalData.cond = conditionFlag;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown condition detected!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case a64inst_REGISTER:
|
||||
inst->data.BranchData.processOpData.registerData.src = getBits(wrd, BRANCH_REGISTER_SRC_LSB, BRANCH_REGISTER_SRC_MSB);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Undefined branch type detected!\n");
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Some minor code duplication between DPR and DPI data interpretation
|
||||
// Data Processing Register interpretation
|
||||
} else if (getBits(wrd, DP_REG_LSB, DP_REG_MSB) == 1) {
|
||||
inst->type = a64inst_DPREGISTER;
|
||||
inst->data.DPRegisterData.regType = getBits(wrd, DP_WIDTH_LSB, DP_WIDTH_MSB);
|
||||
inst->data.DPRegisterData.processOp = getBits(wrd, DP_OP_LSB, DP_OP_MSB);
|
||||
inst->data.DPRegisterData.dest = getBits(wrd, DP_DEST_LSB, DP_DEST_MSB);
|
||||
inst->data.DPRegisterData.src1 = getBits(wrd, DP_REG_SRC1_LSB, DP_REG_SRC1_MSB);
|
||||
inst->data.DPRegisterData.src2 = getBits(wrd, DP_REG_SRC2_LSB, DP_REG_SRC2_MSB);
|
||||
inst->data.DPRegisterData.DPROpType = getBits(wrd, DP_REG_OPTYPE_LSB, DP_REG_OPTYPE_MSB);
|
||||
|
||||
a64inst_DPRegister_ArithmLogicData *arithmLogicData = &inst->data.DPRegisterData.processOpData.arithmLogicData;
|
||||
|
||||
arithmLogicData->type = getBits(wrd, DP_REG_ARITHMLOGIC_ARITHMFLAG_LSB, DP_REG_ARITHMLOGIC_ARITHMFLAG_MSB);
|
||||
arithmLogicData->shiftType = getBits(wrd, DP_REG_ARITHMLOGIC_SHIFTTYPE_LSB, DP_REG_ARITHMLOGIC_SHIFTTYPE_MSB);
|
||||
arithmLogicData->negShiftedSrc2 = getBits(wrd, DP_REG_ARITHMLOGIC_NEGSRC2FLAG_LSB, DP_REG_ARITHMLOGIC_NEGSRC2FLAG_MSB);
|
||||
|
||||
switch(inst->data.DPRegisterData.DPROpType) {
|
||||
|
||||
case a64inst_DPR_ARITHMLOGIC:
|
||||
if (arithmLogicData->type == a64inst_DPR_ARITHM && (arithmLogicData->negShiftedSrc2 || arithmLogicData->shiftType == a64inst_ROR)) {
|
||||
fprintf(stderr, "Attempting to decode arithmetic DPR instruction with invalid format!\n");
|
||||
}
|
||||
arithmLogicData->shiftAmount = getBits(wrd, DP_REG_ARITHMLOGIC_SHIFTAMOUNT_LSB, DP_REG_ARITHMLOGIC_SHIFTAMOUNT_MSB);
|
||||
break;
|
||||
|
||||
case a64inst_DPR_MULTIPLY:;
|
||||
if (!(inst->data.DPRegisterData.processOp == DP_REG_MULTIPLY_PROCESSOP &&
|
||||
arithmLogicData->type == DP_REG_MULTIPLY_ARITHMFLAG &&
|
||||
arithmLogicData->shiftType == DP_REG_MULTIPLY_SHIFTTYPE &&
|
||||
arithmLogicData->negShiftedSrc2 == DP_REG_MULTIPLY_NEGSRC2FLAG)) {
|
||||
fprintf(stderr, "Attempting to decode multiply DPR instruction with invalid format!\n");
|
||||
}
|
||||
inst->data.DPRegisterData.processOpData.multiplydata.summand = getBits(wrd, DP_REG_MULTIPLY_SUMMAND_LSB, DP_REG_MULTIPLY_SUMMAND_MSB);
|
||||
inst->data.DPRegisterData.processOpData.multiplydata.negProd = getBits(wrd, DP_REG_MULTIPLY_NEGPROD_LSB, DP_REG_MULTIPLY_NEGPROD_MSB);
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Load and Store, or unknown
|
||||
// Ignore unknown for now
|
||||
inst->type = a64inst_SINGLETRANSFER;
|
||||
inst->data.SingleTransferData.regType = getBits(wrd, SDT_REGTYPE_FLAG_LSB, SDT_REGTYPE_FLAG_MSB);
|
||||
inst->data.SingleTransferData.target = getBits(wrd, SDT_TARGET_REG_LSB, SDT_TARGET_REG_MSB);
|
||||
|
||||
// TODO: Assert that the instruction is a Single Transfer indeed.
|
||||
|
||||
if(getBits(wrd, SDT_OPTYPE_FLAG_LSB, SDT_OPTYPE_FLAG_MSB) == a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER) {
|
||||
// Single Data Transfer
|
||||
inst->data.SingleTransferData.SingleTransferOpType = a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER;
|
||||
inst->data.SingleTransferData.processOpData.singleDataTransferData.transferType = getBits(wrd, SDT_TRANSFER_TYPE_LSB, SDT_TRANSFER_TYPE_MSB);
|
||||
inst->data.SingleTransferData.processOpData.singleDataTransferData.base = getBits(wrd, SDT_BASE_REG_LSB, SDT_BASE_REG_MSB);
|
||||
if (getBits(wrd, SDT_UNSIGNED_FLAG_LSB, SDT_UNSIGNED_FLAG_MSB) == 1) {
|
||||
// Unsigned offset
|
||||
inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_UNSIGNED_OFFSET;
|
||||
inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.unsignedOffset = getBits(wrd, SDT_OFFSET_LSB, SDT_OFFSET_MSB);
|
||||
} else if (getBits(wrd, SDT_REGISTER_FLAG_LSB, SDT_REGISTER_FLAG_MSB) == 1) {
|
||||
// Register Offset
|
||||
inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_REGISTER_OFFSET;
|
||||
inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.offsetReg = getBits(wrd, SDT_REGISTER_REG_LSB, SDT_REGISTER_REG_MSB);
|
||||
} else {
|
||||
// Pre-Indexed or Post-Indexed
|
||||
inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = getBits(wrd, SDT_INDEXED_ADDRMODE_LSB, SDT_INDEXED_ADDRMODE_MSB);
|
||||
inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset = getBits(wrd, SDT_INDEXED_OFFSET_LSB, SDT_INDEXED_OFFSET_MSB);
|
||||
}
|
||||
} else {
|
||||
// Load Literal
|
||||
inst->data.SingleTransferData.SingleTransferOpType = a64inst_SINGLE_TRANSFER_LOAD_LITERAL;
|
||||
inst->data.SingleTransferData.processOpData.loadLiteralData.offset = getBits(wrd, SDT_LOAD_LITERAL_OFFSET_LSB, SDT_LOAD_LITERAL_OFFSET_MSB);
|
||||
}
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
96
src/decode.h
96
src/decode.h
@ -1,96 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "a64instruction/a64instruction.h"
|
||||
|
||||
#define HALT_WORD 0x8a000000
|
||||
|
||||
#define TYPE_ID_LSB 26
|
||||
#define TYPE_ID_MSB 29
|
||||
#define DP_IMM_ID 4
|
||||
#define BRANCH_ID 5
|
||||
|
||||
#define DP_REG_LSB 25
|
||||
#define DP_REG_MSB 26
|
||||
|
||||
#define DP_WIDTH_LSB 31
|
||||
#define DP_WIDTH_MSB 32
|
||||
#define DP_OP_LSB 29
|
||||
#define DP_OP_MSB 31
|
||||
#define DP_DEST_LSB 0
|
||||
#define DP_DEST_MSB 5
|
||||
|
||||
#define DP_IMM_OPTYPE_LSB 23
|
||||
#define DP_IMM_OPTYPE_MSB 26
|
||||
#define DP_IMM_OPTYPE_ARITHM 2
|
||||
#define DP_IMM_OPTYPE_WIDEMOV 5
|
||||
#define DP_IMM_ARITHM_SHIFTFLAG_LSB 22
|
||||
#define DP_IMM_ARITHM_SHIFTFLAG_MSB 23
|
||||
#define DP_IMM_ARITHM_IMMVAL_LSB 10
|
||||
#define DP_IMM_ARITHM_IMMVAL_MSB 22
|
||||
#define DP_IMM_ARITHM_DEST_LSB 5
|
||||
#define DP_IMM_ARITHM_DEST_MSB 10
|
||||
#define DP_IMM_WIDEMOV_SHIFTSCALAR_LSB 21
|
||||
#define DP_IMM_WIDEMOV_SHIFTSCALAR_MSB 23
|
||||
#define DP_IMM_WIDEMOV_IMMVAL_LSB 5
|
||||
#define DP_IMM_WIDEMOV_IMMVAL_MSB 21
|
||||
|
||||
#define DP_REG_SRC1_LSB 5
|
||||
#define DP_REG_SRC1_MSB 10
|
||||
#define DP_REG_SRC2_LSB 16
|
||||
#define DP_REG_SRC2_MSB 21
|
||||
#define DP_REG_OPTYPE_LSB 28
|
||||
#define DP_REG_OPTYPE_MSB 29
|
||||
#define DP_REG_ARITHMLOGIC_ARITHMFLAG_LSB 24
|
||||
#define DP_REG_ARITHMLOGIC_ARITHMFLAG_MSB 25
|
||||
#define DP_REG_ARITHMLOGIC_SHIFTTYPE_LSB 22
|
||||
#define DP_REG_ARITHMLOGIC_SHIFTTYPE_MSB 24
|
||||
#define DP_REG_ARITHMLOGIC_NEGSRC2FLAG_LSB 21
|
||||
#define DP_REG_ARITHMLOGIC_NEGSRC2FLAG_MSB 22
|
||||
#define DP_REG_ARITHMLOGIC_SHIFTAMOUNT_LSB 10
|
||||
#define DP_REG_ARITHMLOGIC_SHIFTAMOUNT_MSB 16
|
||||
#define DP_REG_MULTIPLY_SUMMAND_LSB 10
|
||||
#define DP_REG_MULTIPLY_SUMMAND_MSB 15
|
||||
#define DP_REG_MULTIPLY_NEGPROD_LSB 15
|
||||
#define DP_REG_MULTIPLY_NEGPROD_MSB 16
|
||||
// Defines the values for fields used for arithmetic/logic DPR instructions
|
||||
// that are necessary to indicate a multiplication instruction
|
||||
#define DP_REG_MULTIPLY_PROCESSOP 0
|
||||
#define DP_REG_MULTIPLY_ARITHMFLAG 1
|
||||
#define DP_REG_MULTIPLY_SHIFTTYPE 0
|
||||
#define DP_REG_MULTIPLY_NEGSRC2FLAG 0
|
||||
|
||||
#define SDT_OPTYPE_FLAG_LSB 31
|
||||
#define SDT_OPTYPE_FLAG_MSB 32
|
||||
#define SDT_REGTYPE_FLAG_LSB 30
|
||||
#define SDT_REGTYPE_FLAG_MSB 31
|
||||
#define SDT_TARGET_REG_LSB 0
|
||||
#define SDT_TARGET_REG_MSB 5
|
||||
|
||||
#define SDT_BASE_REG_LSB 5
|
||||
#define SDT_BASE_REG_MSB 10
|
||||
#define SDT_OFFSET_LSB 10
|
||||
#define SDT_OFFSET_MSB 22
|
||||
#define SDT_TRANSFER_TYPE_LSB 22
|
||||
#define SDT_TRANSFER_TYPE_MSB 23
|
||||
#define SDT_UNSIGNED_FLAG_LSB 24
|
||||
#define SDT_UNSIGNED_FLAG_MSB 25
|
||||
#define SDT_REGISTER_FLAG_LSB 21
|
||||
#define SDT_REGISTER_FLAG_MSB 22
|
||||
#define SDT_REGISTER_REG_LSB 16
|
||||
#define SDT_REGISTER_REG_MSB 21
|
||||
#define SDT_INDEXED_ADDRMODE_LSB 11
|
||||
#define SDT_INDEXED_ADDRMODE_MSB 12
|
||||
#define SDT_INDEXED_OFFSET_LSB 12
|
||||
#define SDT_INDEXED_OFFSET_MSB 21
|
||||
#define SDT_LOAD_LITERAL_OFFSET_LSB 5
|
||||
#define SDT_LOAD_LITERAL_OFFSET_MSB 24
|
||||
|
||||
#define BRANCH_TYPE_LSB 30
|
||||
#define BRANCH_TYPE_MSB 32
|
||||
#define BRANCH_UNCONDITIONAL_OFFSET_LSB 0
|
||||
#define BRANCH_UNCONDITIONAL_OFFSET_MSB 26
|
||||
#define BRANCH_REGISTER_SRC_LSB 5
|
||||
#define BRANCH_REGISTER_SRC_MSB 10
|
||||
#define BRANCH_CONDITIONAL_COND_LSB 0
|
||||
#define BRANCH_CONDITIONAL_COND_MSB 4
|
||||
#define BRANCH_CONDITIONAL_OFFSET_LSB 5
|
||||
#define BRANCH_CONDITIONAL_OFFSET_MSB 24
|
||||
@ -1,67 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "a64instruction/a64instruction.h"
|
||||
#include "emulator.h"
|
||||
#include "fileio.h"
|
||||
#include "global.h"
|
||||
#include "print.h"
|
||||
#include "decode.h"
|
||||
#include "execute.h"
|
||||
|
||||
int main(int arg, char **argv){
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
extern a64inst_instruction *decode(word w);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
// Check the arguments
|
||||
if (argc == 1) {
|
||||
fprintf(stderr, "Error: An object file is required. Syntax: ./emulate <file_in> [<file_out>]");
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialising the machine state
|
||||
Machine state = {0};
|
||||
state.memory = fileio_loadBin(argv[1], MEMORY_SIZE);
|
||||
state.conditionCodes = (PState){0, 1, 0, 0};
|
||||
state.pc = 0x0;
|
||||
|
||||
|
||||
// Fetch-decode-execute cycle
|
||||
word wrd;
|
||||
a64inst_instruction *inst;
|
||||
do {
|
||||
|
||||
// Step 1: Fetch instruction at PC's address
|
||||
wrd = readWord(state.memory, state.pc);
|
||||
|
||||
// Step 2: Decode instruction to internal representation
|
||||
inst = decode(wrd);
|
||||
|
||||
// Step 3: Update processor state to reflect executing the instruction, and increment PC
|
||||
execute(&state, inst);
|
||||
|
||||
if (inst->type != a64inst_BRANCH)
|
||||
state.pc += sizeof(word);
|
||||
} while (inst->type != a64inst_HALT);
|
||||
|
||||
state.pc -= sizeof(word);
|
||||
|
||||
printState(&state, out);
|
||||
free(state.memory);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
*/
|
||||
@ -1,32 +0,0 @@
|
||||
#ifndef __EMULATOR__
|
||||
#define __EMULATOR__
|
||||
#include "global.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/************************************
|
||||
* DEFINITIONS
|
||||
************************************/
|
||||
|
||||
#define BYTE_BITS 8
|
||||
#define WORD_BITS (BYTE_BITS * sizeof(word))
|
||||
#define DWORD_BITS (BYTE_BITS * sizeof(dword))
|
||||
|
||||
/************************************
|
||||
* STRUCTS
|
||||
************************************/
|
||||
|
||||
typedef struct {
|
||||
bool Negative;
|
||||
bool Zero;
|
||||
bool Carry;
|
||||
bool Overflow;
|
||||
} PState;
|
||||
|
||||
typedef struct {
|
||||
dword registers[REGISTER_COUNT];
|
||||
dword pc;
|
||||
byte *memory;
|
||||
PState conditionCodes;
|
||||
} Machine;
|
||||
|
||||
#endif
|
||||
35
src/encode.c
35
src/encode.c
@ -3,7 +3,6 @@
|
||||
#include "a64instruction/a64instruction.h"
|
||||
#include "symboltable.c"
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define HALT_BINARY 2315255808
|
||||
|
||||
@ -26,21 +25,19 @@ void setBits(word* wrd, uint8_t lsb, uint8_t msb, word value) {
|
||||
*wrd |= (value << lsb) & mask;
|
||||
}
|
||||
|
||||
int calculateLabelOffset(char *label, int wordArrIndex, symboltable *st){
|
||||
int labelAddress = st.get(label);
|
||||
int currInstrAddr = wordArrIndex * 4;
|
||||
int totalOffset = labelAddress - currInstrAddr;
|
||||
return totalOffset;
|
||||
static int getLabelOffset(symbol_table* table, char* label, int currentIndex) {
|
||||
address target = st_get(table, label);
|
||||
return target - (currentIndex * 4);
|
||||
}
|
||||
|
||||
// Generates assembled code based on the two-pass assembly method
|
||||
word encodeBranch(a64inst_instruction *instr, int wordArrIndex) {
|
||||
word encodeBranch(a64inst_instruction *instr) {
|
||||
word wrd = 0;
|
||||
|
||||
switch (instr->data.BranchData.BranchType) {
|
||||
case a64inst_UNCONDITIONAL:
|
||||
setBits(&wrd, 26, 30, 0x5);
|
||||
setBits(&wrd, 25, 0, instr->data.BranchData.processOpData.unconditionalData.unconditionalOffset);
|
||||
setBits(&wrd, 0, 25, instr->data.BranchData.processOpData.unconditionalData.unconditionalOffset);
|
||||
break;
|
||||
|
||||
case a64inst_REGISTER:
|
||||
@ -58,20 +55,6 @@ word encodeBranch(a64inst_instruction *instr, int wordArrIndex) {
|
||||
return wrd;
|
||||
}
|
||||
|
||||
st* firstPass(a64inst_instruction instrs[], int numInstrs) {
|
||||
// TODO:
|
||||
// -iterate over instructions, adding to symbol table
|
||||
// create symbol table and map labels to addresses/lines
|
||||
st *table = (st*)malloc(sizeof(st));
|
||||
for (int i = 0; i < numInstrs; i++) {
|
||||
// discuss defining a LABEL type
|
||||
if (instrs[i].type == a64inst_LABEL) {
|
||||
st_add(*table, &(instrs[i].data.LabelData.label), &i);
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
word encodeDPImmediate(a64inst_instruction inst) {
|
||||
word wrd = 0;
|
||||
|
||||
@ -182,11 +165,7 @@ word encodeLoadLiteral(a64inst_instruction cI) {
|
||||
return wrd;
|
||||
}
|
||||
|
||||
word *encode(a64inst_instruction insts[], int instCount, st* table) {
|
||||
// TODO:
|
||||
// iterate over instructions again, this time replacing labels
|
||||
// with values from symbol table
|
||||
// after a line has had all the values replaced, assemble it and append
|
||||
word *encode(a64inst_instruction insts[], int instCount, symbol_table* table) {
|
||||
word *arr = (word*)malloc(sizeof(word) * instCount);
|
||||
int index = 0;
|
||||
for (int i = 0; i < instCount; i++) {
|
||||
@ -220,7 +199,7 @@ word *encode(a64inst_instruction insts[], int instCount, st* table) {
|
||||
// Labels are handled in the first pass and used for addressing.
|
||||
break;
|
||||
case a64inst_BRANCH:
|
||||
arr[index] = encodeBranch(&inst, index);
|
||||
arr[index] = encodeBranch(&inst);
|
||||
index++;
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
#ifndef __EXECUTE__
|
||||
#define __EXECUTE__
|
||||
#include "a64instruction/a64instruction.h"
|
||||
#include "emulator.h"
|
||||
|
||||
void execute(Machine *state, a64inst_instruction *inst);
|
||||
#endif
|
||||
58
src/print.c
58
src/print.c
@ -1,58 +0,0 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include "print.h"
|
||||
#include "emulator.h"
|
||||
|
||||
#define UNSET_CONDITION_CODE_CHAR '-'
|
||||
|
||||
// Prints the current machine state into the provided stream
|
||||
void printState(Machine *state, FILE *stream) {
|
||||
printRegisters(state, stream);
|
||||
printMemory(state, stream);
|
||||
}
|
||||
|
||||
// Prints the current machine registers into the provided stream
|
||||
void printRegisters(Machine *state, FILE *stream) {
|
||||
fprintf(stream, "Registers:\n");
|
||||
for (int i = 0; i < REGISTER_COUNT; i++) {
|
||||
fprintf(stream, "X%02d\t= %016" PRIx64 "\n", i, state->registers[i]);
|
||||
}
|
||||
fprintf(stream, "PC\t= %016" PRIx64 "\n", state->pc);
|
||||
fprintf(stream, "PSTATE\t: %c%c%c%c", state->conditionCodes.Negative ? 'N' : UNSET_CONDITION_CODE_CHAR,
|
||||
state->conditionCodes.Zero ? 'Z' : UNSET_CONDITION_CODE_CHAR,
|
||||
state->conditionCodes.Carry ? 'C' : UNSET_CONDITION_CODE_CHAR,
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (data != 0) {
|
||||
fprintf(stream, "0x%08x: %08x\n", addr, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/print.h
12
src/print.h
@ -1,12 +0,0 @@
|
||||
#ifndef __PRINT__
|
||||
#define __PRINT__
|
||||
#include <stdio.h>
|
||||
#include "emulator.h"
|
||||
|
||||
word readWord(byte *memory, uint32_t address);
|
||||
dword readDoubleWord(byte *memory, uint32_t address);
|
||||
void printState(Machine *state, FILE *stream);
|
||||
void printRegisters(Machine *state, FILE *stream);
|
||||
void printMemory(Machine *state, FILE *stream);
|
||||
|
||||
#endif
|
||||
@ -1,48 +1,74 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "symboltable.h"
|
||||
|
||||
typedef struct st st;
|
||||
typedef struct node node; // forward declaration
|
||||
|
||||
typedef struct node {
|
||||
const void* key;
|
||||
void* value;
|
||||
node* prev;
|
||||
node* next;
|
||||
} node;
|
||||
|
||||
struct st {
|
||||
node* head;
|
||||
node* tail;
|
||||
};
|
||||
|
||||
// add new node to the end
|
||||
void st_add(st table, void* key, void* value) {
|
||||
node n = {key, value, table.tail};
|
||||
if (table.head == NULL) {
|
||||
table.head = &n;
|
||||
table.tail = &n;
|
||||
symbol_table *st_init(void) {
|
||||
symbol_table *st = malloc(sizeof(symbol_table));
|
||||
if (st == NULL) {
|
||||
fprintf(stderr, "Failed to allocate memory for symbol table\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else {
|
||||
(*(table.tail)).next = &n;
|
||||
table.tail = &n;
|
||||
}
|
||||
|
||||
st->table = malloc(INITIAL_CAPACITY * sizeof(symbol_table_map));
|
||||
if (st->table == NULL) {
|
||||
fprintf(stderr, "Failed to allocate memory for table\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
st->size = 0;
|
||||
st->capacity = INITIAL_CAPACITY;
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
void* nodeSearch(node* n, void* key) {
|
||||
if (n != NULL) {
|
||||
if ((*n).key == key) {
|
||||
return (*n).value;
|
||||
}
|
||||
else {
|
||||
return nodeSearch((*n).next, key);
|
||||
/* Grows the symbol table by a factor of GROWTH_FACTOR *only if the table is full*.
|
||||
*/
|
||||
static void grow(symbol_table *st) {
|
||||
if (st->size == st->capacity) {
|
||||
st->capacity *= GROWTH_FACTOR;
|
||||
st->table = realloc(st->table, st->capacity * sizeof(symbol_table_map));
|
||||
if (st->table == NULL) {
|
||||
fprintf(stderr, "Failed to reallocate memory for table\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// returns the pointer to key of the specified node, or null, if it does not exist
|
||||
void* st_search(st table, void* key) {
|
||||
return nodeSearch(table.head, key);
|
||||
void st_insert(symbol_table *st, char *label, address addr) {
|
||||
// If full, grow the table
|
||||
grow(st);
|
||||
|
||||
// Insert the new entry to the end of the table
|
||||
symbol_table_map *entry = &st->table[st->size];
|
||||
entry->label = label;
|
||||
entry->address = addr;
|
||||
|
||||
st->size++;
|
||||
}
|
||||
|
||||
bool st_contains(symbol_table *st, char *label) {
|
||||
for (int i = 0; i < st->size; i++) {
|
||||
if (strcmp(st->table[i].label, label) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
address st_get(symbol_table *st, char *label) {
|
||||
for (int i = 0; i < st->size; i++) {
|
||||
if (strcmp(st->table[i].label, label) == 0) {
|
||||
return st->table[i].address;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Label %s not found in symbol table\n", label);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void st_free(symbol_table *st) {
|
||||
free(st->table);
|
||||
free(st);
|
||||
}
|
||||
|
||||
27
src/symboltable.h
Normal file
27
src/symboltable.h
Normal file
@ -0,0 +1,27 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define INITIAL_CAPACITY 5
|
||||
#define GROWTH_FACTOR 2
|
||||
|
||||
typedef uint32_t address;
|
||||
|
||||
typedef struct {
|
||||
char *label;
|
||||
address address;
|
||||
} symbol_table_map;
|
||||
|
||||
typedef struct {
|
||||
symbol_table_map* table;
|
||||
int size;
|
||||
int capacity;
|
||||
} symbol_table;
|
||||
|
||||
symbol_table *st_init(void);
|
||||
|
||||
void st_insert(symbol_table *st, char *label, address addr);
|
||||
|
||||
bool st_contains(symbol_table *st, char *label);
|
||||
|
||||
address st_get(symbol_table *st, char *label);
|
||||
@ -1,5 +1,6 @@
|
||||
// Tokeniser.c
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -9,6 +10,25 @@
|
||||
#define MAX_OPERAND_COUNT 4
|
||||
#define OPERAND_DELIMITER ", "
|
||||
|
||||
char *trim(char *str) {
|
||||
while (isspace(*str)) {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str == '\0') {
|
||||
return str;
|
||||
}
|
||||
|
||||
char *end = str + strlen(str) - 1;
|
||||
while (end > str && isspace(*end)) {
|
||||
end--;
|
||||
}
|
||||
|
||||
end[1] = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
char **tokenise(char *line, int *numTokens) {
|
||||
char **tokens = malloc(MAX_TOKEN_COUNT * sizeof(char *));\
|
||||
if (!tokens) {
|
||||
@ -16,6 +36,8 @@ char **tokenise(char *line, int *numTokens) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
line = trim(line);
|
||||
|
||||
*numTokens = 0;
|
||||
char *token = strtok(line, " ");
|
||||
assert(token != NULL);
|
||||
@ -23,7 +45,10 @@ char **tokenise(char *line, int *numTokens) {
|
||||
tokens[(*numTokens)++] = token;
|
||||
|
||||
char *operandStart = strtok(NULL, "");
|
||||
assert(operandStart != NULL);
|
||||
if (operandStart == NULL) {
|
||||
// No operands. Return the instruction token.
|
||||
return tokens;
|
||||
}
|
||||
|
||||
bool inBracket = false;
|
||||
char *currentToken = operandStart;
|
||||
@ -48,11 +73,6 @@ char **tokenise(char *line, int *numTokens) {
|
||||
|
||||
if (*currentToken != '\0') {
|
||||
tokens[*numTokens] = currentToken;
|
||||
|
||||
if (tokens[*numTokens][strlen(tokens[*numTokens]) - 1] == '\n') {
|
||||
tokens[*numTokens][strlen(tokens[*numTokens]) - 1] = '\0';
|
||||
}
|
||||
|
||||
(*numTokens)++;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user