#include #include "execute.h" #include "operations.h" #include "state_helpers.h" #include "decode_execute.h" #include "exception.h" uint16_t fetch(struct architectural_state * state, struct memory_map * map) { uint32_t address = zero_extend32(sign_extend32(state->pc[0])); assert((address & 0b1) == 0); return read_memory16(map, address); } void step(struct architectural_state * state, struct memory_map * map) { /* * 3 Fetch the instruction bytes from the address in memory, as * indicated by the current program counter, 2 bytes need to be * fetched for each instruction. */ uint16_t instruction_code = fetch(state, map); /* * 4 Calculate the default values of PC’ and PR’. PC’ is set to the * value of PC”, PR’ is set to the value of PR”. */ state->pc[1] = state->pc[2]; state->pr[1] = state->pr[2]; /* * 5 Calculate the default values of PC” and PR” assuming continued * sequential execution without procedure call or mode switch: PC” * is PC’+2, while PR” is unchanged. */ state->pc[2] = state->pc[1] + 2; state->pr[2] = state->pr[2]; // unchanged /* * 6 Decode and execute the instruction. This includes checks for * synchronous events, such as exceptions and panics, and * initiation of handling if required. Synchronous events are not * accepted between a delayed branch and a delay slot. They are * detected either before the delayed branch or after the delay * slot. */ enum decode_status status = decode_and_execute_instruction(state, map, instruction_code); switch (status) { case DECODE__DEFINED: break; case DECODE__UNDEFINED: // undefined instruction if (state->is_delay_slot) ILLSLOT(state); else RESINST(state); break; default: assert(false); break; } /* * 7 Set the current program counter (PC) to the value of the next * program counter (PC’) and PR to the value of PR’. */ state->pc[0] = state->pc[1]; state->pr[0] = state->pr[1]; }