This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

MDI (Microprocessor Debug Interface) support


Hello,

 This is support for MDI or Microprocessor Debug Interface as defined by 
the spec published by MIPS Technologies.  The implementation corresponds 
to the version 2.20 of the spec.

 The following modes of operation are supported:

1. Single-processor operation.  For explicitly threaded hardware, such as 
   one specified by the MIPS MT spec (34K, etc.) all the contexts of 
   execution are seen as software threads.  The usual "thread" commands 
   can be used.

2. Team operation.  The primary processor is handled as with 1. above.  
   Additional processors are controlled transparently via the team set of 
   MDI calls.

3. Group (or SMP) operation.  Sort of a combination of the two above.  All 
   the controlled processors are treated the same and all contexts of 
   execution within are seen as software threads.  Useful for debugging 
   SMP operating systems.  Note it is currently impossible to add 
   transparently controlled devices when a group of processors is being 
   debugged.

 I have tested it using the mipsisa32-sde-elf target with the 
mips-fs2-sdelib/-EB/-march=mips32r2 and 
mips-fs2-sdelib/-EL/-march=mips32r2 boards -- this is actual hardware with 
a MIPS 24KEf core controlled through an FS2 probe.  The results are as 
follows:

# of expected passes            9845
# of unexpected failures        69
# of unexpected successes       2
# of expected failures          41
# of known failures             32
# of unresolved testcases       2
# of untested testcases         18
# of unsupported tests          69

and:

# of expected passes            9854
# of unexpected failures        60
# of unexpected successes       2
# of expected failures          41
# of known failures             32
# of unresolved testcases       2
# of untested testcases         18
# of unsupported tests          69

respectively.  Due to the lack of support in my current Dejagnu setup 
gdb.threads/ tests have not been run even though the target is capable of 
running them (and actually succeed).

2004-08-23  Nigel Stephens  <nigel@mips.com>
            David Ung  <davidu@mips.com>
            Chris Dearman  <chris@mips.com>
            Maciej W. Rozycki  <macro@mips.com>
            Thiemo Seufer  <ths@mips.com>

	* remote-mdi.c: MDI target support.
	* mdi.h: MDI generic API definition.
	* mdilink.h: MDI dynamic loading support.
	* mdimips.h: MDI MIPS-specific API definition.
	* msim_cfg.txt: MIPSsim configuration file template.
	* top.c (gdb_program_name): New global variable.
	(gdb_init): Set gdb_program_name to argv0.
	* defs.h (gdb_program_name): New global variable.
	* cli/cli-decode.c (add_setshow_cmd_full): If var_type is
	var_filename then force command completer function to be
	filename_completer.
	* configure.tgt (mips*-sde-elf*): Add ruleset for MIPS SDE.
	* Makefile.in (gmon_h, gmon_out_h): New headers.
	(install-mipssim): Add MIPSsim configuration file rule.
	(uninstall-mipssim): Similarly.
	(clean-mipssim): Similarly.
	(mipssim.cfg): Similarly.
	(ALLDEPFILES): Add remote-mdi.c.
	(remote-mdi.o): Add dependencies.  Add rule to compile
	remote-mdi.c with GUI flags.

 I have a pair of follow-on patches for the test suite to actually support 
this target and to set timeouts reasonably (required for it is real 
hardware which is not exactly lightning-fast) that I will post shortly.

 OK to apply?

  Maciej

mdi.diff
Index: binutils-quilt/src/gdb/mdi.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/mdi.h	2008-02-14 14:49:36.000000000 +0000
@@ -0,0 +1,573 @@
+/* MDI (Microprocessor Debug Interface) definitions.
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   Contributed by MIPS Technologies, Inc.
+
+   This file is part of GDB.
+
+   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.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef MDI_Specification_Definitions
+#define MDI_Specification_Definitions
+
+/* To build MDILib:
+   Define MDI_LIB before #include "mdi.h"
+   Include mdi.def in the link on Windows hosts.
+   When building an MDI application (debugger):
+   In one source file only, define MDILOAD_DEFINE before
+   #include "mdi.h" to define pointer variables for the API
+   functions.  */
+
+typedef unsigned int MDIUint32;
+typedef int MDIInt32;
+#ifdef _MSC_VER
+typedef unsigned __int64 MDIUint64;
+typedef __int64 MDIInt64;
+#else
+typedef unsigned long long MDIUint64;
+typedef long long MDIInt64;
+#endif
+
+#ifndef __stdcall
+#define __stdcall
+#endif
+
+#ifndef __declspec
+#define __declspec(e)
+#endif
+
+typedef MDIUint32 MDIVersionT;
+typedef struct MDIVersionRange_struct
+{
+  MDIVersionT oldest;
+  MDIVersionT newest;
+} MDIVersionRangeT;
+
+#define MDIMajor 0x0002
+#define MDIMinor 0x0014
+#define MDIOldMajor 0x0001
+#define MDIOldMinor 0x0000
+#define MDICurrentRevision ((MDIMajor << 16 ) | MDIMinor)
+#define MDIOldestRevision ((MDIOldMajor << 16) | MDIOldMinor)
+
+typedef MDIUint32 MDIHandleT;
+#define MDINoHandle ((MDIHandleT)-1)
+
+typedef MDIUint32 MDITGIdT;
+
+typedef struct MDITGData_struct
+{
+  MDITGIdT TGId;		/* MDI ID to reference this Target Group */
+  char TGName[81];		/* Descriptive string identifying this TG */
+} MDITGDataT;
+
+typedef MDIUint32 MDIDeviceIdT;
+
+typedef struct MDIDData_Struct
+{
+  MDIDeviceIdT Id;		/* MDI ID to reference this device */
+  char DName[81];		/* Descriptive string identifying device */
+  char Family[15];		/* Device's Family (CPU, DSP) */
+  char FClass[15];		/* Device's Class (MIPS, X86, PPC) */
+  char FPart[15];		/* Generic Part Name */
+  char FISA[15];		/* Instruction Set Architecture */
+  char Vendor[15];		/* Vendor of Part */
+  char VFamily[15];		/* Vendor Family name */
+  char VPart[15];		/* Vendor Part Number */
+  char VPartRev[15];		/* Vendor Part Revision Number */
+  char VPartData[15];		/* Used for Part Specific Data */
+  char Endian;			/* 0 Big Endian, 1 Little Endian */
+} MDIDDataT;
+
+/* Valid values for MDIDDataT.Family: */
+#define MDIFamilyCPU "CPU"
+#define MDIFamilyDSP "DSP"
+
+/* Valid values for MDIDDataT.Endian: */
+#define MDIEndianBig 0
+#define MDIEndianLittle 1
+
+/* MDI Resources */
+typedef MDIUint32 MDIResourceT;
+
+typedef MDIUint64 MDIOffsetT;
+
+typedef struct MDIRange_struct
+{
+  MDIOffsetT Start;
+  MDIOffsetT End;
+} MDIRangeT;
+
+typedef struct MDICRange_struct
+{
+  MDIOffsetT Offset;
+  MDIResourceT Resource;
+  MDIInt32 Count;
+} MDICRangeT;
+
+typedef struct MDIConfig_struct
+{
+  /* Provided By: Other Comments */
+  char User[80];		/* Host: ID of caller of MDI */
+
+  char Implementer[80];		/* MDI ID of who implemented MDI */
+  MDIUint32 MDICapability;	/* MDI: Flags for optional capabilities */
+
+  /* Host: CB fn for MDI output */
+  MDIInt32 (__stdcall * MDICBOutput) (MDIHandleT Device,
+				      MDIInt32 Type,
+				      char *Buffer, MDIInt32 Count);
+
+  /* Host: CB fn for MDI input */
+  MDIInt32 (__stdcall * MDICBInput) (MDIHandleT Device,
+				     MDIInt32 Type,
+				     MDIInt32 Mode,
+				     char **Buffer, MDIInt32 * Count);
+
+  /* Host: CB fn for expression eval */
+  MDIInt32 (__stdcall * MDICBEvaluate) (MDIHandleT Device,
+					char *Buffer,
+					MDIInt32 * ResultType,
+					MDIResourceT * Resource,
+					MDIOffsetT * Offset,
+					MDIInt32 * Size, void **Value);
+
+  /* Host: CB fn for sym/src lookup */
+  MDIInt32 (__stdcall * MDICBLookup) (MDIHandleT Device,
+				      MDIInt32 Type,
+				      MDIResourceT Resource,
+				      MDIOffsetT Offset, char **Buffer);
+
+  /* Host: CB fn for Event processing */
+  MDIInt32 (__stdcall * MDICBPeriodic) (MDIHandleT Device);
+
+  /* Host: CB fn for Synchronizing */
+  MDIInt32 (__stdcall * MDICBSync) (MDIHandleT Device,
+				    MDIInt32 Type, MDIResourceT Resource);
+} MDIConfigT;
+
+/* MDIConfigT.MDICapability flag values, can be OR'ed together.  */
+#define MDICAP_NoParser 0x00000001	/* No command parser */
+#define MDICAP_NoDebugOutput 0x00000002	/* No Target I/O */
+#define MDICAP_TraceOutput 0x00000004	/* Supports Trace Output */
+#define MDICAP_TraceCtrl 0x00000008	/* Supports Trace Control */
+#define MDICAP_TargetGroups 0x00000010	/* Supports Target Groups */
+#define MDICAP_PDtrace 0x00000020	/* Supports PDtrace functions */
+#define MDICAP_TraceFetchI 0x00000040	/* Supports Instr Fetch during Trace */
+#define MDICAP_TC 0x00000080		/* Supports Thread Contexts */
+#define MDICAP_Teams 0x00000100		/* Supports Teams */
+
+typedef struct MDIRunState_struct
+{
+  MDIUint32 Status;
+  union u_info
+  {
+    void *ptr;
+    MDIUint32 value;
+  } Info;
+} MDIRunStateT;
+
+/* Status values: */		/* Info interpretation: */
+#define MDIStatusNotRunning 1	/* none */
+#define MDIStatusRunning 2	/* none */
+#define MDIStatusHalted 3	/* none */
+#define MDIStatusStepsDone 4	/* none */
+#define MDIStatusExited 5	/* Info.value = exit value */
+#define MDIStatusBPHit 6	/* Info.value = BpID */
+#define MDIStatusUsrBPHit 7	/* none */
+#define MDIStatusException 8	/* Info.value = which exception */
+#define MDIStatusTraceFull 9	/* none */
+#define MDIStatusDisabled 10	/* none */
+#define MDIStatusVPENoTCs 10	/* none */ /* old name */
+#define MDIStatusVPEDisabled 11	/* none */
+#define MDIStatusMask 0x00ff	/* Status values are in lowest byte */
+
+/* These can be OR'ed in with MDIStatusRunning and MDIStatusNotRunning.  */
+#define MDIStatusReset 0x0100		/* currently held reset */
+#define MDIStatusWasReset 0x0200	/* reset asserted & released */
+#define MDIStatusResetMask 0x0300	/* reset state mask */
+
+/* This can also be OR'ed in with MDIStatusHalted.  */
+#define MDIStatusDescription 0x0400	/* Info.ptr = Descriptive string */
+
+typedef struct MDICacheInfo_struct
+{
+  MDIInt32 Type;
+  MDIUint32 LineSize;		/* Bytes of data in a cache line */
+  MDIUint32 LinesPerSet;	/* Number of lines in a set */
+  MDIUint32 Sets;		/* Number of sets */
+} MDICacheInfoT;
+
+/* Values for MDICacheInfoT.Type (Cache types): */
+#define MDICacheTypeNone 0
+#define MDICacheTypeUnified 1
+#define MDICacheTypeInstruction 2
+#define MDICacheTypeData 3
+
+typedef MDIUint32 MDIBpT;
+
+#define MDIBPT_SWInstruction 1
+#define MDIBPT_SWOneShot 2
+#define MDIBPT_HWInstruction 3
+#define MDIBPT_HWData 4
+#define MDIBPT_HWBus 5
+#define MDIBPT_TypeMax MDIBPT_HWBus
+#define MDIBPT_TypeMask 0x0000ffff
+
+#define MDIBPT_HWType_Exec 0x00000001
+#define MDIBPT_HWType_Data 0x00000002
+#define MDIBPT_HWType_Bus 0x00000004
+#define MDIBPT_HWType_AlignMask 0x000000f0
+#define MDIBPT_HWType_AlignShift 4
+#define MDIBPT_HWType_MaxSMask 0x00003f00
+#define MDIBPT_HWType_MaxSShift 9
+#define MDIBPT_HWType_VirtAddr 0x00004000
+#define MDIBPT_HWType_ASID 0x00008000
+
+/* Hardware breakpoint types may have one or more of the following
+   flag bits OR'ed in to specify additional qualifications. */
+#define MDIBPT_HWFlg_AddrMask 0x00010000
+#define MDIBPT_HWFlg_AddrRange 0x00020000
+#define MDIBPT_HWFlg_DataValue 0x00040000
+#define MDIBPT_HWFlg_DataMask 0x00080000
+#define MDIBPT_HWFlg_DataRead 0x00100000
+#define MDIBPT_HWFlg_DataWrite 0x00200000
+#define MDIBPT_HWFlg_Trigger 0x00400000
+#define MDIBPT_HWFlg_TriggerOnly 0x00800000
+#define MDIBPT_HWFlg_TCMatch 0x01000000
+#define MDIBPT_TypeQualMask 0xffff0000
+
+typedef MDIUint32 MDIBpIdT;
+
+#define MDIAllBpID (~(MDIBpIdT)0)
+
+typedef struct MDIBpData_struct
+{
+  MDIBpIdT Id;
+  MDIBpT Type;
+  MDIUint32 Enabled;		/* 0 if currently disabled, else 1 */
+  MDIResourceT Resource;
+  MDIRangeT Range;		/* Range.End may be an end addr or mask */
+  MDIUint64 Data;		/* valid only for data write breaks */
+  MDIUint64 DataMask;		/* valid only for data write breaks */
+  MDIUint32 PassCount;		/* Pass count reloaded when hit */
+  MDIUint32 PassesToGo;		/* Passes to go until next hit */
+} MDIBpDataT;
+
+typedef struct MDIBpInfo_struct
+{
+  MDIInt32 Num;			/* the number of breakpoints of this type */
+  MDIUint32 Type;		/* the exact type of hardware breakpoint */
+} MDIBpInfoT;
+
+/* MDI Trace data type */
+typedef struct MDITrcFrame_Struct
+{
+  MDIUint32 Type;
+  MDIResourceT Resource;
+  MDIOffsetT Offset;
+  MDIUint64 Value;
+} MDITrcFrameT;
+
+#define MDITTypePC 1		/* Instruction address only */
+#define MDITTypeInst 2		/* Instruction address and value */
+#define MDITTypeRead 3		/* Data Load address only */
+#define MDITTypeWrite 4		/* Data Store address only */
+#define MDITTypeAccess 5	/* Data Access (Load/Store) address only */
+#define MDITTypeRData_8 6	/* Data Load address and 8-bit value */
+#define MDITTypeWData_8 7	/* Data Store address and 8-bit value */
+#define MDITTypeRData_16 8	/* Data Load address and 16-bit value */
+#define MDITTypeWData_16 9	/* Data Store address and 16-bit value */
+#define MDITTypeRData_32 10	/* Data Load address and 32-bit value */
+#define MDITTypeWData_32 11	/* Data Store address and 32-bit value */
+#define MDITTypeRData_64 12	/* Data Load address and 64-bit value */
+#define MDITTypeWData_64 13	/* Data Store address and 64-bit value */
+
+/* Values for Flags parameter to MDITGOpen() and MDIOpen(): */
+#define MDISharedAccess 0
+#define MDIExclusiveAccess 1
+
+/* Values for Flags parameter to MDITGClose() and MDIClose(): */
+#define MDICurrentState 0
+#define MDIResetState 1
+
+/* Values for SyncType parameter to MDICBSync(): */
+#define MDISyncBP 0
+#define MDISyncState 1
+#define MDISyncWrite 2
+
+/* Values for Direction parameter to MDIMove(): */
+#define MDIMoveForward 0
+#define MDIMoveBackward 1
+
+/* Values for Mode parameter to MDIFind(): */
+#define MDIMatchForward 0
+#define MDIMismatchForward 1
+#define MDIMatchBackward 2
+#define MDIMismatchBackward 3
+
+/* Values for Mode parameter to MDIStep(): */
+#define MDIStepInto 0
+#define MDIStepForward 1
+#define MDIStepOver 2
+#define MDINoStep ~0
+
+/* "Wait Forever" value for WaitTime parameter to MDIRunState(): */
+#define MDIWaitForever -1
+
+/* Values for Mode parameter to MDIReset(): */
+#define MDIFullReset 0
+#define MDIDeviceReset 1
+#define MDICPUReset 2
+#define MDIPeripheralReset 3
+
+/* Values for Flags parameter to MDICacheFlush(): */
+#define MDICacheWriteBack 0x01
+#define MDICacheInvalidate 0x02
+
+/* Values for Status parameter from MDITraceStatus(): */
+#define MDITraceStatusNone 1
+#define MDITraceStatusTracing 2
+#define MDITraceStatusWaiting 3
+#define MDITraceStatusFilling 4
+#define MDITraceStatusStopped 5
+
+/* Values for Type parameter to MDICBOutput() and MDICBInput(): */
+#define MDIIOTypeMDIIn 1
+#define MDIIOTypeMDIOut 2
+#define MDIIOTypeMDIErr 3
+#define MDIIOTypeTgtIn 4
+#define MDIIOTypeTgtOut 5
+#define MDIIOTypeTgtErr 6
+
+/* Values for Mode parameter to MDICBInput(): */
+#define MDIIOModeNormal 1
+#define MDIIORawBlock 2
+#define MDIIORawNoBlock 3
+
+/* Values for Type parameter to MDICBEvaluate(): */
+#define MDIEvalTypeResource 1
+#define MDIEvalTypeChar 2
+#define MDIEvalTypeInt 3
+#define MDIEvalTypeUInt 4
+#define MDIEvalTypeFloat 5
+#define MDIEvalTypeNone 6
+
+/* Values for Type parameter to MDICBLookup(): */
+#define MDILookupNearest 1
+#define MDILookupExact 2
+#define MDILookupSource 3
+
+/* MDI function return values: */
+#define MDISuccess 0		/* Success. */
+#define MDINotFound 1		/* MDIFind() did not find a match. */
+#define MDIErrFailure -1	/* Unable to perform operation. */
+#define MDIErrDevice -2		/* Invalid Device handle. */
+#define MDIErrSrcResource -3	/* Invalid Resource type. */
+#define MDIErrDstResource -4	/* 2nd Resource has invalid type. */
+#define MDIErrInvalidSrcOffset -5	/* Offset is invalid for the specified
+					   resource. */
+#define MDIErrInvalidDstOffset -6	/* 2nd Offset is invalid for the 2nd
+					   resource. */
+#define MDIErrSrcOffsetAlignment -7	/* Offset is not correctly aligned. */
+#define MDIErrDstOffsetAlignment -8	/* 2nd Offset is not correctly aligned
+					   for the specified ObjectSize. */
+#define MDIErrSrcCount -9	/* Count causes reference outside of the
+				   resources space. */
+#define MDIErrDstCount -10	/* Count causes reference outside of 2nd
+				   resources space. */
+#define MDIErrBPType -13	/* Invalid breakpoint type. */
+#define MDIErrRange -14		/* Specified range is outside of the scope for
+				   the resource. */
+#define MDIErrNoResource -15	/* Hardware resources are unavailable. */
+#define MDIErrBPId -16		/* Invalid Breakpoint ID. */
+#define MDIErrMore -17		/* More data available than was requested. */
+#define MDIErrParam -18		/* A parameter is in error (See specific
+				   instructions). */
+#define MDIErrTGHandle -19	/* Invalid Target Group Handle. */
+#define MDIErrMDIHandle -20	/* Invalid MDI Environment Handle. */
+#define MDIErrVersion -21	/* Version not supported. */
+#define MDIErrLoadLib -22	/* Error loading library. */
+#define MDIErrModule -23	/* Unable to link required MDI functions. */
+#define MDIErrConfig -24	/* Required callback functions not present. */
+#define MDIErrDeviceId -25	/* Invalid device ID. */
+#define MDIErrAbort -26		/* Command has been aborted. */
+#define MDIErrUnsupported -27	/* Unsupported feature. */
+#define MDIErrLookupNone -28	/* Address did not match a symbol or source
+				   line. */
+#define MDIErrLookupError -29	/* Invalid address for look up. */
+#define MDIErrTracing -30	/* Can't clear trace buffer while capturing
+				   is in progress. */
+#define MDIErrInvalidFunction -31	/* Function pointer is invalid. */
+#define MDIErrAlreadyConnected -32	/* MDI Connection has already been
+					   made for this thread. */
+#define MDIErrTGId -33		/* Invalid Target Group ID. */
+#define MDIErrDeviceHandle -34
+#define MDIErrDevicesOpen -35
+#define MDIErrInvalidData -36
+#define MDIErrDuplicateBP -37
+#define MDIErrInvalidFrames -38	/* Range of requested trace frames is
+				   invalid. */
+#define MDIErrWrongThread -39
+#define MDIErrTargetRunning -40
+#define MDIErrRecursive -41	/* Recursive call from MDICDPeriodic. */
+#define MDIErrObjectSize -42	/* Invalid Object Size for Resource. */
+
+#define MDIErrTCId -43		/* The specified TC id value is not a valid TC
+				   number for the VPE being debugged.  */
+#define MDIErrTooManyTeams -44	/* Too many teams for MDILib.  */
+#define MDIErrTeamId -45	/* Invalid team id.  */
+#define MDIErrDisabled -46	/* Device is disabled.  */
+#define MDIErrAlreadyMember -47	/* Device is already a team member.  */
+#define MDIErrNotMember -48	/* Device is not a team member.  */
+
+typedef MDIInt32 MDITCIdT;
+
+typedef struct MDITCData_struct
+{
+  MDITCIdT TCId;
+  MDIUint32 Status;
+} MDITCDataT;
+
+#define MDITCStatusHalted 0
+#define MDITCStatusFree 1
+#define MDITCStatusRunning 2
+#define MDITCStatusBlockedOnWait 3
+#define MDITCStatusBlockedOnYield 4
+#define MDITCStatusBlockedOnGS 5
+
+typedef MDIInt32 MDITeamIdT;
+
+typedef struct
+{
+  MDIHandleT MDIHandle;
+  MDITGIdT TGId;
+  MDIDeviceIdT DevId;
+} MDITMDataT;
+
+/* Function Prototypes.  */
+
+#if defined (MDI_LIB)
+
+/* MDILib, do extern function declarations.  */
+#define yf(str) extern int __declspec(dllexport) __stdcall str
+
+#elif defined (MDILOAD_DEFINE)
+
+/* Debugger, do function pointer definitions.  */
+#define yf(str) int (__stdcall *str)
+
+#else
+
+/* Debugger, do extern function pointer declarations.  */
+#define yf(str) extern int (__stdcall *str)
+
+#endif
+
+yf (MDIVersion) (MDIVersionRangeT *);
+yf (MDIConnect) (MDIVersionT, MDIHandleT *, MDIConfigT *);
+yf (MDIDisconnect) (MDIHandleT, MDIUint32);
+yf (MDITGQuery) (MDIHandleT, MDIInt32 * HowMany, MDITGDataT *);
+yf (MDITGOpen) (MDIHandleT, MDITGIdT, MDIUint32, MDIHandleT *);
+yf (MDITGClose) (MDIHandleT, MDIUint32);
+yf (MDITGExecute) (MDIHandleT);
+yf (MDITGStop) (MDIHandleT);
+yf (MDIDQuery) (MDIHandleT, MDIInt32 * HowMany, MDIDDataT *);
+yf (MDIOpen) (MDIHandleT, MDIDeviceIdT, MDIUint32, MDIHandleT *);
+yf (MDIClose) (MDIHandleT, MDIUint32);
+yf (MDIRead) (MDIHandleT, MDIResourceT SrcR, MDIOffsetT SrcO,
+	      void *Buffer, MDIUint32 ObjectSize, MDIUint32 Count);
+yf (MDIWrite) (MDIHandleT, MDIResourceT DstR, MDIOffsetT DstO,
+	       void *Buffer, MDIUint32 ObjectSize, MDIUint32 Count);
+yf (MDIReadList) (MDIHandleT, MDIUint32 ObjectSize, MDICRangeT * SrcList,
+		  MDIUint32 ListCount, void *Buffer);
+yf (MDIWriteList) (MDIHandleT, MDIUint32 ObjectSize, MDICRangeT * DstList,
+		   MDIUint32 ListCount, void *Buffer);
+yf (MDIMove) (MDIHandleT, MDIResourceT SrcR, MDIOffsetT SrcO,
+	      MDIResourceT DstR, MDIOffsetT DstO, MDIUint32 ObjectSize,
+	      MDIUint32 Count, MDIUint32 Flag);
+yf (MDIFill) (MDIHandleT, MDIResourceT DstR, MDIRangeT DstRng,
+	      void *Buffer, MDIUint32 ObjectSize, MDIUint32 Count);
+yf (MDIFind) (MDIHandleT, MDIResourceT SrcR, MDIRangeT SrcRng,
+	      void *Buffer, void *MaskBuffer, MDIUint32 ObjectSize,
+	      MDIUint32 Count, MDIOffsetT * FoundOffset, MDIUint32 Mode);
+yf (MDIExecute) (MDIHandleT);
+yf (MDIStep) (MDIHandleT, MDIUint32 Steps, MDIUint32 Mode);
+yf (MDIStop) (MDIHandleT);
+yf (MDIReset) (MDIHandleT, MDIUint32 Flag);
+yf (MDICacheQuery) (MDIHandleT, MDICacheInfoT * CacheInfo);
+yf (MDICacheFlush) (MDIHandleT, MDIUint32 Type, MDIUint32 Flag);
+yf (MDIRunState) (MDIHandleT, MDIInt32 WaitTime, MDIRunStateT * runstate);
+yf (MDISetBp) (MDIHandleT, MDIBpDataT *);
+yf (MDISetSWBp) (MDIHandleT, MDIResourceT, MDIOffsetT, MDIBpIdT *);
+yf (MDIClearBp) (MDIHandleT, MDIBpIdT);
+yf (MDIEnableBp) (MDIHandleT, MDIBpIdT);
+yf (MDIDisableBp) (MDIHandleT, MDIBpIdT);
+yf (MDIBpQuery) (MDIHandleT, MDIInt32 * HowMany, MDIBpDataT *);
+yf (MDIHwBpQuery) (MDIHandleT, MDIInt32 * HowMany, MDIBpInfoT *);
+yf (MDIDoCommand) (MDIHandleT, char *Buffer);
+yf (MDIAbort) (MDIHandleT);
+yf (MDITraceEnable) (MDIHandleT);
+yf (MDITraceDisable) (MDIHandleT);
+yf (MDITraceClear) (MDIHandleT);
+yf (MDITraceStatus) (MDIHandleT, MDIUint32 *);
+yf (MDITraceCount) (MDIHandleT, MDIUint32 *);
+yf (MDITraceRead) (MDIHandleT, MDIUint32, MDIUint32, MDIUint32,
+		   MDITrcFrameT *);
+yf (MDISetTC) (MDIHandleT, MDITCIdT);
+yf (MDIGetTC) (MDIHandleT, MDITCIdT *);
+yf (MDITCQuery) (MDIHandleT, MDIInt32 *, MDITCDataT *);
+yf (MDISetRunMode) (MDIHandleT, MDITCIdT, MDIUint32, MDIUint32);
+yf (MDISetTCRunMode) (MDIHandleT, MDITCIdT, MDIUint32, MDIUint32);
+yf (MDIQueryTC) (MDIHandleT, MDIInt32 *, MDITCDataT *);
+yf (MDITCSet) (MDIHandleT, MDITCIdT);
+yf (MDITCGet) (MDIHandleT, MDITCIdT *);
+yf (MDITCSetRunMode) (MDIHandleT, MDIInt32, MDIUint32, MDIUint32);
+yf (MDITeamCreate) (MDIHandleT, MDITeamIdT *);
+yf (MDIQueryTeams) (MDIHandleT, MDIInt32 *, MDITeamIdT *);
+yf (MDITeamClear) (MDIHandleT, MDITeamIdT);
+yf (MDITeamDestroy) (MDIHandleT, MDITeamIdT);
+yf (MDITMAttach) (MDIHandleT, MDITeamIdT, MDITMDataT *);
+yf (MDITMDetach) (MDIHandleT, MDITeamIdT, MDITMDataT *);
+yf (MDIQueryTM) (MDIHandleT, MDITeamIdT, MDIInt32 *, MDITMDataT *);
+yf (MDICreateTeam) (MDIHandleT, MDITeamIdT *);
+yf (MDIClearTeam) (MDIHandleT, MDITeamIdT);
+yf (MDIDestroyTeam) (MDIHandleT, MDITeamIdT);
+yf (MDIAttachTM) (MDIHandleT, MDITeamIdT, MDITMDataT *);
+yf (MDIDetachTM) (MDIHandleT, MDITeamIdT, MDITMDataT *);
+yf (MDITMQuery) (MDIHandleT, MDITeamIdT, MDIInt32 *, MDITMDataT *);
+yf (MDITeamExecute) (MDIHandleT, MDITeamIdT);
+
+/* MIPSsim special interfaces */
+yf (MIPSsim_SetConfigFile) (MDIHandleT, char *);
+yf (MIPSsim_CreateProfile) (MDIHandleT, MDIInt32 *, MDIUint64, MDIUint64);
+yf (MIPSsim_DestroyProfile) (MDIHandleT, MDIInt32);
+yf (MIPSsim_StartProfile) (MDIHandleT, MDIInt32);
+yf (MIPSsim_StopProfile) (MDIHandleT, MDIInt32);
+yf (MIPSsim_ClearProfile) (MDIHandleT, MDIInt32);
+yf (MIPSsim_FetchProfile) (MDIHandleT, MDIInt32, MDIUint32 **, MDIUint64 *);
+yf (MIPSsim_FreeProfileData) (MDIHandleT, MDIUint32 **);
+yf (MIPSsim_GetTraceLevel) (MDIHandleT, int *);
+yf (MIPSsim_SetTraceLevel) (MDIHandleT, int);
+yf (MIPSsim_GetStats) (MDIHandleT, int, MDIUint64 *);
+yf (MIPSsim_ClearStats) (MDIHandleT, int);
+yf (MIPSsim_GetPerfCounter) (MDIHandleT, int, int, int, MDIUint64 *);
+yf (MIPSsim_ZeroPerfCounter) (MDIHandleT, int, int, int);
+yf (MIPSsim_ZeroPerfCounters) (MDIHandleT);
+yf (MIPSsim_GetVersion) (MDIHandleT, MDIInt32 *, MDIInt32 *, MDIInt32 *);
+
+#undef yf
+
+#endif /* MDI_Specification_Definitions */
Index: binutils-quilt/src/gdb/defs.h
===================================================================
--- binutils-quilt.orig/src/gdb/defs.h	2008-02-14 14:22:13.000000000 +0000
+++ binutils-quilt/src/gdb/defs.h	2008-02-14 14:49:36.000000000 +0000
@@ -139,6 +139,9 @@
 /* Search path for separate debug files.  */
 extern char *debug_file_directory;
 
+/* The name by which GDB was invoked.  */
+extern char *gdb_program_name;
+
 extern int quit_flag;
 extern int immediate_quit;
 extern int sevenbit_strings;
Index: binutils-quilt/src/gdb/remote-mdi.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/remote-mdi.c	2008-02-14 14:49:36.000000000 +0000
@@ -0,0 +1,8726 @@
+/* MDI (MIPS Debug Interface) interface for GDB.
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   Contributed by MIPS Technologies, Inc.
+
+   This file is part of GDB.
+
+   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.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "arch-utils.h"
+#include "exceptions.h"
+#include "gdb_string.h"
+#include "gdb_wait.h"
+#include "inferior.h"
+#include "regcache.h"
+#include "version.h"
+#include <sys/types.h>
+#include "gdb_regex.h"
+#include "gmon.h"
+#include "gmon_out.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#if defined(_WIN32) || defined(__CYGWIN32__)
+#include <windows.h>
+#else
+typedef void * HMODULE;
+#endif
+
+#ifdef __CYGWIN32__
+#include <sys/cygwin.h>
+#include <cygwin/version.h>
+#endif
+
+#ifndef MAX_PATH
+#define MAX_PATH	1024
+#endif
+
+#include "gdbthread.h"
+#include "terminal.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "block.h"
+
+#define MDILOAD_DEFINE
+#include "mdi.h"
+#include "mdimips.h"
+#include "mips-tdep.h"
+
+#ifdef GDBTK
+#include "tcl.h"
+extern Tcl_Interp *gdbtk_interp;
+#endif
+
+/* readline include files */
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#define GET_PID(ptid) ptid_get_pid (ptid)
+
+/* These are pointers to hook functions that may be set in order to
+   modify resume/wait behavior for a particular architecture.  */
+void (*target_resume_hook) (void);
+void (*target_wait_loop_hook) (void);
+
+static const char * mdierrcode (MDIInt32);
+
+/* The list of available "mdi", "set mdi" and "show mdi" commands.  */
+static struct cmd_list_element *mdicmdlist = NULL;
+static struct cmd_list_element *setmdicmdlist = NULL;
+static struct cmd_list_element *showmdicmdlist = NULL;
+
+static HMODULE mdiModule;
+
+static char *mdi_logfile;
+static struct ui_file *mdi_logfp;
+static int mdi_logging;
+
+static int mdi_target;
+static int mdi_device;
+static int mdi_team;
+static int mdi_waittime = 10;	/* XXXX 1/100th second seems very small.  */
+static int mdi_stepinto = 0;
+static int mdi_threadstepall = 0;
+static int mdi_continueonclose = -1;
+static int mdi_rununcached = 1;
+static int mdi_threadviewinactive = 0;
+static unsigned int mdi_connecttimeout = 1;
+static char *mdi_library;
+static char *mdi_configfile;
+static char *mdi_devcfgfile;
+static char *mdi_ftext_syms;
+static char *mdi_etext_syms;
+static char *mdi_mcount_syms;
+static int mdi_connectreset = -1;
+static int mdi_releaseonclose = 0;
+static char *mdi_logdocommand;
+static int mdi_quiet;
+static int mdi_mem_written;
+static char **mdi_argv;
+
+static enum auto_boolean mdi_profiling = AUTO_BOOLEAN_AUTO;
+static char *mdi_gmonfile;
+static int mdi_profile_cycles;
+static int mdi_profile_mcount;
+
+static int mdi_wait_active;
+static int mdi_step_active;
+static int mdi_starting;
+
+static MDIRunStateT mdi_runstate;
+static MDIBpDataT mdi_curbpt;
+
+static char *mdi_target_prompt;	/* the input prompt string */
+static char *mdi_implementer;
+
+static int mdi_found_relf;
+static int mdi_syscall_inserted;
+static CORE_ADDR mdi_syscall = 0;
+static CORE_ADDR mdi_syscall_rom = 0;
+static CORE_ADDR mdi_entrypoint = 0;
+static int mdi_loaded = 0;
+static int mdi_exited = 0;
+
+static enum target_signal mdi_lastsig;
+static int mdi_signalled = 0;
+
+/* Bitmap of missing cp registers:
+   4 coprocessors x 8 banks x 32 registers.  */
+static unsigned int mdi_cpdreg_miss[4][8];
+
+/* Bitmap of missing cp control registers:
+   4 coprocessors x 32 registers.  */
+static unsigned int mdi_cpcreg_miss[4];
+
+/* Bitmap of write protected cp registers:
+   4 coprocessors x 8 banks x 32 registers.  */
+static unsigned int mdi_cpdreg_wp[4][8];
+
+/* Bitmap of write protected cp control registers:
+   4 coprocessors x 32 registers.  */
+static unsigned int mdi_cpcreg_wp[4];
+
+static unsigned int mdi_hilo_miss;
+static unsigned int mdi_dsp_miss;
+
+/* Set if the new MDIMIPFPR resource available.  */
+static int mdi_fpr_avail;
+
+/* Set if the new MDIHwBpQuery call available.  */
+static int mdi_hwbpq_avail;
+
+/* Specify the address type for virtual memory accesses and
+   breakpoints.  */
+
+enum mdi_asidtype
+{
+    ASIDNone,			/* Use global address space.  */
+    ASIDReg,			/* Use current ASID in CP0 EntryHi.  */
+    ASIDFixed,			/* Use fixed ASID in mdi_asid.  */
+    ASIDAuto			/* Use global for unmapped segments,
+				   or current ASID for mapped.  */
+};
+
+static enum mdi_asidtype mdi_asidtype = ASIDAuto;
+
+/* ASID for for ASIDFixed type.  */
+static int mdi_asid;
+
+/*extern int MDIInit (char *dllpath, HMODULE * handle);*/
+/*extern int MDIRelease (HMODULE handle);*/
+
+static ULONGEST mdi_readreg (int regno);
+static void mdi_writereg (int regno, ULONGEST val);
+
+static ULONGEST mdi_readpc (void);
+static void mdi_writepc (ULONGEST val);
+
+static void mdi_reset_breakpoints (void);
+static MDIBpDataT * mdi_find_breakpoint (MDIHandleT devhandle, MDIBpIdT id);
+static MDIBpDataT * mdi_find_usr_breakpoint (CORE_ADDR addr);
+static int mdi_insert_breakpoint1 (CORE_ADDR addr, MDIInt32);
+static int mdi_insert_breakpoint (struct bp_target_info *bp_tgt);
+static int mdi_remove_breakpoint1 (CORE_ADDR addr, MDIInt32);
+static int mdi_remove_breakpoint (struct bp_target_info *bp_tgt);
+
+static void mdi_team_status (MDIInt32 mdistat);
+static void mdi_tm_status (MDIInt32 mdistat, MDITGIdT target,
+			   MDIDeviceIdT device);
+
+static int mdi_cycles_enable (PTR);
+static void mdi_cycles_update (void);
+
+static void dump_mem (void *, int, int);
+static MDIResourceT mdi_memresource (CORE_ADDR);
+static MDIOffsetT mdi_memoffset (CORE_ADDR);
+
+static void mdi_insert_syscallbreakpoint (void);
+static void mdi_remove_syscallbreakpoint (void);
+
+static void mdi_fdinit (void);
+static void mdi_fdcloseall (void);
+
+static void mdi_profiling_start (void);
+static void mdi_profiling_close (int);
+
+static void sleep_ms (long);
+
+static void mdi_switch_to_thread (void);
+static void mdi_find_new_threads (void);
+
+static ptid_t mdi_ptid;
+static ptid_t last_ptid;
+
+enum mdiTlb { NO_TLB, R3000_TLB, R4000_32TLB, R4000_64TLB };
+
+/* List of MDI team members.  */
+struct mdi_tm_data_list
+{
+  MDITMDataT tmdata;		/* MDI handle, TG ID, Dev ID.  */
+  struct mdi_tm_data_list *next;
+};
+
+/* List of MDI group members.  */
+struct mdi_gm_data
+{
+  MDITMDataT tmdata;		/* MDI handle, TG ID, Dev ID.  */
+  MDIHandleT TGHandle;		/* Target handle.  */
+  MDIHandleT DevHandle;		/* Device handle.  */
+  MDIDDataT DeviceData;		/* Device data.  */
+  MDICacheInfoT CacheInfo[4];	/* Cache information.  */
+  int disabled;			/* The device is disabled.  */
+  int probed;			/* The device has been probed.  */
+  int ntlb;			/* Number of TLB entries.  */
+};
+
+/* MDI connection state.  */
+struct mdi_state
+{
+  MDIHandleT MDIHandle;		/* MDI handle */
+  MDITeamIdT gid;		/* Team ID for the group */
+  struct mdi_gm_data gmdata[256];
+				/* Devices opened */
+  int gmcount;			/* Number of devices opened */
+  int gmindex;			/* Index of the selected device */
+
+  MDIConfigT Config;		/* Configuration data */
+
+  int mipssim_p;		/* Connected to MIPSsim */
+  char *cfgfile;		/* MIPSsim temp config file */
+
+  enum mdiTlb tlb;		/* TLB type */
+  int regsize;			/* Device register size */
+};
+
+
+static struct mdi_state *mdi_desc = NULL;
+
+static void mdi_kill (void);
+
+/* Forward data declarations.  */
+struct target_ops mdi_ops;
+
+#define ec(str) {str, #str}
+
+struct errorcodes_struct
+{
+  int errorcode;
+  const char *str;
+};
+
+static const struct errorcodes_struct errorcodes[] =
+{
+  ec (MDINotFound),
+  ec (MDIErrFailure),
+  ec (MDIErrDevice),
+  ec (MDIErrSrcResource),
+  ec (MDIErrDstResource),
+  ec (MDIErrInvalidSrcOffset),
+  ec (MDIErrInvalidDstOffset),
+  ec (MDIErrSrcOffsetAlignment),
+  ec (MDIErrDstOffsetAlignment),
+  ec (MDIErrSrcCount),
+  ec (MDIErrDstCount),
+  ec (MDIErrBPType),
+  ec (MDIErrRange),
+  ec (MDIErrNoResource),
+  ec (MDIErrBPId),
+  ec (MDIErrMore),
+  ec (MDIErrParam),
+  ec (MDIErrTGHandle),
+  ec (MDIErrMDIHandle),
+  ec (MDIErrVersion),
+  ec (MDIErrLoadLib),
+  ec (MDIErrModule),
+  ec (MDIErrConfig),
+  ec (MDIErrDeviceId),
+  ec (MDIErrAbort),
+  ec (MDIErrUnsupported),
+  ec (MDIErrLookupNone),
+  ec (MDIErrLookupError),
+  ec (MDIErrTracing),
+  ec (MDIErrInvalidFunction),
+  ec (MDIErrAlreadyConnected),
+  ec (MDIErrTGId),
+  ec (MDIErrDeviceHandle),
+  ec (MDIErrDevicesOpen),
+  ec (MDIErrInvalidData),
+  ec (MDIErrDuplicateBP),
+  ec (MDIErrInvalidFrames),
+  ec (MDIErrWrongThread),
+  ec (MDIErrTargetRunning),
+  ec (MDIErrRecursive),
+  ec (MDIErrObjectSize),
+  ec (MDIErrTCId),
+  ec (MDIErrTooManyTeams),
+  ec (MDIErrTeamId),
+  ec (MDIErrDisabled),
+  ec (MDIErrAlreadyMember),
+  ec (MDIErrNotMember),
+  {0, 0}
+};
+
+struct mdiresourcename_struct
+{
+  int mdiid;
+  const char *mdistr;
+};
+
+static const struct mdiresourcename_struct resrc_Names[] =
+{
+  ec (MDIMIPCPU),
+  ec (MDIMIPPC),
+  ec (MDIMIPHILO),
+  ec (MDIMIPTLB),
+  ec (MDIMIPPICACHET),
+  ec (MDIMIPPUCACHET),
+  ec (MDIMIPPDCACHET),
+  ec (MDIMIPSICACHET),
+  ec (MDIMIPSUCACHET),
+  ec (MDIMIPSDCACHET),
+  ec (MDIMIP192ACC),
+  ec (MDIMIPCP0),
+  ec (MDIMIPCP0C),
+  ec (MDIMIPCP1),
+  ec (MDIMIPCP1C),
+  ec (MDIMIPCP2),
+  ec (MDIMIPCP2C),
+  ec (MDIMIPCP3),
+  ec (MDIMIPCP3C),
+  ec (MDIMIPFP),
+  ec (MDIMIPDFP),
+  ec (MDIMIPPICACHE),
+  ec (MDIMIPPUCACHE),
+  ec (MDIMIPPDCACHE),
+  ec (MDIMIPSICACHE),
+  ec (MDIMIPSUCACHE),
+  ec (MDIMIPSDCACHE),
+  ec (MDIMIPPHYSICAL),
+  ec (MDIMIPGVIRTUAL),
+  ec (MDIMIPEJTAG),
+  ec (MDIMIPSRS),
+  ec (MDIMIPFPR),
+  ec (MDIMIPDSP),
+  {0, "Invalid Resource"}
+};
+
+
+static const struct mdiresourcename_struct status_Names[] =
+{
+ ec(MDIStatusNotRunning),
+ ec(MDIStatusRunning),
+ ec(MDIStatusHalted),
+ ec(MDIStatusStepsDone),
+ ec(MDIStatusExited),
+ ec(MDIStatusBPHit),
+ ec(MDIStatusUsrBPHit),
+ ec(MDIStatusException),
+ ec(MDIStatusTraceFull),
+ ec(MDIStatusDisabled),
+ ec(MDIStatusVPEDisabled),
+ {0, "Invalid status"}
+};
+
+static const struct mdiresourcename_struct bptype_Names[] =
+{
+  ec (MDIBPT_SWInstruction),
+  ec (MDIBPT_SWOneShot),
+  ec (MDIBPT_HWInstruction),
+  ec (MDIBPT_HWData),
+  ec (MDIBPT_HWBus),
+  {0, "Invalid bptype"}
+};
+
+static const struct mdiresourcename_struct cbtype_Names[] =
+{
+ ec(MDIIOTypeMDIIn),
+ ec(MDIIOTypeMDIOut),
+ ec(MDIIOTypeMDIErr),
+ ec(MDIIOTypeTgtIn),
+ ec(MDIIOTypeTgtOut),
+ ec(MDIIOTypeTgtErr),
+ {0, "Invalid type"}
+};
+
+struct isa_xlate_struct
+{
+  const char *isa;
+  int num;
+};
+
+static const struct isa_xlate_struct isa_xlate[] =
+{
+  {MDIMIP_FISA_M1, 1} ,
+  {MDIMIP_FISA_M2, 2} ,
+  {MDIMIP_FISA_M3, 3} ,
+  {MDIMIP_FISA_M4, 4} ,
+  {MDIMIP_FISA_M5, 5} ,
+  {MDIMIP_FISA_M32, 32} ,
+  {MDIMIP_FISA_M64, 64} ,
+  {0, -1}
+};
+
+
+static void
+show_mdi_stepinto (struct ui_file *file, int from_tty,
+		   struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Step-into mode is %s.\n"), value);
+}
+
+static void
+show_mdi_threadstepall (struct ui_file *file, int from_tty,
+			struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("\
+Simultaneous thread stepping mode is %s.\n"),
+		    value);
+}
+
+static void
+show_mdi_connecttimeout (struct ui_file *file, int from_tty,
+			 struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MDI connect timeout is %s s.\n"), value);
+}
+
+static void
+show_mdi_continueonclose (struct ui_file *file, int from_tty,
+			  struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Continue on MDI close mode is %s.\n"), value);
+}
+
+static void
+show_mdi_rununcached (struct ui_file *file, int from_tty,
+		      struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Program starts uncached is %s.\n"), value);
+}
+
+static void
+show_mdi_waittime (struct ui_file *file, int from_tty,
+		   struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MDI poll period is %s ms.\n"), value);
+}
+
+static void
+show_mdi_releaseonclose (struct ui_file *file, int from_tty,
+			 struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MDI release on close is %s.\n"), value);
+}
+
+static void
+show_mdi_logfile (struct ui_file *file, int from_tty,
+		  struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MDI log file is \"%s\".\n"), value);
+}
+
+static void
+show_mdi_logdocommand (struct ui_file *file, int from_tty,
+		       struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("\
+The command for the MDI target for logging gdb commands is \"%s\".\n"),
+		    value);
+}
+
+static void
+show_mdi_library (struct ui_file *file, int from_tty,
+		  struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MDI interface library is \"%s\".\n"), value);
+}
+
+static void
+show_mdi_configfile (struct ui_file *file, int from_tty,
+		     struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MIPSsim config file is \"%s\".\n"), value);
+}
+
+static void
+show_mdi_devcfgfile (struct ui_file *file, int from_tty,
+		     struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MIPSsim device config file is \"%s\".\n"), value);
+}
+
+static void
+show_mdi_gmonfile (struct ui_file *file, int from_tty,
+		   struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MIPSsim gmon profile file is \"%s\".\n"), value);
+}
+
+static void
+show_mdi_profiling (struct ui_file *file, int from_tty,
+		    struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MIPSsim profiling is %s.\n"), value);
+}
+
+static void
+show_mdi_profile_mcount (struct ui_file *file, int from_tty,
+			 struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Include _mcount in profile is %s.\n"), value);
+}
+
+static void
+show_mdi_profile_cycles (struct ui_file *file, int from_tty,
+			 struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Cycle accurate profiling is %s.\n"), value);
+}
+
+static void
+show_mdi_team (struct ui_file *file, int from_tty,
+	       struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MDI team number is %s.\n"), value);
+}
+
+static void
+show_mdi_target (struct ui_file *file, int from_tty,
+		 struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MDI target group number is %s.\n"), value);
+}
+
+static void
+show_mdi_device (struct ui_file *file, int from_tty,
+		 struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MDI device number is %s.\n"), value);
+}
+
+static void
+show_mdi_target_prompt (struct ui_file *file, int from_tty,
+			struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("MDI target input prompt is \"%s\".\n"), value);
+}
+
+static void
+show_mdi_ftext_syms (struct ui_file *file, int from_tty,
+		     struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("\
+Start of code section symbols names are \"%s\".\n"),
+		    value);
+}
+
+static void
+show_mdi_etext_syms (struct ui_file *file, int from_tty,
+		     struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("\
+End of code section symbols names are \"%s\".\n"),
+		    value);
+}
+
+static void
+show_mdi_mcount_syms (struct ui_file *file, int from_tty,
+		      struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("\
+The mcount symbol name list is \"%s\".\n"),
+		    value);
+}
+
+
+static const char *
+lookupName (const struct mdiresourcename_struct *ptr, int id)
+{
+  static char buf[64];
+  for ( ; ptr->mdiid && ptr->mdiid != id; ptr++)
+    continue;
+  if (ptr->mdiid != 0)
+    return (ptr->mdistr);
+  sprintf (buf, "%s (0x%x)", ptr->mdistr, id);
+  return buf;
+}
+
+static const char *
+resrcName (int resrc)
+{
+  if ((MDIMIPVIRTUAL <= resrc) && (resrc < (MDIMIPVIRTUAL + 0x100))) {
+    static char buf[64];
+    sprintf (buf, "MDIMIPVIRTUAL/ASID=%02x", resrc & 0xff);
+    return buf;
+  }
+  return lookupName (resrc_Names, resrc);
+}
+
+static const char *
+statusName (int status)
+{
+  return lookupName (status_Names, status & MDIStatusMask);
+}
+
+static char *
+bptypeName (int bptype)
+{
+  static char buf[64];
+  snprintf (buf, sizeof buf, "%s%s%s%s%s%s%s",
+	    lookupName (bptype_Names, bptype & MDIBPT_TypeMask),
+	    (bptype & MDIBPT_HWFlg_AddrMask) ? "|AddrMask" : "",
+	    (bptype & MDIBPT_HWFlg_AddrRange) ? "|AddrRange" : "",
+	    (bptype & MDIBPT_HWFlg_DataValue) ? "|DataValue" : "",
+	    (bptype & MDIBPT_HWFlg_DataMask) ? "|DataMask" : "",
+	    (bptype & MDIBPT_HWFlg_Trigger) ? "|Trigger" : "",
+	    (bptype & MDIBPT_HWFlg_TriggerOnly) ? "|TriggerOnly" : "");
+
+  return buf;
+}
+
+static void
+mdiDisplayRunState (MDIRunStateT * runstate)
+{
+  MDIUint32 status = runstate->Status;
+  fprintf_unfiltered (mdi_logfp, "runstate=%s%s%s",
+		      statusName (status),
+		      (status & MDIStatusReset) ? ", in reset" : "",
+		      (status & MDIStatusWasReset) ? ", was reset" : "");
+  switch (status & MDIStatusMask)
+    {
+    case MDIStatusExited:
+      fprintf_unfiltered (mdi_logfp, ", ec=0x%x",
+			  runstate->Info.value);
+      break;
+    case MDIStatusBPHit:
+      fprintf_unfiltered (mdi_logfp, ", BpID=%u",
+			  runstate->Info.value);
+      break;
+    case MDIStatusException:
+      fprintf_unfiltered (mdi_logfp, ", exc=%u",
+			  runstate->Info.value);
+      break;
+    }
+  if (status & MDIStatusDescription)
+    fprintf_unfiltered (mdi_logfp, ", desc=\"%s\"",
+			(char *) runstate->Info.ptr);
+  fputc_unfiltered ('\n', mdi_logfp);
+}
+
+
+
+#include "mdilink.h"
+
+#if defined(_WIN32) || defined(__CYGWIN32__)
+#include <windows.h>
+#define DEFAULT_LIB_NAME "mdi.dll"
+#else
+#define DEFAULT_LIB_NAME "libmdi.so"
+#endif
+
+#if defined(_WIN32) && !defined(__CYGWIN32__)
+#define OpenLib(libname)  \
+  LoadLibrary (libname)
+#define CloseLib(libhandle) \
+  FreeLibrary ((HMODULE) (libhandle))
+#define GetLibSymbolAddress(libhandle, symbolname) \
+  ((void*) GetProcAddress ((HMODULE) (libhandle), (symbolname)))
+#else
+#include <dlfcn.h>
+#define OpenLib(libname) \
+  dlopen (libname, RTLD_LAZY)
+#define CloseLib(libhandle) \
+  dlclose (libhandle)
+#define GetLibSymbolAddress(libhandle, symbolname) \
+  dlsym (libhandle, symbolname)
+#endif
+
+struct libsymbol
+{
+  const char *name;
+  void *funcp;
+  int required;
+};
+
+#if __STDC__
+#define sym(x, req) {F ## x, &x, req}
+#else
+#define sym(x, req) {F/**/x, &x, req}
+#endif
+
+/* List of symbols defined in MDI DLL.  */
+static const struct libsymbol symbols[] = {
+  sym (MDIVersion, 1),
+  sym (MDIConnect, 1),
+  sym (MDIDisconnect, 1),
+  sym (MDITGQuery, 1),
+  sym (MDITGOpen, 1),
+  sym (MDITGClose, 1),
+  sym (MDITGExecute, 1),
+  sym (MDITGStop, 1),
+  sym (MDIDQuery, 1),
+  sym (MDIOpen, 1),
+  sym (MDIClose, 1),
+  sym (MDIRead, 1),
+  sym (MDIWrite, 1),
+  sym (MDIReadList, 1),
+  sym (MDIWriteList, 1),
+  sym (MDIMove, 1),
+  sym (MDIFill, 1),
+  sym (MDIFind, 1),
+  sym (MDIExecute, 1),
+  sym (MDIStep, 1),
+  sym (MDIStop, 1),
+  sym (MDIReset, 1),
+  sym (MDICacheQuery, 1),
+  sym (MDICacheFlush, 1),
+  sym (MDIRunState, 1),
+  sym (MDISetBp, 1),
+  sym (MDISetSWBp, 1),
+  sym (MDIClearBp, 1),
+  sym (MDIEnableBp, 1),
+  sym (MDIDisableBp, 1),
+  sym (MDIBpQuery, 1),
+  sym (MDIHwBpQuery, 0),
+  sym (MDIDoCommand, 1),
+  sym (MDIAbort, 1),
+  sym (MDITraceEnable, 1),
+  sym (MDITraceDisable, 1),
+  sym (MDITraceClear, 1),
+  sym (MDITraceStatus, 1),
+  sym (MDITraceCount, 1),
+  sym (MDITraceRead, 1),
+  /* Optional multi-threading extensions.  */
+  sym (MDIGetTC, 0),
+  sym (MDISetTC, 0),
+  sym (MDITCQuery, 0),
+  sym (MDISetRunMode, 0),
+  /* Early MT MDI spec revision names.  */
+  sym (MDIQueryTC, 0),
+  sym (MDITCGet, 0),
+  sym (MDITCSet, 0),
+  sym (MDITCSetRunMode, 0),
+  sym (MDISetTCRunMode, 0),
+  /* Optional team support extensions.  */
+  sym (MDITeamCreate, 0),
+  sym (MDIQueryTeams, 0),
+  sym (MDITeamClear, 0),
+  sym (MDITeamDestroy, 0),
+  sym (MDITMAttach, 0),
+  sym (MDITMDetach, 0),
+  sym (MDIQueryTM, 0),
+  sym (MDITeamExecute, 0),
+  /* Early MT MDI spec revision names.  */
+  sym (MDICreateTeam, 0),
+  sym (MDIClearTeam, 0),
+  sym (MDIDestroyTeam, 0),
+  sym (MDIAttachTM, 0),
+  sym (MDIDetachTM, 0),
+  sym (MDITMQuery, 0),
+  /* MIPSsim special interfaces.  */
+  sym (MIPSsim_SetConfigFile, 0),
+  sym (MIPSsim_CreateProfile, 0),
+  sym (MIPSsim_DestroyProfile, 0),
+  sym (MIPSsim_StartProfile, 0),
+  sym (MIPSsim_StopProfile, 0),
+  sym (MIPSsim_ClearProfile, 0),
+  sym (MIPSsim_FetchProfile, 0),
+  sym (MIPSsim_FreeProfileData, 0),
+  sym (MIPSsim_GetTraceLevel, 0),
+  sym (MIPSsim_SetTraceLevel, 0),
+  sym (MIPSsim_GetStats, 0),
+  sym (MIPSsim_ClearStats, 0),
+  sym (MIPSsim_GetPerfCounter, 0),
+  sym (MIPSsim_ZeroPerfCounter, 0),
+  sym (MIPSsim_ZeroPerfCounters, 0),
+  sym (MIPSsim_GetVersion, 0),
+  {0, 0, 0}
+};
+
+
+#ifdef __CYGWIN32__
+/* Copy Cygwin environment variables to Windows.  */
+static void
+cygwin_sync_winenv (void)
+{
+#if CYGWIN_VERSION_API_MAJOR > 0 || CYGWIN_VERSION_API_MINOR >= 154
+  /* Only available in Cygwin 1.15.20+.  */
+  cygwin_internal (CW_SYNC_WINENV);
+#else
+  extern char **environ;
+  char **envp = environ;
+
+  if (!envp)
+    return;
+
+  while (*envp)
+    {
+      char *var = xmalloc (strlen (*envp) + 1);
+      char *eq;
+
+      strcpy (var, *envp);
+      eq = strchr (var, '=');
+      if (eq)
+	{
+	  /* Environment variables that need special handling.  */
+	  static const char * const skipenv[] = {
+	    "PATH", "HOME", "LD_LIBRARY_PATH", "TMPDIR", "TMP", "TEMP", NULL
+	  };
+	  const char **skip;
+
+	  /* Split into name/value pair.  */
+	  *eq = '\0';
+
+	  /* Check for special variables.  */
+	  for (skip = skipenv; *skip; skip++)
+	    if (strcmp (var, *skip) == 0)
+	      break;
+
+	  /* Add non-special variables to Windows environment.  */
+	  if (!*skip)
+	    SetEnvironmentVariable (var, eq + 1);
+	}
+      xfree (var);
+      ++envp;
+    }
+#endif /* CYGWIN_VERSION_API_MAJOR == 0 && CYGWIN_VERSION_API_MINOR < 154 */
+}
+#endif /* __CYGWIN__ */
+
+
+/* Debuggers and other MDILib using applications must call this
+   function prior to calling any of the MDI API functions.  MDIInit()
+   loads the MDILib whose pathname is supplied as an argument, or the
+   registered "mdi.dll" if NULL is passed, and initializes the global
+   function pointers with the addresses of the API functions exported
+   from the library.  */
+
+static MDIInt32
+MDIInit (char *libname, HMODULE *handle)
+{
+  char *mdilib;			/* the name of the library to open  */
+  HMODULE lib;			/* the handle to the opened library */
+  char buffer[MAX_PATH];
+  int retvalue;
+  const struct libsymbol *sym;
+
+  mdilib = libname;
+
+#if defined(_WIN32) || defined(__CYGWIN32__)
+  if (!mdilib)
+    {
+      static int MDIDllName (char *, size_t);
+      retvalue = MDIDllName (buffer, MAX_PATH);
+      if (!retvalue)
+	mdilib = buffer;
+    }
+#endif
+
+  if (!mdilib)
+    mdilib = DEFAULT_LIB_NAME;
+
+#ifdef __CYGWIN32__
+  /* Sync Cygwin & Windows environments now, in case we're loading a
+     native Windows DLL which might needs a env variable set up within
+     the Cygwin environment.  Cygwin does this automatically only when
+     spawning a new process, not when loading a DLL.  */
+  cygwin_sync_winenv ();
+#endif
+
+  lib = OpenLib (mdilib);
+  if (!lib)
+    {
+#if ! (defined(_WIN32) && !defined(__CYGWIN32__))
+      char *error  = dlerror ();
+      if (error)
+	fprintf_unfiltered (mdi_logfp, "DLL open error: %s\n", error);
+#endif
+      return MDIErrLoadLib;
+    }
+
+  /* The library has been opened, take all the function pointers
+     defined in mdi.h and point them into the library.  */
+  for (sym = symbols; sym->name; sym++)
+    {
+      *(void **) sym->funcp = GetLibSymbolAddress (lib, sym->name);
+      if (!*(void **) sym->funcp && sym->required)
+	{
+	  CloseLib (lib);
+	  return MDIErrLoadLib;
+	}
+    }
+
+  *handle = (HMODULE) lib;
+  return (MDISuccess);
+}
+
+#if defined(_WIN32) || defined(__CYGWIN32__)
+
+/* MDIDllName returns the fully qualified path of the active mdi.dll.
+   If there is no registered mdi.dll or mdi.dll is incorrectly
+   registered MDIDllName will return the fully qualified path of
+   mdi.dll as it would be loaded by the OS.  */
+
+static int
+MDIDllName (char *dllname, size_t size)
+{
+  int status;
+  HKEY keyHandle;
+  DWORD type;
+  DWORD bufsize;
+  unsigned char buffer[MAX_PATH];
+
+  status =
+    RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SOFTWARE\\MDI", 0, KEY_READ,
+		  &keyHandle);
+  if (status == ERROR_SUCCESS)
+    {
+      bufsize = MAX_PATH;
+      status =
+	RegQueryValueEx (keyHandle, "Active DLL", 0, &type, buffer, &bufsize);
+      RegCloseKey (keyHandle);
+      if (status == ERROR_SUCCESS && bufsize <= MAX_PATH)
+	{
+	  status =
+	    RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SOFTWARE\\MDI\\MDIDLL", 0,
+			  KEY_READ, &keyHandle);
+	  if (status == ERROR_SUCCESS)
+	    {
+	      bufsize = MAX_PATH;
+	      status =
+		RegQueryValueEx (keyHandle, (char *) buffer, 0, &type, buffer,
+				 &bufsize);
+	      RegCloseKey (keyHandle);
+	      if (status == ERROR_SUCCESS && bufsize <= MAX_PATH)
+		{
+		  switch (type)
+		    {
+		    case REG_EXPAND_SZ:
+		      bufsize =
+			ExpandEnvironmentStrings ((const char *) buffer,
+						  dllname, size);
+		      if (bufsize > size)
+			{
+			  return -1;
+			}
+		      return 0;
+
+		    case REG_SZ:
+		    case REG_MULTI_SZ:
+		      strncpy (dllname, (const char *) buffer, size);
+		      if (bufsize > size)
+			{
+			  return -1;
+			}
+		      return 0;
+		    }
+		}
+	    }
+	}
+    }
+
+  bufsize = SearchPath (0, DEFAULT_LIB_NAME, 0, size, dllname, 0);
+  if (bufsize && bufsize <= MAX_PATH)
+    return 0;
+
+  return -1;
+}
+#endif /* _WIN32 || __CYGWIN32__ */
+
+static int
+MDIRelease (HMODULE lib)
+{
+  const struct libsymbol *sym;
+
+  /* Clear all the function pointers, just in case...  */
+  for (sym = symbols; sym->name; sym++)
+    *(void **) sym->funcp = NULL;
+
+  CloseLib (lib);
+  return MDISuccess;
+}
+
+
+
+static MDIInt32
+mdiVersion (MDIVersionRangeT * version)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiVersion (-)\n");
+  stat = MDIVersion (version);
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: version = 0x%x-0x%x\n",
+			    version->oldest, version->newest);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiConnect (MDIVersionT version, MDIHandleT * handle, MDIConfigT * config)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiConnect (0x%08x, -, -)\n", version);
+  stat = MDIConnect (version, handle, config);
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: handle = 0x%x\n", *handle);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiDisconnect (MDIHandleT MDIHandle, MDIUint32 flags)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiDisconnect (-, flags 0x%x)\n", flags);
+  stat = MDIDisconnect (MDIHandle, flags);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiTGQuery (MDIHandleT MDIHandle, MDIInt32 * HowMany, MDITGDataT * TGData)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTGQuery (-, &%d, %p)\n", *HowMany,
+			TGData);
+  stat = MDITGQuery (MDIHandle, HowMany, TGData);
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *HowMany = %d\n", *HowMany);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiTGOpen (MDIHandleT MDIHandle, MDITGIdT TGId, MDIUint32 flags,
+	   MDIHandleT * TGHandle)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp,
+			"mdiTGOpen (-, TGId 0x%x, flags 0x%x, -)\n",
+			TGId, flags);
+  stat = MDITGOpen (MDIHandle, TGId, flags, TGHandle);
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *TGHandle = 0x%x\n",
+			    *TGHandle);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiTGClose (MDIHandleT TGHandle, MDIUint32 flags)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTGClose (0x%x, flags 0x%x)\n",
+			TGHandle, flags);
+  stat = MDITGClose (TGHandle, flags);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+#if unused
+static MDIInt32
+mdiTGExecute (MDIHandleT TGHandle)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTGExecute (0x%x)\n", TGHandle);
+  stat = MDITGExecute (TGHandle);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiTGStop (MDIHandleT TGHandle)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTGStop (0x%x)\n", TGHandle);
+  stat = MDITGStop (TGHandle);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+#endif
+
+static MDIInt32
+mdiDQuery (MDIHandleT TGHandle, MDIInt32 * HowMany, MDIDDataT * DData)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiDQuery (0x%x, &%d, %p)\n",
+			TGHandle, *HowMany, DData);
+  stat = MDIDQuery (TGHandle, HowMany, DData);
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *HowMany = %d\n", *HowMany);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiOpen (MDIHandleT TGHandle, MDIDeviceIdT DeviceID, MDIUint32 flags,
+	 MDIHandleT * DeviceHandle)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiOpen (0x%x, 0x%x, flags 0x%0x, -)\n",
+			TGHandle, DeviceID, flags);
+  stat = MDIOpen (TGHandle, DeviceID, flags, DeviceHandle);
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *DevHandle = 0x%x\n",
+			    *DeviceHandle);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiClose (MDIHandleT DeviceHandle, MDIUint32 flags)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiClose (0x%x, flags 0x%x)\n",
+			DeviceHandle, flags);
+  stat = MDIClose (DeviceHandle, flags);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiRead (MDIHandleT Device, MDIResourceT SrcR, MDIOffsetT SrcO, void *Buffer,
+	 MDIUint32 ObjectSize, MDIUint32 Count)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiRead (0x%x, %s, 0x%s, -, %d, %d)\n",
+			Device, resrcName (SrcR),
+			phex_nz (SrcO, sizeof SrcO), ObjectSize, Count);
+  stat = MDIRead (Device, SrcR, SrcO, Buffer, ObjectSize, Count);
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	{
+	  fprintf_unfiltered (mdi_logfp, "read:");
+	  dump_mem (Buffer, ObjectSize, Count);
+	}
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiWrite (MDIHandleT Device, MDIResourceT DstR, MDIOffsetT DstO, void *Buffer,
+	  MDIUint32 ObjectSize, MDIUint32 Count)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    {
+      fprintf_unfiltered (mdi_logfp, "mdiWrite (0x%x, %s, 0x%s, -, %d, %d)\n",
+			  Device, resrcName (DstR),
+			  phex_nz (DstO, sizeof DstO),
+			  ObjectSize, Count);
+      fprintf_unfiltered (mdi_logfp, "write:");
+      dump_mem (Buffer, ObjectSize, Count);
+    }
+  stat = MDIWrite (Device, DstR, DstO, Buffer, ObjectSize, Count);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+#if unused
+static MDIInt32
+mdiReadList (MDIHandleT Device, MDIUint32 ObjectSize, MDICRangeT * SrcList,
+	     MDIUint32 ListCount, void *Buffer)
+{
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiReadList (-, %d, -, %d, -)\n",
+			ObjectSize, ListCount);
+  return MDIReadList (Device, ObjectSize, SrcList, ListCount, Buffer);
+}
+
+static MDIInt32
+mdiWriteList (MDIHandleT Device, MDIUint32 ObjectSize, MDICRangeT * DstList,
+	      MDIUint32 ListCount, void *Buffer)
+{
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiWriteList (-, %d, -, %d, -)\n",
+			ObjectSize, ListCount);
+  return MDIWriteList (Device, ObjectSize, DstList, ListCount, Buffer);
+}
+
+static MDIInt32
+mdiMove (MDIHandleT Device, MDIResourceT SrcR, MDIOffsetT SrcO,
+	 MDIResourceT DstR, MDIOffsetT DstO, MDIUint32 ObjectSize,
+	 MDIUint32 Count, MDIUint32 Flag)
+{
+  if (remote_debug > 1)
+    fprintf_unfiltered
+      (mdi_logfp,
+       "mdiMove (-, %s, 0x%s, %s, 0x%s, Objsz %d, Cnt %d, Flg 0x%x)\n",
+       resrcName (SrcR), phex_nz (SrcO, sizeof SrcO),
+       resrcName (DstR), phex_nz (DstO, sizeof DstO),
+       ObjectSize, Count, Flag);
+  return MDIMove (Device, SrcR, SrcO, DstR, DstO, ObjectSize, Count, Flag);
+}
+
+static MDIInt32
+mdiFill (MDIHandleT Device, MDIResourceT DstR, MDIRangeT DstRng, void *Buffer,
+	 MDIUint32 ObjectSize, MDIUint32 Count)
+{
+  if (remote_debug > 1)
+    fprintf_unfiltered
+      (mdi_logfp,
+       "mdiFill (-, %s, Rng 0x%s-0x%s, -, Objsz %d, Cnt %d)\n",
+       resrcName (DstR), phex_nz (DstRng.Start, sizeof DstRng.Start),
+       phex_nz (DstRng.End, sizeof DstRng.End), ObjectSize, Count);
+  return MDIFill (Device, DstR, DstRng, Buffer, ObjectSize, Count);
+}
+
+static MDIInt32
+mdiFind (MDIHandleT Device, MDIResourceT SrcR, MDIRangeT SrcRng, void *Buffer,
+	 void *MaskBuffer, MDIUint32 ObjectSize, MDIUint32 Count,
+	 MDIOffsetT * FoundOffset, MDIUint32 Mode)
+{
+  if (remote_debug > 1)
+    fprintf_unfiltered
+      (
+       mdi_logfp,
+       "mdiFind (-, %s, Rng 0x%s-0x%s, -, -, Objsz %d, Cnt %d, -, Mode %d)\n",
+       resrcName (SrcR), phex_nz (SrcRng.Start, sizeof SrcRng.Start),
+       phex_nz (SrcRng.End, sizeof SrcRng.End), ObjectSize, Count, Mode);
+  return MDIFind (Device, SrcR, SrcRng, Buffer, MaskBuffer, ObjectSize, Count,
+		  FoundOffset, Mode);
+}
+#endif
+
+static MDIInt32
+mdiExecute (MDIHandleT Device)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiExecute (0x%x)\n", Device);
+  stat = MDIExecute (Device);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiStep (MDIHandleT Device, MDIUint32 Steps, MDIUint32 Mode)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiStep (0x%x, %d, %d)\n",
+			Device, Steps, Mode);
+  stat = MDIStep (Device, Steps, Mode);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiStop (MDIHandleT Device)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiStop (0x%x)\n", Device);
+  stat = MDIStop (Device);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiReset (MDIHandleT Device, MDIUint32 Flag)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiReset (0x%x, Flg 0x%x)\n",
+			Device, Flag);
+  stat = MDIReset (Device, Flag);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiCacheQuery (MDIHandleT Device, MDICacheInfoT * CacheInfo)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiCacheQuery (0x%x, -)\n", Device);
+  stat = MDICacheQuery (Device, CacheInfo);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiCacheFlush (MDIHandleT Device, MDIUint32 Type, MDIUint32 Flag)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiCacheFlush (0x%x, Type %d, Flg 0x%x)\n",
+			Device, Type, Flag);
+  stat = MDICacheFlush (Device, Type, Flag);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiRunState (MDIHandleT Device, MDIInt32 WaitTime, MDIRunStateT * runstate)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiRunState (0x%x, Wait %d, -)\n",
+			Device, WaitTime);
+  stat = MDIRunState (Device, WaitTime, runstate);
+  if (remote_debug > 1)
+    {
+      fprintf_unfiltered (mdi_logfp, "returned: ");
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "%s\n", mdierrcode (stat));
+      else
+	mdiDisplayRunState (runstate);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiSetBp (MDIHandleT Device, MDIBpDataT * BpData)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "\
+mdiSetBp (0x%x, {%s, Enb %d, %s, 0x%s-0x%s, PassC %d, Pass2Go %d})\n",
+			Device,
+			bptypeName (BpData->Type), BpData->Enabled,
+			resrcName (BpData->Resource),
+			phex_nz (BpData->Range.Start,
+				 sizeof BpData->Range.Start),
+			phex_nz (BpData->Range.End,
+				 sizeof BpData->Range.End),
+			BpData->PassCount,
+			BpData->PassesToGo);
+  stat = MDISetBp (Device, BpData);
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: BpId=0x%x\n", BpData->Id);
+    }
+  return stat;
+}
+
+#if unused
+static MDIInt32
+mdiSetSWBp (MDIHandleT Device, MDIResourceT SrcResource, MDIOffsetT SrcOffset,
+	    MDIBpIdT * BpId)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiSetSWBp (0x%x, %s, 0x%s, -)\n",
+			Device, resrcName (SrcResource),
+			phex_nz (SrcOffset, sizeof SrcOffset));
+  stat = MDISetSWBp (Device, SrcResource, SrcOffset, BpId);
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: BpId=0x%x\n", *BpId);
+    }
+  return stat;
+}
+#endif
+
+static MDIInt32
+mdiClearBp (MDIHandleT Device, MDIBpIdT BpID)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiClearBp (0x%x, BpID 0x%x)\n",
+			Device, BpID);
+  stat = MDIClearBp (Device, BpID);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+#if unused
+static MDIInt32
+mdiEnableBp (MDIHandleT Device, MDIBpIdT BpID)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiEnableBp (0x%x, BpID 0x%x)\n",
+			Device, BpID);
+  stat = MDIEnableBp (Device, BpID);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiDisableBp (MDIHandleT Device, MDIBpIdT BpID)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiDisableBp ()\n");
+  stat = MDIDisableBp (Device, BpID);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiBpQuery (MDIHandleT Device, MDIInt32 * HowMany, MDIBpDataT * BpData)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiBpQuery (0x%x, &%d, -)\n",
+			Device, *HowMany);
+  stat = MDIBpQuery (Device, HowMany, BpData);
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *HowMany = %d\n", *HowMany);
+    }
+  return stat;
+}
+#endif
+
+static MDIInt32
+mdiHwBpQuery (MDIHandleT Device, MDIInt32 *HowMany, MDIBpInfoT *BpInfo)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiHwBpQuery (0x%x, &%d, -)\n",
+			Device, *HowMany);
+  if (MDIHwBpQuery)
+    stat = MDIHwBpQuery (Device, HowMany, BpInfo);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *HowMany = %d\n", *HowMany);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiDoCommand (MDIHandleT Device, char *Buffer)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiDoCommand (0x%x, \"%s\")\n",
+			Device, Buffer);
+  stat = MDIDoCommand (Device, Buffer);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiAbort (MDIHandleT Device)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiAbort (0x%x)\n", Device);
+  stat = MDIAbort (Device);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+#if unused
+static MDIInt32
+mdiTraceEnable (MDIHandleT Device)
+{
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTraceEnable (-)\n");
+  return MDITraceEnable (Device);
+}
+
+static MDIInt32
+mdiTraceDisable (MDIHandleT Device)
+{
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTraceDisable (-)\n");
+  return MDITraceDisable (Device);
+}
+
+static MDIInt32
+mdiTraceClear (MDIHandleT Device)
+{
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTraceClear (-)\n");
+  return MDITraceClear (Device);
+}
+
+static MDIInt32
+mdiTraceStatus (MDIHandleT Device, MDIUint32 * Status)
+{
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTraceStatus (-, -)\n");
+  return MDITraceStatus (Device, Status);
+}
+
+static MDIInt32
+mdiTraceCount (MDIHandleT Device, MDIUint32 * FrameCount)
+{
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTraceCount (-, -)\n");
+  return MDITraceCount (Device, FrameCount);
+}
+
+static MDIInt32
+mdiTraceRead (MDIHandleT Device, MDIUint32 FirstFrame, MDIUint32 FrameCount,
+	      MDIUint32 IncludeInstructions, MDITrcFrameT * Frames)
+{
+  if (remote_debug > 1)
+    fprintf_filtered
+      (mdi_logfp,
+       "mdiTraceRead (-, FirstFrame %d, FrameCnt %d, Insts? %d, -)\n",
+       FirstFrame, FrameCount, IncludeInstructions);
+  return MDITraceRead (Device, FirstFrame, FrameCount, IncludeInstructions,
+		       Frames);
+}
+#endif
+
+static MDIInt32
+mdiSetTC (MDIHandleT Device, MDITCIdT TCId)
+{
+  MDIInt32 stat;
+
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiSetTC (0x%x, TCId 0x%x)\n",
+			Device, TCId);
+  if (MDISetTC)
+    stat = MDISetTC (Device, TCId);
+  else if (MDITCSet)
+    stat = MDITCSet (Device, TCId);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiGetTC (MDIHandleT Device, MDITCIdT *TCId)
+{
+  MDIInt32 stat;
+
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiGetTC (0x%x, -)\n", Device);
+  if (MDIGetTC)
+    stat = MDIGetTC (Device, TCId);
+  else if (MDITCGet)
+    stat = MDITCGet (Device, TCId);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *TCId = 0x%x\n", *TCId);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiTCQuery (MDIHandleT Device, MDIInt32 *HowMany, MDITCDataT *TCData)
+{
+  MDIInt32 stat;
+
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTCQuery (0x%x, &%d, -)\n",
+			Device, *HowMany);
+  if (MDITCQuery)
+    stat = MDITCQuery (Device, HowMany, TCData);
+  else if (MDIQueryTC)
+    stat = MDIQueryTC (Device, HowMany, TCData);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *HowMany = %d\n", *HowMany);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiSetRunMode (MDIHandleT Device, MDITCIdT TCId, MDIUint32 StepMode,
+	       MDIUint32 SuspendMode)
+{
+  MDIInt32 stat;
+
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp,
+			"mdiSetRunMode (0x%x, TCId 0x%x, %d, %u)\n",
+			Device, TCId, StepMode, SuspendMode);
+  if (MDISetRunMode)
+    stat = MDISetRunMode (Device, TCId, StepMode, SuspendMode);
+  else if (MDISetTCRunMode)
+    stat = MDISetTCRunMode (Device, TCId, StepMode != MDINoStep, SuspendMode);
+  else if (MDITCSetRunMode)
+    stat = MDITCSetRunMode (Device, TCId, StepMode != MDINoStep, SuspendMode);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiTeamCreate (MDIHandleT MDIHandle, MDITeamIdT *TeamId)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTeamCreate (0x%x, -)\n", MDIHandle);
+  if (MDITeamCreate)
+    stat = MDITeamCreate (MDIHandle, TeamId);
+  else if (MDICreateTeam)
+    stat = MDICreateTeam (MDIHandle, TeamId);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *TeamId = 0x%x\n", *TeamId);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiQueryTeams (MDIHandleT MDIHandle, MDIInt32 *HowMany, MDITeamIdT *TeamId)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiQueryTeams (0x%x, &%d, -)\n",
+			MDIHandle, *HowMany);
+  if (MDIQueryTeams)
+    stat = MDIQueryTeams (MDIHandle, HowMany, TeamId);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *HowMany = %d\n", *HowMany);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiTeamClear (MDIHandleT MDIHandle, MDITeamIdT TeamId)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTeamClear (0x%x, TeamId 0x%x)\n",
+			MDIHandle, TeamId);
+  if (MDITeamClear)
+    stat = MDITeamClear (MDIHandle, TeamId);
+  else if (MDIClearTeam)
+    stat = MDIClearTeam (MDIHandle, TeamId);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiTeamDestroy (MDIHandleT MDIHandle, MDITeamIdT TeamId)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTeamDestroy (0x%x, TeamId 0x%x)\n",
+			MDIHandle, TeamId);
+  if (MDITeamDestroy)
+    stat = MDITeamDestroy (MDIHandle, TeamId);
+  else if (MDIDestroyTeam)
+    stat = MDIDestroyTeam (MDIHandle, TeamId);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiTMAttach (MDIHandleT MDIHandle, MDITeamIdT TeamId, MDITMDataT *TMData)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTMAttach "
+			"(0x%x, TeamId 0x%x, { 0x%x, TGId 0x%x, 0x%x })\n",
+			MDIHandle, TeamId,
+			TMData->MDIHandle, TMData->TGId, TMData->DevId);
+  if (MDITMAttach)
+    stat = MDITMAttach (MDIHandle, TeamId, TMData);
+  else if (MDIAttachTM)
+    stat = MDIAttachTM (MDIHandle, TeamId, TMData);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiTMDetach (MDIHandleT MDIHandle, MDITeamIdT TeamId, MDITMDataT *TMData)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTMDetach "
+			"(0x%x, TeamId 0x%x, { 0x%x, TGId 0x%x, 0x%x })\n",
+			MDIHandle, TeamId,
+			TMData->MDIHandle, TMData->TGId, TMData->DevId);
+  if (MDITMDetach)
+    stat = MDITMDetach (MDIHandle, TeamId, TMData);
+  else if (MDIDetachTM)
+    stat = MDIDetachTM (MDIHandle, TeamId, TMData);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mdiQueryTM (MDIHandleT MDIHandle, MDITeamIdT TeamId, MDIInt32 *HowMany,
+	    MDITMDataT *TMData)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiQueryTM (0x%x, TeamId 0x%x, &%d, -)\n",
+			MDIHandle, TeamId, *HowMany);
+  if (MDIQueryTM)
+    stat = MDIQueryTM (MDIHandle, TeamId, HowMany, TMData);
+  else if (MDITMQuery)
+    stat = MDITMQuery (MDIHandle, TeamId, HowMany, TMData);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *HowMany = %d\n", *HowMany);
+    }
+  return stat;
+}
+
+static MDIInt32
+mdiTeamExecute (MDIHandleT MDIHandle, MDITeamIdT TeamId)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mdiTeamExecute (0x%x, TeamId 0x%x)\n",
+			MDIHandle, TeamId);
+  if (MDITeamExecute)
+    stat = MDITeamExecute (MDIHandle, TeamId);
+  else
+    stat = MDIErrUnsupported;
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mipssim_SetConfigFile (MDIHandleT handle, char *name)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mipssim_SetConfigFile (0x%x, \"%s\")\n",
+			handle, name);
+  stat = MIPSsim_SetConfigFile (handle, name);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mipssim_CreateProfile (MDIHandleT handle, MDIInt32 *pid,
+		       MDIUint64 start, MDIUint64 size)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp,
+			"mipssim_CreateProfile (0x%x, -, 0x%s, 0x%s)\n",
+			handle,
+			phex_nz (start, sizeof start),
+			phex_nz (size, sizeof size));
+  stat = MIPSsim_CreateProfile (handle, pid, start, size);
+  if (remote_debug > 1)
+    {
+      if (stat != MDISuccess)
+	fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+      else
+	fprintf_unfiltered (mdi_logfp, "returned: *pid = %d\n", *pid);
+    }
+  return stat;
+}
+
+static MDIInt32
+mipssim_DestroyProfile (MDIHandleT handle, MDIInt32 id)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mipssim_DestroyProfile (0x%x, 0x%x)\n",
+			handle, id);
+  stat = MIPSsim_DestroyProfile (handle, id);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mipssim_StartProfile (MDIHandleT handle, MDIInt32 id)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mipssim_StartProfile (0x%x, 0x%x)\n",
+			handle, id);
+  stat = MIPSsim_StartProfile (handle, id);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mipssim_StopProfile (MDIHandleT handle, MDIInt32 id)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mipssim_StopProfile (0x%X, 0x%x)\n",
+			handle, id);
+  stat = MIPSsim_StopProfile (handle, id);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+#if unused
+static MDIInt32
+mipssim_ClearProfile (MDIHandleT handle, MDIInt32 id)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mipssim_ClearProfile (0x%x, 0x%x)\n",
+			handle, id);
+  stat = MIPSsim_ClearProfile (handle, id);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+#endif
+
+static MDIInt32
+mipssim_FetchProfile (MDIHandleT handle, MDIInt32 id,
+		      MDIUint32 **cntbufp, MDIUint64 *cyclesp)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mipssim_FetchProfile (0x%x, 0x%x, -, -)\n",
+			handle, id);
+  stat = MIPSsim_FetchProfile (handle, id, cntbufp, cyclesp);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+static MDIInt32
+mipssim_FreeProfileData (MDIHandleT handle, MDIUint32 **cntbufp)
+{
+  MDIInt32 stat;
+  if (remote_debug > 1)
+    fprintf_unfiltered (mdi_logfp, "mipssim_FreeProfileData (0x%x, -)\n",
+			handle);
+  stat = MIPSsim_FreeProfileData (handle, cntbufp);
+  if (remote_debug > 1 && stat != MDISuccess)
+    fprintf_unfiltered (mdi_logfp, "returned: %s\n", mdierrcode (stat));
+  return stat;
+}
+
+
+
+static void
+togdb_force_update (void)
+{
+#ifdef GDBTK
+  if (gdbtk_interp != NULL)
+    Tcl_Eval (gdbtk_interp, "gdbtk_update");
+#endif
+}
+
+static void
+check_mdi (void)
+{
+  if (mdi_desc == NULL)
+    error (_("MDI connection not opened yet, use the 'target mdi' command."));
+};
+
+static int
+isa2int (char *str)
+{
+  const struct isa_xlate_struct *p;
+
+  for (p = isa_xlate; p->isa && strcmp (p->isa, str); p++)
+    continue;
+  return p->num;
+}
+
+
+static void
+dump_mem (void *buffer, int elsize, int cnt)
+{
+  gdb_byte *buf = buffer;
+  int col = 0;
+  int width;
+  int n;
+
+  if (elsize > sizeof(ULONGEST))
+    {
+      fprintf_unfiltered (mdi_logfp, "Cannot print objects of size %d\n",
+			  elsize);
+      return;
+    }
+
+  if (elsize == 0)
+    elsize = 1;
+
+  n = (cnt * elsize > 128) ? 128 / elsize : cnt;
+
+  width = 16 / elsize;
+
+  while (n-- > 0)
+    {
+      ULONGEST val = extract_unsigned_integer (buf, elsize);
+      buf += elsize;
+      cnt -= 1;
+
+      if (col == 0)
+	fprintf_unfiltered (mdi_logfp, "\t");
+
+      if (elsize > 1)
+	fprintf_unfiltered (mdi_logfp, "%s ", phex (val, elsize));
+      else
+	fprintf_unfiltered (mdi_logfp, "%02x ", (unsigned int)val & 0xff);
+
+      if (++col == width || n == 0)
+	{
+	  /* Output ascii dump for byte size elements.  */
+	  if (elsize == 1)
+	    {
+	      int limit = col;
+	      buf -= col;		/* Backup over printed bytes.  */
+	      /* Space across to ascii column.  */
+	      for ( ; col < width + 1; col++)
+		fprintf_unfiltered (mdi_logfp, "   ");
+	      for (col = 0; col < limit; col++)
+		{
+		  fputc_unfiltered (isprint (*buf) ? *buf : '.', mdi_logfp);
+		  buf++;
+		}
+	    }
+	  fprintf_unfiltered (mdi_logfp, "\n");
+	  col = 0;
+	}
+    }
+
+  if (col != 0)
+    fprintf_unfiltered (mdi_logfp, "\n");
+  if (cnt != 0)
+    fprintf_unfiltered (mdi_logfp, "\tetc...\n");
+}
+
+
+static const char *
+mdierrcode (MDIInt32 err)
+{
+  const char *es;
+  static char buf[64];
+  int i;
+
+  for (i = 0; (es = errorcodes[i].str) && errorcodes[i].errorcode != err; i++)
+    continue;
+
+  if (es)
+    return es;
+
+  sprintf (buf, "MDIerr=%d", err);
+  return buf;
+}
+
+static void
+mdierr (const char *file, int line, MDIInt32 err, const char *what)
+{
+  const char *es = mdierrcode (err);
+  if (remote_debug)
+    error (_("%s:%d: %s failed (%s)"), file, line, what, es);
+  else
+    error (_("MDI %s failed (%s)"), what, es);
+}
+
+#define MDIERR(op, what) \
+  do \
+    { \
+      MDIInt32 __stat = (op); \
+      if (__stat != MDISuccess) \
+	mdierr (__FILE__, __LINE__, __stat, what); \
+    } \
+  while (0)
+
+static void
+mdiwarn (char *file, int line, MDIInt32 err, const char *what)
+{
+  const char *es = mdierrcode (err);
+
+  if (remote_debug)
+    warning (_("%s:%d: %s failed (%s)"), file, line, what, es);
+  else
+    warning (_("MDI %s failed (%s)"), what, es);
+}
+
+#define MDIWARN(op, what) \
+  do \
+    { \
+      MDIInt32 __stat = (op); \
+      if (__stat != MDISuccess) \
+	mdiwarn (__FILE__, __LINE__, __stat, what); \
+    } \
+  while (0)
+
+
+
+static MDIInt32 __stdcall
+mdiPeriodic (MDIHandleT handle)
+{
+  int stop = 0;
+
+  /* Only call ui_loop_hook if this callback is from mdi_wait or
+     mdi_resume(step==1).
+
+     Unfortunately MDIRead/MDIWrite also call the periodic callback
+     and that can lead to problems where the GUI tries to refresh the
+     memory window etc.  */
+
+  if (deprecated_ui_loop_hook != NULL && (mdi_wait_active || mdi_step_active))
+    stop = deprecated_ui_loop_hook (0);
+
+  if (stop)
+    quit_flag = 1;
+  if (quit_flag)		/* gdb's idea of quit */
+    {
+      MDIInt32 mdistat;
+      if (mdi_step_active)
+	mdistat = mdiAbort (handle);
+      /* XXX How do we stop a normal wait?  */
+    }
+
+  if (remote_debug)
+    {
+      static int progress = 0;
+      if ((progress++ % 30) == 0)
+	{
+	  printf_unfiltered (".");
+	  gdb_flush (gdb_stdout);
+	  if (quit_flag)
+	    printf_unfiltered (_("mdiPeriodic: quitting\n"));
+	}
+    }
+
+  return MDISuccess;
+}
+
+
+
+static MDIInt32
+mdi_read (MDIHandleT Device, MDIResourceT SrcR, MDIOffsetT SrcO, void *Buffer,
+	  MDIUint32 ObjectSize, MDIUint32 Count)
+{
+  if (!ptid_equal (inferior_ptid, last_ptid))
+    mdi_switch_to_thread ();
+  return mdiRead (Device, SrcR, SrcO, Buffer, ObjectSize, Count);
+}
+
+static MDIInt32
+mdi_write (MDIHandleT Device, MDIResourceT DstR, MDIOffsetT DstO, void *Buffer,
+	   MDIUint32 ObjectSize, MDIUint32 Count)
+{
+  if (!ptid_equal (inferior_ptid, last_ptid))
+    mdi_switch_to_thread ();
+  return mdiWrite (Device, DstR, DstO, Buffer, ObjectSize, Count);
+}
+
+
+
+static char *
+check_for_template (const char *dir)
+{
+  size_t dirlen;
+  char *buf;
+  struct stat s;
+
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp, "checking \"%s\" for mipssim.cfg\n",
+			dir);
+
+  dirlen = strlen (dir);
+  buf = (char *) xmalloc (dirlen + sizeof("/mipssim.cfg"));
+  sprintf (buf, "%s/mipssim.cfg", dir);
+
+  if (stat (buf, &s) == 0 && S_ISREG (s.st_mode))
+    return buf;
+
+  xfree (buf);
+  return NULL;
+}
+
+
+static void
+mdi_setconfigfile (struct mdi_state *mdi, MDIDDataT *ddata, char *cfg)
+{
+  struct cleanup *cleanups = NULL;
+  MDIInt32 mdistat;
+
+  if (! MIPSsim_SetConfigFile)
+    return;
+
+  if (! cfg || ! *cfg)
+    {
+      char tmpfile[sizeof ("/tmp/gmdiXXXXXX")];
+      char devtmpfile[sizeof ("/tmp/gmddXXXXXX")];
+      char line[256];
+      int matches = 0;
+      char *template = NULL;
+      char *dname;
+      char *end;
+      int cfgfd;
+      int copy;
+      FILE *infile, *outfile;
+      size_t dlen;
+      MDIInt32 major, minor, patch;
+
+      if (remote_debug)
+	fprintf_unfiltered (mdi_logfp, "gdb_program_name=\"%s\"\n",
+			    gdb_program_name);
+
+      end = strrchr (gdb_program_name, '/');
+#if defined(_WIN32) || defined(__CYGWIN32__)
+      {
+	/* We could have \foo\bar, or /foo\bar.  */
+	char *bslash = strrchr (gdb_program_name, '\\');
+	if (bslash > end)
+	  end = bslash;
+      }
+#endif
+
+      if (end)
+	{
+	  /* Make a copy of program_name in dir.
+	     Leave room for later "/../share".  */
+	  size_t dirlen = end - gdb_program_name;
+	  char *dir = (char *) alloca (dirlen + sizeof ("/../share"));
+	  strncpy (dir, gdb_program_name, dirlen);
+	  dir[dirlen] = '\0';
+	  template = check_for_template (dir);
+	  if (! template)
+	    {
+	      /* Try relative path - look in /../share.  */
+	      strcpy (dir + dirlen, "/../share");
+	      template = check_for_template (dir);
+	    }
+	}
+
+      if (! template)
+	{
+	  /* Try looking for it in the directories on the search path.  */
+	  char *path = getenv ("PATH");
+	  if (path)
+	    {
+	      char *sp;
+	      path = xstrdup (path);
+	      for (sp = strtok (path, ":"); ! template && sp;
+		   sp = strtok (NULL, ":"))
+		{
+		  size_t dirlen = strlen (sp);
+		  char *dir;
+		  if (dirlen == 0)
+		    continue;
+		  /* look in /path/../share.  */
+		  dir = (char *) xmalloc (dirlen + sizeof ("/../share"));
+		  strcpy (dir, sp);
+		  strcpy (dir + dirlen, "/../share");
+		  template = check_for_template (dir);
+		  xfree (dir);
+		}
+	      xfree (path);
+	    }
+	}
+
+      if (! template)
+	/* Try in the "standard" directory.  */
+	template = check_for_template (MIPSSIM_LIBRARY);
+
+      if (! template)
+	error (_("Cannot find MIPSsim config file template: mipssim.cfg"));
+
+      cleanups = make_cleanup (xfree, template);
+
+      infile = fopen (template, FOPEN_RT);
+      if (! infile)
+	error (_("Cannot open MIPSsim config template: %s"), template);
+
+      strcpy (tmpfile, "/tmp/gmdiXXXXXX");
+      cfgfd = mkstemp (tmpfile);
+      if (cfgfd < 0)
+	error (_("Cannot create temp MIPSsim config file"));
+
+      if (remote_debug)
+	printf_unfiltered (_("\
+Generating MIPSsim cfg from %s to %s for \"%s\"\n"),
+			   template, tmpfile, ddata->DName);
+
+      mdi->cfgfile = cfg = xstrdup (tmpfile);
+
+      outfile = fdopen (cfgfd, FOPEN_WT);
+      if (! outfile)
+	error (_("Cannot write to temp MIPSsim config file"));
+
+
+      /* Get MIPSsim version number.  */
+      major = MIPSsim_ZeroPerfCounter ? 4 : 3;
+      minor = 0;
+      patch = 0;
+      if (MIPSsim_GetVersion)
+	(void) MIPSsim_GetVersion (mdi->MDIHandle, &major, &minor, &patch);
+
+      dname = ddata->DName;
+
+      /* Skip unneeded leading part of name from MIPSsim 3.x.  */
+      if (strncmp (dname, "MIPS32_", sizeof "MIPS32_" - 1) == 0)
+	dname += sizeof "MIPS32_" - 1;
+      else if (strncmp (dname, "MIPS64_", sizeof "MIPS64_" - 1) == 0)
+	dname += sizeof "MIPS64_" - 1;
+
+      /* Construct string to match a regexp pattern against which
+	 includes MISPsim version number followed by CPU name.  */
+      asprintf (&dname, "%d.%d.%d;%s", major, minor, patch, dname);
+      if (! dname)
+	nomem (0);
+
+      cleanups = make_cleanup (xfree, dname);
+      dlen = strlen (dname);
+      copy = 1;
+
+      while (fgets (line, sizeof (line), infile))
+	{
+	  char *lp;
+
+	  for (lp = line; *lp && isspace (*lp); lp++)
+	    continue;
+	  if (! *lp || *lp == '#')
+	    continue;
+
+	  if (*lp == '{')
+	    {
+	      char *ep;
+	      int plen;
+	      int invert = 0;
+	      for (ep = ++lp; *ep && *ep != '}'; ep++)
+		continue;
+	      if (*ep != '}')
+		continue;
+	      if (*lp == '!')
+		{
+		  ++lp;
+		  invert = 1;
+		}
+	      plen = ep - lp;
+	      if (! strncasecmp (lp, "COMMON", plen))
+		copy = 1;
+	      else if (! strncasecmp (lp, "EB", plen))
+		copy = ddata->Endian == MDIEndianBig;
+	      else if (! strncasecmp (lp, "EL", plen))
+		copy = ddata->Endian == MDIEndianLittle;
+	      else if (! strncasecmp (lp, "DEBUG0", plen))
+		copy = remote_debug == 0;
+	      else if (! strncasecmp (lp, "DEBUG1", plen))
+		copy = remote_debug == 1;
+	      else if (! strncasecmp (lp, "DEBUG2", plen))
+		copy = remote_debug >= 2;
+	      else
+		{
+		  char * patstr;
+		  regex_t pattern;
+		  int ec;
+
+		  /* For input {xxx} make regex.  */
+		  if (asprintf (&patstr, "^(%.*s)([^-a-z0-9]|$)",
+				plen, lp) == 0)
+		    nomem (0);
+
+		  if ((ec = regcomp (&pattern, patstr,
+				     REG_ICASE | REG_EXTENDED)) == 0)
+		    {
+		      copy = re_search (&pattern, dname, dlen,
+					0, dlen, NULL) >= 0;
+		      if (copy)
+			++matches;
+		      regfree (&pattern);
+		    }
+		  else
+		    {
+		      char errorbuffer[512];
+		      regerror (ec, NULL, errorbuffer, sizeof errorbuffer);
+		      warning (_("Error in regexp /%s/: %s"), patstr,
+			       errorbuffer);
+		      copy = 0;
+		    }
+		  free (patstr);
+		}
+	      copy ^= invert;
+	      continue;
+	    }
+
+	  if (copy)
+	    fputs (line, outfile);
+	}
+
+      fclose (infile);
+
+      if (mdi_devcfgfile)
+	{
+	  char *devcfg = mdi_devcfgfile;
+#ifdef __CYGWIN32__
+	  /* Convert the Cygwin name to a Windows name.  */
+	  char winpath[MAX_PATH];
+	  if (cygwin_conv_to_win32_path (devcfg, winpath) == 0)
+	    devcfg = winpath;
+#endif
+	  if (remote_debug)
+	    printf_unfiltered (_("Adding \"set DEV_CFG %s\" to config file\n"),
+			       devcfg);
+	  fprintf (outfile, "set DEV_CFG %s\n", devcfg);
+	}
+
+      fclose (outfile);
+      if (matches == 0)
+	error (_("No entries matching MIPSsim CPU '%s' in %s"),
+	       dname, template);
+    }
+
+#ifdef __CYGWIN32__
+  /* Convert the Cygwin name to a Windows name.  */
+  {
+    char winpath[MAX_PATH];
+    if (cygwin_conv_to_win32_path (cfg, winpath) == 0)
+      cfg = winpath;
+  }
+#endif
+
+  mdistat = mipssim_SetConfigFile (mdi->MDIHandle, cfg);
+  if (mdistat != MDISuccess)
+    error (_("MIPSsim cannot access config file: \"%s\""), cfg);
+
+  if (cleanups)
+    do_cleanups (cleanups);
+}
+
+
+
+static MDIInt32
+SelectDevice (MDIDDataT * ddata, MDIInt32 n, int device)
+{
+  int i;
+  char *s;
+  unsigned long value;
+
+  if (device > n)
+    error (_("Bad device number %d, only %d devices available."), device, n);
+
+  if (device > 0 && device <= n)
+    return device - 1;
+
+  if (n == 1)
+    return (0);
+
+#ifdef GDBTK
+  /* Using command_line_input when GUI is active breaks the console window.  */
+  if (gdbtk_interp != NULL)
+    error (_("Use \"set mdi device\" to select MDI device."));
+#endif
+
+retry:
+  printf_filtered (_("Select Device:\n"));
+  for (i = 0; i < n; i++)
+    {
+      /* Skip devices called "RESERVED".  */
+      if (strncasecmp (ddata[i].DName, "RESERVED", sizeof "RESERVED" - 1) == 0)
+	continue;
+      printf_filtered ("  %02d) %s\n", i + 1, ddata[i].DName);
+    }
+
+  reinitialize_more_filter ();
+  s = command_line_input ("Enter Number (or q to quit) > ", 0,
+			  "mdidevice-choice");
+
+  if (s == NULL)
+    error (_("Unexpected EOF."));
+
+  while (*s == ' ' || *s == '\t')
+    ++s;
+  if (*s == 'q')
+    deprecated_throw_reason (RETURN_QUIT);
+
+  value = strtoul (s, &s, 0);
+  if (value < 1 || value > n || *s)
+    goto retry;
+
+  return (value - 1);
+}
+
+static MDIInt32
+SelectTarget (MDITGDataT * tgdata, MDIInt32 n, int target)
+{
+  int i;
+  char *s;
+  unsigned long value;
+
+  if (target > n)
+    error (_("Bad target number %d, only %d targets available."), target, n);
+
+  if (target > 0 && target <= n)
+    return target - 1;
+
+  if (n == 1)
+    return 0;
+
+#ifdef GDBTK
+  /* Using command_line_input when GUI is active breaks the console window.  */
+  if (gdbtk_interp != NULL)
+    error (_("Use \"set mdi target\" to select MDI target group."));
+#endif
+
+retry:
+  printf_filtered (_("Select Target Group:\n"));
+  for (i = 0; i < n; i++)
+    {
+      /* Skip targets called "RESERVED" */
+      if (strncasecmp (tgdata[i].TGName, "RESERVED",
+		       sizeof "RESERVED" - 1) == 0)
+	continue;
+      printf_filtered ("  %02d) %s\n", i + 1, tgdata[i].TGName);
+    }
+
+  reinitialize_more_filter ();
+  s = command_line_input (_("Enter Number (or q to quit) > "), 0,
+			  "mditarget-choice");
+  if (s == NULL)
+    error (_("Unexpected EOF."));
+
+  while (*s == ' ' || *s == '\t')
+    ++s;
+  if (*s == 'q')
+    deprecated_throw_reason (RETURN_QUIT);
+
+  value = strtoul (s, &s, 0);
+  if (value < 1 || value > n || *s)
+    goto retry;
+
+  return (value - 1);
+}
+
+static void (*mdi_signal (int sig, void (*handler) (int))) (int)
+{
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+  struct sigaction sa, osa;
+
+  sa.sa_handler = handler;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  sigaction (sig, &sa, &osa);
+  return osa.sa_handler;
+#else
+  return signal (sig, handler);
+#endif
+}
+
+static RETSIGTYPE (*ofunc) ();
+static RETSIGTYPE mdi_interrupt (int signo);
+static void (*interrupt_cleanup)(void);
+
+static void
+open_cleanup (void)
+{
+}
+
+static void
+haltDev (struct mdi_state *mdi)
+{
+  MDIInt32 mdistat;
+  MDIRunStateT runstate;
+  struct timeval now, when;
+  int timedout, interrupted, forever;
+  int stopcount;
+  int i;
+
+  /* Wait the specified number of seconds for CPU to halt.  */
+  gettimeofday (&now, NULL);
+  when = now;
+  when.tv_sec += mdi_connecttimeout;
+  forever = (mdi_connecttimeout == UINT_MAX);
+  timedout = interrupted = 0;
+
+  /* Install our SIGINT signal handler.  */
+  interrupt_cleanup = open_cleanup;
+  ofunc = mdi_signal (SIGINT, mdi_interrupt);
+
+  stopcount = 0;
+  i = 0;
+
+  do
+    {
+      mdistat = mdiRunState (mdi->gmdata[i].DevHandle, 100, &runstate);
+      if (mdistat != MDISuccess)
+	break;
+
+      if ((runstate.Status & MDIStatusMask) == MDIStatusRunning
+	  || runstate.Status == MDIStatusDisabled
+	  || runstate.Status == MDIStatusVPEDisabled)
+	{
+	  mdistat = mdiStop (mdi->gmdata[i].DevHandle);
+	  if (mdistat != MDISuccess)
+	    break;
+
+	  mdistat = mdiRunState (mdi->gmdata[i].DevHandle, 100, &runstate);
+	  if (mdistat != MDISuccess)
+	    break;
+	}
+
+      if (runstate.Status == MDIStatusDisabled
+	  || runstate.Status == MDIStatusVPEDisabled)
+	{
+	  mdi->gmdata[i].disabled = 1;
+	  if (mdi->gmcount == 1)
+	    forever = 1;
+	}
+      else if ((runstate.Status & MDIStatusMask) == MDIStatusRunning)
+	forever = (mdi_connecttimeout == UINT_MAX);
+      else
+	{
+	  mdi->gmdata[i].disabled = 0;
+	  stopcount++;
+	  if (stopcount == 1)
+	    mdi->gmindex = i;
+	  if (stopcount == mdi->gmcount)
+	    break;
+	}
+
+      i = (i + 1) % mdi->gmcount;
+
+      /* Only time out after a full poll of all devices.  */
+      if (i == 0 && (!forever || stopcount > 0))
+	{
+	  gettimeofday (&now, NULL);
+	  if (timercmp (&now, &when, >))
+	    {
+	      timedout = 1;
+	      break;
+	    }
+	}
+      /* See if the user has asked us to stop.  */
+      if (quit_flag
+	  || (deprecated_ui_loop_hook && deprecated_ui_loop_hook (0)))
+	{
+	  interrupted = 1;
+	  break;
+	}
+      sleep_ms (100);
+    }
+  while (1);
+
+  /* Restore old SIGINT handler.  */
+  signal (SIGINT, ofunc);
+
+  if (timedout && stopcount == 0)
+    error (_("Cannot halt CPU"));
+  else if (interrupted)
+    error (_("Interrupted while waiting for the device"));
+  else
+    MDIERR (mdistat, _("halting CPU"));
+}
+
+static void
+resetDev (struct mdi_state *mdi, int connreset)
+{
+  MDIInt32 mdistat;
+  MDIRunStateT runstate;
+  struct timeval now, when;
+
+  if (connreset >= 0)
+    {
+      /* Reset the device, wait "connectreset" seconds, then stop it.  */
+      mdistat = mdiReset (mdi->gmdata[0].DevHandle, MDIFullReset);
+      if (mdistat == MDISuccess && connreset > 0  && ! mdi->mipssim_p)
+	{
+	  /* Start CPU execution.  */
+	  if (mdi->gmcount > 1)
+	    {
+	      mdistat = mdiTeamExecute (mdi->MDIHandle, mdi->gid);
+	      if (mdistat == MDIErrUnsupported)
+		{
+		  int i;
+
+		  for (i = 0; i < mdi->gmcount; i++)
+		    {
+		      mdistat = mdiExecute (mdi->gmdata[i].DevHandle);
+		      if (mdistat != MDIErrDisabled)
+			MDIWARN (mdistat, _("starting execution"));
+		    }
+		  mdistat = MDISuccess;
+		}
+	    }
+	  else
+	    mdistat = mdiExecute (mdi->gmdata[0].DevHandle);
+	  if (mdistat == MDISuccess)
+	    {
+	      /* Keep polling MDI until "connectreset" seconds elapsed.  */
+	      gettimeofday (&now, NULL);
+	      when = now;
+	      when.tv_sec += connreset;
+	      do
+		{
+		  /* Poll MDI - may be necessary for some probes.  */
+		  (void) mdiRunState (mdi->gmdata[0].DevHandle,
+				      200, &runstate);
+		  sleep_ms (200);
+		  gettimeofday (&now, NULL);
+		}
+	      while (timercmp (&now, &when, <));
+	      /* Halt CPU.  */
+	      (void) mdiStop (mdi->gmdata[0].DevHandle);
+	    }
+	}
+    }
+}
+
+static MDIInt32
+getDevs (MDIHandleT tg, int index, MDIDDataT **ddata, MDIInt32 *devices)
+{
+  MDIInt32 mdistat;
+
+  *ddata = NULL;
+  *devices = 0;
+
+  mdistat = mdiDQuery (tg, devices, NULL);
+  if (mdistat != MDISuccess)
+    return mdistat;
+
+  *ddata = (MDIDDataT *) xmalloc (*devices * sizeof (MDIDDataT));
+  mdistat = mdiDQuery (tg, devices, *ddata);
+
+  return mdistat;
+}
+
+static void
+updateDev (struct mdi_state *mdi, int index, MDIDeviceIdT device)
+{
+  struct cleanup *cleanups;
+  MDIDDataT *ddata = NULL;
+  MDIInt32 devices, i;
+  MDIInt32 mdistat;
+
+  mdistat = getDevs (mdi->gmdata[index].TGHandle, index, &ddata, &devices);
+  cleanups = make_cleanup (xfree, ddata);
+  MDIERR (mdistat, _("device query"));
+
+  for (i = 0; i < devices; i++)
+    if (ddata[i].Id == device)
+      memmove (&mdi->gmdata[index].DeviceData, ddata + i, sizeof (MDIDDataT));
+
+  do_cleanups (cleanups);
+}
+
+static void
+openDev (struct mdi_state *mdi, int index, char *configfile)
+{
+  struct cleanup *cleanups;
+  MDIDDataT *ddata = NULL;
+  MDIDDataT *dp;
+  MDIInt32 devices;
+  MDIDeviceIdT device;
+  MDIInt32 mdistat;
+
+  mdi->gmdata[index].disabled = 1;
+
+  device = mdi->gmdata[index].tmdata.DevId + 1;
+
+  mdistat = getDevs (mdi->gmdata[index].TGHandle, index, &ddata, &devices);
+  cleanups = make_cleanup (xfree, ddata);
+  MDIERR (mdistat, _("device query"));
+
+  if (devices == 0)
+    error (_("No MDI devices available"));
+
+  device = SelectDevice (ddata, devices, device);
+  dp = &ddata[device];
+
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp, "\
+selected dname '%s' fpart '%s' vendor '%s' vfamily '%s' vpart '%s' \
+vpartrev '%s' vpartdata '%s'\n",
+			dp->DName, dp->FPart, dp->Vendor, dp->VFamily,
+			dp->VPart, dp->VPartRev, dp->VPartData);
+
+  mdi->mipssim_p = (strcmp (dp->VPartData, "MIPSsim") == 0);
+  if (mdi->mipssim_p && index == 0)
+    mdi_setconfigfile (mdi, dp, configfile);
+
+  /* Old versions used to force mdi_continueonclose to "0" for
+     MIPSsim.  Not anymore, but keep this value as the default.  */
+  if (mdi_continueonclose == -1)
+    {
+      if (mdi->mipssim_p)
+	mdi_continueonclose = 0;
+      else
+	mdi_continueonclose = 1;
+    }
+
+  mdistat = mdiOpen (mdi->gmdata[index].TGHandle, dp->Id, MDIExclusiveAccess,
+		     &mdi->gmdata[index].DevHandle);
+  MDIERR (mdistat, _("device open"));
+
+  if (dp->VPartData[0] && strcmp (dp->VPartData, "Unknown") != 0)
+    printf_filtered (_("Selected device %s on %s %s\n"), dp->DName,
+		     dp->Vendor, dp->VPartData);
+  else
+    printf_filtered (_("Selected device %s\n"), dp->DName);
+
+  updateDev (mdi, index, dp->Id);
+
+  do_cleanups (cleanups);
+}
+
+
+static void
+openTG (struct mdi_state *mdi, int index)
+{
+  struct cleanup *cleanups;
+  MDIInt32 mdistat = MDISuccess;
+  MDITGDataT *tgdata = NULL;
+  MDIInt32 targets;
+  MDITGIdT target;
+
+  if ((mdi->Config.MDICapability & MDICAP_TargetGroups) == 0)
+    {
+      mdi->gmdata[index].TGHandle = mdi->gmdata[index].tmdata.MDIHandle;
+      return;
+    }
+
+  target = mdi->gmdata[index].tmdata.TGId + 1;
+  targets = 0;
+  mdistat = mdiTGQuery (mdi->gmdata[index].tmdata.MDIHandle, &targets, NULL);
+  MDIERR (mdistat, _("target group query"));
+
+  tgdata = (MDITGDataT *) xmalloc (targets * sizeof (MDITGDataT));
+  cleanups = make_cleanup (xfree, tgdata);
+
+  mdistat = mdiTGQuery (mdi->gmdata[index].tmdata.MDIHandle, &targets, tgdata);
+  MDIERR (mdistat, _("target group query"));
+
+  target = SelectTarget (tgdata, targets, target);
+
+  mdistat = mdiTGOpen (mdi->gmdata[index].tmdata.MDIHandle,
+		       tgdata[target].TGId, MDISharedAccess,
+		       &mdi->gmdata[index].TGHandle);
+  if (mdistat != MDISuccess)
+    /* Failed shared access - try exclusive access.  */
+    mdistat = mdiTGOpen (mdi->gmdata[index].tmdata.MDIHandle,
+			 tgdata[target].TGId, MDIExclusiveAccess,
+			 &mdi->gmdata[index].TGHandle);
+  MDIERR (mdistat, _("target group open"));
+
+  if (remote_debug)
+    printf_filtered (_("Selected target group %s\n"), tgdata[target].TGName);
+  mdi->gmdata[index].tmdata.TGId = tgdata[target].TGId;
+
+  do_cleanups (cleanups);
+}
+
+static int __stdcall
+mdiDbgOutput (MDIHandleT handle, MDIInt32 Type, char *Buffer, MDIInt32 Count)
+{
+  if (remote_debug > 1)
+    {
+      fprintf_unfiltered (mdi_logfp, "MDICBOutput (0x%x, %s, -, %d) called\n",
+			  handle, lookupName (cbtype_Names, Type), Count);
+      fprintf_unfiltered (mdi_logfp, "data:");
+      dump_mem (Buffer, 0, Count);
+    }
+
+  if (Type == MDIIOTypeMDIErr || Type == MDIIOTypeTgtErr)
+    {
+      ui_file_write (gdb_stdtargerr, Buffer, Count);
+      gdb_flush (gdb_stdtargerr);
+    }
+  else if (! mdi_quiet)
+    {
+      ui_file_write (gdb_stdtarg, Buffer, Count);
+      gdb_flush (gdb_stdtarg);
+    }
+  return MDISuccess;
+}
+
+
+static int __stdcall
+mdiDbgInput (MDIHandleT handle, MDIInt32 Type, MDIInt32 Mode,
+	     char **Buffer, MDIInt32 * Count)
+{
+  static char *lastline = NULL;
+  char *line;
+  extern FILE *instream;
+
+  if (deprecated_readline_begin_hook)
+    (*deprecated_readline_begin_hook) ("\nMDI library has requested input:\n");
+  else if (input_from_terminal_p ())
+    printf_filtered (_("\nMDI library has requested input:\n"));
+
+  /* Make sure that all output has been output.  Some machines may let
+     you get away with leaving out some of the gdb_flush, but not all.  */
+  wrap_here ("");
+  gdb_flush (gdb_stdout);
+  gdb_flush (gdb_stderr);
+
+  if (deprecated_readline_hook)
+    line = (*deprecated_readline_hook) ("MDILIB> ");
+  else if (input_from_terminal_p ())
+    {
+      line = gdb_readline_wrapper ("MDILIB> ");
+      if (line && *line)		/* Add to command history.  */
+	add_history (line);
+    }
+  else
+    line = gdb_readline (0);
+
+  if (deprecated_readline_end_hook)
+    (*deprecated_readline_end_hook) ();
+
+  /* Avoid consuming too much memory.  */
+  if (lastline)
+    {
+      free (lastline);
+      lastline = line;
+    }
+
+  *Buffer = line;
+  *Count = strlen (line);
+  return MDISuccess;
+}
+
+
+
+static void
+mdi_dlopen (char *lib, struct mdi_state *mdi, int from_tty)
+{
+  MDIInt32 mdistat;
+  MDIVersionRangeT vrange;
+  MDIVersionT api;
+
+  /* MDIInit must be called to load the shared library.  */
+  if (!mdiModule)
+    {
+      mdistat = MDIInit (lib, &mdiModule);
+      if (mdistat == MDIErrLoadLib)
+	{
+	  if (lib)
+	    error (_("Cannot load MDI library: \"%s\"."), lib);
+	  if (from_tty)
+	    error (_("\
+Unknown MDI library.\n\
+Please specify the library on the \"target\" command line or\n\
+by setting the 'mdi library' variable, or the $GDBMDILIB\n\
+environment variable."));
+	  error (_("\
+Unknown MDI library.\n\
+Please set the 'mdi library' variable,\n\
+or the $GDBMDILIB environment variable."));
+	}
+      MDIERR (mdistat, _("MDI initialisation"));
+    }
+
+  /* Get API version range supported by library.  */
+  mdistat = mdiVersion (&vrange);
+  MDIERR (mdistat, _("MDI get versions"));
+
+  /* Use the highest API compatible with library.  */
+  api = ((vrange.newest < MDICurrentRevision)
+	 ? vrange.newest : MDICurrentRevision);
+
+  /* Make sure it's not too old.  */
+  if (api < vrange.oldest || api < MDIOldestRevision)
+    {
+      if (remote_debug)
+	{
+	  fprintf_unfiltered (mdi_logfp,
+			      "MDI library API: oldest=%d.%d newest=%d.%d\n",
+			      vrange.oldest >> 16, vrange.oldest & 0xffff,
+			      vrange.newest >> 16, vrange.newest & 0xffff);
+	  fprintf_unfiltered (mdi_logfp,
+			      "Our API: oldest=%d.%d current=%d.%d\n",
+			      MDIOldMajor, MDIOldMinor, MDIMajor, MDIMinor);
+	}
+      error (_("MDI library API version mismatch"));
+    }
+
+  sprintf (mdi->Config.User, "GNU gdb %.*s",
+	   (int) sizeof (mdi->Config.User - sizeof "GNU gdb "), version);
+  mdi->Config.MDICBOutput = mdiDbgOutput;
+  mdi->Config.MDICBInput = mdiDbgInput;
+  mdi->Config.MDICBPeriodic = mdiPeriodic;
+
+  mdistat = mdiConnect (api, &mdi->MDIHandle, &mdi->Config);
+  MDIERR (mdistat, _("MDI connect"));
+
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp,
+			"connected to library '%s', implementer '%s'\n",
+			lib ? lib : "<default>", mdi->Config.Implementer);
+
+  if (mdi_implementer)
+    xfree (mdi_implementer);
+  mdi_implementer = xstrdup (mdi->Config.Implementer);
+}
+
+
+
+#define CFG_M		0x80000000	/* next Config implemented */
+
+/* MIPS32 Config0 register */
+#define CFG0_MTMASK	0x00000380
+#define  CFG0_MT_TLB	 (1<<7)
+
+/* MIPS32 Config1 register */
+#define CFG1_MMUSMASK	0x7e000000	/* mmu size - 1 */
+#define CFG1_MMUSSHIFT	25
+#define CFG1_ISMASK	0x01c00000	/* icache lines 64<<n */
+#define CFG1_ISSHIFT	22
+#define CFG1_ILMASK	0x00380000	/* icache line size 2<<n */
+#define CFG1_ILSHIFT	19
+#define CFG1_IAMASK	0x00070000	/* icache ways - 1 */
+#define CFG1_IASHIFT	16
+#define CFG1_DSMASK	0x0000e000	/* dcache lines 64<<n */
+#define CFG1_DSSHIFT	13
+#define CFG1_DLMASK	0x00001c00	/* dcache line size 2<<n */
+#define CFG1_DLSHIFT	10
+#define CFG1_DAMASK	0x00000380	/* dcache ways - 1 */
+#define CFG1_DASHIFT	7
+
+/* MIPS32 Config2 register */
+#define CFG2_TUMASK	0x70000000	/* tertiary cache control */
+#define CFG2_TUSHIFT	28
+#define CFG2_TSMASK	0x0f000000	/* tcache sets per wway 64<<n */
+#define CFG2_TSSHIFT	24
+#define CFG2_TLMASK	0x00f00000	/* tcache line size 2<<n */
+#define CFG2_TLSHIFT	20
+#define CFG2_TAMASK	0x000f0000	/* tcache ways - 1 */
+#define CFG2_TASHIFT	16
+#define CFG2_SUMASK	0x0000f000	/* secondary cache control */
+#define CFG2_SUSHIFT	12
+#define CFG2_SSMASK	0x00000f00	/* scache sets per wway 64<<n */
+#define CFG2_SSSHIFT	8
+#define CFG2_SLMASK	0x000000f0	/* scache line size 2<<n */
+#define CFG2_SLSHIFT	4
+#define CFG2_SAMASK	0x0000000f	/* scache ways - 1 */
+#define CFG2_SASHIFT	0
+
+static void
+mdi_probe_cpu (struct mdi_state *mdi, int index)
+{
+  enum mdiTlb tlb;
+  int regsize;
+  unsigned long cfg0 = 0, cfg1 = 0, cfg2 = 0;
+  MDIInt32 mdistat;
+  char data[4];
+  int isa;
+
+  isa = isa2int (mdi->gmdata[index].DeviceData.FISA);
+  if (isa <= 2)
+    {
+      regsize = 4;
+      tlb = R3000_TLB;
+    }
+  else if (isa == 32 || isa == 64)
+    {
+      if (isa == 32)
+	{
+	  regsize = 4;
+	  tlb = R4000_32TLB;
+	}
+      else
+	{
+	  regsize = 8;
+	  tlb = R4000_64TLB;
+	}
+      mdi->gmdata[index].ntlb = -1;
+
+      /* Determine TLB size from Config0 and Config1 registers.  */
+
+      /* MIPS32 Config0 Register (CP0 Register 16, Select 0).  */
+      mdistat = mdi_read (mdi->gmdata[index].DevHandle,
+			  MDIMIPCP0, 16, data, 4, 1);
+      cfg0 = (unsigned long) extract_signed_integer (data, 4);
+      if (cfg0 & CFG_M)
+	{
+	  /* MIPS32 Config1 Register (CP0 Register 16, Select 1).  */
+	  mdistat =
+	    mdi_read (mdi->gmdata[index].DevHandle,
+		      MDIMIPCP0, 16 | (1 << 5), data, 4, 1);
+	  if (mdistat == MDISuccess)
+	    cfg1 = (unsigned long) extract_signed_integer (data, 4);
+	}
+
+      if (mdistat == MDISuccess && (cfg0 & CFG0_MTMASK) == CFG0_MT_TLB
+	  && cfg1 != 0)
+	mdi->gmdata[index].ntlb = ((cfg1 & CFG1_MMUSMASK) >> CFG1_MMUSSHIFT)
+				  + 1;
+    }
+  else
+    {
+      regsize = 8;
+      tlb = R4000_64TLB;
+    }
+
+  if (mdi->gmdata[index].ntlb <= 0)
+    tlb = NO_TLB;
+
+  if (index != 0)
+    {
+      if (regsize != mdi->regsize)
+	error (_("\
+Cannot support multiple devices of different register size."));
+      if (tlb != mdi->tlb)
+	error (_("Cannot support multiple devices of different TLB type."));
+    }
+
+  mdi->regsize = regsize;
+  mdi->tlb = tlb;
+
+  if (mdi->gmdata[index].ntlb == 0)
+    {
+      /* Do a binary search to find the number of TLB entries.  */
+      int min = 0, max = 256;
+      int half;
+      MDIInt32 mdistat;
+
+      while (max - min > 1)
+	{
+	  half = (max - min + 1) >> 1;
+	  switch (mdi->tlb)
+	    {
+	    case R3000_TLB:
+	      {
+		MDIUint32 data[2];
+		mdistat = mdi_read (mdi->gmdata[index].DevHandle,
+				    MDIMIPTLB, (min + half) * 2, data, 4, 2);
+	      }
+	      break;
+	    case R4000_32TLB:
+	      {
+		MDIUint32 data[4];
+		mdistat = mdi_read (mdi->gmdata[index].DevHandle,
+				    MDIMIPTLB, (min + half) * 4, data, 4, 4);
+	      }
+	      break;
+	    case R4000_64TLB:
+	      {
+		MDIUint64 data[4];
+		mdistat = mdi_read (mdi->gmdata[index].DevHandle,
+				    MDIMIPTLB, (min + half) * 4, data, 8, 4);
+	      }
+	      break;
+	    default:
+	      mdistat = MDIErrNoResource;
+	      break;
+	    }
+	  if (mdistat == MDISuccess)
+	    min += half;
+	  else
+	    max = min + half;
+	}
+
+      mdi->gmdata[index].ntlb = max;
+    }
+
+  /* Probe cache layout.  */
+  if (isa == 32 || isa == 64)
+    {
+      MDICacheInfoT *cache = mdi->gmdata[index].CacheInfo;
+
+      if (cfg1 & CFG_M)
+	{
+	  /* MIPS32 Config1 Register (CP0 Register 16, Select 2).  */
+	  mdistat = mdi_read (mdi->gmdata[index].DevHandle,
+			      MDIMIPCP0, 16 | (2 << 5), data, 4, 1);
+	  if (mdistat == MDISuccess)
+	    cfg2 = (unsigned long) extract_signed_integer (data, 4);
+	}
+
+      if (cfg1 & CFG1_ILMASK)
+	{
+	  /* I-cache */
+	  cache[0].Type = MDICacheTypeInstruction;
+	  cache[0].LineSize = 2 << ((cfg1 & CFG1_ILMASK) >> CFG1_ILSHIFT);
+	  cache[0].LinesPerSet = 64 << ((cfg1 & CFG1_ISMASK) >> CFG1_ISSHIFT);
+	  cache[0].Sets = 1 + ((cfg1 & CFG1_IAMASK) >> CFG1_IASHIFT);
+	}
+      if (cfg1 & CFG1_DLMASK)
+	{
+	  /* D-cache */
+	  cache[1].Type = MDICacheTypeData;
+	  cache[1].LineSize = 2 << ((cfg1 & CFG1_DLMASK) >> CFG1_DLSHIFT);
+	  cache[1].LinesPerSet = 64 << ((cfg1 & CFG1_DSMASK) >> CFG1_DSSHIFT);
+	  cache[1].Sets = 1 + ((cfg1 & CFG1_DAMASK) >> CFG1_DASHIFT);
+	}
+      if (cfg2 & CFG2_SLMASK)
+	{
+	  /* S-cache */
+	  cache[2].Type = MDICacheTypeUnified;
+	  cache[2].LineSize = 2 << ((cfg2 & CFG2_SLMASK) >> CFG2_SLSHIFT);
+	  cache[2].LinesPerSet = 64 << ((cfg2 & CFG2_SSMASK) >> CFG2_SSSHIFT);
+	  cache[2].Sets = 1 + ((cfg2 & CFG2_SAMASK) >> CFG2_SASHIFT);
+	}
+      if (cfg2 & CFG2_TLMASK)
+	{
+	  /* T-cache */
+	  cache[3].Type = MDICacheTypeUnified;
+	  cache[3].LineSize = 2 << ((cfg2 & CFG2_TLMASK) >> CFG2_TLSHIFT);
+	  cache[3].LinesPerSet = 64 << ((cfg2 & CFG2_TSMASK) >> CFG2_TSSHIFT);
+	  cache[3].Sets = 1 + ((cfg2 & CFG2_TAMASK) >> CFG2_TASHIFT);
+	}
+    }
+  else
+    {
+      /* Ask MDI, but quietly ignore any error.  */
+      (void) mdiCacheQuery (mdi->gmdata[index].DevHandle,
+			    &mdi->gmdata[index].CacheInfo[0]);
+    }
+}
+
+
+
+static void
+mdi_cleanup (void *arg)
+{
+  struct mdi_state *mdi = arg;
+
+  if (mdi_desc)
+    {
+      mdi_desc = NULL;		/* So mdi_close will do nothing.  */
+      unpush_target (&mdi_ops);
+    }
+  if (mdi->cfgfile)
+    {
+      if (remote_debug == 0)
+	unlink (mdi->cfgfile);
+      xfree (mdi->cfgfile);
+    }
+  if (mdi->MDIHandle != MDINoHandle)
+    mdiDisconnect (mdi->MDIHandle, MDICurrentState);
+  xfree (mdi);
+
+  if (mdi_logging)
+    {
+      ui_file_delete (mdi_logfp);
+      mdi_logfp = gdb_stdlog;
+      mdi_logging = 0;
+    }
+}
+
+
+static int
+mdi_first_ptid (struct thread_info *tp, void *data)
+{
+  return 1;
+}
+
+static void
+mdi_set_inferior_ptid (void)
+{
+  MDIInt32 mdistat, TCId;
+  struct thread_info *tp;
+
+  inferior_ptid = mdi_ptid;
+  mdi_find_new_threads ();
+  mdistat = mdiGetTC (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle, &TCId);
+  if (mdistat != MDISuccess)
+    {
+      if (mdistat != MDIErrUnsupported)
+	MDIWARN (mdistat, _("getting current thread"));
+    }
+  else
+    {
+      inferior_ptid =
+	ptid_build (GET_PID (inferior_ptid),
+		    mdi_desc->gmdata[mdi_desc->gmindex].DevHandle, TCId);
+      if (!in_thread_list (inferior_ptid))
+	{
+	  tp = iterate_over_threads (mdi_first_ptid, NULL);
+	  if (tp)
+	    {
+	      inferior_ptid = tp->ptid;
+	      mdi_switch_to_thread ();
+	    }
+	}
+    }
+  last_ptid = inferior_ptid;
+}
+
+/* The open routine takes the rest of the parameters from the command,
+   and (if successful) pushes a new target onto the stack.  Targets
+   should supply this routine, if only to provide an error message.
+   Called when selecting the simulator.  EG: (gdb) target mdi name.  */
+
+static void
+mdi_open (char *args, int from_tty)
+{
+  struct mdi_tm_data_list *tmdatalist = NULL, **listp = &tmdatalist;
+  int group_mode = 0, team_mode = 0;
+  struct cleanup *cleanups;
+  int len;
+  char *arg_buf;
+  char **argv;
+  MDIInt32 mdistat;
+  struct mdi_state *mdi;
+  char *lib = 0;
+  char *configfile = 0;
+  unsigned long device, target;
+  int byte_order;
+  int connreset;
+  int i, j;
+
+  if (remote_debug && mdi_logfile)
+    {
+      mdi_logfp = gdb_fopen (mdi_logfile, "w");
+      if (mdi_logfp == NULL)
+	perror_with_name (mdi_logfile);
+      else
+	mdi_logging = 1;
+    }
+
+  if (mdi_logfp == NULL)
+    mdi_logfp = gdb_stdlog;
+
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp, "mdi_open: args \"%s\"\n",
+			args ? args : "(null)");
+
+  device = mdi_device;
+  target = mdi_target;
+  connreset = mdi_connectreset;
+
+  if (args)
+    {
+      int seendev = 0;
+      char *argscopy, *p;
+
+      argscopy = alloca (strlen (args) + 1);
+      strcpy (argscopy, args);
+      for (p = strtok (argscopy, " \t,{}"); p; p = strtok (NULL, " \t,{}"))
+	{
+	  if (isdigit (*p))
+	    {
+	      if (seendev)
+		error (_("Multiple MDI device numbers specified."));
+	      device = strtoul (p, &p, 0);
+	      if (*p == ':' && isdigit (p[1]))
+		{
+		  target = device;
+		  device = strtoul (p + 1, &p, 0);
+		}
+	      if (*p)
+		error (_("Bad [TARGET:]DEVICE number."));
+	      seendev = 1;
+	    }
+	  else if (strncmp (p, "cfg=", sizeof "cfg=" - 1) == 0)
+	    {
+	      if (configfile)
+		error (_("Multiple MIPSsim config files specified."));
+	      p += sizeof "cfg=" - 1;
+	      if (*p)
+		configfile = p;
+	    }
+	  else if (strncmp (p, "group=", sizeof "group=" - 1) == 0)
+	    {
+	      unsigned long tm_device, tm_target;
+
+	      if (team_mode)
+		error (_("Cannot mix group= and team= options."));
+
+	      group_mode = 1;
+	      p += sizeof "group=" - 1;
+	      if (isdigit (*p))
+		{
+		  tm_target = mdi_target;
+		  tm_device = strtoul (p, &p, 0);
+		  if (*p == ':' && isdigit (p[1]))
+		    {
+		      tm_target = tm_device;
+		      tm_device = strtoul (p + 1, &p, 0);
+		    }
+		  if (*p)
+		    error (_("Bad [TARGET:]DEVICE number."));
+
+		  *listp = alloca (sizeof (**listp));
+		  (*listp)->next = NULL;
+		  (*listp)->tmdata.TGId = tm_target - 1;
+		  (*listp)->tmdata.DevId = tm_device - 1;
+		  listp = &(*listp)->next;
+		}
+	      else
+		error (_("Bad group= option."));
+	    }
+	  else if (strncmp (p, "rst=", sizeof "rst=" - 1) == 0)
+	    {
+	      p += sizeof "rst=" - 1;
+	      if (strcasecmp (p, "off") == 0)
+		connreset = -1;
+	      else if (strcasecmp (p, "on") == 0)
+		connreset = 0;
+	      else
+		{
+		  connreset = strtol (p, &p, 0);
+		  if (*p)
+		    error (_("Bad rst= option."));
+		}
+	    }
+	  else if (strncmp (p, "team=", sizeof "team=" - 1) == 0)
+	    {
+	      unsigned long tm_device, tm_target;
+
+	      if (group_mode)
+		error (_("Cannot mix team= and group= options."));
+
+	      team_mode = 1;
+	      p += sizeof "team=" - 1;
+	      if (isdigit (*p))
+		{
+		  tm_target = mdi_target;
+		  tm_device = strtoul (p, &p, 0);
+		  if (*p == ':' && isdigit (p[1]))
+		    {
+		      tm_target = tm_device;
+		      tm_device = strtoul (p + 1, &p, 0);
+		    }
+		  if (*p)
+		    error (_("Bad [TARGET:]DEVICE number."));
+
+		  *listp = alloca (sizeof (**listp));
+		  (*listp)->next = NULL;
+		  (*listp)->tmdata.TGId = tm_target - 1;
+		  (*listp)->tmdata.DevId = tm_device - 1;
+		  listp = &(*listp)->next;
+		}
+	      else
+		error (_("Bad team= option."));
+	    }
+	  else if (*p)
+	    {
+	      if (lib)
+		error (_("Multiple MDI libraries specified."));
+	      lib = p;
+	    }
+	}
+    }
+
+  if (!lib)
+    lib = mdi_library;
+
+  if (!configfile)
+    configfile = mdi_configfile;
+
+  /* Reread files if they've changed.  */
+  reopen_exec_file ();
+  reread_symbols ();
+
+  target_preopen (from_tty);
+
+  unpush_target (&mdi_ops);
+
+  mdi = (struct mdi_state *) xmalloc (sizeof (struct mdi_state));
+  memset (mdi, 0, sizeof (struct mdi_state));
+  mdi->MDIHandle = MDINoHandle;
+
+  /* Failed coprocessor register masks.  */
+  memset (mdi_cpdreg_miss, 0, sizeof (mdi_cpdreg_miss));
+  memset (mdi_cpcreg_miss, 0, sizeof (mdi_cpcreg_miss));
+  memset (mdi_cpdreg_wp, 0, sizeof (mdi_cpdreg_wp));
+  memset (mdi_cpcreg_wp, 0, sizeof (mdi_cpcreg_wp));
+  mdi_hilo_miss = 0;
+  mdi_dsp_miss = 0;
+
+  /* To avoid confusion, don't access the well known CP0 regs directly.  */
+  mdi_cpdreg_miss[0][0] |= ((1 << 12)		/* Status */
+			    | (1 << 8)		/* BadVaddr */
+			    | (1 << 13));	/* Cause */
+
+  /* Availability of MDIMIPFPR resource is unknown.  */
+  mdi_fpr_avail = -1;
+
+  /* Availability of MDIHwBpQuery call is unknown.  */
+  mdi_hwbpq_avail = -1;
+
+  cleanups = make_cleanup (mdi_cleanup, mdi);
+
+  /* Connect to MDI library.  */
+  mdi_dlopen (lib, mdi, from_tty);
+
+  /* Create a team if requested.  */
+  if (tmdatalist)
+    {
+      struct mdi_tm_data_list tmdatathis;
+
+      /* Add the device to be opened too.  */
+      tmdatathis.next = tmdatalist;
+      tmdatathis.tmdata.TGId = target - 1;
+      tmdatathis.tmdata.DevId = device - 1;
+      tmdatalist = &tmdatathis;
+
+      if (mdi_team <= 0 || group_mode)
+	{
+	  mdistat = mdiTeamCreate (mdi->MDIHandle, &mdi_team);
+	  if (mdistat != MDISuccess)
+	    {
+	      mdi_team = 0;
+	      if (group_mode && mdistat != MDIErrUnsupported)
+		mdi_team_status (mdistat);
+	      else
+		MDIWARN (mdistat, _("creating team"));
+	    }
+	  mdi_team += 1;
+	}
+
+      if (group_mode)
+	mdi->gid = mdi_team - 1;
+
+      for (listp = &tmdatalist; *listp; listp = &(*listp)->next)
+	{
+	  (*listp)->tmdata.MDIHandle = mdi->MDIHandle;
+	  mdistat = mdiTMAttach (mdi->MDIHandle, mdi_team - 1,
+				 &(*listp)->tmdata);
+
+	  if (group_mode && mdistat != MDIErrUnsupported)
+	    mdi_tm_status (mdistat, (*listp)->tmdata.TGId + 1,
+			   (*listp)->tmdata.DevId + 1);
+	  else
+	    MDIWARN (mdistat, _("adding team member"));
+	  if (group_mode || !mdi->gmcount)
+	    mdi->gmdata[mdi->gmcount++].tmdata = (*listp)->tmdata;
+	}
+    }
+  else
+    {
+      mdi->gmdata[mdi->gmcount].tmdata.MDIHandle = mdi->MDIHandle;
+      mdi->gmdata[mdi->gmcount].tmdata.TGId = target - 1;
+      mdi->gmdata[mdi->gmcount].tmdata.DevId = device - 1;
+      mdi->gmcount++;
+    }
+
+  for (i = 0; i < mdi->gmcount; i++)
+    {
+      /* Reuse the target group handle if possible.  */
+      mdi->gmdata[i].TGHandle = MDINoHandle;
+      for (j = 0; j < i; j++)
+	if (mdi->gmdata[i].tmdata.TGId == mdi->gmdata[j].tmdata.TGId)
+	  mdi->gmdata[i].TGHandle = mdi->gmdata[j].TGHandle;
+
+      /* Connect to target group.  */
+      if (mdi->gmdata[i].TGHandle == MDINoHandle)
+	openTG (mdi, i);
+
+      /* Connect to device in group.  */
+      openDev (mdi, i, configfile);
+    }
+
+  /* Reset the primary device.  */
+  resetDev (mdi, connreset);
+
+  /* Halt the devices.  */
+  haltDev (mdi);
+
+  for (i = 0; i < mdi->gmcount; i++)
+    if (mdi->gmdata[i].DeviceData.Endian != mdi->gmdata[0].DeviceData.Endian)
+      error (_("Cannot support multiple devices of mixed endianness."));
+
+  /* Set gdb byte order to match target.  */
+  byte_order = mdi->gmdata[0].DeviceData.Endian == MDIEndianBig
+    ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
+
+  if (gdbarch_byte_order (current_gdbarch) != byte_order)
+    {
+      const char *mdi_order = (byte_order == BFD_ENDIAN_BIG)
+	? _("big") : _("little");
+      const char *gdb_order = (gdbarch_byte_order (current_gdbarch)
+			       == BFD_ENDIAN_BIG)
+	? _("big") : _("little");
+      int ok;
+
+      if (selected_byte_order () == BFD_ENDIAN_UNKNOWN && ! exec_bfd)
+	{
+	  /* If there's no executable file, we might as well
+	     change gdb's endianness now to match the CPU.  */
+	  struct gdbarch_info info;
+	  gdbarch_info_init (&info);
+	  info.byte_order = byte_order;
+	  if (! gdbarch_update_p (info))
+	    internal_error (__FILE__, __LINE__,
+			    _("can't switch gdb to %s endian byte order"),
+			    mdi_order);
+
+#if XXX
+	  /* TBD  */
+	  /* Note that after we clear target_byte_order_auto, gdb
+	     won't change endianness automatically if we open a new
+	     exec-file with a different endianness - and there'll be
+	     no warning about that!!  */
+	  target_byte_order_auto = 0;
+#endif
+
+	  if (remote_debug)
+	    fprintf_unfiltered (mdi_logfp, "switching gdb to %s endian\n",
+				mdi_order);
+	}
+      else
+	{
+	  if (selected_byte_order () == BFD_ENDIAN_UNKNOWN)
+	    /* Endianness probably derived from file.  */
+	    ok = query (_("\
+The selected CPU is %s endian, but file \"%s\" is %s endian.\n\
+Do you want to connect anyway? "),
+			mdi_order, lbasename (get_exec_file (0)), gdb_order);
+	  else
+	    /* Endianness set explicitly with "set endian".  */
+	    ok = query (_("\
+The selected CPU is %s endian, but gdb is set to %s endian.\n\
+Do you want to connect anyway? "),
+			mdi_order, gdb_order);
+	  if (!ok)
+	    error (_("GDB/MDI endianness mismatch."));
+	}
+    }
+
+  /* Probe target CPU for other internal information.  */
+  for (i = 0; i < mdi->gmcount; i++)
+    if (!mdi->gmdata[i].disabled)
+      {
+	mdi_probe_cpu (mdi, i);
+	mdi->gmdata[i].probed = 1;
+      }
+
+  /* No access to DEPC, DESAVE or other debug mode registers,
+     except on MIPSsim, where they aren't used by the debug
+     monitor.  */
+  if (! mdi->mipssim_p)
+    for (i = 0; i < 7; i++)
+      mdi_cpdreg_miss[0][i] |= ((1 << 23) 	/* Debug, Trace, etc */
+				| (1 << 24) 	/* DEPC */
+				| (1 << 31)); 	/* DESAVE */
+
+#if 0
+  /* For now, write protect all the MT registers.  */
+  mdi_cpdreg_wp[0][1] |= ((1 << 0) 	/* MVPControl */
+			  | (1 << 1)	/* VPEControl */
+			  | (1 << 4)	/* TCStatus */
+			  | (1 << 6)	/* SRSConf0 */
+			  | (1 << 15));	/* EBase */
+
+  mdi_cpdreg_wp[0][2] |= ((1 << 0) 	/* MVPConf0 */
+			  | (1 << 1)	/* VPEConf0 */
+			  | (1 << 4)	/* TCPC */
+			  | (1 << 6)	/* SRSConf1 */
+			  | (1 << 12));	/* SRSCtl */
+
+  mdi_cpdreg_wp[0][3] |= ((1 << 0) 	/* MVPConf1 */
+			  | (1 << 1)	/* VPEConf1 */
+			  | (1 << 4)	/* TCHalt */
+			  | (1 << 6)	/* SRSConf2 */
+			  | (1 << 16));	/* Config3 */
+
+  mdi_cpdreg_wp[0][4] |= ((1 << 1)	/* YQMask */
+			  | (1 << 4)	/* TCContext */
+			  | (1 << 6));	/* SRSConf3 */
+
+  mdi_cpdreg_wp[0][5] |= ((1 << 1)	/* VPESchedule */
+			  | (1 << 4)	/* TCShedule */
+			  | (1 << 6));	/* SRSConf4 */
+
+  mdi_cpdreg_wp[0][6] |= ((1 << 1)	/* VPEScheFBack */
+			  | (1 << 4)	/* TCScheFBack */
+			  | (1 << 6));	/* SRSConf4 */
+#endif
+
+
+  /* No access to w/o 4KS family security registers.  */
+  for (i = 1; i < 7; i++)
+    mdi_cpdreg_miss[0][i] |= (1 << 22);
+
+  /* We're connected, record the mdi descriptor.  */
+  mdi_desc = mdi;
+  mdi_loaded = mdi_exited = mdi_signalled = 0;
+
+  push_target (&mdi_ops);
+
+  /* Without this, some commands which require an active target (such
+     as kill) won't work.  This variable serves (at least) double duty
+     as both the pid of the target process (if it has such), and as a
+     flag indicating that a target is active.  These functions should
+     be split out into seperate variables, especially since GDB will
+     someday have a notion of debugging several processes.  */
+  mdi_set_inferior_ptid ();
+
+  discard_cleanups (cleanups);
+
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp, "mdi_open(): connected\n");
+
+  /* Let the user know.  */
+  printf_filtered (_("Connected to MDI target\n"));
+
+#ifdef GDBTK
+  /* The way the insight GUI works, it really needs a prompt...  */
+  if (gdbtk_interp) {
+    if (*mdi_target_prompt == '\0') {
+      xfree (mdi_target_prompt);
+      mdi_target_prompt = xstrdup ("app>");
+    }
+  }
+#endif
+
+  /* Forget about any MDI breakpoints left over in our table.  */
+  mdi_reset_breakpoints ();
+
+#ifdef GDB_TARGET_START_REMOTE
+  GDB_TARGET_START_REMOTE ();
+#endif
+
+  mdi_starting = 1;
+
+  /* Initialise gdb internals.  */
+  start_remote (from_tty);
+
+  mdi_starting = 0;
+
+  /* So that "run" doesn't complain.  */
+  inferior_ptid = null_ptid;
+}
+
+
+
+static void
+do_freeargv (void *arg)
+{
+  freeargv ((char **) arg);
+}
+
+/* This is called not only when we first attach, but also when the
+   user types "run" after having attached.  */
+static void
+mdi_create_inferior (char *execfile, char *args, char **env, int from_tty)
+{
+  struct cleanup *cleanups;
+  char *prog;
+  char *arg_buf;
+  char **argv = NULL;
+  CORE_ADDR entry_point;
+  ULONGEST status;
+  int len;
+
+  if (execfile == 0 || exec_bfd == 0)
+    error (_("No executable file specified."));
+
+  if (mdi_argv)
+    {
+      freeargv (mdi_argv);
+      mdi_argv = NULL;
+    }
+
+  prog = execfile[0] ? execfile : "''";
+  len = strlen (prog) + strlen (args) + 2;
+  arg_buf = (char *) alloca (len);
+  strcpy (arg_buf, prog);
+  if (args)
+    {
+      strcat (arg_buf, " ");
+      strcat (arg_buf, args);
+    }
+
+  argv = buildargv (arg_buf);
+  if (argv == NULL)
+    nomem (0);
+
+  cleanups = make_cleanup (do_freeargv, argv);
+
+  if (mdi_entrypoint != 0)
+    entry_point = mdi_entrypoint;
+  else
+    entry_point = (int) bfd_get_start_address (exec_bfd);
+
+  if (mdi_rununcached)
+    {
+      /* Force to uncached address.  */
+#ifdef BFD64
+      if (entry_point >= 0xffffffff80000000LL
+	  && entry_point < 0xffffffffa0000000LL)
+	entry_point |= 0x20000000;
+#else
+      if (entry_point >= 0x80000000 && entry_point < 0xa0000000)
+	entry_point |= 0x20000000;
+#endif
+    }
+
+  if (!mdi_loaded)
+    {
+      if (query (_("\
+You haven't downloaded the executable to the MDI target.\n\
+Do you want to start executing at 0x%s anyway? "),
+		 paddr_nz (entry_point)))
+	mdi_loaded = 1;
+      else
+	error (_("No program loaded."));
+    }
+
+
+  /* Initialise host file i/o descriptors.  */
+  mdi_fdinit ();
+
+  /* Rip out the breakpoints; we'll reinsert them after restarting.  */
+  remove_breakpoints ();
+
+  mdi_set_inferior_ptid ();
+  mdi_exited = mdi_signalled = 0;
+
+  /* Now put the breakpoints back in.  This way we're safe if the
+     restart function reloads the image.  */
+  insert_breakpoints ();
+
+  /* Clean up from the last time we were running.  */
+  clear_proceed_status ();
+
+  /* Set argument registers and stack pointer to zero,
+     as used by some startup code.
+     XXX Should we clear all registers for consistency?  */
+  regcache_cooked_write_unsigned (get_current_regcache (),
+				  MIPS_A0_REGNUM + 0, 0);	/* $a0 */
+  regcache_cooked_write_unsigned (get_current_regcache (),
+				  MIPS_A0_REGNUM + 1, 0);	/* $a1 */
+  regcache_cooked_write_unsigned (get_current_regcache (),
+				  MIPS_A0_REGNUM + 2, 0);	/* $a2 */
+  regcache_cooked_write_unsigned (get_current_regcache (),
+				  MIPS_A0_REGNUM + 3, 0);	/* $a3 */
+  regcache_cooked_write_unsigned (get_current_regcache (),
+				  MIPS_SP_REGNUM, 0);		/* $sp */
+
+  /* Ensure interrupts are disabled.  */
+  regcache_cooked_read_unsigned (get_current_regcache (),
+				 MIPS_FIRST_EMBED_REGNUM + 12, &status);
+  regcache_cooked_write_unsigned (get_current_regcache (),
+				  MIPS_FIRST_EMBED_REGNUM + 12, status & ~1);
+
+  /* Set the entry point.  */
+  mdi_writepc (entry_point);
+
+  discard_cleanups (cleanups);
+  mdi_argv = argv;
+}
+
+
+
+static void
+mdi_close (int quitting)
+{
+  MDIInt32 mdistat;
+  MDIUint32 flags;
+  struct mdi_state *mdi;
+  int i;
+
+  if ((mdi = mdi_desc) == NULL)
+    return;
+
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp, "mdi_close: quitting %d\n", quitting);
+
+  inferior_ptid = null_ptid;
+
+  /* Clean up target file i/o.  */
+  mdi_fdcloseall ();
+
+  /* Clear our hidden syscall breakpoints.  */
+  mdi_remove_syscallbreakpoint ();
+
+  /* Output any pending profile data.  */
+  mdi_profiling_close (1);
+
+  /* Release target program argument vector.  */
+  if (mdi_argv)
+    {
+      freeargv (mdi_argv);
+      mdi_argv = NULL;
+    }
+
+  flags = MDICurrentState;
+
+#if 0
+  if (mdi->mipssim_p)
+    {
+      flags = MDIResetState;
+    }
+#endif
+
+  if (mdi_continueonclose)
+    for (i = 0; i < mdi_desc->gmcount; i++)
+      {
+	mdistat = mdiSetRunMode (mdi_desc->gmdata[i].DevHandle,
+				 -1, MDINoStep, 0);
+	/* Let the target continue when we disconnect from it.  */
+	mdistat = mdiExecute (mdi->gmdata[i].DevHandle);
+	if (mdistat != MDIErrDisabled)
+	  MDIWARN (mdistat, _("continue execution"));
+      }
+
+  for (i = 0; i < mdi->gmcount; i++)
+    {
+      mdistat = mdiClose (mdi->gmdata[i].DevHandle, flags);
+      if (mdistat != MDISuccess)
+	{
+	  MDIRunStateT runstate;
+
+	  if (! mdi_continueonclose || mdistat != MDIErrTargetRunning)
+	    MDIWARN (mdistat, _("closing device"));
+
+	  /* Try stopping the target again.  */
+	  mdistat = mdiStop (mdi->gmdata[i].DevHandle);
+	  MDIWARN (mdistat, _("stopping CPU"));
+
+	  /* Let it report that it has stopped.  */
+	  mdiRunState (mdi->gmdata[i].DevHandle, 200, &runstate);
+
+	  if (mdi_continueonclose)
+	    {
+	      mdistat = mdiSetRunMode (mdi_desc->gmdata[i].DevHandle,
+				       -1, MDINoStep, 0);
+	      /* Let the target continue when we disconnect from it.  */
+	      mdistat = mdiExecute (mdi->gmdata[i].DevHandle);
+	      if (mdistat != MDIErrDisabled)
+		MDIWARN (mdistat, _("continue execution"));
+	    }
+
+	  /* Try the close again.  */
+	  mdistat = mdiClose (mdi->gmdata[i].DevHandle, flags);
+	  MDIWARN (mdistat, _("closing device again"));
+	}
+    }
+
+  if (mdi->Config.MDICapability & MDICAP_TargetGroups)
+    for (i = 0; i < mdi->gmcount; i++)
+      if (mdi->gmdata[i].TGHandle != MDINoHandle)
+	{
+	  int j;
+
+	  mdistat = mdiTGClose (mdi->gmdata[i].TGHandle, flags);
+	  MDIWARN (mdistat, _("target group close"));
+
+	  for (j = i + 1; j < mdi->gmcount; j++)
+	    if (mdi->gmdata[i].tmdata.TGId == mdi->gmdata[j].tmdata.TGId)
+	      mdi->gmdata[j].TGHandle = MDINoHandle;
+	}
+
+  if (mdi->gmcount > 1)
+    {
+      mdistat = mdiTeamClear (mdi->MDIHandle, mdi->gid);
+      MDIWARN (mdistat, _("clearing team"));
+      mdistat = mdiTeamDestroy (mdi->MDIHandle, mdi->gid);
+      MDIWARN (mdistat, _("destroying team"));
+    }
+
+  mdistat = mdiDisconnect (mdi->MDIHandle, flags);
+  MDIWARN (mdistat, _("MDI disconnect"));
+
+  if (mdi->cfgfile)
+    {
+      if (remote_debug == 0)
+	unlink (mdi->cfgfile);
+      xfree (mdi->cfgfile);
+    }
+
+  if (mdi_releaseonclose)
+    {
+      /* Release MDI DLL.  */
+      MDIRelease (mdiModule);
+      mdiModule = 0;
+    }
+
+  xfree (mdi);
+  mdi_desc = NULL;
+
+  if (mdi_logging)
+    {
+      ui_file_delete (mdi_logfp);
+      mdi_logfp = gdb_stdlog;
+      mdi_logging = 0;
+    }
+}
+
+
+
+/* Takes a program previously attached to and detaches it.
+   The program may resume execution (some targets do, some don't) and will
+   no longer stop on signals, etc.  We better not have left any breakpoints
+   in the program or it'll die when it hits one.  ARGS is arguments
+   typed by the user (e.g. a signal to send the process).  FROM_TTY
+   says whether to be verbose or not.  */
+
+/* Terminate the open connection to the remote debugger.
+   Use this when you want to detach and do something else with your gdb.  */
+
+static void
+mdi_detach (char *args, int from_tty)
+{
+  if (args)
+    error (_("Argument given to \"detach\" when remotely debugging."));
+
+  if (remote_debug)
+    printf_unfiltered ("mdi_detach\n");
+
+  target_mourn_inferior ();
+
+  /* XXX Should we actually pop the target here - we could leave it open
+     and all allow a following attach.  */
+  pop_target ();		/* Calls mdi_close to do the real work.  */
+
+  if (from_tty)
+    printf_filtered (_("Ending MDI debugging\n"));
+}
+
+
+static void
+mdi_disconnect (struct target_ops *target, char *args, int from_tty)
+{
+  if (args)
+    error (_("Argument given to \"disconnect\" when remotely debugging."));
+
+  if (remote_debug)
+    printf_unfiltered ("mdi_disconnect\n");
+
+  target_mourn_inferior ();
+
+  /* XXX Need to tell mdi_close not to restart the app.  */
+  pop_target ();		/* Calls mdi_close to do the real work.  */
+
+  if (from_tty)
+    printf_filtered (_("Ending MDI debugging\n"));
+}
+
+static void
+mdi_attach (char *args, int from_tty)
+{
+  MDIInt32 mdistat;
+  MDIRunStateT runstate;
+  int i;
+
+  if (args && *args)
+    error (_("Can't pass arguments to MDI."));
+
+  if (exec_bfd == 0)
+    error (_("No executable file specified"));
+
+  check_mdi ();
+
+  if (from_tty)
+    printf_unfiltered (_("Attaching to MDI target...\n"));
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    {
+      mdiStop (mdi_desc->gmdata[i].DevHandle);
+      mdiRunState (mdi_desc->gmdata[i].DevHandle, 200, &runstate);
+    }
+
+  inferior_ptid = null_ptid;
+  mdi_exited = mdi_signalled = 0;
+
+  reinit_frame_cache ();
+
+  printf_unfiltered (_("MDI target is now halted\n"));
+}
+
+
+static void
+mdi_resume (ptid_t ptid, int step, enum target_signal ssignal)
+{
+  MDIInt32 mdistat;
+  MDIUint32 stepmode = MDINoStep;
+  MDIUint32 stepallmode = MDINoStep;
+  MDIUint32 freezeallmode = 1;
+  int i;
+
+  if (mdi_exited)
+    {
+      if (mdi_loaded)
+	error (_("\
+The program is not being run.\n\
+Please \"load\" and \"run\" it again.\n"));
+      else
+	error (_("\
+The program is not being run.\n\
+Please use \"mdi reset\" to restart execution.\n"));
+    }
+
+  /* Can only pass signals on when stopped in the signal handler.  */
+  if (mdi_signalled && ssignal != mdi_lastsig)
+    mdi_writereg (MIPS_V0_REGNUM, ssignal);
+  mdi_signalled = 0;
+
+  /* Set up "syscall" breakpoints if not already done.  */
+  if (!mdi_syscall_inserted)
+    mdi_insert_syscallbreakpoint ();
+
+  /* Start profiling now, if requested and not already profiling.  */
+  mdi_profiling_start ();
+
+  if (mdi_mem_written)
+    {
+      /* We have written something to memory, which could possibly be
+	 instructions: synchronise the i- and d-caches.  */
+      /* XXX Would be better if we could use an address range,
+	 but the MDI API doesn't support this.  */
+      for (i = 0; i < mdi_desc->gmcount; i++)
+	if (!mdi_desc->gmdata[i].disabled)
+	  {
+	    mdiCacheFlush (mdi_desc->gmdata[i].DevHandle, MDICacheTypeData,
+			   MDICacheWriteBack | MDICacheInvalidate);
+	    mdiCacheFlush (mdi_desc->gmdata[i].DevHandle, MDICacheTypeUnified,
+			   MDICacheWriteBack | MDICacheInvalidate);
+	    mdiCacheFlush (mdi_desc->gmdata[i].DevHandle,
+			   MDICacheTypeInstruction, MDICacheInvalidate);
+	  }
+      mdi_mem_written = 0;
+    }
+
+  /* A hook for when we need to do something at the last moment before
+     resumption.  */
+  if (target_resume_hook)
+    (*target_resume_hook) ();
+
+  if (step)
+    stepmode = mdi_stepinto ? MDIStepInto : MDIStepForward;
+  if (step && mdi_threadstepall)
+    stepallmode = stepmode;
+  if ((step && mdi_threadstepall) || ptid_equal (ptid, pid_to_ptid (-1)))
+    freezeallmode = 0;
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    if (!mdi_desc->gmdata[i].disabled)
+      mdistat = mdiSetRunMode (mdi_desc->gmdata[i].DevHandle,
+			       -1, stepallmode, freezeallmode);
+
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    mdistat = mdiSetRunMode (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+			     ptid_get_tid (inferior_ptid), stepmode, 0);
+  else
+    {
+      MDIInt32 tid = -1;
+
+      mdistat = mdiGetTC (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle, &tid);
+      if (mdistat != MDIErrUnsupported)
+	MDIWARN (mdistat, _("getting current thread"));
+      mdistat = mdiSetRunMode (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+			       tid, stepmode, 0);
+    }
+
+  if (step)
+    {
+      if (remote_debug)
+	fprintf_unfiltered (mdi_logfp, "mdi_resume: stepping at 0x%s\n",
+			    phex (mdi_readpc (), sizeof (ULONGEST)));
+
+      mdi_step_active = 1;
+      if (mdi_desc->gmcount > 1)
+	{
+	  mdistat = mdiTeamExecute (mdi_desc->MDIHandle, mdi_desc->gid);
+	  if (mdistat == MDIErrUnsupported)
+	    {
+	      for (i = 1; i < mdi_desc->gmcount + 1; i++)
+		{
+		  int index = (mdi_desc->gmindex + i) % mdi_desc->gmcount;
+		  mdistat = mdiExecute (mdi_desc->gmdata[index].DevHandle);
+		  if (mdistat != MDIErrDisabled)
+		    MDIWARN (mdistat, _("starting single step"));
+		}
+	      mdistat = MDISuccess;
+	    }
+	}
+      else
+	mdistat = mdiStep (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+			   1, stepmode);
+      mdi_step_active = 0;
+      MDIERR (mdistat, _("starting single step"));
+    }
+  else
+    {
+      if (remote_debug)
+	fprintf_unfiltered (mdi_logfp, "mdi_resume: resuming at 0x%s\n",
+			    phex (mdi_readpc (), sizeof (ULONGEST)));
+
+      if (mdi_desc->gmcount > 1)
+	{
+	  mdistat = mdiTeamExecute (mdi_desc->MDIHandle, mdi_desc->gid);
+	  if (mdistat == MDIErrUnsupported)
+	    {
+	      for (i = 1; i < mdi_desc->gmcount + 1; i++)
+		{
+		  int index = (mdi_desc->gmindex + i) % mdi_desc->gmcount;
+		  mdistat = mdiExecute (mdi_desc->gmdata[index].DevHandle);
+		  if (mdistat != MDIErrDisabled)
+		    MDIWARN (mdistat, _("starting execution"));
+		}
+	      mdistat = MDISuccess;
+	    }
+	}
+      else
+	mdistat = mdiExecute (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle);
+      MDIERR (mdistat, _("starting execution"));
+    }
+}
+
+static RETSIGTYPE mdi_interrupt_twice (int signo);
+static void interrupt_query (void);
+
+static RETSIGTYPE
+mdi_interrupt (int signo)
+{
+  /* If this doesn't work, try more severe steps.  */
+  mdi_signal (signo, mdi_interrupt_twice);
+
+  if (remote_debug)
+    {
+      target_terminal_ours_for_output ();
+      printf_unfiltered (_("mdi_interrupt called\n"));
+      target_terminal_inferior ();
+    }
+
+  quit_flag = 1;
+}
+
+/* The user typed ^C twice.  */
+static RETSIGTYPE
+mdi_interrupt_twice (int signo)
+{
+  signal (signo, ofunc);
+
+  if (remote_debug)
+    {
+      target_terminal_ours_for_output ();
+      printf_unfiltered (_("mdi_interrupt_twice called\n"));
+      target_terminal_inferior ();
+    }
+
+  interrupt_query ();
+
+  mdi_signal (signo, mdi_interrupt);
+}
+
+
+/* Ask the user what to do when an interrupt is received.  */
+
+static void
+wait_cleanup (void)
+{
+  /* Stop it manually.  */
+  MDIRunStateT runstate;
+  int i;
+
+  mdi_wait_active = 0;
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    {
+      mdiStop (mdi_desc->gmdata[i].DevHandle);
+      mdiRunState (mdi_desc->gmdata[i].DevHandle, 200, &runstate);
+    }
+  target_mourn_inferior ();
+  deprecated_throw_reason (RETURN_QUIT);
+}
+
+static void
+interrupt_query (void)
+{
+  target_terminal_ours ();
+
+  if (query (_("\
+Interrupted while waiting for the program.\n\
+Give up (and stop debugging it)? ")))
+    interrupt_cleanup ();
+
+  target_terminal_inferior ();
+}
+
+
+
+static int		mdi_profile_active;
+static CORE_ADDR 	mdi_profile_lowpc;
+static CORE_ADDR 	mdi_profile_highpc;
+static HISTCOUNTER * 	mdi_hist;
+static FILE * 		mdi_gfp;
+
+struct mdi_profile_region {
+  int		valid;
+  MDIInt32 	id;
+  CORE_ADDR	low;
+  CORE_ADDR	high;
+  MDIUint32 * 	counts;
+} mdi_profreg[2];
+
+#define ROUNDDOWN(x,y)	(((x)/(y))*(y))
+#define ROUNDUP(x,y)	((((x)+(y)-1)/(y))*(y))
+
+
+/* Cleanup if an error is thrown while writing profiling data.  */
+
+static void
+mdi_profiling_cleanup (void *arg)
+{
+  MDIInt32 mdistat;
+  int i;
+
+  if (mdi_gfp)
+    fclose (mdi_gfp);
+
+  if (mdi_hist)
+    xfree (mdi_hist);
+
+  for (i = 0; i < 2; i++)
+    {
+      if (mdi_profreg[i].valid)
+	{
+	  if (mdi_profreg[i].counts)
+	    (void) mipssim_FreeProfileData
+	      (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+	       &mdi_profreg[i].counts);
+	  (void) mipssim_DestroyProfile
+	    (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle, mdi_profreg[i].id);
+	  mdi_profreg[i].counts = 0;
+	  mdi_profreg[i].valid = 0;
+	}
+    }
+}
+
+
+/* Only called via catch_errors, to avoid fatal errors.  */
+
+static int
+mdi_profiling_close_1 (PTR writep)
+{
+  int write = *(int *)writep;
+  struct cleanup *cleanups;
+  MDIInt32 mdistat;
+  MDIUint64 cycles;
+  int i;
+
+  if (!mdi_profile_active)
+    return 0;
+  mdi_profile_active = 0;
+
+  for (i = 0; i < 2; i++)
+    if (mdi_profreg[i].valid)
+      {
+	mdistat =
+	  mipssim_StopProfile (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+			       mdi_profreg[i].id);
+	MDIWARN (mdistat, _("Stop Profiling"));
+      }
+
+  cleanups = make_cleanup (mdi_profiling_cleanup, NULL);
+  mdi_gfp = NULL;
+  mdi_hist = NULL;
+
+  if (write)
+    {
+      MDIUint64 max;
+      MDIUint64 total;
+      unsigned long monsize, moncount;
+      unsigned long mdicount, mdiidx, histidx;
+      unsigned int counts_per_bin;
+      unsigned int scale;
+      int tracelev;
+      const char * counting;
+      struct gmon_hdr hdr;
+      struct gmon_hist_hdr {
+	/* char lowpc[addrsize]; */
+	/* char highpc[addrsize]; */
+	char hist_size[4];
+	char prof_rate[4];
+	char dimen[15];
+	char dimen_abbrev;
+      } hist_hdr;
+      u_char tag;
+
+      tracelev = 0;
+      if (MIPSsim_GetTraceLevel)
+	(void) MIPSsim_GetTraceLevel
+	  (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle, &tracelev);
+      counting = (tracelev & 1) ? "cycles" : "insns";
+
+      /* Allocate gmon histogram buffer of textsize / HISTFRACTION.  */
+      monsize = (mdi_profile_highpc - mdi_profile_lowpc) / HISTFRACTION;
+      mdi_hist = xmalloc (monsize);
+
+      /* There is one gmon counter for every HISTFRACTION * sizeof
+         (HISTCOUNTER) bytes of text space.  (That's 1 for every 4
+         bytes for the current settings).  */
+      moncount = monsize / sizeof (HISTCOUNTER);
+
+      /* There is one MIPSsim counter for every 2 bytes of text.  */
+      mdicount = (mdi_profile_highpc - mdi_profile_lowpc) / 2;
+
+      /* So that's how many MIPSsim counts for every gmon count?  */
+      counts_per_bin = mdicount / moncount;
+
+      if (remote_debug)
+	fprintf_unfiltered (mdi_logfp, "\
+hist size=%ld count=%ld; mdi count=%ld; mdi/hist=%d\n",
+			    monsize, moncount, mdicount, counts_per_bin);
+
+      /* Fetch the MIPSsim cycle counts, and find the maximum MIPSsim
+	 cycle count that will go in one gmon histogram bin.  */
+      max = 0;
+      for (i = 0; i < 2; i++)
+	{
+	  if (! mdi_profreg[i].valid)
+	    continue;
+
+	  mdistat =
+	    mipssim_FetchProfile
+	      (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+	       mdi_profreg[i].id, &mdi_profreg[i].counts, &total);
+	  MDIERR (mdistat, _("Fetch Profile"));
+
+	  mdicount = (mdi_profreg[i].high - mdi_profreg[i].low) / 2;
+	  for (mdiidx = 0; mdiidx < mdicount; )
+	    {
+	      MDIUint64 sum;
+	      int c;
+	      for (sum = 0, c = counts_per_bin; c != 0; c--)
+		sum += mdi_profreg[i].counts[mdiidx++];
+	      if (sum > max)
+		max = sum;
+	    }
+	}
+
+      /* Find a scale factor which will allow the largst MDI count to
+	 fit into a 16-bit histogram bin.  */
+      /* TODO
+	 At some point we should enhance gprof to support
+	 32-bit histogram counters.  */
+      if (max > 65535)
+	scale = (max + 65534) / 65535;
+      else
+	scale = 1;
+
+      if (remote_debug)
+	fprintf_unfiltered (mdi_logfp, "max=%lld scale=%d\n",
+			    max, scale);
+
+      /* Rescale the MDI counters and insert into the gmon "pc"
+         histogram.  Gprof doesn't support multiple histograms, so we
+         have to merge all profile regions into a single output
+         histogram.  */
+      histidx = 0;
+      for (i = 0; i < 2; i++)
+	{
+	  unsigned long nextidx;
+
+	  if (! mdi_profreg[i].valid)
+	    continue;
+
+	  /* Calculate first gmon histogram index for this region.  */
+	  nextidx = (mdi_profreg[i].low - mdi_profile_lowpc)
+	    / (HISTFRACTION * sizeof(HISTCOUNTER));
+
+	  /* Clear any hole between this and the last region.
+	     XXX Assumes region list is sorted by ascending address.  */
+	  if (histidx < nextidx)
+	    memset (&mdi_hist[histidx], 0,
+		    (nextidx - histidx) * sizeof mdi_hist[0]);
+
+	  /* Merge and scale the MDI counters into the gmon bins.  */
+	  mdicount = (mdi_profreg[i].high - mdi_profreg[i].low) / 2;
+	  for (mdiidx = 0, histidx = nextidx; mdiidx < mdicount; histidx++)
+	    {
+	      MDIUint64 sum;
+	      int c;
+	      for (sum = 0, c = counts_per_bin; c != 0; c--)
+		sum += mdi_profreg[i].counts[mdiidx++];
+	      if (scale != 1)
+		sum = (sum + scale / 2) / scale; /* Rescale to 16 bits.  */
+	      if (sum > 0xffff)
+		sum = 0xffff;
+	      store_unsigned_integer ((gdb_byte *)&mdi_hist[histidx],
+				      sizeof (mdi_hist[0]),
+				      (ULONGEST) sum);
+	    }
+	}
+
+      /* Write the results to the gmon.out file.  */
+      mdi_gfp = fopen (mdi_gmonfile, FOPEN_WB);
+      if (! mdi_gfp)
+	error (_("Cannot open profile output file \"%s\": %s."),
+	       mdi_gmonfile, safe_strerror (errno));
+
+      if (remote_debug)
+	fprintf_unfiltered (mdi_logfp, "writing to %s\n", mdi_gmonfile);
+
+      /* Write file header.  */
+      memset (&hdr, 0, sizeof hdr);
+      memcpy (hdr.cookie, GMON_MAGIC, sizeof hdr.cookie);
+      store_unsigned_integer ((gdb_byte *)&hdr.version, sizeof hdr.version,
+			      GMON_VERSION);
+      if (fwrite (&hdr, sizeof hdr, 1, mdi_gfp) != 1)
+	perror_with_name (mdi_gmonfile);
+
+      /* Create histogram header.  */
+
+      /* Write histogram tag.  */
+      tag = GMON_TAG_TIME_HIST;
+      if (fwrite (&tag, sizeof tag, 1, mdi_gfp) != 1)
+	perror_with_name (mdi_gmonfile);
+
+      {
+	char hilo[2*8];
+	int sz = register_size (current_gdbarch, 0);
+	store_signed_integer (&hilo[0], sz, mdi_profile_lowpc);
+	store_signed_integer (&hilo[sz], sz, mdi_profile_highpc);
+	if (fwrite (hilo, sz, 2, mdi_gfp) != 2)
+	  perror_with_name (mdi_gmonfile);
+      }
+
+      store_unsigned_integer ((gdb_byte *)hist_hdr.hist_size,
+			      sizeof hist_hdr.hist_size, moncount);
+      store_signed_integer (hist_hdr.prof_rate, sizeof hist_hdr.prof_rate,
+			    scale == 1 ? 1 : -scale);
+      strncpy (hist_hdr.dimen, counting, sizeof (hist_hdr.dimen));
+      hist_hdr.dimen_abbrev = counting[0];
+
+      /* Write tail of histogram header.  */
+      if (fwrite (&hist_hdr, sizeof hist_hdr, 1, mdi_gfp) != 1)
+	perror_with_name (mdi_gmonfile);
+
+      /* Write histogram data.  */
+      if (fwrite (mdi_hist, sizeof (HISTCOUNTER), moncount, mdi_gfp)
+	  != moncount)
+	perror_with_name (mdi_gmonfile);
+
+      if (fclose (mdi_gfp) != 0)
+	perror_with_name (mdi_gmonfile);
+      mdi_gfp = NULL;
+
+      if (remote_debug)
+	fprintf_unfiltered (mdi_logfp, "profiling output done\n");
+    }
+
+  do_cleanups (cleanups);
+  return 0;
+}
+
+
+static void
+mdi_profiling_close (int write)
+{
+  /* Don't let errors bounce us all the way to the top level.  */
+  (void) catch_errors (mdi_profiling_close_1, &write,
+		       _("Couldn't output profiling data:\n"),
+		       RETURN_MASK_ALL);
+}
+
+static struct minimal_symbol *
+mdi_lookup_symbols (const char *syms)
+{
+  struct minimal_symbol *ms;
+  char *copy, *p;
+
+  copy = alloca (strlen (syms) + 1);
+  strcpy (copy, syms);
+  for (p = strtok (copy, " \t,"); p; p = strtok (NULL, " \t,"))
+    if ((ms = lookup_minimal_symbol (p, NULL, NULL)) != NULL)
+      return ms;
+  return NULL;
+}
+
+
+static void
+mdi_profiling_start (void)
+{
+  MDIInt32 mdistat;
+  struct minimal_symbol *fs, *es;
+  struct symbol *s;
+  int i;
+
+  /* If already active, then nothing to do.  */
+  if (mdi_profile_active)
+    return;
+
+  /* Is profiling requested?  */
+  switch (mdi_profiling)
+    {
+    case AUTO_BOOLEAN_FALSE:
+      /* Never.  */
+      return;
+    case AUTO_BOOLEAN_TRUE:
+      /* Always.  */
+      if (! mdi_desc->mipssim_p)
+	{
+	  mdi_profiling = AUTO_BOOLEAN_FALSE;
+	  warning (_("Profiling only supported on MIPSsim - disabled"));
+	  return;
+	}
+      if (! MIPSsim_FreeProfileData)
+	{
+	  mdi_profiling = AUTO_BOOLEAN_FALSE;
+	  warning (_("\
+Profiling not available with this version of MIPSsim - disabled"));
+	  return;
+	}
+      break;
+    case AUTO_BOOLEAN_AUTO:
+      /* Only if _mcount symbol found.  */
+      if (! mdi_desc->mipssim_p
+	  || ! MIPSsim_FreeProfileData
+	  || ! mdi_lookup_symbols (mdi_mcount_syms))
+	return;
+      break;
+    }
+
+  fs = mdi_lookup_symbols (mdi_ftext_syms);
+  if (! fs)
+    {
+      mdi_profiling = AUTO_BOOLEAN_FALSE;
+      warning (_("Missing start of code symbol - profiling disabled"));
+      return;
+    }
+
+  es = mdi_lookup_symbols (mdi_etext_syms);
+  if (! es)
+    {
+      mdi_profiling = AUTO_BOOLEAN_FALSE;
+      warning (_("Missing end of code symbol - profiling disabled"));
+      return;
+    }
+
+  mdi_profile_lowpc = SYMBOL_VALUE_ADDRESS (fs) & ~(CORE_ADDR)1;
+  mdi_profile_highpc = SYMBOL_VALUE_ADDRESS (es) & ~(CORE_ADDR)1;
+  mdi_profile_lowpc = ROUNDDOWN (mdi_profile_lowpc,
+				 HISTFRACTION * sizeof(HISTCOUNTER));
+  mdi_profile_highpc = ROUNDUP (mdi_profile_highpc,
+				HISTFRACTION * sizeof(HISTCOUNTER));
+
+  if (mdi_profile_highpc <= mdi_profile_lowpc)
+    {
+      mdi_profiling = AUTO_BOOLEAN_FALSE;
+      warning (_("Cannot profile - lowpc (0x%s) >= highpc (0x%s) - disabled"),
+	       paddr_nz (mdi_profile_lowpc), paddr_nz (mdi_profile_highpc));
+    }
+
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp, "profile start: lowpc=0x%s highpc=0x%s\n",
+			paddr_nz (mdi_profile_lowpc),
+			paddr_nz (mdi_profile_highpc));
+
+  /* Set up profiling region 0, region 1 is empty.  */
+  memset (mdi_profreg, 0, sizeof mdi_profreg);
+  mdi_profreg[0].low = mdi_profile_lowpc;
+  mdi_profreg[0].high = mdi_profile_highpc;
+
+  /* If the _mcount symbol is in the middle of region 0, split
+     it into two regions (0 & 1), excluding the _mcount function.  */
+  if (! mdi_profile_mcount
+      && ((s = lookup_symbol ("_mcount", NULL, VAR_DOMAIN, NULL, NULL))
+	  || (s = lookup_symbol ("__mcount", NULL, VAR_DOMAIN, NULL, NULL))))
+    {
+      CORE_ADDR mcount_beg = BLOCK_START (SYMBOL_BLOCK_VALUE (s));
+      CORE_ADDR mcount_end = BLOCK_END (SYMBOL_BLOCK_VALUE (s));
+      mcount_beg = ROUNDUP (mcount_beg & ~(CORE_ADDR)1,
+			      HISTFRACTION * sizeof(HISTCOUNTER));
+      mcount_end = ROUNDDOWN (mcount_end & ~(CORE_ADDR)1,
+			      HISTFRACTION * sizeof(HISTCOUNTER));
+      if (mcount_beg < mcount_end
+	  && mcount_beg >= mdi_profreg[0].low
+	  && mcount_end < mdi_profreg[0].high)
+	{
+	  mdi_profreg[1].low = mcount_end;
+	  mdi_profreg[1].high = mdi_profreg[0].high;
+	  mdi_profreg[0].high = mcount_beg;
+	}
+    }
+
+  if (mdi_desc->regsize == 4)
+    {
+      /* Inconsistent address sign-extension (sigh).  */
+      mdi_profile_lowpc &= (CORE_ADDR) 0xffffffff;
+      mdi_profile_highpc &= (CORE_ADDR) 0xffffffff;
+    }
+
+  /* Create the MIPSsim profile regions and start counting.  */
+  mdistat = MDISuccess;
+  for (i = 0; i < 2; i++)
+    {
+      if (mdi_profreg[i].low != mdi_profreg[i].high)
+	{
+	  if (mdi_desc->regsize == 4)
+	    {
+	      /* Inconsistent address sign-extension (sigh).  */
+	      mdi_profreg[i].low &= (CORE_ADDR) 0xffffffff;
+	      mdi_profreg[i].high &= (CORE_ADDR) 0xffffffff;
+	    }
+
+	  /* Create profile region.  */
+	  mdistat =
+	    mipssim_CreateProfile
+	      (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+	       &mdi_profreg[i].id,
+	       mdi_profreg[i].low,
+	       mdi_profreg[i].high - mdi_profreg[i].low);
+	  if (mdistat != MDISuccess)
+	    break;
+
+	  mdi_profreg[i].valid = 1;
+	}
+    }
+
+  if (mdistat == MDISuccess)
+    {
+      for (i = 0; i < 2; i++)
+	if (mdi_profreg[i].valid)
+	  {
+	    /* Start accumulating profile data.  */
+	    mdistat =
+	      mipssim_StartProfile
+		(mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+		 mdi_profreg[i].id);
+	    if (mdistat != MDISuccess)
+	      break;
+	  }
+    }
+
+  if (mdistat != MDISuccess)
+    {
+      warning (_("Cannot create MIPSsim profile for range 0x%s-0x%s."),
+	       paddr_nz (mdi_profreg[i].low),
+	       paddr_nz (mdi_profreg[i].high));
+
+      for (i = 0; i < 2; i++)
+	if (mdi_profreg[i].valid)
+	  mipssim_DestroyProfile
+	    (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle, mdi_profreg[i].id);
+      return;
+    }
+
+  /* Finally try to enable cycle counting, if requested.  */
+  if (mdi_profile_cycles)
+    {
+      if (! catch_errors (mdi_cycles_enable, NULL,
+			  _("Couldn't enable cycle profiling:\n"),
+			  RETURN_MASK_ALL))
+	mdi_profile_cycles = 0;
+    }
+
+  mdi_profile_active = 1;
+}
+
+
+
+static int
+mdi_readstring (ULONGEST memaddr, char *mybuf, int len)
+{
+  MDIInt32 mdistat;
+
+  /* Just read a full buffer's worth.  */
+  mdistat = mdi_read (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+		      mdi_memresource (memaddr), mdi_memoffset (memaddr),
+		      mybuf, 0, len);
+  return mdistat == MDISuccess;
+}
+
+static int
+mdi_writestring (ULONGEST memaddr, char *mybuf, int len)
+{
+  MDIInt32 mdistat;
+
+  /* Write a full buffer's worth.  */
+  mdistat = mdi_write (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+		       mdi_memresource (memaddr), mdi_memoffset (memaddr),
+		       mybuf, 0, len);
+  return mdistat == MDISuccess;
+}
+
+#define MAXMDIFD 64
+static struct mdifd
+{
+  int open;
+  int sysfd;
+}
+mdifd[MAXMDIFD];
+
+
+static void
+mdi_fdcloseall (void)
+{
+  struct mdifd *mp;
+  for (mp = &mdifd[3]; mp < &mdifd[MAXMDIFD]; mp++)
+    if (mp->open)
+      {
+	close (mp->sysfd);
+	mp->open = 0;
+      }
+}
+
+static void
+mdi_fdinit (void)
+{
+  int nfd;
+  struct mdifd *mp;
+
+  mdi_fdcloseall ();
+  for (nfd = 0; nfd < MAXMDIFD; nfd++)
+    {
+      mp = &mdifd[nfd];
+      if (nfd <= 2)
+	{
+	  mp->sysfd = nfd;
+	  mp->open = 1;
+	}
+      else
+	mp->open = 0;
+    }
+}
+
+
+static int
+mdi_fdalloc (int sysfd)
+{
+  struct mdifd *mp;
+  int fd;
+
+  if (sysfd < 0)
+    return sysfd;
+  for (fd = 2, mp = &mdifd[2]; fd < MAXMDIFD; fd++, mp++)
+    {
+      if (!mp->open)
+	{
+	  mp->sysfd = sysfd;
+	  mp->open = 1;
+	  break;
+	}
+    }
+  if (fd >= MAXMDIFD)
+    return -1;
+  return fd;
+}
+
+static int
+mdi_fdlookup (int fd)
+{
+  if (fd < 0 || fd >= MAXMDIFD || !mdifd[fd].open)
+    return -1;
+  return mdifd[fd].sysfd;
+}
+
+
+static int
+mdi_fdopen (char *buf, int flags, int mode)
+{
+  int fd;
+  int hflags = 0;
+
+  /* Convert SDE flag bits into host flags bits.  */
+  switch (flags & 0x0003)
+    {
+    case 0:
+      hflags = O_RDONLY;
+      break;
+    case 1:
+      hflags = O_WRONLY;
+      break;
+    case 2:
+      hflags = O_RDWR;
+      break;
+    default:
+      return -1;
+    }
+#ifdef O_APPEND
+  if (flags & 0x0008)
+    hflags |= O_APPEND;
+#endif
+#ifdef O_CREAT
+  if (flags & 0x0200)
+    hflags |= O_CREAT;
+#endif
+#ifdef O_TRUNC
+  if (flags & 0x0400)
+    hflags |= O_TRUNC;
+#endif
+#ifdef O_EXCL
+  if (flags & 0x0800)
+    hflags |= O_EXCL;
+#endif
+#ifdef O_BINARY
+  if (flags & 0x8000)
+    hflags |= O_BINARY;
+#endif
+
+  fd = open (buf, hflags, mode);
+  if (fd >= 0)
+    fd = mdi_fdalloc (fd);
+  return fd;
+}
+
+
+static int
+mdi_fdclose (int fd)
+{
+  int status = 0;
+
+  if (fd > 2)
+    {
+      int sysfd = mdi_fdlookup (fd);
+      struct mdifd *mp;
+      if (sysfd < 0)
+	return sysfd;
+      mp = &mdifd[fd];
+      status = close (sysfd);
+      mp->open = 0;
+    }
+  return status;
+}
+
+#if defined(HAVE_SIGSETJMP)
+#define SIGJMP_BUF		sigjmp_buf
+#define SIGSETJMP(buf)		sigsetjmp(buf, 1)
+#define SIGLONGJMP(buf,val)	siglongjmp(buf,val)
+#else
+#define SIGJMP_BUF		jmp_buf
+#define SIGSETJMP(buf)		setjmp(buf)
+#define SIGLONGJMP(buf,val)	longjmp(buf,val)
+#endif
+
+static SIGJMP_BUF mdi_readline_env;
+
+static RETSIGTYPE (*mdi_readline_prev_sigint) ();
+
+
+static RETSIGTYPE
+mdi_readline_signal_handler (int signo)
+{
+#if 0
+  /* Don't want to invoke old handler.  */
+  (*mdi_readline_prev_sigint) (signo);
+#endif
+  SIGLONGJMP (mdi_readline_env, 1);
+}
+
+
+static int
+mdi_read_stdin (char *buf, int len)
+{
+  static char *inbuf = NULL;
+  char *tmpbuf = NULL;
+  static int inlen = 0;
+  static int inptr;
+  char *bp = buf;
+
+  char *line;
+  extern FILE *instream;
+
+  while (len > 0)
+    {
+      if (inlen <= 0)
+	{
+	  int result;
+
+	  if (inbuf)
+	    {
+	      free (inbuf);
+	      inbuf = NULL;
+	    }
+
+	  if (gdb_stdtargin == gdb_stdin && deprecated_readline_begin_hook)
+	    (*deprecated_readline_begin_hook) ("%s", "");
+
+	  /* Make sure that all output has been output.  Some machines
+	     may let you get away with leaving out some of the
+	     gdb_flush, but not all.  */
+	  wrap_here ("");
+	  gdb_flush (gdb_stdout);
+	  gdb_flush (gdb_stderr);
+
+	  if (gdb_stdtargin == gdb_stdin && deprecated_readline_hook)
+	    tmpbuf = (*deprecated_readline_hook) (mdi_target_prompt);
+	  else if (gdb_stdtargin != gdb_stdin || input_from_terminal_p ())
+	    {
+	      if (SIGSETJMP (mdi_readline_env))
+		{
+		  signal (SIGINT, mdi_readline_prev_sigint);
+		  quit_flag = 1;
+		}
+
+	      mdi_readline_prev_sigint = signal (SIGINT,
+						 mdi_readline_signal_handler);
+
+	      if (gdb_stdtargin == gdb_stdin)
+		{
+		  tmpbuf = gdb_readline_wrapper (mdi_target_prompt);
+		}
+	      else
+		{
+		  long ret;
+		  tmpbuf = xmalloc (32768);
+		  ret = ui_file_read (gdb_stdtargin, tmpbuf, 32767);
+		  if (ret > 0)
+		    tmpbuf[ret] = '\0';
+		  else
+		    {
+		      xfree (tmpbuf);
+		      tmpbuf = NULL;
+		    }
+		}
+
+	      signal (SIGINT, mdi_readline_prev_sigint);
+	    }
+	  else
+	    {
+	      /* Read one line from a file.  */
+	      tmpbuf = gdb_readline (0);
+	    }
+
+	  if (gdb_stdtargin == gdb_stdin && deprecated_readline_end_hook)
+	    (*deprecated_readline_end_hook) ();
+
+	  if (remote_debug)
+	    fprintf_unfiltered (mdi_logfp, "read \"%s\", quit_flag=%d\n",
+				tmpbuf ? tmpbuf : "<null>", quit_flag);
+
+	  if (quit_flag)
+	    {
+	      if (tmpbuf)
+		free (tmpbuf);
+	      quit_flag = 0;
+	      errno = EINTR;
+	      return -1;
+	    }
+
+	  if (tmpbuf)
+	    {
+	      /* Append \n.  */
+	      inlen = strlen (tmpbuf) + 1;
+	      inbuf = (char *) malloc (inlen + 1);
+	      memcpy (inbuf, tmpbuf, inlen - 1);
+	      inbuf[inlen - 1] = '\n';
+	      inbuf[inlen] = '\0';
+	      free (tmpbuf);
+	      inptr = 0;
+	    }
+	  else
+	    {
+	      /* EOF!  */
+	      inlen = 0;
+	      break;
+	    }
+	}
+      else
+	{
+	  int n = inlen > len ? len : inlen;
+	  memcpy (bp, &inbuf[inptr], n);
+	  bp += n;
+	  len -= n;
+	  inptr += n;
+	  inlen -= n;
+	  if (inlen == 0)
+	    break;
+	}
+    }
+
+  return bp - buf;
+}
+
+
+#define _MDI_SYSCALL_OPEN	0
+#define _MDI_SYSCALL_CLOSE	1
+#define _MDI_SYSCALL_READ	2
+#define _MDI_SYSCALL_WRITE	3
+#define _MDI_SYSCALL_GETCHAR	4
+#define _MDI_SYSCALL_PUTCHAR	5
+#define _MDI_SYSCALL_LSEEK32	6
+#define _MDI_SYSCALL_GETTIME	7
+#define _MDI_SYSCALL_EXIT	8
+#define _MDI_SYSCALL_MOVED	9
+#define _MDI_SYSCALL_GETARGS	10
+#define _MDI_SYSCALL_ISATTY	11
+#define _MDI_SYSCALL_PROFIL	12
+#define _MDI_SYSCALL_SIGHOOK	13
+
+#define MDI_SYS_EXITED		0
+#define MDI_SYS_RESUME		1
+#define MDI_SYS_SIGNALLED	2
+#define MDI_SYS_INTERRUPT	3
+
+/* Provide a host file i/o mechanism.  */
+
+static int
+mdi_do_syscall (void)
+{
+  ULONGEST v0 = mdi_readreg (MIPS_V0_REGNUM);
+  ULONGEST a0 = mdi_readreg (MIPS_A0_REGNUM);
+  ULONGEST a1 = mdi_readreg (MIPS_A0_REGNUM + 1);
+  ULONGEST a2 = mdi_readreg (MIPS_A0_REGNUM + 2);
+#define BUFLEN 8192
+  char buf[BUFLEN];
+  int ptrsize = gdbarch_ptr_bit (current_gdbarch) / 8;
+  int result = MDI_SYS_RESUME;
+  int rv;
+
+  switch ((int) v0)
+    {
+    case _MDI_SYSCALL_OPEN:
+      if (mdi_readstring (a0, buf, 1024))
+	{
+	  if (remote_debug > 0)
+	    fprintf_unfiltered (mdi_logfp,
+				"mdi_syscall: open(\"%s\", 0x%x, 0%o)\n",
+				buf, (int)a1, (int)a2);
+	  rv = mdi_fdopen (buf, a1, a2);
+	}
+      else
+	{
+	  if (remote_debug > 0)
+	    fprintf_unfiltered (mdi_logfp,
+				"mdi_syscall: open(memerr<0x%s>, 0x%x, 0%o)",
+				phex_nz (a0, sizeof a0), (int)a1, (int)a2);
+	  rv = -1;
+	}
+      if (remote_debug > 0)
+	fprintf_unfiltered (mdi_logfp, "mdi_syscall: open -> %d\n", rv);
+      mdi_writereg (MIPS_V0_REGNUM, rv);
+      break;
+
+    case _MDI_SYSCALL_CLOSE:
+      if (remote_debug > 0)
+	fprintf_unfiltered (mdi_logfp, "mdi_syscall: close(%d)\n", (int)a1);
+      rv = mdi_fdclose (a0);
+      if (remote_debug > 0)
+	fprintf_unfiltered (mdi_logfp, "mdi_syscall: close -> %d\n", rv);
+      mdi_writereg (MIPS_V0_REGNUM, rv);
+      break;
+
+    case _MDI_SYSCALL_READ:
+      {
+	int sysfd = mdi_fdlookup (a0);
+	int remain = a2;
+	int nread = 0;
+	int n = 0;
+
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp,
+			      "mdi_syscall: read(%d, 0x%s, %d)\n",
+			      (int)a0, phex_nz (a1, sizeof a1), remain);
+	if (sysfd < 0)
+	  nread = -1;
+	else if (remain > 0)
+	  switch (sysfd)
+	    {
+	    case 0:
+	      n = (remain > BUFLEN) ? BUFLEN : remain;
+	      nread = mdi_read_stdin (buf, n);
+	      if (nread < 0)
+		{
+		  mdi_writestring (a1, "\n", 1);
+		  nread = 1;	/* to avoid end of file */
+		  result = MDI_SYS_INTERRUPT;
+		  break;
+		}
+	      if (nread > 0 && !mdi_writestring (a1, buf, nread))
+		nread = -1;	/* memory error */
+	      break;
+
+	    case 1:
+	    case 2:
+	      nread = -1;	/* Bad file descriptor.  */
+	      break;
+
+	    default:
+	      while (remain > 0)
+		{
+		  n = (remain > BUFLEN) ? BUFLEN : remain;
+		  n = read (sysfd, buf, n);
+		  if (n > 0)
+		    {
+		      if (!mdi_writestring (a1, buf, n))
+			n = -1;	/* memory error */
+		    }
+		  if (n <= 0)
+		    {
+		      if (nread == 0)
+			nread = n;
+		      break;
+		    }
+		  a1 += n;
+		  remain -= n;
+		  nread += n;
+		}
+	      break;
+	    }
+
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp, "mdi_syscall: read -> %d\n", nread);
+	mdi_writereg (MIPS_V0_REGNUM, nread);
+      }
+      break;
+
+    case _MDI_SYSCALL_WRITE:
+      {
+	int sysfd = mdi_fdlookup (a0);
+	int remain = a2;
+	int nwritten = 0;
+	int n;
+
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp,
+			      "mdi_syscall: write(%d, 0x%s, %d)\n",
+			      (int)a0, phex_nz (a1, sizeof a1), remain);
+	if (sysfd <= 0)
+	  nwritten = -1;
+	else
+	  {
+	    while (remain > 0)
+	      {
+		n = (remain > BUFLEN) ? BUFLEN : remain;
+		if (mdi_readstring (a1, buf, n))
+		  {
+		    if (sysfd == 1)
+		      {
+			ui_file_write (gdb_stdtarg, buf, n);
+			gdb_flush (gdb_stdtarg);
+		      }
+		    else if (sysfd == 2)
+		      {
+			ui_file_write (gdb_stdtargerr, buf, n);
+			gdb_flush (gdb_stdtargerr);
+		      }
+		    else
+		      n = write (sysfd, buf, n);
+		  }
+		else
+		  n = -1;		/* memory error */
+		if (n <= 0)
+		  {
+		    if (nwritten == 0)
+		      nwritten = n;
+		    break;
+		  }
+		a1 += n;
+		remain -= n;
+		nwritten += n;
+	      }
+	  }
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp, "mdi_syscall: write -> %d\n",
+			      nwritten);
+	mdi_writereg (MIPS_V0_REGNUM, nwritten);
+      }
+      break;
+
+    case _MDI_SYSCALL_LSEEK32:
+      {
+	int sysfd = mdi_fdlookup (a0);
+	int whence = a2;
+	long offs;
+
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp,
+			      "mdi_syscall: lseek32(%d, %ld, %d)\n",
+			      (int)a0, (long)a1, whence);
+	if (sysfd > 2)
+	  {
+	    switch (whence)
+	      {
+	      case 0:
+		whence = SEEK_SET;
+		break;
+	      case 1:
+		whence = SEEK_CUR;
+		break;
+	      case 2:
+		whence = SEEK_END;
+		break;
+	      }
+	    offs = lseek (sysfd, (long) a1, whence);
+	  }
+	else
+	  offs = -1;
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp, "mdi_syscall: lseek32 -> %ld\n",
+			      offs);
+	mdi_writereg (MIPS_V0_REGNUM, offs);
+      }
+      break;
+
+    case _MDI_SYSCALL_ISATTY:
+      {
+	int sysfd = mdi_fdlookup (a0);
+	rv = 0;
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp, "mdi_syscall: isatty(%d)\n", (int)a0);
+	if (sysfd >= 0)
+	  {
+	    switch (sysfd)
+	      {
+	      case 0:
+		rv = ui_file_isatty (gdb_stdtargin);
+		break;
+	      case 1:
+		rv = ui_file_isatty (gdb_stdtarg);
+		break;
+	      case 2:
+		rv = ui_file_isatty (gdb_stdtargerr);
+		break;
+	      default:
+		rv = isatty (sysfd);
+		break;
+	      }
+	  }
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp, "mdi_syscall: isatty -> %d\n", rv);
+	mdi_writereg (MIPS_V0_REGNUM, rv);
+      }
+      break;
+
+    case _MDI_SYSCALL_GETCHAR:
+      /* XXX Find a way to read a single character without line editing.  */
+      if (remote_debug > 0)
+	fprintf_unfiltered (mdi_logfp, "mdi_syscall: getchar(%d)\n", (int)a0);
+      rv = 0;
+      if (a0 == 0)
+	{
+	  int n = mdi_read_stdin (buf, 1);
+	  if (n < 0)
+	    /* Return no character, and interrupt result.  */
+	    result = MDI_SYS_INTERRUPT;
+	  else if (n == 1)
+	    {
+	      if (buf[0] == '\n')
+		rv = '\r';
+	      else
+		rv = buf[0] & 0xff;
+	    }
+	}
+      if (remote_debug > 0)
+	fprintf_unfiltered (mdi_logfp, "mdi_syscall: getchar -> '%c' (0x%x)\n",
+			    isprint (rv) ? rv : '.', rv);
+      mdi_writereg (MIPS_V0_REGNUM, rv);
+      break;
+
+    case _MDI_SYSCALL_PUTCHAR:
+      {
+	char buf = a1;
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp, "mdi_syscall: putchar('%c' (0x%x))\n",
+			      isprint (buf) ? buf : '.', buf);
+	ui_file_write (gdb_stdtarg, &buf, 1);
+	gdb_flush (gdb_stdtarg);
+      }
+      break;
+
+    case _MDI_SYSCALL_GETTIME:
+      {
+	struct timeval tv;
+	gettimeofday (&tv, NULL);
+	mdi_writereg (MIPS_V0_REGNUM, tv.tv_sec);
+	mdi_writereg (MIPS_V0_REGNUM + 1, tv.tv_usec);
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp, "mdi_syscall: gettime -> %ld.%06ld\n",
+			      tv.tv_sec, tv.tv_usec);
+      }
+      break;
+
+    case _MDI_SYSCALL_GETARGS:
+      {
+	CORE_ADDR sp, argv;
+	unsigned char buf[8];
+	int argc, nbytes, i;
+
+	/* Get total arg string length.  */
+	nbytes = 0;
+	for (argc = 0; mdi_argv && mdi_argv[argc]; argc++)
+	  nbytes += strlen (mdi_argv[argc]) + 1;
+
+	/* Start writing arg strings at top of stack.  */
+	sp = mdi_readreg (MIPS_SP_REGNUM);
+
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp, "mdi_syscall: getargs(), sp=0x%s\n",
+			      phex_nz (sp, sizeof sp));
+
+	/* Start writing argv[] array just below arg strings.  */
+	argv = (sp - nbytes) & ~7;
+
+	/* Store terminating NULL in argv[argc].  */
+	store_signed_integer (buf, ptrsize, 0);
+	mdi_writestring (argv -= ptrsize, buf, ptrsize);
+
+	/* Write arguments to stack in "reverse" order.  */
+	for (i = argc - 1; i >= 0; i--)
+	  {
+	    size_t len = strlen (mdi_argv[i]) + 1;
+	    /* Write arg string.  */
+	    mdi_writestring (sp -= len, mdi_argv[i], len);
+	    /* Write argv[] pointer.  */
+	    store_signed_integer (buf, ptrsize, sp);
+	    mdi_writestring (argv -= ptrsize, buf, ptrsize);
+	  }
+
+	if (argc > 0)
+	  {
+	    /* Set $a0, $a1 to argc & argv.  */
+	    mdi_writereg (MIPS_A0_REGNUM + 0, argc);
+	    mdi_writereg (MIPS_A0_REGNUM + 1, argv);
+	    /* Round stack pointer down to max stack alignment, then
+	       leave space for max arg save area.  */
+	    sp = (argv & ~15) - 64;
+	    mdi_writereg (MIPS_SP_REGNUM, sp);
+	  }
+
+	if (remote_debug > 0)
+	  fprintf_unfiltered (mdi_logfp, "\
+mdi_syscall: getargs -> argc=%d argv=0x%s sp=0x%s\n",
+			      argc, phex_nz (argv, sizeof argv),
+			      phex_nz (sp, sizeof sp));
+      }
+      break;
+
+    case _MDI_SYSCALL_PROFIL:
+      /* Program control over MIPSsim profiling.  */
+      if (remote_debug > 0)
+	fprintf_unfiltered (mdi_logfp, "mdi_syscall: profil(%s)\n",
+			    a0 ? "start" : "stop");
+      if (mdi_profile_active)
+	{
+	  int i;
+	  for (i = 0; i < 2; i++)
+	    {
+	      if (mdi_profreg[i].valid)
+		{
+		  if (a0)
+		    mipssim_StartProfile
+		      (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+		       mdi_profreg[i].id);
+		  else
+		    mipssim_StopProfile
+		      (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+		       mdi_profreg[i].id);
+		}
+	    }
+	}
+      break;
+
+    case _MDI_SYSCALL_SIGHOOK:
+      /* Program received signal - return signal number to handler.  */
+      if (remote_debug > 0)
+	fprintf_unfiltered (mdi_logfp, "mdi_syscall: sighook(signo %d)\n",
+			    (int)a0);
+      mdi_writereg (MIPS_V0_REGNUM, a0);
+      result = MDI_SYS_SIGNALLED;
+      break;
+
+    case _MDI_SYSCALL_EXIT:
+      /* Program exited.  */
+      if (remote_debug > 0)
+	fprintf_unfiltered (mdi_logfp, "mdi_syscall: exit(%d)\n", (int)a0);
+      result = MDI_SYS_EXITED;
+      break;
+
+    case _MDI_SYSCALL_MOVED:
+      if (remote_debug > 0)
+	fprintf_unfiltered (mdi_logfp, "mdi_syscall: moved()\n");
+      break;
+
+    default:
+      /* Just let target continue, MDI can reinsert breakpoints.  */
+      break;
+    }
+
+  if (result != MDI_SYS_EXITED)
+    /* Skip rest of "syscall" function and return to caller.  */
+    mdi_writepc (mdi_readreg (MIPS_RA_REGNUM));
+
+  if (remote_debug > 0 && result != MDI_SYS_RESUME)
+    fprintf_unfiltered (mdi_logfp, "mdi_syscall: not resuming, result=%s\n",
+			(result == MDI_SYS_EXITED) ? "exited"
+			: (result == MDI_SYS_SIGNALLED) ? "signalled"
+			: (result == MDI_SYS_INTERRUPT) ? "interrupt"
+			: "???");
+
+  return result;
+}
+
+
+static CORE_ADDR
+mdi_kva2phys (CORE_ADDR addr)
+{
+#if defined(BFD64) && defined(CC_HAS_LONG_LONG)
+  if (0xffffffff80000000LL <= addr && addr < 0xffffffffc0000000LL)
+    /* kseg0 / kseg1 */
+    return addr & 0x1fffffffLL;
+  if (0x8000000000000000LL <= addr && addr < 0xc000000000000000LL)
+    /* xkphys */
+    return addr & 0x07ffffffffffffffLL;
+#else
+  if ((CORE_ADDR) 0x80000000 <= addr && addr < (CORE_ADDR) 0xc0000000)
+    return addr & (CORE_ADDR) 0x1fffffff;
+#endif
+  return addr;
+}
+
+
+/* Sleep for the specified number of milliseconds.
+   If select() is interrupted, returns immediately;
+   takes an error exit if select() fails for some other reason.  */
+
+static void
+sleep_ms (long ms)
+{
+  struct timeval timeout;
+  int status;
+
+  timeout.tv_sec = ms / 1000;
+  timeout.tv_usec = (ms % 1000) * 1000;
+
+  status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &timeout);
+
+  if (status < 0 && errno != EINTR)
+    perror_with_name ("select");
+}
+
+
+static ptid_t
+mdi_wait (ptid_t ptid, struct target_waitstatus *status)
+{
+  MDIInt32 mdistat;
+  MDIRunStateT runstate;
+  CORE_ADDR pc;
+  int stop;
+  int restarted;
+  int quit_printed;
+  int i;
+
+  if (mdi_starting)
+    {
+      /* First time through, called from start_remote(), do nothing.  */
+      mdi_starting = 0;
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_TRAP;
+      return inferior_ptid;
+    }
+
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp, "mdi_wait:...\n");
+
+  /* Install our SIGINT signal handler.  */
+  interrupt_cleanup = wait_cleanup;
+  ofunc = mdi_signal (SIGINT, mdi_interrupt);
+
+  /* Ideally we should just call mdiRunState with an infinite wait
+     time and rely on mdiAbort from the periodic callback.
+     Unfortunately MIPSsim 3.x doesn't use the periodic callback, in
+     fact it doesn't implement wait time either, it treats all calls
+     as a poll, so we implement our own small sleep, to give other
+     parts of the system a chance.
+     XXX Could we fix this up for MIPSsim 4.x?  */
+
+  stop = 0;
+
+  do
+    {
+      int sleep_time;
+      int not_running;
+      int seen_reset;
+
+      restarted = 0;
+
+      i = (mdi_desc->gmindex + 1) % mdi_desc->gmcount;
+
+      sleep_time = 10;		/* Start off with 10ms and increase.  */
+      not_running = 0;
+      seen_reset = 0;
+      quit_printed = 0;
+
+      do
+	{
+	  int disabled;
+
+	  runstate.Status = MDIStatusNotRunning;
+
+	  mdi_wait_active = 1;
+	  mdistat = mdiRunState (mdi_desc->gmdata[i].DevHandle,
+				 mdi_waittime, &runstate);
+	  mdi_wait_active = 0;
+
+	  if (mdistat != MDISuccess)
+	    {
+	      MDIWARN (mdistat, _("fetching CPU run state"));
+	      break;
+	    }
+
+	  /* See if the user has asked us to stop.  */
+	  if (ptid_equal (ptid, pid_to_ptid (-1))
+	      || mdi_desc->gmdata[i].DevHandle == ptid_get_lwp (ptid))
+	    {
+	      if (!stop && deprecated_ui_loop_hook != NULL)
+		stop = deprecated_ui_loop_hook (0);
+
+	      if (quit_flag)
+		{
+		  quit_flag = 0;
+		  stop = 1;
+		}
+	    }
+
+	  if (runstate.Status == MDIStatusNotRunning)
+	    {
+	      /* Accumulate time spent NotRunning.  */
+	      not_running += mdi_waittime;
+	      /* Time out after 5000ms,
+	         or immediately if called from start_remote.  */
+	      if (not_running >= 5000)
+		break;
+	    }
+
+	  disabled = (runstate.Status == MDIStatusDisabled
+		      || runstate.Status == MDIStatusVPEDisabled);
+
+	  if ((runstate.Status & MDIStatusMask) != MDIStatusRunning
+	      && runstate.Status != MDIStatusNotRunning
+	      && !disabled)
+	    /* Terminate wait loop when an interesting new state occurs.  */
+	    break;
+
+	  if (runstate.Status & MDIStatusReset)
+	    {
+	      if (! seen_reset)
+		warning (_("CPU reset active"));
+	      seen_reset = 1;
+	    }
+	  else
+	    {
+	      seen_reset = 0;
+	    }
+
+	  if (stop && (!disabled || mdi_desc->gmcount == 1))
+	    {
+	      if (!quit_printed)
+		{
+		  printf_filtered (_("Quit received: Stopping target\n"));
+		  quit_printed = 1;
+		}
+	      mdistat = mdiStop (mdi_desc->gmdata[i].DevHandle);
+	      if (mdistat != MDISuccess)
+		MDIWARN (mdistat, _("stopping CPU"));
+	    }
+
+	  /* Give the rest of the system a chance to do something.  */
+	  sleep_ms (sleep_time);
+
+	  /* Accumulate time spent not running. */
+	  not_running += sleep_time;
+
+	  /* Keep increasing the length of the sleep, but limit to
+	     200ms to avoid long GUI delays when hitting the stop
+	     button.  */
+	  sleep_time *= 2;
+	  if (sleep_time > 200)
+	    sleep_time = 200;
+
+	  if (!stop || disabled)
+	    i = (i + 1) % mdi_desc->gmcount;
+	}
+      while (1);
+
+      mdi_desc->gmindex = i;
+
+      /* This is a hook for when we need to do something (perhaps the
+	 collection of trace data) every time the target stops.  */
+      if (target_wait_loop_hook)
+	(*target_wait_loop_hook) ();
+
+      if (remote_debug)
+	{
+	  fprintf_unfiltered (mdi_logfp,
+			      "mdi_wait: stopped at 0x%s, ",
+			      phex (mdi_readpc (), sizeof (ULONGEST)));
+	  mdiDisplayRunState (&runstate);
+	}
+
+      /* Check for a host i/o "system call".  */
+      if ((runstate.Status == MDIStatusBPHit
+	   || runstate.Status == MDIStatusUsrBPHit
+	   || runstate.Status == MDIStatusStepsDone)
+	  && mdi_syscall_inserted
+	  && (pc = mdi_kva2phys ((CORE_ADDR) mdi_readpc ()))
+	  && (mdi_kva2phys (mdi_syscall) == pc
+	      || mdi_kva2phys (mdi_syscall_rom) == pc))
+	{
+	  int result = mdi_do_syscall ();
+	  if (stop)
+	    result = MDI_SYS_INTERRUPT;		/* Catch a pending halt.  */
+	  switch (result)
+	    {
+	    case MDI_SYS_RESUME:
+	      /* I/O complete - restart target.  */
+	      mdistat = mdiExecute (mdi_desc->gmdata[i].DevHandle);
+	      if (mdistat != MDISuccess)
+		MDIWARN (mdistat, _("resume execution after syscall"));
+	      else
+		restarted = 1;
+	      break;
+	    case MDI_SYS_EXITED:
+	      /* Target program exited.  */
+	      runstate.Status = MDIStatusExited;
+	      break;
+	    case MDI_SYS_INTERRUPT:
+	      /* Interrupted by user.  */
+	      runstate.Status = MDIStatusHalted;
+	      break;
+	    case MDI_SYS_SIGNALLED:
+	      /* Signal occurred.  */
+	      runstate.Status = MDIStatusHalted;
+	      mdi_signalled = 1;
+	      break;
+	    }
+	}
+    }
+  while (restarted);
+
+  /* Restore old SIGINT handler.  */
+  signal (SIGINT, ofunc);
+
+  for (i = (mdi_desc->gmindex + 1) % mdi_desc->gmcount;
+       i != mdi_desc->gmindex;
+       i = (i + 1) % mdi_desc->gmcount)
+    {
+      mdistat = mdiStop (mdi_desc->gmdata[i].DevHandle);
+      if (mdistat != MDISuccess)
+	MDIWARN (mdistat, _("stopping CPU"));
+    }
+
+  for (i = (mdi_desc->gmindex + 1) % mdi_desc->gmcount;
+       i != mdi_desc->gmindex;
+       i = (i + 1) % mdi_desc->gmcount)
+    {
+      MDIRunStateT rs;
+      int sleep_time = 10;	/* Start off with 10ms and increase.  */
+
+      while (1)
+	{
+	  rs.Status = MDIStatusNotRunning;
+
+	  mdi_wait_active = 1;
+	  mdistat = mdiRunState (mdi_desc->gmdata[i].DevHandle,
+				 mdi_waittime, &rs);
+	  mdi_wait_active = 0;
+
+	  if (mdistat != MDISuccess)
+	    {
+	      MDIWARN (mdistat, _("fetching CPU run state"));
+	      break;
+	    }
+
+	  if ((rs.Status & MDIStatusMask) != MDIStatusRunning)
+	    break;
+
+	  /* Keep increasing the length of the sleep, but limit to
+	     200ms to avoid long GUI delays when hitting the stop
+	     button.  */
+	  sleep_time *= 2;
+	  if (sleep_time > 200)
+	    sleep_time = 200;
+	}
+
+	if (rs.Status == MDIStatusDisabled
+	    || rs.Status == MDIStatusVPEDisabled)
+	  {
+	    mdi_desc->gmdata[i].disabled = 1;
+	  }
+	else
+	  {
+	    mdi_desc->gmdata[i].disabled = 0;
+	    if (!mdi_desc->gmdata[i].probed)
+	      {
+		updateDev (mdi_desc, i, mdi_desc->gmdata[i].DeviceData.Id);
+		mdi_probe_cpu (mdi_desc, i);
+		mdi_desc->gmdata[i].probed = 1;
+	      }
+	  }
+    }
+
+  quit_flag = 0;		/* Consume any left over quit signal.  */
+  mdi_runstate = runstate;
+
+  /* Update $cycles convenience variable.  */
+  if (mdi_desc->mipssim_p)
+    mdi_cycles_update ();
+
+  mdi_set_inferior_ptid ();
+
+  mdi_curbpt.Type = 0;
+  switch (runstate.Status & MDIStatusMask)
+    {
+    default:
+      warning ("MDIRunState=%s", statusName (runstate.Status & MDIStatusMask));
+      status->kind = TARGET_WAITKIND_SPURIOUS;
+      status->value.sig = TARGET_SIGNAL_0;
+      break;
+    case MDIStatusDisabled:
+      /* Can't happen...  */
+      internal_error (__FILE__, __LINE__,
+		      "MDIRunState.Status = MDIStatusDisabled");
+    case MDIStatusRunning:
+      /* Can't happen...  */
+      internal_error (__FILE__, __LINE__,
+		      "MDIRunState.Status = MDIStatusRunning");
+    case MDIStatusNotRunning:
+      if ((runstate.Status & (MDIStatusReset | MDIStatusWasReset)) == 0)
+	warning (_("MDI time out: MDIStatusNotRunning"));
+      /* Fall through.  */
+    case MDIStatusHalted:
+      /* Report interesting reset events to user.  */
+      if (runstate.Status & MDIStatusReset)
+	warning (_("CPU held in reset"));
+      else if (runstate.Status & MDIStatusWasReset)
+	warning (_("CPU was reset"));
+      /* We requested target to stop.  */
+      status->kind = TARGET_WAITKIND_STOPPED;
+      if (mdi_signalled)
+	{
+	  mdi_lastsig = (enum target_signal) mdi_readreg (MIPS_A0_REGNUM);
+	  if (mdi_lastsig <= TARGET_SIGNAL_FIRST ||
+	      mdi_lastsig >= TARGET_SIGNAL_LAST)
+	    mdi_lastsig = TARGET_SIGNAL_UNKNOWN;
+	  status->value.sig = mdi_lastsig;
+	}
+      else
+	{
+	  status->value.sig = TARGET_SIGNAL_INT;
+	  if (runstate.Status & MDIStatusDescription)
+	    warning (_("MDI halted: %s"), (char *) runstate.Info.ptr);
+	}
+      break;
+    case MDIStatusExited:
+      {
+	unsigned int ec = mdi_readreg (MIPS_A0_REGNUM);
+	if (ec >> 8)
+	  {
+	    mdi_lastsig = (enum target_signal) ((ec >> 8) & 0xff);
+	    if (mdi_lastsig <= TARGET_SIGNAL_FIRST ||
+		mdi_lastsig >= TARGET_SIGNAL_LAST)
+	      mdi_lastsig = TARGET_SIGNAL_UNKNOWN;
+	    status->kind = TARGET_WAITKIND_SIGNALLED;
+	    status->value.sig = mdi_lastsig;
+	  }
+	else
+	  {
+	    status->kind = TARGET_WAITKIND_EXITED;
+	    status->value.integer = ec;
+	  }
+      }
+      /* Cleanup target file i/o and write profiling data.  */
+      mdi_fdcloseall ();
+      mdi_profiling_close (1);
+      mdi_exited = 1;
+      inferior_ptid = null_ptid;
+      break;
+    case MDIStatusStepsDone:
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_TRAP;
+      break;
+    case MDIStatusBPHit:
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_TRAP;
+      {
+	MDIBpDataT *bpt =
+	  mdi_find_breakpoint (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+			       runstate.Info.value);
+	if (bpt)
+	  {
+	    mdi_curbpt = *bpt;
+	    break;
+	  }
+      }
+      /* Fall through in case something has gone wrong in MDIlib.  */
+    case MDIStatusUsrBPHit:
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_TRAP;
+      {
+	MDIBpDataT *bpt = mdi_find_usr_breakpoint ((CORE_ADDR) mdi_readpc ());
+	if (bpt)
+	  mdi_curbpt = *bpt;
+      }
+      break;
+    case MDIStatusException:
+      status->kind = TARGET_WAITKIND_STOPPED;
+      switch (runstate.Info.value)
+	{
+	case 0:		/* INTR */
+	  status->value.sig = TARGET_SIGNAL_KILL;
+	  break;
+	case 1:		/* MOD */
+	case 2:		/* TLBL/IBOUND */
+	case 3:		/* TLBS/DBOUND */
+	  status->value.sig = TARGET_SIGNAL_SEGV;
+	  break;
+	case 4:		/* ADEL */
+	case 5:		/* ADES */
+	case 6:		/* IBE/BE */
+	case 7:		/* DBE */
+	  /* NB some LSI processors signal watchpoints with a bus error.  */
+	  status->value.sig = TARGET_SIGNAL_BUS;
+	  break;
+	case 8:		/* SYS */
+	  status->value.sig = TARGET_SIGNAL_SYS;
+	  break;
+	case 9:		/* BP */
+	  /* NB could decode break instruction to refine the signal.  */
+	  status->value.sig = TARGET_SIGNAL_TRAP;
+	  break;
+	case 10:		/* RI */
+	case 11:		/* CPU */
+	  status->value.sig = TARGET_SIGNAL_ILL;
+	  break;
+	case 12:		/* OVF */
+	  status->value.sig = TARGET_SIGNAL_FPE;	/* ??? */
+	  break;
+	case 13:		/* TRAP */
+	  status->value.sig = TARGET_SIGNAL_TRAP;
+	  break;
+	case 14:		/* VCEI */
+	case 15:		/* FPE */
+	case 16:		/* CP2 */
+	  status->value.sig = TARGET_SIGNAL_KILL;
+	  break;
+	case 17:		/* RES17 */
+	case 18:		/* RES18 */
+	case 19:		/* RES19 */
+	case 20:		/* RES20 */
+	case 21:		/* RES21 */
+	case 22:		/* RES22 */
+	  status->value.sig = TARGET_SIGNAL_KILL;
+	  break;
+	case 23:		/* WATCH */
+	  status->value.sig = TARGET_SIGNAL_TRAP;
+	  break;
+	case 24:		/* MCHECK */
+	case 25:		/* RES25 */
+	case 26:		/* RES26 */
+	case 27:		/* RES27 */
+	case 28:		/* RES28 */
+	case 29:		/* RES29 */
+	case 30:		/* CACHEERR */
+	case 31:		/* VCED */
+	  status->value.sig = TARGET_SIGNAL_KILL;
+	  break;
+	default:
+	  status->value.sig = TARGET_SIGNAL_KILL;
+	  break;
+	}
+      break;
+    case MDIStatusTraceFull:
+      /* FIXME collect trace data. */
+      status->kind = TARGET_WAITKIND_IGNORE;
+      break;
+    }
+
+  return inferior_ptid;
+}
+
+
+static int
+mdi_map_regno (int regno, MDIResourceT * rsrc, MDIOffsetT * offs, int write)
+{
+  const struct mips_regnum *regnum = mips_regnum (current_gdbarch);
+  int size = mdi_desc->regsize;
+
+  if (regno < 32)
+    {
+      *offs = regno;
+      *rsrc = MDIMIPCPU;
+    }
+  else if (regno >= regnum->fp0
+	   && regno < regnum->fp0 + 32)
+    {
+      size = register_size (current_gdbarch, regno);
+
+      if (mdi_fpr_avail < 0)
+	{
+	  /* Check for availability of new MDI FPR resource.  */
+	  char tmp[8];
+	  mdi_fpr_avail =
+	    (mdi_read (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+		       MDIMIPFPR, 0,
+		       tmp, register_size (current_gdbarch, regnum->fp0), 1)
+	     == MDISuccess);
+	}
+
+      if (mdi_fpr_avail)
+	/* Got new "software-model" MDI resource.  */
+	*rsrc = MDIMIPFPR;
+      else
+	{
+	  /* Have to use old "hardware-model" MDI resource.  */
+	  /* XXX We don't really know if we're on CPU with 32 or 16
+	     64-bit fp registers, so we don't know whether to divide
+	     the regno by two or not.  We can't just tell from the
+	     size, because MIPS32 has 32 single precision registers,
+	     and MIPS I has 16. We'll assume MIPS32 and hope for the
+	     best.  */
+	  if (size == 4)
+	    /* 32-bit register mode: 0 - 15/31, assume 31.  */
+	    /* XXX Will the odd registers actually give us the
+	       high part of the double?  */
+	    *rsrc = MDIMIPFP;
+	  else
+	    /* 64-bit register mode: 0 - 15/31, assume 31.  */
+	    *rsrc = MDIMIPDFP;
+	}
+      regno -= regnum->fp0;
+      *offs = regno;
+      if (mdi_cpdreg_miss[1][0] & (1 << regno))
+	return 0;
+    }
+  else if (regno >= MIPS_EMBED_CP0_REGNUM
+	   && regno < MIPS_EMBED_CP0_REGNUM + 32 * 8)
+    {
+      /* CP0 registers.  */
+      int reg = regno - MIPS_EMBED_CP0_REGNUM;
+      /* Don't access cp0 registers where a previous read failed.  */
+      if (mdi_cpdreg_miss[0][reg / 32] & (1 << (reg % 32)))
+	return 0;
+      /* Don't allow writes to write protected registers.  */
+      if (write && (mdi_cpdreg_wp[0][reg / 32] & (1 << (reg % 32))))
+	return 0;
+      *offs = reg;
+      *rsrc = MDIMIPCP0;
+    }
+  else if (regno >= MIPS_EMBED_CP2_REGNUM
+	   && regno < MIPS_EMBED_CP2_REGNUM + 32 * 8)
+    {
+      /* CP2 registers.  */
+      int reg = regno - MIPS_EMBED_CP2_REGNUM;
+      /* Don't access cp2 registers where a previous read failed.  */
+      if (mdi_cpdreg_miss[2][reg / 32] & (1 << (reg % 32)))
+	return 0;
+      /* Don't allow writes to write protected registers.  */
+      if (write && (mdi_cpdreg_wp[2][reg / 32] & (1 << (reg % 32))))
+	return 0;
+      *offs = reg;
+      *rsrc = MDIMIPCP2;
+    }
+  else if (regno >= MIPS_EMBED_CP2CTL_REGNUM
+	   && regno < MIPS_EMBED_CP2CTL_REGNUM + 32)
+    {
+      /* CP2 control registers.  */
+      int reg = regno - MIPS_EMBED_CP2CTL_REGNUM;
+      /* Don't access cp2 control registers where a previous read failed.  */
+      if (mdi_cpcreg_miss[2] & (1 << reg))
+	return 0;
+      /* Don't allow writes to write protected registers.  */
+      if (write && (mdi_cpcreg_wp[2] & (1 << reg)))
+	return 0;
+      *offs = reg;
+      *rsrc = MDIMIPCP2C;
+    }
+  else if (regno == regnum->hi)
+    {
+      *offs = 0;
+      *rsrc = MDIMIPHILO;
+    }
+  else if (regno == regnum->lo)
+    {
+      *offs = 1;
+      *rsrc = MDIMIPHILO;
+    }
+  else if (regnum->dspacc <= regno && regno < regnum->dspacc + 10)
+    {
+      int o = 2 + regno - regnum->dspacc;
+      if (mdi_hilo_miss & (1 << o))
+	return 0;
+      *offs = o;
+      *rsrc = MDIMIPHILO;
+    }
+  else if (regno == regnum->dspctl)
+    {
+      int o = regno - regnum->dspctl;
+      if (mdi_dsp_miss & (1 << o))
+	return 0;
+      *offs = o;
+      *rsrc = MDIMIPDSP;
+    }
+  else if (regno == regnum->badvaddr)
+    {
+      *offs = 8;
+      *rsrc = MDIMIPCP0;
+    }
+  else if (regno == MIPS_PS_REGNUM)
+    {
+      *offs = 12;
+      *rsrc = MDIMIPCP0;
+    }
+  else if (regno == regnum->cause)
+    {
+      *offs = 13;
+      *rsrc = MDIMIPCP0;
+    }
+  else if (regno == regnum->pc)
+    {
+      *offs = 0;
+      *rsrc = MDIMIPPC;
+    }
+  else if (regno == regnum->fp_control_status)
+    {
+      *offs = 31;
+      *rsrc = MDIMIPCP1C;
+      if (mdi_cpcreg_miss[1] & (1 << 31))
+	return 0;
+    }
+  else if (regno == regnum->fp_implementation_revision)
+    {
+      *offs = 0;
+      *rsrc = MDIMIPCP1C;
+      if (mdi_cpcreg_miss[1] & (1 << 0))
+	return 0;
+    }
+  else
+    return 0;
+
+  return size;
+}
+
+
+static void
+mdi_bad_register (MDIInt32 stat, MDIResourceT rsrc, MDIOffsetT offset,
+		  const char *what)
+{
+  unsigned int offs = offset;
+  int coprocessor = 1;
+
+  /* Record the failure, so we don't try again.  */
+  switch (rsrc)
+    {
+    case MDIMIPCP0:
+      mdi_cpdreg_miss[0][offs / 32] |= 1 << (offs % 32);
+      break;
+    case MDIMIPFP:
+    case MDIMIPDFP:
+    case MDIMIPFPR:
+      /* If an even register isn't available, assume no fpu.  */
+      if ((offs & 1) == 0)
+	mdi_cpdreg_miss[1][0] = ~0;
+      break;
+    case MDIMIPCP1C:
+      mdi_cpcreg_miss[1] |= 1 << (offs % 32);
+      break;
+    case MDIMIPCP2:
+      mdi_cpdreg_miss[2][offs / 32] |= 1 << (offs % 32);
+      break;
+    case MDIMIPCP2C:
+      mdi_cpcreg_miss[2] |= 1 << (offs % 32);
+      break;
+    case MDIMIPCP3:
+      mdi_cpdreg_miss[3][offs / 32] |= 1 << (offs % 32);
+      break;
+    case MDIMIPCP3C:
+      mdi_cpcreg_miss[3] |= 1 << (offs % 32);
+      break;
+    case MDIMIPDSP:
+      mdi_dsp_miss |= 1 << offs;
+      break;
+    case MDIMIPHILO:
+      mdi_hilo_miss |= 1 << offs;
+      if (offs > 1)
+	break;			/* DSP HI/LO/ACX may be missing.  */
+      /* Fall through.  */
+    default:
+      coprocessor = 0;
+      break;
+    }
+
+  /* Coprocessor registers are allowed to be missing.  */
+  if (coprocessor)
+    {
+      switch (stat)
+	{
+	case MDIErrSrcResource:
+	case MDIErrSrcCount:
+	case MDIErrInvalidSrcOffset:
+	case MDIErrDstResource:
+	case MDIErrDstCount:
+	case MDIErrInvalidDstOffset:
+	case MDIErrFailure:	/* Grrr, libs shouldn't return this.  */
+	  /* Safe to ignore.  */
+	  return;
+	}
+    }
+
+  fprintf_unfiltered (gdb_stderr, _("MDI %s: register %s %d\n"),
+		      what, resrcName (rsrc), offs);
+  MDIERR (stat, what);
+}
+
+
+static void
+mdi_fetch_register (struct regcache *regcache, int regno)
+{
+  unsigned LONGEST val;
+  char *s;
+  int err = 0;
+
+  if (regno == -1)
+    {
+      for (regno = 0; regno < gdbarch_num_regs (current_gdbarch); regno++)
+	mdi_fetch_register (regcache, regno);
+      return;
+    }
+
+  if (regno == MIPS_ZERO_REGNUM)
+    {
+      val = 0;
+    }
+  else
+    {
+      char tmp[MAX_REGISTER_SIZE];
+      int nr_bytes;
+      MDIResourceT rsrc;
+      MDIOffsetT offs;
+
+      nr_bytes = mdi_map_regno (regno, &rsrc, &offs, 0);
+      if (nr_bytes > 0)
+	{
+	  MDIInt32 mdistat;
+	  mdistat = mdi_read (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+			      rsrc, offs, tmp, nr_bytes, 1);
+	  if (mdistat == MDISuccess)
+	    {
+	      /* Register arrives in target byte order,
+		 sign-extend the value at the same time.  */
+	      val = extract_signed_integer (tmp, nr_bytes);
+	    }
+	  else
+	    {
+	      mdi_bad_register (mdistat, rsrc, offs, _("fetching register"));
+	      val = 0;
+	      err = 1;
+	    }
+	}
+      else
+	{
+	  val = 0;
+	  err = 1;
+	}
+    }
+
+  {
+    gdb_byte buf[MAX_REGISTER_SIZE];
+    /* Gdb expects to see a value in the target byte ordering.  */
+    store_unsigned_integer (buf, register_size (current_gdbarch, regno), val);
+    regcache_raw_supply (regcache, regno, buf);
+  }
+
+  if (err)
+    /* Register value not available.  */
+    regcache_set_valid_p (regcache, regno, -1);
+}
+
+
+static void
+mdi_store_register (struct regcache *regcache, int regno)
+{
+  char tmp[MAX_REGISTER_SIZE];
+
+  int nr_bytes;
+  MDIResourceT rsrc;
+  MDIOffsetT offs;
+
+  if (regno == -1)
+    {
+      for (regno = 0; regno < gdbarch_num_regs (current_gdbarch); regno++)
+	mdi_store_register (regcache, regno);
+      return;
+    }
+
+  nr_bytes = mdi_map_regno (regno, &rsrc, &offs, 1);
+  if (nr_bytes > 0)
+    {
+      LONGEST val;
+      MDIInt32 mdistat;
+
+      regcache_cooked_read_unsigned (regcache, regno, &val);
+
+      /* If h/w reg size is 64-bits, but s/w model is 32-bits, then
+	 sign-extend from 32 to 64 bits.  */
+      if (nr_bytes == 8 && register_size (current_gdbarch, regno) == 4)
+	val = (int) val;
+
+      /* Send in target order.  */
+      store_signed_integer (tmp, nr_bytes, val);
+
+      mdistat = mdi_write (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+			   rsrc, offs, tmp, nr_bytes, 1);
+      if (mdistat != MDISuccess)
+	mdi_bad_register (mdistat, rsrc, offs, _("storing register"));
+    }
+}
+
+
+static ULONGEST
+mdi_readreg (int regno)
+{
+  ULONGEST val = 0;
+  char tmp[MAX_REGISTER_SIZE];
+  int nr_bytes;
+  MDIResourceT rsrc;
+  MDIOffsetT offs;
+
+  nr_bytes = mdi_map_regno (regno, &rsrc, &offs, 0);
+  if (nr_bytes > 0)
+    {
+      MDIInt32 mdistat;
+      mdistat = mdi_read (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+			  rsrc, offs, tmp, nr_bytes, 1);
+      if (mdistat == MDISuccess)
+	{
+	  /* Register arrives in target byte order,
+	     sign-extend the value at the same time.  */
+	  val = extract_signed_integer (tmp, nr_bytes);
+	}
+      else
+	{
+	  /* Some registers may be missing.  */
+	  mdi_bad_register (mdistat, rsrc, offs, _("reading register"));
+	}
+    }
+  return val;
+}
+
+static void
+mdi_writereg (int regno, ULONGEST val)
+{
+  gdb_byte tmp[MAX_REGISTER_SIZE];
+  MDIResourceT rsrc;
+  MDIOffsetT offs;
+  MDIInt32 mdistat = MDISuccess;
+  int nr_bytes;
+
+  nr_bytes = mdi_map_regno (regno, &rsrc, &offs, 1);
+  if (nr_bytes > 0)
+    {
+      /* Send in target order.  */
+      store_unsigned_integer (tmp, nr_bytes, val);
+      mdistat = mdi_write (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+			   rsrc, offs, tmp, nr_bytes, 1);
+      MDIERR (mdistat, _("writing register"));
+    }
+}
+
+
+static ULONGEST
+mdi_readpc (void)
+{
+  return mdi_readreg (mips_regnum (current_gdbarch)->pc);
+}
+
+static void
+mdi_writepc (ULONGEST v)
+{
+  mdi_writereg (mips_regnum (current_gdbarch)->pc, v);
+}
+
+
+static int
+mapped_segment_p (CORE_ADDR addr)
+{
+#ifdef BFD64
+  switch ((int)(addr >> 62) & 0x3)
+    {
+    case 0x3:	/* xkseg */
+      if (addr == (bfd_signed_vma)(int)addr)
+	/* 32-bit compatibility segment */
+	break;
+      /* xkseg -mapped */
+      return 1;
+    case 0x2:
+      /* xkphys - unmapped */
+      return 0;
+    case 0x1:
+      /* xksseg - mapped */
+      return 1;
+    case 0x0:
+      /* xkuseg/kuseg - mapped */
+      return 1;
+    }
+#endif
+
+  /* 32-bit address space */
+  switch (((int)addr >> 30) & 0x3) {
+  case 0x3:
+    /* kseg2/ksseg/kseg3 - mapped */
+    return 1;
+  case 0x2:
+    /* kseg 0/1 - unmapped */
+    return 0;
+  case 0x1:
+  case 0x0:
+    /* kuseg - mapped */
+    return 1;
+  }
+
+  abort ();
+}
+
+static MDIResourceT
+mdi_memresource (CORE_ADDR addr)
+{
+  MDIResourceT rsrc;
+  ULONGEST entryhi;
+
+  switch (mdi_asidtype)
+    {
+    default:
+    case ASIDNone:
+      rsrc = MDIMIPGVIRTUAL;
+      break;
+    case ASIDAuto:
+      if (! mapped_segment_p (addr))
+	{
+	  /* Use global address space for unmapped segments.  */
+	  rsrc = MDIMIPGVIRTUAL;
+	  break;
+	}
+      /* Fall through.  */
+    case ASIDReg:
+      /* FIXME: EntryHI */
+      regcache_cooked_read_unsigned (get_current_regcache (),
+				     MIPS_FIRST_EMBED_REGNUM + 10, &entryhi);
+      rsrc = MDIMIPVIRTUAL + (entryhi & 0xff);
+      break;
+    case ASIDFixed:
+      rsrc = MDIMIPVIRTUAL + mdi_asid;
+      break;
+    }
+  return rsrc;
+}
+
+
+static MDIOffsetT
+mdi_memoffset (CORE_ADDR addr)
+{
+  MDIOffsetT offs = addr;
+  if (mdi_desc->regsize == 4
+      && (offs >> 32 == (MDIOffsetT) 0xffffffff))
+    /* FS2 doesn't like 64 sig bits of address on a 32 bit CPU.  */
+    offs &= (MDIOffsetT) 0xffffffff;
+  return offs;
+}
+
+static CORE_ADDR
+mdi_memaddr (MDIOffsetT offs)
+{
+  CORE_ADDR addr = offs;
+  if (mdi_desc->regsize == 4)
+    /* FS2 doesn't like 64 sig bits of address on a 32 bit CPU.  */
+    addr = ((addr & (CORE_ADDR) 0xffffffff) ^ (CORE_ADDR) 0x80000000)
+	   - (CORE_ADDR) 0x80000000;
+  return addr;
+}
+
+
+static int
+mdi_read_bytes (CORE_ADDR memaddr, char *myaddr, int len)
+{
+  if (mdi_read (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+		mdi_memresource (memaddr), mdi_memoffset (memaddr),
+		myaddr, 0, len) != MDISuccess)
+    return 0;
+  return len;
+}
+
+
+static int
+mdi_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
+{
+  if (mdi_write (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+		 mdi_memresource (memaddr), mdi_memoffset (memaddr),
+		 myaddr, 0, len) != MDISuccess)
+    return 0;
+  mdi_mem_written = 1;
+  return len;
+}
+
+
+static void
+mdi_prepare_to_store (struct regcache *regcache)
+{
+  /* Do nothing, since we can store individual regs.  */
+}
+
+
+static int
+mdi_xfer_memory (CORE_ADDR memaddr, gdb_byte *buf, int len, int write,
+		 struct mem_attrib *attrib,
+		 struct target_ops *target)
+{
+  int res;
+
+  if (len <= 0)
+    return 0;
+
+  if (write)
+    res = mdi_write_bytes (memaddr, buf, len);
+  else
+    res = mdi_read_bytes (memaddr, buf, len);
+  return res;
+}
+
+static void
+mdi_files_info (struct target_ops *ops)
+{
+  if (!mdi_desc)
+    {
+      printf_filtered (_("\tNot attached.\n"));
+      return;
+    }
+
+  if (mdi_desc->gmdata[mdi_desc->gmindex].DeviceData.VPartData[0]
+      && strcmp (mdi_desc->gmdata[mdi_desc->gmindex].DeviceData.VPartData,
+		 "Unknown") != 0)
+    printf_filtered (_("\tAttached to %s on %s %s\n"),
+		     mdi_desc->gmdata[mdi_desc->gmindex].DeviceData.DName,
+		     mdi_desc->gmdata[mdi_desc->gmindex].DeviceData.Vendor,
+		     mdi_desc->gmdata[mdi_desc->gmindex].DeviceData.VPartData);
+  else
+    printf_filtered (_("\tAttached to %s\n"),
+		     mdi_desc->gmdata[mdi_desc->gmindex].DeviceData.DName);
+  if (exec_bfd)
+    {
+      printf_filtered (_("\tand running program %s.\n"),
+		       bfd_get_filename (exec_bfd));
+    }
+}
+
+static void
+mdi_kill (void)
+{
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp, "mdi_kill\n");
+
+  /* XXX Should we forcibly stop any running MDI device here.  */
+
+  /* Just note that the inferior is no longer running.  */
+  target_mourn_inferior ();
+}
+
+/* Load an executable file into the target process.  This is expected to
+   not only bring new code into the target process, but also to update
+   GDB's symbol tables to match.  */
+
+static void
+mdi_load (char *prog, int fromtty)
+{
+  struct cleanup *cleanups;
+  char *filename, *offset = NULL;
+  char *ext;
+  CORE_ADDR pc;
+  CORE_ADDR entry;
+  int i;
+
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp, "mdi_load: prog \"%s\"\n", prog);
+
+#if 0
+  if (mdi_asidtype != ASIDNone)
+    warning (_("Using mapped addresses for load\n"));
+#endif
+
+  /* Flush any leftover profiling data - don't write to file.  */
+  mdi_profiling_close (0);
+
+  /* Forget about any previous "syscall" breakpoints.  */
+  mdi_remove_syscallbreakpoint ();
+
+  /* Writeback and invalidate data caches.  */
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    if (!mdi_desc->gmdata[i].disabled)
+      {
+	mdiCacheFlush (mdi_desc->gmdata[i].DevHandle, MDICacheTypeData,
+		       MDICacheWriteBack | MDICacheInvalidate);
+	mdiCacheFlush (mdi_desc->gmdata[i].DevHandle, MDICacheTypeUnified,
+		       MDICacheWriteBack | MDICacheInvalidate);
+      }
+
+  mdi_found_relf = 0;
+  mdi_entrypoint = 0;
+  mdi_loaded = 0;
+  inferior_ptid = null_ptid;
+
+  /* Reinitialise target file i/o.  */
+  mdi_fdinit ();
+
+  filename = xmalloc (strlen (prog) + sizeof ".relf");
+  cleanups = make_cleanup (xfree, filename);
+
+  /* Copy arguments and terminate after file name.  */
+  strcpy (filename, prog);
+  ext = strchr (filename, ' ');
+  if (ext != NULL)
+    {
+      char *s;
+      *ext = '\0';
+      for (s = ext + 1; *s == ' ' || *s == '\t'; s++)
+	continue;
+      if (*s)
+	offset = s;
+    }
+  else
+    ext = filename + strlen (filename);
+
+  /* Don't do enything if an offset is present, assume the
+     user knows what their doing.  */
+  if (!offset)
+    {
+      /* Append .relf extension.  */
+      strcpy (ext, ".relf");
+      /* If .relf file doesn't exist, revert to original name.  */
+      if (access (filename, F_OK) != 0)
+	*ext = '\0';
+      else
+	mdi_found_relf = 1;
+    }
+
+  /* The generic_load function sets the PC, but we don't want to do this.  */
+  pc = read_pc ();
+  generic_load (filename, fromtty);
+  mdi_entrypoint = read_pc ();
+  write_pc (pc);
+
+  do_cleanups (cleanups);
+
+  mdi_loaded = 1;
+}
+
+
+struct mdi_bpt
+{
+  struct mdi_bpt *next;
+  MDIHandleT devhandle;
+  MDIBpDataT mdibp;
+};
+
+static struct mdi_bpt *mdi_bpts;
+
+static void
+mdi_reset_breakpoints (void)
+{
+  struct mdi_bpt *bpt, *nbpt;
+
+  for (bpt = mdi_bpts; bpt; bpt = nbpt)
+    {
+      nbpt = bpt->next;
+      xfree (bpt);
+    }
+  mdi_bpts = NULL;
+}
+
+
+static MDIBpDataT *
+mdi_find_breakpoint (MDIHandleT devhandle, MDIBpIdT id)
+{
+  struct mdi_bpt *bpt;
+
+  for (bpt = mdi_bpts; bpt; bpt = bpt->next)
+    if (bpt->devhandle == devhandle && bpt->mdibp.Id == id)
+      return &bpt->mdibp;
+  return NULL;
+}
+
+
+static MDIBpDataT *
+mdi_find_usr_breakpoint (CORE_ADDR addr)
+{
+  struct mdi_bpt *bpt;
+
+  for (bpt = mdi_bpts; bpt; bpt = bpt->next)
+    if (bpt->mdibp.Type == MDIBPT_SWInstruction
+	&& bpt->mdibp.Enabled == 1
+	&& bpt->mdibp.Resource == mdi_memresource (addr)
+	&& bpt->mdibp.Range.Start == mdi_memoffset (addr))
+      return &bpt->mdibp;
+  return NULL;
+}
+
+
+static int
+mdi_insert_breakpoint1 (CORE_ADDR addr, MDIInt32 rsrc)
+{
+  struct mdi_bpt *bpt, *bpdata, **next;
+  MDIInt32 mdistat;
+
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp, "mdi_insert_breakpoint1: 0x%x\n",
+			(unsigned int) addr);
+
+  bpt = xcalloc (1, sizeof (struct mdi_bpt));
+  /* Set the breakpoint for the first device only; others will get
+     MDIStatusUsrBPHit.  */
+  bpt->devhandle = mdi_desc->gmdata[0].DevHandle;
+  bpt->mdibp.Id = 0;
+  bpt->mdibp.Type = MDIBPT_SWInstruction;
+  bpt->mdibp.Enabled = 1;
+  bpt->mdibp.Resource = rsrc;
+  bpt->mdibp.Range.Start = mdi_memoffset (addr);
+  bpt->mdibp.PassCount = 1;
+
+  next = &mdi_bpts;
+  while (*next)
+    {
+      bpdata = *next;
+
+      if (bpdata->devhandle == bpt->devhandle
+	  && bpdata->mdibp.Type == bpt->mdibp.Type
+	  && bpdata->mdibp.Resource == bpt->mdibp.Resource
+	  && bpdata->mdibp.Range.Start == bpt->mdibp.Range.Start
+	  && bpdata->mdibp.Enabled == 1)
+	    bpt->mdibp.Enabled = ~0;
+
+      next = &(*next)->next;
+    }
+
+  if (bpt->mdibp.Enabled != ~0)
+    {
+      mdistat = mdiSetBp (bpt->devhandle, &bpt->mdibp);
+      if (mdistat != MDISuccess)
+	{
+	  xfree (bpt);
+	  MDIWARN (mdistat, _("setting breakpoint"));
+	  return EIO;
+	}
+    }
+
+  bpt->next = mdi_bpts;
+  mdi_bpts = bpt;
+
+  return 0;
+}
+
+static int
+mdi_insert_breakpoint (struct bp_target_info *bp_tgt)
+{
+  CORE_ADDR addr = bp_tgt->placed_address;
+
+  return mdi_insert_breakpoint1 (addr, mdi_memresource (addr));
+}
+
+static void
+mdi_insert_syscallbreakpoint (void)
+{
+  struct minimal_symbol *ms;
+
+  mdi_syscall = mdi_syscall_rom = 0;
+  if ((ms = lookup_minimal_symbol ("_mdi_syscall", NULL, NULL)))
+    {
+      mdi_syscall = SYMBOL_VALUE_ADDRESS (ms);
+
+      /* If symbol is in RAM then add an additional breakpoint
+	 at pre-relocation ROM address.  */
+      if (mdi_found_relf
+	  && (ms = lookup_minimal_symbol ("___reset", NULL, NULL)))
+	mdi_syscall_rom = mdi_syscall
+	  - SYMBOL_VALUE_ADDRESS (ms)
+	  + mdi_entrypoint;
+    }
+
+  if (mdi_syscall)
+    mdi_insert_breakpoint1 (mdi_syscall, MDIMIPGVIRTUAL);
+  if (mdi_syscall_rom && mdi_syscall_rom != mdi_syscall)
+    mdi_insert_breakpoint1 (mdi_syscall_rom, MDIMIPGVIRTUAL);
+  mdi_syscall_inserted = 1;
+}
+
+static int
+mdi_remove_bpt (MDIInt32 type, CORE_ADDR addr, MDIInt32 rsrc)
+{
+  MDIHandleT devhandle = mdi_desc->gmdata[0].DevHandle;
+  MDIOffsetT off = mdi_memoffset (addr);
+  struct mdi_bpt *bpt, *pbpt;
+  MDIInt32 mdistat;
+
+  /* Find matching breakpoint.  */
+  for (bpt = mdi_bpts, pbpt = NULL; bpt; pbpt = bpt, bpt = bpt->next)
+    {
+      if (bpt->devhandle == devhandle
+	  && (bpt->mdibp.Type & MDIBPT_TypeMask) == type
+	  && bpt->mdibp.Range.Start == off
+	  && bpt->mdibp.Resource == rsrc)
+	break;
+    }
+
+  if (!bpt)
+    /* Not found. */
+    return 0;
+
+  if (bpt->mdibp.Enabled != ~0)
+    {
+      mdistat = mdiClearBp (bpt->devhandle, bpt->mdibp.Id);
+      if (mdistat != MDISuccess)
+	{
+	  MDIWARN (mdistat, _("clearing breakpoint"));
+	  return EIO;
+	}
+    }
+
+  /* Unlink and free the breakpoint.  */
+  if (pbpt)
+    pbpt->next = bpt->next;
+  else
+    mdi_bpts = bpt->next;
+  xfree (bpt);
+
+  return 0;
+}
+
+static int
+mdi_remove_breakpoint1 (CORE_ADDR addr, MDIInt32 rsrc)
+{
+  return mdi_remove_bpt (MDIBPT_SWInstruction, addr, rsrc);
+}
+
+static int
+mdi_remove_breakpoint (struct bp_target_info *bp_tgt)
+{
+  CORE_ADDR addr = bp_tgt->placed_address;
+
+  return mdi_remove_breakpoint1 (addr, mdi_memresource (addr));
+}
+
+static void
+mdi_remove_syscallbreakpoint (void)
+{
+  if (mdi_syscall)
+    mdi_remove_breakpoint1 (mdi_syscall, MDIMIPGVIRTUAL);
+  if (mdi_syscall_rom && mdi_syscall_rom != mdi_syscall)
+    mdi_remove_breakpoint1 (mdi_syscall_rom, MDIMIPGVIRTUAL);
+  mdi_syscall_rom = mdi_syscall = 0;
+  mdi_syscall_inserted = 0;
+}
+
+static void
+mdi_mourn_inferior (void)
+{
+  if (remote_debug)
+    fprintf_unfiltered (mdi_logfp, "mdi_mourn_inferior:\n");
+
+  remove_breakpoints ();
+  generic_mourn_inferior ();
+}
+
+static void
+mdi_switch_to_thread (void)
+{
+  MDIInt32 mdistat;
+  MDIHandleT devhandle;
+  MDITCIdT TCId;
+  int i, j;
+
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    {
+      j = mdi_desc->gmindex;
+      devhandle = ptid_get_lwp (inferior_ptid);
+      for (i = 0; i < mdi_desc->gmcount; i++)
+	if (!mdi_desc->gmdata[i].disabled
+	    && mdi_desc->gmdata[i].DevHandle == devhandle)
+	  {
+	    j = i;
+	    break;
+	  }
+
+      TCId = ptid_get_tid (inferior_ptid);
+      mdistat = mdiSetTC (mdi_desc->gmdata[j].DevHandle, TCId);
+      if (mdistat == MDISuccess)
+	mdi_desc->gmindex = j;
+      else
+	{
+	  warning (_("Thread %d (%s) unavailable."),
+		   pid_to_thread_id (inferior_ptid),
+		   target_tid_to_str (inferior_ptid));
+
+	  /* Attempt to recover.  */
+	  mdistat = mdiGetTC (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+			      &TCId);
+	  if (mdistat != MDISuccess)
+	    /* Too bad...  */
+	    error (_("Current thread went away!?"));
+
+	  inferior_ptid =
+	    ptid_build (GET_PID (inferior_ptid),
+			mdi_desc->gmdata[mdi_desc->gmindex].DevHandle, TCId);
+	}
+    }
+  last_ptid = inferior_ptid;
+}
+
+static int
+mdi_thread_alive (ptid_t ptid)
+{
+  MDIInt32 howmany;
+  MDITCDataT *tcdata;
+  MDIInt32 mdistat;
+  int i, j;
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    {
+      if (mdi_desc->gmdata[i].disabled)
+	continue;
+
+      howmany = 0;
+
+      mdistat = mdiTCQuery (mdi_desc->gmdata[i].DevHandle, &howmany, NULL);
+      if (mdistat == MDIErrUnsupported && mdi_desc->gmcount > 1)
+	{
+	  if (ptid_get_lwp (ptid) == mdi_desc->gmdata[i].DevHandle
+	      && ptid_get_tid (ptid) == 0)
+	    return 1;
+	}
+      else if (mdistat != MDISuccess)
+	return 0;
+
+      if (howmany > 0)
+	{
+	  tcdata = alloca (howmany * sizeof (*tcdata));
+	  mdistat = mdiTCQuery (mdi_desc->gmdata[i].DevHandle,
+				&howmany, tcdata);
+	  if (mdistat != MDISuccess)
+	    return 0;				/* Shouldn't happen.  */
+	  for (j = 0; j < howmany; j++)
+	    {
+	      int active;
+
+	      active = mdi_threadviewinactive
+		       || ((tcdata[j].Status != MDITCStatusHalted)
+			   && (tcdata[j].Status != MDITCStatusFree));
+	      if (active
+		  && ptid_get_lwp (ptid) == mdi_desc->gmdata[i].DevHandle
+		  && ptid_get_tid (ptid) == tcdata[j].TCId)
+		return 1;
+	    }
+	}
+    }
+  return 0;
+}
+
+static void
+mdi_find_new_threads (void)
+{
+  MDIInt32 howmany;
+  MDITCDataT *tcdata;
+  MDIInt32 mdistat;
+  ptid_t ptid;
+  int i, j;
+
+  /* Don't add threads till a running program is available.  */
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return;
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    {
+      if (mdi_desc->gmdata[i].disabled)
+	continue;
+
+      howmany = 0;
+
+      mdistat = mdiTCQuery (mdi_desc->gmdata[i].DevHandle, &howmany, NULL);
+      if (mdistat == MDIErrUnsupported && mdi_desc->gmcount > 1)
+	{
+	  ptid = ptid_build (GET_PID (inferior_ptid),
+			     mdi_desc->gmdata[i].DevHandle, 0);
+	  if (!in_thread_list (ptid))
+	    {
+	      add_thread (ptid);
+	      printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid));
+	    }
+	  continue;
+	}
+      else if (mdistat != MDISuccess)
+	{
+	  if (mdistat != MDIErrUnsupported)
+	    MDIWARN (mdistat, _("getting thread list"));
+	  return;
+	}
+
+      if (howmany > 0)
+	{
+	  tcdata = alloca (howmany * sizeof (*tcdata));
+	  mdistat = mdiTCQuery (mdi_desc->gmdata[i].DevHandle,
+				&howmany, tcdata);
+	  if (mdistat != MDISuccess)
+	    {
+	      MDIWARN (mdistat, _("getting thread list"));
+	      return;				/* Shouldn't happen.  */
+	    }
+	  for (j = 0; j < howmany; j++)
+	    {
+	      int active;
+
+	      active = mdi_threadviewinactive
+		       || ((tcdata[j].Status != MDITCStatusHalted)
+			   && (tcdata[j].Status != MDITCStatusFree));
+	      ptid = ptid_build (GET_PID (inferior_ptid),
+				 mdi_desc->gmdata[i].DevHandle,
+				 tcdata[j].TCId);
+	      if (active && !in_thread_list (ptid))
+		{
+		  add_thread (ptid);
+		  printf_unfiltered (_("[New %s]\n"),
+				     target_pid_to_str (ptid));
+		}
+	      else if (!active)
+		delete_thread (ptid);
+	    }
+	}
+    }
+}
+
+static char *
+mdi_pid_to_str (ptid_t ptid)
+{
+  MDIHandleT devhandle;
+  static char *buf = NULL;
+  int i;
+
+  devhandle = ptid_get_lwp (ptid);
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    if (devhandle == mdi_desc->gmdata[i].DevHandle)
+      {
+	xfree (buf);
+	if (mdi_desc->gmcount > 1)
+	  buf = xstrprintf ("Thread Context %d:%d:%ld",
+			    mdi_desc->gmdata[i].tmdata.TGId + 1,
+			    mdi_desc->gmdata[i].tmdata.DevId + 1,
+			    ptid_get_tid (ptid));
+	else
+	  buf = xstrprintf ("Thread Context %ld", ptid_get_tid (ptid));
+	break;
+      }
+  return buf;
+}
+
+#if notyet
+int
+mdi_region_ok_for_hw_watchpoint (CORE_ADDR addr, int byte_count)
+{
+  int n = mdi_desc->nhwbpt;
+
+  while (n > 0)
+    {
+      unsigned int cap = mdi_desc->hwbpt_cap[--n];
+      if (cap & MIPS_WATCHPOINT_W)
+	{
+	  CORE_ADDR align;
+
+	  /* Mask/range supports any length.  */
+	  if (cap & (MIPS_WATCHPOINT_MASK | MIPS_WATCHPOINT_RANGE))
+	    return 1;
+
+	  /* Watchpoint must fit into one watch register.  */
+	  /* XXX Could span several watchpoints but no MIPS cpu with
+	     more than one watchpoint doesn't have a mask reg.  */
+	  align = (cap & MIPS_WATCHPOINT_DWORD) ? 8 : 4;
+	  if ((addr & (align - 1)) + byte_count <= align)
+	    return 1;
+	}
+    }
+
+  return 0;
+}
+
+
+/* Check whether the hit read watchpoint overlaps with the
+   object spanned by VADDR and LEN.  (XXX assumes kseg0/1)  */
+
+int
+mdi_data_address_match (CORE_ADDR vaddr, int len)
+{
+  CORE_ADDR wpaddr;
+  int wplen;
+  CORE_ADDR abeg, aend;
+  CORE_ADDR bbeg, bend;
+  int res;
+
+  if ((mdi_curbpt.Type & MDIBPT_TypeMask) != MDIBPT_HWData)
+     return 0;
+
+  wpaddr = mdi_curbpt.Range.Start;
+  if (mdi_curbpt.Type & MDIBPT_HWFlg_AddrRange)
+    wplen = mdi_curbpt.Range.End - wpaddr;
+  else if (mdi_curbpt.Type & MDIBPT_HWFlg_AddrMask)
+    wplen = mdi_curbpt.Range.End + 1;
+  else
+    wplen = 8;
+
+  /* Check for physical address overlap.  */
+  abeg = mdi_kva2phys (wpaddr);
+  aend = abeg + wplen;
+  bbeg = mdi_kva2phys (vaddr);
+  bend = bbeg + len;
+  res = (abeg < bend && bbeg < aend);
+
+  if (remote_debug && res)
+    printf_unfiltered (_("Watchpoint match: W[0x%s,%d] D[0x%s,%d]\n"),
+		       paddr_nz (wpaddr), wplen,
+		       paddr_nz (vaddr), len);
+  return res;
+}
+#endif
+
+
+static int
+mdi_breakpoint_type_supported (MDIUint32 bptype)
+{
+  MDIInt32 howmany;
+  MDIBpInfoT *bpinfo;
+  MDIInt32 mdistat;
+  int i;
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    {
+      if (mdi_desc->gmdata[i].disabled)
+	return 0;
+
+      howmany = 0;
+
+      mdistat = mdiHwBpQuery (mdi_desc->gmdata[i].DevHandle, &howmany, NULL);
+      if (mdistat == MDIErrUnsupported)
+	{
+	  if (mdi_hwbpq_avail < 0)
+	    {
+	      warning
+		(_("Cannot query hardware breakpoint/watchpoint resources."));
+	      warning (_("Available functionality may be limited."));
+	      mdi_hwbpq_avail = 0;
+	    }
+	  return 0;
+	}
+      mdi_hwbpq_avail = 1;
+      if (mdistat != MDISuccess)
+	return -1;
+    }
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    {
+      int found = 0;
+      int j;
+
+      if (howmany > 0)
+	{
+	  bpinfo = alloca (howmany * sizeof (*bpinfo));
+	  mdistat = mdiHwBpQuery (mdi_desc->gmdata[i].DevHandle,
+				  &howmany, bpinfo);
+	  if (mdistat != MDISuccess)
+	    return -1;				/* Shouldn't happen.  */
+
+	  for (j = 0; j < howmany; j++)
+	    if ((bpinfo[j].Type & bptype) == bptype)
+	      {
+		found = 1;
+		break;
+	      }
+	}
+
+      if (!found)
+	return -1;
+    }
+
+  return 1;
+}
+
+static int
+mdi_can_use_hw_breakpoint (int type, int cnt, int othertype)
+{
+  MDIUint32 bptype = MDIBPT_HWType_Data;
+
+  switch (type)
+    {
+    case bp_hardware_breakpoint:
+      bptype = MDIBPT_HWType_Exec;
+      break;
+    case bp_hardware_watchpoint:
+      bptype = MDIBPT_HWFlg_DataWrite | MDIBPT_HWType_Data;
+      break;
+    case bp_read_watchpoint:
+      bptype = MDIBPT_HWFlg_DataRead | MDIBPT_HWType_Data;
+      break;
+    case bp_access_watchpoint:
+      bptype = MDIBPT_HWFlg_DataWrite | MDIBPT_HWFlg_DataRead
+	       | MDIBPT_HWType_Data;
+      break;
+    default:
+      return 0;
+    }
+
+  return mdi_breakpoint_type_supported (bptype) >= 0;
+}
+
+/* Find the widest mask that still spans the whole area specified.  */
+static MDIRangeT
+mdi_watchpoint_range_to_mask (MDIRangeT addrrange)
+{
+  MDIRangeT addrmask;
+  MDIOffsetT select = ~0;
+  MDIOffsetT mask, newmask;
+  int shift;
+
+  shift = sizeof (select) * 4;
+  select <<= shift;
+
+  mask = ((addrrange.Start ^ addrrange.End) << 1) + 1;
+  do
+    {
+      newmask = mask & select;
+      if (newmask)
+	mask = newmask;
+      shift >>= 1;
+      select ^= select >> shift;
+    }
+  while (shift);
+  mask = -mask;
+
+  addrmask.Start = addrrange.Start & mask;
+  addrmask.End = ~mask;
+
+  return addrmask;
+}
+
+/*  Convert a mask into a range.  */
+static MDIRangeT
+mdi_watchpoint_mask_to_range (MDIRangeT addrmask)
+{
+  MDIRangeT addrrange;
+
+  addrrange.Start = addrmask.Start;
+  addrrange.End = (addrmask.Start & addrmask.End) | ~addrmask.End;
+
+  return addrrange;
+}
+
+static int
+mdi_insert_hw_any (MDIHandleT devhandle, MDIBpDataT bp)
+{
+  MDIBpDataT bpcopy;
+  int maskok = 0, rangeok, needrange, usedmask = 0;
+  MDIRangeT bprange = bp.Range;
+  MDIRangeT bpmask = mdi_watchpoint_range_to_mask (bp.Range);
+  MDIRangeT bpdatarange;
+  MDIBpT bptype;
+  struct mdi_bpt *bpdata, **next;
+  MDIInt32 mdistat;
+
+  bptype = bp.Type & ~(MDIBpT)MDIBPT_TypeMask;
+  needrange = bprange.Start != bprange.End;
+  if (!needrange)
+    needrange == (mdi_breakpoint_type_supported (bptype) < 0);
+  if (needrange)
+    {
+      rangeok = mdi_breakpoint_type_supported (bptype
+					       | MDIBPT_HWFlg_AddrRange);
+      if (rangeok < 0)
+	{
+	  maskok = mdi_breakpoint_type_supported (bptype
+						  | MDIBPT_HWFlg_AddrMask);
+	  if (maskok < 0)
+	    return -1;
+	}
+    }
+  else
+    maskok = -1;
+
+  next = &mdi_bpts;
+  while (*next)
+    {
+      bpdata = *next;
+      bptype = bpdata->mdibp.Type & ~(MDIBpT)(MDIBPT_HWFlg_AddrMask
+					      | MDIBPT_HWFlg_AddrRange);
+
+      bpdatarange = bpdata->mdibp.Range;
+      if ((bpdata->mdibp.Type & MDIBPT_HWFlg_AddrMask) != 0)
+	bpdatarange = mdi_watchpoint_mask_to_range (bpdatarange);
+
+      if (bpdata->devhandle == devhandle
+	  && bptype == bp.Type
+	  && bpdata->mdibp.Resource == bp.Resource
+	  && bpdatarange.Start == bprange.Start
+	  && bpdata->mdibp.Enabled == 1)
+	{
+	  if (bpdatarange.End < bprange.End)
+	    {
+	      mdistat =
+		mdiClearBp (bpdata->devhandle, bpdata->mdibp.Id);
+	      if (mdistat != MDISuccess)
+		return -1;
+
+	      if ((bpdata->mdibp.Type & MDIBPT_HWFlg_AddrMask) != 0)
+		usedmask = 1;
+	      bpdata->mdibp.Enabled = ~0;
+	    }
+	  else
+	    bp.Enabled = ~0;
+	}
+
+      next = &(*next)->next;
+    }
+
+  bpdata = xmalloc (sizeof (*bpdata));
+  bpdata->next = NULL;
+  bpdata->devhandle = devhandle;
+
+  bpcopy = bp;
+  mdistat = MDIErrFailure;
+
+  if (!usedmask || maskok <= 0)
+    {
+      if (needrange)
+	bpcopy.Type |= MDIBPT_HWFlg_AddrRange;
+      else
+	bpcopy.Range.End = 0;
+      if (bpcopy.Enabled != ~0)
+	{
+	  mdistat = mdiSetBp (bpdata->devhandle, &bpcopy);
+	  if (mdistat != MDISuccess)
+	    bpcopy = bp;
+	}
+      else
+	mdistat = MDISuccess;
+    }
+
+  if (mdistat != MDISuccess && maskok >= 0)
+    {
+      bpcopy.Type |= MDIBPT_HWFlg_AddrMask;
+      bpcopy.Range = bpmask;
+      if (bpcopy.Enabled != ~0)
+	mdistat = mdiSetBp (bpdata->devhandle, &bpcopy);
+      else
+	mdistat = MDISuccess;
+    }
+
+  if (mdistat != MDISuccess)
+    {
+      xfree (bpdata);
+      return -1;
+    }
+
+  bpdata->mdibp = bpcopy;
+  *next = bpdata;
+
+  return 0;
+}
+
+static int
+mdi_remove_hw_any (MDIHandleT devhandle, MDIBpDataT bp)
+{
+  MDIRangeT bprange = bp.Range;
+  MDIRangeT bpmask = mdi_watchpoint_range_to_mask (bp.Range);
+  MDIBpT bptype;
+  struct mdi_bpt *bpdata, **next;
+  MDIInt32 mdistat;
+
+  next = &mdi_bpts;
+  while (*next)
+    {
+      bpdata = *next;
+      bptype = bpdata->mdibp.Type & ~(MDIBpT)(MDIBPT_HWFlg_AddrMask
+					      | MDIBPT_HWFlg_AddrRange);
+
+      if (bpdata->devhandle == devhandle
+	  && bptype == bp.Type
+	  && bpdata->mdibp.Resource == bp.Resource
+	  && (((bpdata->mdibp.Type & MDIBPT_HWFlg_AddrMask) != 0
+	       && bpdata->mdibp.Range.Start == bpmask.Start
+	       && bpdata->mdibp.Range.End == bpmask.End)
+	      || ((bpdata->mdibp.Type & MDIBPT_HWFlg_AddrRange) != 0
+	       && bpdata->mdibp.Range.Start == bprange.Start
+	       && bpdata->mdibp.Range.End == bprange.End)
+	      || ((bpdata->mdibp.Type
+		   & (MDIBPT_HWFlg_AddrMask | MDIBPT_HWFlg_AddrRange)) == 0
+	       && bpdata->mdibp.Range.Start == bprange.Start)))
+	{
+	  if (bpdata->mdibp.Enabled != ~0)
+	    {
+	      mdistat =
+		mdiClearBp (bpdata->devhandle, bpdata->mdibp.Id);
+	      if (mdistat != MDISuccess)
+		return -1;
+	    }
+
+	  *next = bpdata->next;
+	  xfree (bpdata);
+
+	  return 0;
+	}
+      next = &(*next)->next;
+    }
+
+  return -1;
+}
+
+
+static MDIBpDataT
+mdi_setup_hw_breakpoint (CORE_ADDR addr)
+{
+  MDIBpDataT bp;
+
+  memset (&bp, 0, sizeof (bp));
+  bp.Type = MDIBPT_HWInstruction;
+  bp.Enabled = 1;
+  bp.Resource = mdi_memresource (addr);
+  bp.Range.Start = mdi_memoffset (addr);
+  bp.Range.End = mdi_memoffset (addr);
+  bp.PassCount = 1;
+
+  return bp;
+}
+
+static int
+mdi_insert_hw_breakpoint (struct bp_target_info *bp_tgt)
+{
+  CORE_ADDR addr = bp_tgt->placed_address;
+  MDIBpDataT bp;
+  int i;
+
+  bp = mdi_setup_hw_breakpoint (addr);
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    if (!mdi_desc->gmdata[i].disabled)
+      if (mdi_insert_hw_any (mdi_desc->gmdata[i].DevHandle, bp) < 0)
+	{
+	  for (i--; i >= 0; i--)
+	    if (!mdi_desc->gmdata[i].disabled)
+	      mdi_remove_hw_any (mdi_desc->gmdata[i].DevHandle, bp);
+	  return -1;
+	}
+
+  return 0;
+}
+
+static int
+mdi_remove_hw_breakpoint (struct bp_target_info *bp_tgt)
+{
+  CORE_ADDR addr = bp_tgt->placed_address;
+  MDIBpDataT bp;
+  int i, result = 0;
+
+  bp = mdi_setup_hw_breakpoint (addr);
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    if (!mdi_desc->gmdata[i].disabled)
+      if (mdi_remove_hw_any (mdi_desc->gmdata[i].DevHandle, bp) < 0)
+	result = -1;
+
+  return result;
+}
+
+
+static MDIBpDataT
+mdi_setup_watchpoint (CORE_ADDR addr, int len, int type)
+{
+  MDIBpDataT bp;
+
+  memset (&bp, 0, sizeof (bp));
+  bp.Type = MDIBPT_HWData;
+  bp.Enabled = 1;
+  bp.Resource = mdi_memresource (addr);
+  bp.PassCount = 1;
+
+  switch (type)
+    {
+    case 0:
+      bp.Type |= MDIBPT_HWFlg_DataWrite;
+      break;
+    case 1:
+      bp.Type |= MDIBPT_HWFlg_DataRead;
+      break;
+    case 2:
+    default:
+      bp.Type |= MDIBPT_HWFlg_DataWrite | MDIBPT_HWFlg_DataRead;
+      break;
+    }
+
+  bp.Range.Start = mdi_memoffset (addr);
+  bp.Range.End = mdi_memoffset (addr) + len - 1;
+
+  return bp;
+}
+
+static int
+mdi_insert_watchpoint (CORE_ADDR addr, int len, int type)
+{
+  MDIBpDataT bp;
+  int i;
+
+  bp = mdi_setup_watchpoint (addr, len, type);
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    if (!mdi_desc->gmdata[i].disabled)
+      if (mdi_insert_hw_any (mdi_desc->gmdata[i].DevHandle, bp) < 0)
+	{
+	  for (i--; i >= 0; i--)
+	    if (!mdi_desc->gmdata[i].disabled)
+	      mdi_remove_hw_any (mdi_desc->gmdata[i].DevHandle, bp);
+	  return -1;
+	}
+
+  return 0;
+}
+
+static int
+mdi_remove_watchpoint (CORE_ADDR addr, int len, int type)
+{
+  MDIBpDataT bp;
+  int i, result = 0;
+
+  bp = mdi_setup_watchpoint (addr, len, type);
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    if (!mdi_desc->gmdata[i].disabled)
+      if (mdi_remove_hw_any (mdi_desc->gmdata[i].DevHandle, bp) < 0)
+	result = -1;
+
+  return result;
+}
+
+
+static int
+mdi_stopped_by_watchpoint (void)
+{
+  return ((mdi_curbpt.Type & MDIBPT_TypeMask) == MDIBPT_HWData);
+}
+
+static int
+mdi_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
+{
+  int rc = 0;
+
+  if (mdi_stopped_by_watchpoint())
+    {
+      *addr_p = mdi_memaddr (mdi_curbpt.Range.Start);
+      rc = 1;
+    }
+
+  return rc;
+}
+
+
+static void
+mdi_rcmd (char *command, struct ui_file *outbuf)
+{
+  MDIInt32 mdistat;
+
+  if (command == NULL)
+    return;
+
+  check_mdi ();
+
+  mdistat = mdiDoCommand (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+			  command);
+  if (mdistat == MDIErrUnsupported)
+    error (_("MDI library does not recognise this command"));
+  else
+    MDIERR (mdistat, "DoCommand");
+}
+
+
+static void
+mdi_log_command (const char *cmd)
+{
+  if (mdi_logging)
+    {
+      fprintf_unfiltered (mdi_logfp, "(gdb) %s\n", cmd);
+
+      /* Make sure that the log file is as up-to-date as possible,
+         in case we are getting ready to dump core or something.  */
+      gdb_flush (mdi_logfp);
+    }
+
+  if (mdi_logdocommand && *mdi_logdocommand)
+    {
+      char *logcmd, *p;
+      int loglen;
+
+      loglen = strlen (mdi_logdocommand);
+      p = strstr (mdi_logdocommand, "%s");
+      if (p)
+	loglen += strlen (cmd) - (sizeof ("%s") - 1);
+      logcmd = alloca (loglen + 1);
+
+      if (p)
+	{
+	  memcpy (logcmd, mdi_logdocommand, p - mdi_logdocommand);
+	  memcpy (logcmd + (p - mdi_logdocommand), cmd, strlen (cmd));
+	  memcpy (logcmd + (p - mdi_logdocommand) + strlen (cmd),
+		  p + (sizeof ("%s") - 1),
+		  strlen (mdi_logdocommand) - (p - mdi_logdocommand) + 1);
+	}
+      else
+	strcpy (logcmd, mdi_logdocommand);
+
+      mdiDoCommand (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle, logcmd);
+    }
+}
+
+static void
+set_asid_command (char *args, int from_tty)
+{
+  unsigned long n;
+
+  if (args == NULL || *args == '\0')
+    error (_("Usage: set mdi asid on|off|ASID"));
+  if (strcasecmp (args, "off") == 0)
+    mdi_asidtype = ASIDNone;
+  else if (strcasecmp (args, "on") == 0)
+    mdi_asidtype = ASIDReg;
+  else if (strcasecmp (args, "auto") == 0)
+    mdi_asidtype = ASIDAuto;
+  else
+    {
+      char *tail;
+      n = strtoul (args, &tail, 0);
+      for (; *tail && isspace (*tail); tail++)
+	continue;
+      if (*tail || n > 256)
+	error (_("ASID out of range: %s"), args);
+      mdi_asidtype = ASIDFixed;
+      mdi_asid = n;
+    }
+}
+
+static void
+show_asid_command (char *args, int from_tty)
+{
+  switch (mdi_asidtype)
+    {
+    case ASIDNone:
+      printf_filtered ("off\n");
+      break;
+    case ASIDReg:
+      printf_filtered ("on\n");
+      break;
+    case ASIDAuto:
+      printf_filtered ("auto\n");
+      break;
+    case ASIDFixed:
+      printf_filtered ("%d\n", mdi_asid);
+      break;
+    }
+}
+
+static void
+set_connectreset_command (char *args, int from_tty)
+{
+  unsigned long n;
+
+  if (args == NULL || *args == '\0')
+    error (_("Usage: set mdi connectreset on|off|SECS"));
+  if (strcasecmp (args, "off") == 0)
+    mdi_connectreset = -1;
+  else if (strcasecmp (args, "on") == 0)
+    mdi_connectreset = 0;
+  else
+    {
+      char *tail;
+      n = strtoul (args, &tail, 0);
+      for (; *tail && isspace (*tail); tail++)
+	continue;
+      if (*tail || n > 60)
+	error (_("SECS out of range: %s"), args);
+      mdi_connectreset = n;
+    }
+}
+
+static void
+show_connectreset_command (char *args, int from_tty)
+{
+  if (mdi_connectreset < 0)
+    {
+      printf_filtered ("off\n");
+    }
+  else if (mdi_connectreset == 0)
+    {
+      printf_filtered ("on\n");
+    }
+  else
+    {
+      printf_filtered ("%d\n", mdi_connectreset);
+    }
+}
+
+
+static struct cmd_list_element *mditeamlist = NULL;
+
+static void
+mdi_team_status (MDIInt32 mdistat)
+{
+  switch (mdistat)
+    {
+    case MDISuccess:
+      break;
+    case MDIErrTeamId:
+      error (_("No such MDI team."));
+      break;
+    case MDIErrUnsupported:
+      error (_("MDI teams unsupported."));
+      break;
+    default:
+      error (_("MDI team operation failure."));
+      break;
+    }
+}
+
+static void
+mdi_tm_status (MDIInt32 mdistat, MDITGIdT target, MDIDeviceIdT device)
+{
+  switch (mdistat)
+    {
+    case MDISuccess:
+      break;
+    case MDIErrAlreadyMember:
+      printf_filtered (_("Device %d:%d already a member.\n"), target, device);
+      break;
+    case MDIErrNotMember:
+      printf_filtered (_("Device %d:%d not a member.\n"), target, device);
+      break;
+    case MDIErrTeamId:
+      error (_("No such MDI team."));
+      break;
+    case MDIErrUnsupported:
+      error (_("MDI teams unsupported."));
+      break;
+    default:
+      error (_("MDI team member operation failure."));
+      break;
+    }
+}
+
+static void
+mdi_team_command (char *args, int from_tty)
+{
+  unsigned long n;
+  char *tail;
+
+  if (args)
+    {
+      n = strtoul (args, &tail, 0);
+      for (; *tail && isspace (*tail); tail++)
+	continue;
+      if (*tail)
+	error (_("Junk at end of command."));
+      mdi_team = n;
+    }
+  else
+    printf_filtered (_("MDI team number is %d.\n"), mdi_team);
+}
+
+static void
+mdi_team_attach_command (char *args, int from_tty)
+{
+  unsigned long tm_device, tm_target;
+  struct mdi_tm_data_list *tmdatalist = NULL, **listp = &tmdatalist;
+  char *argscopy, *p;
+  MDIInt32 mdistat;
+
+  if (args)
+    {
+      check_mdi ();
+
+      argscopy = alloca (strlen (args) + 1);
+      strcpy (argscopy, args);
+      for (p = strtok (argscopy, " \t"); p; p = strtok (NULL, " \t"))
+	{
+	  if (isdigit (*p))
+	    {
+	      tm_target = mdi_target;
+	      tm_device = strtoul (p, &p, 0);
+	      if (*p == ':' && isdigit (p[1]))
+		{
+		  tm_target = tm_device;
+		  tm_device = strtoul (p + 1, &p, 0);
+		}
+	      if (*p)
+		error (_("Bad [TARGET:]DEVICE number."));
+
+	      *listp = alloca (sizeof (**listp));
+	      (*listp)->next = NULL;
+	      (*listp)->tmdata.MDIHandle = mdi_desc->MDIHandle;
+	      (*listp)->tmdata.TGId = tm_target - 1;
+	      (*listp)->tmdata.DevId = tm_device - 1;
+	      listp = &(*listp)->next;
+	    }
+	  else
+	    error (_("Junk at end of command."));
+	}
+
+      if (mdi_team <= 0)
+	{
+	  mdistat = mdiTeamCreate (mdi_desc->MDIHandle, &mdi_team);
+	  if (mdistat != MDISuccess)
+	    {
+	      mdi_team = 0;
+	      mdi_team_status (mdistat);
+	    }
+	  mdi_team += 1;
+	}
+
+      for (listp = &tmdatalist; *listp; listp = &(*listp)->next)
+	{
+	  mdistat = mdiTMAttach (mdi_desc->MDIHandle, mdi_team - 1,
+				 &(*listp)->tmdata);
+	  mdi_tm_status (mdistat, (*listp)->tmdata.TGId + 1,
+			 (*listp)->tmdata.DevId + 1);
+	}
+    }
+  else
+    error (_("Argument required."));
+}
+
+static void
+mdi_team_clear_command (char *args, int from_tty)
+{
+  MDIInt32 mdistat;
+
+  if (args)
+    error (_("Junk at end of command."));
+
+  check_mdi ();
+
+  if (mdi_team <= 0)
+    error (_("No MDI team selected."));
+
+  mdistat = mdiTeamClear (mdi_desc->MDIHandle, mdi_team - 1);
+  mdi_team_status (mdistat);
+  mdistat = mdiTeamDestroy (mdi_desc->MDIHandle, mdi_team - 1);
+  mdi_team_status (mdistat);
+  mdi_team = 0;
+}
+
+static void
+mdi_team_detach_command (char *args, int from_tty)
+{
+  unsigned long tm_device, tm_target;
+  struct mdi_tm_data_list *tmdatalist = NULL, **listp = &tmdatalist;
+  char *argscopy, *p;
+  MDIInt32 mdistat;
+
+  if (args)
+    {
+      check_mdi ();
+
+      if (mdi_team <= 0)
+	error (_("No MDI team selected."));
+
+      argscopy = alloca (strlen (args) + 1);
+      strcpy (argscopy, args);
+      for (p = strtok (argscopy, " \t"); p; p = strtok (NULL, " \t"))
+	{
+	  if (isdigit (*p))
+	    {
+	      tm_target = mdi_target;
+	      tm_device = strtoul (p, &p, 0);
+	      if (*p == ':' && isdigit (p[1]))
+		{
+		  tm_target = tm_device;
+		  tm_device = strtoul (p + 1, &p, 0);
+		}
+	      if (*p)
+		error (_("Bad [TARGET:]DEVICE number."));
+
+	      *listp = alloca (sizeof (**listp));
+	      (*listp)->next = NULL;
+	      (*listp)->tmdata.MDIHandle = mdi_desc->MDIHandle;
+	      (*listp)->tmdata.TGId = tm_target - 1;
+	      (*listp)->tmdata.DevId = tm_device - 1;
+	      listp = &(*listp)->next;
+	    }
+	  else
+	    error (_("Junk at end of command."));
+	}
+
+      for (listp = &tmdatalist; *listp; listp = &(*listp)->next)
+	{
+	  mdistat = mdiTMDetach (mdi_desc->MDIHandle, mdi_team - 1,
+				 &(*listp)->tmdata);
+	  mdi_tm_status (mdistat, (*listp)->tmdata.TGId + 1,
+			 (*listp)->tmdata.DevId + 1);
+	}
+    }
+  else
+    error (_("Argument required."));
+}
+
+static void
+mdi_team_list_command (char *args, int from_tty)
+{
+  MDIInt32 mdistat;
+  MDIInt32 nteamids = 0;
+  MDIInt32 ntms;
+  MDITeamIdT *teamid;
+  MDITMDataT *tmdata;
+  int i, j;
+
+  if (args)
+    error (_("Junk at end of command."));
+
+  check_mdi ();
+
+  mdistat = mdiQueryTeams (mdi_desc->MDIHandle, &nteamids, NULL);
+  if (mdistat != MDISuccess || nteamids <= 0)
+    return;
+
+  teamid = alloca (nteamids * sizeof (*teamid));
+  mdistat = mdiQueryTeams (mdi_desc->MDIHandle, &nteamids, teamid);
+  if (mdistat != MDISuccess)
+    return;					/* Shouldn't happen.  */
+
+  for (i = 0; i < nteamids; i++)
+    {
+      ntms = 0;
+      mdistat = mdiQueryTM (mdi_desc->MDIHandle, teamid[i], &ntms, NULL);
+      if (mdistat != MDISuccess)
+	continue;				/* Shouldn't happen.  */
+
+      tmdata = xmalloc (ntms * sizeof (*tmdata));
+      mdistat = mdiQueryTM (mdi_desc->MDIHandle, teamid[i], &ntms, tmdata);
+
+      if (mdistat == MDISuccess)
+	{
+	  /* Got a team member list - output it.  */
+	  if (from_tty)
+	    printf_filtered (_("Team %02d:\n"), teamid[i] + 1);
+
+	  for (j = 0; j < ntms; j++)
+	      /* Output in human readable form if from_tty, else
+		 in machine readable form for GDBTK.  */
+	      if (from_tty)
+		printf_filtered (_("    Dev %02d:%02d\n"),
+				 tmdata[j].TGId + 1,
+				 tmdata[j].DevId + 1);
+	      else
+		printf_filtered ("%d|%d:%d\n",
+				 teamid[i] + 1,
+				 tmdata[j].TGId + 1,
+				 tmdata[j].DevId + 1);
+	}
+
+      xfree (tmdata);
+    }
+}
+
+
+static void
+mdi_reset_command (char *arg, int from_tty)
+{
+  MDIInt32 mdistat;
+  MDIUint32 flag = MDIFullReset;
+  int i;
+
+  if (arg != NULL && *arg != '\0')
+    {
+      if (strcasecmp (arg, "full") == 0)
+	flag = MDIFullReset;
+      else if (strcasecmp (arg, "device") == 0)
+	flag = MDIDeviceReset;
+      else if (strcasecmp (arg, "cpu") == 0)
+	flag = MDICPUReset;
+      else if (strcasecmp (arg, "periph") == 0)
+	flag = MDIPeripheralReset;
+      else
+	error (_("Usage: mdi reset [full | device | cpu | periph]"));
+    }
+
+  check_mdi ();
+
+  mdistat = mdiReset (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle, flag);
+  for (i = 0; i < mdi_desc->gmcount; i++)
+      (void) mdiStop (mdi_desc->gmdata[i].DevHandle);
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    {
+      MDIRunStateT runstate;
+
+      mdi_desc->gmdata[i].disabled = 1;
+      mdistat = mdiRunState (mdi_desc->gmdata[i].DevHandle, 100, &runstate);
+      if (mdistat != MDISuccess)
+	continue;
+
+      if (runstate.Status != MDIStatusDisabled
+	  && runstate.Status != MDIStatusVPEDisabled)
+	mdi_desc->gmdata[i].disabled = 0;
+    }
+
+  /* Note that the inferior is no longer running.  */
+  target_mourn_inferior ();
+
+  /* Reconnect to target. */
+  mdi_set_inferior_ptid ();
+  mdi_exited = mdi_signalled = 0;
+
+  reinit_frame_cache ();
+
+  togdb_force_update ();
+
+  MDIERR (mdistat, _("resetting device"));
+}
+
+static void
+mdi_regsync_command (char *arg, int from_tty)
+{
+  MDIInt32 mdistat;
+
+  if (arg && *arg)
+    error (_("Usage: mdi regsync"));
+
+  check_mdi ();
+
+  /* mdi_store_register (-1); */
+  registers_changed ();
+  togdb_force_update ();
+}
+
+
+/* MDI cacheflush command.  */
+
+static void
+mdi_cacheflush_command (char *arg, int from_tty)
+{
+  MDIInt32 mdistat;
+  int i;
+
+  if (arg && *arg)
+    error (_("Usage: mdi cacheflush"));
+
+  check_mdi ();
+
+  /* Writeback and invalidate all caches.  */
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    if (!mdi_desc->gmdata[i].disabled)
+      {
+	mdiCacheFlush (mdi_desc->gmdata[i].DevHandle, MDICacheTypeData,
+		       MDICacheWriteBack | MDICacheInvalidate);
+	mdiCacheFlush (mdi_desc->gmdata[i].DevHandle, MDICacheTypeUnified,
+		       MDICacheWriteBack | MDICacheInvalidate);
+	mdiCacheFlush (mdi_desc->gmdata[i].DevHandle, MDICacheTypeInstruction,
+		       MDICacheInvalidate);
+      }
+}
+
+
+
+
+static struct cmd_list_element *mdicycleslist = NULL;
+
+
+/* Enable MIPSsim cycle counting, return 1 on success.
+   Can be called via catch_errors to prevent fatal error.  */
+
+static int
+mdi_cycles_enable (PTR dummy)
+{
+  static int cycle_failure = 0;
+  int i;
+
+  if (! mdi_desc->mipssim_p)
+    error (_("Cycle counting only available with MIPSsim"));
+  if (! MIPSsim_SetTraceLevel)
+    error (_("Cycle counting not supported on this version of MIPSsim"));
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    {
+      int tracelev = 0;
+      (void) MIPSsim_GetTraceLevel (mdi_desc->gmdata[i].DevHandle, &tracelev);
+      if (! (tracelev & 1))
+	{
+	  if (MIPSsim_SetTraceLevel (mdi_desc->gmdata[i].DevHandle,
+				     tracelev | 1)
+	      != MDISuccess)
+	    cycle_failure = 1;
+	  else {
+	    int newlev = 0;
+	    (void) MIPSsim_GetTraceLevel (mdi_desc->gmdata[i].DevHandle,
+					  &newlev);
+	    if (! (newlev & 1))
+	      cycle_failure = 1;
+	  }
+	  if (dummy)
+	    /* reset to previous trace level */
+	    (void) MIPSsim_SetTraceLevel (mdi_desc->gmdata[i].DevHandle,
+					  tracelev);
+
+	}
+    }
+  if (cycle_failure)
+    error (_("Cycle counting not available"));
+  return 1;
+}
+
+/* Set $cycles variable to current MIPSsim cycle counter.  */
+static void
+mdi_cycles_update (void)
+{
+  MDIUint64 cycles = 0, allcycles = 0;
+  MDIInt32 stat;
+  int i;
+
+  for (i = 0; i < mdi_desc->gmcount; i++)
+    {
+      if (MIPSsim_GetPerfCounter)
+	stat = MIPSsim_GetPerfCounter (mdi_desc->gmdata[i].DevHandle,
+				       MIPS_E_PerfCntMode_ALL,
+				       MIPS_PerfCntSel_Cycles0,
+				       MIPS_PerfCntInd_Cycles0, &cycles);
+      else if (MIPSsim_GetStats)
+	stat = MIPSsim_GetStats (mdi_desc->gmdata[i].DevHandle,
+				 MIPS_MDI_PerfCycles, &cycles);
+      else
+	stat = MDINotFound;
+
+      if (stat != MDISuccess)
+	return;
+
+      allcycles += cycles;
+    }
+
+  set_internalvar (lookup_internalvar ("cycles"),
+		   value_from_longest (builtin_type_uint64,
+				       (LONGEST) allcycles));
+}
+
+static void
+mdi_cycles_enable_command (char *args, int from_tty)
+{
+  check_mdi ();
+  mdi_cycles_enable (NULL);
+  mdi_cycles_update ();
+}
+
+static void
+mdi_cycles_disable_command (char *args, int from_tty)
+{
+  check_mdi ();
+  if (mdi_desc->mipssim_p && MIPSsim_SetTraceLevel)
+    {
+      int tracelev, i;
+
+      for (i = 0; i < mdi_desc->gmcount; i++)
+	{
+	  (void) MIPSsim_GetTraceLevel (mdi_desc->gmdata[i].DevHandle,
+					&tracelev);
+	  if (tracelev & 1)
+	    (void) MIPSsim_SetTraceLevel (mdi_desc->gmdata[i].DevHandle,
+					  tracelev & ~1);
+	}
+    }
+}
+
+static void
+mdi_cycles_clear_command (char *args, int from_tty)
+{
+  check_mdi ();
+
+  /* Clear cycle counter.  */
+  if (mdi_desc->mipssim_p)
+    {
+      int i;
+
+      for (i = 0; i < mdi_desc->gmcount; i++)
+	if (MIPSsim_ZeroPerfCounter)
+	  MIPSsim_ZeroPerfCounter (mdi_desc->gmdata[i].DevHandle,
+				   MIPS_E_PerfCntMode_ALL,
+				   MIPS_PerfCntSel_Cycles0,
+				   MIPS_PerfCntInd_Cycles0);
+	else if (MIPSsim_ClearStats)
+	  MIPSsim_ClearStats (mdi_desc->gmdata[i].DevHandle,
+			      MIPS_MDI_PerfCycles);
+    }
+
+  /* Enable cycle counting and set $cycles.  */
+  mdi_cycles_enable_command (args, from_tty);
+}
+
+static void
+mdi_cycles_status_command (char *args, int from_tty)
+{
+  int tracelev;
+
+  check_mdi ();
+
+  /* Passing a non-zero argument causes the tracelevel to be reset
+     after checking that it is possible to enable it.  */
+  mdi_cycles_enable ((PTR)1);
+
+  (void) MIPSsim_GetTraceLevel (mdi_desc->gmdata[mdi_desc->gmindex].DevHandle,
+				&tracelev);
+  fprintf_filtered (gdb_stdout, _("Cycle counting: %s\n"),
+		    (tracelev & 1) ? _("enabled") : _("disabled"));
+}
+
+static void
+mdi_cycles_command (char *args, int from_tty)
+{
+  printf_unfiltered (_("\
+\"mdi cycles\" must be followed by \"enable\", \"disable\", \"clear\" or \
+\"status\".\n"));
+  mdi_cycles_status_command (args, from_tty);
+}
+
+
+
+static void
+set_mdi_threadviewinactive (char *args, int from_tty,
+			    struct cmd_list_element *c)
+{
+  mdi_find_new_threads ();
+}
+
+static void
+show_mdi_threadviewinactive (struct ui_file *file, int from_tty,
+			     struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("View inactive threads is %s.\n"), value);
+}
+
+/* Root of all "mdi "/"set mdi "/"show mdi " commands.
+   This will eventually be used for all MDI specific commands.  */
+
+static void
+mdi_command (char *args, int from_tty)
+{
+  help_list (mdicmdlist, "mdi ", all_commands, gdb_stdout);
+}
+
+static void
+show_mdi_command (char *args, int from_tty)
+{
+  help_list (showmdicmdlist, "show mdi ", all_commands, gdb_stdout);
+}
+
+static void
+set_mdi_command (char *args, int from_tty)
+{
+  printf_unfiltered (_("\
+\"set mdi\" must be followed by an appropriate subcommand.\n"));
+  help_list (setmdicmdlist, "set mdi ", all_commands, gdb_stdout);
+}
+
+
+static void
+init_mdi_ops (void)
+{
+  mdi_ops.to_shortname = "mdi";
+  mdi_ops.to_longname = "MIPS Debug Interface";
+  mdi_ops.to_doc = _("Use MDI to access MIPS targets");
+  mdi_ops.to_open = mdi_open;
+  mdi_ops.to_close = mdi_close;
+  mdi_ops.to_attach = mdi_attach;
+  mdi_ops.to_detach = mdi_detach;
+  mdi_ops.to_disconnect = mdi_disconnect;
+  mdi_ops.to_resume = mdi_resume;
+  mdi_ops.to_wait = mdi_wait;
+  mdi_ops.to_fetch_registers = mdi_fetch_register;
+  mdi_ops.to_store_registers = mdi_store_register;
+  mdi_ops.to_prepare_to_store = mdi_prepare_to_store;
+  mdi_ops.deprecated_xfer_memory = mdi_xfer_memory;
+  mdi_ops.to_files_info = mdi_files_info;
+  mdi_ops.to_insert_breakpoint = mdi_insert_breakpoint;
+  mdi_ops.to_remove_breakpoint = mdi_remove_breakpoint;
+  mdi_ops.to_can_use_hw_breakpoint = mdi_can_use_hw_breakpoint;
+  mdi_ops.to_insert_hw_breakpoint = mdi_insert_hw_breakpoint;
+  mdi_ops.to_remove_hw_breakpoint = mdi_remove_hw_breakpoint;
+  mdi_ops.to_insert_watchpoint = mdi_insert_watchpoint;
+  mdi_ops.to_remove_watchpoint = mdi_remove_watchpoint;
+  mdi_ops.to_stopped_by_watchpoint = mdi_stopped_by_watchpoint;
+  mdi_ops.to_have_continuable_watchpoint = 0;
+  mdi_ops.to_stopped_data_address = mdi_stopped_data_address;
+#ifdef notyet
+  mdi_ops.to_region_size_ok_for_hw_watchpoint =
+    mdi_region_size_ok_for_hw_watchpoint;
+#endif
+  mdi_ops.to_kill = mdi_kill;
+  mdi_ops.to_load = mdi_load;
+  mdi_ops.to_create_inferior = mdi_create_inferior;
+  mdi_ops.to_mourn_inferior = mdi_mourn_inferior;
+  mdi_ops.to_thread_alive = mdi_thread_alive;
+  mdi_ops.to_find_new_threads = mdi_find_new_threads;
+  mdi_ops.to_pid_to_str = mdi_pid_to_str;
+  mdi_ops.to_stop = 0; /* XXX */
+  mdi_ops.to_rcmd = mdi_rcmd;
+  mdi_ops.to_log_command = mdi_log_command;
+  mdi_ops.to_stratum = process_stratum;
+  mdi_ops.to_has_all_memory = 1;
+  mdi_ops.to_has_memory = 1;
+  mdi_ops.to_has_stack = 1;
+  mdi_ops.to_has_registers = 1;
+  mdi_ops.to_has_execution = 1;
+  mdi_ops.to_has_thread_control = tc_schedlock;	/* Can we lock scheduler??  */
+  mdi_ops.to_magic = OPS_MAGIC;			/* Always the last thing.  */
+}				/* init_mdi_ops */
+
+
+static void
+mdi_getenv_number (const char *env, int *resp, int min, int max)
+{
+  char *s;
+  if ((s = getenv (env)) != NULL)
+    {
+      char *tail;
+      long val;
+      val = strtol (s, &tail, 0);
+      if (val >= min && val <= max && !*tail)
+	*resp = val;
+      else
+	warning (_("Bad environment variable: %s=%s ignored"), env, s);
+    }
+}
+
+
+void
+_initialize_remote_mdi (void)
+{
+  struct cmd_list_element *c;
+  char *s;
+
+  init_mdi_ops ();
+  add_target (&mdi_ops);
+
+  /* Default MDI log message stream.  */
+  mdi_logfp = gdb_stdlog;
+
+  /* We need a fake non-null ptid to indicate the target is connected
+     and running.  */
+  mdi_ptid = pid_to_ptid (42000);
+
+  /* Pick up useful "global" settings from environment. */
+  if ((s = getenv ("GDBMDILIB")) != NULL)
+    mdi_library = xstrdup (s);
+  if ((s = getenv ("GDBMIPSSIMCONFIG")) != NULL)
+    mdi_configfile = xstrdup (s);
+  if ((s = getenv ("GDBMIPSSIMDEVCFG")) != NULL)
+    mdi_devcfgfile = xstrdup (s);
+  mdi_getenv_number ("GDBMDITARGET", &mdi_target, 1, 99);
+  mdi_getenv_number ("GDBMDIDEVICE", &mdi_device, 1, 99);
+  mdi_getenv_number ("GDBMDICONNRST", &mdi_connectreset, -1, 99);
+
+  mdi_ftext_syms = xstrdup ("_ftext");
+  mdi_etext_syms = xstrdup ("_ecode _etext");
+  mdi_mcount_syms = xstrdup ("_mcount __mcount");
+
+  add_prefix_cmd ("mdi", no_class, set_mdi_command,
+		  _("Various MDI specific commands."),
+		  &setmdicmdlist, "set mdi ", 0, &setlist);
+  add_prefix_cmd ("mdi", no_class, show_mdi_command,
+		  _("Various MDI specific commands."),
+		  &showmdicmdlist, "show mdi ", 0, &showlist);
+
+  add_setshow_boolean_cmd ("stepinto", no_class,
+			   &mdi_stepinto, _("\
+Set MDI step-into mode."), _("\
+Show MDI step-into mode."), _("\
+When on, trap handlers can be stepped through."),
+			   NULL,
+			   show_mdi_stepinto,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_boolean_cmd ("threadstepall", no_class,
+			   &mdi_threadstepall, _("\
+Set simultaneous thread stepping mode."), _("\
+Show simultaneous thread stepping mode."), _("\
+When on, all threads are stepped together with the scheduler locking\n\
+mode enabled, otherwise single-stepping only enables execution in the\n\
+selected thread."),
+			   NULL,
+			   show_mdi_threadstepall,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_uinteger_cmd ("connecttimeout", no_class,
+			    &mdi_connecttimeout, _("\
+Set MDI connect timeout."), _("\
+Show MDI connect timeout."), _("\
+The number of seconds that the target is waited to halt in a response\n\
+to such a request when a new connection has been made."),
+			   NULL,
+			   show_mdi_connecttimeout,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_boolean_cmd ("continueonclose", no_class,
+			   &mdi_continueonclose, _("\
+Set continue on MDI close mode."), _("\
+Show continue on MDI close mode."), _("\
+When on, the target will be restarted before detaching."),
+			   NULL,
+			   show_mdi_continueonclose,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_boolean_cmd ("rununcached", no_class,
+			   &mdi_rununcached, _("\
+Set program starts uncached."), _("\
+Show program starts uncached."), _("\
+When on, the loaded program's entrypoint address will be forced to\n\
+an uncached MIPS segment, even if linked to a cacheable address."),
+			   NULL,
+			   show_mdi_rununcached,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_boolean_cmd ("threadviewinactive", no_class,
+			   &mdi_threadviewinactive, _("\
+Set view inactive threads."), _("\
+Show view inactive threads."), _("\
+When on, all threads are always visible, otherwise only ones that\n\
+are activated and unhalted."),
+			   &set_mdi_threadviewinactive,
+			   &show_mdi_threadviewinactive,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_zinteger_cmd ("waittime", no_class,
+			    &mdi_waittime, _("\
+Set MDI poll period."), _("\
+Show MDI poll period."), _("\
+The number of milliseconds that the target is allowed to run for\n\
+between gdb status polls.  Note that some MDI implementations do\n\
+not have accurate time keeping."),
+			   NULL,
+			   show_mdi_waittime,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_boolean_cmd ("releaseonclose", no_class,
+			   &mdi_releaseonclose, _("\
+Set MDI release on close."), _("\
+Show MDI release on close."), _("\
+When on, the MDI library is released when the target is closed."),
+			   NULL,
+			   show_mdi_releaseonclose,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_filename_cmd ("logfile", no_class,
+			    &mdi_logfile, _("\
+Set MDI session log file."), _("\
+Show MDI session log file."), _("\
+The file to receive the MDI session debug log when \"debug remote\"\n\
+has been set."),
+			    NULL,
+			    show_mdi_logfile,
+			    &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_string_cmd ("logdocommand", no_class,
+			   &mdi_logdocommand, _("\
+Set the remote command for logging gdb commands."), _("\
+Show the remote command for logging gdb commands."), _("\
+A textual command to be passed to the MDI target for logging gdb commands.\n\
+The gdb command is supplied in place of %s if present in the string,\n\
+otherwise the string is passed as is."),
+			   NULL,
+			   show_mdi_logdocommand,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_filename_cmd ("library", no_class,
+			   &mdi_library, _("\
+Set MDI interface library."), _("\
+Show MDI interface library."), _("\
+The name of the dynamically loaded MDI interface library."),
+			   NULL,
+			   show_mdi_library,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_filename_cmd ("configfile", no_class,
+			   &mdi_configfile, _("\
+Set MIPSsim config file name."), _("\
+Show MIPSsim config file name."), _("\
+The name of the configuration file to be loaded by MIPSsim.\n\
+This can also be set by the GDBMIPSSIMCONFIG environment variable.\n\
+If neither is set then GDB will auto-generate a configuration file."),
+			   NULL,
+			   show_mdi_configfile,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_filename_cmd ("devcfgfile", no_class,
+			   &mdi_devcfgfile, _("\
+Set MIPSsim device config file name."), _("\
+Show MIPSsim device config file name."), _("\
+The name of the device configuration file which will be added to GDB's\n\
+auto-generated MIPSsim CPU config file.\n\
+This can also be set by the GDBMIPSSIMDEVCFG environment variable."),
+			   NULL,
+			   show_mdi_devcfgfile,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  mdi_gmonfile = xstrdup ("gmon.out");
+  add_setshow_filename_cmd ("gmonfile", no_class,
+			   &mdi_gmonfile, _("\
+Set MIPSsim gmon profile output file name."), _("\
+Show MIPSsim gmon profile output file name."), _("\
+The name of the file in which to store gmon profiling data, \
+for use by gprof. Currently only supported by the MIPSsim target."),
+			    NULL,
+			    show_mdi_gmonfile,
+			    &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_auto_boolean_cmd ("profile", no_class,
+				&mdi_profiling, _("\
+Set MIPSsim profiling."), _("\
+Show MIPSsim profiling."), _("\
+When on, GDB will collect profiling data for the application\n\
+and write it to the profile output file (\"show mdi gmonfile\").\n\
+When auto, enable when _mcount symbol found in executable."),
+				NULL,
+				show_mdi_profiling,
+				&setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_boolean_cmd ("profile-mcount", no_class,
+			   &mdi_profile_mcount, _("\
+Set _mcount in MIPSsim profile."), _("\
+Show _mcount in MIPSsim profile."), _("\
+When on, GDB will include time spent in the _mcount function in the\n\
+profile data."),
+			   NULL,
+			   show_mdi_profile_mcount,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_boolean_cmd ("profile-cycles", no_class,
+			   &mdi_profile_cycles, _("\
+Set cycle counting in when MIPSsim profiling."), _("\
+Show cycle counting in when MIPSsim profiling."), _("\
+When on, GDB will enable cycle accurate MIPSsim profiling, if supported\n\
+by MIPSsim."),
+			   NULL,
+			   show_mdi_profile_cycles,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_zinteger_cmd ("team", no_class,
+			   &mdi_team, _("\
+Set MDI team number."), _("\
+Show MDI team number."), _("\
+Selects the MDI team to be used.  If this variable is set to 0\n\
+a new team will be created for new members."),
+			   NULL,
+			   show_mdi_team,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_zinteger_cmd ("target", no_class,
+			   &mdi_target, _("\
+Set MDI target group number."), _("\
+Show MDI target group number."), _("\
+Selects the MDI target group to be used.  If this variable is set to 0\n\
+you will be given a list of options during the connection setup."),
+			   NULL,
+			   show_mdi_target,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_zinteger_cmd ("device", no_class,
+			   &mdi_device, _("\
+Set MDI device number."), _("\
+Show MDI device number."), _("\
+Selects the MDI device to be used.  If this variable is set to 0 you will\n\
+be given a list of options during the connection setup."),
+			   NULL,
+			   show_mdi_device,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  mdi_target_prompt = xstrdup ("");
+  add_setshow_string_cmd ("prompt", no_class,
+			   &mdi_target_prompt, _("\
+Set MDI target input prompt."), _("\
+Show MDI target input prompt."), _("\
+Sets the prompt used when the program running under MDI attempts to read\n\
+from the console."),
+			   NULL,
+			   show_mdi_target_prompt,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_string_cmd ("ftext-symbols", no_class,
+			   &mdi_ftext_syms, _("\
+Set start of code section symbol name list."), _("\
+Show start of code section symbol list."), _("\
+Sets the list of symbol names which may indicate the start of the text or\n\
+code section for profiling."),
+			   NULL,
+			   show_mdi_ftext_syms,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_string_cmd ("etext-symbols", no_class,
+			   &mdi_etext_syms, _("\
+Set end of code section symbol name list."), _("\
+Show end of code section symbol name list."), _("\
+Sets the list of symbol names which may indicate the end of the text or\n\
+code section for profiling."),
+			   NULL,
+			   show_mdi_etext_syms,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_setshow_string_cmd ("mcount-symbols", no_class,
+			   &mdi_mcount_syms, _("\
+Set mcount symbol name list."), _("\
+Show mcount symbol name list."), _("\
+Sets the list of symbol names which may match the call-graph profiling\n\
+function."),
+			   NULL,
+			   show_mdi_mcount_syms,
+			   &setmdicmdlist, &showmdicmdlist);
+
+  add_cmd ("connectreset", class_support, set_connectreset_command, _("\
+Set reset on initial connection state.\n\
+If \"off\" then gdb will not reset the target when connecting.\n\
+If \"on\" then gdb will reset the target when connecting, and\n\
+will leave it in reset.\n\
+If a value N, then gdb will reset the target when connecting,\n\
+start it executing, wait N seconds, and then stop the target.\n\
+This is to allow the target's PROM monitor to initialise the\n\
+memory controller, etc."),
+	    &setmdicmdlist);
+
+  add_cmd ("connectreset", class_support, show_connectreset_command, _("\
+Show reset on initial connection state.\n\
+If \"off\" then gdb will not reset the target when connecting.\n\
+If \"on\" then gdb will reset the target when connecting, and\n\
+will leave it in reset.\n\
+If a value N, then gdb will reset the target when connecting,\n\
+start it executing, wait N seconds, and then stop the target.\n\
+This is to allow the target's PROM monitor to initialise the\n\
+memory controller, etc."),
+	    &showmdicmdlist);
+
+  add_cmd ("asid", class_support, set_asid_command, _("\
+Set target memory access mode.\n\
+If ASID is \"off\", gdb will access target memory and set\n\
+breakpoints using the global virtual address space.\n\
+If ASID is \"on\", gdb will reference target memory using the\n\
+address space id (asid) from the current ENTRYHI register.\n\
+If ASID is \"auto\", gdb will reference target memory using the\n\
+global mapping if the address is in an \"unmapped\" region, otherwise\n\
+it will use the current asid from ENTRYHI.\n\
+In all other cases ASID is an address space identifier\n\
+which gdb will use to qualify a target virtual address."),
+	   &setmdicmdlist);
+
+  add_cmd ("asid", class_support, show_asid_command, _("\
+Show target memory access mode.\n\
+If ASID is \"off\", gdb will access target memory and set\n\
+breakpoints using the global virtual address space.\n\
+If ASID is \"on\", gdb will reference target memory using the\n\
+address space id (asid) from the current ENTRYHI register.\n\
+If ASID is \"auto\", gdb will reference target memory using the\n\
+global mapping if the address is in an \"unmapped\" region, otherwise\n\
+it will use the current asid from ENTRYHI.\n\
+In all other cases ASID is a numeric address space identifier\n\
+which gdb will use to qualify a target virtual address."),
+	   &showmdicmdlist);
+
+  add_prefix_cmd ("mdi", class_obscure, mdi_command,
+		  _("Various MDI specific commands."),
+		  &mdicmdlist, "mdi ", 0, &cmdlist);
+
+  add_prefix_cmd ("team", class_obscure, mdi_team_command,
+		  _("MDI team support.\n\
+With no arguments the currently selected team is shown.\n\
+With a numerical argument the MDI team to be used is selected,\n\
+with 0 meaning a new team will be created for new members\n\
+Otherwise one of the subcommands can be used."),
+		  &mditeamlist, "mdi team ", 1, &mdicmdlist);
+
+  add_cmd ("list", class_obscure, mdi_team_list_command,
+	   _("List MDI teams."), &mditeamlist);
+  add_cmd ("detach", class_obscure, mdi_team_detach_command,
+	   _("Detach from an MDI team."), &mditeamlist);
+  add_cmd ("clear", class_obscure, mdi_team_clear_command,
+	   _("Clear an MDI team."), &mditeamlist);
+  add_cmd ("attach", class_obscure, mdi_team_attach_command,
+	   _("Attach to an MDI team."), &mditeamlist);
+
+  add_cmd ("reset", class_obscure, mdi_reset_command, _("\
+Reset MDI target.\n\
+Resets CPU and associated peripherals.  GDB will attempt to\n\
+remain synchronised with the CPU, but this probably won't do\n\
+anything useful unless you are debugging the ROM startup code."),
+	   &mdicmdlist);
+
+  add_cmd ("regsync", class_obscure, mdi_regsync_command, _("\
+Flush cached registers.\n\
+This is only required in unusual circumstances, for example if a coprocessor\n\
+register may have changed due to a previous MDI operation."),
+	   &mdicmdlist);
+
+  add_cmd ("cacheflush", class_obscure, mdi_cacheflush_command, _("\
+Flush (writeback and invalidate) all CPU caches."),
+	   &mdicmdlist);
+
+  add_prefix_cmd ("cycles", class_obscure, mdi_cycles_command, _("\
+Control MIPSsim cycle counting.\n\
+While cycle counting is enabled, the current cycle count is stored in\n\
+the GDB $cycles convenience variable.  To display the cycle count\n\
+whenever the program stops, use \"display $cycles\"."),
+		  &mdicycleslist, "mdi cycles ", 0, &mdicmdlist);
+
+  add_cmd ("enable", class_obscure, mdi_cycles_enable_command,
+	   _("Enable MIPSsim cycle counting."),
+	   &mdicycleslist);
+  add_alias_cmd ("on", "enable", class_obscure, 1, &mdicycleslist);
+  add_alias_cmd ("yes", "enable", class_obscure, 1, &mdicycleslist);
+  add_alias_cmd ("start", "enable", class_obscure, 1, &mdicycleslist);
+
+  add_cmd ("clear", class_obscure, mdi_cycles_clear_command,
+	   _("Clear MIPSsim cycle count and enable counting."),
+	   &mdicycleslist);
+  add_alias_cmd ("0", "clear", class_obscure, 1, &mdicycleslist);
+
+  add_cmd ("disable", class_obscure, mdi_cycles_disable_command,
+	   _("Disable MIPSsim cycle counting."),
+	   &mdicycleslist);
+  add_alias_cmd ("off", "disable", class_obscure, 1, &mdicycleslist);
+  add_alias_cmd ("no", "disable", class_obscure, 1, &mdicycleslist);
+  add_alias_cmd ("stop", "disable", class_obscure, 1, &mdicycleslist);
+
+  add_cmd ("status", class_obscure, mdi_cycles_status_command,
+	   _("Report MIPSsim cycle counting status."),
+	   &mdicycleslist);
+}
Index: binutils-quilt/src/gdb/msim_cfg.txt
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/msim_cfg.txt	2008-02-14 14:49:36.000000000 +0000
@@ -0,0 +1,1385 @@
+# MIPSsim config file template for GDB
+
+{common}
+# Entries common to all MIPSsim targets
+
+{EB}
+# CPU endianness
+#    	1 = Big Endian
+set BIG_ENDIAN 1
+
+{EL}
+# CPU endianness
+#    	0 = Little Endian
+set BIG_ENDIAN 0
+
+{!4}
+# Trace file
+#    Name of the trace file to be generated.  Can be
+#	a full path or a relative path to the file.
+#	'stdout' will point the output to standard
+#	output.
+set TRACE_FILE mipssim.trace
+
+# Tracing: Generate trace files
+#    	0 = none
+#    	1 = cycle counting on
+#    	2 = instruction trace on
+#    	3 = cycle counting and instruction trace
+set TRACE_LEVEL 0
+
+# Trace Format
+#    	0 = x(X) prints in hexadecimal
+#    	1 = h(H) prints in hexadecimal
+#    	2 = d(D) prints in decimal
+#    	3 = b(B) prints in binary
+#    	4 = r(R) prints in 8 byte hex value
+set TRACE_FORMAT 4
+
+# Dumpmem file
+#    Name of the dumpmem file.  Can be a full path
+#	or a relative path
+#set DUMP_FILE test.dumpmem
+
+{3\..*;20Kc}
+# Processor to System (Exernal) clock ratio
+#	1 = 2:1
+#	2 = 3:1
+#	3 = 4:1
+set EXTERNAL_CLOCK_RATIO 1
+
+# Indicates a bus configuration if low packaging cost
+#	0 = 64-bit bus
+#	1 = 32-bit bus
+set LOW_PACKAGING 0
+
+# set core to 20K NOT optional but needs to be set for GUI
+set CPU_CORE 30
+
+{3\..*;25Kf}
+# Processor to L2 clock divisor (L2 domain)
+#    L2 clock domain is synchronous to the processor clock,
+#    but may be devided-down in frequency.
+#	1 = 2:1
+#	2 = 3:1
+#	3 = 4:1
+#	4 = 5:1
+#	5 = 6:1
+#	6 = 7:1
+#	7 = 8:1
+#	8 = 9:1 (TBD)
+#	9 = 10:1 (TBD)
+set EXTERNAL_CLOCK_RATIO 1
+
+
+# L2 clock domain to System Controller clock domain ratio
+#    System Controller domain is synchronous to the L2 domain,
+#    but may be divided in frequency.  In bypass mode, the
+#    System Controller domain is exactly the same as the L2
+#    domain (choice 0 below).
+#	0 = 1:1
+#	1 = 2:1
+#	2 = 3:1
+#	3 = 4:1
+#	4 = 5:1 (TBD)
+set L2_CLOCK_RATIO 1
+
+
+# Primary Cache size:
+#    	0 = 16KB
+#    	1 = 32KB
+set CACHE_SIZE 1
+
+
+# Floating point coprocessor enable
+#    	0 = No FPU present
+#    	1 = FPU present
+set FLOATING_POINT 0
+
+
+# Level 2 Cache line size
+#    	0 = No level 2 cache present
+#    	1 = 4 bytes
+#    	2 = 8 bytes
+#    	3 = 16 bytes
+#    	4 = 32 bytes
+#    	5 = 64 bytes
+#    	6 = 128 bytes
+#    	7 = 256 bytes
+set SCACHE_LINE_SIZE 4
+
+
+# Level 2 Cache sets per way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+#	3 = 512 sets
+#	4 = 1024 sets
+#	5 = 2048 sets
+#	6 = 4096 sets
+#	7 = 8192 sets
+set SCACHE_SETS_PER_WAY 5
+
+
+# Level 2 Cache Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+#	 4 = 5-way
+#	 5 = 6-way
+#	 6 = 7-way
+#	 7 = 8-way
+set SCACHE_ASSOC 3
+
+
+# set core to 25Kf NOT optional but needs to be set for GUI
+set CPU_CORE 40
+
+{3\..*;4Kc}
+set CPU_CORE 0
+
+{3\..*;4Km}
+set CPU_CORE 1
+
+{3\..*;4Kp}
+set CPU_CORE 2
+
+{3\..*;4K[cmp]}
+# Merge Mode: 32-byte collapsing Write-thru buffer merge mode
+#    	0 = None
+#    	1 = SysAD valid
+#    	2 = Full
+set MERGE_MODE 1
+
+# Burst order
+#    	0 = Sequential
+#    	1 = Sub-block
+set BURST_MODE 1
+
+
+# Processor Instruction Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+set ICACHE_SETS_PER_WAY 2
+
+
+# Processor Instruction Cache
+#    Line Size
+#    	0 = No Icache present
+#	1 = 16 bytes
+set ICACHE_LINE_SIZE 1
+
+
+# Processor Instruction Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set ICACHE_ASSOC 3
+
+
+# Processor Data Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+set DCACHE_SETS_PER_WAY 2
+
+
+# Processor Data Cache
+#    Line Size
+#    	0 = No Dcache present
+#	1 = 16 bytes
+set DCACHE_LINE_SIZE 1
+
+
+# Processor Data Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set DCACHE_ASSOC 3
+
+{3\..*;4KEc}
+set CPU_CORE 60
+
+{3\..*;4KEm}
+set CPU_CORE 61
+
+{3\..*;4KEp}
+set CPU_CORE 62
+
+{3\..*;4KE[cmp]}
+
+# User Defined Instruction(UDI) implemented
+#	0 = not implemented
+#	1 = implemented
+set UDI_ENABLE 0
+
+
+# Indicates whether SimpleBE bus mode is enabled
+#	0 = no reserved byte enables on EC interface
+#	1 = Only simple byte enables allowed on EC interface
+set SIMPLE_BE 0
+
+
+# Merge Mode: 32-byte collapsing Write-thru buffer merge mode
+#    	0 = None
+#    	1 = Merging allowed
+set MERGE_MODE 1
+
+
+# Burst order
+#    	0 = Sequential
+#    	1 = Sub-block
+set BURST_MODE 1
+
+
+# Processor Instruction Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+#	3 = 512 sets
+#	4 = 1024 sets
+set ICACHE_SETS_PER_WAY 2
+
+
+# Processor Instruction Cache
+#    Line Size
+#    	0 = No Icache present
+#	1 = 16 bytes
+set ICACHE_LINE_SIZE 1
+
+
+# Processor Instruction Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set ICACHE_ASSOC 1
+
+
+# Processor Data Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+#	3 = 512 sets
+#	4 = 1024 sets
+set DCACHE_SETS_PER_WAY 2
+
+
+# Processor Data Cache
+#    Line Size
+#    	0 = No Dcache present
+#	1 = 16 bytes
+set DCACHE_LINE_SIZE 1
+
+
+# Processor Data Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set DCACHE_ASSOC 1
+
+
+# Coprocessor 2
+#	0 = not present
+#	1 = A coprocessor is attached to the cop2 interface
+set COP2_ENABLE 0
+
+
+# Code compression (MIPS16TM) implemented
+#	0 = no MIPS16 is present
+#	1 = MIPS16 implemented
+set CODE_COMPRESSION 1
+
+
+# ISPram present
+#	0 = not present
+#	1 = present
+set ISPRAM_ENABLE 0
+
+
+# DSPram present
+#	0 = not present
+#	1 = present
+set DSPRAM_ENABLE 0
+
+
+# IP number to which the Timer Interrupt request is merged
+#     and allow software to determine whether to consider
+#     Cause(TI) for potential interrupt.
+#	2 = HW0
+#       3 = HW1
+#       4 = HW2
+#       5 = HW3
+#       6 = HW4
+#       7 = HW5
+set INTCTL_IPTI 7
+
+
+# The number of CPU in a multi-processor system.  In
+#     a single processor system, this value should be set
+#     to zero. (Maximum value = 1023)
+set EBASE_CPUNUM 0
+
+
+# Shadow Register Sets
+#	0 = not implemented
+#	1 = One set of shadow registers
+#	3 = Three sets of shadow registers
+set SHADOW_REGISTER_SETS 0
+
+
+# Small (1K Byte) page support
+#	0 = not implemented
+#       1 = implemented
+set SMALL_PAGE_SUPPORT 0
+
+{3\..*;4KEc-R1}
+set CPU_CORE 10
+
+{3\..*;4KEm-R1}
+set CPU_CORE 11
+
+{3\..*;4KEp-R1}
+set CPU_CORE 12
+
+{3\..*;4KE[cmp]-R1}
+# User Defined Instruction(UDI) implemented
+#	0 = not implemented
+#	1 = implemented
+set UDI_ENABLE 0
+
+
+# Indicates whether SimpleBE bus mode is enabled
+#	0 = no reserved byte enables on EC interface
+#	1 = Only simple byte enables allowed on EC interface
+set SIMPLE_BE 0
+
+
+# Merge Mode: 32-byte collapsing Write-thru buffer merge mode
+#    	0 = None
+#    	1 = Merging allowed
+set MERGE_MODE 1
+
+
+# Burst order
+#    	0 = Sequential
+#    	1 = Sub-block
+set BURST_MODE 1
+
+
+# Processor Instruction Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+#	3 = 512 sets
+#	4 = 1024 sets
+set ICACHE_SETS_PER_WAY 2
+
+
+# Processor Instruction Cache
+#    Line Size
+#    	0 = No Icache present
+#	1 = 16 bytes
+set ICACHE_LINE_SIZE 1
+
+
+# Processor Instruction Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set ICACHE_ASSOC 1
+
+
+# Processor Data Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+#	3 = 512 sets
+#	4 = 1024 sets
+set DCACHE_SETS_PER_WAY 2
+
+
+# Processor Data Cache
+#    Line Size
+#    	0 = No Dcache present
+#	1 = 16 bytes
+set DCACHE_LINE_SIZE 1
+
+
+# Processor Data Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set DCACHE_ASSOC 1
+
+
+# Coprocessor 2
+#	0 = not present
+#	1 = A coprocessor is attached to the cop2 interface
+set COP2_ENABLE 0
+
+
+# Code compression (MIPS16TM) implemented
+#	0 = no MIPS16 is present
+#	1 = MIPS16 implemented
+set CODE_COMPRESSION 1
+
+
+# ISPram present
+#	0 = not present
+#	1 = present
+set ISPRAM_ENABLE 0
+
+
+# DSPram present
+#	0 = not present
+#	1 = present
+set DSPRAM_ENABLE 0
+
+{3\..*;4KSc}
+# User Defined Instruction(UDI) implemented
+#	0 = not implemented
+#	1 = implemented
+set UDI_ENABLE 0
+
+
+# Indicates whether SimpleBE bus mode is enabled
+#	0 = no reserved byte enables on EC interface
+#	1 = Only simple byte enables allowed on EC interface
+set SIMPLE_BE 0
+
+
+# Merge Mode: 32-byte collapsing Write-thru buffer merge mode
+#    	0 = None
+#    	1 = Merging allowed
+set MERGE_MODE 1
+
+
+# Burst order
+#    	0 = Sequential
+#    	1 = Sub-block
+set BURST_MODE 1
+
+
+# Processor Instruction Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+#	3 = 512 sets
+#	4 = 1024 sets
+set ICACHE_SETS_PER_WAY 2
+
+
+# Processor Instruction Cache
+#    Line Size
+#    	0 = No Icache present
+#	1 = 16 bytes
+set ICACHE_LINE_SIZE 1
+
+
+# Processor Instruction Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set ICACHE_ASSOC 1
+
+
+# Processor Data Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+#	3 = 512 sets
+#	4 = 1024 sets
+set DCACHE_SETS_PER_WAY 2
+
+
+# Processor Data Cache
+#    Line Size
+#    	0 = No Dcache present
+#	1 = 16 bytes
+set DCACHE_LINE_SIZE 1
+
+
+# Processor Data Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set DCACHE_ASSOC 1
+
+
+# Coprocessor 2
+#	0 = not present
+#	1 = A coprocessor is attached to the cop2 interface
+set COP2_ENABLE 0
+
+
+# CPU_CORE
+#       default to 4KSc Not needed for configuration but needed by GUI
+set CPU_CORE 13
+
+
+# ISPram present
+#	0 = not present
+#	1 = present
+set ISPRAM_ENABLE 0
+
+
+# DSPram present
+#	0 = not present
+#	1 = present
+set DSPRAM_ENABLE 0
+
+{3\..*;4KSd}
+# User Defined Instruction(UDI) implemented
+#	0 = not implemented
+#	1 = implemented
+set UDI_ENABLE 0
+
+
+# Indicates whether SimpleBE bus mode is enabled
+#	0 = no reserved byte enables on EC interface
+#	1 = Only simple byte enables allowed on EC interface
+set SIMPLE_BE 0
+
+
+# Merge Mode: 32-byte collapsing Write-thru buffer merge mode
+#    	0 = None
+#    	1 = Merging allowed
+set MERGE_MODE 1
+
+
+# Burst order
+#    	0 = Sequential
+#    	1 = Sub-block
+set BURST_MODE 1
+
+
+# Processor Instruction Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+#	3 = 512 sets
+#	4 = 1024 sets
+set ICACHE_SETS_PER_WAY 2
+
+
+# Processor Instruction Cache
+#    Line Size
+#    	0 = No Icache present
+#	1 = 16 bytes
+set ICACHE_LINE_SIZE 1
+
+
+# Processor Instruction Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set ICACHE_ASSOC 1
+
+
+# Processor Data Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+#	3 = 512 sets
+#	4 = 1024 sets
+set DCACHE_SETS_PER_WAY 2
+
+
+# Processor Data Cache
+#    Line Size
+#    	0 = No Dcache present
+#	1 = 16 bytes
+set DCACHE_LINE_SIZE 1
+
+
+# Processor Data Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set DCACHE_ASSOC 1
+
+
+# Coprocessor 2
+#	0 = not present
+#	1 = A coprocessor is attached to the cop2 interface
+set COP2_ENABLE 0
+
+
+# CPU_CORE
+#       default to 4KSd Not needed for configuration but needed by GUI
+set CPU_CORE 63
+
+
+# ISPram present
+#	0 = not present
+#	1 = present
+set ISPRAM_ENABLE 0
+
+
+# DSPram present
+#	0 = not present
+#	1 = present
+set DSPRAM_ENABLE 0
+
+
+# *** THIS IS MIPS RELEASE 2 ARCHITECTURE EXTENSIONS ***
+# IP number to which the Timer Interrupt request is merged
+#     and allow software to determine whether to consider
+#     Cause(TI) for potential interrupt.
+#	2 = HW0
+#       3 = HW1
+#       4 = HW2
+#       5 = HW3
+#       6 = HW4
+#       7 = HW5
+set INTCTL_IPTI 7
+
+
+# *** THIS IS MIPS RELEASE 2 ARCHITECTURE EXTENSIONS ***
+# The number of CPU in a multi-processor system.  In
+#     a single processor system, this value should be set
+#     to zero. (Maximum value = 1023)
+set EBASE_CPUNUM 0
+
+
+# *** THIS IS MIPS RELEASE 2 ARCHITECTURE EXTENSIONS ***
+# Shadow Register Sets
+#	0 = not implemented
+#	1 = One set of shadow registers
+#	3 = Three sets of shadow registers
+set SHADOW_REGISTER_SETS 0
+
+{3\..*;5Kc}
+set CPU_CORE 20
+
+{3\..*;5Kf}
+set CPU_CORE 21
+
+{3\..*;5K[cf]}
+# Indicates whether SimpleBE bus mode is enabled
+#	0 = no reserved byte enables on EC interface
+#	1 = Only simple byte enables allowed on EC interface
+set SIMPLE_BE 0
+
+# Burst order
+#    	0 = Sequential
+#    	1 = Sub-block
+set BURST_MODE 1
+
+
+# Type of MMU implemented
+#	0 = Standard TLB
+#	1 = Standard FMT
+set MMU_TYPE 0
+
+# Size of MMU (number of entries in TLB minus one)
+#	0 = Value used when the MMU is not TLB-based
+#	1 = 16-entry TLB MMU
+#	2 = 32-entry TLB MMU
+#	3 = 48-entry TLB MMU
+set MMU_SIZE 3
+
+# Processor Instruction Cache
+#    Sets per Way
+#	1 = 128 sets
+#	2 = 256 sets
+#	 3 = 512 sets
+set ICACHE_SETS_PER_WAY 3
+
+
+# Processor Instruction Cache
+#    Line Size
+#    	0 = No Icache present
+#	1 = 32 bytes
+set ICACHE_LINE_SIZE 1
+
+
+# Processor Instruction Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set ICACHE_ASSOC 3
+
+
+# Processor Data Cache
+#    Sets per Way
+#	1 = 128 sets
+#	2 = 256 sets
+#	 3 = 512 sets
+set DCACHE_SETS_PER_WAY 3
+
+
+# Processor Data Cache
+#    Line Size
+#    	0 = No Dcache present
+#	1 = 32 bytes
+set DCACHE_LINE_SIZE 1
+
+
+# Processor Data Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set DCACHE_ASSOC 3
+
+
+# Coprocessor 2
+#	0 = not present
+#	1 = A coprocessor is attached to the cop2 interface
+set COP2_ENABLE 0
+
+{3\..*;M4K}
+# User Defined Instruction(UDI) implemented
+#	0 = not implemented
+#	1 = implemented
+set UDI_ENABLE 0
+
+
+# Indicates whether SimpleBE bus mode is enabled
+#	0 = no reserved byte enables on EC interface
+#	1 = Only simple byte enables allowed on EC interface
+set SIMPLE_BE 0
+
+
+# Indicates whether Multiply/Divide Unit present
+#	0 = Fast, high performance MDU
+#	1 = Interative, area-efficient MDU
+set MDU 1
+
+
+# Dual SRAM Interface
+#	0 = Unified instruction/data SRAM interface
+#	1 = Dual instruction/data SRAM interfaces
+set DUAL_SRAM 0
+
+
+# Coprocessor 2
+#	0 = not present
+#	1 = A coprocessor is attached to the cop2 interface
+set COP2_ENABLE 0
+
+
+# CPU_CORE
+#       default to M4K Not needed for configuration but needed by GUI
+set CPU_CORE 50
+
+
+# Shadow Register Sets
+#	0 = not implemented
+#	1 = One set of shadow registers
+#	3 = Three sets of shadow registers
+set SHADOW_REGISTER_SETS 0
+
+
+# IP number to which the Timer Interrupt request is merged
+#     and allow software to determine whether to consider
+#     Cause(TI) for potential interrupt.
+#	2 = HW0
+#       3 = HW1
+#       4 = HW2
+#       5 = HW3
+#       6 = HW4
+#       7 = HW5
+set INTCTL_IPTI 7
+
+
+# The number of CPU in a multi-processor system.  In
+#     a single processor system, this value should be set
+#     to zero. (Maximum value = 1023)
+set EBASE_CPUNUM 0
+
+
+# Code compression (MIPS16TM) implemented
+#	0 = no MIPS16 is present
+#	1 = MIPS16 implemented
+set CODE_COMPRESSION 1
+
+{4}
+############################################################
+# ENVIRONMENT
+#
+
+# Trace file
+#    Name of the trace file to be generated.  Can be
+#	a full path or a relative path to the file.
+#	'stdout' will point the output to standard
+#	output.
+#set TRACE_FILE mipssim.trace
+
+# Error Limit
+# When ERROR_LIMIT errors have been reached the simulation will exit
+# 0 - infinite
+set ERROR_LIMIT 0
+
+# Warn Limit
+# When WARN_LIMIT errors have been reached the simulation will exit
+# 0 - infinite
+set WARN_LIMIT 0
+
+# Console level
+# Set the console output level.  As you go down the list of possible values
+# each successive value includes all values before it (e.g. a level of MIPS_C_CONSOLEFATAL
+# will show all fatal messages and all panic messages).
+# NONE   - no output
+# PANIC  - only show panic message
+# FATAL  - show fatal messages
+# ERROR  - show error messages
+# WARN   - show warning messages
+# INFO   - show info messages
+# COMMON - show common messages
+# ALL    - show all messages
+set CONSOLE_LEVEL INFO
+
+# STRICT_CONSISTENCY_CHECKS
+# 0 - false
+# 1 - true
+set STRICT_CONSISTENCY_CHECKS 1
+
+############################################################
+# SIMULATION
+#
+
+# CPU CORE
+{4\..*;24K}
+# Only one value allowed for 24K
+set CPU_CORE 70
+
+{4\..*;24KE}
+# Only one value allowed for 24KE
+set CPU_CORE 71
+
+{4\..*;34K}
+# Only one value allowed for 34K
+set CPU_CORE 80
+
+{4\..*;74K}
+# Only one value allowed for 74K
+set CPU_CORE 90
+
+{4\..*;(24K|24KE|34K|74K)}
+# Run time out.
+# Max cycles or instructions to run.  This parameter is included
+# for the purposes of bring up only.  This will not remain.
+#set TIMEOUT 1000000
+
+# TIMER_INT_ENABLE
+# 0 - disabled
+# 1 - enabled
+# (SDE kit uses timer)
+set TIMER_INT_ENABLE 1
+
+# LWR_SIGN_EXTEND
+#
+set LWR_SIGN_EXTEND 0
+
+# TODO: FPU_REV
+#
+# set C1FIR_REV 0
+
+# VALID_COUNT_REGISTER
+# 0 - Count register valid bits disabled
+# 1 - Count register valid bits enabled
+#
+set CNT_REG_VALIDITY 0
+
+# VALID_ACX_REGISTER
+# 0 - ACX register valid bits disabled
+# 1 - ACX register valid bits enabled
+#
+set ACX_REG_VALIDITY 0
+
+# XOR_OPTION - give it a better name?
+# 0 - off
+# 1 - on
+set XOR_OPTION 0
+
+############################################################
+# CORE PERSONALITY
+#
+
+# Udi enabled for the core?
+# 0 - no
+# 1 - yes
+set UDI_ENABLE           0
+
+# Simple Burst Enabled for the core?
+# 0 - no
+# 1 - yes
+set SIMPLE_BE            0
+
+# Burst order
+# 0 - sequential
+# 1 - sub-block
+set BURST_MODE           1
+
+# Instruction Cache Sets per Way
+# 1 - 128 sets
+# 2 - 256 sets
+# 3 - 512 sets
+set ICACHE_SETS_PER_WAY  3
+
+# Data Cache Sets per Way
+# 1 - 128 sets
+# 2 - 256 sets
+# 3 - 512 sets
+set DCACHE_SETS_PER_WAY  3
+
+# FPU Present
+# 0 - no
+# 1 - yes
+set FPU_PRESENT          1
+
+# Number of tlb entries
+# 0  - none (FMT)
+# 32 - 32 entries
+# 64 - 64 entries
+set MMU_SIZE            64
+
+# Secondary Cache Sets per Way
+# 0 - 64 sets
+# 1 - 128 sets
+# 2 - 256 sets
+# 3 - 512 sets
+# 4 - 1024 sets
+# 5 - 2048 sets
+# 6 - 4096 sets
+# 7 - 8192 sets
+set SCACHE_SETS_PER_WAY  0
+
+# Secondary Cache Line size
+# 0 - No cache present
+# 1 - 4 bytes
+# 2 - 8 bytes
+# 3 - 16 bytes
+# 4 - 32 bytes
+# 5 - 64 bytes
+# 6 - 128 bytes
+# 7 - 256 bytes
+set SCACHE_LINE_SIZE     0
+
+# Secondary Cache number of sets
+# 0 - direct mapped
+# 1 - 2 sets
+# 2 - 3 sets
+# 3 - 4 sets
+# 4 - 5 sets
+# 5 - 6 sets
+# 6 - 7 sets
+# 7 - 8 sets
+set SCACHE_ASSOC         0
+
+# External interrupt controller present.
+# This represents the static input SI_EICPresent
+# 0 - no
+# 1 - yes
+set EIC_PRESENT          0
+
+# Number of shadow register sets
+# 0 - One shadow set (normal GPR set) is present
+# 1 - Two shadow sets are present
+# 3 - Four shadow sets are present
+set SHADOW_REGISTER_SETS 3
+
+# Cpu Number used to distinguish this processor from others in
+# a multi-processor system.
+# This may take any value from 0 to 511
+set EBASE_CPUNUM         0
+
+# Timer Interrupt IP number
+# 2 - Hardware interrupt source HW0
+# 3 - Hardware interrupt source HW1
+# 4 - Hardware interrupt source HW2
+# 5 - Hardware interrupt source HW3
+# 6 - Hardware interrupt source HW4
+# 7 - Hardware interrupt source HW5
+set INTCTL_IPTI          7
+
+# Performance Counter Interrupt IP number
+# 2 - Hardware interrupt source HW0
+# 3 - Hardware interrupt source HW1
+# 4 - Hardware interrupt source HW2
+# 5 - Hardware interrupt source HW3
+# 6 - Hardware interrupt source HW4
+# 7 - Hardware interrupt source HW5
+set INTCTL_IPPCI          7
+
+# Processor Id Revision Number
+# Major - 0-7
+# Minor - 0-7
+# Patch - 0-3
+# Revision - Major<<5 | Minor << 2 | Patch
+set PRID_REV             0
+
+# Number of EJTAG Data Breakpoints implemented
+# 0 - No data breakpoints
+# 2 - 2 data breakpoints
+set EJTAG_NDB       0
+
+# Number of EJTAG Instruction Breakpoints implemented
+# 0 - No instruction breakpoints
+# 4 - 4 instruction breakpoints
+set EJTAG_NIB      0
+
+# Cache Parity Error Register
+set PARITY_ENABLE 0
+
+# EIC interrupt mode default shadow set.
+#
+set EIC_DEFAULT_SHADOW_SET 0
+
+# 32K Data Cache Aliasing Hardware Fix
+# 0 - no hardware fix for aliasing, must be fixed in software
+# 1 - hardware fix for alias is enabled, slight performance
+#     penalty
+set DCACHE_ALIAS_HW_FIX 0
+
+# Clock ratio between integer core and floating point unit
+# 0 - FP clock frequency is the same as the integer clock
+# 1 - FP clock frequency is one-half the integer clock
+set FPU_CLOCK_RATIO 0
+
+{4\..*;34K}
+# Total processor complement of VPE contexts
+# 1 - One VPE
+# 2 - Two VPEs
+set VPE_COUNT 2
+
+# Total processor complement of Thread Contexts (TC)
+# 1 - 1 Thread Context
+# 2 - 2 Thread Contexts
+# 3 - 3 Thread Contexts
+# 4 - 4 Thread Contexts
+# 5 - 5 Thread Contexts
+# 6 - 6 Thread Contexts
+# 7 - 7 Thread Contexts
+# 8 - 8 Thread Contexts
+# 9 - 9 Thread Contexts
+set TC_COUNT 9
+
+# Maximum Thread Contexts allowed for VPE 0
+# 1 - 1 Thread Context
+# 2 - 2 Thread Contexts
+# 3 - 3 Thread Contexts
+# 4 - 4 Thread Contexts
+# 5 - 5 Thread Contexts
+# 6 - 6 Thread Contexts
+# 7 - 7 Thread Contexts
+# 8 - 8 Thread Contexts
+# 9 - 9 Thread Contexts ( Only valid if VPE_COUNT is 1 )
+set VPE0_TC_COUNT 8
+
+# VPE that owns CorExt on reset if only one context
+# is implemented
+# 0 - VPE0
+# 1 - VPE1
+set VPE_CX 0
+
+# VPE that owns FPU on reset if only one context is implemented
+# 0 - VPE0
+# 1 - VPE1
+set VPE_CP1 0
+
+# Total processor complement of integrated and allocatable
+# Coprocessor 2 contexts
+# 0 - Cop 2 not supported
+# 1 - 1 context available
+set COP2_ENABLE 0
+
+# VPE that owns Coprocessor 2 on reset if only one context
+# is implemented
+# 0 - VPE0
+# 1 - VPE1
+set VPE_CP2 0
+
+# Parameters for VPE 1
+#set MMU_SIZE_1  64
+#set EIC_PRESENT_1  1
+#set EBASE_CPUNUM_1  1
+
+{4\..*;4KEc}
+set CPU_CORE 60
+{4\..*;4KEm}
+set CPU_CORE 61
+{4\..*;4KEp}
+set CPU_CORE 62
+{4\..*;4KSd}
+set CPU_CORE 63
+
+{4\..*;(4KE[cmp]|4KSd)}
+# TIMER_INT_ENABLE
+# 0 - disabled
+# 1 - enabled
+set TIMER_INT_ENABLE 1
+
+############################################################
+# CORE PERSONALITY
+#
+
+# Udi enabled for the core?
+# 0 - no
+# 1 - yes
+set UDI_ENABLE           0
+
+# Simple Burst Enabled for the core?
+# Indicates whether SimpleBE bus mode is enabled
+#	0 = no reserved byte enables on EC interface
+#	1 = Only simple byte enables allowed on EC interface
+set SIMPLE_BE 0
+
+# Merge Mode: 32-byte collapsing Write-thru buffer merge mode
+#    	0 = None
+#    	2 = Full Merging allowed
+set MERGE_MODE 2
+
+# Burst order
+#    	0 = Sequential
+#    	1 = Sub-block
+set BURST_MODE 1
+
+#  Processor Instruction Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+#	3 = 512 sets
+#	4 = 1024 sets
+set ICACHE_SETS_PER_WAY 2
+
+
+# Processor Instruction Cache
+#    Line Size
+#    	0 = No Icache present
+#	3 = 16 bytes
+set ICACHE_LINE_SIZE 3
+
+
+# Processor Instruction Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set ICACHE_ASSOC 1
+
+
+# Processor Data Cache
+#    Sets per Way
+#	0 = 64 sets
+#	1 = 128 sets
+#	2 = 256 sets
+#	3 = 512 sets
+#	4 = 1024 sets
+set DCACHE_SETS_PER_WAY 2
+
+
+# Processor Data Cache
+#    Line Size
+#    	0 = No Dcache present
+#	3 = 16 bytes
+set DCACHE_LINE_SIZE 3
+
+
+# Processor Data Cache
+#    Associativity
+#	0 = Direct Mapped
+#	1 = 2-way
+#	2 = 3-way
+#	3 = 4-way
+set DCACHE_ASSOC 1
+
+
+# Coprocessor 2
+#	0 = not present
+#	1 = A coprocessor is attached to the cop2 interface
+set COP2_ENABLE 0
+
+
+# Code compression (MIPS16TM) implemented
+#	0 = no MIPS16 is present
+#	1 = MIPS16 implemented
+set CODE_COMPRESSION 1
+
+
+# ISPram present
+#	0 = not present
+#	1 = present
+set ISPRAM_ENABLE 0
+
+
+# DSPram present
+#	0 = not present
+#	1 = present
+set DSPRAM_ENABLE 0
+
+
+# IP number to which the Timer Interrupt request is merged
+#     and allow software to determine whether to consider
+#     Cause(TI) for potential interrupt.
+#		2 = HW0
+#       3 = HW1
+#       4 = HW2
+#       5 = HW3
+#       6 = HW4
+#       7 = HW5
+set INTCTL_IPTI 7
+
+
+# The number of CPU in a multi-processor system.  In
+#     a single processor system, this value should be set
+#     to zero. (Maximum value = 1023)
+set EBASE_CPUNUM 0
+
+# External interrupt controller present.
+# This represents the static input SI_EICPresent
+# 0 - no
+# 1 - yes
+set EIC_PRESENT          0
+
+# Shadow Register Sets
+#	0 = not implemented
+#	1 = One set of shadow registers
+#	3 = Three sets of shadow registers
+set SHADOW_REGISTER_SETS 0
+
+# Processor Id Revision Number
+# Major - 0-7
+# Minor - 0-7
+# Patch - 0-3
+# Revision - Major<<5 | Minor << 2 | Patch
+set PRID_REV             0
+
+
+# EIC interrupt mode default shadow set.
+#
+set EIC_DEFAULT_SHADOW_SET 0
+
+# Num Watch Regs
+# 0 = No WatchRegs
+# 1 = 1 Watch Register Pair Present
+# 2 = 2 Watch Register Pairs Present
+# 3 = 1 Watch Register Pairs Present
+# 4 = 2 Watch Register Pairs Present
+# 5 = 1 Watch Register Pairs Present
+# 6 = 2 Watch Register Pairs Present
+# 7 = 1 Watch Register Pairs Present
+# 8 = 8 Watch Register Pairs Present
+set WATCH_NUM 1
+
+{4\..*;M4K}
+
+# CPU CORE
+# Processor Core with Release 2 Architecture
+#   	50 = M4K
+set CPU_CORE 50
+
+# The number of CPU in a multi-processor system.  In
+#     a single processor system, this value should be set
+#     to zero. (Maximum value = 1023)
+set EBASE_CPUNUM 0
+
+# Processor Id Revision Number
+# Major - 0-7
+# Minor - 0-7
+# Patch - 0-3
+# Revision - Major<<5 | Minor << 2 | Patch
+set PRID_REV             0
+
+# Dual SRAM
+#       0 = Unified SRAM
+#       1 = Separate I and D SRAM
+set DUAL_SRAM 0
+
+# Simple Burst Enabled for the core?
+# Indicates whether SimpleBE bus mode is enabled
+#	0 = no reserved byte enables on EC interface
+#	1 = Only simple byte enables allowed on EC interface
+set SIMPLE_BE 0
+
+# Multiply/Divide Unit
+#       0 = Fast MDU
+#       1 = Iterative MDU (fewer transistors)
+set MDU 0
+
+# UDI enabled for the core?
+#       0 = Disabled
+#       1 = Enabled
+#
+set UDI_ENABLE 0
+
+# Coprocessor 2
+#	0 = not present
+#	1 = A coprocessor is attached to the cop2 interface
+set COP2_ENABLE 0
+
+# Code compression (MIPS16TM) implemented
+#	0 = no MIPS16 is present
+#	1 = MIPS16 implemented
+set CODE_COMPRESSION 1
+
+# IP number to which the Timer Interrupt request is merged
+#     and allow software to determine whether to consider
+#     Cause(TI) for potential interrupt.
+#		2 = HW0
+#       3 = HW1
+#       4 = HW2
+#       5 = HW3
+#       6 = HW4
+#       7 = HW5
+set INTCTL_IPTI 7
+
+# TIMER_INT_ENABLE
+# 0 - disabled
+# 1 - enabled (needed by SDE kit)
+set TIMER_INT_ENABLE 1
+
+# External interrupt controller present.
+# This represents the static input SI_EICPresent
+# 0 - no
+# 1 - yes
+set EIC_PRESENT          0
+
+# EIC interrupt mode default shadow set.
+set EIC_DEFAULT_SHADOW_SET 0
+
+# Shadow Register Sets
+#	0 = not implemented
+#	1 = One set of shadow registers
+#	3 = Three sets of shadow registers
+set SHADOW_REGISTER_SETS 0
+
Index: binutils-quilt/src/gdb/mdimips.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/mdimips.h	2008-02-14 14:49:36.000000000 +0000
@@ -0,0 +1,121 @@
+/* MDI (Microprocessor Debug Interface) MIPS specific definitions.
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   Contributed by MIPS Technologies, Inc.
+
+   This file is part of GDB.
+
+   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.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef MDI_MIPS_Specification_Definitions
+#define MDI_MIPS_Specification_Definitions
+
+/* Valid values for MDIDDataT.FClass:  */
+#define MDIMIP_FClass       "MIPS"
+/* Valid values for MDIDDataT.FISA:  */
+#define MDIMIP_FISA_M1      "MIPSI"
+#define MDIMIP_FISA_M2      "MIPSII"
+#define MDIMIP_FISA_M3      "MIPSIII"
+#define MDIMIP_FISA_M4      "MIPSIV"
+#define MDIMIP_FISA_M5      "MIPSV"
+#define MDIMIP_FISA_M32     "MIPS32"
+#define MDIMIP_FISA_M64     "MIPS64"
+
+/* Valid values for Resource:  */
+#define MDIMIPCPU           1
+#define MDIMIPPC            2
+#define MDIMIPHILO          3
+#define MDIMIPTLB           4
+#define MDIMIPPICACHET      5
+#define MDIMIPPUCACHET      5
+#define MDIMIPPDCACHET      6
+#define MDIMIPSICACHET      7
+#define MDIMIPSUCACHET      7
+#define MDIMIPSDCACHET      8
+#define MDIMIP192ACC        9
+#define MDIMIPCP0           10
+#define MDIMIPCP0C          11
+#define MDIMIPCP1           12
+#define MDIMIPCP1C          13
+#define MDIMIPCP2           14
+#define MDIMIPCP2C          15
+#define MDIMIPCP3           16
+#define MDIMIPCP3C          17
+#define MDIMIPFP            18
+#define MDIMIPDFP           19
+#define MDIMIPPICACHE       20
+#define MDIMIPPUCACHE       20
+#define MDIMIPPDCACHE       21
+#define MDIMIPSICACHE       22
+#define MDIMIPSUCACHE       22
+#define MDIMIPSDCACHE       23
+#define MDIMIPPHYSICAL      24
+#define MDIMIPGVIRTUAL      25
+#define MDIMIPEJTAG         26
+#define MDIMIPSRS           27
+#define MDIMIPFPR           28
+#define MDIMIPDSP           29
+#define MDIMIPTICACHET      30
+#define MDIMIPTUCACHET      31
+#define MDIMIPTDCACHET      32
+#define MDIMIPTICACHE       33
+#define MDIMIPTUCACHE       34
+#define MDIMIPTDCACHE       35
+#define MDIMIPITCVIRTUAL    36
+#define MDIMIPHWR           37
+
+#define MDIMIPVIRTUAL       0x00001000  /* 0x10xx: 0x1000+ASID value */
+
+/* For MDISetBp(), MDISetSWBp(), and MDITraceRead(), setting the low
+   order address bit to 1 means that the addressed instruction is a
+   MIPS16 instruction.  */
+#define MDIMIP_Flg_MIPS16   1
+
+/* Select codes for MIPSsim_GetStats().  */
+#define MIPS_MDI_PerfCycles               1
+#define MIPS_MDI_PerfInstructionsExecuted 2
+#define MIPS_MDI_PerfBranchesTaken        3
+#define MIPS_MDI_PerfLoadInstructions     4
+#define MIPS_MDI_PerfStoreInstructions    5
+#define MIPS_MDI_PerfIUncachedAccesses    6
+#define MIPS_MDI_PerfPICacheMisses        7
+#define MIPS_MDI_PerfPICacheHits          8
+#define MIPS_MDI_PerfDUncachedAccesses    9
+#define MIPS_MDI_PerfPDCacheMisses        10
+#define MIPS_MDI_PerfPDCacheHits          11
+#define MIPS_MDI_PerfPDCacheLoadMisses    12
+#define MIPS_MDI_PerfUnmappedAccesses     13
+#define MIPS_MDI_PerfTLBMisses            14
+#define MIPS_MDI_PerfTLBHits              15
+#define MIPS_MDI_PerfISpramHits           16
+#define MIPS_MDI_PerfDSpramHits           17
+
+/* MIPSsim 4.x performance counter modes.  */
+#define MIPS_E_PerfCntMode_UM      0x01
+#define MIPS_E_PerfCntMode_SM      0x02
+#define MIPS_E_PerfCntMode_KM      0x04
+#define MIPS_E_PerfCntMode_EXL     0x08
+#define MIPS_E_PerfCntMode_ERL     0x10
+#define MIPS_E_PerfCntMode_EXLERL  0x20
+#define MIPS_E_PerfCntMode_ALL     0xffff
+
+/* MIPSsim 4.x performance counters (a selection).  */
+#define MIPS_PerfCntSel_Cycles0           0
+#define MIPS_PerfCntInd_Cycles0           0
+#define MIPS_PerfCntSel_Instr0            0
+#define MIPS_PerfCntInd_Instr0            1
+
+#endif
+
Index: binutils-quilt/src/gdb/Makefile.in
===================================================================
--- binutils-quilt.orig/src/gdb/Makefile.in	2008-02-14 14:49:36.000000000 +0000
+++ binutils-quilt/src/gdb/Makefile.in	2008-02-14 14:49:36.000000000 +0000
@@ -664,6 +664,8 @@
 elf_m32c_h =    $(INCLUDE_DIR)/elf/m32c.h $(elf_reloc_macros_h)
 elf_mep_h =     $(INCLUDE_DIR)/elf/mep.h $(elf_reloc_macros_h)
 elf_ppc_h =     $(INCLUDE_DIR)/elf/ppc.h $(elf_reloc_macros_h)
+gmon_h =	$(INCLUDE_DIR)/gmon.h
+gmon_out_h =	$(INCLUDE_DIR)/gmon_out.h
 libaout_h =	$(BFD_SRC)/libaout.h
 libiberty_h =	$(INCLUDE_DIR)/libiberty.h
 libbfd_h =	$(BFD_SRC)/libbfd.h
@@ -1230,6 +1232,21 @@
 	$(CC_LD) $(INTERNAL_LDFLAGS) -o test-cp-name-parser$(EXEEXT) \
 		test-cp-name-parser.o $(LIBIBERTY)
 
+# Handle MIPSsim configuration file
+.PHONY: install-mipssim
+install-mipssim:
+	$(INSTALL_DATA) mipssim.cfg $(datadir)/mipssim.cfg
+.PHONY: uninstall-mipssim
+uninstall-mipssim:
+	rm -f $(datadir)/mipssim.cfg
+.PHONY: clean-mipssim
+clean-mipssim:
+	rm -f mipssim.cfg
+mipssim.cfg: $(srcdir)/msim_cfg.txt
+	rm -f mipssim.cfg
+	cp $(srcdir)/msim_cfg.txt mipssim.cfg
+# End MIPSsim configuration file
+
 # We do this by grepping through sources.  If that turns out to be too slow,
 # maybe we could just require every .o file to have an initialization routine
 # of a given name (top.o -> _initialize_top, etc.).
@@ -1581,7 +1598,9 @@
 	ppcnbsd-nat.c ppcnbsd-tdep.c \
 	ppcobsd-nat.c ppcobsd-tdep.c \
 	procfs.c \
-	remote-m32r-sdi.c remote-mips.c \
+	remote-m32r-sdi.c \
+	remote-mdi.c \
+	remote-mips.c \
 	remote-sim.c \
 	dcache.c \
 	rs6000-nat.c rs6000-tdep.c \
@@ -1624,6 +1643,13 @@
 	$(CC) -c $(INTERNAL_CFLAGS) $(TARGET_SYSTEM_ROOT_DEFINE) \
 		-DBINDIR=\"$(bindir)\" $(srcdir)/main.c
 
+remote-mdi.o: remote-mdi.c
+	$(CC) -c $(IDE_CFLAGS) $(ITCL_CFLAGS) \
+		 $(ITK_CFLAGS) $(TCL_CFLAGS) $(TK_CFLAGS) \
+		 -I- $(INTERNAL_CFLAGS) $(X11_CFLAGS) $(GDBTK_CFLAGS) \
+		-DMIPSSIM_LIBRARY=\"$(datadir)\"\
+		$(srcdir)/remote-mdi.c
+
 # FIXME: cagney/2003-08-10: "monitor.c" gets -Wformat-nonliteral
 # errors.  It turns out that that is the least of monitor.c's
 # problems.  The function print_vsprintf appears to be using
@@ -2629,6 +2655,11 @@
 	$(exceptions_h) $(remote_fileio_h)
 remote-m32r-sdi.o: remote-m32r-sdi.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
 	$(inferior_h) $(target_h) $(regcache_h) $(gdb_string_h) $(serial_h)
+remote-mdi.o: remote-mdi.c $(defs_h) $(inferior_h) $(bfd_h) $(symfile_h) \
+	$(gdbcmd_h) $(gdbcore_h) $(serial_h) $(target_h) \
+	$(gdb_regex_h) $(gmon_h) $(gmon_out_h) $(gdb_string_h) $(gdb_stat_h) \
+	$(regcache_h) $(readline_h) $(dcache_h) $(symfile_h) $(arch_utils_h) \
+	$(mips_tdep_h) mdi.h mdilink.h mdimips.h
 remote-mips.o: remote-mips.c $(defs_h) $(inferior_h) $(bfd_h) $(symfile_h) \
 	$(gdbcmd_h) $(gdbcore_h) $(serial_h) $(target_h) $(exceptions_h) \
 	$(gdb_string_h) $(gdb_stat_h) $(regcache_h) \
Index: binutils-quilt/src/gdb/top.c
===================================================================
--- binutils-quilt.orig/src/gdb/top.c	2008-02-14 14:22:13.000000000 +0000
+++ binutils-quilt/src/gdb/top.c	2008-02-14 14:49:36.000000000 +0000
@@ -122,6 +122,9 @@
 /* The directory name is actually stored here (usually).  */
 char gdb_dirbuf[1024];
 
+/* The name by which gdb was invoked.  */
+char *gdb_program_name;
+
 /* Function to call before reading a command, if nonzero.
    The function receives two args: an input stream,
    and a prompt string.  */
@@ -1623,6 +1626,8 @@
 void
 gdb_init (char *argv0)
 {
+  gdb_program_name = argv0;
+
   if (pre_init_ui_hook)
     pre_init_ui_hook ();
 
Index: binutils-quilt/src/gdb/cli/cli-decode.c
===================================================================
--- binutils-quilt.orig/src/gdb/cli/cli-decode.c	2008-02-14 14:22:13.000000000 +0000
+++ binutils-quilt/src/gdb/cli/cli-decode.c	2008-02-14 14:49:36.000000000 +0000
@@ -368,6 +368,8 @@
     *set_result = set;
   if (show_result != NULL)
     *show_result = show;
+  if (var_type == var_filename)
+    set_cmd_completer (set, filename_completer);
 }
 
 struct cmd_list_element *
Index: binutils-quilt/src/gdb/configure.tgt
===================================================================
--- binutils-quilt.orig/src/gdb/configure.tgt	2008-02-14 14:22:13.000000000 +0000
+++ binutils-quilt/src/gdb/configure.tgt	2008-02-14 14:49:36.000000000 +0000
@@ -307,6 +307,21 @@
 	gdb_target_obs="mips-tdep.o mips64obsd-tdep.o \
 			corelow.o solib.o solib-svr4.o"
 	;;
+mips*-sde*-elf*)
+	# Target: MIPS SDE
+	gdb_target_obs="mips-tdep.o remote-mips.o"
+	case "${gdb_host}" in
+	cygwin | sol2 | linux | hpux11)
+		# Need to support dlopen et al for MDI to work.
+		gdb_target_obs="${gdb_target_obs} remote-mdi.o"
+		CONFIG_ALL="${CONFIG_ALL} mipssim.cfg"
+		CONFIG_INSTALL="${CONFIG_INSTALL} install-mipssim"
+		CONFIG_UNINSTALL="${CONFIG_UNINSTALL} uninstall-mipssim"
+		CONFIG_CLEAN="${CONFIG_CLEAN} clean-mipssim"
+		;;
+	esac
+	gdb_sim=../sim/mips/libsim.a
+	;;
 mips*-*-*)
 	# Target: MIPS
 	gdb_target_obs="mips-tdep.o"
Index: binutils-quilt/src/gdb/mdilink.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/mdilink.h	2008-02-14 14:49:36.000000000 +0000
@@ -0,0 +1,200 @@
+/* MDI (Microprocessor Debug Interface) DLL loader definitions.
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   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.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MDILINK_H
+#define _MDILINK_H
+
+#if defined(_WIN32) || defined(__CYGWIN32__)
+
+/* Have to look for symbols
+   prefixed with _ and postfixed with @ sizeof args.  */
+#define FMDIAbort "_MDIAbort@4"
+#define FMDIAttachTM "_MDIAttachTM@12"
+#define FMDIBpQuery "_MDIBpQuery@12"
+#define FMDICacheFlush "_MDICacheFlush@12"
+#define FMDICacheQuery "_MDICacheQuery@8"
+#define FMDIClearBp "_MDIClearBp@8"
+#define FMDIClearTeam "_MDIClearTeam@8"
+#define FMDIClose "_MDIClose@8"
+#define FMDIConnect "_MDIConnect@12"
+#define FMDICreateTeam "_MDICreateTeam@8"
+#define FMDIDestroyTeam "_MDIDestroyTeam@8"
+#define FMDIDetachTM "_MDIDetachTM@12"
+#define FMDIDQuery "_MDIDQuery@12"
+#define FMDIDisableBp "_MDIDisableBp@8"
+#define FMDIDisconnect "_MDIDisconnect@8"
+#define FMDIDoCommand "_MDIDoCommand@8"
+#define FMDIEnableBp "_MDIEnableBp@8"
+#define FMDIExecute "_MDIExecute@4"
+#define FMDIFill "_MDIFill@36"
+#define FMDIFind "_MDIFind@48"
+#define FMDIGetTC "_MDIGetTC@8"
+#define FMDIHwBpQuery "_MDIHwBpQuery@12"
+#define FMDIMove "_MDIMove@40"
+#define FMDIOpen "_MDIOpen@16"
+#define FMDIQueryTC "_MDIQueryTC@12"
+#define FMDIQueryTM "_MDIQueryTM@16"
+#define FMDIQueryTeams "_MDIQueryTeams@12"
+#define FMDIRead "_MDIRead@28"
+#define FMDIReadList "_MDIReadList@20"
+#define FMDIReset "_MDIReset@8"
+#define FMDIRunState "_MDIRunState@12"
+#define FMDISetBp "_MDISetBp@8"
+#define FMDISetRunMode "_MDISetRunMode@16"
+#define FMDISetSWBp "_MDISetSWBp@20"
+#define FMDISetTC "_MDISetTC@8"
+#define FMDISetTCRunMode "_MDISetTCRunMode@16"
+#define FMDIStep "_MDIStep@12"
+#define FMDIStop "_MDIStop@4"
+#define FMDITCGet "_MDITCGet@8"
+#define FMDITCQuery "_MDITCQuery@12"
+#define FMDITCSet "_MDITCSet@8"
+#define FMDITCSetRunMode "_MDITCSetRunMode@16"
+#define FMDITGClose "_MDITGClose@8"
+#define FMDITGExecute "_MDITGExecute@4"
+#define FMDITGOpen "_MDITGOpen@16"
+#define FMDITGQuery "_MDITGQuery@12"
+#define FMDITGStop "_MDITGStop@4"
+#define FMDITMAttach "_MDITMAttach@12"
+#define FMDITMDetach "_MDITMDetach@12"
+#define FMDITMQuery "_MDITMQuery@16"
+#define FMDITeamClear "_MDITeamClear@8"
+#define FMDITeamCreate "_MDITeamCreate@8"
+#define FMDITeamDestroy "_MDITeamDestroy@8"
+#define FMDITeamExecute "_MDITeamExecute@8"
+#define FMDITraceClear "_MDITraceClear@4"
+#define FMDITraceCount "_MDITraceCount@8"
+#define FMDITraceDisable "_MDITraceDisable@4"
+#define FMDITraceEnable "_MDITraceEnable@4"
+#define FMDITraceRead "_MDITraceRead@20"
+#define FMDITraceStatus "_MDITraceStatus@8"
+#define FMDIVersion "_MDIVersion@4"
+#define FMDIWrite "_MDIWrite@28"
+#define FMDIWriteList "_MDIWriteList@20"
+#define FMDITraceRead "_MDITraceRead@20"
+
+/* MIPSsim special interfaces.  */
+#define FMIPSsim_SetConfigFile "_MIPSsim_SetConfigFile@8"
+#define FMIPSsim_CreateProfile "_MIPSsim_CreateProfile@24"
+#define FMIPSsim_DestroyProfile "_MIPSsim_DestroyProfile@8"
+#define FMIPSsim_StartProfile "_MIPSsim_StartProfile@8"
+#define FMIPSsim_StopProfile "_MIPSsim_StopProfile@8"
+#define FMIPSsim_ClearProfile "_MIPSsim_ClearProfile@8"
+#define FMIPSsim_FetchProfile "_MIPSsim_FetchProfile@16"
+#define FMIPSsim_FreeProfileData "_MIPSsim_FreeProfileData@8"
+#define FMIPSsim_GetTraceLevel "_MIPSsim_GetTraceLevel@8"
+#define FMIPSsim_SetTraceLevel "_MIPSsim_SetTraceLevel@8"
+#define FMIPSsim_GetStats "_MIPSsim_GetStats@12"
+#define FMIPSsim_ClearStats "_MIPSsim_ClearStats@8"
+#define FMIPSsim_GetPerfCounter "_MIPSsim_GetPerfCounter@20"
+#define FMIPSsim_ZeroPerfCounter "_MIPSsim_ZeroPerfCounter@16"
+#define FMIPSsim_ZeroPerfCounters "_MIPSsim_ZeroPerfCounters@4"
+#define FMIPSsim_GetVersion "_MIPSsim_GetVersion@16"
+
+#else
+
+/* Unix, just look for the symbol name.  */
+#define FMDIAbort "MDIAbort"
+#define FMDIAttachTM "MDIAttachTM"
+#define FMDIBpQuery "MDIBpQuery"
+#define FMDICacheFlush "MDICacheFlush"
+#define FMDICacheQuery "MDICacheQuery"
+#define FMDIClearBp "MDIClearBp"
+#define FMDIClearTeam "MDIClearTeam"
+#define FMDIClose "MDIClose"
+#define FMDIConnect "MDIConnect"
+#define FMDICreateTeam "MDICreateTeam"
+#define FMDIDQuery "MDIDQuery"
+#define FMDIDestroyTeam "MDIDestroyTeam"
+#define FMDIDetachTM "MDIDetachTM"
+#define FMDIDisableBp "MDIDisableBp"
+#define FMDIDisconnect "MDIDisconnect"
+#define FMDIDoCommand "MDIDoCommand"
+#define FMDIEnableBp "MDIEnableBp"
+#define FMDIExecute "MDIExecute"
+#define FMDIFill "MDIFill"
+#define FMDIFind "MDIFind"
+#define FMDIGetTC "MDIGetTC"
+#define FMDIHwBpQuery "MDIHwBpQuery"
+#define FMDIMove "MDIMove"
+#define FMDIOpen "MDIOpen"
+#define FMDIQueryTC "MDIQueryTC"
+#define FMDIQueryTM "MDIQueryTM"
+#define FMDIQueryTeams "MDIQueryTeams"
+#define FMDIRead "MDIRead"
+#define FMDIReadList "MDIReadList"
+#define FMDIReset "MDIReset"
+#define FMDIRunState "MDIRunState"
+#define FMDISetBp "MDISetBp"
+#define FMDISetRunMode "MDISetRunMode"
+#define FMDISetSWBp "MDISetSWBp"
+#define FMDISetTC "MDISetTC"
+#define FMDISetTCRunMode "MDISetTCRunMode"
+#define FMDIStep "MDIStep"
+#define FMDIStop "MDIStop"
+#define FMDITCGet "MDITCGet"
+#define FMDITCQuery "MDITCQuery"
+#define FMDITCSet "MDITCSet"
+#define FMDITCSetRunMode "MDITCSetRunMode"
+#define FMDITGClose "MDITGClose"
+#define FMDITGExecute "MDITGExecute"
+#define FMDITGOpen "MDITGOpen"
+#define FMDITGQuery "MDITGQuery"
+#define FMDITGStop "MDITGStop"
+#define FMDITMAttach "MDITMAttach"
+#define FMDITMDetach "MDITMDetach"
+#define FMDITMQuery "MDITMQuery"
+#define FMDITeamClear "MDITeamClear"
+#define FMDITeamCreate "MDITeamCreate"
+#define FMDITeamDestroy "MDITeamDestroy"
+#define FMDITeamExecute "MDITeamExecute"
+#define FMDITMQuery "MDITMQuery"
+#define FMDITeamClear "MDITeamClear"
+#define FMDITeamCreate "MDITeamCreate"
+#define FMDITeamDestroy "MDITeamDestroy"
+#define FMDITeamExecute "MDITeamExecute"
+#define FMDITraceClear "MDITraceClear"
+#define FMDITraceCount "MDITraceCount"
+#define FMDITraceDisable "MDITraceDisable"
+#define FMDITraceEnable "MDITraceEnable"
+#define FMDITraceRead "MDITraceRead"
+#define FMDITraceStatus "MDITraceStatus"
+#define FMDIVersion "MDIVersion"
+#define FMDIWrite "MDIWrite"
+#define FMDIWriteList "MDIWriteList"
+
+/* MIPSsim special interfaces.  */
+#define FMIPSsim_SetConfigFile "MIPSsim_SetConfigFile"
+#define FMIPSsim_CreateProfile "MIPSsim_CreateProfile"
+#define FMIPSsim_DestroyProfile "MIPSsim_DestroyProfile"
+#define FMIPSsim_StartProfile "MIPSsim_StartProfile"
+#define FMIPSsim_StopProfile "MIPSsim_StopProfile"
+#define FMIPSsim_ClearProfile "MIPSsim_ClearProfile"
+#define FMIPSsim_FetchProfile "MIPSsim_FetchProfile"
+#define FMIPSsim_FreeProfileData "MIPSsim_FreeProfileData"
+#define FMIPSsim_GetTraceLevel "MIPSsim_GetTraceLevel"
+#define FMIPSsim_SetTraceLevel "MIPSsim_SetTraceLevel"
+#define FMIPSsim_GetStats "MIPSsim_GetStats"
+#define FMIPSsim_ClearStats "MIPSsim_ClearStats"
+#define FMIPSsim_GetPerfCounter "MIPSsim_GetPerfCounter"
+#define FMIPSsim_ZeroPerfCounter "MIPSsim_ZeroPerfCounter"
+#define FMIPSsim_ZeroPerfCounters "MIPSsim_ZeroPerfCounters"
+#define FMIPSsim_GetVersion "MIPSsim_GetVersion"
+
+#endif
+
+#endif


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]