diff options
author | Aki <please@ignore.pl> | 2021-07-09 20:52:12 +0200 |
---|---|---|
committer | Aki <please@ignore.pl> | 2021-07-09 20:52:12 +0200 |
commit | 7ad24735886bd94c90da027280ca69ca7748df52 (patch) | |
tree | 471f98b3a3e8ee9b73d1625f0147023d20293ce2 | |
parent | 0199c0a7b735d474fa1f7bed67b841f65ee7b780 (diff) | |
download | lc3-7ad24735886bd94c90da027280ca69ca7748df52.zip lc3-7ad24735886bd94c90da027280ca69ca7748df52.tar.gz lc3-7ad24735886bd94c90da027280ca69ca7748df52.tar.bz2 |
Implemented interrupts and exceptions
-rw-r--r-- | lc3.c | 52 |
1 files changed, 51 insertions, 1 deletions
@@ -124,6 +124,32 @@ uint16_t sign_extend(uint16_t value, const int bits) return (value ^ mask) - mask; } +void fire(const uint16_t interrupt, const uint16_t priority) +{ + const uint16_t current_priority = (registers[REGISTER_PSR] >> 8) & 0x07; + if (current_priority >= priority) + { + return; + } + if (0x80 == interrupt && 0 == (0x4000 & memory[MEMORY_KBSR])) + { + return; + } + if (FLAG_SUP & registers[REGISTER_PSR]) + { + registers[REGISTER_PSR] &= ~FLAG_SUP; + registers[REGISTER_USR] = registers[REGISTER_R6]; + registers[REGISTER_R6] = registers[REGISTER_SSR]; + } + registers[REGISTER_R6]--; + memory[registers[REGISTER_R6]] = registers[REGISTER_PSR]; + registers[REGISTER_R6]--; + memory[registers[REGISTER_R6]] = registers[REGISTER_PC]; + registers[REGISTER_PC] = 0x0100 | (interrupt & 0x00ff); + registers[REGISTER_PSR] &= 0xfeff; + registers[REGISTER_PSR] |= priority << 8; +} + uint16_t check_key() { fd_set fds; @@ -363,6 +389,21 @@ void step(const uint16_t instruction) write_memory(address, registers[src]); break; } + case OP_RTI: + { + if (FLAG_SUP & registers[REGISTER_PSR]) + { + fire(0, (registers[REGISTER_PSR] >> 8) & 0x07); + } + else + { + registers[REGISTER_PC] = memory[registers[REGISTER_R6]]; + registers[REGISTER_R6]++; + registers[REGISTER_PSR] = memory[registers[REGISTER_R6]]; + registers[REGISTER_R6]++; + } + break; + } case OP_NOT: { const uint16_t dest = (instruction >> 9) & 0x07; @@ -403,13 +444,18 @@ void step(const uint16_t instruction) break; } case OP_TRAP: + { registers[REGISTER_R7] = registers[REGISTER_PC]; registers[REGISTER_PC] = 0 | (instruction & 0xff); trap(instruction); registers[REGISTER_PC] = registers[REGISTER_R7]; // TODO: Remove this once traps are implemented. break; - case OP_RTI: + } case OP_RES: + { + fire(0x01, (registers[REGISTER_PSR] >> 8) & 0x07); + break; + } default: exit(EXIT_FAILURE); } @@ -453,5 +499,9 @@ int main(int argc, char ** argv) { const uint16_t instruction = read_memory(registers[REGISTER_PC]++); step(instruction); + if (check_key()) + { + fire(0x80, 4); + } } } |