From 9064a896bc697b09ec01e2bfba7776ce476318bd Mon Sep 17 00:00:00 2001 From: Lachlan Harris Date: Tue, 23 Sep 2025 08:35:47 +1000 Subject: [PATCH] Add remaining LC-3 instructions, refactor slightly --- include/instructions.h | 1 - include/utils.h | 2 +- src/instructions.c | 151 ++++++++++++++++++++++++++++------------- src/utils.c | 5 +- 4 files changed, 109 insertions(+), 50 deletions(-) diff --git a/include/instructions.h b/include/instructions.h index e861457..4334408 100644 --- a/include/instructions.h +++ b/include/instructions.h @@ -22,7 +22,6 @@ 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); diff --git a/include/utils.h b/include/utils.h index 1e7e619..e034d0f 100644 --- a/include/utils.h +++ b/include/utils.h @@ -8,7 +8,7 @@ #include #include -void handle_interrupt(); +void handle_interrupt(int signal); void disable_input_buffering(); void restore_input_buffering(); void update_flags(uint16_t r); diff --git a/src/instructions.c b/src/instructions.c index 6da21e7..805884f 100644 --- a/src/instructions.c +++ b/src/instructions.c @@ -140,7 +140,8 @@ enum }; */ -void execute_add(uint16_t instr) { +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); @@ -155,7 +156,8 @@ void execute_add(uint16_t instr) { update_flags(r0); } -void execute_and(uint16_t instr) { +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); @@ -170,13 +172,97 @@ void execute_and(uint16_t instr) { update_flags(r0); } -void execute_not(uint16_t instr) { +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); } +void execute_br(uint16_t instr) +{ + uint16_t pc_offset = sext(GET_PC_OFFSET9(instr), 9); + uint16_t cond_flag = (instr >> 9) & 0x7; + if (cond_flag & reg[R_COND]) { + reg[R_PC] += pc_offset; + } +} + +void execute_jmp(uint16_t instr) +{ + uint16_t r1 = GET_BASE_R(instr); + reg[R_PC] = reg[r1]; +} + +void execute_jsr(uint16_t instr) +{ + uint16_t long_flag = (instr >> 11) & 1; + reg[R_R7] = reg[R_PC]; + if (long_flag) { + uint16_t pc_offset = sext(GET_PC_OFFSET11(instr), 11); + reg[R_PC] += pc_offset; + } else { + uint16_t r1 = GET_BASE_R(instr); + reg[R_PC] = reg[r1]; + } +} + +void execute_ld(uint16_t instr) +{ + uint16_t r0 = GET_DR(instr); + uint16_t pc_offset = sext(GET_PC_OFFSET9(instr), 9); + reg[r0] = mem_read(reg[R_PC] + pc_offset); + update_flags(r0); +} + +void execute_ldr(uint16_t instr) +{ + uint16_t r0 = GET_DR(instr); + uint16_t r1 = GET_BASE_R(instr); + uint16_t offset6 = sext(GET_OFFSET6(instr), 6); + reg[r0] = mem_read(reg[r1] + offset6); + update_flags(r0); +} + +void execute_ldi(uint16_t instr) +{ + uint16_t r0 = GET_DR(instr); + uint16_t pc_offset = sext(GET_PC_OFFSET9(instr), 9); + reg[r0] = mem_read(mem_read(reg[R_PC] + pc_offset)); + update_flags(r0); +} + +void execute_lea(uint16_t instr) +{ + uint16_t r0 = GET_DR(instr); + uint16_t pc_offset = sext(GET_PC_OFFSET9(instr), 9); + reg[r0] = reg[R_PC] + pc_offset; + update_flags(r0); +} + +void execute_st(uint16_t instr) +{ + uint16_t r0 = GET_DR(instr); + uint16_t pc_offset = sext(GET_PC_OFFSET9(instr), 9); + mem_write(reg[R_PC] + pc_offset, reg[r0]); +} + +void execute_sti(uint16_t instr) +{ + uint16_t r0 = GET_DR(instr); + uint16_t pc_offset = sext(GET_PC_OFFSET9(instr), 9); + mem_write(mem_read(reg[R_PC] + pc_offset), reg[r0]); +} + +void execute_str(uint16_t instr) +{ + uint16_t r0 = GET_DR(instr); + uint16_t r1 = GET_BASE_R(instr); + uint16_t offset6 = sext(GET_OFFSET6(instr), 6); + mem_write(reg[r1] + offset6, reg[r0]); +} + static void trap_dispatch(uint8_t trapvect8) { switch (trapvect8) { case TRAP_GETC: trap_getc(); break; @@ -193,6 +279,7 @@ static void trap_dispatch(uint8_t trapvect8) { void execute_trap(uint16_t instr) { uint8_t trapvect8 = instr & 0xFF; + reg[R_R7] = reg[R_PC]; trap_dispatch(trapvect8); } @@ -205,52 +292,24 @@ void execute_bad_opcode(uint16_t instr) { - - - - 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; + 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(instruction); break; + case OP_JMP: execute_jmp(instruction); break; + case OP_JSR: execute_jsr(instruction); break; + case OP_LD: execute_ld(instruction); break; + case OP_LDI: execute_ldi(instruction); break; + case OP_LDR: execute_ldr(instruction); break; + case OP_LEA: execute_lea(instruction); break; + case OP_ST: execute_st(instruction); break; + case OP_STI: execute_sti(instruction); break; + case OP_STR: execute_str(instruction); break; + default: execute_bad_opcode(instruction); break; } } diff --git a/src/utils.c b/src/utils.c index 593d278..ea60538 100644 --- a/src/utils.c +++ b/src/utils.c @@ -48,8 +48,9 @@ uint16_t check_key() -void handle_interrupt() +void handle_interrupt(int signal) { + (void)signal; restore_input_buffering(); printf("\n"); exit(-2); @@ -82,7 +83,7 @@ void read_image_file(FILE* file) } origin = swap16(origin); - uint16_t max_read = UINT16_MAX - origin; + uint16_t max_read = MEMORY_MAX - origin; uint16_t* p = memory + origin; size_t read = fread(p, sizeof(uint16_t), max_read, file);