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.

This commit is contained in:
2025-10-16 23:43:15 -05:00
parent 013925e2ba
commit e69d4208df
4 changed files with 304 additions and 113 deletions
+13 -2
View File
@@ -1,9 +1,13 @@
#ifndef OPCODES_H #ifndef OPCODES_H
#define OPCODES_H #define OPCODES_H
#include <ctype.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
typedef enum { typedef enum {
R1 = 1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, 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 OUTB, INB, HLT, CLI, ENI, INT, LIVT, PUSHA, POPA, CALL, RET, PUSH, POP
} Mnemonics; } Mnemonics;
int IsOpcode(const char*, Mnemonics*); typedef struct opcode Opcode;
int IsRegister(const char*, Registers*);
bool IsOpcode(const char*, Mnemonics*);
bool IsRegister(const char*, Registers*);
void GetMnemonicText(Mnemonics mnemonic, char buffer[12]); void GetMnemonicText(Mnemonics mnemonic, char buffer[12]);
void GetRegisterText(Registers reg, char buffer[5]); 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 #endif
+218 -45
View File
@@ -1,48 +1,221 @@
#include "../includes/opcodes.h" #include "../includes/opcodes.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#define OPCODE_COUNT 30 #define OPCODE_COUNT 30
struct argRules {
bool NoArgs;
bool Numerics;
bool Registers;
bool Pointers;
};
struct _instruction { struct _instruction {
char* Name; char* Name;
Mnemonics Mnemonic; Mnemonics Mnemonic;
struct argRules ParamOne;
struct argRules ParamTwo;
}; };
struct _instruction Instructions[OPCODE_COUNT] = { struct _instruction Instructions[OPCODE_COUNT] = {
{ "add", ADD }, { "add", ADD, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } },
{ "sub", SUB }, { "sub", SUB, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } },
{ "mul", MUL }, { "mul", MUL, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } },
{ "div", DIV }, { "div", DIV, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } },
{ "mov", MOV }, { "mov", MOV, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } },
{ "and", AND }, { "and", AND, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } },
{ "or", OR }, { "or", OR, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } },
{ "xor", XOR }, { "xor", XOR, { .Numerics = 1, .Registers = 1 }, { .Registers = 1 } },
{ "not", NOT }, { "not", NOT, { .Registers = 1 }, { .NoArgs = 1 } },
{ "shl", SHL }, { "shl", SHL, { .Numerics = 1, }, { .Registers = 1 } },
{ "shr", SHR }, { "shr", SHR, { .Numerics = 1, }, { .Registers = 1 } },
{ "nop", NOP }, { "nop", NOP, { .NoArgs = 1 }, { .NoArgs = 1 } },
{ "cmp", CMP }, { "cmp", CMP, { .Numerics = 1, .Registers = 1 }, { .Numerics = 1, .Registers = 1 } },
{ "jmp", JMP }, { "jmp", JMP, { .Numerics = 1 }, { .NoArgs = 1 } },
{ "jz", JZ }, { "jz", JZ, { .Numerics = 1 }, { .NoArgs = 1 } },
{ "jg", JG }, { "jg", JG, { .Numerics = 1 }, { .NoArgs = 1 } },
{ "jl", JL }, { "jl", JL, { .Numerics = 1 }, { .NoArgs = 1 } },
{ "outb", OUTB }, { "outb", OUTB, { .Numerics = 1 }, { .Numerics = 1 } },
{ "inb", INB }, { "inb", INB, { .Numerics = 1 }, { .Registers = 1 } },
{ "hlt", HLT }, { "hlt", HLT, { .NoArgs = 1 }, { .NoArgs = 1 } },
{ "cli", CLI }, { "cli", CLI, { .NoArgs = 1 }, { .NoArgs = 1 } },
{ "eni", ENI }, { "eni", ENI, { .NoArgs = 1 }, { .NoArgs = 1 } },
{ "int", INT }, { "int", INT, { .Numerics = 1 }, { .NoArgs = 1 } },
{ "livt", LIVT }, { "livt", LIVT, { .Numerics = 1 }, { .NoArgs = 1 } },
{ "pusha", PUSHA }, { "pusha", PUSHA, { .NoArgs = 1 }, { .NoArgs = 1 } },
{ "popa", POPA }, { "popa", POPA, { .NoArgs = 1 }, { .NoArgs = 1 } },
{ "call", CALL }, { "call", CALL, { .Numerics = 1 }, { .NoArgs = 1 } },
{ "ret", RET }, { "ret", RET, { .NoArgs = 1 }, { .NoArgs = 1 } },
{ "push", PUSH }, { "push", PUSH, { .Registers = 1 }, { .NoArgs = 1 } },
{ "pop", POP } { "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]) { void GetMnemonicText(Mnemonics mnemonic, char buffer[12]) {
memset(buffer, '\0', 12); memset(buffer, '\0', 12);
@@ -79,30 +252,30 @@ void GetRegisterText(Registers reg, char buffer[5]) {
} }
} }
int IsOpcode(const char* text, Mnemonics* opcode) { bool IsOpcode(const char* text, Mnemonics* opcode) {
if (!text) return 0; if (!text) return false;
for(unsigned long i = 0; i < OPCODE_COUNT; i++) { for(unsigned long i = 0; i < OPCODE_COUNT; i++) {
if (strcmp(Instructions[i].Name, text) == 0) { if (strcmp(Instructions[i].Name, text) == 0) {
if (opcode) *opcode = Instructions[i].Mnemonic; if (opcode) *opcode = Instructions[i].Mnemonic;
return 1; return true;
} }
} }
return 0; return false;
} }
int IsRegister(const char* text, Registers* reg) { bool IsRegister(const char* text, Registers* reg) {
if (!text) return 0; if (!text) return false;
int length = strlen(text); int length = strlen(text);
Registers r; Registers r;
if (length < 2 || length > 3) return 0; if (length < 2 || length > 3) return false;
if (text[0] != 'r') return 0; if (text[0] != 'r') return false;
if (length == 2) { if (length == 2) {
if (!isdigit(text[1])) return 0; if (!isdigit(text[1])) return false;
r = text[1] - 0x30; r = text[1] - 0x30;
} }
@@ -114,11 +287,11 @@ int IsRegister(const char* text, Registers* reg) {
r = RIP; r = RIP;
else { else {
r = (text[1] - 0x30) * 10; r = (text[1] - 0x30) * 10;
if (!isdigit(text[2])) return 0; if (!isdigit(text[2])) return false;
r += text[2] - 0x30; r += text[2] - 0x30;
} }
if (reg) *reg = r; if (reg) *reg = r;
return 1; return true;
} }
+70 -63
View File
@@ -23,11 +23,11 @@ Token* ParserExpect(TokenType type);
Token* ParserExpectList(int count, ...); Token* ParserExpectList(int count, ...);
Token* ParserWant(TokenType type); Token* ParserWant(TokenType type);
void ParserExpectLineEnd(void); 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 //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 ParserSync(char* format, ...) __attribute__ ((noreturn));
void ParserSyncExpect(TokenType expected, TokenType found) __attribute__ ((noreturn)); void ParserSyncExpect(TokenType expected, TokenType found) __attribute__ ((noreturn));
void ParserSyncMessage(char* message) __attribute__ ((noreturn)); void ParserSyncMessage(char* message) __attribute__ ((noreturn));
Instruction* ParserCreateInstruction(void);
Instructions* ParseTokens(Array* tokens) { Instructions* ParseTokens(Array* tokens) {
MessageString = CreateString(); MessageString = CreateString();
@@ -86,12 +86,12 @@ void ParserSyncMessage(char* message) {
} }
void ParserHandleKeyword(Keywords keyword) { void ParserHandleKeyword(Keywords keyword) {
Token* namespace = NULL; //Token* namespace = NULL;
switch(keyword) { switch(keyword) {
case NAMESPACE: case NAMESPACE:
{ {
namespace = ParserExpect(Symbol); //namespace = ParserExpect(Symbol);
ParserExpectLineEnd(); ParserExpectLineEnd();
break; break;
@@ -102,70 +102,81 @@ void ParserHandleKeyword(Keywords keyword) {
} }
void ParserHandleMnemonic(Mnemonics mnemonic) { void ParserHandleMnemonic(Mnemonics mnemonic) {
Instruction* inst = ParserCreateInstruction(); Opcode* opcode = OpcodeCreate(mnemonic);
inst->Inst.Opcode = mnemonic;
inst->IsOpcode = true;
switch(mnemonic) { if (!opcode) {
case ADD: ParserSync("Mnemonic %d is invalid.", mnemonic);
inst->ParameterCount = 2; }
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; break;
default: default:
break; break;
} }
}
void ParserExpectParameter(Instruction* inst) { if (isPointer)
if (ParserAtEnd()) return; (void) ParserExpect(CloseBracket);
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);
} }
Token* ParserExpect(TokenType type) { Token* ParserExpect(TokenType type) {
@@ -278,8 +289,4 @@ Token* ParserPeek(void) {
bool ParserAtEnd() { bool ParserAtEnd() {
return ParserIndex >= Tokens->Size; return ParserIndex >= Tokens->Size;
}
Instruction* ParserCreateInstruction(void) {
return calloc(1, sizeof(Instruction));
} }
+3 -3
View File
@@ -1,6 +1,6 @@
#include "../includes/pstring.h" #include "../includes/pstring.h"
#define DEFUALT_PSTRING_SIZE 64 #define DEFAULT_PSTRING_SIZE 64
struct pstring { struct pstring {
char* Buffer; char* Buffer;
@@ -11,8 +11,8 @@ struct pstring {
PString* CreateString(void) { PString* CreateString(void) {
PString* string = calloc(1, sizeof(PString)); PString* string = calloc(1, sizeof(PString));
string->Buffer = calloc(DEFUALT_PSTRING_SIZE, sizeof(char)); string->Buffer = calloc(DEFAULT_PSTRING_SIZE, sizeof(char));
string->Capacity = DEFUALT_PSTRING_SIZE; string->Capacity = DEFAULT_PSTRING_SIZE;
return string; return string;
} }