diff --git a/ext/gdb-xml/power-core.xml b/ext/gdb-xml/power-core.xml
new file mode 100644
index 0000000000..6cf57b1379
--- /dev/null
+++ b/ext/gdb-xml/power-core.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ext/gdb-xml/power-fpu.xml b/ext/gdb-xml/power-fpu.xml
new file mode 100644
index 0000000000..145eede7fc
--- /dev/null
+++ b/ext/gdb-xml/power-fpu.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ext/gdb-xml/power.xml b/ext/gdb-xml/power.xml
deleted file mode 100644
index da5a07ca91..0000000000
--- a/ext/gdb-xml/power.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-
-
-
-
-
- powerpc
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ext/gdb-xml/power64-core.xml b/ext/gdb-xml/power64-core.xml
new file mode 100644
index 0000000000..cd5bc6d0ea
--- /dev/null
+++ b/ext/gdb-xml/power64-core.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ext/gdb-xml/powerpc-32.xml b/ext/gdb-xml/powerpc-32.xml
new file mode 100644
index 0000000000..a537f927d6
--- /dev/null
+++ b/ext/gdb-xml/powerpc-32.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ powerpc:common
+
+
+
diff --git a/ext/gdb-xml/powerpc-64.xml b/ext/gdb-xml/powerpc-64.xml
new file mode 100644
index 0000000000..a762f8cc25
--- /dev/null
+++ b/ext/gdb-xml/powerpc-64.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ powerpc:common64
+
+
+
diff --git a/src/arch/power/SConscript b/src/arch/power/SConscript
index 24bf5dbbbd..720455c588 100644
--- a/src/arch/power/SConscript
+++ b/src/arch/power/SConscript
@@ -59,4 +59,8 @@ if env['TARGET_ISA'] == 'power':
ISADesc('isa/main.isa')
- GdbXml('power.xml', 'gdb_xml_power')
+ GdbXml('power-core.xml', 'gdb_xml_power_core')
+ GdbXml('power64-core.xml', 'gdb_xml_power64_core')
+ GdbXml('power-fpu.xml', 'gdb_xml_power_fpu')
+ GdbXml('powerpc-32.xml', 'gdb_xml_powerpc_32')
+ GdbXml('powerpc-64.xml', 'gdb_xml_powerpc_64')
diff --git a/src/arch/power/remote_gdb.cc b/src/arch/power/remote_gdb.cc
index 886a8402a3..5536879a6b 100644
--- a/src/arch/power/remote_gdb.cc
+++ b/src/arch/power/remote_gdb.cc
@@ -136,7 +136,12 @@
#include
-#include "blobs/gdb_xml_power.hh"
+#include "arch/power/regs/misc.hh"
+#include "blobs/gdb_xml_power64_core.hh"
+#include "blobs/gdb_xml_power_core.hh"
+#include "blobs/gdb_xml_power_fpu.hh"
+#include "blobs/gdb_xml_powerpc_32.hh"
+#include "blobs/gdb_xml_powerpc_64.hh"
#include "cpu/thread_state.hh"
#include "debug/GDBAcc.hh"
#include "debug/GDBMisc.hh"
@@ -149,7 +154,7 @@ namespace gem5
using namespace PowerISA;
RemoteGDB::RemoteGDB(System *_system, int _port)
- : BaseRemoteGDB(_system, _port), regCache(this)
+ : BaseRemoteGDB(_system, _port), regCache32(this), regCache64(this)
{
}
@@ -173,22 +178,26 @@ RemoteGDB::PowerGdbRegCache::getRegs(ThreadContext *context)
{
DPRINTF(GDBAcc, "getRegs in remotegdb \n");
+ Msr msr = context->readIntReg(INTREG_MSR);
+ ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big);
+
// Default order on 32-bit PowerPC:
// R0-R31 (32-bit each), F0-F31 (64-bit IEEE754 double),
- // PC, MSR, CR, LR, CTR, XER (32-bit each)
+ // PC, MSR, CR, LR, CTR, XER, FPSCR (32-bit each)
for (int i = 0; i < NumIntArchRegs; i++)
- r.gpr[i] = htobe((uint32_t)context->readIntReg(i));
+ r.gpr[i] = htog((uint32_t)context->readIntReg(i), order);
for (int i = 0; i < NumFloatArchRegs; i++)
r.fpr[i] = context->readFloatReg(i);
- r.pc = htobe((uint32_t)context->pcState().pc());
- r.msr = 0; // Is MSR modeled?
- r.cr = htobe((uint32_t)context->readIntReg(INTREG_CR));
- r.lr = htobe((uint32_t)context->readIntReg(INTREG_LR));
- r.ctr = htobe((uint32_t)context->readIntReg(INTREG_CTR));
- r.xer = htobe((uint32_t)context->readIntReg(INTREG_XER));
+ r.pc = htog((uint32_t)context->pcState().pc(), order);
+ r.msr = 0; // MSR is privileged, hence not exposed here
+ r.cr = htog((uint32_t)context->readIntReg(INTREG_CR), order);
+ r.lr = htog((uint32_t)context->readIntReg(INTREG_LR), order);
+ r.ctr = htog((uint32_t)context->readIntReg(INTREG_CTR), order);
+ r.xer = htog((uint32_t)context->readIntReg(INTREG_XER), order);
+ r.fpscr = htog((uint32_t)context->readIntReg(INTREG_FPSCR), order);
}
void
@@ -196,24 +205,89 @@ RemoteGDB::PowerGdbRegCache::setRegs(ThreadContext *context) const
{
DPRINTF(GDBAcc, "setRegs in remotegdb \n");
+ Msr msr = context->readIntReg(INTREG_MSR);
+ ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big);
+
for (int i = 0; i < NumIntArchRegs; i++)
- context->setIntReg(i, betoh(r.gpr[i]));
+ context->setIntReg(i, gtoh(r.gpr[i], order));
for (int i = 0; i < NumFloatArchRegs; i++)
context->setFloatReg(i, r.fpr[i]);
- context->pcState(betoh(r.pc));
- // Is MSR modeled?
- context->setIntReg(INTREG_CR, betoh(r.cr));
- context->setIntReg(INTREG_LR, betoh(r.lr));
- context->setIntReg(INTREG_CTR, betoh(r.ctr));
- context->setIntReg(INTREG_XER, betoh(r.xer));
+ auto pc = context->pcState();
+ pc.byteOrder(order);
+ pc.set(gtoh(r.pc, order));
+ context->pcState(pc);
+ // MSR is privileged, hence not modified here
+ context->setIntReg(INTREG_CR, gtoh(r.cr, order));
+ context->setIntReg(INTREG_LR, gtoh(r.lr, order));
+ context->setIntReg(INTREG_CTR, gtoh(r.ctr, order));
+ context->setIntReg(INTREG_XER, gtoh(r.xer, order));
+ context->setIntReg(INTREG_FPSCR, gtoh(r.fpscr, order));
+}
+
+void
+RemoteGDB::Power64GdbRegCache::getRegs(ThreadContext *context)
+{
+ DPRINTF(GDBAcc, "getRegs in remotegdb \n");
+
+ Msr msr = context->readIntReg(INTREG_MSR);
+ ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big);
+
+ // Default order on 64-bit PowerPC:
+ // GPRR0-GPRR31 (64-bit each), FPR0-FPR31 (64-bit IEEE754 double),
+ // CIA, MSR, CR, LR, CTR, XER, FPSCR (only CR, XER, FPSCR are 32-bit
+ // each and the rest are 64-bit)
+
+ for (int i = 0; i < NumIntArchRegs; i++)
+ r.gpr[i] = htog(context->readIntReg(i), order);
+
+ for (int i = 0; i < NumFloatArchRegs; i++)
+ r.fpr[i] = context->readFloatReg(i);
+
+ r.pc = htog(context->pcState().pc(), order);
+ r.msr = 0; // MSR is privileged, hence not exposed here
+ r.cr = htog((uint32_t)context->readIntReg(INTREG_CR), order);
+ r.lr = htog(context->readIntReg(INTREG_LR), order);
+ r.ctr = htog(context->readIntReg(INTREG_CTR), order);
+ r.xer = htog((uint32_t)context->readIntReg(INTREG_XER), order);
+ r.fpscr = htog((uint32_t)context->readIntReg(INTREG_FPSCR), order);
+}
+
+void
+RemoteGDB::Power64GdbRegCache::setRegs(ThreadContext *context) const
+{
+ DPRINTF(GDBAcc, "setRegs in remotegdb \n");
+
+ Msr msr = context->readIntReg(INTREG_MSR);
+ ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big);
+
+ for (int i = 0; i < NumIntArchRegs; i++)
+ context->setIntReg(i, gtoh(r.gpr[i], order));
+
+ for (int i = 0; i < NumFloatArchRegs; i++)
+ context->setFloatReg(i, r.fpr[i]);
+
+ auto pc = context->pcState();
+ pc.byteOrder(order);
+ pc.set(gtoh(r.pc, order));
+ context->pcState(pc);
+ // MSR is privileged, hence not modified here
+ context->setIntReg(INTREG_CR, gtoh(r.cr, order));
+ context->setIntReg(INTREG_LR, gtoh(r.lr, order));
+ context->setIntReg(INTREG_CTR, gtoh(r.ctr, order));
+ context->setIntReg(INTREG_XER, gtoh(r.xer, order));
+ context->setIntReg(INTREG_FPSCR, gtoh(r.fpscr, order));
}
BaseGdbRegCache*
RemoteGDB::gdbRegs()
{
- return ®Cache;
+ Msr msr = context()->readIntReg(INTREG_MSR);
+ if (msr.sf)
+ return ®Cache64;
+ else
+ return ®Cache32;
}
bool
@@ -222,10 +296,20 @@ RemoteGDB::getXferFeaturesRead(const std::string &annex, std::string &output)
#define GDB_XML(x, s) \
{ x, std::string(reinterpret_cast(Blobs::s), \
Blobs::s ## _len) }
- static const std::map annexMap {
- GDB_XML("target.xml", gdb_xml_power),
+ static const std::map annexMap32{
+ GDB_XML("target.xml", gdb_xml_powerpc_32),
+ GDB_XML("power-core.xml", gdb_xml_power_core),
+ GDB_XML("power-fpu.xml", gdb_xml_power_fpu)
+ };
+ static const std::map annexMap64{
+ GDB_XML("target.xml", gdb_xml_powerpc_64),
+ GDB_XML("power64-core.xml", gdb_xml_power64_core),
+ GDB_XML("power-fpu.xml", gdb_xml_power_fpu)
};
#undef GDB_XML
+
+ Msr msr = context()->readIntReg(INTREG_MSR);
+ auto& annexMap = msr.sf ? annexMap64 : annexMap32;
auto it = annexMap.find(annex);
if (it == annexMap.end())
return false;
diff --git a/src/arch/power/remote_gdb.hh b/src/arch/power/remote_gdb.hh
index fa21df5123..dc7ae65855 100644
--- a/src/arch/power/remote_gdb.hh
+++ b/src/arch/power/remote_gdb.hh
@@ -53,7 +53,7 @@ class RemoteGDB : public BaseRemoteGDB
{
using BaseGdbRegCache::BaseGdbRegCache;
private:
- struct
+ struct GEM5_PACKED
{
uint32_t gpr[NumIntArchRegs];
uint64_t fpr[NumFloatArchRegs];
@@ -63,7 +63,9 @@ class RemoteGDB : public BaseRemoteGDB
uint32_t lr;
uint32_t ctr;
uint32_t xer;
+ uint32_t fpscr;
} r;
+
public:
char *data() const { return (char *)&r; }
size_t size() const { return sizeof(r); }
@@ -76,16 +78,48 @@ class RemoteGDB : public BaseRemoteGDB
}
};
- PowerGdbRegCache regCache;
+ class Power64GdbRegCache : public BaseGdbRegCache
+ {
+ using BaseGdbRegCache::BaseGdbRegCache;
+ private:
+ struct GEM5_PACKED
+ {
+ uint64_t gpr[NumIntArchRegs];
+ uint64_t fpr[NumFloatArchRegs];
+ uint64_t pc;
+ uint64_t msr;
+ uint32_t cr;
+ uint64_t lr;
+ uint64_t ctr;
+ uint32_t xer;
+ uint32_t fpscr;
+ } r;
+
+ public:
+ char *data() const { return (char *)&r; }
+ size_t size() const { return sizeof(r); }
+ void getRegs(ThreadContext*);
+ void setRegs(ThreadContext*) const;
+ const std::string
+ name() const
+ {
+ return gdb->name() + ".Power64GdbRegCache";
+ }
+ };
+
+ PowerGdbRegCache regCache32;
+ Power64GdbRegCache regCache64;
public:
RemoteGDB(System *_system, int _port);
BaseGdbRegCache *gdbRegs();
+
std::vector
availableFeatures() const
{
return {"qXfer:features:read+"};
};
+
bool getXferFeaturesRead(const std::string &annex, std::string &output);
};