Updated the opcode listing and 'fixed' the code to at least compile, but obviously I'll need to rework how the new copy instructions are to be parsed. Fixed some errors in the documentation where I skipped some hex numbers and added a copy immediate op.
This commit is contained in:
+22
-19
@@ -82,7 +82,7 @@
|
||||
0000 0 & XXX \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\caption{Encoding Layout, Register Required}
|
||||
\caption{Encoding Layout, No Register Required}
|
||||
\label{fig:NoRegisterEncoding}
|
||||
\end{figure}
|
||||
|
||||
@@ -92,28 +92,31 @@
|
||||
or "word" for two bytes. That would make the assembly easier to read but put a bit more work on the
|
||||
assembler. The Stack Pointer will start 2 bytes above the video memory start.
|
||||
\section{COPY (Copy Word from Address)}
|
||||
\OpcodeTable{0x08}{0000 1000}{copy}{Register}{Address}\\[6pt]
|
||||
\OpcodeTable{0x08}{0000 1000}{copya}{Register}{Address}\\[6pt]
|
||||
Copy a machine word from Operand 2 into Operand 1.
|
||||
\section{COPY BYTE (Copy Byte from Address)}
|
||||
\OpcodeTable{0x10}{0001 0000}{copy byte}{Register}{Address}\\[6pt]
|
||||
\OpcodeTable{0x10}{0001 0000}{copyab}{Register}{Address}\\[6pt]
|
||||
Copy a byte (8 bits) from Operand 2 into Operand 1, clearing the setting the most significant bits to zero.
|
||||
\section{COPY (Copy Word Indirect Address)}
|
||||
\OpcodeTable{0x18}{0001 1000}{copy}{Register}{[Register]}\\[6pt]
|
||||
\OpcodeTable{0x18}{0001 1000}{copyra}{Register}{[Register]}\\[6pt]
|
||||
Copy a machine word from the address stored in Operand 2 into Operand 1.
|
||||
\section{COPY BYTE (Copy Byte Indirect Address)}
|
||||
\OpcodeTable{0x20}{0010 0000}{copy byte}{Register}{[Register]}\\[6pt]
|
||||
\OpcodeTable{0x20}{0010 0000}{copyrab}{Register}{[Register]}\\[6pt]
|
||||
Copy a byte (8 bits) from the address stored in Operand 2 into Operand 1.
|
||||
\section{COPY (Copy)}
|
||||
\OpcodeTable{0x28}{0010 1000}{copy}{[Register]}{[Register]}\\[6pt]
|
||||
\OpcodeTable{0x28}{0010 1000}{copyrara}{[Register]}{[Register]}\\[6pt]
|
||||
Copy a machine word from the address stored in Operand 2 into the address stored in Operand 1.
|
||||
\section{COPY BYTE (Copy Byte)}
|
||||
\OpcodeTable{0x30}{0011 0000}{copy byte}{[Register]}{[Register]}\\[6pt]
|
||||
\OpcodeTable{0x30}{0011 0000}{copyrarab}{[Register]}{[Register]}\\[6pt]
|
||||
Copy a byte (8 bits) from the address stored in Operand 2 into the address stored in Operand 1.
|
||||
\section{COPY (Copy)}
|
||||
\OpcodeTable{0x38}{0011 1000}{copy}{Register}{Register}\\[6pt]
|
||||
Copy a machine word from Operand 2 into Operand 1.
|
||||
\section{COPY (Copy Immediate)}
|
||||
\OpcodeTable{0xC0}{1100 0000}{copyi}{Register}{Constant}\\[6pt]
|
||||
Copy a machine word from Operand 2 into Operand 1.
|
||||
\section{COPY BYTE (Copy Byte)}
|
||||
\OpcodeTable{0x40}{0100 0000}{copy byte}{Register}{Constant}\\[6pt]
|
||||
\OpcodeTable{0x40}{0100 0000}{copyb}{Register}{Constant}\\[6pt]
|
||||
Copy a byte (8 bits) from Operand 2 into Operand 1.
|
||||
\section{CMP (Compare)}
|
||||
\OpcodeTable{0x48}{0100 1000}{cmp}{Register}{Register}\\[6pt]
|
||||
@@ -128,37 +131,37 @@
|
||||
\OpcodeTable{0x60}{0110 0000}{sub}{Register}{Register}\\[6pt]
|
||||
Performs subtraction on a register with a value from another (or the same) register.
|
||||
\section{AND (Logical AND)}
|
||||
\OpcodeTable{0x70}{0111 0000}{and}{Register}{Register}\\[6pt]
|
||||
\OpcodeTable{0x68}{0110 1000}{and}{Register}{Register}\\[6pt]
|
||||
Logical ANDs the two registers together storing the result in operand 1.
|
||||
\section{XOR (Logical Exclusive OR)}
|
||||
\OpcodeTable{0x78}{0111 1000}{xor}{Register}{Register}\\[6pt]
|
||||
\OpcodeTable{0x70}{0111 0000}{xor}{Register}{Register}\\[6pt]
|
||||
Logical XORs the two registers together storing the result in operand 1.
|
||||
\section{OR (Logical OR)}
|
||||
\OpcodeTable{0x80}{1000 0000}{or}{Register}{Register}\\[6pt]
|
||||
\OpcodeTable{0x78}{0111 1000}{or}{Register}{Register}\\[6pt]
|
||||
Logical ORs the two registers together storing the result in operand 1.
|
||||
\section{NOT (Logical Negation)}
|
||||
\OpcodeTable{0x88}{1000 1000}{not}{Register}{None}\\[6pt]
|
||||
\OpcodeTable{0x80}{1000 0000}{not}{Register}{None}\\[6pt]
|
||||
Inverts the bits of the target register.
|
||||
\section{SHR (Shift Right)}
|
||||
\OpcodeTable{0x90}{1001 0000}{shr}{Register}{Constant}\\[6pt]
|
||||
\OpcodeTable{0x88}{1000 1000}{shr}{Register}{Constant}\\[6pt]
|
||||
Bit-wise shifts the contents of the register right Constant number of times.
|
||||
\section{SHL (Shift Left)}
|
||||
\OpcodeTable{0x98}{1001 1000}{shl}{Register}{Constant}\\[6pt]
|
||||
\OpcodeTable{0x90}{1001 0000}{shl}{Register}{Constant}\\[6pt]
|
||||
Bit-wise shifts the contents of the register left Constant number of times.
|
||||
\section{INC (Increment)}
|
||||
\OpcodeTable{0xA0}{1010 0000}{inc}{Register}{None}\\[6pt]
|
||||
\OpcodeTable{0x98}{1001 1000}{inc}{Register}{None}\\[6pt]
|
||||
Increments the contents of the register by one. Over-flows will not be reported.
|
||||
\section{DEC (Decrement)}
|
||||
\OpcodeTable{0xA8}{1010 1000}{dec}{Register}{None}\\[6pt]
|
||||
\OpcodeTable{0xA0}{1010 0000}{dec}{Register}{None}\\[6pt]
|
||||
Decrements the contents of the register by one. Under-flows will not be reported.
|
||||
\section{Push}
|
||||
\OpcodeTable{0xB0}{1011 0000}{push}{Register}{None}
|
||||
\OpcodeTable{0xA8}{1010 1000}{push}{Register}{None}
|
||||
Pushes the value of Register onto the stack, decrementing the Stack Pointer by 2.
|
||||
\section{Pop}
|
||||
\OpcodeTable{0xB8}{1011 1000}{pop}{Register}{None}
|
||||
\OpcodeTable{0xB0}{1011 0000}{pop}{Register}{None}
|
||||
Pops the top of the stack into Register, incrementing the Stack Pointer by 2.
|
||||
\section{JMPI (Jump Indirect)}
|
||||
\OpcodeTable{0xC0}{1100 0000}{jmpi}{Register}{None}\\[6pt]
|
||||
\OpcodeTable{0xB8}{1011 1000}{jmpi}{Register}{None}\\[6pt]
|
||||
Jumps unconditionally to a memory address stored in Operand 1. Sets the Program Counter to Operand 1.
|
||||
\section{JMP (Jump)}
|
||||
\OpcodeTable{0x02}{0000 0010}{jmp}{Address}{None}\\[6pt]
|
||||
|
||||
+5
-28
@@ -7,47 +7,24 @@
|
||||
//#include "symbols_table.h"
|
||||
|
||||
typedef enum {
|
||||
R1, R2, R3, R4, R5, R6, R7, R8
|
||||
R1 = 0, R2, R3, R4, R5, R6, R7, R8 = 7
|
||||
} Registers;
|
||||
|
||||
typedef enum {
|
||||
ADD, SUB, JZ, INT, YLD, RET,
|
||||
CMP, CMPI, NOP, JMP, CALL, LODW, LAA, LODWI, JE, INC, DEC, LOADB,
|
||||
STOB, STOW, JG, JL, AND, XOR, OR, NOT, SHR, SHL, POP, PUSH, LODB,
|
||||
JMPA, JZA, JLA, JGA
|
||||
COPYA = 0x08, COPYAB = 0x10, COPYRA = 0x18, COPYRAB = 0x20, COPYRARA = 0x28, COPYRARAB = 0x30, COPY = 0x38, COPYB = 0x40, COPYI = 0xC0,
|
||||
CMP = 0x48, CMPI = 0x50, ADD = 0x58, SUB = 0x60, AND = 0x68, XOR = 0x70, OR = 0x78, NOT = 0x80, SHR = 0x88, SHL = 0x90,
|
||||
INC = 0x98, DEC = 0xA0, PUSH = 0xA8, POP = 0xB0,
|
||||
JMPI = 0xB8, JMP = 0x02, JZ = 0x03, JG = 0x04, JL = 0x05, NOP = 0x01, CALL = 0x06, RET = 0x07
|
||||
} Mnemonic;
|
||||
|
||||
typedef enum {
|
||||
NoParameter = 1,
|
||||
ConstantParameter = 2,
|
||||
AddressParameter = 4,
|
||||
RegisterParameter = 8,
|
||||
UnresolvedParameter = 16
|
||||
} OpcodeParameter;
|
||||
|
||||
typedef struct {
|
||||
OpcodeParameter ParameterType;
|
||||
OpcodeParameter InterpretedAs;
|
||||
|
||||
union {
|
||||
int Number; //ConstanrParam
|
||||
Registers Register; //Register param
|
||||
char* Symbol; //Symbol* Symbol; //Address param
|
||||
} Value;
|
||||
} Parameter;
|
||||
|
||||
typedef struct {
|
||||
Mnemonic Mnemonic;
|
||||
Parameter* ParameterOne;
|
||||
Parameter* ParameterTwo;
|
||||
} Instruction;
|
||||
|
||||
Instruction* CreateInstruction(Mnemonic mnemonic);
|
||||
Parameter* CreateParameter(OpcodeParameter parameterType);
|
||||
void FreeInstruction(Instruction* instruction);
|
||||
int IsOpcode(const char*, Mnemonic*);
|
||||
int IsRegister(const char*, Registers*);
|
||||
void ExpectParameters(Mnemonic mnemonic, OpcodeParameter* paramOne, OpcodeParameter* paramTwo);
|
||||
void GetMnemonicText(Mnemonic mnemonic, char buffer[12]);
|
||||
void GetRegisterText(Registers reg, char buffer[3]);
|
||||
unsigned char GetInstructionMask(Mnemonic type);
|
||||
|
||||
+33
-69
@@ -7,65 +7,43 @@
|
||||
struct _instruction {
|
||||
char* Name;
|
||||
Mnemonic Mnemonic;
|
||||
OpcodeParameter ParameterOne;
|
||||
OpcodeParameter ParameterTwo;
|
||||
};
|
||||
|
||||
struct _instruction instructions[OPCODECOUNT] = {
|
||||
{ "add", ADD, RegisterParameter, RegisterParameter },
|
||||
{ "sub", SUB, RegisterParameter, RegisterParameter },//, Reg, Reg | Constant },
|
||||
{ "jz", JZ, AddressParameter, NoParameter },//, Address, None },
|
||||
{ "yld", YLD, NoParameter, NoParameter },//, None, None },
|
||||
{ "cmp", CMP, RegisterParameter, RegisterParameter },//, Reg, Reg | Constant },
|
||||
{ "cmpi", CMPI, RegisterParameter, ConstantParameter },
|
||||
{ "inc", INC, RegisterParameter, NoParameter },//, Constant | Reg, None},
|
||||
{ "dec", DEC, RegisterParameter, NoParameter },//, None, None},
|
||||
{ "nop", NOP, NoParameter, NoParameter },//, None, None},
|
||||
{ "jmp", JMP, AddressParameter, NoParameter },//, Address, None},
|
||||
{ "call", CALL, AddressParameter, NoParameter },//, Address, None}
|
||||
{ "lodwi", LODWI, RegisterParameter, ConstantParameter },
|
||||
{ "je", JE, AddressParameter, NoParameter },
|
||||
{ "stob", STOB, RegisterParameter, AddressParameter },
|
||||
{ "stow", STOW, RegisterParameter, AddressParameter },
|
||||
{ "laa", LAA, RegisterParameter, AddressParameter },
|
||||
{ "lodw", LODW, RegisterParameter, RegisterParameter },
|
||||
{ "jmp", JMP, AddressParameter, NoParameter },
|
||||
{ "jg", JG, AddressParameter, NoParameter },
|
||||
{ "jl", JL, AddressParameter, NoParameter },
|
||||
{ "and", AND, RegisterParameter, RegisterParameter },
|
||||
{ "xor", XOR, RegisterParameter, RegisterParameter },
|
||||
{ "or", OR, RegisterParameter, RegisterParameter },
|
||||
{ "not", NOT, RegisterParameter, NoParameter },
|
||||
{ "shr", SHR, RegisterParameter, ConstantParameter },
|
||||
{ "shl", SHL, RegisterParameter, ConstantParameter },
|
||||
{ "nop", NOP, NoParameter, NoParameter },
|
||||
{ "pop", POP, RegisterParameter, NoParameter },
|
||||
{ "push", PUSH, RegisterParameter, NoParameter },
|
||||
{ "lodb", LODB, RegisterParameter, RegisterParameter},
|
||||
{ "jmpa", JMPA, RegisterParameter, NoParameter},
|
||||
{ "jza", JZA, RegisterParameter, NoParameter},
|
||||
{ "jla", JLA, RegisterParameter, NoParameter},
|
||||
{ "jga", JGA, RegisterParameter, NoParameter},
|
||||
struct _instruction instructions[31] = {
|
||||
{ "copya", COPYA },
|
||||
{ "copyab", COPYAB },
|
||||
{ "copyra", COPYRA },
|
||||
{ "copyrab", COPYRAB },
|
||||
{ "copyrara", COPYRARA },
|
||||
{ "copyrarab", COPYRARAB },
|
||||
{ "copy", COPY },
|
||||
{ "copyi", COPYI },
|
||||
{ "copyb", COPYB },
|
||||
{ "cmp", CMP },
|
||||
{ "cmpi", CMPI },
|
||||
{ "add", ADD },
|
||||
{ "sub", SUB },
|
||||
{ "and", AND },
|
||||
{ "xor", XOR },
|
||||
{ "or", OR },
|
||||
{ "not", NOT },
|
||||
{ "shr", SHR },
|
||||
{ "shl", SHL },
|
||||
{ "inc", INC },
|
||||
{ "dec", DEC },
|
||||
{ "push", PUSH },
|
||||
{ "pop", POP },
|
||||
{ "jmpi", JMPI },
|
||||
{ "jmp", JMP },
|
||||
{ "jz", JZ },
|
||||
{ "jg", JG },
|
||||
{ "jl", JL },
|
||||
{ "nop", NOP },
|
||||
{ "call", CALL },
|
||||
{ "ret", RET }
|
||||
//yld
|
||||
};
|
||||
|
||||
void ExpectParameters(Mnemonic mnemonic, OpcodeParameter* paramOne, OpcodeParameter* paramTwo) {
|
||||
*paramOne = NoParameter;
|
||||
*paramTwo = NoParameter;
|
||||
|
||||
for (int i = 0; i < OPCODECOUNT; i++) {
|
||||
struct _instruction ins = instructions[i];
|
||||
|
||||
if (ins.Mnemonic == mnemonic) {
|
||||
*paramOne = ins.ParameterOne;
|
||||
*paramTwo = ins.ParameterTwo;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "[Warning] Could not find mnemonic (%d) when looking for parameters.\n", mnemonic);
|
||||
}
|
||||
|
||||
Instruction* CreateInstruction(Mnemonic mnemonic) {
|
||||
Instruction* instruction = calloc(1, sizeof(Instruction));
|
||||
|
||||
@@ -80,20 +58,6 @@ Instruction* CreateInstruction(Mnemonic mnemonic) {
|
||||
return instruction;
|
||||
}
|
||||
|
||||
Parameter* CreateParameter(OpcodeParameter parameterType) {
|
||||
Parameter* param = calloc(1, sizeof(Parameter));
|
||||
|
||||
if (!param) {
|
||||
fprintf(stderr, "Failed to calloc room for a Parameter. %s,\n", strerror(errno));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
param->ParameterType = parameterType;
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
void FreeInstruction(Instruction* instruction) {
|
||||
if (!instruction) return;
|
||||
|
||||
|
||||
+34
-31
@@ -130,42 +130,42 @@ void HandleAssemblerDirective() {
|
||||
|
||||
if (PeekToken()->Class == NumberClass) {
|
||||
directive->Class = MnemonicClass;
|
||||
directive->Value.Mnemonic = LODWI;
|
||||
directive->Lemexe = "LODWI";
|
||||
directive->Value.Mnemonic = COPYI;
|
||||
directive->Lemexe = "copyi";
|
||||
AdvanceParser(); //Number, register or identifier
|
||||
}
|
||||
else if (PeekToken()->Class == RegisterClass) {
|
||||
directive->Class = MnemonicClass;
|
||||
directive->Value.Mnemonic = LODW;
|
||||
directive->Lemexe = "LODW";
|
||||
directive->Value.Mnemonic = COPY;
|
||||
directive->Lemexe = "copy";
|
||||
AdvanceParser(); //Number, register or identifier
|
||||
}
|
||||
else {
|
||||
ExpectIdentifier(0, ForwardParser);
|
||||
|
||||
directive->Class = MnemonicClass;
|
||||
directive->Value.Mnemonic = LAA;
|
||||
directive->Lemexe = "LAA";
|
||||
directive->Value.Mnemonic = COPYA;
|
||||
directive->Lemexe = "copya";
|
||||
}
|
||||
}
|
||||
else if (reg->Class == DirectiveClass) {
|
||||
if (reg->Value.Directive != Byte) {
|
||||
fprintf(stderr, "[Line %d] Syntax error, expected keyword 'byte'.\n", reg->LineNumber);
|
||||
exit(3);
|
||||
}
|
||||
// else if (reg->Class == DirectiveClass) {
|
||||
// if (reg->Value.Directive != Byte) {
|
||||
// fprintf(stderr, "[Line %d] Syntax error, expected keyword 'byte'.\n", reg->LineNumber);
|
||||
// exit(3);
|
||||
// }
|
||||
|
||||
RemoveCurrentToken(); //byte
|
||||
// RemoveCurrentToken(); //byte
|
||||
|
||||
ExpectRegister();
|
||||
// ExpectRegister();
|
||||
|
||||
ExpectPuncuation(Comma, ForwardParser);
|
||||
// ExpectPuncuation(Comma, ForwardParser);
|
||||
|
||||
ExpectRegister();
|
||||
// ExpectRegister();
|
||||
|
||||
directive->Class = MnemonicClass;
|
||||
directive->Value.Mnemonic = LODB;
|
||||
directive->Lemexe = "LODB";
|
||||
}
|
||||
// directive->Class = MnemonicClass;
|
||||
// directive->Value.Mnemonic = LODB;
|
||||
// directive->Lemexe = "LODB";
|
||||
// }
|
||||
|
||||
ExpectLineEndOrFileEnd(ForwardParser);
|
||||
}
|
||||
@@ -180,9 +180,9 @@ void HandleAssemblerDirective() {
|
||||
if (next->Class != DirectiveClass) {
|
||||
//If the token after the current one is invalid then the expect function ahead will exit, so we can
|
||||
//go ahead and change the STORE directive into a proper opcode here.
|
||||
directive->Value.Mnemonic = STOW;
|
||||
directive->Value.Mnemonic = COPY;
|
||||
directive->Class = MnemonicClass;
|
||||
directive->Lemexe = "STOW";
|
||||
directive->Lemexe = "copy";
|
||||
}
|
||||
else {
|
||||
if (next->Value.Directive != Byte) {
|
||||
@@ -192,9 +192,9 @@ void HandleAssemblerDirective() {
|
||||
|
||||
RemoveCurrentToken(); //Remove byte modifier token.
|
||||
|
||||
directive->Value.Mnemonic = STOB;
|
||||
directive->Value.Mnemonic = COPYB;
|
||||
directive->Class = MnemonicClass;
|
||||
directive->Lemexe = "STOB";
|
||||
directive->Lemexe = "copyb";
|
||||
}
|
||||
|
||||
ExpectRegister();
|
||||
@@ -272,11 +272,14 @@ void HandleOpcode(void) {
|
||||
{
|
||||
Token* arg = PeekToken();
|
||||
|
||||
opcode->Value.Mnemonic = JMPI;
|
||||
opcode->Lemexe = "jmpi";
|
||||
|
||||
if (arg->Class == IdentifierClass) {
|
||||
ExpectIdentifier(0, ForwardParser);
|
||||
|
||||
opcode->Value.Mnemonic = JMPA;
|
||||
opcode->Lemexe = "JMPA";
|
||||
opcode->Value.Mnemonic = JMP;
|
||||
opcode->Lemexe = "jmp";
|
||||
}
|
||||
else ExpectRegister();
|
||||
}
|
||||
@@ -288,8 +291,8 @@ void HandleOpcode(void) {
|
||||
if (arg->Class == IdentifierClass) {
|
||||
ExpectIdentifier(0, ForwardParser);
|
||||
|
||||
opcode->Value.Mnemonic = JZA;
|
||||
opcode->Lemexe = "JZA";
|
||||
opcode->Value.Mnemonic = JZ;
|
||||
opcode->Lemexe = "jz";
|
||||
}
|
||||
else ExpectRegister();
|
||||
}
|
||||
@@ -301,8 +304,8 @@ void HandleOpcode(void) {
|
||||
if (arg->Class == IdentifierClass) {
|
||||
ExpectIdentifier(0, ForwardParser);
|
||||
|
||||
opcode->Value.Mnemonic = JGA;
|
||||
opcode->Lemexe = "JGA";
|
||||
opcode->Value.Mnemonic = JG;
|
||||
opcode->Lemexe = "jg";
|
||||
}
|
||||
else ExpectRegister();
|
||||
}
|
||||
@@ -314,8 +317,8 @@ void HandleOpcode(void) {
|
||||
if (arg->Class == IdentifierClass) {
|
||||
ExpectIdentifier(0, ForwardParser);
|
||||
|
||||
opcode->Value.Mnemonic = JLA;
|
||||
opcode->Lemexe = "JLA";
|
||||
opcode->Value.Mnemonic = JL;
|
||||
opcode->Lemexe = "jl";
|
||||
}
|
||||
else ExpectRegister();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user