arch: Add a virtual asBytes function to the StaticInst class.
authorGabe Black <gabeblack@google.com>
Wed, 24 Jan 2018 07:57:48 +0000 (23:57 -0800)
committerGabe Black <gabeblack@google.com>
Mon, 26 Mar 2018 22:33:52 +0000 (22:33 +0000)
This function takes a pointer to a buffer and the current size of the
buffer as a pass by reference argument. If the size of the buffer is
sufficient, the function stores a binary representation of itself
(generally the ISA defined instruction encoding) in the buffer, and
sets the size argument to how much space it used. This could be used
by ISAs which have two instruction sizes (ARM and thumb, for example).
If the buffer size isn't sufficient, then the size parameter should be
set to what size is required, and then the function should return
without modifying the buffer.

The buffer itself should be aligned to the same standard as memory
returned by new, specifically "The pointer returned shall be suitably
aligned so that it can be converted to a pointer of any complete object
type and then used to access the object or array in the storage
allocated...". This will avoid having to memcpy buffers to avoid
unaligned accesses.

To standardize the representation of the data, it should be stored in
the buffer as little endian. Since most hosts (including ARM and x86
hosts) will be little endian, this will almost always be a no-op.

Change-Id: I2f31aa0b4f9c0126b44f47a881c2901243279bd6
Reviewed-on: https://gem5-review.googlesource.com/7562
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/arch/alpha/isa/main.isa
src/arch/arm/insts/static_inst.hh
src/arch/mips/isa/base.isa
src/arch/power/insts/static_inst.hh
src/arch/riscv/insts/static_inst.hh
src/arch/sparc/insts/static_inst.hh
src/cpu/static_inst.hh

index a23710a2d27ba09e8f5d732055886b5bbe5e3cc6..4f269b3730eafed437ff5cfa915939c48c4735b7 100644 (file)
@@ -51,6 +51,8 @@ output header {{
 #include "cpu/static_inst.hh"
 #include "mem/packet.hh"
 #include "mem/request.hh"  // some constructors use MemReq flags
+#include "sim/byteswap.hh"
+
 }};
 
 output decoder {{
@@ -59,9 +61,9 @@ output decoder {{
 #include "arch/alpha/decoder.hh"
 #include "arch/alpha/registers.hh"
 #include "arch/alpha/regredir.hh"
-#include "base/loader/symtab.hh"
 #include "base/cprintf.hh"
 #include "base/fenv.hh"
+#include "base/loader/symtab.hh"
 #include "config/ss_compatible_fp.hh"
 #include "cpu/thread_context.hh"  // for Jump::branchTarget()
 #include "mem/packet.hh"
@@ -219,7 +221,6 @@ output header {{
     class AlphaStaticInst : public StaticInst
     {
       protected:
-
         /// Constructor.
         AlphaStaticInst(const char *mnem, ExtMachInst _machInst,
                         OpClass __opClass)
@@ -239,6 +240,13 @@ output header {{
         {
             pcState.advance();
         }
+
+      public:
+        size_t
+        asBytes(void *buf, size_t max_size) override
+        {
+            return simpleAsBytes(buf, max_size, machInst);
+        }
     };
 }};
 
index c68880c97667b82701766f81e33ea013e0f87f53..3ed374ab12dc80fed3e418fc56ae890f188e9015 100644 (file)
@@ -505,6 +505,12 @@ class ArmStaticInst : public StaticInst
     {
         return static_cast<MachInst>(machInst & (mask(instSize() * 8)));
     }
+
+    size_t
+    asBytes(void *buf, size_t max_size) override
+    {
+        return simpleAsBytes(buf, max_size, machInst);
+    }
 };
 }
 
index 946dce6dfd53fcc05b90f4a6f19d14dd577c4702..3759390d152fffaad0d5f2b01de01a1c7fc8c731 100644 (file)
@@ -63,6 +63,12 @@ output header {{
         {
             pc.advance();
         }
+
+        size_t
+        asBytes(void *buf, size_t max_size) override
+        {
+            return simpleAsBytes(buf, max_size, machInst);
+        }
     };
 
 }};
index b7a818a2c326a13c159f24708a8ff5392c676918..f4f1bec7b0d7f1b991ff711e720403f98e89e38a 100644 (file)
@@ -69,6 +69,12 @@ class PowerStaticInst : public StaticInst
     {
         pcState.advance();
     }
+
+    size_t
+    asBytes(void *buf, size_t max_size) override
+    {
+        return simpleAsBytes(buf, max_size, machInst);
+    }
 };
 
 } // namespace PowerISA
index 073b60c1c02f0bbf1be52d712b057fde0621257a..3f6d58654ffd118c8f0e4fe28d396cda3614bae3 100644 (file)
@@ -56,6 +56,12 @@ class RiscvStaticInst : public StaticInst
 
   public:
     void advancePC(PCState &pc) const { pc.advance(); }
+
+    size_t
+    asBytes(void *buf, size_t size) override
+    {
+        return simpleAsBytes(buf, size, machInst);
+    }
 };
 
 /**
index cc5a6022573a1a7bf58940e28727de34c214c4d8..9e15c8dab0a899d8bead98efa4c7fc0c098c21fb 100644 (file)
@@ -105,6 +105,12 @@ class SparcStaticInst : public StaticInst
 
     static bool passesFpCondition(uint32_t fcc, uint32_t condition);
     static bool passesCondition(uint32_t codes, uint32_t condition);
+
+    size_t
+    asBytes(void *buf, size_t size) override
+    {
+        return simpleAsBytes(buf, size, machInst);
+    }
 };
 
 }
index 79f45d8282088f533785370770efd36a81efbfa4..84b3525027aedcd9307999f2a4949c46d00a1b8a 100644 (file)
@@ -33,6 +33,7 @@
 #define __CPU_STATIC_INST_HH__
 
 #include <bitset>
+#include <memory>
 #include <string>
 
 #include "arch/registers.hh"
@@ -47,6 +48,7 @@
 #include "cpu/static_inst_fwd.hh"
 #include "cpu/thread_context.hh"
 #include "enums/StaticInstFlags.hh"
+#include "sim/byteswap.hh"
 
 // forward declarations
 class Packet;
@@ -317,6 +319,31 @@ class StaticInst : public RefCounted, public StaticInstFlags
 
     /// Return name of machine instruction
     std::string getName() { return mnemonic; }
+
+  protected:
+    template<typename T>
+    size_t
+    simpleAsBytes(void *buf, size_t max_size, const T &t)
+    {
+        size_t size = sizeof(T);
+        if (size <= max_size)
+            *reinterpret_cast<T *>(buf) = htole<T>(t);
+        return size;
+    }
+
+  public:
+    /**
+     * Instruction classes can override this function to return a
+     * a representation of themselves as a blob of bytes, generally assumed to
+     * be that instructions ExtMachInst.
+     *
+     * buf is a buffer to hold the bytes.
+     * max_size is the size allocated for that buffer by the caller.
+     * The return value is how much data was actually put into the buffer,
+     * zero if no data was put in the buffer, or the necessary size of the
+     * buffer if there wasn't enough space.
+     */
+    virtual size_t asBytes(void *buf, size_t max_size) { return 0; }
 };
 
 #endif // __CPU_STATIC_INST_HH__