/// <summary> /// Instruction Decoder for Disassembly /// </summary> private static Operation InstructionDecode(uint MemoryLocation) { ushort memoryOpCode = Functions.BytesToWord(Memory.Data[MemoryLocation], Memory.Data[MemoryLocation + 1]); // a new operation does not interfere with the executing Operation instruction = null; if (InstructionSet.OperationsList[(ushort)(memoryOpCode & 0x0fe03)] != null) { instruction = new Operation() { AddressingModeDestination = InstructionSet.OperationsList[(ushort)(memoryOpCode & 0x0fe03)].AddressingModeDestination, AddressingModeSource = InstructionSet.OperationsList[(ushort)(memoryOpCode & 0x0fe03)].AddressingModeSource, Context = InstructionSet.OperationsList[(ushort)(memoryOpCode & 0x0fe03)].Context, Length = InstructionSet.OperationsList[(ushort)(memoryOpCode & 0x0fe03)].Length, Mnemonic = InstructionSet.OperationsList[(ushort)(memoryOpCode & 0x0fe03)].Mnemonic, OpCode = InstructionSet.OperationsList[(ushort)(memoryOpCode & 0x0fe03)].OpCode, OpCodeValue = memoryOpCode, Type = InstructionSet.OperationsList[(ushort)(memoryOpCode & 0x0fe03)].Type, Width = InstructionSet.OperationsList[(ushort)(memoryOpCode & 0x0fe03)].Width, }; } if (MemoryLocation < 0x020 || instruction == null) { return(new Operation() { OpCode = memoryOpCode, OpCodeValue = memoryOpCode, Type = OperationType.Undefined, Width = OperationWidth.Word, Mnemonic = "DW", Cycles = 0, Length = 2, Operands = new List <Operand>() { new Operand() { AddressingMode = AddressingMode.Immediate, Notation = OperandNotation.Destination, Symbol = string.Format("${0}", Convert.ToString(memoryOpCode, 16).ToUpper().PadLeft(4, '0')), Value = memoryOpCode } } }); } //else if (instruction == null) // throw new Exception("oh no no no no..."); ushort opcode = (ushort)(instruction.OpCodeValue & 0x0fe00); if (instruction.Type == OperationType.Implicit) { // specific with bwb, correct mnemonic else passed as is if ((instruction.OpCodeValue & 0x020) > 0) { switch (opcode) { case 0x08600: instruction.Mnemonic = "CLI"; break; } } return(instruction); } else { // specific with bwb, correct mnemonic if ((instruction.OpCodeValue & 0x020) > 0) { switch (opcode) { case 0x04e00: instruction.Mnemonic = "JZ"; break; case 0x05200: instruction.Mnemonic = "JO"; break; case 0x05600: instruction.Mnemonic = "JC"; break; case 0x05a00: instruction.Mnemonic = "JN"; break; case 0x0f200: instruction.Mnemonic = "JRZ"; break; case 0x04c00: instruction.Mnemonic = "SRSET"; break; } } // operands with addressing modes // destination addressing switch (instruction.AddressingModeDestination) { case AddressingMode.MemoryReference: case AddressingMode.Immediate: instruction.Operands.Add(DispatchOperand(Functions.BytesToWord(Memory.Data[MemoryLocation + 2], Memory.Data[MemoryLocation + 3]), instruction.AddressingModeDestination, OperandNotation.Destination, (ushort)(instruction.Context == OperationContext.Relative ? MemoryLocation + instruction.Length : 0))); break; case AddressingMode.RegisterDirect: case AddressingMode.RegisterReference: instruction.Operands.Add(DispatchOperand(memoryOpCode, instruction.AddressingModeDestination, OperandNotation.Destination, (ushort)(instruction.Context == OperationContext.Relative ? MemoryLocation + instruction.Length : 0))); break; case AddressingMode.StackPointer: instruction.Operands.Add(new Operand() { AddressingMode = AddressingMode.StackPointer, Notation = OperandNotation.Destination, Symbol = "SP", Value = 0, }); break; case AddressingMode.ProgramCounter: instruction.Operands.Add(new Operand() { AddressingMode = AddressingMode.ProgramCounter, Notation = OperandNotation.Destination, Symbol = "PC", Value = 0, }); break; case AddressingMode.StatusRegister: instruction.Operands.Add(new Operand() { AddressingMode = AddressingMode.StatusRegister, Notation = OperandNotation.Destination, Symbol = "SR", Value = 0, }); break; } // source addressing switch (instruction.AddressingModeSource) { case AddressingMode.Immediate: case AddressingMode.MemoryReference: if (instruction.AddressingModeDestination == AddressingMode.MemoryReference || instruction.AddressingModeDestination == AddressingMode.Immediate) { instruction.Operands.Add(DispatchOperand(Functions.BytesToWord(Memory.Data[MemoryLocation + 4], Memory.Data[MemoryLocation + 5]), instruction.AddressingModeSource, OperandNotation.Source, (ushort)(instruction.Context == OperationContext.Relative ? MemoryLocation + instruction.Length : 0))); } else { // register reference instruction.Operands.Add(DispatchOperand(Functions.BytesToWord(Memory.Data[MemoryLocation + 2], Memory.Data[MemoryLocation + 3]), instruction.AddressingModeSource, OperandNotation.Source, (ushort)(instruction.Context == OperationContext.Relative ? MemoryLocation + instruction.Length : 0))); } break; case AddressingMode.ImmediateQuick: case AddressingMode.RegisterDirect: case AddressingMode.RegisterReference: if (instruction.AddressingModeDestination == AddressingMode.Internal) { instruction.Operands.Add(DispatchOperand(memoryOpCode, instruction.AddressingModeSource, OperandNotation.Destination, 0)); } else { instruction.Operands.Add(DispatchOperand(memoryOpCode, instruction.AddressingModeSource, OperandNotation.Source, 0)); } break; case AddressingMode.StackPointer: instruction.Operands.Add(new Operand() { AddressingMode = AddressingMode.StackPointer, Notation = OperandNotation.Source, Symbol = "SP", Value = 0, }); break; case AddressingMode.ProgramCounter: instruction.Operands.Add(new Operand() { AddressingMode = AddressingMode.ProgramCounter, Notation = OperandNotation.Source, Symbol = "PC", Value = 0, }); break; case AddressingMode.StatusRegister: instruction.Operands.Add(new Operand() { AddressingMode = AddressingMode.StatusRegister, Notation = OperandNotation.Source, Symbol = "SR", Value = 0, }); break; } } return(instruction); }
// debug helper public static Operation Disassembly(uint memIndex) { DasmSymbol symbol = BinFileDasmRecord.SymbolsList.Where(w => w.DecimalValue == memIndex).FirstOrDefault(); Operation instruction = InstructionDecode(memIndex); if (symbol != null) { if (!symbol.isLabel) { // make variable ushort dataWordValue = Functions.BytesToWord(Memory.Data[memIndex], Memory.Data[memIndex + 1]); DasmSymbol valueSymbol = BinFileDasmRecord.SymbolsList.Where(w => w.isLabel == true && w.DecimalValue == dataWordValue).FirstOrDefault(); instruction = new Operation() { OpCode = dataWordValue, OpCodeValue = dataWordValue, Length = 2, Mnemonic = "DW", Type = OperationType.Undefined, Operands = new List <Operand>() { new Operand() { Value = dataWordValue, Symbol = valueSymbol == null? string.Format("${0}", Convert.ToString(dataWordValue, 16).ToUpper().PadLeft(4, '0')) : valueSymbol.Name } } }; } } // undefined mnemonic passed as is if (instruction.Type != OperationType.Undefined) { if (instruction.Width == OperationWidth.Mixed) { instruction.Mnemonic += (instruction.OpCodeValue & 0x020) != 0 ? ".B" : string.Empty; } foreach (Operand op in instruction.Operands) { DasmSymbol valueSymbol = BinFileDasmRecord.SymbolsList.Where(w => w.DecimalValue == op.Value).FirstOrDefault(); // jumps see labels if (instruction.Type != OperationType.Branch && valueSymbol != null) { // not jumps see vars reference if (valueSymbol.isLabel && instruction.Context != OperationContext.Relative) { valueSymbol = null; } } // lovely operands values to dump if doMonitor switch (op.AddressingMode) { case AddressingMode.RegisterDirect: op.DebugText = string.Format("{0}={1}", op.Symbol, Convert.ToString(State.A[op.Value], 16).PadLeft(4, '0')); break; case AddressingMode.RegisterReference: op.DebugText = string.Format("{0}={1}", op.Symbol, Convert.ToString(Functions.BytesToWord(Memory.Data[State.A[op.Value]], Memory.Data[State.A[op.Value] + 1]), 16).PadLeft(4, '0')); break; case AddressingMode.ImmediateQuick: op.DebugText = string.Format("{0}={1}", op.Symbol, op.Value); break; case AddressingMode.Immediate: if (valueSymbol != null) // && instruction.Type == OperationType.Branch) { op.Symbol = valueSymbol.Name; } op.DebugText = string.Format("{0}={1}", op.Symbol, Convert.ToString(op.Value, 16).PadLeft(4, '0')); break; case AddressingMode.MemoryReference: if (valueSymbol != null) { op.Symbol = string.Format("({0})", valueSymbol.Name); } op.DebugText = string.Format("{0}={1}", op.Symbol, Convert.ToString(Functions.BytesToWord(Memory.Data[op.Value], Memory.Data[op.Value + 1]), 16).PadLeft(4, '0')); break; case AddressingMode.StackPointer: op.DebugText = string.Format("{0}={1}", "SP", Convert.ToString(State.SP, 16).PadLeft(4, '0')); break; case AddressingMode.StatusRegister: op.DebugText = string.Format("{0}={1}", "SR", StatusRegisterValue()); break; case AddressingMode.ProgramCounter: op.DebugText = string.Format("{0}={1}", "PC", Convert.ToString(State.PC, 16).PadLeft(4, '0'));; break; } } } instruction.DebugText = instruction.Mnemonic; if (instruction.Type == OperationType.Undefined || instruction.AddressingModeSource == AddressingMode.Internal || instruction.AddressingModeDestination == AddressingMode.Internal) { instruction.DebugText += " " + instruction.Operands[0].Symbol; } else if (instruction.Type == OperationType.Memory && instruction.AddressingModeDestination == AddressingMode.StackPointer) { instruction.DebugText += instruction.Operands[0].Symbol + " "; } else if (instruction.Type == OperationType.Memory && instruction.AddressingModeSource == AddressingMode.Internal) { instruction.DebugText += " " + instruction.Operands[0].Symbol + " "; } else { instruction.DebugText += instruction.Operands.Count() > 0 ? " " + instruction.Operands[0].Symbol + "," : string.Empty; } // GETSP if (instruction.Type == OperationType.Memory && instruction.AddressingModeSource == AddressingMode.StackPointer) { instruction.DebugText = "GETSP" + " " + instruction.Operands[0].Symbol; } else { instruction.DebugText += instruction.Operands.Count() > 1 ? instruction.Operands[1].Symbol : string.Empty; } return(instruction); }