arch,cpu,mem: Replace the mmmapped IPR mechanism with local accesses.

The new local access mechanism installs a callback in the request which
implements what the mmapped IPR was doing. That avoids having to have
stubs in ISAs that don't have mmapped IPRs, avoids having to encode
what to do to communicate from the TLB and the mmapped IPR functions,
and gets rid of another global ISA interface function and header files.

Jira Issue: https://gem5.atlassian.net/browse/GEM5-187

Change-Id: I772c2ae2ca3830a4486919ce9804560c0f2d596a
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23188
Reviewed-by: Matthew Poremba <matthew.poremba@amd.com>
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/arch/SConscript b/src/arch/SConscript
index 1b68f3f..444e188 100644
--- a/src/arch/SConscript
+++ b/src/arch/SConscript
@@ -63,7 +63,6 @@
         kernel_stats.hh
         locked_mem.hh
         microcode_rom.hh
-        mmapped_ipr.hh
         process.hh
         pseudo_inst.hh
         registers.hh
diff --git a/src/arch/arm/mmapped_ipr.hh b/src/arch/arm/mmapped_ipr.hh
deleted file mode 100644
index 7df6667..0000000
--- a/src/arch/arm/mmapped_ipr.hh
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * Copyright (c) 2007-2008 The Florida State University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ARCH_ARM_MMAPPED_IPR_HH__
-#define __ARCH_ARM_MMAPPED_IPR_HH__
-
-/**
- * @file
- *
- * ISA-specific helper functions for memory mapped IPR accesses.
- */
-
-#include "base/types.hh"
-#include "mem/packet.hh"
-#include "mem/packet_access.hh"
-#include "sim/pseudo_inst.hh"
-#include "sim/system.hh"
-
-class ThreadContext;
-
-namespace ArmISA
-{
-
-inline Cycles
-handleIprRead(ThreadContext *tc, Packet *pkt)
-{
-    Addr addr = pkt->getAddr();
-    auto m5opRange = tc->getSystemPtr()->m5opRange();
-    if (m5opRange.contains(addr)) {
-        uint8_t func;
-        PseudoInst::decodeAddrOffset(addr - m5opRange.start(), func);
-        uint64_t ret = PseudoInst::pseudoInst<PseudoInstABI>(tc, func);
-        pkt->setLE(ret);
-    }
-    return Cycles(1);
-}
-
-inline Cycles
-handleIprWrite(ThreadContext *tc, Packet *pkt)
-{
-    Addr addr = pkt->getAddr();
-    auto m5opRange = tc->getSystemPtr()->m5opRange();
-    if (m5opRange.contains(addr)) {
-        uint8_t func;
-        PseudoInst::decodeAddrOffset(addr - m5opRange.start(), func);
-        PseudoInst::pseudoInst<PseudoInstABI>(tc, func);
-    }
-    return Cycles(1);
-}
-
-} // namespace ArmISA
-
-#endif
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index f53e5e4..a998749 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -59,11 +59,13 @@
 #include "debug/Checkpoint.hh"
 #include "debug/TLB.hh"
 #include "debug/TLBVerbose.hh"
+#include "mem/packet_access.hh"
 #include "mem/page_table.hh"
 #include "mem/request.hh"
 #include "params/ArmTLB.hh"
 #include "sim/full_system.hh"
 #include "sim/process.hh"
+#include "sim/pseudo_inst.hh"
 
 using namespace std;
 using namespace ArmISA;
@@ -133,8 +135,19 @@
 {
     const Addr paddr = req->getPaddr();
 
-    if (m5opRange.contains(paddr))
-        req->setFlags(Request::MMAPPED_IPR);
+    if (m5opRange.contains(paddr)) {
+        uint8_t func;
+        PseudoInst::decodeAddrOffset(paddr - m5opRange.start(), func);
+        req->setLocalAccessor(
+            [func, mode](ThreadContext *tc, PacketPtr pkt) -> Cycles
+            {
+                uint64_t ret = PseudoInst::pseudoInst<PseudoInstABI>(tc, func);
+                if (mode == Read)
+                    pkt->setLE(ret);
+                return Cycles(1);
+            }
+        );
+    }
 
     return NoFault;
 }
