예제 #1
0
/** lc3_finish
  *
  * Finishes the current subroutine
  */
void lc3_finish(lc3_state& state)
{
    // Subroutine depth We assume the user is already in a subroutine and just wants to get out of it
    int depth = 1;

    do
    {
        // Get Next Instruction.
        lc3_instr instr = lc3_decode(state, state.mem[state.pc]);
        // So if we get a JSR/JSRR or if we get a TRAP and true traps are enabled
        if (instr.data.opcode == JSR_INSTR || (instr.data.opcode == TRAP_INSTR && state.true_traps))
            depth++;

        // If we get a RET instruction JMP R7
        if (instr.data.opcode == JMP_INSTR && instr.jmp.base_r == 7)
            depth--;

        // If we got an RTI instruction
        if (instr.data.opcode == RTI_INSTR)
            depth--;

        // Execute
        lc3_step(state);

        // If we got interrupted
        if (state.interrupt_enabled && state.undo_stack.back().changes == LC3_INTERRUPT_BEGIN)
            depth++;
    } while (depth != 0 && !state.halted);
}
예제 #2
0
/** lc3_prev_line
  *
  * Undos the current instruction ignoring subroutines
  */
void lc3_prev_line(lc3_state& state)
{
    // Subroutine depth
    int depth = 0;

    do
    {
        if (!state.undo_stack.empty())
        {
            lc3_state_change& last = state.undo_stack.back();
            // Can't backstep through interrupt
            if (last.changes == LC3_INTERRUPT_BEGIN)
                return;

            // Get rid of all processed interrupts.
            while (last.changes == LC3_INTERRUPT && !state.undo_stack.empty())
            {
                lc3_back(state);
                last = state.undo_stack.back();
            }
        }

        // Execute (Have to do this first you can't assume mem[pc - 1] was the last
        // instruction due to jumps.
        lc3_back(state);
        // Get the instruction that got you where you are.
        lc3_instr instr = lc3_decode(state, state.mem[state.pc]);
        // If we get a RET instruction JMP R7
        if (instr.data.opcode == JMP_INSTR && instr.jmp.base_r == 7)
            depth++;
        // So if we get a JSR/JSRR or if we get a TRAP and true traps are enabled
        if (instr.data.opcode == JSR_INSTR || (instr.data.opcode == TRAP_INSTR && state.true_traps))
            depth--;
        // Don't have to handle interrupts here...
    } while (depth != 0 && !state.halted && !state.undo_stack.empty());
}
예제 #3
0
/** Entry
  *
  *
  */
void* LC3RunThread::Entry()
{
    ///TODO consider writing this without rewriting next_line/prev_line.
    int depth = 0;
    lc3_instr instr;
    bool interrupt_begin = false;

    state.halted = 0;

    switch(run_mode)
    {
    case RUNMODE_RUN:
        while(!state.halted)
        {
            lc3_step(state);
            if (TestDestroy()) break;
            Yield();
        }
        break;
    case RUNMODE_RUNFOR:
        if (runtime > 0)
            lc3_run(state, runtime);
        else
            lc3_rewind(state, -runtime);
        break;
    case RUNMODE_STEP:
        lc3_step(state);
        break;
    case RUNMODE_BACK:
        lc3_back(state);
        break;
    case RUNMODE_FINISH:
        depth = 1;
    case RUNMODE_NEXTLINE:
        // Subroutine depth
        do
        {
            // Get Next Instruction.
            instr = lc3_decode(state, state.mem[state.pc]);
            // So if we get a JSR/JSRR or if we get a TRAP and true traps are enabled
            if (instr.data.opcode == JSR_INSTR || (instr.data.opcode == TRAP_INSTR && state.true_traps))
                depth++;

            // If we get a RET instruction JMP R7
            if (instr.data.opcode == JMP_INSTR && instr.jmp.base_r == 7)
                depth--;

            // If we get an RTI instruction
            if (instr.data.opcode == RTI_INSTR)
                depth--;

            // Execute
            lc3_step(state);

            // If we got interrupted
            if (state.interrupt_enabled && state.undo_stack.back().changes == LC3_INTERRUPT_BEGIN)
                depth++;

            if (TestDestroy()) break;
            Yield();
        }
        while (depth != 0 && !state.halted);
        break;
    case RUNMODE_PREVLINE:
        // Subroutine depth
        depth = 0;

        do
        {
            if (!state.undo_stack.empty())
            {
                lc3_state_change& last = state.undo_stack.back();
                // Can't backstep through interrupt
                if (last.changes == LC3_INTERRUPT_BEGIN)
                    break;

                // Get rid of all processed interrupts.
                while (last.changes == LC3_INTERRUPT && !state.undo_stack.empty())
                {
                    lc3_back(state);
                    last = state.undo_stack.back();
                    if (TestDestroy()) break;
                    Yield();
                }
            }

            // Execute (Have to do this first you can't assume mem[pc - 1] was the last
            // instruction due to jumps.
            lc3_back(state);
            // Get the instruction that got you where you are.
            lc3_instr instr = lc3_decode(state, state.mem[state.pc]);
            // If we get a RET instruction JMP R7
            if (instr.data.opcode == JMP_INSTR && instr.jmp.base_r == 7)
                depth++;
            // So if we get a JSR/JSRR or if we get a TRAP and true traps are enabled
            if (instr.data.opcode == JSR_INSTR || (instr.data.opcode == TRAP_INSTR && state.true_traps))
                depth--;
            if (TestDestroy()) break;
            Yield();
            // Don't have to handle interrupts here...
        }
        while (depth != 0 && !state.halted && !state.undo_stack.empty());
        break;
    case RUNMODE_REWIND:
        // Do this until no more changes.
        while (!state.undo_stack.empty() && !interrupt_begin)
        {
            lc3_state_change& last = state.undo_stack.back();
            interrupt_begin = (last.changes == LC3_INTERRUPT_BEGIN);
            // Backstep
            lc3_back(state);

            if (TestDestroy()) break;
            Yield();
        }
        break;
    }

    wxQueueEvent(frame, new wxThreadEvent(wxEVT_COMMAND_RUNTHREAD_COMPLETED));

    return NULL;
}
예제 #4
0
/** lc3_step
  *
  * Executes one instruction
  */
