From e69d4208df1e27ed9f1459f8a18f677d49d3f694 Mon Sep 17 00:00:00 2001 From: Garritt McCune Date: Thu, 16 Oct 2025 23:43:15 -0500 Subject: [PATCH] Updated the parser and setup the opcodes.c file to include helper functions to build up an Opcode object. I don't like how this is setup at the moment but seems to be a decent way to handle things for now. --- includes/opcodes.h | 15 ++- src/opcodes.c | 263 +++++++++++++++++++++++++++++++++++++-------- src/parser.c | 133 ++++++++++++----------- src/pstring.c | 6 +- 4 files changed, 304 insertions(+), 113 deletions(-) diff --git a/includes/opcodes.h b/includes/opcodes.h index 52fc0a1..7ded054 100644 --- a/includes/opcodes.h +++ b/includes/opcodes.h @@ -1,9 +1,13 @@ #ifndef OPCODES_H #define OPCODES_H +#include +#include #include #include #include +#include +#include typedef enum { R1 = 1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, @@ -15,9 +19,16 @@ typedef enum { OUTB, INB, HLT, CLI, ENI, INT, LIVT, PUSHA, POPA, CALL, RET, PUSH, POP } Mnemonics; -int IsOpcode(const char*, Mnemonics*); -int IsRegister(const char*, Registers*); +typedef struct opcode Opcode; + +bool IsOpcode(const char*, Mnemonics*); +bool IsRegister(const char*, Registers*); void GetMnemonicText(Mnemonics mnemonic, char buffer[12]); void GetRegisterText(Registers reg, char buffer[5]); +Opcode* OpcodeCreate(Mnemonics mnemonic); +int OpcodeArgCount(const Opcode* opcode); +int OpcodeAddLiteral(uint32_t number, bool pointer, Opcode* opcode); +int OpcodeAddSymbol(char* symbol, bool pointer, Opcode* opcode); +int OpcodeAddRegister(Registers reg, bool pointer, Opcode* opcode); #endif \ No newline at end of file diff --git a/src/opcodes.c b/src/opcodes.c index 3373e03..3a30a40 100644 --- a/src/opcodes.c +++ b/src/opcodes.c @@ -1,48 +1,221 @@ #include "../includes/opcodes.h" -#include -#include -#include -#define OPCODE_COUNT 30 +#define OPCODE_COUNT 30 + +struct argRules { + bool NoArgs; + bool Numerics; + bool Registers; + bool Pointers; +}; struct _instruction { char* Name; Mnemonics Mnemonic; + struct argRules ParamOne; + struct argRules ParamTwo; }; struct _instruction Instructions[OPCODE_COUNT] = { - { "add", ADD }, - { "sub", SUB }, - { "mul", MUL }, - { "div", DIV }, - { "mov", MOV }, - { "and", AND }, - { "or", OR }, - { "xor", XOR }, - { "not", NOT }, - { "shl", SHL }, - { "shr", SHR }, - { "nop", NOP }, - { "cmp", CMP }, - { "jmp", JMP }, - { "jz", JZ }, - { "jg", JG }, - { "jl", JL }, - { "outb", OUTB }, - { "inb", INB }, - { "hlt", HLT }, - { "cli", CLI }, - { "eni", ENI }, - { "int", INT }, - { "livt", LIVT }, - { "pusha", PUSHA }, - { "popa", POPA }, - { "call", CALL }, - { "ret", RET }, - { "push", PUSH }, - { "pop", POP } + { "add", ADD, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } }, + { "sub", SUB, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } }, + { "mul", MUL, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } }, + { "div", DIV, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } }, + { "mov", MOV, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } }, + { "and", AND, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } }, + { "or", OR, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } }, + { "xor", XOR, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } }, + { "not", NOT, { .Registers = 1 }, { .NoArgs = 1 } }, + { "shl", SHL, { .Numerics = 1, }, { .Registers = 1 } }, + { "shr", SHR, { .Numerics = 1, }, { .Registers = 1 } }, + { "nop", NOP, { .NoArgs = 1 }, { .NoArgs = 1 } }, + { "cmp", CMP, { .Numerics = 1, .Registers = 1 }, { .Numerics = 1, .Registers = 1 } }, + { "jmp", JMP, { .Numerics = 1 }, { .NoArgs = 1 } }, + { "jz", JZ, { .Numerics = 1 }, { .NoArgs = 1 } }, + { "jg", JG, { .Numerics = 1 }, { .NoArgs = 1 } }, + { "jl", JL, { .Numerics = 1 }, { .NoArgs = 1 } }, + { "outb", OUTB, { .Numerics = 1 }, { .Numerics = 1 } }, + { "inb", INB, { .Numerics = 1 }, { .Registers = 1 } }, + { "hlt", HLT, { .NoArgs = 1 }, { .NoArgs = 1 } }, + { "cli", CLI, { .NoArgs = 1 }, { .NoArgs = 1 } }, + { "eni", ENI, { .NoArgs = 1 }, { .NoArgs = 1 } }, + { "int", INT, { .Numerics = 1 }, { .NoArgs = 1 } }, + { "livt", LIVT, { .Numerics = 1 }, { .NoArgs = 1 } }, + { "pusha", PUSHA, { .NoArgs = 1 }, { .NoArgs = 1 } }, + { "popa", POPA, { .NoArgs = 1 }, { .NoArgs = 1 } }, + { "call", CALL, { .Numerics = 1 }, { .NoArgs = 1 } }, + { "ret", RET, { .NoArgs = 1 }, { .NoArgs = 1 } }, + { "push", PUSH, { .Registers = 1 }, { .NoArgs = 1 } }, + { "pop", POP, { .Registers = 1 }, { .NoArgs = 1 } } }; +struct argument { + bool IsPointer; + bool IsNumeric; + unsigned char Width; + char* SymbolName; + union { + uint32_t Number; + Registers Register; + } Value; +}; + +struct opcode { + struct _instruction* Instruction; + struct argument* ParamOne; + struct argument* ParamTwo; +}; + +Opcode* OpcodeCreate(Mnemonics mnemonic) { + Opcode* opcode = calloc(1, sizeof(struct opcode)); + + for(unsigned long i = 0; i < OPCODE_COUNT; i++) { + if (Instructions[i].Mnemonic != mnemonic) + continue; + + opcode->Instruction = &Instructions[i]; + + break; + } + + if (!opcode->Instruction) + { + free(opcode); + + return NULL; + } + + return opcode; +} + +int OpcodeArgCount(const Opcode* opcode) { + if (!opcode) return 0; + + struct _instruction* instruction = opcode->Instruction; + + if (instruction->ParamOne.NoArgs) return 0; + else if (instruction->ParamTwo.NoArgs) return 1; + else return 2; +} + +int OpcodeAppend(struct argument* arg, struct argRules* rule) { + if (rule->NoArgs) return -1; + if (arg->IsPointer && !rule->Pointers) return -2; + if (arg->IsNumeric && rule->Numerics) return 0; + if (!arg->IsNumeric && rule->Registers) return 0; + + return -3; +} + +int OpcodeAppendArgument(struct argument* arg, Opcode* opcode) { + if (!arg || !opcode) return -3; + + int expected = OpcodeArgCount(opcode); + + if (expected == 0) return -1; //No args expected + if (expected == 1 && !opcode->ParamOne) return -2; //Only one arg expected + if (expected == 2 && !opcode->ParamTwo) return -3; //Max number of args + + int result = OpcodeAppend(arg, &opcode->Instruction->ParamOne); + + if (expected == 1) return result; + + result = OpcodeAppend(arg, &opcode->Instruction->ParamTwo); + + return result; +} + +int OpcodeAddLiteral(uint32_t number, bool pointer, Opcode* opcode) { + struct _instruction* instruction = opcode->Instruction; + unsigned char width = 1; + + if (!opcode->ParamOne) { + if (!instruction->ParamOne.Numerics) return -1; + if (!instruction->ParamOne.Pointers && pointer) return -4; + + opcode->ParamOne = calloc(1, sizeof(struct argument)); + opcode->ParamOne->IsNumeric = true; + opcode->ParamOne->Value.Number = number; + opcode->ParamOne->Width = width; + + return 0; + } + + if (!opcode->ParamTwo) { + if (!instruction->ParamTwo.Numerics) return -2; + if (!instruction->ParamTwo.Pointers && pointer) return -5; + + opcode->ParamTwo = calloc(1, sizeof(struct argument)); + opcode->ParamTwo->IsNumeric = true; + opcode->ParamTwo->Value.Number = number; + opcode->ParamTwo->Width = width; + + return 0; + } + + return -3; +} + +int OpcodeAddSymbol(char* symbol, bool pointer, Opcode* opcode) { + struct _instruction* instruction = opcode->Instruction; + unsigned char width = 1; + + if (!opcode->ParamOne) { + if (!instruction->ParamOne.Numerics) return -1; + if (!instruction->ParamOne.Pointers && pointer) return -4; + + opcode->ParamOne = calloc(1, sizeof(struct argument)); + opcode->ParamOne->SymbolName = symbol; + opcode->ParamOne->Width = width; + + return 0; + } + + if (!opcode->ParamTwo) { + if (!instruction->ParamTwo.Numerics) return -2; + if (!instruction->ParamTwo.Pointers && pointer) return -5; + + opcode->ParamTwo = calloc(1, sizeof(struct argument)); + opcode->ParamTwo->SymbolName = symbol; + opcode->ParamTwo->Width = width; + + return 0; + } + + return -3; +} + +int OpcodeAddRegister(Registers reg, bool pointer, Opcode* opcode) { + struct _instruction* instruction = opcode->Instruction; + unsigned char width = 1; + + if (!opcode->ParamOne) { + if (!instruction->ParamOne.Numerics) return -1; + if (!instruction->ParamOne.Pointers && pointer) return -4; + + opcode->ParamOne = calloc(1, sizeof(struct argument)); + opcode->ParamOne->IsNumeric = false; + opcode->ParamTwo->Value.Register = reg; + opcode->ParamOne->Width = width; + + return 0; + } + + if (!opcode->ParamTwo) { + if (!instruction->ParamTwo.Numerics) return -2; + if (!instruction->ParamTwo.Pointers && pointer) return -5; + + opcode->ParamTwo = calloc(1, sizeof(struct argument)); + opcode->ParamTwo->IsNumeric = false; + opcode->ParamTwo->Value.Register = reg; + opcode->ParamTwo->Width = width; + + return 0; + } + + return -3; +} + void GetMnemonicText(Mnemonics mnemonic, char buffer[12]) { memset(buffer, '\0', 12); @@ -79,30 +252,30 @@ void GetRegisterText(Registers reg, char buffer[5]) { } } -int IsOpcode(const char* text, Mnemonics* opcode) { - if (!text) return 0; +bool IsOpcode(const char* text, Mnemonics* opcode) { + if (!text) return false; for(unsigned long i = 0; i < OPCODE_COUNT; i++) { if (strcmp(Instructions[i].Name, text) == 0) { if (opcode) *opcode = Instructions[i].Mnemonic; - return 1; + return true; } } - return 0; + return false; } -int IsRegister(const char* text, Registers* reg) { - if (!text) return 0; +bool IsRegister(const char* text, Registers* reg) { + if (!text) return false; int length = strlen(text); Registers r; - if (length < 2 || length > 3) return 0; - if (text[0] != 'r') return 0; + if (length < 2 || length > 3) return false; + if (text[0] != 'r') return false; if (length == 2) { - if (!isdigit(text[1])) return 0; + if (!isdigit(text[1])) return false; r = text[1] - 0x30; } @@ -114,11 +287,11 @@ int IsRegister(const char* text, Registers* reg) { r = RIP; else { r = (text[1] - 0x30) * 10; - if (!isdigit(text[2])) return 0; + if (!isdigit(text[2])) return false; r += text[2] - 0x30; } if (reg) *reg = r; - return 1; + return true; } \ No newline at end of file diff --git a/src/parser.c b/src/parser.c index b617464..d362db6 100644 --- a/src/parser.c +++ b/src/parser.c @@ -23,11 +23,11 @@ Token* ParserExpect(TokenType type); Token* ParserExpectList(int count, ...); Token* ParserWant(TokenType type); void ParserExpectLineEnd(void); +void ParserHandleParameter(Opcode* opcode); //Some more on attributes: https://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Function-Attributes.html#Function%20Attributes void ParserSync(char* format, ...) __attribute__ ((noreturn)); void ParserSyncExpect(TokenType expected, TokenType found) __attribute__ ((noreturn)); void ParserSyncMessage(char* message) __attribute__ ((noreturn)); -Instruction* ParserCreateInstruction(void); Instructions* ParseTokens(Array* tokens) { MessageString = CreateString(); @@ -86,12 +86,12 @@ void ParserSyncMessage(char* message) { } void ParserHandleKeyword(Keywords keyword) { - Token* namespace = NULL; + //Token* namespace = NULL; switch(keyword) { case NAMESPACE: { - namespace = ParserExpect(Symbol); + //namespace = ParserExpect(Symbol); ParserExpectLineEnd(); break; @@ -102,70 +102,81 @@ void ParserHandleKeyword(Keywords keyword) { } void ParserHandleMnemonic(Mnemonics mnemonic) { - Instruction* inst = ParserCreateInstruction(); - inst->Inst.Opcode = mnemonic; - inst->IsOpcode = true; + Opcode* opcode = OpcodeCreate(mnemonic); - switch(mnemonic) { - case ADD: - inst->ParameterCount = 2; + if (!opcode) { + ParserSync("Mnemonic %d is invalid.", mnemonic); + } + + int expectedCount = OpcodeArgCount(opcode); + + if (expectedCount == 0) { + ParserExpectLineEnd(); + + return; + } + + ParserHandleParameter(); + + // switch(mnemonic) { + // case ADD: - ParserExpects(LineEnd, Colon, Comma); + // //ParserExpects(LineEnd, Colon, Comma); + + // break; + // default: + // break; + // } +} + +void ParserHandleParameter(Opcode* opcode) { + Token* token = ParserWant(Keyword); + + if (token) { + switch(token->Value.Keyword) { + case BYTE: + break; + case SHORT: + break; + case WORD: + break; + default: + { + StringTruncate(MessageString); + char keyword[16]; + + GetKeywordText(token->Value.Keyword, keyword); + + StringVAppend(MessageString, "Expected width modifier keyword but got '%s'.", keyword); + + ParserSyncMessage(StringToCString(MessageString)); + } + } + } + + bool isPointer = ParserWant(OpenBracket) != NULL; + + token = ParserExpects(Number, Symbol, Register); + + switch(token->Type) { + case Number: + OpcodeAddLiteral(token->Value.Number, isPointer, opcode); + + break; + case Symbol: + OpcodeAddLiteral(token->Value.String, isPointer, opcode); + + break; + case Register: + OpcodeAddLiteral(token->Value.Register, isPointer, opcode); break; default: break; } -} -void ParserExpectParameter(Instruction* inst) { - if (ParserAtEnd()) return; - - Token* token = ParserPeek(); - - if (token->Type == Keyword) { - - } - - inst->Parameters[0].Pointer = ParserWant(OpenBracket) != NULL; - - token = ParserAdvance(); - - if (token->Type == Number) { - inst->Parameters[0].Type = Number; - inst->Parameters[0].Value.Number = token->Value.Number; - } - else if (token->Type == Symbol) { - inst->Parameters[0].Type = Symbol; - inst->Parameters[0].Value.Name = token->Value.String; - } - else if (token->Type == Register) { - inst->Parameters[0].Type = Register; - inst->Parameters[0].Value.Register = token->Value.Register; - } - else ParserSyncMessage("No valid parameter found 1."); - - if (inst->Parameters[0].Pointer) ParserExpect(CloseBracket); - - if (inst->ParameterCount == 1) return; - - ParserExpect(Comma); - - if (!inst->Parameters[0].Pointer) inst->Parameters[1].Pointer = ParserWant(OpenBracket) != NULL; - - token = ParserAdvance(); - - if (token->Type == Symbol) { - inst->Parameters[1].Type = Symbol; - inst->Parameters[1].Value.Name = token->Value.String; - } - if (token->Type == Register) { - inst->Parameters[1].Type = Register; - inst->Parameters[1].Value.Register = token->Value.Register; - } - else ParserSyncMessage("No valid parameter found 2."); - - if (inst->Parameters[1].Pointer) ParserExpect(CloseBracket); + if (isPointer) + (void) ParserExpect(CloseBracket); } Token* ParserExpect(TokenType type) { @@ -278,8 +289,4 @@ Token* ParserPeek(void) { bool ParserAtEnd() { return ParserIndex >= Tokens->Size; -} - -Instruction* ParserCreateInstruction(void) { - return calloc(1, sizeof(Instruction)); } \ No newline at end of file diff --git a/src/pstring.c b/src/pstring.c index dfae3ed..de211c7 100644 --- a/src/pstring.c +++ b/src/pstring.c @@ -1,6 +1,6 @@ #include "../includes/pstring.h" -#define DEFUALT_PSTRING_SIZE 64 +#define DEFAULT_PSTRING_SIZE 64 struct pstring { char* Buffer; @@ -11,8 +11,8 @@ struct pstring { PString* CreateString(void) { PString* string = calloc(1, sizeof(PString)); - string->Buffer = calloc(DEFUALT_PSTRING_SIZE, sizeof(char)); - string->Capacity = DEFUALT_PSTRING_SIZE; + string->Buffer = calloc(DEFAULT_PSTRING_SIZE, sizeof(char)); + string->Capacity = DEFAULT_PSTRING_SIZE; return string; }