diff --git a/src/arch/arm/tracers/tarmac_parser.cc b/src/arch/arm/tracers/tarmac_parser.cc
index e245f5d..65d5a18 100644
--- a/src/arch/arm/tracers/tarmac_parser.cc
+++ b/src/arch/arm/tracers/tarmac_parser.cc
@@ -1198,8 +1198,8 @@
     // Now do the access
     if (fault == NoFault &&
         !req->getFlags().isSet(Request::NO_ACCESS)) {
-        if (req->isLLSC() || req->isMmappedIpr())
-            // LLSCs and mem. mapped IPRs are ignored
+        if (req->isLLSC() || req->isLocalAccess())
+            // LLSCs and local accesses are ignored
             return false;
         // the translating proxy will perform the virtual to physical
         // translation again
diff --git a/src/arch/mips/mmapped_ipr.hh b/src/arch/mips/mmapped_ipr.hh
deleted file mode 100644
index 0e398a2..0000000
--- a/src/arch/mips/mmapped_ipr.hh
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ARCH_MIPS_MMAPPED_IPR_HH__
-#define __ARCH_MIPS_MMAPPED_IPR_HH__
-
-/**
- * @file
- *
- * ISA-specific helper functions for memory mapped IPR accesses.
- */
-
-#include "base/types.hh"
-
-class Packet;
-class ThreadContext;
-
-namespace MipsISA
-{
-
-inline Cycles handleIprRead(ThreadContext *, Packet *) { return Cycles(1); }
-inline Cycles handleIprWrite(ThreadContext *, Packet *) { return Cycles(1); }
-
-} // namespace MipsISA
-
-#endif
diff --git a/src/arch/power/mmapped_ipr.hh b/src/arch/power/mmapped_ipr.hh
deleted file mode 100644
index db4db3f..0000000
--- a/src/arch/power/mmapped_ipr.hh
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * Copyright (c) 2007-2008 The Florida State University
- * Copyright (c) 2009 The University of Edinburgh
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ARCH_POWER_MMAPPED_IPR_HH__
-#define __ARCH_POWER_MMAPPED_IPR_HH__
-
-/**
- * @file
- *
- * ISA-specific helper functions for memory mapped IPR accesses.
- */
-
-#include "base/types.hh"
-
-class Packet;
-class ThreadContext;
-
-namespace PowerISA
-{
-
-inline Cycles handleIprRead(ThreadContext *, Packet *) { return Cycles(1); }
-inline Cycles handleIprWrite(ThreadContext *, Packet *) { return Cycles(1); }
-
-} // namespace PowerISA
-
-#endif // __ARCH_POWER_MMAPPED_IPR_HH__
diff --git a/src/arch/riscv/mmapped_ipr.hh b/src/arch/riscv/mmapped_ipr.hh
deleted file mode 100644
index bc995fc..0000000
--- a/src/arch/riscv/mmapped_ipr.hh
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ARCH_RISCV_MMAPPED_IPR_HH__
-#define __ARCH_RISCV_MMAPPED_IPR_HH__
-
-/**
- * @file
- *
- * ISA-specific helper functions for memory mapped IPR accesses.
- */
-
-#include "base/types.hh"
-
-class Packet;
-class ThreadContext;
-
-namespace RiscvISA
-{
-
-inline Cycles handleIprRead(ThreadContext *, Packet *) { return Cycles(1); }
-inline Cycles handleIprWrite(ThreadContext *, Packet *) { return Cycles(1); }
-
-} // namespace RiscvISA
-
-#endif
diff --git a/src/arch/sparc/mmapped_ipr.hh b/src/arch/sparc/mmapped_ipr.hh
deleted file mode 100644
index 91ff4a3..0000000
--- a/src/arch/sparc/mmapped_ipr.hh
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ARCH_SPARC_MMAPPED_IPR_HH__
-#define __ARCH_SPARC_MMAPPED_IPR_HH__
-
-/**
- * @file
- *
- * ISA-specific helper functions for memory mapped IPR accesses.
- */
-
-#include "arch/sparc/tlb.hh"
-#include "cpu/thread_context.hh"
-#include "mem/packet.hh"
-
-namespace SparcISA
-{
-
-inline Cycles
-handleIprRead(ThreadContext *xc, Packet *pkt)
-{
-    return dynamic_cast<TLB *>(xc->getDTBPtr())->doMmuRegRead(xc, pkt);
-}
-
-inline Cycles
-handleIprWrite(ThreadContext *xc, Packet *pkt)
-{
-    return dynamic_cast<TLB *>(xc->getDTBPtr())->doMmuRegWrite(xc, pkt);
-}
-
-
-} // namespace SparcISA
-
-#endif
diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc
index 2396960..f569bbc 100644
--- a/src/arch/sparc/tlb.cc
+++ b/src/arch/sparc/tlb.cc
@@ -825,8 +825,13 @@
 
 regAccessOk:
 handleMmuRegAccess:
-    DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n");
-    req->setFlags(Request::MMAPPED_IPR);
+    DPRINTF(TLB, "TLB: DTB Translating local access\n");
+    req->setLocalAccessor(
+        [this,write](ThreadContext *tc, PacketPtr pkt) -> Cycles
+        {
+            return write ? doMmuRegWrite(tc, pkt) : doMmuRegRead(tc, pkt);
+        }
+    );
     req->setPaddr(req->getVaddr());
     return NoFault;
 };
diff --git a/src/arch/x86/mmapped_ipr.hh b/src/arch/x86/mmapped_ipr.hh
deleted file mode 100644
index 5b0a1e9..0000000
--- a/src/arch/x86/mmapped_ipr.hh
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
- * All rights reserved.
- *
- * The license below extends only to copyright in the software and shall
- * not be construed as granting a license to any other intellectual
- * property including but not limited to intellectual property relating
- * to a hardware implementation of the functionality of the software
- * licensed hereunder.  You may use the software subject to the license
- * terms below provided that you ensure that this notice is replicated
- * unmodified and in its entirety in all distributions of the software,
- * modified or unmodified, in source code or in binary form.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ARCH_X86_MMAPPEDIPR_HH__
-#define __ARCH_X86_MMAPPEDIPR_HH__
-
-/**
- * @file
- *
- * ISA-specific helper functions for memory mapped IPR accesses.
- */
-
-#include "arch/x86/pseudo_inst_abi.hh"
-#include "arch/x86/regs/misc.hh"
-#include "cpu/base.hh"
-#include "cpu/thread_context.hh"
-#include "mem/packet.hh"
-#include "mem/packet_access.hh"
-#include "sim/pseudo_inst.hh"
-
-namespace X86ISA
-{
-    inline Cycles
-    handleIprRead(ThreadContext *tc, Packet *pkt)
-    {
-        Addr addr = pkt->getAddr();
-        auto m5opRange = tc->getSystemPtr()->m5opRange();
-        if (m5opRange.contains(addr)) {
-            uint8_t func;
-            PseudoInst::decodeAddrOffset(addr - m5opRange.start(), func);
-            uint64_t ret = PseudoInst::pseudoInst<X86PseudoInstABI>(tc, func);
-            pkt->setLE(ret);
-        } else {
-            Addr offset = addr & mask(3);
-            MiscRegIndex index = (MiscRegIndex)(addr / sizeof(RegVal));
-            RegVal data = htole(tc->readMiscReg(index));
-            // Make sure we don't trot off the end of data.
-            assert(offset + pkt->getSize() <= sizeof(RegVal));
-            pkt->setData(((uint8_t *)&data) + offset);
-        }
-        return Cycles(1);
-    }
-
-    inline Cycles
-    handleIprWrite(ThreadContext *tc, Packet *pkt)
-    {
-        Addr addr = pkt->getAddr();
-        auto m5opRange = tc->getSystemPtr()->m5opRange();
-        if (m5opRange.contains(addr)) {
-            uint8_t func;
-            PseudoInst::decodeAddrOffset(addr - m5opRange.start(), func);
-            PseudoInst::pseudoInst<X86PseudoInstABI>(tc, func);
-        } else {
-            Addr offset = addr & mask(3);
-            MiscRegIndex index = (MiscRegIndex)(addr / sizeof(RegVal));
-            RegVal data = htole(tc->readMiscRegNoEffect(index));
-            // Make sure we don't trot off the end of data.
-            assert(offset + pkt->getSize() <= sizeof(RegVal));
-            pkt->writeData(((uint8_t *)&data) + offset);
-            tc->setMiscReg(index, letoh(data));
-        }
-        return Cycles(1);
-    }
-}
-
-#endif // __ARCH_X86_MMAPPEDIPR_HH__
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index ee01d93..15c431c 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -43,16 +43,19 @@
 #include "arch/x86/faults.hh"
 #include "arch/x86/insts/microldstop.hh"
 #include "arch/x86/pagetable_walker.hh"
