diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..122b2db --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "ram.h": "c" + } +} \ No newline at end of file diff --git a/README.md b/README.md index bb518a6..a4466f9 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,32 @@ # r16 -| number | instruction | argument 1 | argument 2 | explanation | -|--------|-------------|------------|------------|---------------------------------------------------| -| 0x00 | HLT | | | halts the CPU | -| 0x01 | ADD | value 1 | value 2 | ACU = value 1 + value 2 | -| 0x02 | SUB | value 1 | value 2 | ACU = value 1 - value 2 | -| 0x03 | MUL | value 1 | value 2 | ACU = value 1 * value 2 | -| 0x04 | DIV | value 1 | value 2 | ACU = value 1 / value 2 | -| 0x05 | LBS | value | amount | ACU = value << amount | -| 0x06 | RBS | value | amount | ACU = value << amount | -| 0x07 | BAN | value 1 | value 2 | ACU = value 1 & value 2 | -| 0x08 | BOR | value 1 | value 2 | ACU = value 1 \ | -| 0x09 | BXO | value 1 | value 2 | ACU = value 1 ^ value 2 | -| 0x0A | BNO | value | | ACU = ~ value | -| 0x0B | PUS | value | | pushes value onto the stack | -| 0x0C | POP | | | pops a value from the stack and stores it in ACU | -| 0x0D | JMP | address | | jumps to address | -| 0x0E | JEQ | address | value | jumps to address, if value is equal to ACU | -| 0x0F | JNZ | address | value | jumps to address, if value is not zero | -| 0x10 | CAL | address | | pushes PC + 1 to the stack, then jumps to address | -| 0x11 | RET | | | pops value from stack and jumps to it | -| 0x12 | REG | int type | address | registers int type to address | -| 0x13 | INT | int type | | interrupts as int type | -| 0x14 | INP | | | inputs a character into ACU | -| 0x15 | OUT | value | | outputs value | -| 0x16 | DIN | location | | reads value from disk at location to ACU | -| 0x17 | DOT | location | value | writes value to disk at location | -| 0x18 | MOV | value 1 | value 2 | move value 2 to value 1 | +| number | instruction | argument 1 | argument 2 | fullname | explanation | +|-------:|:-----------:|------------|------------|----------------------|---------------------------------------------------| +| 0x00 | HLT | | | Halt | halts the CPU | +| 0x01 | ADD | value 1 | value 2 | Add | ACU = value 1 + value 2 | +| 0x02 | SUB | value 1 | value 2 | Subtract | ACU = value 1 - value 2 | +| 0x03 | MUL | value 1 | value 2 | Multiply | ACU = value 1 * value 2 | +| 0x04 | DIV | value 1 | value 2 | Divide | ACU = value 1 / value 2 | +| 0x05 | LBS | value | amount | Left Bit-Shift | ACU = value << amount | +| 0x06 | RBS | value | amount | Right Bit-Shift | ACU = value << amount | +| 0x07 | BAN | value 1 | value 2 | Bitwise And | ACU = value 1 & value 2 | +| 0x08 | BOR | value 1 | value 2 | Bitwise Or | ACU = value 1 \ | +| 0x09 | BXO | value 1 | value 2 | Bitwise Exclusive Or | ACU = value 1 ^ value 2 | +| 0x0A | BNO | value | | Bitwise Not | ACU = ~ value | +| 0x0B | PUS | value | | Push | pushes value onto the stack | +| 0x0C | POP | | | Pop | pops a value from the stack and stores it in ACU | +| 0x0D | JMP | address | | Jump | jumps to address | +| 0x0E | JEQ | address | value | Jump If Equal | jumps to address, if value is equal to ACU | +| 0x0F | JNZ | address | value | Jump If Not Zero | jumps to address, if value is not zero | +| 0x10 | CAL | address | | Call | pushes PC + 1 to the stack, then jumps to address | +| 0x11 | RET | | | Return | pops value from stack and jumps to it | +| 0x12 | REG | int type | address | Register Interrupt | registers int type to address | +| 0x13 | INT | int type | | Interrupt | interrupts as int type | +| 0x14 | INP | | | Input | inputs a character into ACU | +| 0x15 | OUT | value | | Output | outputs value | +| 0x16 | DIN | location | | Disk In | reads value from disk at location to ACU | +| 0x17 | DOT | location | value | Disk Out | writes value to disk at location | +| 0x18 | MOV | value 1 | value 2 | Move | move value 2 to value 1 | | Number | Register | Usage | |-------:|---------:|-----------------| diff --git a/build.sh b/build.sh index 9272b00..9b7b068 100755 --- a/build.sh +++ b/build.sh @@ -1,2 +1,2 @@ mkdir ./bin -clang -o ./bin/r16e ./emu/main.c ./emu/cpu/ram.c ./emu/cpu/register.c ./emu/cpu/stack.c ./lib/carg-parse/carg-parse.c \ No newline at end of file +clang -o ./bin/r16e ./emu/main.c ./emu/cpu/instruction.c ./emu/cpu/ram.c ./emu/cpu/register.c ./emu/cpu/stack.c ./lib/carg-parse/carg-parse.c \ No newline at end of file diff --git a/emu/cpu.c b/emu/cpu.c new file mode 100644 index 0000000..c952391 --- /dev/null +++ b/emu/cpu.c @@ -0,0 +1,14 @@ +#include "cpu.h" +#include + +void Run(r16_int entry) +{ + r16_int instruction, arg1, arg2; + + SetRegister(PC, entry); + + while (true) + { + + } +} \ No newline at end of file diff --git a/emu/cpu.h b/emu/cpu.h new file mode 100644 index 0000000..d1725bb --- /dev/null +++ b/emu/cpu.h @@ -0,0 +1,9 @@ +#ifndef EMU_CPU_H +#define EMU_CPU_H + +#include "cpu_const.h" +#include "cpu/ram.h" +#include "cpu/register.h" +#include "cpu/instruction.h" + +#endif \ No newline at end of file diff --git a/emu/cpu/instruction.c b/emu/cpu/instruction.c index e409636..4ebf50a 100644 --- a/emu/cpu/instruction.c +++ b/emu/cpu/instruction.c @@ -1,41 +1,122 @@ #include "./instruction.h" +#include +#include r16_int GetArgVal(ArgumentInfo argInfo, r16_int arg) { - + switch (argInfo) + { + case value: + return arg; + case valueInRegister: + return GetRegister((CpuRegisters)arg.u); + case valueInRam: + return GetValue(arg); + case pointerInRegister: + return GetValue(GetRegister((CpuRegisters)arg.u)); + } +} + +void GetAllArgVal(ArgumentInfo arg1Info, ArgumentInfo arg2Info, + r16_int arg1, r16_int arg2, + r16_int *arg1Out, r16_int *arg2Out) +{ + *arg1Out = GetArgVal(arg1Info, arg1); + *arg2Out = GetArgVal(arg2Info, arg2); } void ExecuteInstruction(CpuInstructions instruction, ArgumentInfo arg1Info, ArgumentInfo arg2Info, r16_int arg1, r16_int arg2) { + r16_int actArg1, actArg2; + switch (instruction) { case HLT: - printf("program halted\n"); + printf("\nprogram HALTED!\n"); exit(0); case ADD: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + SetRegister(ACU, (r16_int){ actArg1.s + actArg2.s }); + break; case SUB: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + SetRegister(ACU, (r16_int){ actArg1.s - actArg2.s }); + break; case MUL: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + SetRegister(ACU, (r16_int){ actArg1.s * actArg2.s }); + break; case DIV: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + SetRegister(ACU, (r16_int){ actArg1.s / actArg2.s }); + break; case LBS: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + SetRegister(ACU, (r16_int){ actArg1.s << actArg2.s }); + break; case RBS: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + SetRegister(ACU, (r16_int){ actArg1.s >> actArg2.s }); + break; case BAN: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + SetRegister(ACU, (r16_int){ actArg1.u & actArg2.u }); + break; case BOR: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + SetRegister(ACU, (r16_int){ actArg1.u | actArg2.u }); + break; case BXO: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + SetRegister(ACU, (r16_int){ actArg1.u ^ actArg2.u }); + break; case BNO: + SetRegister(ACU, (r16_int){ ~ GetArgVal(arg1Info, arg1).u }); + break; case PUS: + StackPush(GetArgVal(arg1Info, arg1)); + break; case POP: + SetRegister(ACU, StackPop()); + break; case JMP: + SetRegister(PC, GetArgVal(arg1Info, arg1)); + break; case JEQ: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + if (actArg2.u == GetRegister(ACU).u) + SetRegister(PC, actArg1); + break; case JNZ: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + if (actArg2.s != 0) + SetRegister(PC, actArg1); + break; case CAL: + StackPush(GetRegister(PC)); + SetRegister(PC, GetArgVal(arg1Info, arg1)); + break; case RET: - case REG: - case INT: + SetRegister(PC, StackPop()); + break; + case REG: // TODO + case INT: // TODO + fprintf(stderr, "INTS NOT IMPLEMENTED YET\n"); + exit(-1); case INP: + SetRegister(ACU, (r16_int){ getchar() }); + break; case OUT: - case DIN: - case DOT: + putchar((char)(GetArgVal(arg1Info, arg1).u)); + break; + case DIN: // TODO + case DOT: // TODO + fprintf(stderr, "DISK NOT IMPLEMENTED YET\n"); + exit(-1); case MOV: + GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); + SetValue(actArg1, actArg2); + break; } } \ No newline at end of file diff --git a/emu/cpu/instruction.h b/emu/cpu/instruction.h index 8cb3f5c..a3900a5 100644 --- a/emu/cpu/instruction.h +++ b/emu/cpu/instruction.h @@ -6,4 +6,7 @@ #include "./register.h" #include "./stack.h" +void ExecuteInstruction(CpuInstructions instruction, ArgumentInfo arg1Info, + ArgumentInfo arg2Info, r16_int arg1, r16_int arg2); + #endif \ No newline at end of file