summaryrefslogtreecommitdiff
path: root/src/arch/x86/memhelpers.hh
diff options
context:
space:
mode:
authorSteve Reinhardt <steve.reinhardt@amd.com>2016-02-06 17:21:20 -0800
committerSteve Reinhardt <steve.reinhardt@amd.com>2016-02-06 17:21:20 -0800
commit5200e04e92b487181d4a678231564272730e04a2 (patch)
tree83a8a71c6dffa7a58a5f10c3232022ce2a4741ff /src/arch/x86/memhelpers.hh
parentf5343df1e1999e66c39b95085b77b547e7d94262 (diff)
downloadgem5-5200e04e92b487181d4a678231564272730e04a2.tar.xz
arch, x86: add support for arrays as memory operands
Although the cache models support wider accesses, the ISA descriptions assume that (for the most part) memory operands are integer types, which makes it difficult to define instructions that do memory accesses larger than 64 bits. This patch adds some generic support for memory operands that are arrays of uint64_t, and specifically a 'u2qw' operand type for x86 that is an array of 2 uint64_ts (128 bits). This support is unused at this point, but will be needed shortly for cmpxchg16b. Ideally the 128-bit SSE memory accesses will also be rewritten to use this support. Support for 128-bit accesses could also have been added using the gcc __int128_t extension, which would have been less disruptive. However, although clang also supports __int128_t, it's still non-standard. Also, more importantly, this approach creates a path to defining 256- and 512-byte operands as well, which will be useful for eventual AVX support.
Diffstat (limited to 'src/arch/x86/memhelpers.hh')
-rw-r--r--src/arch/x86/memhelpers.hh104
1 files changed, 100 insertions, 4 deletions
diff --git a/src/arch/x86/memhelpers.hh b/src/arch/x86/memhelpers.hh
index 705457d67..b13207ec4 100644
--- a/src/arch/x86/memhelpers.hh
+++ b/src/arch/x86/memhelpers.hh
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2011 Google
+ * Copyright (c) 2015 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,6 +32,8 @@
#ifndef __ARCH_X86_MEMHELPERS_HH__
#define __ARCH_X86_MEMHELPERS_HH__
+#include <array>
+
#include "base/types.hh"
#include "sim/byteswap.hh"
#include "sim/insttracer.hh"
@@ -47,10 +50,10 @@ initiateMemRead(XC *xc, Trace::InstRecord *traceData, Addr addr,
return xc->initiateMemRead(addr, dataSize, flags);
}
-static inline uint64_t
-getMem(PacketPtr pkt, unsigned dataSize, Trace::InstRecord *traceData)
+static void
+getMem(PacketPtr pkt, uint64_t &mem, unsigned dataSize,
+ Trace::InstRecord *traceData)
{
- uint64_t mem;
switch (dataSize) {
case 1:
mem = pkt->get<uint8_t>();
@@ -69,9 +72,31 @@ getMem(PacketPtr pkt, unsigned dataSize, Trace::InstRecord *traceData)
}
if (traceData)
traceData->setData(mem);
- return mem;
}
+
+template <size_t N>
+void
+getMem(PacketPtr pkt, std::array<uint64_t, N> &mem, unsigned dataSize,
+ Trace::InstRecord *traceData)
+{
+ assert(dataSize >= 8);
+ assert((dataSize % 8) == 0);
+
+ int num_words = dataSize / 8;
+ assert(num_words <= N);
+
+ auto pkt_data = pkt->getConstPtr<const uint64_t>();
+ for (int i = 0; i < num_words; ++i)
+ mem[i] = gtoh(pkt_data[i]);
+
+ // traceData record only has space for 64 bits, so we just record
+ // the first qword
+ if (traceData)
+ traceData->setData(mem[0]);
+}
+
+
template <class XC>
Fault
readMemAtomic(XC *xc, Trace::InstRecord *traceData, Addr addr, uint64_t &mem,
@@ -90,6 +115,30 @@ readMemAtomic(XC *xc, Trace::InstRecord *traceData, Addr addr, uint64_t &mem,
return fault;
}
+template <class XC, size_t N>
+Fault
+readMemAtomic(XC *xc, Trace::InstRecord *traceData, Addr addr,
+ std::array<uint64_t, N> &mem, unsigned dataSize,
+ unsigned flags)
+{
+ assert(dataSize >= 8);
+ assert((dataSize % 8) == 0);
+
+ Fault fault = xc->readMem(addr, (uint8_t *)&mem, dataSize, flags);
+
+ if (fault == NoFault) {
+ int num_words = dataSize / 8;
+ assert(num_words <= N);
+
+ for (int i = 0; i < num_words; ++i)
+ mem[i] = gtoh(mem[i]);
+
+ if (traceData)
+ traceData->setData(mem[0]);
+ }
+ return fault;
+}
+
template <class XC>
Fault
writeMemTiming(XC *xc, Trace::InstRecord *traceData, uint64_t mem,
@@ -102,6 +151,28 @@ writeMemTiming(XC *xc, Trace::InstRecord *traceData, uint64_t mem,
return xc->writeMem((uint8_t *)&mem, dataSize, addr, flags, res);
}
+template <class XC, size_t N>
+Fault
+writeMemTiming(XC *xc, Trace::InstRecord *traceData,
+ std::array<uint64_t, N> &mem, unsigned dataSize,
+ Addr addr, unsigned flags, uint64_t *res)
+{
+ assert(dataSize >= 8);
+ assert((dataSize % 8) == 0);
+
+ if (traceData) {
+ traceData->setData(mem[0]);
+ }
+
+ int num_words = dataSize / 8;
+ assert(num_words <= N);
+
+ for (int i = 0; i < num_words; ++i)
+ mem[i] = htog(mem[i]);
+
+ return xc->writeMem((uint8_t *)&mem, dataSize, addr, flags, res);
+}
+
template <class XC>
Fault
writeMemAtomic(XC *xc, Trace::InstRecord *traceData, uint64_t mem,
@@ -119,6 +190,31 @@ writeMemAtomic(XC *xc, Trace::InstRecord *traceData, uint64_t mem,
return fault;
}
+template <class XC, size_t N>
+Fault
+writeMemAtomic(XC *xc, Trace::InstRecord *traceData,
+ std::array<uint64_t, N> &mem, unsigned dataSize,
+ Addr addr, unsigned flags, uint64_t *res)
+{
+ if (traceData) {
+ traceData->setData(mem[0]);
+ }
+
+ int num_words = dataSize / 8;
+ assert(num_words <= N);
+
+ for (int i = 0; i < num_words; ++i)
+ mem[i] = htog(mem[i]);
+
+ Fault fault = xc->writeMem((uint8_t *)&mem, dataSize, addr, flags, res);
+
+ if (fault == NoFault && res != NULL) {
+ *res = gtoh(*res);
+ }
+
+ return fault;
+}
+
}
#endif