+#include "arch/x86/pseudo_inst_abi.hh"
 #include "arch/x86/regs/misc.hh"
 #include "arch/x86/regs/msr.hh"
 #include "arch/x86/x86_traits.hh"
 #include "base/trace.hh"
 #include "cpu/thread_context.hh"
 #include "debug/TLB.hh"
+#include "mem/packet_access.hh"
 #include "mem/page_table.hh"
 #include "mem/request.hh"
 #include "sim/full_system.hh"
 #include "sim/process.hh"
+#include "sim/pseudo_inst.hh"
 
 namespace X86ISA {
 
@@ -166,8 +169,30 @@
     }
 }
 
+namespace
+{
+
+Cycles
+localMiscRegAccess(bool read, MiscRegIndex regNum,
+                   ThreadContext *tc, PacketPtr pkt)
+{
+    if (read) {
+        RegVal data = htole(tc->readMiscReg(regNum));
+        assert(pkt->getSize() <= sizeof(RegVal));
+        pkt->setData((uint8_t *)&data);
+    } else {
+        RegVal data = htole(tc->readMiscRegNoEffect(regNum));
+        assert(pkt->getSize() <= sizeof(RegVal));
+        pkt->writeData((uint8_t *)&data);
+        tc->setMiscReg(regNum, letoh(data));
+    }
+    return Cycles(1);
+}
+
+} // anonymous namespace
+
 Fault
