public static InstructionFlowBehavior GenerateOutgoingCall(ProgramLine programLine, IDictionary<string, NumberExpression> programVariables) { if (programLine.Type == ProgramLineType.OpCodeInstruction) { // Analyse instruction effect on the program flow InstructionFlowBehavior instructionFlowBehavior = ProgramFlowAnalyzer.GetInstructionFlowBehavior(programLine.InstructionCode.InstructionType); // - check if the program flow continues to the next line programLine.ContinueToNextLine = (instructionFlowBehavior & InstructionFlowBehavior.ContinueToNextInstruction) > 0; // - check if the current program line can jump elswhere (either always or depending on a condition) if ((instructionFlowBehavior & InstructionFlowBehavior.JumpToKnownLocation) > 0) { // Register the outgoing call address in the program line CallSourceType callInstructionType; InstructionLineParam targetAddressParameter; AddressingMode targetAddressParameterType; switch (programLine.InstructionType.Index) { // -- Call and jump instructions -- // Instruction_18_CALL_Address PC => stack, PC = Param1 (ODh|ODl) case 18: callInstructionType = CallSourceType.CallInstruction; targetAddressParameter = programLine.OpCodeParameters[0]; targetAddressParameterType = programLine.InstructionType.Param1Type.Value; break; // Instruction_19_CALL_FlagCondition_Address (PC += instruction size) OR (PC => stack, PC = Param2 (ODh|ODl)) case 19: callInstructionType = CallSourceType.CallInstruction; targetAddressParameter = programLine.OpCodeParameters[1]; targetAddressParameterType = programLine.InstructionType.Param2Type.Value; break; // Instruction_36_DJNZ_RelativeDisplacement (PC += instruction size) OR (PC += Param1 (OD)) case 36: callInstructionType = CallSourceType.JumpInstruction; targetAddressParameter = programLine.OpCodeParameters[0]; targetAddressParameterType = programLine.InstructionType.Param1Type.Value; break; // Instruction_54_JP_Address PC = Param1 (ODh|ODl) case 54: callInstructionType = CallSourceType.JumpInstruction; targetAddressParameter = programLine.OpCodeParameters[0]; targetAddressParameterType = programLine.InstructionType.Param1Type.Value; break; // Instruction_56_JP_FlagCondition_Address (PC += instruction size) OR (PC = Param2 (ODh|ODl)) case 56: callInstructionType = CallSourceType.JumpInstruction; targetAddressParameter = programLine.OpCodeParameters[1]; targetAddressParameterType = programLine.InstructionType.Param2Type.Value; break; // Instruction_57_JR_RelativeDisplacement PC += Param1 (OD) case 57: callInstructionType = CallSourceType.JumpInstruction; targetAddressParameter = programLine.OpCodeParameters[0]; targetAddressParameterType = programLine.InstructionType.Param1Type.Value; break; // Instruction_58_JR_FlagCondition_RelativeDisplacement (PC += instruction size) OR (PC += Param2 (OD)) case 58: callInstructionType = CallSourceType.JumpInstruction; targetAddressParameter = programLine.OpCodeParameters[1]; targetAddressParameterType = programLine.InstructionType.Param2Type.Value; break; // Instruction_122_RST_ResetAddress PC => stack, PC = (AddressModifiedPageZero)Param1 case 122: callInstructionType = CallSourceType.CallInstruction; targetAddressParameter = programLine.OpCodeParameters[0]; targetAddressParameterType = programLine.InstructionType.Param1Type.Value; break; default: throw new NotImplementedException("Unexpected instruction type " + programLine.InstructionType.Index); } // Compute target address int targetAddress; if (targetAddressParameterType == AddressingMode.Relative && !(targetAddressParameter.NumberExpression is SymbolOperand)) { targetAddress = programLine.LineAddress + targetAddressParameter.NumberExpression.GetValue(programVariables, programLine) /* + 2 not necessary because the assembler already adjusts when parsing the expression */; } else { targetAddress = targetAddressParameter.NumberExpression.GetValue(programVariables, programLine); } // Register call source and call target CallSource callSource = new CallSource(callInstructionType, programLine.LineAddress, programLine); CallTarget callTarget = new CallTarget(callSource, targetAddress); programLine.OutgoingCall = callTarget; } return instructionFlowBehavior; } else { return 0; } }
public static InstructionFlowBehavior GenerateOutgoingCall(ProgramLine programLine, IDictionary <string, NumberExpression> programVariables) { if (programLine.Type == ProgramLineType.OpCodeInstruction) { // Analyse instruction effect on the program flow InstructionFlowBehavior instructionFlowBehavior = ProgramFlowAnalyzer.GetInstructionFlowBehavior(programLine.InstructionCode.InstructionType); // - check if the program flow continues to the next line programLine.ContinueToNextLine = (instructionFlowBehavior & InstructionFlowBehavior.ContinueToNextInstruction) > 0; // - check if the current program line can jump elswhere (either always or depending on a condition) if ((instructionFlowBehavior & InstructionFlowBehavior.JumpToKnownLocation) > 0) { // Register the outgoing call address in the program line CallSourceType callInstructionType; InstructionLineParam targetAddressParameter; AddressingMode targetAddressParameterType; switch (programLine.InstructionType.Index) { // -- Call and jump instructions -- // Instruction_18_CALL_Address PC => stack, PC = Param1 (ODh|ODl) case 18: callInstructionType = CallSourceType.CallInstruction; targetAddressParameter = programLine.OpCodeParameters[0]; targetAddressParameterType = programLine.InstructionType.Param1Type.Value; break; // Instruction_19_CALL_FlagCondition_Address (PC += instruction size) OR (PC => stack, PC = Param2 (ODh|ODl)) case 19: callInstructionType = CallSourceType.CallInstruction; targetAddressParameter = programLine.OpCodeParameters[1]; targetAddressParameterType = programLine.InstructionType.Param2Type.Value; break; // Instruction_36_DJNZ_RelativeDisplacement (PC += instruction size) OR (PC += Param1 (OD)) case 36: callInstructionType = CallSourceType.JumpInstruction; targetAddressParameter = programLine.OpCodeParameters[0]; targetAddressParameterType = programLine.InstructionType.Param1Type.Value; break; // Instruction_54_JP_Address PC = Param1 (ODh|ODl) case 54: callInstructionType = CallSourceType.JumpInstruction; targetAddressParameter = programLine.OpCodeParameters[0]; targetAddressParameterType = programLine.InstructionType.Param1Type.Value; break; // Instruction_56_JP_FlagCondition_Address (PC += instruction size) OR (PC = Param2 (ODh|ODl)) case 56: callInstructionType = CallSourceType.JumpInstruction; targetAddressParameter = programLine.OpCodeParameters[1]; targetAddressParameterType = programLine.InstructionType.Param2Type.Value; break; // Instruction_57_JR_RelativeDisplacement PC += Param1 (OD) case 57: callInstructionType = CallSourceType.JumpInstruction; targetAddressParameter = programLine.OpCodeParameters[0]; targetAddressParameterType = programLine.InstructionType.Param1Type.Value; break; // Instruction_58_JR_FlagCondition_RelativeDisplacement (PC += instruction size) OR (PC += Param2 (OD)) case 58: callInstructionType = CallSourceType.JumpInstruction; targetAddressParameter = programLine.OpCodeParameters[1]; targetAddressParameterType = programLine.InstructionType.Param2Type.Value; break; // Instruction_122_RST_ResetAddress PC => stack, PC = (AddressModifiedPageZero)Param1 case 122: callInstructionType = CallSourceType.CallInstruction; targetAddressParameter = programLine.OpCodeParameters[0]; targetAddressParameterType = programLine.InstructionType.Param1Type.Value; break; default: throw new NotImplementedException("Unexpected instruction type " + programLine.InstructionType.Index); } // Compute target address int targetAddress; if (targetAddressParameterType == AddressingMode.Relative && !(targetAddressParameter.NumberExpression is SymbolOperand)) { targetAddress = programLine.LineAddress + targetAddressParameter.NumberExpression.GetValue(programVariables, programLine) /* + 2 not necessary because the assembler already adjusts when parsing the expression */; } else { targetAddress = targetAddressParameter.NumberExpression.GetValue(programVariables, programLine); } // Register call source and call target CallSource callSource = new CallSource(callInstructionType, programLine.LineAddress, programLine); CallTarget callTarget = new CallTarget(callSource, targetAddress); programLine.OutgoingCall = callTarget; } return(instructionFlowBehavior); } else { return(0); } }
public CallTarget(CallSource source, int targetAddress) { Source = source; Address = targetAddress; }