arch,cpu: Turn the Decoder objects into SimObjects.

Change-Id: I85839880db588b3b92064b8fcbf053c1811a1fdc
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/52080
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/arch/arm/ArmDecoder.py b/src/arch/arm/ArmDecoder.py
new file mode 100644
index 0000000..9f01af6
--- /dev/null
+++ b/src/arch/arm/ArmDecoder.py
@@ -0,0 +1,31 @@
+# Copyright 2021 Google, Inc.
+#
+# 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.
+
+from m5.objects.InstDecoder import InstDecoder
+
+class ArmDecoder(InstDecoder):
+    type = 'ArmDecoder'
+    cxx_class = 'gem5::ArmISA::Decoder'
+    cxx_header = "arch/arm/decoder.hh"
diff --git a/src/arch/arm/SConscript b/src/arch/arm/SConscript
index ddc9526..ec1db57 100644
--- a/src/arch/arm/SConscript
+++ b/src/arch/arm/SConscript
@@ -93,6 +93,7 @@
 Source('tlbi_op.cc', tags='arm isa')
 Source('utility.cc', tags='arm isa')
 
+SimObject('ArmDecoder.py', tags='arm isa')
 SimObject('ArmFsWorkload.py', tags='arm isa')
 SimObject('ArmInterrupts.py', tags='arm isa')
 SimObject('ArmISA.py', tags='arm isa')
diff --git a/src/arch/arm/decoder.cc b/src/arch/arm/decoder.cc
index 7297161..9d90537 100644
--- a/src/arch/arm/decoder.cc
+++ b/src/arch/arm/decoder.cc
@@ -54,14 +54,15 @@
 
 GenericISA::BasicDecodeCache<Decoder, ExtMachInst> Decoder::defaultCache;
 
-Decoder::Decoder(ISA* isa)
-    : InstDecoder(&data), data(0), fpscrLen(0), fpscrStride(0),
-      decoderFlavor(isa->decoderFlavor())
+Decoder::Decoder(const ArmDecoderParams &params)
+    : InstDecoder(params, &data), data(0), fpscrLen(0), fpscrStride(0),
+      decoderFlavor(dynamic_cast<ISA *>(params.isa)->decoderFlavor())
 {
     reset();
 
     // Initialize SVE vector length
-    sveLen = (isa->getCurSveVecLenInBitsAtReset() >> 7) - 1;
+    sveLen = (dynamic_cast<ISA *>(params.isa)
+            ->getCurSveVecLenInBitsAtReset() >> 7) - 1;
 }
 
 void
diff --git a/src/arch/arm/decoder.hh b/src/arch/arm/decoder.hh
index b99ac4f..62d6f54 100644
--- a/src/arch/arm/decoder.hh
+++ b/src/arch/arm/decoder.hh
@@ -51,6 +51,7 @@
 #include "cpu/static_inst.hh"
 #include "debug/Decode.hh"
 #include "enums/DecoderFlavor.hh"
+#include "params/ArmDecoder.hh"
 
 namespace gem5
 {
@@ -130,7 +131,7 @@
     }
 
   public: // Decoder API
-    Decoder(ISA* isa = nullptr);
+    Decoder(const ArmDecoderParams &params);
 
     /** Reset the decoders internal state. */
     void reset() override;
diff --git a/src/arch/generic/InstDecoder.py b/src/arch/generic/InstDecoder.py
new file mode 100644
index 0000000..7f3b7fd
--- /dev/null
+++ b/src/arch/generic/InstDecoder.py
@@ -0,0 +1,35 @@
+# Copyright 2021 Google, Inc.
+#
+# 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.
+
+from m5.params import *
+from m5.SimObject import SimObject
+
+class InstDecoder(SimObject):
+    type = 'InstDecoder'
+    abstract = True
+    cxx_header = "arch/generic/decoder.hh"
+    cxx_class = 'gem5::InstDecoder'
+
+    isa = Param.BaseISA(NULL, "ISA object for this context")
diff --git a/src/arch/generic/SConscript b/src/arch/generic/SConscript
index 8231ccf..140ea6c 100644
--- a/src/arch/generic/SConscript
+++ b/src/arch/generic/SConscript
@@ -45,6 +45,7 @@
 SimObject('BaseISA.py')
 SimObject('BaseMMU.py')
 SimObject('BaseTLB.py')
