-
Notifications
You must be signed in to change notification settings - Fork 6
luis #215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
luis #215
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "workbench.colorCustomizations": { | ||
| "activityBar.background": "#033615", | ||
| "titleBar.activeBackground": "#044B1D", | ||
| "titleBar.activeForeground": "#F0FEF5" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,41 +1,72 @@ | ||
| #include "cpu.h" | ||
| #include <stdio.h> | ||
| #include <string.h> | ||
| #include <stdlib.h> | ||
|
|
||
| #define DATA_LEN 6 | ||
|
|
||
| unsigned char cpu_ram_read(struct cpu *cpu, unsigned char MAR) | ||
| { | ||
| return cpu->ram[MAR]; | ||
| } | ||
|
|
||
| void cpu_ram_write(struct cpu *cpu, unsigned char MAR, unsigned char MDR) | ||
| { | ||
| cpu->ram[MAR] = MDR; | ||
| } | ||
|
|
||
| /** | ||
| * Load the binary bytes from a .ls8 source file into a RAM array | ||
| */ | ||
| void cpu_load(struct cpu *cpu) | ||
| void cpu_load(struct cpu *cpu, char *filename) | ||
| { | ||
| char data[DATA_LEN] = { | ||
| // From print8.ls8 | ||
| 0b10000010, // LDI R0,8 | ||
| 0b00000000, | ||
| 0b00001000, | ||
| 0b01000111, // PRN R0 | ||
| 0b00000000, | ||
| 0b00000001 // HLT | ||
| }; | ||
|
|
||
| int address = 0; | ||
|
|
||
| for (int i = 0; i < DATA_LEN; i++) { | ||
| cpu->ram[address++] = data[i]; | ||
| //Init the file | ||
| FILE *fp = fopen(filename, "r"); | ||
|
|
||
| char line[1024]; | ||
|
|
||
| unsigned char mar = 0x00; | ||
|
|
||
| //Check if the file exits: | ||
| if (fp == NULL) | ||
| { | ||
| fprintf(stderr, "error opening file %s\n", filename); | ||
| exit(1); | ||
| } | ||
|
|
||
| // TODO: Replace this with something less hard-coded | ||
| //While there's lines in the file... | ||
| while (fgets(line, sizeof line, fp) != NULL) | ||
| { | ||
| char *endptr; | ||
| unsigned char machine_code = strtoul(line, &endptr, 2); | ||
|
|
||
| if (endptr == line) | ||
| { | ||
| //we got no numbers | ||
| continue; | ||
| } | ||
|
|
||
| //Write it into Memory | ||
| cpu_ram_write(cpu, mar++, machine_code); | ||
| } | ||
|
|
||
| fclose(fp); | ||
| } | ||
|
|
||
| /** | ||
| * ALU | ||
| */ | ||
| void alu(struct cpu *cpu, enum alu_op op, unsigned char regA, unsigned char regB) | ||
| { | ||
| switch (op) { | ||
| case ALU_MUL: | ||
| // TODO | ||
| break; | ||
| switch (op) | ||
| { | ||
| case ALU_MUL: | ||
| cpu->reg[regA] *= cpu->reg[regB]; | ||
| break; | ||
|
|
||
| case ALU_ADD: | ||
| cpu->reg[regA] += cpu->reg[regB]; | ||
| break; | ||
| // TODO: implement more ALU ops | ||
| } | ||
| } | ||
|
|
@@ -45,16 +76,83 @@ void alu(struct cpu *cpu, enum alu_op op, unsigned char regA, unsigned char regB | |
| */ | ||
| void cpu_run(struct cpu *cpu) | ||
| { | ||
| int running = 1; // True until we get a HLT instruction | ||
|
|
||
| while (running) { | ||
| // TODO | ||
| // 1. Get the value of the current instruction (in address PC). | ||
| // 2. Figure out how many operands this next instruction requires | ||
| // 3. Get the appropriate value(s) of the operands following this instruction | ||
| // 4. switch() over it to decide on a course of action. | ||
| // 5. Do whatever the instruction should do according to the spec. | ||
| // 6. Move the PC to the next instruction. | ||
| int running = 1; | ||
|
|
||
| unsigned char IR; | ||
|
|
||
| while (running) | ||
| { | ||
| IR = cpu_ram_read(cpu, cpu->PC); | ||
| unsigned char operandA = cpu_ram_read(cpu, (cpu->PC + 1) & 0xFF); | ||
| unsigned char operandB = cpu_ram_read(cpu, (cpu->PC + 2) & 0xFF); | ||
|
|
||
| int add_to_pc = (IR >> 6) + 1; | ||
| switch (IR) | ||
| { | ||
| case LDI: | ||
| cpu->reg[operandA] = operandB; | ||
| break; | ||
| case MUL: | ||
| alu(cpu, ALU_MUL, operandA, operandB); | ||
| break; | ||
|
|
||
| case ADD: | ||
| alu(cpu, ALU_ADD, operandA, operandB); | ||
| break; | ||
|
|
||
| case PUSH: | ||
| cpu_ram_write(cpu, --cpu->reg[7], cpu->reg[operandA]); | ||
| break; | ||
|
|
||
| case POP: | ||
| cpu->reg[operandA] = cpu_ram_read(cpu, cpu->reg[7]++); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like that you're using |
||
| break; | ||
|
|
||
| case CALL: | ||
| cpu_ram_write(cpu, --cpu->reg[7], ++cpu->PC); | ||
| cpu->PC = cpu->reg[operandA]; | ||
| add_to_pc = 0; | ||
| break; | ||
| case RET: | ||
| cpu->PC = cpu_ram_read(cpu, cpu->reg[7]++); | ||
| break; | ||
| case CMP: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is actually an ALU operation. You can move it there if you want to. When looking at the operation codes, the third bit from the left is 1 if it is an ALU operation. |
||
| if (cpu->reg[operandA] == cpu->reg[operandB]) | ||
| { | ||
| cpu->flag_reg[0] = 1; | ||
| } | ||
| else if (cpu->reg[operandA] > cpu->reg[operandB]) | ||
| { | ||
| cpu->flag_reg[1] = 1; | ||
| } | ||
| else | ||
| { | ||
| cpu->flag_reg[2] = 1; | ||
| } | ||
| break; | ||
| case JMP: | ||
| cpu->PC = cpu->reg[operandA]; | ||
| add_to_pc = 0; | ||
| break; | ||
| case JEQ: | ||
| if (cpu->flag_reg[0] == 1) | ||
| { | ||
| cpu->PC = cpu->reg[operandA]; | ||
| add_to_pc = 0; | ||
| } | ||
| break; | ||
| case JNE: | ||
| if (cpu->flag_reg[0] == 0) | ||
| { | ||
| cpu->PC = cpu->reg[operandA]; | ||
| add_to_pc = 0; | ||
| } | ||
| break; | ||
| case HLT: | ||
| running = 0; | ||
| break; | ||
| } | ||
| cpu->PC += add_to_pc; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -63,5 +161,11 @@ void cpu_run(struct cpu *cpu) | |
| */ | ||
| void cpu_init(struct cpu *cpu) | ||
| { | ||
| // TODO: Initialize the PC and other special registers | ||
| } | ||
| cpu->PC = 0; | ||
|
|
||
| memset(cpu->ram, 0, sizeof(cpu->ram)); | ||
| memset(cpu->reg, 0, sizeof(cpu->reg)); | ||
| memset(cpu->flag_reg, 0, sizeof(cpu->flag_reg)); | ||
|
|
||
| cpu->reg[7] = 0b11110100; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These look good. What other operations could you add to the ALU?