diff --git a/ls8/cpu.c b/ls8/cpu.c index bdb1f506..9f864caf 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -8,18 +8,19 @@ void cpu_load(struct cpu *cpu) { char data[DATA_LEN] = { - // From print8.ls8 - 0b10000010, // LDI R0,8 - 0b00000000, - 0b00001000, - 0b01000111, // PRN R0 - 0b00000000, - 0b00000001 // HLT + // 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++) { + for (int i = 0; i < DATA_LEN; i++) + { cpu->ram[address++] = data[i]; } @@ -31,10 +32,11 @@ void cpu_load(struct cpu *cpu) */ 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: + // TODO + break; // TODO: implement more ALU ops } @@ -43,25 +45,92 @@ void alu(struct cpu *cpu, enum alu_op op, unsigned char regA, unsigned char regB /** * Run the CPU */ + +void push_to_stack(struct cpu *cpu, int val) +{ + cpu->reg[7]--; + cpu->ram[cpu->reg[7]] = val; +} +unsigned char cpu_pop(struct cpu *cpu) +{ + unsigned char val = cpu_ram_read(cpu, cpu->reg[7]); + cpu->reg[7]++; + return val; +} + void cpu_run(struct cpu *cpu) { int running = 1; // True until we get a HLT instruction - while (running) { + while (running) + { // TODO // 1. Get the value of the current instruction (in address PC). + unsigned char IR = cpu_ram_read(cpu, cpu->pc); // 2. Figure out how many operands this next instruction requires + //IR gives you the current instuction + //reading from the bitwise right shift will give you the number of operands: + unsigned char operandA = 0; + unsigned char operandB = 0; + unsigned int numOp = IR >> 6; + // 3. Get the appropriate value(s) of the operands following this instruction + if (numOp == 2) + { + unsigned char operandA = cpu_ram_read(cpu, (cpu->pc + 1) & 0xff); + unsigned char operandB = cpu_ram_read(cpu, (cpu->pc + 2) & 0xff); + } // 4. switch() over it to decide on a course of action. + switch (IR) + { + case LDI: + // change the value of reg @ operanA to operandB; + printf("%d\n", cpu->reg[operandB]); + cpu->reg[operandA] = operandB; + cpu->pc += 2; + printf("%d\n", cpu->reg[operandB]); + break; + case PRN: + cpu->pc += 2; + printf("%d\n", cpu->reg[operandA]); + break; + case HLT: + running = 0; + break; + default: + printf("Error"); + break; + } // 5. Do whatever the instruction should do according to the spec. // 6. Move the PC to the next instruction. } } +// ram functions +unsigned char cpu_ram_read(struct cpu *cpu, unsigned char index) +{ + return cpu->ram[index]; +} + +void cpu_ram_write(struct cpu *cpu, unsigned mar, unsigned char mdr) +{ + cpu->ram[mar] = mdr; +} + /** * Initialize a CPU struct */ void cpu_init(struct cpu *cpu) { // TODO: Initialize the PC and other special registers + for (int i = 0; i <= 6; i++) + { + cpu->reg[i] = 0; + } + + cpu->reg[7] = 0; + cpu->pc = 0; + + // set everything in ram to 0 + memset(cpu->ram, 0, sizeof cpu->ram); } diff --git a/ls8/cpu.h b/ls8/cpu.h index 46e49c44..6848838d 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -2,17 +2,22 @@ #define _CPU_H_ // Holds all information about the CPU -struct cpu { +struct cpu +{ // TODO // PC + unsigned int pc; // registers (array) + unsigned char reg[8]; // ram (array) + unsigned char ram[256]; }; // ALU operations -enum alu_op { - ALU_MUL - // Add more here +enum alu_op +{ + ALU_MUL + // Add more here }; // Instructions @@ -20,9 +25,9 @@ enum alu_op { // These use binary literals. If these aren't available with your compiler, hex // literals should be used. -#define LDI 0b10000010 -#define HLT 0b00000001 -#define PRN 0b01000111 +#define LDI 0b10000010 +#define HLT 0b00000001 +#define PRN 0b01000111 // TODO: more instructions here. These can be used in cpu_run(). // Function declarations @@ -31,4 +36,4 @@ extern void cpu_load(struct cpu *cpu); extern void cpu_init(struct cpu *cpu); extern void cpu_run(struct cpu *cpu); -#endif +#endif \ No newline at end of file