From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5123 invoked by alias); 29 May 2002 14:46:05 -0000 Mailing-List: contact sid-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: sid-owner@sources.redhat.com Received: (qmail 5102 invoked from network); 29 May 2002 14:45:58 -0000 Received: from unknown (HELO touchme.toronto.redhat.com) (216.138.202.10) by sources.redhat.com with SMTP; 29 May 2002 14:45:58 -0000 Received: from tooth.toronto.redhat.com (unknown [172.16.14.29]) by touchme.toronto.redhat.com (Postfix) with ESMTP id E72F4B8036 for ; Wed, 29 May 2002 10:45:57 -0400 (EDT) Received: (from bje@localhost) by tooth.toronto.redhat.com (8.11.6/8.11.6) id g4TEjv519265; Wed, 29 May 2002 10:45:57 -0400 From: Ben Elliston MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <15604.59813.750421.114817@tooth.toronto.redhat.com> Date: Wed, 29 May 2002 07:46:00 -0000 To: sid@sources.redhat.com Subject: CPU disassembler-memory accessor X-SW-Source: 2002-q2/txt/msg00023.txt.bz2 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 * 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 * 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(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 @@

Each instruction is first fetched from memory via the insn-memory accessor, and its decoding traced if the trace-extract? attribute is - set to a true value. The decoded form may be cached - indefinitely afterwards, although this cache is flushed when the - flush-icache pin is driven.

+ set to a true value. To prevent unwanted cache side effects, + the disassembler-memory 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 flush-icache + pin is driven.

The engine-type 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 @@ + 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 @@ -506,6 +507,8 @@ namespace sidutil BigOrLittleInt read_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) const; template BigOrLittleInt write_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value) const; + template + 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 (s) << t; return s; } - + + template + 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 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)