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:
+13
-2
@@ -1,9 +1,13 @@
|
||||
#ifndef OPCODES_H
|
||||
#define OPCODES_H
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
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
|
||||
+218
-45
@@ -1,48 +1,221 @@
|
||||
#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 {
|
||||
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;
|
||||
}
|
||||
+70
-63
@@ -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));
|
||||
}
|
||||
+3
-3
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user