Пример #1
0
 // Throws a program exception with the given message.
 private void error(String message) throws ProgramException {
   throw new ProgramException(
       message
           + " in "
           + callStack.getTopFunction()
           + "."
           + currentInstruction.getIndexInFunction());
 }
Пример #2
0
  /** Returns the value of the function to the top of the stack. */
  public void returnFromFunction() throws ProgramException {

    // make sure that there's somewhere to return to (old local <> 0)
    if (stackSegment.getValueAt(Definitions.LOCAL_POINTER_ADDRESS) == 0)
      throw new ProgramException(
          "Nowhere to return to in "
              + getCallStack().getTopFunction()
              + "."
              + getCurrentInstruction().getIndexInFunction());

    // done in order to clear the method stack's contents
    workingStackSegment.setStartAddress(getSP());

    bus.send(ram, Definitions.LOCAL_POINTER_ADDRESS, ram, Definitions.R13_ADDRESS); // R13 = lcl
    bus.send(
        stackSegment,
        stackSegment.getValueAt(Definitions.LOCAL_POINTER_ADDRESS) - 5,
        ram,
        Definitions.R14_ADDRESS); // R14 = return address
    bus.send(
        stackSegment,
        getSP() - 1,
        stackSegment,
        ram.getValueAt(Definitions.ARG_POINTER_ADDRESS)); // *arg = return value
    setSP((short) (ram.getValueAt(Definitions.ARG_POINTER_ADDRESS) + 1)); // SP = arg + 1
    bus.send(
        stackSegment,
        ram.getValueAt(Definitions.R13_ADDRESS) - 1,
        ram,
        Definitions.THAT_POINTER_ADDRESS); // that = *(R13 - 1)
    bus.send(
        stackSegment,
        ram.getValueAt(Definitions.R13_ADDRESS) - 2,
        ram,
        Definitions.THIS_POINTER_ADDRESS); // this = *(R13 - 2)
    bus.send(
        stackSegment,
        ram.getValueAt(Definitions.R13_ADDRESS) - 3,
        ram,
        Definitions.ARG_POINTER_ADDRESS); // arg = *(R13 - 3)
    bus.send(
        stackSegment,
        ram.getValueAt(Definitions.R13_ADDRESS) - 4,
        ram,
        Definitions.LOCAL_POINTER_ADDRESS); // lcl = *(R13 - 4)

    // removes the top function from the call stack
    callStack.popFunction();

    // check whether there is a "calling frame"
    if (stackFrames.size() > 0) {
      // retrieve stack frame address of old function
      int frameAddress = ((Integer) stackFrames.lastElement()).intValue();
      stackFrames.removeElementAt(stackFrames.size() - 1);
      workingStackSegment.setStartAddress(frameAddress);

      // disable non relevant range of the local segment - enable only the locals
      // of the function that we returned to.
      localSegment.setEnabledRange(
          Math.max(localSegment.getStartAddress(), Definitions.STACK_START_ADDRESS),
          frameAddress - 1,
          true);

      // enable in the arg segment only the number of args that were sent to the function
      // that we returned to.
      argSegment.setEnabledRange(
          argSegment.getStartAddress(), localSegment.getStartAddress() - 6, true);

      // enable this, that according to their retrieved pointers
      thisSegment.setEnabledRange(
          Math.max(thisSegment.getStartAddress(), Definitions.HEAP_START_ADDRESS),
          Definitions.HEAP_END_ADDRESS,
          true);
      thatSegment.setEnabledRange(
          Math.max(thatSegment.getStartAddress(), Definitions.HEAP_START_ADDRESS),
          Definitions.SCREEN_END_ADDRESS,
          true);
    } /* else {
      	error("Nowhere to return to");
      } */
    // Allow return if we previously had "function" even with no call -
    // For the SimpleFunction test

    short returnAddress = ram.getValueAt(Definitions.R14_ADDRESS);
    if (returnAddress == VMProgram.BUILTIN_FUNCTION_ADDRESS) {
      staticSegment.setEnabledRange(0, -1, true); // empty static segment
      builtInFunctionsRunner.returnToBuiltInFunction(popValue(METHOD_STACK));
    } else if (returnAddress >= 0 && returnAddress < program.getSize()) {
      // sets the static segment range
      if (stackFrames.size() > 0) {
        setStaticRange(callStack.getTopFunction());
      } else {
        staticSegment.setStartAddress(Definitions.VAR_START_ADDRESS);
        staticSegment.setEnabledRange(
            Definitions.VAR_START_ADDRESS, Definitions.VAR_END_ADDRESS - 1, true);
      }
      program.setPC((short) (returnAddress - 1)); // set previousPC correctly
      program.setPC(returnAddress); // pc = *sp
    } else {
      error("Illegal return address");
    }
  }
Пример #3
0
  /**
   * Executes the current instruction (Program at pc). Returns false if END command, true otherwise.
   */
  public void executeInstruction() throws ProgramException {
    currentInstruction = program.getNextInstruction();

    if (currentInstruction == null) throw new ProgramException("No more instructions to execute");

    switch (currentInstruction.getOpCode()) {
      case HVMInstructionSet.ADD_CODE:
        add();
        break;
      case HVMInstructionSet.SUBSTRACT_CODE:
        substract();
        break;
      case HVMInstructionSet.NEGATE_CODE:
        negate();
        break;
      case HVMInstructionSet.EQUAL_CODE:
        equal();
        break;
      case HVMInstructionSet.GREATER_THAN_CODE:
        greaterThan();
        break;
      case HVMInstructionSet.LESS_THAN_CODE:
        lessThan();
        break;
      case HVMInstructionSet.AND_CODE:
        and();
        break;
      case HVMInstructionSet.OR_CODE:
        or();
        break;
      case HVMInstructionSet.NOT_CODE:
        not();
        break;

      case HVMInstructionSet.PUSH_CODE:
        push(currentInstruction.getArg0(), currentInstruction.getArg1());
        break;
      case HVMInstructionSet.POP_CODE:
        pop(currentInstruction.getArg0(), currentInstruction.getArg1());
        break;

      case HVMInstructionSet.GOTO_CODE:
        goTo(currentInstruction.getArg0());
        break;
      case HVMInstructionSet.IF_GOTO_CODE:
        ifGoTo(currentInstruction.getArg0());
        break;

      case HVMInstructionSet.FUNCTION_CODE:
        if (program.getCurrentPC() == program.getPreviousPC() + 1)
          throw new ProgramException("Missing return in " + callStack.getTopFunction());

        function(currentInstruction.getArg0());
        break;
      case HVMInstructionSet.RETURN_CODE:
        returnFromFunction();
        break;
      case HVMInstructionSet.CALL_CODE:
        callFunction(
            currentInstruction.getArg0(),
            currentInstruction.getArg1(),
            currentInstruction.getStringArg(),
            false);
        break;
    }
  }