Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
actions: read # To read the workflow path.
id-token: write # To sign the provenance.
contents: write # To add assets to a release.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.4.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
with:
base64-subjects: "${{ needs.build.outputs.digests }}"
upload-assets: true # Optional: Upload to a new release
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ all: build

build:
mkdir -p $(DIR)
$(CC) $(INC) $(SRC_MAIN) -o $(BIN)
$(CC) $(INC) $(SRC_MAIN) -o $(BIN) $(FLAGS)

clean:
rm -f $(BIN)
Expand Down
27 changes: 27 additions & 0 deletions include/hardware.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ M-type: memory/branch addressing
offset10: bits [9:0] (10) // signed immediate with sext when needed

*/



// Phantom-18 (later iteration):
/*
enum
{
NOP = 0, //
Expand Down Expand Up @@ -91,6 +96,28 @@ enum
OP_RAND, // r-type
OP_SLEEP // i-type
};
*/

// LC-3:
enum
{
OP_BR = 0, // branch
OP_ADD, // add
OP_LD, // load
OP_ST, // store
OP_JSR, // jump register
OP_AND, // bitwise and
OP_LDR, // load register
OP_STR, // store register
OP_RTI, // unused
OP_NOT, // bitwise not
OP_LDI, // load indirect
OP_STI, // store indirect
OP_JMP, // jump
OP_RES, // reserved (unused)
OP_LEA, // load effective address
OP_TRAP // execute trap
};

// define cond flags
enum
Expand Down
31 changes: 30 additions & 1 deletion include/instructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,35 @@
#define INSTRUCTIONS_H

// function prototypes for instruction handling
void execute_instruction(uint32_t instruction);
void execute_instruction(uint16_t instruction);

void execute_add(uint16_t instr);
void execute_and(uint16_t instr);
void execute_not(uint16_t instr);
void execute_br(uint16_t instr);
void execute_jmp(uint16_t instr);
void execute_jsr(uint16_t instr);
void execute_ld(uint16_t instr);
void execute_ldi(uint16_t instr);
void execute_ldr(uint16_t instr);
void execute_lea(uint16_t instr);
void execute_st(uint16_t instr);
void execute_sti(uint16_t instr);
void execute_str(uint16_t instr);
void execute_math(uint16_t instr);
void execute_trap(uint16_t instr);
void execute_bad_opcode(uint16_t instr);

// LC-3 decode helpers
#define GET_OP(x) (((x) >> 12) & 0xF)
#define GET_DR(x) (((x) >> 9) & 0x7)
#define GET_SR1(x) (((x) >> 6) & 0x7)
#define GET_SR2(x) ((x) & 0x7)
#define GET_IMM_FLAG5(x) (((x) >> 5) & 0x1)
#define GET_IMM5(x) ((x) & 0x1F)
#define GET_PC_OFFSET9(x) ((x) & 0x1FF)
#define GET_PC_OFFSET11(x) ((x) & 0x7FF)
#define GET_BASE_R(x) (((x) >> 6) & 0x7)
#define GET_OFFSET6(x) ((x) & 0x3F)

#endif // INSTRUCTIONS_H
256 changes: 255 additions & 1 deletion src/instructions.c
Original file line number Diff line number Diff line change
@@ -1,2 +1,256 @@
// instructions.c
// implementation of the instructions specified in the ISA
// implementation of the instructions specified in the ISA

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#include "instructions.h"
#include "hardware.h"
#include "utils.h"



// trap routines
void trap_puts() {
uint16_t* c = memory + reg[R_R0];
while (*c) {
putc((char)*c, stdout);
++c;
}
fflush(stdout);
}

void trap_getc() {
reg[R_R0] = (uint16_t)getchar();
update_flags(R_R0);
}

void trap_out() {
putc((char)reg[R_R0], stdout);
fflush(stdout);
}

void trap_in() {
char c = getchar();
putc(c, stdout);
fflush(stdout);
reg[R_R0] = (uint16_t)c;
update_flags(R_R0);
}

void trap_putsp() {
// one char per byte, two bytes per word
uint16_t* c = memory + reg[R_R0];
while (*c) {
char char1 = (*c) & 0xFF;
putc(char1, stdout);
char char2 = (*c >> 8) & 0xFF;
if (char2) putc(char2, stdout);
++c;
}
fflush(stdout);
}

void trap_halt() {
puts("HALT");
fflush(stdout);
exit(0);
}



