// macro-arrNotEndOrExit // advance array index and reset and return/terminate if its over // else jump relative public static void macroArrayNotEndOrExit(GlobalInterpreterState globalState, LocalInterpreterState localState, int ipDelta, out bool success) { if (globalState.arrayState == null) { success = false; return; } bool isIndexValid = globalState.arrayState.isIndexValid; if (!isIndexValid) { globalState.arrayState.index = 0; Operations.@return(localState, out success); return; } localState.instructionPointer++; localState.instructionPointer += ipDelta; success = true; }
// \param indirectCall is not -1 if the instruction is an indirect call to another function public static void dispatch( GlobalInterpreterState globalState, LocalInterpreterState localState, Instruction instr, out bool success, out int indirectCall ) { indirectCall = -1; uint instructionWithoutRelative; int relative; decodeInstruction(instr.code, out instructionWithoutRelative, out relative); switch (instructionWithoutRelative) { case INSTRUCTION_RET: Operations.@return(localState, out success); return; case 1: ArrayOperations.macroArrayAdvanceOrExit(globalState, localState, relative, out success); return; case 2: ArrayOperations.macroArrayNotEndOrExit(globalState, localState, relative, out success); return; case 3: Operations.jump(localState, relative); success = true; return; case 4: Operations.jumpIfNotFlag(localState, relative); success = true; return; case 5: Operations.call(localState, relative); success = true; return; case 6: ArrayOperationsTwoArgumentWrapper.arrayMove(globalState, localState, -1, int.MaxValue, out success); return; case 7: ArrayOperationsTwoArgumentWrapper.arrayMove(globalState, localState, 1, int.MaxValue, out success); return; case 8: ArrayOperationsTwoArgumentWrapper.arrayRemove(globalState, localState, int.MaxValue, int.MaxValue, out success); return; case 9: ArrayOperationsTwoArgumentWrapper.arrayCompareWithRegister(globalState, localState, 0, int.MaxValue, out success); return; case 10: ArrayOperationsTwoArgumentWrapper.arrayCompareWithRegister(globalState, localState, 1, int.MaxValue, out success); return; case 11: ArrayOperations.insert(globalState, localState, /*reg*/ 0, out success); return; case 12: ArrayOperations.insert(globalState, localState, /*reg*/ 1, out success); return; case 13: ArrayOperations.insert(globalState, localState, /*reg*/ 2, out success); return; case 14: ArrayOperations.setIdxRelative(globalState, localState, 0, 0, out success); return; case 15: ArrayOperations.setIdxRelative(globalState, localState, 0, -1, out success); return; // -1 is end of array case 16: ArrayOperations.idxFlag(globalState, localState, 0, 1, out success); return; // TODO< should be an intrinsic command which gets added by default > case 17: ArrayOperations.valid(globalState, localState, /*array*/ 0, out success); return; case 18: ArrayOperations.read(globalState, localState, /*array*/ 0, /*register*/ 0, out success); return; case 19: ArrayOperations.idx2Reg(globalState, localState, /*array*/ 0, /*register*/ 0, out success); return; case 20: Operations.movImmediate(localState, /*register*/ 0, 0, out success); return; case 21: Operations.movImmediate(localState, /*register*/ 0, 1, out success); return; case 22: Operations.movImmediate(localState, /*register*/ 0, 3, out success); return; case 23: ArrayOperations.arrayMovToArray(globalState, localState, /*array*/ 0, /*register*/ 0, out success); return; case 24: Operations.mulRegisterImmediate(localState, /*register*/ 0, -1); success = true; return; case 25: Operations.binaryNegate(globalState, localState, /*register*/ 0); success = true; return; case 26: ArrayOperations.macroArrayAdvanceOrExit(globalState, localState, -4, out success); return; case 27: Operations.movImmediate(localState, /*register*/ 1, 0, out success); return; case 28: Operations.movImmediate(localState, /*register*/ 1, 1, out success); return; case 29: Operations.movImmediate(localState, /*register*/ 1, 3, out success); return; case 30: ArrayOperations.read(globalState, localState, /*array*/ 0, /*register*/ 1, out success); return; case 31: Operations.mulRegisterRegister(localState, 0, 1); success = true; return; case 32: Operations.addRegisterRegister(localState, 0, 1); success = true; return; case 33: ArrayOperations.arrayMovToArray(globalState, localState, /*array*/ 0, /*register*/ 1, out success); return; case 34: Operations.subRegisterRegister(localState, 1, 0); success = true; return; case 35: ArrayOperations.read(globalState, localState, /*array*/ 0, /*register*/ 1, out success); return; case 36: ArrayOperations.reg2idx(globalState, localState, /*register*/ 0, /*array*/ 0, out success); return; case 37: Operations.compareRegister(localState, /*register*/ 0, /*register*/ 1, /*type*/ -1); success = true; return; // TODO< maybe using relative value as immediate > case 38: Operations.random(globalState, localState, 0, 0, out success); return; case 39: ArrayOperations.length(globalState, localState, /*destRegister*/ 0, out success); return; } // if we are here we have instrution with hardcoded parameters uint baseInstruction = InstructionInfo.getNumberOfHardcodedSingleInstructions(); Debug.Assert(instructionWithoutRelative >= baseInstruction); int currentBaseInstruction = (int)baseInstruction; // add register constant if (instructionWithoutRelative <= currentBaseInstruction + 3) { int subInstruction = (int)instructionWithoutRelative - currentBaseInstruction; // which instruction do we choose from the pool if (subInstruction == 0) { Operations.add(localState, /*register*/ 0, -1); success = true; } else if (subInstruction == 1) { Operations.add(localState, /*register*/ 0, 2); success = true; } else if (subInstruction == 2) { Operations.add(localState, /*register*/ 1, -1); success = true; } } currentBaseInstruction += 3; // addFlag reg0 constant if (instructionWithoutRelative <= currentBaseInstruction + 1) { // currently just compare reg0 with zero Operations.addFlag(localState, /*register*/ 0, 1); success = true; return; } currentBaseInstruction += 1; // indirect table call if (instructionWithoutRelative <= currentBaseInstruction + 1) { // currently just compare reg0 with zero indirectCall = 0; success = true; return; } currentBaseInstruction += 1; // additional instructions GlobalInterpreterState.AdditionalOperationsDelegateType additionalOperationDelegate; if (globalState.additionalOperations.TryGetValue(instructionWithoutRelative, out additionalOperationDelegate)) { additionalOperationDelegate(globalState, localState, out success); return; } // unknown instruction success = false; }