void lc3_step(lc3_state& state)
{
    // If we are halted then don't step.
    if (state.halted) return;
    // Tick all plugins
    lc3_tick_plugins(state);
    // Fetch Instruction
    unsigned short data = state.mem[state.pc];
    // Test for blackbox (If the line was a JSR statement and it had a blackbox).
    bool blackbox_finish = lc3_blackbox_test(state);
    // Increment PC
    state.pc++;
    // Form Instruction
    lc3_instr instr = lc3_decode(state, data);
    // Execute Instruction
    const lc3_state_change change = lc3_execute(state, instr);
    // Test for blackbox (If the first line of subroutine had a blackbox).
    if (instr.data.opcode == JSR_INSTR || (instr.data.opcode == TRAP_INSTR && state.true_traps))
        blackbox_finish = blackbox_finish || lc3_blackbox_test(state);
    // Increment executions
    state.executions++;

    if (state.max_stack_size != 0)
    {
        // If the change is INTERRUPT END
        if (change.changes == LC3_INTERRUPT_END)
        {
            // After you've scrubbed all of the floors in hyrule (remove all instructions that have been added except the LC3_INTERRUPT change.
            lc3_state_change* hmm = &state.undo_stack.back();
            while (hmm->changes != LC3_INTERRUPT_BEGIN)
            {
                state.undo_stack.pop_back();
                hmm = &state.undo_stack.back();
            }
            // Please sire have mercy (Change LC3_INTERRUPT_BEGIN to LC3_INTERRUPT to signal a completed interrupt)
            lc3_state_change& lib = state.undo_stack.back();
            lib.changes = LC3_INTERRUPT;
        }
        else
        {
            // Push Old into state
            state.undo_stack.push_back(change);
        }
        // Never pop if you are in privileged mode.

        if (state.privilege && state.max_stack_size < state.undo_stack.size())
            state.undo_stack.pop_front();
    }

    // Tock all plugins
    lc3_tock_plugins(state);

    if (blackbox_finish)
        lc3_finish(state);

    // If we hit an error or a halt instruction return. no need to do any breakpoint tests.
    if (state.halted) return;
    // Breakpoint test
    lc3_break_test(state, &change);

    if (!state.interrupt_enabled) return;

    // Chime in on all observers.
    std::list<interrupt_test_func>::iterator i;
    for (i = state.interrupt_test.begin(); i != state.interrupt_test.end(); ++i)
    {
        interrupt_test_func func = *i;
        func();
    }

    // Interrupt?
    if (!lc3_interrupt(state)) return;

    lc3_state_change interrupt;
    interrupt.changes = LC3_INTERRUPT_BEGIN;
    interrupt.warnings = state.warnings;
    interrupt.executions = state.executions;
    if (state.max_stack_size != 0)
        state.undo_stack.push_back(interrupt);

    // Another breakpoint test
    lc3_break_test(state, &interrupt);
}
예제 #5
0
    BOOST_CHECK_EQUAL(instr.arith.inv.unused, 0x3E);

    instr = lc3_decode(state, 0xF100);
    BOOST_REQUIRE_EQUAL(instr.trap.opcode, TRAP_INSTR);
    BOOST_CHECK_EQUAL(instr.trap.unused, 1);
    BOOST_CHECK_EQUAL(instr.trap.vector, 0);
}

BOOST_FIXTURE_TEST_CASE(MalformedInstructionTest, LC3BasicTest)
{
    const std::vector<unsigned short> malformed_instructions = {0, 1, 0x1008, 0x4001, 0x4200, 0x5008, 0x8001, 0x903E, 0xC001, 0xC200, 0xF100};

    for (const auto& data : malformed_instructions)
    {
        BOOST_TEST_MESSAGE("data = x" << std::hex << data);
        lc3_instr instr = lc3_decode(state, data);
        lc3_state_change change = lc3_execute(state, instr);
        BOOST_CHECK(state.halted);
        BOOST_CHECK_EQUAL(state.warnings, 1);
        BOOST_CHECK_EQUAL(state.pc, 0x2FFF);
        BOOST_CHECK_EQUAL(change.pc, 0x3000);
        BOOST_CHECK(!change.halted);
        lc3_init(state, false, false);
    }
}

BOOST_FIXTURE_TEST_CASE(MalformedInstructionDisassemble, LC3BasicTest)
{
    const std::vector<unsigned short> malformed_instructions = {0, 1, 0x1008, 0x4001, 0x4200, 0x5008, 0x8001, 0x903E, 0xC001, 0xC200, 0xF100};
    const std::vector<std::string> answers = {"NOP *", "NOP *", "ADD R0, R0, R0 *", "JSRR R0 *", "JSRR R0 *", "AND R0, R0, R0 *", "RTI *", "NOT R0, R0 *", "JMP R0 *", "JMP R0 *", "TRAP x00 *"};