From 097125f53483a3ef8b53d67fbd2455b90e2c7ad7 Mon Sep 17 00:00:00 2001 From: txiong000 Date: Mon, 4 Mar 2019 14:01:28 -0600 Subject: [PATCH 1/8] init commit Comp architect Toua --- ls8/cpu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ls8/cpu.h b/ls8/cpu.h index 1b87668c..d651b4b6 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -6,7 +6,9 @@ struct cpu { // TODO // PC // registers (array) + char **registers; // ram (array) + char **ram; }; // Instructions From 6fb34acaf04e110d3950209e5764a3c3c85fa088 Mon Sep 17 00:00:00 2001 From: txiong000 Date: Mon, 4 Mar 2019 16:30:02 -0600 Subject: [PATCH 2/8] implemented struct --- ls8/cpu.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ls8/cpu.h b/ls8/cpu.h index d651b4b6..536f32ed 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -2,14 +2,15 @@ #define _CPU_H_ // Holds all information about the CPU -struct cpu { +typedef struct cpu { // TODO // PC + unsigned int PC; // registers (array) - char **registers; + unsigned char registers[6]; // ram (array) - char **ram; -}; + unsigned char ram[256]; +} CPU; // Instructions From 05146898c2dc067ef2ab5f6ae1e794f51f52a61f Mon Sep 17 00:00:00 2001 From: txiong000 Date: Mon, 4 Mar 2019 16:45:41 -0600 Subject: [PATCH 3/8] cpu ram read and cpu ram write finish --- ls8/cpu.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index 734a8f52..d00f3f14 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -3,6 +3,18 @@ /** * Load the binary bytes from a .ls8 source file into a RAM array */ + +unsigned char cpu_ram_read(struct cpu *cpu, unsigned char mem) +{ + return cpu->ram[mem]; +} + +void cpu_ram_write(struct cpu *cpu, unsigned char mem, unsigned char mdr) +{ + cpu->ram[mem] = mdr; +} + + void cpu_load(struct cpu *cpu) { const int DATA_LEN = 6; @@ -61,6 +73,8 @@ void cpu_run(struct cpu *cpu) void cpu_init(struct cpu *cpu) { // TODO: Initialize the PC and other special registers - + + + // TODO: Zero registers and RAM } From 57b464c8bd16a323ffd11d7d86c83d611727f425 Mon Sep 17 00:00:00 2001 From: txiong000 Date: Mon, 4 Mar 2019 17:08:45 -0600 Subject: [PATCH 4/8] implement HTL, LDI, PRN --- ls8/cpu.c | 24 +++++++++++++++++++++++- ls8/cpu.h | 8 +++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index d00f3f14..d26b73f2 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -57,11 +57,30 @@ 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 + unsigned char IR, operandA, operandB; while (running) { // TODO // 1. Get the value of the current instruction (in address PC). + IR = cpu_ram_read(cpu, cpu->PC); + operandA = cpu_ram_read(cpu, cpu->PC+1); + operandB = cpu_ram_read(cpu, cpu->PC+1); // 2. switch() over it to decide on a course of action. + switch (IR) { + case LDI: + cpu->registers[operandA] = operandB; + cpu->PC+=3; + break; + case PRN: + printf("%d\n", cpu->registers[operandA]); + cpu->PC+=2; + break; + case HTL: + running = 0; + cpu->PC+=1; + break + } + // 3. Do whatever the instruction should do according to the spec. // 4. Move the PC to the next instruction. } @@ -73,8 +92,11 @@ void cpu_run(struct cpu *cpu) void cpu_init(struct cpu *cpu) { // TODO: Initialize the PC and other special registers - + cpu->PC = 0; + // TODO: Zero registers and RAM + memset(cpu->ram, 0, sizeof cpu->ram); + memset(cpu->registers, 0, sizeof cpu->registers); } diff --git a/ls8/cpu.h b/ls8/cpu.h index 536f32ed..13b76904 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -2,15 +2,15 @@ #define _CPU_H_ // Holds all information about the CPU -typedef struct cpu { +struct cpu { // TODO // PC - unsigned int PC; + unsigned char PC; // registers (array) unsigned char registers[6]; // ram (array) unsigned char ram[256]; -} CPU; +}; // Instructions @@ -18,6 +18,8 @@ typedef struct cpu { // literals should be used. #define LDI 0b10000010 +#define PRN 0b01000111 +#define HTL 0b00000001 // TODO: more instructions here. These can be used in cpu_run(). // Function declarations From bcd0518aafe912f49edc5a1ab8ccd07e5160b455 Mon Sep 17 00:00:00 2001 From: txiong000 Date: Tue, 5 Mar 2019 16:59:21 -0600 Subject: [PATCH 5/8] un-hardcode and cpu_load complete --- ls8/cpu.c | 87 ++++++++++++++++++++++++++++++++++++------------------- ls8/cpu.h | 9 ++++-- ls8/ls8.c | 12 ++++++-- 3 files changed, 74 insertions(+), 34 deletions(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index d26b73f2..dbda5f45 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -1,47 +1,62 @@ #include "cpu.h" +#include +#include +#include /** * Load the binary bytes from a .ls8 source file into a RAM array */ -unsigned char cpu_ram_read(struct cpu *cpu, unsigned char mem) +#define DATA_LEN 6 + +unsigned char cpu_ram_read(struct cpu *cpu, unsigned mar) { - return cpu->ram[mem]; + return cpu->ram[mar]; } -void cpu_ram_write(struct cpu *cpu, unsigned char mem, unsigned char mdr) +void cpu_ram_write(struct cpu *cpu, unsigned char mar, unsigned char mdr) { - cpu->ram[mem] = mdr; + cpu->ram[mar] = mdr; } -void cpu_load(struct cpu *cpu) +void cpu_load(struct cpu *cpu, char *filename) { - const int DATA_LEN = 6; - char data[DATA_LEN] = { - // From print8.ls8 - 0b10000010, // LDI R0,8 - 0b00000000, - 0b00001000, - 0b01000111, // PRN R0 - 0b00000000, - 0b00000001 // HLT - }; + + FILE *fp = fopen(filename, "r"); + + if(fp == NULL) { + fprintf(stderr, "ls8: error opening file: %s\n", filename); + exit(1); + } + + char buff[8192]; int address = 0; - for (int i = 0; i < DATA_LEN; i++) { - cpu->ram[address++] = data[i]; + while (fgets(buff, sizeof buff, fp) != NULL) { + unsigned char val = strtoul(buff, NULL, 2); + cpu_ram_write(cpu, address++, val); } + + fclose(fp); + + } + + + // TODO: Replace this with something less hard-coded -} + /** * ALU */ void alu(struct cpu *cpu, enum alu_op op, unsigned char regA, unsigned char regB) { + (void)cpu; + (void)regA; + (void)regB; switch (op) { case ALU_MUL: // TODO @@ -51,6 +66,8 @@ void alu(struct cpu *cpu, enum alu_op op, unsigned char regA, unsigned char regB } } + + /** * Run the CPU */ @@ -59,31 +76,38 @@ void cpu_run(struct cpu *cpu) int running = 1; // True until we get a HLT instruction unsigned char IR, operandA, operandB; + while (running) { // TODO // 1. Get the value of the current instruction (in address PC). IR = cpu_ram_read(cpu, cpu->PC); operandA = cpu_ram_read(cpu, cpu->PC+1); - operandB = cpu_ram_read(cpu, cpu->PC+1); + operandB = cpu_ram_read(cpu, cpu->PC+2); + + // 2. switch() over it to decide on a course of action. switch (IR) { case LDI: cpu->registers[operandA] = operandB; - cpu->PC+=3; + cpu->PC += 3; break; case PRN: printf("%d\n", cpu->registers[operandA]); - cpu->PC+=2; + cpu->PC += 2; break; case HTL: running = 0; - cpu->PC+=1; - break - } + cpu->PC += 1; + break; + default: + printf("Unexpected instruction 0x%02X at 0x%02X\n", IR, cpu->PC); + exit(1); + } + } + // 3. Do whatever the instruction should do according to the spec. // 4. Move the PC to the next instruction. - } } /** @@ -92,11 +116,14 @@ void cpu_run(struct cpu *cpu) void cpu_init(struct cpu *cpu) { // TODO: Initialize the PC and other special registers + for (int i = 0; i < 6; i++) + { + cpu->registers[i] = 0; + } cpu->PC = 0; - - - + cpu->FL = 0; + cpu->registers[7] = 0xF4; // TODO: Zero registers and RAM - memset(cpu->ram, 0, sizeof cpu->ram); - memset(cpu->registers, 0, sizeof cpu->registers); + memset(cpu->ram, 0, sizeof(cpu->ram)); + } diff --git a/ls8/cpu.h b/ls8/cpu.h index 13b76904..0aa8739c 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -6,12 +6,17 @@ struct cpu { // TODO // PC unsigned char PC; + unsigned char FL; // registers (array) - unsigned char registers[6]; + unsigned char registers[8]; // ram (array) unsigned char ram[256]; }; +enum alu_op { + ALU_MUL +}; + // Instructions // These use binary literals. If these aren't available with your compiler, hex @@ -24,7 +29,7 @@ struct cpu { // Function declarations -extern void cpu_load(struct cpu *cpu); +extern void cpu_load(struct cpu *cpu, char *filename); extern void cpu_init(struct cpu *cpu); extern void cpu_run(struct cpu *cpu); diff --git a/ls8/ls8.c b/ls8/ls8.c index d24578ee..b5e0d9f1 100644 --- a/ls8/ls8.c +++ b/ls8/ls8.c @@ -1,15 +1,23 @@ #include #include "cpu.h" + /** * Main */ -int main(void) +int main(int argc, char **argv) { struct cpu cpu; + if (argc !=2 ) { + fprintf(stderr, "usage: ls8 filename\n"); + return 1; + } + + char *filename = argv[1]; + cpu_init(&cpu); - cpu_load(&cpu); + cpu_load(&cpu, filename); cpu_run(&cpu); return 0; From ac04506e2c658b9a32407d5da71cf8ae9a18e00d Mon Sep 17 00:00:00 2001 From: txiong000 Date: Wed, 6 Mar 2019 14:31:43 -0600 Subject: [PATCH 6/8] mul complete --- ls8/cpu.c | 39 ++++++++++++++++++++++++++++++++++----- ls8/cpu.h | 8 +++++++- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index dbda5f45..267eba9b 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -8,17 +8,35 @@ */ #define DATA_LEN 6 +#define SP 7 unsigned char cpu_ram_read(struct cpu *cpu, unsigned mar) { return cpu->ram[mar]; } + + + void cpu_ram_write(struct cpu *cpu, unsigned char mar, unsigned char mdr) { cpu->ram[mar] = mdr; } +void push(struct cpu *cpu, unsigned char value) +{ + cpu->registers[SP]--; + cpu_ram_write(cpu, cpu->registers[SP], value); +} + +unsigned char pop(struct cpu *cpu) +{ + unsigned char value = cpu_ram_read(cpu, cpu->registers[SP]); + + cpu->registers[SP]++; + return value; +} + void cpu_load(struct cpu *cpu, char *filename) { @@ -54,14 +72,14 @@ void cpu_load(struct cpu *cpu, char *filename) */ void alu(struct cpu *cpu, enum alu_op op, unsigned char regA, unsigned char regB) { - (void)cpu; - (void)regA; - (void)regB; + + unsigned char num_A = cpu->registers[regA]; + unsigned char num_B = cpu->registers[regB]; + switch (op) { case ALU_MUL: - // TODO + cpu->registers[regA] = num_A * num_B; break; - // TODO: implement more ALU ops } } @@ -91,10 +109,21 @@ void cpu_run(struct cpu *cpu) cpu->registers[operandA] = operandB; cpu->PC += 3; break; + case MUL: + alu(cpu, ALU_MUL, operandA, operandB); + cpu->PC += 3; + break; case PRN: printf("%d\n", cpu->registers[operandA]); cpu->PC += 2; break; + case PUSH: + push(cpu, cpu->registers[operandA]); + cpu->PC += 2; + break; + case POP: + cpu->registers[operandA] = pop(cpu); + cpu->PC += 2; case HTL: running = 0; cpu->PC += 1; diff --git a/ls8/cpu.h b/ls8/cpu.h index 0aa8739c..866aa090 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -14,7 +14,8 @@ struct cpu { }; enum alu_op { - ALU_MUL + ALU_MUL, + }; // Instructions @@ -25,6 +26,11 @@ enum alu_op { #define LDI 0b10000010 #define PRN 0b01000111 #define HTL 0b00000001 +#define MUL 0b10100010 +#define PUSH 0b01000101 +#define POP 0b01000110 + + // TODO: more instructions here. These can be used in cpu_run(). // Function declarations From bb80a55a174c2e37e9f4ce2c2b2d51c7a8dd13e5 Mon Sep 17 00:00:00 2001 From: txiong000 Date: Wed, 6 Mar 2019 15:15:52 -0600 Subject: [PATCH 7/8] stack complete --- ls8/cpu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ls8/cpu.c b/ls8/cpu.c index 267eba9b..b410e736 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -113,6 +113,10 @@ void cpu_run(struct cpu *cpu) alu(cpu, ALU_MUL, operandA, operandB); cpu->PC += 3; break; + case POP: + cpu->registers[operandA] = pop(cpu); + cpu->PC += 2; + break; case PRN: printf("%d\n", cpu->registers[operandA]); cpu->PC += 2; @@ -121,9 +125,6 @@ void cpu_run(struct cpu *cpu) push(cpu, cpu->registers[operandA]); cpu->PC += 2; break; - case POP: - cpu->registers[operandA] = pop(cpu); - cpu->PC += 2; case HTL: running = 0; cpu->PC += 1; From b6b9e548347f46e0535aa5e04446272e4ca375ea Mon Sep 17 00:00:00 2001 From: txiong000 Date: Wed, 6 Mar 2019 17:24:00 -0600 Subject: [PATCH 8/8] call and ret finsh --- ls8/cpu.c | 13 +++++++++++++ ls8/cpu.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/ls8/cpu.c b/ls8/cpu.c index b410e736..5e85a904 100644 --- a/ls8/cpu.c +++ b/ls8/cpu.c @@ -80,6 +80,9 @@ void alu(struct cpu *cpu, enum alu_op op, unsigned char regA, unsigned char regB case ALU_MUL: cpu->registers[regA] = num_A * num_B; break; + case ALU_ADD: + cpu->registers[regA] = num_A + num_B; + break; // TODO: implement more ALU ops } } @@ -113,6 +116,9 @@ void cpu_run(struct cpu *cpu) alu(cpu, ALU_MUL, operandA, operandB); cpu->PC += 3; break; + case ADD: + alu(cpu, ALU_ADD, operandA, operandB); + cpu->PC += 3; case POP: cpu->registers[operandA] = pop(cpu); cpu->PC += 2; @@ -125,6 +131,13 @@ void cpu_run(struct cpu *cpu) push(cpu, cpu->registers[operandA]); cpu->PC += 2; break; + case CALL: + push(cpu, (cpu->PC + 2)); + cpu->PC = cpu->registers[operandA]; + break; + case RET: + cpu->PC = pop(cpu); + break; case HTL: running = 0; cpu->PC += 1; diff --git a/ls8/cpu.h b/ls8/cpu.h index 866aa090..7fd00977 100644 --- a/ls8/cpu.h +++ b/ls8/cpu.h @@ -15,6 +15,7 @@ struct cpu { enum alu_op { ALU_MUL, + ALU_ADD }; @@ -29,6 +30,7 @@ enum alu_op { #define MUL 0b10100010 #define PUSH 0b01000101 #define POP 0b01000110 +#define ADD 0b10100000 // TODO: more instructions here. These can be used in cpu_run().