/// @brief Reset the propeller CPU to initial state. /// @details Release cog instances, clock sources, clear locks and pins, and reset plugins. /// @version 15.03.26 - Separate reset loops for clock sources, cogs and locks. public void Reset() { ResetMemory.CopyTo(Memory, 0); SystemCounter = 0; Time = 0; RingPosition = 0; for (int i = 0; i < ClockSources.Length; i++) //clear clock source references { ClockSources[i] = null; } for (int i = 0; i < TOTAL_COGS; i++) //clear cog references { Cogs[i] = null; } CogsRunning = 0; for (int i = 0; i < TOTAL_LOCKS; i++) //clear locks state { LocksAvailable[i] = true; LocksState[i] = false; } PinChanged(); //update situation of pins foreach (PluginCommon plugin in PlugIns) { plugin.OnReset(); } SetClockMode((byte)(ClockMode & 0x7F)); // Start the runtime in interpreted mode (fake boot) // Pushes the 3 primary offsets (local offset, var offset, and object offset) // Stack -1 is the boot parameter uint InitFrame = ReadWord(10); WriteWord(InitFrame - 8, ReadWord(6)); // Object WriteWord(InitFrame - 6, ReadWord(8)); // Var WriteWord(InitFrame - 4, ReadWord(12)); // Local WriteWord(InitFrame - 2, ReadWord(14)); // Stack // Boot parameter is Initial PC in the lo word, and the stack frame in the hi word ClockSources[0] = new PLLGroup(); Cogs[0] = new InterpretedCog(this, InitFrame, CoreFreq, (PLLGroup)ClockSources[0]); CogsRunning = 1; }
private void Repaint(bool tick, InterpretedCog host) { Graphics g = Graphics.FromImage((Image)BackBuffer); Brush brush; g.Clear(SystemColors.Control); String display; uint topLine, bottomLine; topLine = 5; bottomLine = (uint)((ClientRectangle.Height / MonoFont.Height) - 5); zeroFlagLabel.Text = ""; carryFlagLabel.Text = ""; OpcodeSize.Visible = true; DisplayUnits.Visible = true; if (memoryViewButton.Checked) { for (uint i = (uint)positionScroll.Value, y = 0; y < ClientRectangle.Height; y += (uint)MonoFont.Height, i++) { if ((i > 0xFFFF) || (i < 0)) { continue; } uint mem = host[(int)i]; string binary = Convert.ToString((long)mem, 2); while (binary.Length < 32) { binary = "0" + binary; } display = String.Format("{0:X4}: {1:X8} {2} ", i, mem, binary); if (displayAsHexadecimal) { display = display + String.Format("{0:X8}", mem); } else { display = display + String.Format("{0}", mem); } g.FillRectangle(SystemBrushes.Control, 0, y, assemblyPanel.Width, y + MonoFont.Height); g.DrawString( display, (host.ProgramCursor == i) ? MonoFontBold : MonoFont, SystemBrushes.ControlText, 0, y); } } else { uint y = 0; for (uint i = (uint)positionScroll.Value, line = 1; y < ClientRectangle.Height; y += (uint)MonoFont.Height, line++) { if (i > 0xFFFF) { continue; } uint start = i; Propeller.MemoryManager mem = new Propeller.MemoryManager(Chip, i); string inst = InstructionDisassembler.InterpreterText(mem, displayAsHexadecimal, useShortOpcodes); i = mem.Address; display = String.Format("{0:X4}: ", start); InterpAddress[line] = start; for (uint q = start; q < start + 4; q++) { if (q < i) { byte b = Chip.DirectReadByte(q); display += String.Format(" {0:X2}", b); } else { display += " "; } } display += " " + inst; if (InterpAddress[line] == host.BreakPoint) { brush = System.Drawing.Brushes.Pink; } else if ((!followPCButton.Checked) || (line <= topLine) || (line >= bottomLine)) { brush = SystemBrushes.Control; } else { brush = SystemBrushes.Window; } g.FillRectangle(brush, 0, y, assemblyPanel.Width, y + MonoFont.Height); g.DrawString( display, (host.ProgramCursor == start) ? MonoFontBold : MonoFont, SystemBrushes.ControlText, 0, y); } StringBrush = SystemBrushes.ControlText; StringY = 0; StringX = (uint)(assemblyPanel.Width - StackMargin); DrawString(g, String.Format("@Stk[0] = ${0:X4} {0}", host.Stack)); DrawString(g, String.Format("@Obj[0] = ${0:X4} {0}", host.Object)); DrawString(g, String.Format("@Loc[0] = ${0:X4} {0}", host.Local)); DrawString(g, String.Format("@Var[0] = ${0:X4} {0}", host.Variable)); g.DrawLine(Pens.Black, assemblyPanel.Width - StackMargin, StringY, assemblyPanel.Width, StringY); DrawString(g, String.Format("Caller& = ${0:X4} {0}", Chip.DirectReadWord(host.Local - 8))); DrawString(g, String.Format(" ${0:X4} {0}", Chip.DirectReadWord(host.Local - 6))); DrawString(g, String.Format(" ${0:X4} {0}", Chip.DirectReadWord(host.Local - 4))); DrawString(g, String.Format("Return& = ${0:X4}", Chip.DirectReadWord(host.Local - 2))); g.DrawLine(Pens.Black, assemblyPanel.Width - StackMargin, StringY, assemblyPanel.Width, StringY); for (uint i = host.Local; i < host.Stack && StringY < ClientRectangle.Height; i += 4) { DrawString(g, String.Format("${0:X8} {0}", (int)Chip.DirectReadLong(i))); } } }
/// @brief Execute the hub operations. /// @details This method is called from a cog to do the operations related to all the CPU. /// @version 15.03.26 - corrected problem in COGSTOP return. /// @param[in] caller Reference to the caller Cog of this method. /// @param[in] operation Hub operation to execute. /// @param[in] argument Parameter given to the opcode (destination field in PASM). /// @param[in,out] carry Carry flag that could be affected by the operation. /// @param[in,out] zero Zero flag that could be affected by the operation. /// @returns Value depending on operation. /// @note Reference of supported Operations, based in Propeller Manual v1.2: /// @arg HUBOP_CLKSET - page 271. /// @arg HUBOP_COGID - page 283. /// @arg HUBOP_COGINIT - page 284. /// @arg HUBOP_COGSTOP - page 286. /// @arg HUBOP_LOCKNEW - page 304. /// @arg HUBOP_LOCKRET - page 305. /// @arg HUBOP_LOCKSET - page 306. /// @arg HUBOP_LOCKCLR - page 303. public uint HubOp(Cog caller, uint operation, uint argument, ref bool carry, ref bool zero) { uint maskedArg = (argument & 0x7); uint cog = (uint)Cogs.Length; switch ((HubOperationCodes)operation) { case HubOperationCodes.HUBOP_CLKSET: zero = false; carry = false; SetClockMode((byte)argument); break; case HubOperationCodes.HUBOP_COGID: carry = false; cog = CogID(caller); zero = (cog == 0) ? true : false; return(cog); case HubOperationCodes.HUBOP_COGINIT: //determine witch cog start if ((argument & 0x8) != 0) //if free cog should be started (bit 3 is set) { for (uint i = 0; i < Cogs.Length; i++) //assign the first free cog { if (Cogs[i] == null) { cog = i; break; } } if (cog >= Cogs.Length) { carry = true; //no free cog return(0xFFFFFFFF); } else { carry = false; } } else // instead specific cog should be started { cog = maskedArg; } zero = (cog == 0) ? true : false; PLLGroup pll = new PLLGroup(); ClockSources[cog] = (ClockSource)pll; uint param = (argument >> 16) & 0xFFFC; //decode param value uint progm = (argument >> 2) & 0xFFFC; //decode program address to load to if (progm == 0xF004) { Cogs[cog] = new InterpretedCog(this, param, CoreFreq, pll); } else { Cogs[cog] = new NativeCog(this, progm, param, CoreFreq, pll); } CogsRunning++; return((uint)cog); case HubOperationCodes.HUBOP_COGSTOP: zero = (maskedArg == 0) ? true: false; carry = (CogsRunning < TOTAL_COGS) ? false : true; Stop((int)maskedArg); CogsRunning--; return(maskedArg); case HubOperationCodes.HUBOP_LOCKCLR: zero = (maskedArg == 0) ? true : false; carry = LocksState[maskedArg]; LocksState[maskedArg] = false; return(argument); case HubOperationCodes.HUBOP_LOCKNEW: zero = false; // initial value if no Locks available carry = true; // initial value if no Locks available for (uint i = 0; i < LocksAvailable.Length; i++) { if (LocksAvailable[i]) { LocksAvailable[i] = false; carry = false; if (i == 0) { zero = true; } return(i); } } return(7); // if all are occupied, return a 7, but carry is true case HubOperationCodes.HUBOP_LOCKRET: zero = (maskedArg == 0) ? true : false; carry = true; // initial value if no Locks available for (uint i = 0; i < LocksAvailable.Length; i++) { if (LocksAvailable[i]) { carry = false; } } LocksAvailable[maskedArg] = true; return(maskedArg); case HubOperationCodes.HUBOP_LOCKSET: zero = (maskedArg == 0) ? true : false; carry = LocksState[maskedArg]; LocksState[maskedArg] = true; return(maskedArg); default: // TODO: RAISE EXCEPTION break; } return(0); }