/// <summary> /// Sets the PIC execution mode per the XINST device configuration bit value (if present in the memory image). /// If no XINST bit can be found in the image or for this processor, the PIC execution mode is left to the user's choice. /// </summary> private void SetPICExecMode() { PICExecMode pexec = architecture.Options.PICExecutionMode; var dcf = PICMemoryDescriptor.GetDCRField("XINST"); if (dcf != null) { var dcr = PICMemoryDescriptor.GetDCR(dcf.RegAddress); if (program.SegmentMap.TryFindSegment(dcr.Address, out ImageSegment xinstsegt)) { uint xinstval; if (dcr.BitWidth <= 8) { xinstval = xinstsegt.MemoryArea.ReadByte(dcf.RegAddress); } else if (dcr.BitWidth <= 16) { xinstval = xinstsegt.MemoryArea.ReadLeUInt16(dcf.RegAddress); } else { xinstval = xinstsegt.MemoryArea.ReadLeUInt32(dcf.RegAddress); } pexec = (dcr.CheckIf("XINST", "ON", xinstval) ? PICExecMode.Extended : PICExecMode.Traditional); } } else { pexec = PICExecMode.Traditional; } PICMemoryDescriptor.ExecMode = pexec; architecture.Options.PICExecutionMode = pexec; architecture.Description = architecture.Options.ProcessorModel.PICName + $" ({pexec})"; }
protected override void DoRender(MachineInstructionRenderer renderer, MachineInstructionRendererOptions options) { var memop = Operands[0] as PICOperandBankedMemory ?? throw new InvalidOperationException($"Invalid memory operand: {Operands[0]}"); renderer.WriteMnemonic(Mnemonic.ToString()); renderer.Tab(); var bankmem = PICMemoryDescriptor.CreateBankedAddr(memop); if (PICRegisters.TryGetAlwaysAccessibleRegister(bankmem, out var reg)) { renderer.WriteString($"{reg.Name}"); } else { Operands[0].Render(renderer, options); } }
public override void Render(MachineInstructionWriter writer, MachineInstructionWriterOptions options) { var memop = op1 as PICOperandBankedMemory ?? throw new InvalidOperationException($"Invalid memory operand: {op1}"); writer.WriteOpcode(Opcode.ToString()); writer.Tab(); var bankmem = PICMemoryDescriptor.CreateBankedAddr(memop); if (PICRegisters.TryGetAlwaysAccessibleRegister(bankmem, out var reg)) { writer.WriteString($"{reg.Name}"); } else { op1.Write(writer, options); } }
private Program PerformValidation() { var user = program.User; user.TextEncoding = Encoding.ASCII; bool renameSection = architecture.Options.LoaderType == "raw"; // Re-assign memory segments according to PIC program memory space definition. Rename segments, as-needed (raw file, segment larger than PIC memory region). foreach (var segt in program.SegmentMap.Segments.Values) { var curAddr = segt.Address; var curSize = segt.ContentSize; do { var regn = PICMemoryDescriptor.GetProgramRegion(curAddr); if (regn == null) { throw new InvalidOperationException("Attempt to load a binary image which is not compatible with the selected PIC's program memory space."); } var fitSize = Math.Min(regn.PhysicalByteAddrRange.End - curAddr, curSize); if (fitSize <= 0) { throw new InvalidOperationException("Attempt to load a binary image which is not compatible with the selected PIC's program memory space."); } var rd = segt.MemoryArea.CreateLeReader(curAddr); var b = rd.ReadBytes((int)fitSize); var splitMem = new MemoryArea(curAddr, b); string segmentName = (renameSection ? GetRegionSequentialName(regn) : GetSegmentSequentialName(segt)); var newsegt = new ImageSegment(segmentName, splitMem, GetAccessMode(regn)); newMap.AddSegment(newsegt); curSize -= (uint)fitSize; curAddr += fitSize; } while (curSize > 0); } program.SegmentMap = newMap; SetPICExecMode(); SetRegistersAtPOR(); return(program); }
/// <summary> /// Disassemble a single instruction. Return null if the end of the reader has been reached. /// </summary> /// <returns> /// A <seealso cref="PICInstruction"/> instance. /// </returns> /// <exception cref="AddressCorrelatedException">Thrown when the Address Correlated error /// condition occurs.</exception> public override PICInstruction DisassembleInstruction() { IMemoryRegion GetProgRegion() { if (lastusedregion != null && lastusedregion.Contains(addrCur)) { return(lastusedregion); } return(lastusedregion = PICMemoryDescriptor.GetProgramRegion(addrCur)); } if (!rdr.IsValid) { return(null); } addrCur = PICProgAddress.Ptr(rdr.Address); var regn = GetProgRegion(); if (regn is null) { throw new InvalidOperationException($"Unable to retrieve program memory region for address {addrCur.ToString()}."); } if ((addrCur.Offset % (regn.Trait?.LocSize ?? 1)) != 0) { instrCur = new PICInstructionNoOpnd(Mnemonic.unaligned) { Address = addrCur, Length = 1 }; rdr.Offset += 1; // Consume only the first byte of the binary instruction. return(instrCur); } switch (regn.SubtypeOfMemory) { case PICMemorySubDomain.Code: case PICMemorySubDomain.ExtCode: case PICMemorySubDomain.Debugger: if (!rdr.TryReadUInt16(out ushort uInstr)) { return(null); } return(DecodePICInstruction(uInstr, PICProgAddress.Ptr(rdr.Address))); case PICMemorySubDomain.EEData: return(DecodeEEPROMInstruction()); case PICMemorySubDomain.UserID: return(DecodeUserIDInstruction()); case PICMemorySubDomain.DeviceConfig: return(DecodeConfigInstruction()); case PICMemorySubDomain.DeviceID: return(DecodeDWInstruction()); case PICMemorySubDomain.DeviceConfigInfo: //TODO: Decode DCI return(DecodeDCIInstruction()); case PICMemorySubDomain.DeviceInfoAry: //TODO: Decode DIA return(DecodeDIAInstruction()); case PICMemorySubDomain.RevisionID: //TODO: Decode Revision ID return(DecodeRevisionIDInstruction()); case PICMemorySubDomain.Test: case PICMemorySubDomain.Other: default: throw new NotImplementedException($"Disassembly of '{regn.SubtypeOfMemory}' memory region is not yet implemented."); } }
protected override void DoRender(MachineInstructionRenderer renderer, MachineInstructionRendererOptions options) { var s = PICMemoryDescriptor.RenderDeviceConfigRegister(addr, Values[0]); renderer.WriteString(s); }
public override void Write(MachineInstructionWriter writer, MachineInstructionWriterOptions options) { var s = PICMemoryDescriptor.RenderDeviceConfigRegister(addr, Values[0]); writer.WriteString(s); }