rm) {
+ rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Functionality not supported", null)); //$NON-NLS-1$
+ rm.done();
+ }
+}
diff --git a/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/MIRegisters.java b/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/MIRegisters.java
new file mode 100644
index 00000000000..56c17b4eb45
--- /dev/null
+++ b/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/MIRegisters.java
@@ -0,0 +1,583 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Ericsson - Modified for additional features in DSF Reference Implementation
+ *******************************************************************************/
+package org.eclipse.dd.mi.service;
+
+import java.util.Hashtable;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.datamodel.AbstractDMContext;
+import org.eclipse.dd.dsf.datamodel.DMContexts;
+import org.eclipse.dd.dsf.datamodel.IDMContext;
+import org.eclipse.dd.dsf.debug.service.IRegisters;
+import org.eclipse.dd.dsf.debug.service.IRunControl;
+import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
+import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMData;
+import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
+import org.eclipse.dd.dsf.debug.service.command.CommandCache;
+import org.eclipse.dd.dsf.debug.service.command.ICommandControl;
+import org.eclipse.dd.dsf.service.AbstractDsfService;
+import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.mi.internal.MIPlugin;
+import org.eclipse.dd.mi.service.command.commands.MIDataListRegisterNames;
+import org.eclipse.dd.mi.service.command.commands.MIDataListRegisterValues;
+import org.eclipse.dd.mi.service.command.output.MIDataListRegisterNamesInfo;
+import org.eclipse.dd.mi.service.command.output.MIDataListRegisterValuesInfo;
+import org.eclipse.dd.mi.service.command.output.MIInfo;
+import org.eclipse.dd.mi.service.command.output.MIRegisterValue;
+import org.osgi.framework.BundleContext;
+
+
+/**
+ *
+ *
+ * Implementation note:
+ * This class implements event handlers for the events that are generated by
+ * this service itself. When the event is dispatched, these handlers will
+ * be called first, before any of the clients. These handlers update the
+ * service's internal state information to make them consistent with the
+ * events being issued. Doing this in the handlers as opposed to when
+ * the events are generated, guarantees that the state of the service will
+ * always be consistent with the events.
+ */
+
+public class MIRegisters extends AbstractDsfService implements IRegisters {
+ private static final String BLANK_STRING = ""; //$NON-NLS-1$
+ /*
+ * Support class used to construct Register Group DMCs.
+ */
+
+ public static class MIRegisterGroupDMC extends AbstractDMContext implements IRegisterGroupDMContext {
+ private int fGroupNo;
+ private String fGroupName;
+
+ public MIRegisterGroupDMC(MIRegisters service, IContainerDMContext contDmc, int groupNo, String groupName) {
+ super(service.getSession().getId(), new IDMContext[] { contDmc });
+ fGroupNo = groupNo;
+ fGroupName = groupName;
+ }
+
+ public int getGroupNo() { return fGroupNo; }
+ public String getName() { return fGroupName; }
+
+ @Override
+ public boolean equals(Object other) {
+ return ((super.baseEquals(other)) && (((MIRegisterGroupDMC) other).fGroupNo == fGroupNo) &&
+ (((MIRegisterGroupDMC) other).fGroupName.equals(fGroupName)));
+ }
+
+ @Override
+ public int hashCode() { return super.baseHashCode() ^ fGroupNo; }
+ @Override
+ public String toString() { return baseToString() + ".group[" + fGroupNo + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /*
+ * Support class used to construct Register DMCs.
+ */
+
+ public static class MIRegisterDMC extends AbstractDMContext implements IRegisterDMContext {
+ private int fRegNo;
+ private String fRegName;
+
+ public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, int regNo, String regName) {
+ super(service.getSession().getId(),
+ new IDMContext[] { group });
+ fRegNo = regNo;
+ fRegName = regName;
+ }
+
+ public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, IMIExecutionDMContext execDmc, int regNo, String regName) {
+ super(service.getSession().getId(),
+ new IDMContext[] { execDmc, group });
+ fRegNo = regNo;
+ fRegName = regName;
+ }
+
+ public int getRegNo() { return fRegNo; }
+ public String getName() { return fRegName; }
+
+ @Override
+ public boolean equals(Object other) {
+ return ((super.baseEquals(other)) && (((MIRegisterDMC) other).fRegNo == fRegNo) &&
+ (((MIRegisterDMC) other).fRegName.equals(fRegName)));
+ }
+
+ @Override
+ public int hashCode() { return super.baseHashCode() ^ fRegNo; }
+ @Override
+ public String toString() { return baseToString() + ".register[" + fRegNo + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /*
+ * Event class to notify register value is changed
+ */
+ public static class RegisterChangedDMEvent implements IRegisters.IRegisterChangedDMEvent {
+
+ private final IRegisterDMContext fRegisterDmc;
+
+ RegisterChangedDMEvent(IRegisterDMContext registerDMC) {
+ fRegisterDmc = registerDMC;
+ }
+
+ public IRegisterDMContext getDMContext() {
+ return fRegisterDmc;
+ }
+ }
+
+ /*
+ * Internal control variables.
+ */
+
+ private MIRegisterGroupDMC fGeneralRegistersGroupDMC;
+ private CommandCache fRegisterNameCache; // Cache for holding the Register Names in the single Group
+ private CommandCache fRegisterValueCache; // Cache for holding the Register Values
+
+ public MIRegisters(DsfSession session)
+ {
+ super(session);
+ }
+
+ @Override
+ protected BundleContext getBundleContext()
+ {
+ return MIPlugin.getBundleContext();
+ }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleOK() {
+ doInitialize(requestMonitor);
+ }});
+ }
+
+ private void doInitialize(RequestMonitor requestMonitor) {
+ /*
+ * Create the lower level register cache.
+ */
+ fRegisterValueCache = new CommandCache(getServicesTracker().getService(ICommandControl.class));
+ fRegisterNameCache = new CommandCache(getServicesTracker().getService(ICommandControl.class));
+
+ /*
+ * Signup so we see events. We use these events to decide how to manage
+ * any local caches we are providing as well as the lower level register
+ * cache we create to get/set registers on the target.
+ */
+ getSession().addServiceEventListener(this, null);
+
+ /*
+ * Make ourselves known so clients can use us.
+ */
+ register(new String[]{IRegisters.class.getName(), MIRegisters.class.getName()}, new Hashtable());
+
+ requestMonitor.done();
+ }
+
+ @Override
+ public void shutdown(RequestMonitor requestMonitor)
+ {
+ unregister();
+ getSession().removeServiceEventListener(this);
+ super.shutdown(requestMonitor);
+ }
+
+ public boolean isValid() { return true; }
+
+ @SuppressWarnings("unchecked")
+ public void getModelData(IDMContext dmc, DataRequestMonitor> rm) {
+ /*
+ * This is the method which is called when actual results need to be returned. We
+ * can be called either with a service DMC for which we return oureslves or we can
+ * be called with the DMC's we have handed out. If the latter is the case then we
+ * datamine by talking to the Debug Engine.
+ */
+
+ if (dmc instanceof MIRegisterGroupDMC) {
+ getRegisterGroupData((MIRegisterGroupDMC)dmc, (DataRequestMonitor)rm);
+ } else if (dmc instanceof MIRegisterDMC) {
+ getRegisterData((MIRegisterDMC)dmc, (DataRequestMonitor)rm);
+ } else if (dmc instanceof FormattedValueDMContext) {
+ getFormattedExpressionValue((FormattedValueDMContext)dmc, (DataRequestMonitor)rm);
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, -1, "Unknown DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ public void getFormattedExpressionValue(FormattedValueDMContext dmc, DataRequestMonitor rm) {
+ if (dmc.getParents().length == 1 && dmc.getParents()[0] instanceof MIRegisterDMC) {
+ getRegisterDataValue( (MIRegisterDMC) dmc.getParents()[0], dmc.getFormatID(), rm);
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ public void getRegisterGroupData(IRegisterGroupDMContext regGroupDmc, DataRequestMonitor rm) {
+ /**
+ * For the GDB GDBMI implementation there is only on group. The GPR and FPU registers are grouped into
+ * one set. We are going to hard wire this set as the "General Registers".
+ */
+ class RegisterGroupData implements IRegisterGroupDMData {
+ public String getName() { return "General Registers"; } //$NON-NLS-1$
+ public String getDescription() { return "General Purpose and FPU Register Group"; } //$NON-NLS-1$
+ }
+
+ rm.setData( new RegisterGroupData() ) ;
+ rm.done();
+ }
+
+ public void getBitFieldData(IBitFieldDMContext dmc, DataRequestMonitor rm) {
+ rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Bit fields not yet supported", null)); //$NON-NLS-1$
+ rm.done();
+ }
+
+ /**
+ * For the GDB GDBMI implementation there is only on group. We represent
+ * this group as a single list we maintain within this service. So we
+ * need to search this list to see if we have a current value.
+ */
+ public void getRegisterData(IRegisterDMContext regDmc , final DataRequestMonitor rm) {
+ if (regDmc instanceof MIRegisterDMC) {
+ final MIRegisterDMC miRegDmc = (MIRegisterDMC)regDmc;
+ IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(regDmc, IMIExecutionDMContext.class);
+ // Create register DMC with name if execution DMC is not present.
+ if(execDmc == null){
+ rm.setData(new RegisterData(miRegDmc.getName(), BLANK_STRING, false));
+ rm.done();
+ return;
+ }
+
+ int[] regnos = {miRegDmc.getRegNo()};
+ fRegisterValueCache.execute(
+ new MIDataListRegisterValues(execDmc, MIFormat.HEXADECIMAL, regnos),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleOK() {
+ // Retrieve the register value.
+ MIRegisterValue[] regValue = getData().getMIRegisterValues();
+
+ // If the list is empty just return empty handed.
+ if (regValue.length == 0) {
+ assert false : "Backend protocol error"; //$NON-NLS-1$
+ //done.setStatus(new Status(IStatus.ERROR, IDsfService.INTERNAL_ERROR ,));
+ rm.done();
+ return;
+ }
+
+ // We can determine if the register is floating point because
+ // GDB returns this additional information as part of the value.
+ MIRegisterValue reg = regValue[0];
+ boolean isFloat = false;
+
+ if ( reg.getValue().contains("float")) { //$NON-NLS-1$
+ isFloat = true;
+ }
+
+ // Return the new register attributes.
+ rm.setData(new RegisterData(miRegDmc.getName(), BLANK_STRING, isFloat));
+ rm.done();
+ }
+ });
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ private void getRegisterDataValue( final MIRegisterDMC regDmc, final String formatId, final DataRequestMonitor