Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<!-- https://github.com/LambdaSchool/Computer-Architecture/pull/199 -->
# Computer Architecture

## Project
Expand All @@ -7,19 +8,19 @@
## Task List: add this to the first comment of your Pull Request

### Day 1: Get `print8.ls8` running
- [ ] Inventory what is here
- [ ] Implement `struct cpu` in `cpu.h`
- [ ] Add RAM functions `cpu_ram_read` and `cpu_ram_write`
- [ ] Implement `cpu_init()`
- [ ] Implement the core of `cpu_run()`
- [ ] Implement the `HLT` instruction handler
- [ ] Add the `LDI` instruction
- [ ] Add the `PRN` instruction
- [x] Inventory what is here
- [x] Implement `struct cpu` in `cpu.h`
- [x] Add RAM functions `cpu_ram_read` and `cpu_ram_write`
- [x] Implement `cpu_init()`
- [x] Implement the core of `cpu_run()`
- [x] Implement the `HLT` instruction handler
- [x] Add the `LDI` instruction
- [x] Add the `PRN` instruction

### Day 2: Add the ability to load files dynamically, get `mult.ls8` and `stack.ls8` running
- [ ] Un-hardcode the machine code
- [ ] Implement the `cpu_load` function to load an `.ls8` file given the filename passed in as an argument
- [ ] Implement a Multiply instruction and Print the result (run `mult8.ls8`)
- [x] Un-hardcode the machine code
- [x] Implement the `cpu_load` function to load an `.ls8` file given the filename passed in as an argument
- [x] Implement a Multiply instruction and Print the result (run `mult8.ls8`)
- [ ] Implement the System Stack and be able to run the `stack.ls8` program

### Day 3: Get `call.ls8` running
Expand Down
113 changes: 98 additions & 15 deletions ls8/cpu.c
Original file line number Diff line number Diff line change
@@ -1,45 +1,87 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cpu.h"

#define DATA_LEN 6

/**
* Load the binary bytes from a .ls8 source file into a RAM array
*/
void cpu_load(struct cpu *cpu)
void cpu_load(char *filename, struct cpu *cpu)
{
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];
// get the file | will get file path via argument later
// per guided demo
FILE *fp;
char line[1024];

int address = 0x00;

if((fp = fopen(filename, "r")) == NULL) {
fprintf(stderr, "Unable to open file %s\n", filename);
exit(2);
}

while (fgets(line, sizeof line, fp) != NULL) {
char *endpoint;
unsigned char value;

value = strtoul(line, &endpoint, 2);

if(endpoint == line) {
continue;
}

cpu->ram[address++] = value;

}

// TODO: Replace this with something less hard-coded
}

// MAR - memory address register | where does is go
// MDR - memory data register | what it is
void cpu_ram_write(struct cpu *cpu, unsigned char mar, unsigned char mdr) {
cpu->ram[mar] = mdr;
}

unsigned char cpu_ram_read(struct cpu *cpu, unsigned char mar) {
return cpu->ram[mar];
}

/**
* ALU
*/
void alu(struct cpu *cpu, enum alu_op op, unsigned char regA, unsigned char regB)
{
unsigned char *reg = cpu->reg;

// assign operands to values
unsigned char valueA = reg[regA];
unsigned char valueB = reg[regB];

switch (op) {
case ALU_MUL:
reg[regA] *= valueB;
// TODO
break;

// TODO: implement more ALU ops
}
}

void push_to_stack(struct cpu *cpu, int val) {
cpu->reg[7]--;
cpu->ram[cpu->reg[7]] = val;
}

int pop_from_stack(struct cpu *cpu) {
int val = cpu->ram[cpu->reg[7]];
cpu->reg[7]++;
return val;
}

/**
* Run the CPU
*/
Expand All @@ -50,10 +92,40 @@ void cpu_run(struct cpu *cpu)
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
// 3. Get the appropriate value(s) of the operands following this instruction
unsigned char operand0 = cpu_ram_read(cpu, cpu->PC + 1);
unsigned char operand1 = cpu_ram_read(cpu, cpu->PC + 2);
// 4. switch() over it to decide on a course of action.
// 5. Do whatever the instruction should do according to the spec.
switch (IR) {
// BE SURE CASE IS SAVED AS BINARY LITERALS IN CPU.H FILE
case LDI:
cpu->reg[operand0] = operand1;
cpu->PC += 3;
break;
case PRN:
printf("%d\n", cpu->reg[operand0]);
cpu->PC += 2;
break;
case HLT:
cpu->PC++;
return 0;
case MUL:
alu(cpu, ALU_MUL, operand0, operand1);
cpu->PC += 3;
break;
case PUSH:
break;
case POP:
break;

default:
// beej printed IR & cpu->PC
printf("unexpected command\n");
exit(1);
}
// 6. Move the PC to the next instruction.
}
}
Expand All @@ -64,4 +136,15 @@ void cpu_run(struct cpu *cpu)
void cpu_init(struct cpu *cpu)
{
// TODO: Initialize the PC and other special registers
// set r0-r6 to clear to 0
for (int i = 0; i < 7; i++) {
cpu->reg[i] = 0;
}
// set r7 to 0xF4
cpu->reg[7] = 0xF4;
// set PC to 0 | no flags yet
cpu->PC = 0;
// set ram to 0
memset(cpu->ram, 0, sizeof cpu->ram);

}
8 changes: 7 additions & 1 deletion ls8/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
struct cpu {
// TODO
// PC
unsigned char PC;
// registers (array)
unsigned char reg[8];
// ram (array)
unsigned char ram[256];
};

// ALU operations
Expand All @@ -23,11 +26,14 @@ enum alu_op {
#define LDI 0b10000010
#define HLT 0b00000001
#define PRN 0b01000111
#define MUL 0b10100010
#define PUSH 0b01000101
#define POP 0b01000110
// TODO: more instructions here. These can be used in cpu_run().

// Function declarations

extern void cpu_load(struct cpu *cpu);
extern void cpu_load(char *filename, struct cpu *cpu);
extern void cpu_init(struct cpu *cpu);
extern void cpu_run(struct cpu *cpu);

Expand Down
8 changes: 6 additions & 2 deletions ls8/ls8.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
/**
* Main
*/
int main(void)
int main(int argc, char **argv)
{
struct cpu cpu;
if (argc != 2) {
fprintf(stderr, "correct formatting: ls8 <filename.ls8>\n");
return 1;
}

cpu_init(&cpu);
cpu_load(&cpu);
cpu_load(argv[1], &cpu);
cpu_run(&cpu);

return 0;
Expand Down