-TLB::translateInt(const RequestPtr &req, ThreadContext *tc)
+TLB::translateInt(bool read, RequestPtr req, ThreadContext *tc)
 {
     DPRINTF(TLB, "Addresses references internal memory.\n");
     Addr vaddr = req->getVaddr();
@@ -176,16 +201,18 @@
         panic("CPUID memory space not yet implemented!\n");
     } else if (prefix == IntAddrPrefixMSR) {
         vaddr = (vaddr >> 3) & ~IntAddrPrefixMask;
-        req->setFlags(Request::MMAPPED_IPR);
 
         MiscRegIndex regNum;
         if (!msrAddrToIndex(regNum, vaddr))
             return std::make_shared<GeneralProtection>(0);
 
-        //The index is multiplied by the size of a RegVal so that
-        //any memory dependence calculations will not see these as
-        //overlapping.
-        req->setPaddr((Addr)regNum * sizeof(RegVal));
+        req->setLocalAccessor(
+            [read,regNum](ThreadContext *tc, PacketPtr pkt)
+            {
+                return localMiscRegAccess(read, regNum, tc, pkt);
+            }
+        );
+
         return NoFault;
     } else if (prefix == IntAddrPrefixIO) {
         // TODO If CPL > IOPL or in virtual mode, check the I/O permission
@@ -196,8 +223,13 @@
         // space.
         assert(!(IOPort & ~0xFFFF));
         if (IOPort == 0xCF8 && req->getSize() == 4) {
-            req->setFlags(Request::MMAPPED_IPR);
-            req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(RegVal));
+            req->setLocalAccessor(
+                [read](ThreadContext *tc, PacketPtr pkt)
+                {
+                    return localMiscRegAccess(
+                            read, MISCREG_PCI_CONFIG_ADDRESS, tc, pkt);
+                }
+            );
         } else if ((IOPort & ~mask(2)) == 0xCFC) {
             req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
             Addr configAddress =
@@ -227,7 +259,19 @@
     Addr paddr = req->getPaddr();
 
     if (m5opRange.contains(paddr)) {
-        req->setFlags(Request::MMAPPED_IPR | Request::STRICT_ORDER);
+        req->setFlags(Request::STRICT_ORDER);
+        uint8_t func;
+        PseudoInst::decodeAddrOffset(paddr - m5opRange.start(), func);
+        req->setLocalAccessor(
+            [func, mode](ThreadContext *tc, PacketPtr pkt) -> Cycles
+            {
+                uint64_t ret =
+                    PseudoInst::pseudoInst<X86PseudoInstABI>(tc, func);
+                if (mode == Read)
+                    pkt->setLE(ret);
+                return Cycles(1);
+            }
+        );
     } else if (FullSystem) {
         // Check for an access to the local APIC
         LocalApicBase localApicBase =
@@ -271,7 +315,7 @@
     // If this is true, we're dealing with a request to a non-memory address
     // space.
     if (seg == SEGMENT_REG_MS) {
-        return translateInt(req, tc);
+        return translateInt(mode == Read, req, tc);
     }
 
     Addr vaddr = req->getVaddr();
diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh
index 40bbe90..e5ae567 100644
--- a/src/arch/x86/tlb.hh
+++ b/src/arch/x86/tlb.hh
@@ -106,7 +106,7 @@
         Stats::Scalar rdMisses;
         Stats::Scalar wrMisses;
 
-        Fault translateInt(const RequestPtr &req, ThreadContext *tc);
+        Fault translateInt(bool read, RequestPtr req, ThreadContext *tc);
 
         Fault translate(const RequestPtr &req, ThreadContext *tc,
                 Translation *translation, Mode mode,
diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc
index 5a9b8bc..a0ad242 100644
--- a/src/cpu/checker/cpu.cc
+++ b/src/cpu/checker/cpu.cc
@@ -214,7 +214,7 @@
 
             pkt->dataStatic(data);
 
-            if (!(mem_req->isUncacheable() || mem_req->isMmappedIpr())) {
+            if (!(mem_req->isUncacheable() || mem_req->isLocalAccess())) {
                 // Access memory to see if we have the same data
                 dcachePort->sendFunctional(pkt);
             } else {
diff --git a/src/cpu/kvm/base.cc b/src/cpu/kvm/base.cc
index 996d6be..38fea19 100644
--- a/src/cpu/kvm/base.cc
+++ b/src/cpu/kvm/base.cc
@@ -46,7 +46,6 @@
 #include <csignal>
 #include <ostream>
 
-#include "arch/mmapped_ipr.hh"
 #include "arch/utility.hh"
 #include "debug/Checkpoint.hh"
 #include "debug/Drain.hh"
@@ -1128,13 +1127,11 @@
     PacketPtr pkt = new Packet(mmio_req, cmd);
     pkt->dataStatic(data);
 
-    if (mmio_req->isMmappedIpr()) {
+    if (mmio_req->isLocalAccess()) {
         // We currently assume that there is no need to migrate to a
-        // different event queue when doing IPRs. Currently, IPRs are
-        // only used for m5ops, so it should be a valid assumption.
-        const Cycles ipr_delay(write ?
-                             TheISA::handleIprWrite(tc, pkt) :
-                             TheISA::handleIprRead(tc, pkt));
+        // different event queue when doing local accesses. Currently, they
+        // are only used for m5ops, so it should be a valid assumption.
+        const Cycles ipr_delay = mmio_req->localAccessor(tc, pkt);
         threadContextDirty = true;
         delete pkt;
         return clockPeriod() * ipr_delay;
diff --git a/src/cpu/minor/lsq.cc b/src/cpu/minor/lsq.cc
index a165513..2d393ab 100644
--- a/src/cpu/minor/lsq.cc
+++ b/src/cpu/minor/lsq.cc
@@ -41,7 +41,6 @@
 #include <sstream>
 
 #include "arch/locked_mem.hh"
-#include "arch/mmapped_ipr.hh"
 #include "base/logging.hh"
 #include "cpu/minor/cpu.hh"
 #include "cpu/minor/exec_context.hh"
@@ -1045,7 +1044,7 @@
         }
     } else {
         /* Store.  Can it be sent to the store buffer? */
-        if (bufferable && !request->request->isMmappedIpr()) {
+        if (bufferable && !request->request->isLocalAccess()) {
             request->setState(LSQRequest::StoreToStoreBuffer);
             moveFromRequestsToTransfers(request);
             DPRINTF(MinorMem, "Moving store into transfers queue\n");
@@ -1184,18 +1183,17 @@
          *  so the response can be correctly handled */
         assert(packet->findNextSenderState<LSQRequest>());
 
-        if (request->request->isMmappedIpr()) {
+        if (request->request->isLocalAccess()) {
             ThreadContext *thread =
                 cpu.getContext(cpu.contextToThread(
                                 request->request->contextId()));
 
-            if (request->isLoad) {
+            if (request->isLoad)
                 DPRINTF(MinorMem, "IPR read inst: %s\n", *(request->inst));
-                TheISA::handleIprRead(thread, packet);
-            } else {
+            else
                 DPRINTF(MinorMem, "IPR write inst: %s\n", *(request->inst));
-                TheISA::handleIprWrite(thread, packet);
-            }
+
+            request->request->localAccessor(thread, packet);
 
             request->stepToNextPacket();
             ret = request->sentAllPackets();
diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh
index fdad792..49a25e5 100644
--- a/src/cpu/o3/lsq.hh
+++ b/src/cpu/o3/lsq.hh
@@ -549,8 +549,8 @@
         /**
          * Memory mapped IPR accesses
          */
-        virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt) = 0;
-        virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt) = 0;
+        virtual Cycles handleLocalAccess(
+                ThreadContext *thread, PacketPtr pkt) = 0;
 
         /**
          * Test if the request accesses a particular cache line.
@@ -737,8 +737,7 @@
         virtual bool recvTimingResp(PacketPtr pkt);
         virtual void sendPacketToCache();
         virtual void buildPackets();
-        virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt);
-        virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt);
+        virtual Cycles handleLocalAccess(ThreadContext *thread, PacketPtr pkt);
         virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask);
     };
 
@@ -811,8 +810,7 @@
         virtual void sendPacketToCache();
         virtual void buildPackets();
 
-        virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt);
-        virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt);
+        virtual Cycles handleLocalAccess(ThreadContext *thread, PacketPtr pkt);
         virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask);
 
         virtual RequestPtr mainRequest();
diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh
index 484d9fb..15bd42c 100644
--- a/src/cpu/o3/lsq_impl.hh
+++ b/src/cpu/o3/lsq_impl.hh
@@ -1093,48 +1093,26 @@
 }
 
 template<class Impl>
-void
-LSQ<Impl>::SingleDataRequest::handleIprWrite(ThreadContext *thread,
-                                             PacketPtr pkt)
+Cycles
+LSQ<Impl>::SingleDataRequest::handleLocalAccess(
+        ThreadContext *thread, PacketPtr pkt)
 {
-    TheISA::handleIprWrite(thread, pkt);
-}
-
-template<class Impl>
-void
-LSQ<Impl>::SplitDataRequest::handleIprWrite(ThreadContext *thread,
-                                            PacketPtr mainPkt)
-{
-    unsigned offset = 0;
-    for (auto r: _requests) {
-        PacketPtr pkt = new Packet(r, MemCmd::WriteReq);
-        pkt->dataStatic(mainPkt->getPtr<uint8_t>() + offset);
-        TheISA::handleIprWrite(thread, pkt);
-        offset += r->getSize();
-        delete pkt;
-    }
+    return pkt->req->localAccessor(thread, pkt);
 }
 
 template<class Impl>
 Cycles
-LSQ<Impl>::SingleDataRequest::handleIprRead(ThreadContext *thread,
-                                            PacketPtr pkt)
-{
-    return TheISA::handleIprRead(thread, pkt);
-}
-
-template<class Impl>
-Cycles
-LSQ<Impl>::SplitDataRequest::handleIprRead(ThreadContext *thread,
-                                           PacketPtr mainPkt)
+LSQ<Impl>::SplitDataRequest::handleLocalAccess(
+        ThreadContext *thread, PacketPtr mainPkt)
 {
     Cycles delay(0);
     unsigned offset = 0;
 
     for (auto r: _requests) {
-        PacketPtr pkt = new Packet(r, MemCmd::ReadReq);
+        PacketPtr pkt =
+            new Packet(r, isLoad() ? MemCmd::ReadReq : MemCmd::WriteReq);
         pkt->dataStatic(mainPkt->getPtr<uint8_t>() + offset);
-        Cycles d = TheISA::handleIprRead(thread, pkt);
+        Cycles d = r->localAccessor(thread, pkt);
         if (d > delay)
             delay = d;
         offset += r->getSize();
diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh
index ae035f4..e0cb68b 100644
--- a/src/cpu/o3/lsq_unit.hh
+++ b/src/cpu/o3/lsq_unit.hh
@@ -51,7 +51,6 @@
 #include "arch/generic/vec_reg.hh"
 #include "arch/isa_traits.hh"
 #include "arch/locked_mem.hh"
-#include "arch/mmapped_ipr.hh"
 #include "config/the_isa.hh"
 #include "cpu/inst_seq.hh"
 #include "cpu/timebuf.hh"
@@ -665,7 +664,7 @@
         load_inst->recordResult(true);
     }
 
-    if (req->mainRequest()->isMmappedIpr()) {
+    if (req->mainRequest()->isLocalAccess()) {
         assert(!load_inst->memData);
         load_inst->memData = new uint8_t[MaxDataBytes];
 
@@ -674,7 +673,7 @@
 
         main_pkt->dataStatic(load_inst->memData);
 
-        Cycles delay = req->handleIprRead(thread, main_pkt);
+        Cycles delay = req->mainRequest()->localAccessor(thread, main_pkt);
 
         WritebackEvent *wb = new WritebackEvent(load_inst, main_pkt, this);
         cpu->schedule(wb, cpu->clockEdge(delay));
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index b622199..f7fb3fe 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -814,13 +814,13 @@
             }
         }
 
-        if (req->request()->isMmappedIpr()) {
+        if (req->request()->isLocalAccess()) {
             assert(!inst->isStoreConditional());
             ThreadContext *thread = cpu->tcBase(lsqID);
             PacketPtr main_pkt = new Packet(req->mainRequest(),
                                             MemCmd::WriteReq);
             main_pkt->dataStatic(inst->memData);
-            req->handleIprWrite(thread, main_pkt);
+            req->request()->localAccessor(thread, main_pkt);
             delete main_pkt;
             completeStore(storeWBIt);
             storeWBIt++;
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index 675a4b8..e6fccdf 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -42,7 +42,6 @@
 #include "cpu/simple/atomic.hh"
 
 #include "arch/locked_mem.hh"
-#include "arch/mmapped_ipr.hh"
 #include "arch/utility.hh"
 #include "base/output.hh"
 #include "config/the_isa.hh"
@@ -406,8 +405,8 @@
             Packet pkt(req, Packet::makeReadCmd(req));
             pkt.dataStatic(data);
 
-            if (req->isMmappedIpr()) {
-                dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt);
+            if (req->isLocalAccess()) {
+                dcache_latency += req->localAccessor(thread->getTC(), &pkt);
             } else {
                 dcache_latency += sendPacket(dcachePort, &pkt);
             }
@@ -511,9 +510,9 @@
                 Packet pkt(req, Packet::makeWriteCmd(req));
                 pkt.dataStatic(data);
 
-                if (req->isMmappedIpr()) {
+                if (req->isLocalAccess()) {
                     dcache_latency +=
-                        TheISA::handleIprWrite(thread->getTC(), &pkt);
+                        req->localAccessor(thread->getTC(), &pkt);
                 } else {
                     dcache_latency += sendPacket(dcachePort, &pkt);
 
@@ -607,8 +606,8 @@
         Packet pkt(req, Packet::makeWriteCmd(req));
         pkt.dataStatic(data);
 
-        if (req->isMmappedIpr())
-            dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt);
+        if (req->isLocalAccess())
+            dcache_latency += req->localAccessor(thread->getTC(), &pkt);
         else {
             dcache_latency += sendPacket(dcachePort, &pkt);
         }
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index f805fe2..8c5e74f 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -42,7 +42,6 @@
 #include "cpu/simple/timing.hh"
 
 #include "arch/locked_mem.hh"
-#include "arch/mmapped_ipr.hh"
 #include "arch/utility.hh"
 #include "config/the_isa.hh"
 #include "cpu/exetrace.hh"
@@ -266,8 +265,8 @@
     if (pkt->isRead() && pkt->req->isLLSC()) {
         TheISA::handleLockedRead(thread, pkt->req);
     }
-    if (req->isMmappedIpr()) {
-        Cycles delay = TheISA::handleIprRead(thread->getTC(), pkt);
+    if (req->isLocalAccess()) {
+        Cycles delay = req->localAccessor(thread->getTC(), pkt);
         new IprEvent(pkt, this, clockEdge(delay));
         _status = DcacheWaitResponse;
         dcache_pkt = NULL;
@@ -388,7 +387,7 @@
 {
     pkt1 = pkt2 = NULL;
 
-    assert(!req1->isMmappedIpr() && !req2->isMmappedIpr());
+    assert(!req1->isLocalAccess() && !req2->isLocalAccess());
 
     if (req->getFlags().isSet(Request::NO_ACCESS)) {
         pkt1 = buildPacket(req, read);
@@ -476,8 +475,8 @@
     SimpleThread* thread = t_info.thread;
 
     const RequestPtr &req = dcache_pkt->req;
-    if (req->isMmappedIpr()) {
-        Cycles delay = TheISA::handleIprWrite(thread->getTC(), dcache_pkt);
+    if (req->isLocalAccess()) {
+        Cycles delay = req->localAccessor(thread->getTC(), dcache_pkt);
         new IprEvent(dcache_pkt, this, clockEdge(delay));
         _status = DcacheWaitResponse;
         dcache_pkt = NULL;
diff --git a/src/gpu-compute/gpu_tlb.cc b/src/gpu-compute/gpu_tlb.cc
index cfde2cc..73194de 100644
--- a/src/gpu-compute/gpu_tlb.cc
+++ b/src/gpu-compute/gpu_tlb.cc
@@ -56,6 +56,7 @@
 #include "mem/page_table.hh"
 #include "mem/request.hh"
 #include "sim/process.hh"
+#include "sim/pseudo_inst.hh"
 
 namespace X86ISA
 {
@@ -273,8 +274,30 @@
         }
     }
 
+
+
+    namespace
+    {
+
+    Cycles
+    localMiscRegAccess(bool read, MiscRegIndex regNum,
+                       ThreadContext *tc, PacketPtr pkt)
+    {
+        if (read) {
+            RegVal data = htole(tc->readMiscReg(regNum));
+            // Make sure we don't trot off the end of data.
+            pkt->setData((uint8_t *)&data);
+        } else {
+            RegVal data = htole(tc->readMiscRegNoEffect(regNum));
+            tc->setMiscReg(regNum, letoh(data));
+        }
+        return Cycles(1);
+    }
+
+    } // anonymous namespace
+
     Fault
-    GpuTLB::translateInt(const RequestPtr &req, ThreadContext *tc)
+    GpuTLB::translateInt(bool read, const RequestPtr &req, ThreadContext *tc)
     {
         DPRINTF(GPUTLB, "Addresses references internal memory.\n");
         Addr vaddr = req->getVaddr();
@@ -283,327 +306,19 @@
         if (prefix == IntAddrPrefixCPUID) {
             panic("CPUID memory space not yet implemented!\n");
         } else if (prefix == IntAddrPrefixMSR) {
-            vaddr = vaddr >> 3;
-            req->setFlags(Request::MMAPPED_IPR);
-            Addr regNum = 0;
+            vaddr = (vaddr >> 3) & ~IntAddrPrefixMask;
 
-            switch (vaddr & ~IntAddrPrefixMask) {
-              case 0x10:
-                regNum = MISCREG_TSC;
-                break;
-              case 0x1B:
-                regNum = MISCREG_APIC_BASE;
-                break;
-              case 0xFE:
-                regNum = MISCREG_MTRRCAP;
-                break;
-              case 0x174:
-                regNum = MISCREG_SYSENTER_CS;
-                break;
-              case 0x175:
-                regNum = MISCREG_SYSENTER_ESP;
-                break;
-              case 0x176:
-                regNum = MISCREG_SYSENTER_EIP;
-                break;
-              case 0x179:
-                regNum = MISCREG_MCG_CAP;
-                break;
-              case 0x17A:
-                regNum = MISCREG_MCG_STATUS;
-                break;
-              case 0x17B:
-                regNum = MISCREG_MCG_CTL;
-                break;
-              case 0x1D9:
-                regNum = MISCREG_DEBUG_CTL_MSR;
-                break;
-              case 0x1DB:
-                regNum = MISCREG_LAST_BRANCH_FROM_IP;
-                break;
-              case 0x1DC:
-                regNum = MISCREG_LAST_BRANCH_TO_IP;
-                break;
-              case 0x1DD:
-                regNum = MISCREG_LAST_EXCEPTION_FROM_IP;
-                break;
-              case 0x1DE:
-                regNum = MISCREG_LAST_EXCEPTION_TO_IP;
-                break;
-              case 0x200:
-                regNum = MISCREG_MTRR_PHYS_BASE_0;
-                break;
-              case 0x201:
-                regNum = MISCREG_MTRR_PHYS_MASK_0;
-                break;
-              case 0x202:
-                regNum = MISCREG_MTRR_PHYS_BASE_1;
-                break;
-              case 0x203:
-                regNum = MISCREG_MTRR_PHYS_MASK_1;
-                break;
-              case 0x204:
-                regNum = MISCREG_MTRR_PHYS_BASE_2;
-                break;
-              case 0x205:
-                regNum = MISCREG_MTRR_PHYS_MASK_2;
-                break;
-              case 0x206:
-                regNum = MISCREG_MTRR_PHYS_BASE_3;
-                break;
-              case 0x207:
-                regNum = MISCREG_MTRR_PHYS_MASK_3;
-                break;
-              case 0x208:
-                regNum = MISCREG_MTRR_PHYS_BASE_4;
-                break;
-              case 0x209:
-                regNum = MISCREG_MTRR_PHYS_MASK_4;
-                break;
-              case 0x20A:
-                regNum = MISCREG_MTRR_PHYS_BASE_5;
-                break;
-              case 0x20B:
-                regNum = MISCREG_MTRR_PHYS_MASK_5;
-                break;
-              case 0x20C:
-                regNum = MISCREG_MTRR_PHYS_BASE_6;
-                break;
-              case 0x20D:
-                regNum = MISCREG_MTRR_PHYS_MASK_6;
-                break;
-              case 0x20E:
-                regNum = MISCREG_MTRR_PHYS_BASE_7;
-                break;
-              case 0x20F:
-                regNum = MISCREG_MTRR_PHYS_MASK_7;
-                break;
-              case 0x250:
-                regNum = MISCREG_MTRR_FIX_64K_00000;
-                break;
-              case 0x258:
-                regNum = MISCREG_MTRR_FIX_16K_80000;
-                break;
-              case 0x259:
-                regNum = MISCREG_MTRR_FIX_16K_A0000;
-                break;
-              case 0x268:
-                regNum = MISCREG_MTRR_FIX_4K_C0000;
-                break;
-              case 0x269:
-                regNum = MISCREG_MTRR_FIX_4K_C8000;
-                break;
-              case 0x26A:
-                regNum = MISCREG_MTRR_FIX_4K_D0000;
-                break;
-              case 0x26B:
-                regNum = MISCREG_MTRR_FIX_4K_D8000;
-                break;
-              case 0x26C:
-                regNum = MISCREG_MTRR_FIX_4K_E0000;
-                break;
-              case 0x26D:
-                regNum = MISCREG_MTRR_FIX_4K_E8000;
-                break;
-              case 0x26E:
-                regNum = MISCREG_MTRR_FIX_4K_F0000;
-                break;
-              case 0x26F:
-                regNum = MISCREG_MTRR_FIX_4K_F8000;
-                break;
-              case 0x277:
-                regNum = MISCREG_PAT;
-                break;
-              case 0x2FF:
-                regNum = MISCREG_DEF_TYPE;
-                break;
-              case 0x400:
-                regNum = MISCREG_MC0_CTL;
-                break;
-              case 0x404:
-                regNum = MISCREG_MC1_CTL;
-                break;
-              case 0x408:
-                regNum = MISCREG_MC2_CTL;
-                break;
-              case 0x40C:
-                regNum = MISCREG_MC3_CTL;
-                break;
-              case 0x410:
-                regNum = MISCREG_MC4_CTL;
-                break;
-              case 0x414:
-                regNum = MISCREG_MC5_CTL;
-                break;
-              case 0x418:
-                regNum = MISCREG_MC6_CTL;
-                break;
-              case 0x41C:
-                regNum = MISCREG_MC7_CTL;
-                break;
-              case 0x401:
-                regNum = MISCREG_MC0_STATUS;
-                break;
-              case 0x405:
-                regNum = MISCREG_MC1_STATUS;
-                break;
-              case 0x409:
-                regNum = MISCREG_MC2_STATUS;
-                break;
-              case 0x40D:
-                regNum = MISCREG_MC3_STATUS;
-                break;
-              case 0x411:
-                regNum = MISCREG_MC4_STATUS;
-                break;
-              case 0x415:
-                regNum = MISCREG_MC5_STATUS;
-                break;
-              case 0x419:
-                regNum = MISCREG_MC6_STATUS;
-                break;
-              case 0x41D:
-                regNum = MISCREG_MC7_STATUS;
-                break;
-              case 0x402:
-                regNum = MISCREG_MC0_ADDR;
-                break;
-              case 0x406:
-                regNum = MISCREG_MC1_ADDR;
-                break;
-              case 0x40A:
-                regNum = MISCREG_MC2_ADDR;
-                break;
-              case 0x40E:
-                regNum = MISCREG_MC3_ADDR;
-                break;
-              case 0x412:
-                regNum = MISCREG_MC4_ADDR;
-                break;
-              case 0x416:
-                regNum = MISCREG_MC5_ADDR;
-                break;
-              case 0x41A:
-                regNum = MISCREG_MC6_ADDR;
-                break;
-              case 0x41E:
-                regNum = MISCREG_MC7_ADDR;
-                break;
-              case 0x403:
-                regNum = MISCREG_MC0_MISC;
-                break;
-              case 0x407:
-                regNum = MISCREG_MC1_MISC;
-                break;
-              case 0x40B:
-                regNum = MISCREG_MC2_MISC;
-                break;
-              case 0x40F:
-                regNum = MISCREG_MC3_MISC;
-                break;
-              case 0x413:
-                regNum = MISCREG_MC4_MISC;
-                break;
-              case 0x417:
-                regNum = MISCREG_MC5_MISC;
-                break;
-              case 0x41B:
-                regNum = MISCREG_MC6_MISC;
-                break;
-              case 0x41F:
-                regNum = MISCREG_MC7_MISC;
-                break;
-              case 0xC0000080:
-                regNum = MISCREG_EFER;
-                break;
-              case 0xC0000081:
-                regNum = MISCREG_STAR;
-                break;
-              case 0xC0000082:
-                regNum = MISCREG_LSTAR;
-                break;
-              case 0xC0000083:
-                regNum = MISCREG_CSTAR;
-                break;
-              case 0xC0000084:
-                regNum = MISCREG_SF_MASK;
-                break;
-              case 0xC0000100:
-                regNum = MISCREG_FS_BASE;
-                break;
-              case 0xC0000101:
-                regNum = MISCREG_GS_BASE;
-                break;
-              case 0xC0000102:
-                regNum = MISCREG_KERNEL_GS_BASE;
-                break;
-              case 0xC0000103:
-                regNum = MISCREG_TSC_AUX;
-                break;
-              case 0xC0010000:
-                regNum = MISCREG_PERF_EVT_SEL0;
-                break;
-              case 0xC0010001:
-                regNum = MISCREG_PERF_EVT_SEL1;
-                break;
-              case 0xC0010002:
-                regNum = MISCREG_PERF_EVT_SEL2;
-                break;
-              case 0xC0010003:
-                regNum = MISCREG_PERF_EVT_SEL3;
-                break;
-              case 0xC0010004:
-                regNum = MISCREG_PERF_EVT_CTR0;
-                break;
-              case 0xC0010005:
-                regNum = MISCREG_PERF_EVT_CTR1;
-                break;
-              case 0xC0010006:
-                regNum = MISCREG_PERF_EVT_CTR2;
-                break;
-              case 0xC0010007:
-                regNum = MISCREG_PERF_EVT_CTR3;
-                break;
-              case 0xC0010010:
-                regNum = MISCREG_SYSCFG;
-                break;
-              case 0xC0010016:
-                regNum = MISCREG_IORR_BASE0;
-                break;
-              case 0xC0010017:
-                regNum = MISCREG_IORR_BASE1;
-                break;
-              case 0xC0010018:
-                regNum = MISCREG_IORR_MASK0;
-                break;
-              case 0xC0010019:
-                regNum = MISCREG_IORR_MASK1;
-                break;
-              case 0xC001001A:
-                regNum = MISCREG_TOP_MEM;
-                break;
-              case 0xC001001D:
-                regNum = MISCREG_TOP_MEM2;
-                break;
-              case 0xC0010114:
-                regNum = MISCREG_VM_CR;
-                break;
-              case 0xC0010115:
-                regNum = MISCREG_IGNNE;
-                break;
-              case 0xC0010116:
-                regNum = MISCREG_SMM_CTL;
-                break;
-              case 0xC0010117:
-                regNum = MISCREG_VM_HSAVE_PA;
-                break;
-              default:
+            MiscRegIndex regNum;
+            if (!msrAddrToIndex(regNum, vaddr))
                 return std::make_shared<GeneralProtection>(0);
-            }
-            //The index is multiplied by the size of a MiscReg so that
-            //any memory dependence calculations will not see these as
-            //overlapping.
-            req->setPaddr(regNum * sizeof(RegVal));
+
+            req->setLocalAccessor(
+                [read,regNum,vaddr](ThreadContext *tc, PacketPtr pkt)
+                {
+                    return localMiscRegAccess(read, regNum, tc, pkt);
+                }
+            );
+
             return NoFault;
         } else if (prefix == IntAddrPrefixIO) {
             // TODO If CPL > IOPL or in virtual mode, check the I/O permission
@@ -613,25 +328,27 @@
             // Make sure the address fits in the expected 16 bit IO address
             // space.
             assert(!(IOPort & ~0xFFFF));
-
             if (IOPort == 0xCF8 && req->getSize() == 4) {
-                req->setFlags(Request::MMAPPED_IPR);
-                req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(RegVal));
+                req->setLocalAccessor(
+                    [read](ThreadContext *tc, PacketPtr pkt)
+                    {
+                        return localMiscRegAccess(
+                                read, MISCREG_PCI_CONFIG_ADDRESS, tc, pkt);
+                    }
+                );
             } else if ((IOPort & ~mask(2)) == 0xCFC) {
-                req->setFlags(Request::UNCACHEABLE);
-
+                req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
                 Addr configAddress =
                     tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS);
-
                 if (bits(configAddress, 31, 31)) {
                     req->setPaddr(PhysAddrPrefixPciConfig |
-                                  mbits(configAddress, 30, 2) |
-                                  (IOPort & mask(2)));
+                            mbits(configAddress, 30, 2) |
+                            (IOPort & mask(2)));
                 } else {
                     req->setPaddr(PhysAddrPrefixIO | IOPort);
                 }
             } else {
-                req->setFlags(Request::UNCACHEABLE);
+                req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
                 req->setPaddr(PhysAddrPrefixIO | IOPort);
             }
             return NoFault;
@@ -709,7 +426,7 @@
         // If this is true, we're dealing with a request
         // to a non-memory address space.
         if (seg == SEGMENT_REG_MS) {
-            return translateInt(req, tc);
+            return translateInt(mode == Read, req, tc);
         }
 
         delayedResponse = false;
diff --git a/src/mem/cache/mshr.cc b/src/mem/cache/mshr.cc
index 8ae6d97..9dae03d 100644
--- a/src/mem/cache/mshr.cc
+++ b/src/mem/cache/mshr.cc
@@ -129,8 +129,7 @@
         // strictly ordered)
         const Request::FlagsType no_merge_flags =
             Request::UNCACHEABLE | Request::STRICT_ORDER |
-            Request::MMAPPED_IPR | Request::PRIVILEGED |
-            Request::LLSC | Request::MEM_SWAP |
+            Request::PRIVILEGED | Request::LLSC | Request::MEM_SWAP |
             Request::MEM_SWAP_COND | Request::SECURE;
         const auto &req_flags = pkt->req->getFlags();
         bool compat_write = !req_flags.isSet(no_merge_flags);
diff --git a/src/mem/request.hh b/src/mem/request.hh
index debf8a1..57ca793 100644
--- a/src/mem/request.hh
+++ b/src/mem/request.hh
@@ -76,7 +76,9 @@
     };
 }
 
+class Packet;
 class Request;
+class ThreadContext;
 
 typedef std::shared_ptr<Request> RequestPtr;
 typedef uint16_t MasterID;
@@ -119,8 +121,6 @@
          * the UNCACHEABLE flag is set as well.
          */
         STRICT_ORDER                = 0x00000800,
-        /** This request is to a memory mapped register. */
-        MMAPPED_IPR                 = 0x00002000,
         /** This request is made in privileged mode. */
         PRIVILEGED                  = 0x00008000,
 
@@ -247,6 +247,9 @@
         ARG_SEGMENT            = 0x00000800,
     };
 
+    using LocalAccessor =
+        std::function<Cycles(ThreadContext *tc, Packet *pkt)>;
+
   private:
     typedef uint16_t PrivateFlagsType;
     typedef ::Flags<PrivateFlagsType> PrivateFlags;
@@ -382,6 +385,8 @@
     /** A pointer to an atomic operation */
     AtomicOpFunctorPtr atomicOpFunctor;
 
+    LocalAccessor _localAccessor;
+
   public:
 
     /**
@@ -478,10 +483,10 @@
           _taskId(other._taskId), _asid(other._asid), _vaddr(other._vaddr),
           _extraData(other._extraData), _contextId(other._contextId),
           _pc(other._pc), _reqInstSeqNum(other._reqInstSeqNum),
+          _localAccessor(other._localAccessor),
           translateDelta(other.translateDelta),
           accessDelta(other.accessDelta), depth(other.depth)
     {
-
         atomicOpFunctor.reset(other.atomicOpFunctor ?
                                 other.atomicOpFunctor->clone() : nullptr);
     }
@@ -536,6 +541,7 @@
         accessDelta = 0;
         translateDelta = 0;
         atomicOpFunctor = std::move(amo_op);
+        _localAccessor = nullptr;
     }
 
     /**
@@ -663,6 +669,17 @@
         return _time;
     }
 
+    /** Is this request for a local memory mapped resource/register? */
+    bool isLocalAccess() { return (bool)_localAccessor; }
+    /** Set the function which will enact that access. */
+    void setLocalAccessor(LocalAccessor acc) { _localAccessor = acc; }
+    /** Perform the installed local access. */
+    Cycles
+    localAccessor(ThreadContext *tc, Packet *pkt)
+    {
+        return _localAccessor(tc, pkt);
+    }
+
     /**
      * Accessor for atomic-op functor.
      */
@@ -895,7 +912,6 @@
     bool isLockedRMW() const { return _flags.isSet(LOCKED_RMW); }
     bool isSwap() const { return _flags.isSet(MEM_SWAP|MEM_SWAP_COND); }
     bool isCondSwap() const { return _flags.isSet(MEM_SWAP_COND); }
-    bool isMmappedIpr() const { return _flags.isSet(MMAPPED_IPR); }
     bool isSecure() const { return _flags.isSet(SECURE); }
     bool isPTWalk() const { return _flags.isSet(PT_WALK); }
     bool isAcquire() const { return _flags.isSet(ACQUIRE); }