+SimObject('InstDecoder.py')
 
 DebugFlag('PageTableWalker',
           "Page table walker state machine debugging")
@@ -53,7 +54,4 @@
 GTest('vec_reg.test', 'vec_reg.test.cc')
 GTest('vec_pred_reg.test', 'vec_pred_reg.test.cc')
 
-if env['TARGET_ISA'] == 'null':
-    Return()
-
 Source('decoder.cc')
diff --git a/src/arch/generic/decoder.hh b/src/arch/generic/decoder.hh
index 9f0fc2a..afba1a3 100644
--- a/src/arch/generic/decoder.hh
+++ b/src/arch/generic/decoder.hh
@@ -33,11 +33,13 @@
 #include "base/intmath.hh"
 #include "base/types.hh"
 #include "cpu/static_inst_fwd.hh"
+#include "params/InstDecoder.hh"
+#include "sim/sim_object.hh"
 
 namespace gem5
 {
 
-class InstDecoder
+class InstDecoder : public SimObject
 {
   protected:
     void *_moreBytesPtr;
@@ -49,8 +51,9 @@
 
   public:
     template <typename MoreBytesType>
-    InstDecoder(MoreBytesType *mb_buf) :
-        _moreBytesPtr(mb_buf), _moreBytesSize(sizeof(MoreBytesType)),
+    InstDecoder(const InstDecoderParams &params, MoreBytesType *mb_buf) :
+        SimObject(params), _moreBytesPtr(mb_buf),
+        _moreBytesSize(sizeof(MoreBytesType)),
         _pcMask(~mask(floorLog2(_moreBytesSize)))
     {}
 
diff --git a/src/arch/mips/MipsDecoder.py b/src/arch/mips/MipsDecoder.py
new file mode 100644
index 0000000..3fe5930
--- /dev/null
+++ b/src/arch/mips/MipsDecoder.py
@@ -0,0 +1,31 @@
+# Copyright 2021 Google, Inc.
+#
+# 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.
+
+from m5.objects.InstDecoder import InstDecoder
+
+class MipsDecoder(InstDecoder):
+    type = 'MipsDecoder'
+    cxx_class = 'gem5::MipsISA::Decoder'
+    cxx_header = "arch/mips/decoder.hh"
diff --git a/src/arch/mips/SConscript b/src/arch/mips/SConscript
index 26be9f6..ab903fa 100644
--- a/src/arch/mips/SConscript
+++ b/src/arch/mips/SConscript
@@ -43,6 +43,7 @@
 Source('tlb.cc', tags='mips isa')
 Source('utility.cc', tags='mips isa')
 
+SimObject('MipsDecoder.py', tags='mips isa')
 SimObject('MipsInterrupts.py', tags='mips isa')
 SimObject('MipsISA.py', tags='mips isa')
 SimObject('MipsMMU.py', tags='mips isa')
diff --git a/src/arch/mips/decoder.hh b/src/arch/mips/decoder.hh
index 815a437..1e47e1b 100644
--- a/src/arch/mips/decoder.hh
+++ b/src/arch/mips/decoder.hh
@@ -36,6 +36,7 @@
 #include "base/types.hh"
 #include "cpu/static_inst.hh"
 #include "debug/Decode.hh"
+#include "params/MipsDecoder.hh"
 
 namespace gem5
 {
@@ -52,7 +53,7 @@
     uint32_t machInst;
 
   public:
-    Decoder(ISA* isa = nullptr) : InstDecoder(&machInst)
+    Decoder(const MipsDecoderParams &p) : InstDecoder(p, &machInst)
     {}
 
     //Use this to give data to the decoder. This should be used
diff --git a/src/arch/power/PowerDecoder.py b/src/arch/power/PowerDecoder.py
new file mode 100644
index 0000000..7298c40
--- /dev/null
+++ b/src/arch/power/PowerDecoder.py
@@ -0,0 +1,31 @@
+# Copyright 2021 Google, Inc.
+#
+# 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.
+
+from m5.objects.InstDecoder import InstDecoder
+
+class PowerDecoder(InstDecoder):
+    type = 'PowerDecoder'
+    cxx_class = 'gem5::PowerISA::Decoder'
+    cxx_header = "arch/power/decoder.hh"
diff --git a/src/arch/power/SConscript b/src/arch/power/SConscript
index b26525b..0b1b9ea 100644
--- a/src/arch/power/SConscript
+++ b/src/arch/power/SConscript
@@ -46,6 +46,7 @@
 Source('se_workload.cc', tags='power isa')
 Source('tlb.cc', tags='power isa')
 
+SimObject('PowerDecoder.py', tags='power isa')
 SimObject('PowerInterrupts.py', tags='power isa')
 SimObject('PowerISA.py', tags='power isa')
 SimObject('PowerMMU.py', tags='power isa')
diff --git a/src/arch/power/decoder.hh b/src/arch/power/decoder.hh
index c5e7e27..8668095 100644
--- a/src/arch/power/decoder.hh
+++ b/src/arch/power/decoder.hh
@@ -35,6 +35,7 @@
 #include "arch/power/types.hh"
 #include "cpu/static_inst.hh"
 #include "debug/Decode.hh"
+#include "params/PowerDecoder.hh"
 
 namespace gem5
 {
@@ -50,7 +51,7 @@
     ExtMachInst emi;
 
   public:
-    Decoder(ISA* isa=nullptr) : InstDecoder(&emi) {}
+    Decoder(const PowerDecoderParams &p) : InstDecoder(p, &emi) {}
 
     // Use this to give data to the predecoder. This should be used
     // when there is control flow.
diff --git a/src/arch/riscv/RiscvDecoder.py b/src/arch/riscv/RiscvDecoder.py
new file mode 100644
index 0000000..1eebf2f
--- /dev/null
+++ b/src/arch/riscv/RiscvDecoder.py
@@ -0,0 +1,31 @@
+# Copyright 2021 Google, Inc.
+#
+# 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.
+
+from m5.objects.InstDecoder import InstDecoder
+
+class RiscvDecoder(InstDecoder):
+    type = 'RiscvDecoder'
+    cxx_class = 'gem5::RiscvISA::Decoder'
+    cxx_header = "arch/riscv/decoder.hh"
diff --git a/src/arch/riscv/SConscript b/src/arch/riscv/SConscript
index 9f3fd48..ddd7c6b 100644
--- a/src/arch/riscv/SConscript
+++ b/src/arch/riscv/SConscript
@@ -62,6 +62,7 @@
 
 SimObject('PMAChecker.py', tags='riscv isa')
 SimObject('PMP.py', tags='riscv isa')
+SimObject('RiscvDecoder.py', tags='riscv isa')
 SimObject('RiscvFsWorkload.py', tags='riscv isa')
 SimObject('RiscvInterrupts.py', tags='riscv isa')
 SimObject('RiscvISA.py', tags='riscv isa')
diff --git a/src/arch/riscv/decoder.hh b/src/arch/riscv/decoder.hh
index 8e6bc80..d4abe68 100644
--- a/src/arch/riscv/decoder.hh
+++ b/src/arch/riscv/decoder.hh
@@ -37,6 +37,7 @@
 #include "base/types.hh"
 #include "cpu/static_inst.hh"
 #include "debug/Decode.hh"
+#include "params/RiscvDecoder.hh"
 
 namespace gem5
 {
@@ -65,7 +66,10 @@
     StaticInstPtr decode(ExtMachInst mach_inst, Addr addr);
 
   public:
-    Decoder(ISA* isa=nullptr) : InstDecoder(&machInst) { reset(); }
+    Decoder(const RiscvDecoderParams &p) : InstDecoder(p, &machInst)
+    {
+        reset();
+    }
 
     void reset() override;
 
diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript
index 2a15847..e69754c 100644
--- a/src/arch/sparc/SConscript
+++ b/src/arch/sparc/SConscript
@@ -43,6 +43,7 @@
 Source('tlb.cc', tags='sparc isa')
 Source('ua2005.cc', tags='sparc isa')
 
+SimObject('SparcDecoder.py', tags='sparc isa')
 SimObject('SparcFsWorkload.py', tags='sparc isa')
 SimObject('SparcInterrupts.py', tags='sparc isa')
 SimObject('SparcISA.py', tags='sparc isa')
diff --git a/src/arch/sparc/SparcDecoder.py b/src/arch/sparc/SparcDecoder.py
new file mode 100644
index 0000000..cc91948
--- /dev/null
+++ b/src/arch/sparc/SparcDecoder.py
@@ -0,0 +1,31 @@
+# Copyright 2021 Google, Inc.
+#
+# 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.
+
+from m5.objects.InstDecoder import InstDecoder
+
+class SparcDecoder(InstDecoder):
+    type = 'SparcDecoder'
+    cxx_class = 'gem5::SparcISA::Decoder'
+    cxx_header = "arch/sparc/decoder.hh"
diff --git a/src/arch/sparc/decoder.hh b/src/arch/sparc/decoder.hh
index e42ecd2..56eb177 100644
--- a/src/arch/sparc/decoder.hh
+++ b/src/arch/sparc/decoder.hh
@@ -34,6 +34,7 @@
 #include "arch/sparc/types.hh"
 #include "cpu/static_inst.hh"
 #include "debug/Decode.hh"
+#include "params/SparcDecoder.hh"
 
 namespace gem5
 {
@@ -51,7 +52,7 @@
     RegVal asi;
 
   public:
-    Decoder(ISA* isa=nullptr) : InstDecoder(&machInst), asi(0)
+    Decoder(const SparcDecoderParams &p) : InstDecoder(p, &machInst), asi(0)
     {}
 
     // Use this to give data to the predecoder. This should be used
diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript
index a455ded..50ec117 100644
--- a/src/arch/x86/SConscript
+++ b/src/arch/x86/SConscript
@@ -63,6 +63,7 @@
 
 SimObject('X86SeWorkload.py', tags='x86 isa')
 SimObject('X86FsWorkload.py', tags='x86 isa')
+SimObject('X86Decoder.py', tags='x86 isa')
 SimObject('X86ISA.py', tags='x86 isa')
 SimObject('X86LocalApic.py', tags='x86 isa')
 SimObject('X86MMU.py', tags='x86 isa')
diff --git a/src/arch/x86/X86Decoder.py b/src/arch/x86/X86Decoder.py
new file mode 100644
index 0000000..e73367b
--- /dev/null
+++ b/src/arch/x86/X86Decoder.py
@@ -0,0 +1,31 @@
+# Copyright 2021 Google, Inc.
+#
+# 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.
+
+from m5.objects.InstDecoder import InstDecoder
+
+class X86Decoder(InstDecoder):
+    type = 'X86Decoder'
+    cxx_class = 'gem5::X86ISA::Decoder'
+    cxx_header = "arch/x86/decoder.hh"
diff --git a/src/arch/x86/decoder.hh b/src/arch/x86/decoder.hh
index cca6a1d..1f7a7e4 100644
--- a/src/arch/x86/decoder.hh
+++ b/src/arch/x86/decoder.hh
@@ -44,6 +44,7 @@
 #include "cpu/decode_cache.hh"
 #include "cpu/static_inst.hh"
 #include "debug/Decoder.hh"
+#include "params/X86Decoder.hh"
 
 namespace gem5
 {
@@ -253,7 +254,7 @@
     void process();
 
   public:
-    Decoder(ISA *isa=nullptr) : InstDecoder(&fetchChunk)
+    Decoder(const X86DecoderParams &p) : InstDecoder(p, &fetchChunk)
     {
         emi.reset();
         emi.mode.mode = mode;
diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py
index c60b12d..5eeedd3 100644
--- a/src/cpu/BaseCPU.py
+++ b/src/cpu/BaseCPU.py
@@ -60,26 +60,32 @@
     from m5.objects.SparcMMU import SparcMMU as ArchMMU
     from m5.objects.SparcInterrupts import SparcInterrupts as ArchInterrupts
     from m5.objects.SparcISA import SparcISA as ArchISA
+    from m5.objects.SparcDecoder import SparcDecoder as ArchDecoder
 elif buildEnv['TARGET_ISA'] == 'x86':
     from m5.objects.X86MMU import X86MMU as ArchMMU
     from m5.objects.X86LocalApic import X86LocalApic as ArchInterrupts
     from m5.objects.X86ISA import X86ISA as ArchISA
+    from m5.objects.X86Decoder import X86Decoder as ArchDecoder
 elif buildEnv['TARGET_ISA'] == 'mips':
     from m5.objects.MipsMMU import MipsMMU as ArchMMU
     from m5.objects.MipsInterrupts import MipsInterrupts as ArchInterrupts
     from m5.objects.MipsISA import MipsISA as ArchISA
+    from m5.objects.MipsDecoder import MipsDecoder as ArchDecoder
 elif buildEnv['TARGET_ISA'] == 'arm':
     from m5.objects.ArmMMU import ArmMMU as ArchMMU
     from m5.objects.ArmInterrupts import ArmInterrupts as ArchInterrupts
     from m5.objects.ArmISA import ArmISA as ArchISA
+    from m5.objects.ArmDecoder import ArmDecoder as ArchDecoder
 elif buildEnv['TARGET_ISA'] == 'power':
     from m5.objects.PowerMMU import PowerMMU as ArchMMU
     from m5.objects.PowerInterrupts import PowerInterrupts as ArchInterrupts
     from m5.objects.PowerISA import PowerISA as ArchISA
+    from m5.objects.PowerDecoder import PowerDecoder as ArchDecoder
 elif buildEnv['TARGET_ISA'] == 'riscv':
     from m5.objects.RiscvMMU import RiscvMMU as ArchMMU
     from m5.objects.RiscvInterrupts import RiscvInterrupts as ArchInterrupts
     from m5.objects.RiscvISA import RiscvISA as ArchISA
+    from m5.objects.RiscvDecoder import RiscvDecoder as ArchDecoder
 else:
     print("Don't know what object types to use for ISA %s" %
             buildEnv['TARGET_ISA'])
@@ -152,6 +158,7 @@
     mmu = Param.BaseMMU(ArchMMU(), "CPU memory management unit")
     interrupts = VectorParam.BaseInterrupts([], "Interrupt Controller")
     isa = VectorParam.BaseISA([], "ISA instance")
+    decoder = VectorParam.InstDecoder([], "Decoder instance")
 
     max_insts_all_threads = Param.Counter(0,
         "terminate when all threads have reached this inst count")
@@ -231,11 +238,14 @@
         # If no ISAs have been created, assume that the user wants the
         # default ISA.
         if len(self.isa) == 0:
-            self.isa = [ ArchISA() for i in range(self.numThreads) ]
+            self.isa = list([ ArchISA() for i in range(self.numThreads) ])
         else:
             if len(self.isa) != int(self.numThreads):
                 raise RuntimeError("Number of ISA instances doesn't "
                                    "match thread count")
+        if len(self.decoder) != 0:
+            raise RuntimeError("Decoders should not be set up manually")
+        self.decoder = list([ ArchDecoder(isa=isa) for isa in self.isa ])
         if self.checker != NULL:
             self.checker.createThreads()
 
diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc
index c20321c..f374331 100644
--- a/src/cpu/checker/cpu.cc
+++ b/src/cpu/checker/cpu.cc
@@ -101,11 +101,12 @@
     systemPtr = system;
 
     if (FullSystem) {
-        thread = new SimpleThread(this, 0, systemPtr, mmu, p.isa[0]);
+        thread = new SimpleThread(this, 0, systemPtr, mmu, p.isa[0],
+                                  p.decoder[0]);
     } else {
         thread = new SimpleThread(this, 0, systemPtr,
                                   workload.size() ? workload[0] : NULL,
-                                  mmu, p.isa[0]);
+                                  mmu, p.isa[0], p.decoder[0]);
     }
 
     tc = thread->getTC();
diff --git a/src/cpu/kvm/base.cc b/src/cpu/kvm/base.cc
index 79bbf02..bc0e428 100644
--- a/src/cpu/kvm/base.cc
+++ b/src/cpu/kvm/base.cc
@@ -87,11 +87,11 @@
 
     if (FullSystem)
         thread = new SimpleThread(this, 0, params.system, params.mmu,
-                                  params.isa[0]);
+                                  params.isa[0], params.decoder[0]);
     else
         thread = new SimpleThread(this, /* thread_num */ 0, params.system,
                                   params.workload[0], params.mmu,
-                                  params.isa[0]);
+                                  params.isa[0], params.decoder[0]);
 
     thread->setStatus(ThreadContext::Halted);
     tc = thread->getTC();
diff --git a/src/cpu/minor/cpu.cc b/src/cpu/minor/cpu.cc
index b8e9711..0bc26e3 100644
--- a/src/cpu/minor/cpu.cc
+++ b/src/cpu/minor/cpu.cc
@@ -58,12 +58,12 @@
     for (ThreadID i = 0; i < numThreads; i++) {
         if (FullSystem) {
             thread = new minor::MinorThread(this, i, params.system,
-                    params.mmu, params.isa[i]);
+                    params.mmu, params.isa[i], params.decoder[i]);
             thread->setStatus(ThreadContext::Halted);
         } else {
             thread = new minor::MinorThread(this, i, params.system,
                     params.workload[i], params.mmu,
-                    params.isa[i]);
+                    params.isa[i], params.decoder[i]);
         }
 
         threads.push_back(thread);
diff --git a/src/cpu/o3/fetch.cc b/src/cpu/o3/fetch.cc
index 61ffc17..2105900 100644
--- a/src/cpu/o3/fetch.cc
+++ b/src/cpu/o3/fetch.cc
@@ -136,8 +136,7 @@
     branchPred = params.branchPred;
 
     for (ThreadID tid = 0; tid < numThreads; tid++) {
-        decoder[tid] = new TheISA::Decoder(
-                dynamic_cast<TheISA::ISA *>(params.isa[tid]));
+        decoder[tid] = params.decoder[tid];
         // Create space to buffer the cache line data,
         // which may not hold the entire cache line.
         fetchBuffer[tid] = new uint8_t[fetchBufferSize];
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index 5d4ee3e..ad98ed9 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -93,10 +93,11 @@
     for (unsigned i = 0; i < numThreads; i++) {
         if (FullSystem) {
             thread = new SimpleThread(
-                this, i, p.system, p.mmu, p.isa[i]);
+                this, i, p.system, p.mmu, p.isa[i], p.decoder[i]);
         } else {
             thread = new SimpleThread(
-                this, i, p.system, p.workload[i], p.mmu, p.isa[i]);
+                this, i, p.system, p.workload[i], p.mmu, p.isa[i],
+                p.decoder[i]);
         }
         threadInfo.push_back(new SimpleExecContext(this, thread));
         ThreadContext *tc = thread->getTC();
diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc
index 67a0ce6..3c4eae7 100644
--- a/src/cpu/simple_thread.cc
+++ b/src/cpu/simple_thread.cc
@@ -67,12 +67,12 @@
 // constructor
 SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
                            Process *_process, BaseMMU *_mmu,
-                           BaseISA *_isa)
+                           BaseISA *_isa, InstDecoder *_decoder)
     : ThreadState(_cpu, _thread_num, _process),
       isa(dynamic_cast<TheISA::ISA *>(_isa)),
       predicate(true), memAccPredicate(true),
       comInstEventQueue("instruction-based event queue"),
-      system(_sys), mmu(_mmu), decoder(new TheISA::Decoder(isa)),
+      system(_sys), mmu(_mmu), decoder(_decoder),
       htmTransactionStarts(0), htmTransactionStops(0)
 {
     assert(isa);
@@ -87,8 +87,8 @@
 }
 
 SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
-                           BaseMMU *_mmu, BaseISA *_isa)
-    : SimpleThread(_cpu, _thread_num, _sys, nullptr, _mmu, _isa)
+                           BaseMMU *_mmu, BaseISA *_isa, InstDecoder *_decoder)
+    : SimpleThread(_cpu, _thread_num, _sys, nullptr, _mmu, _isa, _decoder)
 {}
 
 void
diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh
index f896071..50e9f30 100644
--- a/src/cpu/simple_thread.hh
+++ b/src/cpu/simple_thread.hh
@@ -143,11 +143,11 @@
     // constructor: initialize SimpleThread from given process structure
     // FS
     SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system,
-                 BaseMMU *_mmu, BaseISA *_isa);
+                 BaseMMU *_mmu, BaseISA *_isa, InstDecoder *_decoder);
     // SE
     SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system,
                  Process *_process, BaseMMU *_mmu,
-                 BaseISA *_isa);
+                 BaseISA *_isa, InstDecoder *_decoder);
 
     virtual ~SimpleThread() {}