This is the mail archive of the sid@sources.redhat.com mailing list for the SID 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]

CPU disassembler-memory accessor


Hi.

The following patch adds a third accessor to CPUs for the purpose of
providing the disassembler with access to the instruction memory
without causing undesirable side effects in the memory hierarchy.
Without this patch, the disassembler may produce unwanted side effects
such as priming cache lines as it groks around the instruction memory.
Since this inspection tool should not modify the system it is
inspecting, the new accessor provides an opportunity to wire the
disassembler directly to the instruction memory, bypassing caches.

If the disassembler-memory accessor is not used, the CPU will default
to using the insn-mem accessor so this change is backward compatible
with existing ports.  Any comments?

Ben

2002-05-28  Ben Elliston  <bje@redhat.com>
 
	* compCGEN.cxx (cgen_bi_endian_cpu::cgen_read_memory): Don't
	bother fiddling the latency values.  Catch exceptions raised by
	read_disasm_memory_1 and return 1 if so (as required by GNU
	opcodes read_memory functions).
	* common-xml/interface.xml: Document disassembler-memory accessor.
	* common-xml/behavior.xml (execution): Likewise.

2002-05-28  Ben Elliston  <bje@redhat.com>

	* sidcpuutil.h (basic_cpu::disassembler_bus): New accessor.
	(basic_cpu::basic_cpu): Initialise; register disassembler-memory".
	(basic_cpu::read_disasm_memory): New function template.
	(basic_big_endian_cpu::read_disasm_memory_{1,2,4,8}): New members.
	(basic_little_endian_cpu::read_disasm_memory_{1,2,4,8}): Likewise.
	(basic_bi_endian_cpu::read_disasm_memory_{1,2,4,8}): Likewise.

Index: component/cgen-cpu/compCGEN.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/cgen-cpu/compCGEN.cxx,v
retrieving revision 1.8
diff -u -p -r1.8 compCGEN.cxx
--- component/cgen-cpu/compCGEN.cxx	7 Feb 2002 17:32:28 -0000	1.8
+++ component/cgen-cpu/compCGEN.cxx	29 May 2002 14:39:23 -0000
@@ -178,10 +178,6 @@ cgen_bi_endian_cpu::cgen_read_memory(bfd
 {
   cgen_bi_endian_cpu *thisp = static_cast<cgen_bi_endian_cpu *>(info->application_data);
 
-  // We don't want to penalize the disassembler with memory latency counts, so we
-  // store it away here ...
-  host_int_8 prev_latency = thisp->total_latency;
-
   switch (length) {
 #if 0 // XXX not sure if this has byte order dependancies or not
   case 1:
@@ -198,13 +194,16 @@ cgen_bi_endian_cpu::cgen_read_memory(bfd
     break;
 #endif
   default:
-    for (int i = 0; i < length; i++)
-      *(myaddr + i) = thisp->read_insn_memory_1(0, memaddr + i);
+    try {
+	for (int i = 0; i < length; i++)
+	  *(myaddr + i) = thisp->read_disasm_memory_1 (0, memaddr + i);
+    }
+    catch (cpu_memory_fault& f) {
+      // The GNU disassembler interface is not expecting an exception.
+      // Return a non-zero value as prescribed by the interface.
+      return 1;
+    }
   }
-
-  // ... and restore it here.
-  thisp->total_latency = prev_latency;
-
   return 0;
 }
 
Index: component/cgen-cpu/common-xml/behavior.xml
===================================================================
RCS file: /cvs/src/src/sid/component/cgen-cpu/common-xml/behavior.xml,v
retrieving revision 1.2
diff -u -p -r1.2 behavior.xml
--- component/cgen-cpu/common-xml/behavior.xml	14 Mar 2002 00:16:28 -0000	1.2
+++ component/cgen-cpu/common-xml/behavior.xml	29 May 2002 14:39:23 -0000
@@ -32,9 +32,12 @@
       <p>Each instruction is first fetched from memory via the
       <accessor>insn-memory</accessor> accessor, and its decoding
       traced if the <attribute>trace-extract?</attribute> attribute is
-      set to a true value.  The decoded form may be cached
-      indefinitely afterwards, although this cache is flushed when the
-      <pin>flush-icache</pin> pin is driven.</p>
+      set to a true value.  To prevent unwanted cache side effects,
+      the <accessor>disassembler-memory</accessor> accessor can be
+      used and connected directly to main memory, bypassing any memory
+      caches.  The decoded form may be cached indefinitely afterwards,
+      although this cache is flushed when the <pin>flush-icache</pin>
+      pin is driven.</p>
 
       <p>The <attribute>engine-type</attribute> attribute specifies
       whether the "scache" ("semantic cache") or "pbb" ("pseudo basic
Index: component/cgen-cpu/common-xml/interface.xml
===================================================================
RCS file: /cvs/src/src/sid/component/cgen-cpu/common-xml/interface.xml,v
retrieving revision 1.3
diff -u -p -r1.3 interface.xml
--- component/cgen-cpu/common-xml/interface.xml	8 May 2002 19:33:13 -0000	1.3
+++ component/cgen-cpu/common-xml/interface.xml	29 May 2002 14:39:23 -0000
@@ -16,6 +16,7 @@
     <!-- accessors -->
     <defaccessor name="data-memory" accesses="any" behaviors="execution" />
     <defaccessor name="insn-memory" accesses="typically 4-byte accesses" behaviors="execution" />
+    <defaccessor name="disassembler-memory" accesses="any" behaviors="execution" />
 
 
     <!-- buses -->
Index: include/sidcpuutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidcpuutil.h,v
retrieving revision 1.19
diff -u -p -r1.19 sidcpuutil.h
--- include/sidcpuutil.h	23 Apr 2002 21:00:33 -0000	1.19
+++ include/sidcpuutil.h	29 May 2002 14:39:24 -0000
@@ -496,6 +496,7 @@ namespace sidutil
   protected:
     sid::bus* data_bus;
     sid::bus* insn_bus;
+    sid::bus* disassembler_bus;
 
   protected:
     template <typename BigOrLittleInt>
@@ -506,6 +507,8 @@ namespace sidutil
     BigOrLittleInt read_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) const;
     template <typename BigOrLittleInt>
     BigOrLittleInt write_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value) const;
+    template <typename BigOrLittleInt>
+    BigOrLittleInt read_disasm_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) const;
 
     // ------------------------------------------------------------------------
     
