aboutsummaryrefslogtreecommitdiff
path: root/SrcShared/SystemPacket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SrcShared/SystemPacket.cpp')
-rw-r--r--SrcShared/SystemPacket.cpp1282
1 files changed, 1282 insertions, 0 deletions
diff --git a/SrcShared/SystemPacket.cpp b/SrcShared/SystemPacket.cpp
new file mode 100644
index 0000000..8b1a104
--- /dev/null
+++ b/SrcShared/SystemPacket.cpp
@@ -0,0 +1,1282 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "SystemPacket.h"
+
+#include "ATraps.h" // ATrap
+#include "DebugMgr.h" // Debug::
+#include "EmBankMapped.h" // EmBankMapped::GetEmulatedAddress
+#include "EmCPU68K.h" // gCPU68K->UpdateRegistersFromSR
+#include "EmErrCodes.h" // kError_NoError
+#include "EmLowMem.h" // EmLowMem_GetGlobal
+#include "EmMemory.h" // EmMem_memcpy
+#include "EmPalmFunction.h" // FindFunctionName
+#include "EmPalmStructs.h" // EmSysPktRPCType, etc
+#include "EmRPC.h" // slkSocketRPC
+#include "EmSession.h" // EmSession::Reset
+#include "HostControl.h" // hostSelectorWaitForIdle
+#include "Logging.h" // LogAppendMsg
+#include "Platform.h" // Platform::ExitDebugger
+#include "SLP.h" // SLP
+
+#include <ctype.h> // isalpha
+
+
+/*
+ This module implements the handling of all "serial link" packets.
+
+ Serial Link packets can be sent to Poser via a number of mechanisms:
+
+ * serial connections
+ * TCP connections
+ * PPC Toolbox connections (Macintosh)
+ * Memory-mapped file connection (Windows)
+
+ Regardless of how they're received, they get processed by SLP::HandleNewPacket.
+ This function looks at the destination of the packet specified in the packet
+ header. Currently, there are three supported targets in Poser:
+
+ * Debugger socket (also supported by Palm OS debugger nub)
+ * Console socket (also supported by Palm OS debugger nub)
+ * RPC socket (Poser specific)
+
+ Before handing the packet off to a socket-specific packet handler,
+ SLP::HandleNewPacket (which is running in the UI thread) synchronizes
+ with the CPU thread. For the debugger socket, it halts the thread
+ at whatever spot it's in. For the other sockets, it halts the thread
+ the next time a system call is made.
+
+ Poser's Debugger sub-system handles packets targeted to the debugger
+ and console sockets. Poser's RPC sub-system handles packets targeted
+ to the RPC socket.
+
+ The three sockets handle the following packets:
+
+ Debugger
+ sysPktStateCmd
+ sysPktReadMemCmd
+ sysPktWriteMemCmd
+ sysPktGetRtnNameCmd
+ sysPktReadRegsCmd
+ sysPktWriteRegsCmd
+ sysPktContinueCmd
+ sysPktRPCCmd
+ sysPktSetBreakpointsCmd
+ sysPktDbgBreakToggleCmd
+ sysPktGetTrapBreaksCmd
+ sysPktSetTrapBreaksCmd
+ sysPktFindCmd
+ sysPktGetTrapConditionsCmd
+ sysPktSetTrapConditionsCmd
+
+ Console
+ sysPktRPCCmd
+
+ RPC
+ sysPktReadMemCmd
+ sysPktWriteMemCmd
+ sysPktRPCCmd
+ sysPktRPC2Cmd
+
+ The Console and RPC sockets will always handle the packet they receive
+ (assuming that the UI thread has first synchronized with the CPU thread
+ on a system call first). If the packet is sent to the Debugger socket,
+ then the CPU must first be in "debug mode". This debug mode is automatically
+ entered if an error or exception has occurred and Poser has sent a "state"
+ packet to the external debugger. After that point, the external debugger
+ can send any packet it wants, optionally exiting debug mode by sending
+ a "Continue" packet, or perhaps sending an RPC packet to invoke the
+ SysReset Palm OS function.
+
+ An external debugger can also force the entry into "debug mode" by sending
+ a "get state" request packet to the Debugger socket. If the CPU is not in
+ debug mode, Poser will enter debug mode as a courtesey. Note that this is
+ a Poser-specific extension to the way the Debugger socket works. The Palm
+ OS ROM doesn't work this way.
+
+ All other packets sent to the Debugger socket are silently ignored if the
+ CPU is not in "debug mode".
+
+ ------------------------------------------------------------------------------
+
+ Crib notes on the supported packets:
+
+ +- Called by Debugger
+ | +- Implemented
+ | | Command
+ | | Command name Number Sent to
+ ------- --------------------------- ----------- -----------------
+ * * sysPktStateCmd 0x00 slkSocketDebugger SysPktStateCmdType SysPktStateRspType
+ * * sysPktReadMemCmd 0x01 slkSocketDebugger SysPktReadMemCmdType SysPktReadMemRspType
+ * * sysPktWriteMemCmd 0x02 slkSocketDebugger SysPktWriteMemCmdType SysPktWriteMemRspType
+ * . sysPktSingleStepCmd 0x03
+ * * sysPktGetRtnNameCmd 0x04 slkSocketDebugger SysPktRtnNameCmdType SysPktRtnNameRspType
+ * * sysPktReadRegsCmd 0x05 slkSocketDebugger SysPktReadRegsCmdType SysPktReadRegsRspType
+ * * sysPktWriteRegsCmd 0x06 slkSocketDebugger SysPktWriteRegsCmdType SysPktWriteRegsRspType
+ * * sysPktContinueCmd 0x07 slkSocketDebugger SysPktContinueCmdType <no response>
+ * * sysPktRPCCmd 0x0A both* SysPktRPCType
+ * sysPktGetBreakpointsCmd 0x0B SysPktGetBreakpointsCmdType SysPktGetBreakpointsRspType
+ * * sysPktSetBreakpointsCmd 0x0C slkSocketDebugger SysPktSetBreakpointsCmdType SysPktSetBreakpointsRspType
+ . sysPktRemoteUIUpdCmd 0x0C SysPktRemoteUIUpdCmdType
+ . sysPktRemoteEvtCmd 0x0D SysPktRemoteEvtCmdType
+ * * sysPktDbgBreakToggleCmd 0x0D slkSocketDebugger SysPktDbgBreakToggleCmdType SysPktDbgBreakToggleRspType
+ * . sysPktFlashCmd 0x0E SysPktFlashWriteType
+ * . sysPktCommCmd 0x0F both* SysPktCommCmdType SysPktCommRspType
+ * * sysPktGetTrapBreaksCmd 0x10 slkSocketDebugger SysPktGetTrapBreaksCmdType SysPktGetTrapBreaksRspType
+ * * sysPktSetTrapBreaksCmd 0x11 slkSocketDebugger SysPktSetTrapBreaksCmdType SysPktSetTrapBreaksRspType
+ + sysPktGremlinsCmd 0x12 slkSocketConsole SysPktGremlinsCmdType
+ * * sysPktFindCmd 0x13 slkSocketDebugger SysPktFindCmdType SysPktFindRspType
+ * sysPktGetTrapConditionsCmd 0x14 slkSocketDebugger SysPktGetTrapConditionsCmdType SysPktGetTrapConditionsRspType
+ * sysPktSetTrapConditionsCmd 0x15 slkSocketDebugger SysPktSetTrapConditionsCmdType SysPktSetTrapConditionsRspType
+ . sysPktChecksumCmd 0x16 slkSocketDebugger SysPktChecksumType
+ . sysPktExecFlashCmd 0x17 slkSocketDebugger sysPktExecFlashType
+ * * sysPktRemoteMsgCmd 0x7f both SysPktRemoteMsgCmdType
+
+ "both*" = if attached, sent to slkSocketDebugger, else slkSocketConsole
+*/
+
+#define sysPktBadFormatRsp 0xFF
+
+
+#define ENTER_CODE(fnName, cmdType, rspType) \
+ PRINTF ("Entering SystemPacket::" fnName "."); \
+ EmAlias##cmdType<LAS> packet (slp.Body ().GetPtr ())
+
+
+#define ENTER_PACKET(fnName, cmdType, rspType) \
+ PRINTF ("Entering SystemPacket::" fnName "."); \
+ EmAlias##cmdType<LAS> packet (slp.Body ().GetPtr ()); \
+ EmProxy##rspType response
+
+
+#define EXIT_PACKET(fnName, code, bodySize) \
+ response.command = code; \
+ response._filler = 0; \
+ ErrCode result = SystemPacket::SendPacket (slp, response.GetPtr(), bodySize); \
+ PRINTF ("Exiting SystemPacket::" fnName "."); \
+ return result
+
+
+#define EXIT_CODE(fnName, code) \
+ ErrCode result = SystemPacket::SendResponse (slp, code); \
+ PRINTF ("Exiting SystemPacket::" fnName "."); \
+ return result
+
+
+#define PRINTF if (!LogHLDebugger ()) ; else LogAppendMsg
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SendState
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SendState (SLP& slp)
+{
+ // Do this function entry by hand instead of using the ENTER_PACKET macro.
+ // That macro will call SLP::Body, which returns a reference to the
+ // packet body that was sent to us. However, SendState (a) doesn't
+ // need the body reference, so there's no need to set it up, and (b)
+ // isn't necessarily called in response to a "SendState" command,
+ // and so the reference may be NULL.
+
+ PRINTF ("Entering SystemPacket::SendState.");
+ EmProxySysPktStateRspType response;
+
+ // Get the resetted boolean. This flag is true if the "device" has
+ // been resetted since the last time we sent a packet. The debugger
+ // needs to know this in order to update its notion of the device's
+ // state (like, for instance, if breakpoints are installed).
+
+ response.resetted = gDebuggerGlobals.firstEntrance;
+ gDebuggerGlobals.firstEntrance = false;
+
+ // Get the exception id.
+
+ response.exceptionId = gDebuggerGlobals.excType;
+
+ // Get the registers.
+
+ M68KRegsType reg;
+ SystemPacket::GetRegs (reg);
+
+ response.reg.d[0] = reg.d[0];
+ response.reg.d[1] = reg.d[1];
+ response.reg.d[2] = reg.d[2];
+ response.reg.d[3] = reg.d[3];
+ response.reg.d[4] = reg.d[4];
+ response.reg.d[5] = reg.d[5];
+ response.reg.d[6] = reg.d[6];
+ response.reg.d[7] = reg.d[7];
+ response.reg.a[0] = reg.a[0];
+ response.reg.a[1] = reg.a[1];
+ response.reg.a[2] = reg.a[2];
+ response.reg.a[3] = reg.a[3];
+ response.reg.a[4] = reg.a[4];
+ response.reg.a[5] = reg.a[5];
+ response.reg.a[6] = reg.a[6];
+ response.reg.usp = reg.usp;
+ response.reg.ssp = reg.ssp;
+ response.reg.pc = reg.pc;
+ response.reg.sr = reg.sr;
+
+ // Get the breakpoints.
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ response.bp[ii].addr = gDebuggerGlobals.bp[ii].addr;
+ response.bp[ii].enabled = gDebuggerGlobals.bp[ii].enabled;
+ response.bp[ii].installed = gDebuggerGlobals.bp[ii].installed;
+ }
+
+ // Get some code beginning at PC.
+
+ emuptr pc = m68k_getpc ();
+ for (int jj = 0; jj < sysPktStateRspInstWords; ++jj)
+ {
+ // Do this as two fetches in case the PC is odd.
+ response.inst[jj] = EmMemGet8 (pc + 2 * jj + 0) * 256 +
+ EmMemGet8 (pc + 2 * jj + 1);
+ }
+
+
+ // Get the routine name and address range info.
+
+ void* startAddr;
+ void* endAddr;
+ memset (response.name.GetPtr (), 0, sysPktMaxNameLen);
+ ::FindFunctionName ( pc & 0xFFFFFFFE, // Protect against odd addresses.
+ (char*) response.name.GetPtr (),
+ (emuptr*) &startAddr,
+ (emuptr*) &endAddr);
+
+ response.startAddr = startAddr;
+ response.endAddr = endAddr;
+
+ // Send the rev of the trap table.
+
+ response.trapTableRev = EmLowMem_GetGlobal (sysDispatchTableRev);
+
+ EXIT_PACKET ("SendState", sysPktStateRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::ReadMem
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::ReadMem (SLP& slp)
+{
+ ENTER_PACKET ("ReadMem", SysPktReadMemCmdType, SysPktReadMemRspType);
+
+ void* dest = response.data.GetPtr ();
+ emuptr src = (emuptr) packet.address;
+ UInt16 len = packet.numBytes;
+
+ memset (dest, 0xFF, len); // Clear buffer in case of failure.
+
+ if (len > 0 && EmMemCheckAddress (src, 1) && EmMemCheckAddress (src + len - 1, 1))
+ {
+ EmMem_memcpy (dest, src, len);
+ }
+
+ EXIT_PACKET ("ReadMem", sysPktReadMemRsp,
+ EmProxySysPktEmptyRspType::GetSize () + packet.numBytes);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::WriteMem
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::WriteMem (SLP& slp)
+{
+ ENTER_CODE ("WriteMem", SysPktWriteMemCmdType, SysPktWriteMemRspType);
+
+ emuptr dest = (emuptr) packet.address;
+ const void* src = packet.data.GetPtr ();
+ UInt16 len = packet.numBytes;
+
+ if (len > 0 && EmMemCheckAddress (dest, 1) && EmMemCheckAddress (dest + len - 1, 1))
+ {
+ EmMem_memcpy (dest, src, len);
+ }
+
+ // If we just altered low memory, recalculate the low-memory checksum.
+ // Make sure we're on a ROM that has this field! Determine this by
+ // seeing that the address of sysLowMemChecksum is below the memCardInfo
+ // fields that come after the FixedGlobals.
+ //
+ // !!! This chunk of code should be in some more generally accessible location.
+
+ if (offsetof (LowMemType, fixed.globals.sysLowMemChecksum) < EmLowMem_GetGlobal (memCardInfoP))
+ {
+ if ((emuptr) packet.address < (emuptr) 0x100)
+ {
+ UInt32 checksum = 0;
+ emuptr csP = EmMemNULL;
+
+ // First, calculate the checksum
+
+ while (csP < (emuptr) 0x100)
+ {
+ UInt32 data = EmMemGet32 (csP);
+
+ // Don't do these trap vectors since they change whenever the
+ // debugger is set to break on any a-trap or breakpoint.
+
+ if (csP == offsetof (M68KExcTableType, trapN[sysDispatchTrapNum]))
+ data = 0;
+
+ if (csP == offsetof (M68KExcTableType, trapN[sysDbgBreakpointTrapNum]))
+ data = 0;
+
+ if (csP == offsetof (M68KExcTableType, trace))
+ data = 0;
+
+ checksum += data;
+ csP += 4;
+ }
+
+ // Save new checksum
+
+ EmLowMem_SetGlobal (sysLowMemChecksum, checksum);
+ }
+ }
+
+ EXIT_CODE ("WriteMem", sysPktWriteMemRsp);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SendRoutineName
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SendRoutineName (SLP& slp)
+{
+ ENTER_PACKET ("SendRoutineName", SysPktRtnNameCmdType, SysPktRtnNameRspType);
+
+ emuptr pc = ((emuptr) packet.address) & ~1; // Protect against odd address.
+ void* startAddr;
+ void* endAddr;
+
+ ::FindFunctionName( pc, (char*) response.name.GetPtr (),
+ (emuptr*) &startAddr,
+ (emuptr*) &endAddr);
+
+ response.address = packet.address;
+ response.startAddr = startAddr;
+ response.endAddr = endAddr;
+
+ EXIT_PACKET ("SendRoutineName", sysPktGetRtnNameRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::ReadRegs
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::ReadRegs (SLP& slp)
+{
+ ENTER_PACKET ("ReadRegs", SysPktReadRegsCmdType, SysPktReadRegsRspType);
+ UNUSED_PARAM (packet)
+
+ // Get the registers.
+
+ M68KRegsType reg;
+ SystemPacket::GetRegs (reg);
+
+ response.reg.d[0] = reg.d[0];
+ response.reg.d[1] = reg.d[1];
+ response.reg.d[2] = reg.d[2];
+ response.reg.d[3] = reg.d[3];
+ response.reg.d[4] = reg.d[4];
+ response.reg.d[5] = reg.d[5];
+ response.reg.d[6] = reg.d[6];
+ response.reg.d[7] = reg.d[7];
+ response.reg.a[0] = reg.a[0];
+ response.reg.a[1] = reg.a[1];
+ response.reg.a[2] = reg.a[2];
+ response.reg.a[3] = reg.a[3];
+ response.reg.a[4] = reg.a[4];
+ response.reg.a[5] = reg.a[5];
+ response.reg.a[6] = reg.a[6];
+ response.reg.usp = reg.usp;
+ response.reg.ssp = reg.ssp;
+ response.reg.pc = reg.pc;
+ response.reg.sr = reg.sr;
+
+ EXIT_PACKET ("ReadRegs", sysPktReadRegsRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::WriteRegs
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::WriteRegs (SLP& slp)
+{
+ ENTER_CODE ("WriteRegs", SysPktWriteRegsCmdType, SysPktWriteRegsRspType);
+
+ M68KRegsType reg;
+
+ reg.d[0] = packet.reg.d[0];
+ reg.d[1] = packet.reg.d[1];
+ reg.d[2] = packet.reg.d[2];
+ reg.d[3] = packet.reg.d[3];
+ reg.d[4] = packet.reg.d[4];
+ reg.d[5] = packet.reg.d[5];
+ reg.d[6] = packet.reg.d[6];
+ reg.d[7] = packet.reg.d[7];
+ reg.a[0] = packet.reg.a[0];
+ reg.a[1] = packet.reg.a[1];
+ reg.a[2] = packet.reg.a[2];
+ reg.a[3] = packet.reg.a[3];
+ reg.a[4] = packet.reg.a[4];
+ reg.a[5] = packet.reg.a[5];
+ reg.a[6] = packet.reg.a[6];
+ reg.usp = packet.reg.usp;
+ reg.ssp = packet.reg.ssp;
+ reg.pc = packet.reg.pc;
+ reg.sr = packet.reg.sr;
+
+ SystemPacket::SetRegs (reg);
+
+ EXIT_CODE ("ReadRegs", sysPktWriteRegsRsp);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::Continue
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::Continue (SLP& slp)
+{
+ ENTER_CODE ("Continue", SysPktContinueCmdType, SysPktContinueCmdType);
+
+ M68KRegsType reg;
+
+ reg.d[0] = packet.regs.d[0];
+ reg.d[1] = packet.regs.d[1];
+ reg.d[2] = packet.regs.d[2];
+ reg.d[3] = packet.regs.d[3];
+ reg.d[4] = packet.regs.d[4];
+ reg.d[5] = packet.regs.d[5];
+ reg.d[6] = packet.regs.d[6];
+ reg.d[7] = packet.regs.d[7];
+ reg.a[0] = packet.regs.a[0];
+ reg.a[1] = packet.regs.a[1];
+ reg.a[2] = packet.regs.a[2];
+ reg.a[3] = packet.regs.a[3];
+ reg.a[4] = packet.regs.a[4];
+ reg.a[5] = packet.regs.a[5];
+ reg.a[6] = packet.regs.a[6];
+ reg.usp = packet.regs.usp;
+ reg.ssp = packet.regs.ssp;
+ reg.pc = packet.regs.pc;
+ reg.sr = packet.regs.sr;
+
+ SystemPacket::SetRegs (reg);
+
+
+ gDebuggerGlobals.stepSpy = packet.stepSpy != 0;
+ gDebuggerGlobals.ssAddr = packet.ssAddr;
+ // ssCount is ignored?
+ gDebuggerGlobals.ssValue = packet.ssCheckSum;
+
+ ErrCode result = Debug::ExitDebugger ();
+
+ // Perform any platform-specific actions.
+
+ if (result == errNone)
+ {
+ Platform::ExitDebugger ();
+ }
+
+ // No reply...
+
+ PRINTF ("Exiting SystemPacket::Continue.");
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::RPC
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::RPC (SLP& slp)
+{
+ ENTER_PACKET ("RPC", SysPktRPCType, SysPktRPCType);
+
+ // Handle calls to SysReset specially, since that function never
+ // returns. Do this *before* creating the ATrap object, as that
+ // object's d'tor will attempt to restore the PC to what it was
+ // when the c'tor was run.
+
+ if (packet.trapWord == sysTrapSysReset)
+ {
+#if 0
+ emuptr sysResetAddr = EmLowMem::GetTrapAddress (sysTrapSysReset);
+ EmAssert (sysResetAddr);
+
+ m68k_setpc (sysResetAddr);
+
+ // Exit trace mode. On an actual device, debugger packets (including
+ // the final call to SysReset) are handled at interrupt time when
+ // trace mode is turned off. However, on Poser, trace mode may be
+ // left on by any previous single-step commands since we handle
+ // debugger packets "between cycles" and not at interrupt time.
+
+ regs.t1 = regs.t0 = regs.m = 0;
+ regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
+#else
+ // Call EmSession::Reset instead of doing the above in order
+ // to more cleanly exit not only trace mode, but debug mode
+ // and any other modes I didn't think of.
+ EmAssert (gSession);
+ gSession->Reset (kResetSoft);
+#endif
+
+ return kError_NoError;
+ }
+
+
+ ATrap trap;
+
+ // Map in the memory pointed to by the reference parameters
+ StMemoryMapper mapper (packet.GetPtr (), sysPktMaxBodySize);
+
+
+ void* paramStart = packet.param.GetPtr ();
+ void* paramPtr = paramStart;
+
+ for (UInt16 ii = 0; ii < packet.numParams; ++ii)
+ {
+ EmAliasSysPktRPCParamType<LAS> param (paramPtr);
+
+ if (param.byRef)
+ {
+ trap.PushLong (EmBankMapped::GetEmulatedAddress (param.asByte.GetPtr ()));
+ }
+ else
+ {
+ if (param.size == 1)
+ {
+ trap.PushByte (param.asByte);
+ }
+ else if (param.size == 2)
+ {
+ trap.PushWord (param.asShort);
+ }
+ else if (param.size == 4)
+ {
+ trap.PushLong (param.asLong);
+ }
+ }
+
+ paramPtr = ((char*) param.asByte.GetPtr ()) + ((param.size + 1) & ~1);
+ }
+
+
+ // Call the trap.
+
+ trap.Call (packet.trapWord);
+
+ memcpy (response.GetPtr (), packet.GetPtr (), sysPktMaxBodySize);
+
+ response.resultD0 = trap.GetD0 ();
+ response.resultA0 = trap.GetA0 ();
+
+ long numBytes = ((char*) paramPtr) - ((char*) packet.GetPtr ()); // or get from header...
+
+ EXIT_PACKET ("RPC", sysPktRPCRsp, numBytes);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::RPC2
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::RPC2 (SLP& slp)
+{
+ ENTER_PACKET ("RPC2", SysPktRPC2Type, SysPktRPC2Type);
+
+ // Handle calls to SysReset specially, since that function never
+ // returns. Do this *before* creating the ATrap object, as that
+ // object's d'tor will attempt to restore the PC to what it was
+ // when the c'tor was run.
+
+ if (packet.trapWord == sysTrapSysReset)
+ {
+#if 0
+ emuptr sysResetAddr = EmLowMem::GetTrapAddress (sysTrapSysReset);
+ EmAssert (sysResetAddr);
+
+ m68k_setpc (sysResetAddr);
+
+ // Exit trace mode. On an actual device, debugger packets (including
+ // the final call to SysReset) are handled at interrupt time when
+ // trace mode is turned off. However, on Poser, trace mode may be
+ // left on by any previous single-step commands since we handle
+ // debugger packets "between cycles" and not at interrupt time.
+
+ regs.t1 = regs.t0 = regs.m = 0;
+ regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
+#else
+ // Call EmSession::Reset instead of doing the above in order
+ // to more cleanly exit not only trace mode, but debug mode
+ // and any other modes I didn't think of.
+ EmAssert (gSession);
+ gSession->Reset (kResetSoft);
+#endif
+
+ return kError_NoError;
+ }
+
+
+ ATrap trap;
+
+ // Map in the memory pointed to by the reference parameters
+ StMemoryMapper mapper (packet.GetPtr (), sysPktMaxBodySize);
+
+
+ // Extract any D-registers from the packet.
+
+ UInt32* regsP = (UInt32*) packet.Regs.GetPtr ();
+ int mask = 0x01;
+ int regNum = 0;
+
+ while (mask < 0x100)
+ {
+ if ((mask & packet.DRegMask) != 0)
+ {
+ EmAliasUInt32<LAS> reg (regsP++);
+ trap.SetNewDReg (regNum, reg);
+ }
+
+ ++regNum;
+ mask <<= 1;
+ }
+
+ // Extract any A-registers from the packet.
+
+ mask = 0x01;
+ regNum = 0;
+
+ while (mask < 0x100)
+ {
+ if ((mask & packet.ARegMask) != 0)
+ {
+ EmAliasUInt32<LAS> reg (regsP++);
+ trap.SetNewAReg (regNum, reg);
+ }
+
+ ++regNum;
+ mask <<= 1;
+ }
+
+ // Extract any stack-based parameters from the packet.
+
+ EmAliasUInt16<LAS> numParamsP (regsP);
+ UInt16 numParams = numParamsP;
+
+ void* paramStart = ((char*) regsP) + sizeof (UInt16);
+ void* paramPtr = paramStart;
+
+ for (UInt16 ii = 0; ii < numParams; ++ii)
+ {
+ EmAliasSysPktRPCParamType<LAS> param (paramPtr);
+
+ if (param.byRef)
+ {
+ trap.PushLong (EmBankMapped::GetEmulatedAddress (param.asByte.GetPtr ()));
+ }
+ else
+ {
+ if (param.size == 1)
+ {
+ trap.PushByte (param.asByte);
+ }
+ else if (param.size == 2)
+ {
+ trap.PushWord (param.asShort);
+ }
+ else if (param.size == 4)
+ {
+ trap.PushLong (param.asLong);
+ }
+ }
+
+ paramPtr = ((char*) param.asByte.GetPtr ()) + ((param.size + 1) & ~1);
+ }
+
+
+ // Call the trap.
+
+ trap.Call (packet.trapWord);
+
+ memcpy (response.GetPtr (), packet.GetPtr (), sysPktMaxBodySize);
+
+ response.resultD0 = trap.GetD0 ();
+ response.resultA0 = trap.GetA0 ();
+ response.resultException = 0;
+
+ long numBytes = ((char*) paramPtr) - ((char*) packet.GetPtr ()); // or get from header...
+
+ EXIT_PACKET ("RPC2", sysPktRPC2Rsp, numBytes);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::GetBreakpoints
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::GetBreakpoints (SLP& slp)
+{
+ ENTER_PACKET ("GetBreakpoints", SysPktGetBreakpointsCmdType, SysPktGetBreakpointsRspType);
+ UNUSED_PARAM (packet)
+
+ // Get the breakpoints.
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ response.bp[ii].addr = gDebuggerGlobals.bp[ii].addr;
+ response.bp[ii].enabled = gDebuggerGlobals.bp[ii].enabled;
+ response.bp[ii].installed = gDebuggerGlobals.bp[ii].installed;
+ }
+
+ EXIT_PACKET ("GetBreakpoints", sysPktGetBreakpointsRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SetBreakpoints
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SetBreakpoints (SLP& slp)
+{
+ ENTER_CODE ("SetBreakpoints", SysPktSetBreakpointsCmdType, SysPktSetBreakpointsRspType);
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ if (packet.bp[ii].enabled)
+ {
+ Debug::SetBreakpoint (ii, (emuptr) packet.bp[ii].addr, NULL);
+ }
+ else
+ {
+ Debug::ClearBreakpoint (ii);
+ }
+ }
+
+ EXIT_CODE ("GetBreakpoints", sysPktSetBreakpointsRsp);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::ToggleBreak
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::ToggleBreak (SLP& slp)
+{
+ ENTER_PACKET ("ToggleBreak", SysPktDbgBreakToggleCmdType, SysPktDbgBreakToggleRspType);
+ UNUSED_PARAM (packet)
+
+ gDebuggerGlobals.ignoreDbgBreaks = !gDebuggerGlobals.ignoreDbgBreaks;
+
+ response.newState = gDebuggerGlobals.ignoreDbgBreaks;
+
+ EXIT_PACKET ("ToggleBreak", sysPktDbgBreakToggleRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::GetTrapBreaks
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::GetTrapBreaks (SLP& slp)
+{
+ ENTER_PACKET ("GetTrapBreaks", SysPktGetTrapBreaksCmdType, SysPktGetTrapBreaksRspType);
+ UNUSED_PARAM (packet)
+
+ for (int ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ response.trapBP[ii] = gDebuggerGlobals.trapBreak[ii];
+ }
+
+ EXIT_PACKET ("GetTrapBreaks", sysPktGetTrapBreaksRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SetTrapBreaks
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SetTrapBreaks (SLP& slp)
+{
+ ENTER_CODE ("SetTrapBreaks", SysPktSetTrapBreaksCmdType, SysPktSetTrapBreaksRspType);
+
+ for (int ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ gDebuggerGlobals.trapBreak[ii] = packet.trapBP[ii];
+ }
+
+ gDebuggerGlobals.breakingOnATrap = false;
+ for (int jj = 0; jj < dbgTotalTrapBreaks; ++jj)
+ {
+ if (gDebuggerGlobals.trapBreak[jj])
+ {
+ gDebuggerGlobals.breakingOnATrap = true;
+ break;
+ }
+ }
+
+ EXIT_CODE ("SetTrapBreaks", sysPktSetTrapBreaksRsp);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::Find
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::Find (SLP& slp)
+{
+ ENTER_PACKET ("Find", SysPktFindCmdType, SysPktFindRspType);
+
+ response.addr = (UInt32) NULL;
+ response.found = false;
+
+ {
+ UInt8* dataP = (UInt8*) packet.data.GetPtr ();
+ UInt32 startP = packet.firstAddr;
+
+ while (startP <= packet.lastAddr)
+ {
+ UInt16 ii;
+
+ for (ii = 0; ii < packet.numBytes; ++ii)
+ {
+ UInt8 b1 = EmMemGet8 (startP + ii);
+ UInt8 b2 = dataP[ii];
+
+ // Handle caseless conversion
+
+ if (packet.caseInsensitive)
+ {
+ if (isalpha (b1))
+ b1 = tolower (b1);
+
+ if (isalpha (b2))
+ b2 = tolower (b2);
+ }
+
+ if (b1 != b2) // if different -->
+ break;
+ }
+
+ // Check if matched
+
+ if (ii >= packet.numBytes)
+ {
+ response.addr = startP;
+ response.found = true;
+ break;
+ }
+
+ startP++; // advance start of search pointer
+ }
+ }
+
+ EXIT_PACKET ("Find", sysPktFindRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::GetTrapConditions
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::GetTrapConditions (SLP& slp)
+{
+ ENTER_PACKET ("GetTrapConditions", SysPktGetTrapConditionsCmdType, SysPktGetTrapConditionsRspType);
+ UNUSED_PARAM (packet);
+
+ for (int ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ response.trapParam[ii] = gDebuggerGlobals.trapParam[ii];
+ }
+
+ EXIT_PACKET ("GetTrapConditions", sysPktGetTrapConditionsRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SetTrapConditions
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SetTrapConditions (SLP& slp)
+{
+ ENTER_CODE ("SetTrapConditions", SysPktSetTrapConditionsCmdType, SysPktSetTrapConditionsRspType);
+
+ for (int ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ gDebuggerGlobals.trapParam[ii] = packet.trapParam[ii];
+ }
+
+ EXIT_CODE ("SetTrapConditions", sysPktSetTrapConditionsRsp);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SendMessage
+ *
+ * DESCRIPTION: Sends a text string to the external client.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SendMessage (SLP& slp, const char* msg)
+{
+// ENTER_PACKET ("SendMessage", SysPktBodyType, SysPktBodyType);
+
+ // Do this function entry by hand instead of using the ENTER_PACKET macro.
+ // That macro will call SLP::Body, which returns a reference to the
+ // packet body that was sent to us. However, SendMessage (a) doesn't
+ // need the body reference, so there's no need to set it up, and (b)
+ // isn't necessarily called in response to a "SendMessage" command,
+ // and so the reference may be NULL.
+
+ PRINTF ("Entering SystemPacket::SendMessage.");
+ EmProxySysPktBodyType response;
+
+ size_t len = strlen (msg) + 1;
+ strcpy ((char*) response.data.GetPtr (), msg);
+
+ EXIT_PACKET ("SendMessage", sysPktRemoteMsgCmd,
+ EmProxySysPktEmptyRspType::GetSize () + len);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SendResponse
+ *
+ * DESCRIPTION: Sends a simple null-body message to the external debugger.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SendResponse (SLP& slp, UInt8 code)
+{
+ EmProxySysPktEmptyRspType response;
+
+ response.command = code;
+ response._filler = 0;
+
+ return SystemPacket::SendPacket (slp, response.GetPtr (), response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SendPacket
+ *
+ * DESCRIPTION: Sends the given packet to the external client.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SendPacket (SLP& slp, const void* body, long bodySize)
+{
+ PRINTF ("Entering SystemPacket::SendPacket.");
+
+ ErrCode result = slp.SendPacket (body, bodySize);
+
+ PRINTF ("Exiting SystemPacket::SendPacket.");
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::GetRegs
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void SystemPacket::GetRegs (M68KRegsType& debuggerRegs)
+{
+ debuggerRegs.d[0] = m68k_dreg (regs, 0);
+ debuggerRegs.d[1] = m68k_dreg (regs, 1);
+ debuggerRegs.d[2] = m68k_dreg (regs, 2);
+ debuggerRegs.d[3] = m68k_dreg (regs, 3);
+ debuggerRegs.d[4] = m68k_dreg (regs, 4);
+ debuggerRegs.d[5] = m68k_dreg (regs, 5);
+ debuggerRegs.d[6] = m68k_dreg (regs, 6);
+ debuggerRegs.d[7] = m68k_dreg (regs, 7);
+
+ debuggerRegs.a[0] = m68k_areg (regs, 0);
+ debuggerRegs.a[1] = m68k_areg (regs, 1);
+ debuggerRegs.a[2] = m68k_areg (regs, 2);
+ debuggerRegs.a[3] = m68k_areg (regs, 3);
+ debuggerRegs.a[4] = m68k_areg (regs, 4);
+ debuggerRegs.a[5] = m68k_areg (regs, 5);
+ debuggerRegs.a[6] = m68k_areg (regs, 6);
+// debuggerRegs.a[7] = m68k_areg (regs, 7);
+
+ // Update the usp, isp, and/or msp before returning it.
+ // (from m68k_dumpstate() in newcpu.c)
+
+ if (regs.s == 0)
+ regs.usp = m68k_areg (regs, 7);
+ else
+ regs.isp = m68k_areg (regs, 7);
+
+ // Make sure the Status Register is up-to-date before moving it
+ // into the debugger register set.
+
+ EmAssert (gCPU68K);
+ gCPU68K->UpdateSRFromRegisters ();
+
+ // Copy the remaining registers from the UAE register set to the
+ // debugger's register set.
+
+ debuggerRegs.usp = regs.usp;
+ debuggerRegs.ssp = regs.isp;
+ debuggerRegs.sr = regs.sr;
+ debuggerRegs.pc = m68k_getpc ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::SetRegs
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void SystemPacket::SetRegs (const M68KRegsType& debuggerRegs)
+{
+ m68k_dreg (regs, 0) = debuggerRegs.d[0];
+ m68k_dreg (regs, 1) = debuggerRegs.d[1];
+ m68k_dreg (regs, 2) = debuggerRegs.d[2];
+ m68k_dreg (regs, 3) = debuggerRegs.d[3];
+ m68k_dreg (regs, 4) = debuggerRegs.d[4];
+ m68k_dreg (regs, 5) = debuggerRegs.d[5];
+ m68k_dreg (regs, 6) = debuggerRegs.d[6];
+ m68k_dreg (regs, 7) = debuggerRegs.d[7];
+
+ m68k_areg (regs, 0) = debuggerRegs.a[0];
+ m68k_areg (regs, 1) = debuggerRegs.a[1];
+ m68k_areg (regs, 2) = debuggerRegs.a[2];
+ m68k_areg (regs, 3) = debuggerRegs.a[3];
+ m68k_areg (regs, 4) = debuggerRegs.a[4];
+ m68k_areg (regs, 5) = debuggerRegs.a[5];
+ m68k_areg (regs, 6) = debuggerRegs.a[6];
+// m68k_areg (regs, 7) = debuggerRegs.a[7];
+
+ regs.usp = debuggerRegs.usp;
+ regs.isp = debuggerRegs.ssp;
+ regs.sr = debuggerRegs.sr;
+ m68k_setpc (debuggerRegs.pc);
+
+ // Make sure 's' bit is correct. This will also set SPCFLAG_INT, and
+ // if either the t0 or t1 bits are set, SPCFLAG_TRACE, too.
+
+ EmAssert (gCPU68K);
+ gCPU68K->UpdateRegistersFromSR ();
+
+ // I think we need to do a little extra handling here of the TRACE
+ // mode. If the TRACE mode bit is set, UpdateRegistersFromSR will
+ // set its SPCFLAG_TRACE flag, which tells the CPU loop to finish
+ // executing the current instruction, and then set the SPCFLAG_DOTRACE
+ // flag afterwards, which will then cause execution to stop after
+ // the NEXT instruction. We have a bit of an edge condition here
+ // when we set the SPCFLAG_TRACE flag BETWEEN instructions. Doing it
+ // this way will cause the next instruction to be treated as the
+ // "current" instruction, and so execution will stop after executing
+ // the second opcode. We want execution to stop with the first
+ // opcode, so fix up the flags here. This code is the same as in
+ // Emulator::ExecuteSpecial for managing this stuff.
+
+ if (regs.spcflags & SPCFLAG_TRACE)
+ {
+ regs.spcflags &= ~SPCFLAG_TRACE;
+ regs.spcflags |= SPCFLAG_DOTRACE;
+ }
+
+ // Finally, update the stack pointer from the usp or ssp,
+ // as appropriate.
+
+ if (regs.s == 0)
+ m68k_areg (regs, 7) = debuggerRegs.usp;
+ else
+ m68k_areg (regs, 7) = debuggerRegs.ssp;
+}