// define instructions
/*
R-type: three register or two-register + small flags
opcode: bits [17:13] (5)
rd: bits [12:10] (3)
rs: bits [9:7] (3)
rt: bits [6:4] (3)
flags / unused: bits [3:0] (4)

I-type: register + immediate
opcode: bits [17:13] (5)
rd: bits [12:10] (3)
rs: bits [9:7] (3)
imm7: bits [6:0] (7) // signed immediate with sext when needed

M-type: memory/branch addressing
opcode: bits [17:13] (5)
rd: bits [12:10] (3)
offset10: bits [9:0] (10) // signed immediate with sext when needed


Phantom-18:
{
NOP = 0, //
OP_HALT, //
OP_ADD, // r-type
OP_SUB, // r-type
OP_AND, // r-type
OP_OR, // r-type
OP_XOR, // r-type
OP_NOT, // r-type, rd = ~rs
OP_MOV, // r-type, rd = rs
OP_LSH, // r-type, logical
OP_RSH, // r-type, logical
OP_CMP, // r-type, set condition codes
OP_ADDI, // i-type
OP_ANDI, // i-type
OP_ORI, // i-type
OP_LDI, // m-type, load immediate/addressing
OP_LD, // m-type, load from memory
OP_ST, // m-type, store to memory
OP_LDIND, // m-type, load via pointer
OP_STIND, // m-type, store via pointer
OP_JMP, // m-type
OP_JZ, // m-type
OP_JNZ, // m-type
OP_CALL, // m-type
OP_RET, // r-type OR implicit
OP_PUSH, // r-type
OP_POP, // r-type
OP_IN, // i-type, I/O
OP_OUT, // i-type, I/O
OP_TRAP, // i-type
OP_RAND, // r-type
OP_SLEEP // i-type
};


LC-3:
enum
{
OP_BR = 0, // branch
OP_ADD, // add
OP_LD, // load
OP_ST, // store
OP_JSR, // jump register
OP_AND, // bitwise and
OP_LDR, // load register
OP_STR, // store register
OP_RTI, // unused
OP_NOT, // bitwise not
OP_LDI, // load indirect
OP_STI, // store indirect
OP_JMP, // jump
OP_RES, // reserved (unused)
OP_LEA, // load effective address
OP_TRAP // execute trap
};
*/

void execute_add(uint16_t instr) {
uint16_t r0 = GET_DR(instr);
uint16_t r1 = GET_SR1(instr);
uint16_t imm_flag = GET_IMM_FLAG5(instr);

if (imm_flag) {
uint16_t imm5 = sext(GET_IMM5(instr), 5);
reg[r0] = reg[r1] + imm5;
} else {
uint16_t r2 = GET_SR2(instr);
reg[r0] = reg[r1] + reg[r2];
}
update_flags(r0);
}

void execute_and(uint16_t instr) {
uint16_t r0 = GET_DR(instr);
uint16_t r1 = GET_SR1(instr);
uint16_t imm_flag = GET_IMM_FLAG5(instr);

if (imm_flag) {
uint16_t imm5 = sext(GET_IMM5(instr), 5);
reg[r0] = reg[r1] & imm5;
} else {
uint16_t r2 = GET_SR2(instr);
reg[r0] = reg[r1] & reg[r2];
}
update_flags(r0);
}

void execute_not(uint16_t instr) {
uint16_t r0 = GET_DR(instr);
uint16_t r1 = GET_SR1(instr);
reg[r0] = ~reg[r1];
update_flags(r0);
}

static void trap_dispatch(uint8_t trapvect8) {
switch (trapvect8) {
case TRAP_GETC: trap_getc(); break;
case TRAP_OUT: trap_out(); break;
case TRAP_PUTS: trap_puts(); break;
case TRAP_IN: trap_in(); break;
case TRAP_PUTSP:trap_putsp();break;
case TRAP_HALT: trap_halt(); break;
default:
fprintf(stderr, "Bad TRAP vector: 0x%02X\n", trapvect8);
exit(1);
}
}

void execute_trap(uint16_t instr) {
uint8_t trapvect8 = instr & 0xFF;
trap_dispatch(trapvect8);
}

void execute_bad_opcode(uint16_t instr) {
uint16_t op = (instr >> 12) & 0xF;
fprintf(stderr, "Bad opcode: 0x%X (instr=0x%04X)\n", op, instr);
exit(1);
}








void execute_instruction(uint16_t instruction) {
uint16_t op = GET_OP(instruction);
switch (op) {
case OP_ADD: execute_add(instruction); break;
case OP_AND: execute_and(instruction); break;
case OP_NOT: execute_not(instruction); break;
case OP_TRAP: execute_trap(instruction); break;
/*
case OP_BR:
execute_br((uint16_t)instruction);
break;
case OP_JMP:
execute_jmp((uint16_t)instruction);
break;
case OP_JSR:
execute_jsr((uint16_t)instruction);
break;
case OP_LD:
execute_ld((uint16_t)instruction);
break;
case OP_LDI:
execute_ldi((uint16_t)instruction);
break;
case OP_LDR:
execute_ldr((uint16_t)instruction);
break;
case OP_LEA:
execute_lea((uint16_t)instruction);
break;
case OP_ST:
execute_st((uint16_t)instruction);
break;
case OP_STI:
execute_sti((uint16_t)instruction);
break;
case OP_STR:
execute_str((uint16_t)instruction);
break;
*/
default:
execute_bad_opcode((uint16_t)instruction);
break;
}
}

13 changes: 4 additions & 9 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ int load_arguments(int argc, const char* argv[])
exit(1);
}
}
return 0;
}

int setup()
{
signal(SIGINT, handle_interrupt);
disable_input_buffering();
atexit(restore_input_buffering);
return 0;
}

Expand All @@ -55,14 +57,7 @@ int main(int argc, const char* argv[])
int running = 1;
while (running)
{
// uint16_t instr = mem_read(reg[R_PC]++);
// uint16_t op = instr >> 12;
/*
switch (op) {
case OP_HALT:
running = 0;
break;
}
*/
uint16_t instr = mem_read(reg[R_PC]++);
execute_instruction(instr);
}
}