@@ -530,6 +533,8 @@ public:
 	add_accessor ("data-memory", & this->data_bus);
 	this->insn_bus = 0;
 	add_accessor ("insn-memory", & this->insn_bus);
+	this->disassembler_bus = 0;
+	add_accessor ("disassembler-memory", & this->disassembler_bus);
 	add_bus ("debugger-bus", & this->debugger_bus);
 
 	// pins
@@ -599,7 +604,25 @@ public:
 	dynamic_cast <ofstream&> (s) << t;
       return s;
     }
-  
+
+    template <typename BigOrLittleInt>
+    BigOrLittleInt basic_cpu::read_disasm_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) const
+      {
+	BigOrLittleInt value;
+	sid::bus::status s;
+	    
+	if (UNLIKELY (this->disassembler_bus))
+	  {
+	    s = this->disassembler_bus->read (address, value);
+	    if (LIKELY (s == sid::bus::ok))
+	      return value;
+	  }
+	else
+	  return read_insn_memory (pc, address, BigOrLittleInt());
+
+	throw cpu_memory_fault (pc, address, s, "insn disasm read");
+      }
+
     template <typename BigOrLittleInt>
     BigOrLittleInt basic_cpu::read_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) const
       {
@@ -679,6 +702,26 @@ public:
       }
     ~basic_big_endian_cpu () throw() {}
 
+    sid::host_int_1 read_disasm_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const
+      {
+	return this->read_disasm_memory (pc, address, sid::big_int_1());
+      }
+
+    sid::host_int_2 read_disasm_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) const
+      {
+	return this->read_disasm_memory (pc, address, sid::big_int_2());
+      }
+
+    sid::host_int_4 read_disasm_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) const
+      {
+	return this->read_disasm_memory (pc, address, sid::big_int_4());
+      }
+
+    sid::host_int_8 read_disasm_memory_8 (sid::host_int_4 pc, sid::host_int_8 address) const
+      {
+	return this->read_disasm_memory (pc, address, sid::big_int_8());
+      }
+
     sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const
       {
 	return this->read_insn_memory (pc, address, sid::big_int_1());
@@ -774,6 +817,26 @@ public:
       }
     ~basic_little_endian_cpu () throw() {}
 
+    sid::host_int_1 read_disasm_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const
+      {
+	return this->read_disasm_memory (pc, address, sid::little_int_1());
+      }
+
+    sid::host_int_2 read_disasm_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) const
+      {
+	return this->read_disasm_memory (pc, address, sid::little_int_2());
+      }
+
+    sid::host_int_4 read_disasm_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) const
+      {
+	return this->read_disasm_memory (pc, address, sid::little_int_4());
+      }
+
+    sid::host_int_8 read_disasm_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) const
+      {
+	return this->read_disasm_memory (pc, address, sid::little_int_8());
+      }
+
     sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const
       {
 	return this->read_insn_memory (pc, address, sid::little_int_1());
@@ -901,7 +964,38 @@ public:
 	i >> this->_current_endianness;
       }
 
+    sid::host_int_1 read_disasm_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const
+      {
+	if (this->_current_endianness == endian_little)
+	  return this->read_disasm_memory (pc, address, sid::little_int_1());
+	else // endian_big or endian_unknown
+	  return this->read_disasm_memory (pc, address, sid::big_int_1());
+      }
+
+    sid::host_int_2 read_disasm_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) const
+      {
+	if (this->_current_endianness == endian_little)
+	  return this->read_disasm_memory (pc, address, sid::little_int_2());
+	else // endian_big or endian_unknown
+	  return this->read_disasm_memory (pc, address, sid::big_int_2());
+      }
 
+    sid::host_int_4 read_disasm_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) const
+      {
+	if (this->_current_endianness == endian_little)
+	  return this->read_disasm_memory (pc, address, sid::little_int_4());
+	else // endian_big or endian_unknown
+	  return this->read_disasm_memory (pc, address, sid::big_int_4());
+      }
+
+    sid::host_int_8 read_disasm_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) const
+      {
+	if (this->_current_endianness == endian_little)
+	  return this->read_disasm_memory (pc, address, sid::little_int_8());
+	else // endian_big or endian_unknown
+	  return this->read_disasm_memory (pc, address, sid::big_int_8());
+      }
+    
     sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const
       {
 	if (this->_current_endianness == endian_little)


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