public void PrintState() { string output = ""; output += "Thread:\r\n\t\tPC: " + mInstructionPtr + "\r\n\r\n"; output += "\t\tFP: " + mFramePtr + "\r\n\r\n"; output += "Local:\n\r"; for (int i = 0; i < mLocal.mStore.Length; ++i) { CFibreReg val = mLocal.mStore[i]; if (val == null) { break; } output += "L" + i + "\t"; if (i < 100) { output += "\t"; } output += val.mType + ", " + val.PrintVal() + "\n\r"; } output += "\r\nCall Frames:\n\r"; CFibreCallFrame[] callFrames = mCallFrames.ToArray(); for (int i = 0; i < callFrames.Length; ++i) { CFibreCallFrame frame = callFrames[i]; output += "F" + i + "\t"; if (i < 100) { output += "\t"; } output += frame.mNextInstruction + ", " + frame.mFramePtr + "\n\r"; } File.WriteAllText(CGame.DataDirectory + "thread.txt", output); }
public ERunResult Run() { while (mInstructionPtr != mScript.mProgram.Count) { // Fetch CFibreOpcode op = mScript.mProgram[mInstructionPtr++]; // Decode & Execute switch (op.mOpcode) { case EFibreOpcodeType.NOP: break; case EFibreOpcodeType.MOV: { _SetRegister(op.mOperand[0], _GetRegister(op.mOperand[1])); } break; case EFibreOpcodeType.NOT: case EFibreOpcodeType.NEG: { CFibreReg opL = _GetRegister(op.mOperand[1]); BinaryOpDelegate opDel = _opTable[(int)op.mOpcode, (int)opL.mType, 0]; if (opDel == null) { throw new CFibreRuntimeException("Can't perform operator " + op.mOpcode + " on type " + opL.mType, this); } _SetRegister(op.mOperand[0], opDel(opL, null)); } break; case EFibreOpcodeType.MUL: case EFibreOpcodeType.DIV: case EFibreOpcodeType.INC: case EFibreOpcodeType.DEC: case EFibreOpcodeType.MOD: case EFibreOpcodeType.EQL: case EFibreOpcodeType.NQL: case EFibreOpcodeType.LES: case EFibreOpcodeType.GRT: case EFibreOpcodeType.LQL: case EFibreOpcodeType.GQL: case EFibreOpcodeType.AND: case EFibreOpcodeType.LOR: { CFibreReg opL = _GetRegister(op.mOperand[1]); CFibreReg opR = _GetRegister(op.mOperand[2]); BinaryOpDelegate opDel = _opTable[(int)op.mOpcode, (int)opL.mType, (int)opR.mType]; if (opDel == null) { throw new CFibreRuntimeException("Can't perform operator " + op.mOpcode + " on types " + opL.mType + " and " + opR.mType, this); } _SetRegister(op.mOperand[0], opDel(opL, opR)); } break; case EFibreOpcodeType.JMP: { mInstructionPtr = (int)op.mOperand[0]; } break; case EFibreOpcodeType.J*Z: { CFibreReg opL = _GetRegister(op.mOperand[0]); if (opL.mType != EFibreType.BOOL) { throw new CFibreRuntimeException("Comparison can only operate on a bool, got " + opL.mType, this); } if (opL.mBool == false) { mInstructionPtr = (int)op.mOperand[1]; } } break; case EFibreOpcodeType.JNZ: { CFibreReg opL = _GetRegister(op.mOperand[0]); if (opL.mType != EFibreType.BOOL) { throw new CFibreRuntimeException("Comparison can only operate on a bool, got " + opL.mType, this); } if (opL.mBool == true) { mInstructionPtr = (int)op.mOperand[1]; } } break; case EFibreOpcodeType.CAL: { int stackFrameStartIndex = (int)(op.mOperand[1] & 0x3FFFFFFF) + mFramePtr; int argCount = (int)op.mOperand[2]; CFibreReg funcDef = _GetRegister(op.mOperand[0]); if (funcDef.mType != EFibreType.FUNCTION) { throw new CFibreRuntimeException("Tried to call a function but got a " + funcDef.mType, this); } else { // TODO: Push data about function so we can reference it in call stack for debugging. mCallFrames.Push(new CFibreCallFrame(mInstructionPtr, stackFrameStartIndex, argCount)); mFramePtr = stackFrameStartIndex; if (funcDef.mID < -1) { int funcIndex = -funcDef.mID - 10; CFibreReg returnValue = mInteropFuncs[funcIndex](this, argCount); if (returnValue != null && returnValue.mType != EFibreType.COUNT) { SetLocalRegister(0, returnValue); } else { SetLocalRegister(0, mData.mStore[2]); } CFibreCallFrame frame = mCallFrames.Pop(); mInstructionPtr = frame.mNextInstruction; if (mCallFrames.Count == 0) { return(ERunResult.DONE); } mFramePtr = mCallFrames.Peek().mFramePtr; if (returnValue != null && returnValue.mType == EFibreType.COUNT) { return(ERunResult.CONTINUE); } } else { mInstructionPtr = funcDef.mID; } } } break; case EFibreOpcodeType.FNC: { int argCount = (int)op.mOperand[0]; // Push undefineds over missing args for (int i = mCallFrames.Peek().mPushedArgCount; i < argCount; ++i) { SetLocalRegister(i, mData.mStore[2]); } } break; case EFibreOpcodeType.RET: { if (op.mOperand[0] == 0) { SetLocalRegister(0, mData.mStore[2]); } CFibreCallFrame frame = mCallFrames.Pop(); mInstructionPtr = frame.mNextInstruction; if (mCallFrames.Count == 0) { return(ERunResult.DONE); } mFramePtr = mCallFrames.Peek().mFramePtr; } break; } } return(ERunResult.DONE); }