Gabe Black has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/56489 )

Change subject: arch-x86: Move the fp uop defintions to the ucasmlib.
......................................................................

arch-x86: Move the fp uop defintions to the ucasmlib.

The code which actually emits the c++ version of the microop classes is
still in the ISA desc, but now the python version lives in the ucasmlib.

Change-Id: Ib1cd1b7f9048a89a5ef2cbfbb38463c4a1057f55
---
M src/arch/x86/isa/microops/base.isa
M src/arch/x86/isa/microops/fpop.isa
M src/arch/x86/ucasmlib/arch/x86/__init__.py
C src/arch/x86/ucasmlib/arch/x86/microops/__init__.py
R src/arch/x86/ucasmlib/arch/x86/microops/base.py
A src/arch/x86/ucasmlib/arch/x86/microops/fpop.py
A src/arch/x86/ucasmlib/arch/x86/microops/operands.py
7 files changed, 511 insertions(+), 450 deletions(-)



diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa
index 89a9e80..b023749 100644
--- a/src/arch/x86/isa/microops/base.isa
+++ b/src/arch/x86/isa/microops/base.isa
@@ -43,169 +43,15 @@

     # This will be populated with mappings between microop mnemonics and
     # the classes that represent them.
-    from ucasmlib.arch.x86 import microopClasses
+    from ucasmlib.arch.x86 import microops as microopClasses

     # For now, implement this base class into the ISA desc until it's no
     # longer needed.
-    from ucasmlib.arch.x86.microops import X86Microop
+    from ucasmlib.arch.x86.microops.base import X86Microop
+
+ # Bring in all the operand classes for microops which are still defined in
+    # the ISA description.
+    from ucasmlib.arch.x86.microops.operands import *

     sys.path = old_path
 }};
-
-//////////////////////////////////////////////////////////////////////////
-//
-// Base class for the python representation of x86 microops
-//
-//////////////////////////////////////////////////////////////////////////
-
-let {{
-    class Operand(object):
-        @classmethod
-        def isDual(cls):
-            return False
-
-        @classmethod
-        def cxx_class(cls):
-            return 'X86ISA::' + cls.flavor + cls.idx_name + 'Op'
-
-    class FlavorlessOperand(Operand):
-        @classmethod
-        def cxx_class(cls):
-            return 'X86ISA::' + cls.op_type
-
-        def __init__(self, it):
-            self.value = next(it)
-
-        def ctor_args(self):
-            return str(self.value)
-
-    class UpcOp(FlavorlessOperand):
-        op_type = 'Upc'
-    class FaultOp(FlavorlessOperand):
-        op_type = 'Fault'
-    class AddrOp(FlavorlessOperand):
-        op_type = 'Addr'
-
-        def __init__(self, it):
-            self.segment = next(it)
-            [self.scale, self.index, self.base] = next(it)
-            self.disp = next(it)
-
-        def ctor_args(self):
- args = [self.scale, self.index, self.base, self.disp, self.segment]
-            return ', '.join(map(str, args))
-
-    class ImmOp(object):
-        idx_name = ''
-
-        def __init__(self, it):
-            self.value = next(it)
-            super().__init__()
-
-        def ctor_args(self):
-            return str(self.value)
-
-    class Imm8Op(ImmOp, Operand):
-        flavor = 'Imm8'
-    class Imm64Op(ImmOp, Operand):
-        flavor = 'Imm64'
-
-    class DestOp(object):
-        idx_name = 'Dest'
-    class Src1Op(object):
-        idx_name = 'Src1'
-    class Src2Op(object):
-        idx_name = 'Src2'
-
-    class RegisterOp(object):
-        def __init__(self, it):
-            self.idx = next(it)
-            super().__init__()
-
-        def ctor_args(self):
-            return str(self.idx)
-
-    class FoldedOp(RegisterOp):
-        flavor = 'Folded'
-    class DbgOp(RegisterOp):
-        flavor = 'Dbg'
-    class CrOp(RegisterOp):
-        flavor = 'Cr'
-    class SegOp(RegisterOp):
-        flavor = 'Seg'
-    class MiscOp(RegisterOp):
-        flavor = 'Misc'
-    class FloatOp(RegisterOp):
-        flavor = 'Float'
-    class IntOp(RegisterOp):
-        flavor = 'Int'
-    class DataOp(RegisterOp):
-        idx_name = 'Data'
-    class DataHiOp(RegisterOp):
-        idx_name = 'DataHi'
-    class DataLowOp(RegisterOp):
-        idx_name = 'DataLow'
-
-    class FoldedDataOp(FoldedOp, DataOp, Operand):
-        pass
-    class FloatDataOp(FloatOp, DataOp, Operand):
-        pass
-    class FoldedDataHiOp(FoldedOp, DataHiOp, Operand):
-        pass
-    class FoldedDataLowOp(FoldedOp, DataLowOp, Operand):
-        pass
-
-    class FoldedDestOp(FoldedOp, DestOp, Operand):
-        pass
-    class DbgDestOp(DbgOp, DestOp, Operand):
-        pass
-    class CrDestOp(CrOp, DestOp, Operand):
-        pass
-    class SegDestOp(SegOp, DestOp, Operand):
-        pass
-    class MiscDestOp(MiscOp, DestOp, Operand):
-        pass
-    class FloatDestOp(FloatOp, DestOp, Operand):
-        pass
-    class IntDestOp(IntOp, DestOp, Operand):
-        pass
-
-    class FoldedSrc1Op(FoldedOp, Src1Op, Operand):
-        pass
-    class DbgSrc1Op(DbgOp, Src1Op, Operand):
-        pass
-    class CrSrc1Op(CrOp, Src1Op, Operand):
-        pass
-    class SegSrc1Op(SegOp, Src1Op, Operand):
-        pass
-    class MiscSrc1Op(MiscOp, Src1Op, Operand):
-        pass
-    class FloatSrc1Op(FloatOp, Src1Op, Operand):
-        pass
-    class IntSrc1Op(IntOp, Src1Op, Operand):
-        pass
-
-    class FoldedSrc2Op(FoldedOp, Src2Op, Operand):
-        pass
-    class DbgSrc2Op(DbgOp, Src2Op, Operand):
-        pass
-    class CrSrc2Op(CrOp, Src2Op, Operand):
-        pass
-    class SegSrc2Op(SegOp, Src2Op, Operand):
-        pass
-    class MiscSrc2Op(MiscOp, Src2Op, Operand):
-        pass
-    class FloatSrc2Op(FloatOp, Src2Op, Operand):
-        pass
-    class IntSrc2Op(IntOp, Src2Op, Operand):
-        pass
-
-    class Op2(object):
-        @classmethod
-        def isDual(cls):
-            return True
-
-        RegType = FoldedSrc2Op
-        FloatType = FloatSrc2Op
-        ImmType = Imm8Op
-}};
diff --git a/src/arch/x86/isa/microops/fpop.isa b/src/arch/x86/isa/microops/fpop.isa
index f73f181..c47396e 100644
--- a/src/arch/x86/isa/microops/fpop.isa
+++ b/src/arch/x86/isa/microops/fpop.isa
@@ -80,278 +80,19 @@
         template <typename ...Args>
         %(class_name)s(ExtMachInst mach_inst, const char *inst_mnem,
                 uint64_t set_flags, uint8_t data_size, int8_t _spm,
-                Args... args);
+                Args... args) :
+            %(base_class)s(mach_inst, "%(mnemonic)s", inst_mnem, set_flags,
+                    %(op_class)s, { args... }, data_size, _spm)
+        {
+            %(set_reg_idx_arr)s;
+            %(constructor)s;
+        }

         Fault execute(ExecContext *, Trace::InstRecord *) const override;
     };
 }};

-def template MicroFpOpConstructor {{
-    template <typename ...Args>
-    %(class_name)s::%(class_name)s(ExtMachInst mach_inst,
-            const char *inst_mnem, uint64_t set_flags,
-            uint8_t data_size, int8_t _spm, Args... args) :
-        %(base_class)s(mach_inst, "%(mnemonic)s", inst_mnem, set_flags,
-                %(op_class)s, { args... }, data_size, _spm)
-    {
-        %(set_reg_idx_arr)s;
-        %(constructor)s;
-    }
-}};
-
 let {{
-    microopClasses.fpops = []
-
-    class FpOpMeta(type):
-        def __new__(mcls, Name, bases, dict):
-            dict.setdefault('abstract', False)
-            dict['className'] = Name
-            dict['mnemonic'] = Name.lower()
-
-            cls = super().__new__(mcls, Name, bases, dict)
-
-            if not cls.abstract:
-                # Hook into the microassembler dict
-                global microopClasses
-                microopClasses[cls.mnemonic] = cls
-                microopClasses.fpops.append(cls)
-
-            return cls
-
-    class FpOp(X86Microop, metaclass=FpOpMeta):
-        # This class itself doesn't act as a microop
-        abstract = True
-
-        # Default template parameter values
-        flag_code = ""
-        cond_check = "true"
-        else_code = ";"
-        op_class = "FloatAddOp"
-
-        def __init__(self, *ops, spm=0,
-                SetStatus=False, UpdateFTW=True, dataSize="env.dataSize"):
-            self.ops = list(map(str, ops))
-            self.spm = spm
-            self.dataSize = dataSize
-            if SetStatus:
-                self.className += "Flags"
-            if spm:
-                self.className += "Top"
-            if spm and UpdateFTW:
-                self.className += "Tag"
-
-        def getAllocator(self, microFlags):
-            # Ensure there's at least one element to join with ","s.
-            op_iter = iter(self.ops)
-            ops = list([Type(op_iter).ctor_args() for
-                    Type in self.operand_types])
-            spm_ops = [str(self.spm)] + ops
-            return '''new %(class_name)s(machInst, macrocodeBlock,
-                    %(flags)s, %(dataSize)s, %(spm_ops)s)''' % {
-                "class_name" : self.className,
-                "flags" : self.microFlagsText(microFlags),
-                "dataSize" : self.dataSize,
-                "spm_ops" : ", ".join(spm_ops)}
-
-    class Fp0Op(FpOp):
-        abstract = True
-        operand_types = ()
-        def __init__(self, **kwargs):
-            super().__init__(**kwargs)
-
-    class Fp1Op(FpOp):
-        abstract = True
-        operand_types = (FloatDestOp)
-        def __init__(self, reg1, **kwargs):
-            super().__init__(reg1, **kwargs)
-
-    class Fp2Op(FpOp):
-        abstract = True
-        operand_types = (FloatDestOp, FloatSrc1Op)
-        def __init__(self, reg1, reg2, **kwargs):
-            super().__init__(reg1, reg2, **kwargs)
-
-    class Fp3Op(FpOp):
-        abstract = True
-        operand_types = (FloatDestOp, FloatSrc1Op, FloatSrc2Op)
-        def __init__(self, reg1, reg2, reg3, **kwargs):
-            super().__init__(reg1, reg2, reg3, **kwargs)
-
-    class Movfp(Fp2Op):
-        code = 'FpDestReg_uqw = FpSrcReg1_uqw;'
-        else_code = 'FpDestReg_uqw = FpDestReg_uqw;'
-        cond_check = "checkCondition(ccFlagBits | cfofBits | dfBit | \
-                                     ecfBit | ezfBit, src1)"
-        op_class = 'IntAluOp'
-
-    class Xorfp(Fp3Op):
-        code = 'FpDestReg_uqw = FpSrcReg1_uqw ^ FpSrcReg2_uqw;'
-
-    class Sqrtfp(Fp2Op):
-        code = 'FpDestReg = sqrt(FpSrcReg1);'
-        op_class = 'FloatSqrtOp'
-
-    class Cosfp(Fp2Op):
-        code = 'FpDestReg = cos(FpSrcReg1);'
-        op_class = 'FloatSqrtOp'
-
-    class Sinfp(Fp2Op):
-        code = 'FpDestReg = sin(FpSrcReg1);'
-        op_class = 'FloatSqrtOp'
-
-    class Tanfp(Fp2Op):
-        code = 'FpDestReg = tan(FpSrcReg1);'
-        op_class = 'FloatSqrtOp'
-
-
-    # Conversion microops
-    class ConvOp(Fp2Op):
-        abstract = True
-        op_class = 'FloatCvtOp'
-
-    # These probably shouldn't look at the ExtMachInst directly to figure
- # out what size to use and should instead delegate that to the macroop's
-    # constructor. That would be more efficient, and it would make the
-    # microops a little more modular.
-    class Cvtf_i2d(ConvOp):
-        operand_types = (FloatDestOp, IntSrc1Op)
-        code = '''
-            X86IntReg intReg = SrcReg1;
-            if (REX_W)
-                FpDestReg = intReg.SR;
-            else
-                FpDestReg = intReg.SE;
-            '''
-
-    class Cvtf_i2d_hi(ConvOp):
-        operand_types = (FloatDestOp, IntSrc1Op)
-        code = 'FpDestReg = bits(SrcReg1, 63, 32);'
-
-    class Cvtf_d2i(ConvOp):
-        operand_types = (FoldedDestOp, FloatSrc1Op)
-        code = '''
-            int64_t intSrcReg1 = static_cast<int64_t>(FpSrcReg1);
-            DestReg = merge(DestReg, dest, intSrcReg1, dataSize);
-            '''
-
-    # Convert two integers registers representing an 80-bit floating
-    # point number to an x87 register.
-    class Cvtint_fp80(Fp3Op):
-        operand_types = (FloatDestOp, IntSrc1Op, IntSrc2Op)
-        code = '''
-            uint8_t bits[10];
-            *(uint64_t *)(bits + 0) = SrcReg1;
-            *(uint16_t *)(bits + 8) = (uint16_t)SrcReg2;
-            FpDestReg = loadFloat80(bits);
-            '''
-
-    # Convert an x87 register (double) into extended precision and
-    # extract the highest 64 bits.
-    class Cvtfp80h_int(ConvOp):
-        operand_types = (IntDestOp, FloatSrc1Op)
-        code = '''
-            char bits[10];
-            storeFloat80(bits, FpSrcReg1);
-            DestReg = *(uint64_t *)(bits + 0);
-            '''
-
-    # Convert an x87 register (double) into extended precision and
-    # extract the lowest 16 bits.
-    class Cvtfp80l_int(ConvOp):
-        operand_types = (IntDestOp, FloatSrc1Op)
-        code = '''
-            char bits[10];
-            storeFloat80(bits, FpSrcReg1);
-            DestReg = *(uint16_t *)(bits + 8);
-            '''
-
-    # These need to consider size at some point. They'll always use doubles
-    # for the moment.
-    class Addfp(Fp3Op):
-        code = 'FpDestReg = FpSrcReg1 + FpSrcReg2;'
-
-    class Mulfp(Fp3Op):
-        code = 'FpDestReg = FpSrcReg1 * FpSrcReg2;'
-        op_class = 'FloatMultOp'
-
-    class Divfp(Fp3Op):
-        code = 'FpDestReg = FpSrcReg1 / FpSrcReg2;'
-        op_class = 'FloatDivOp'
-
-    class Subfp(Fp3Op):
-        code = 'FpDestReg = FpSrcReg1 - FpSrcReg2;'
-
-    class Yl2xFp(Fp3Op):
-        code = '''
-            FpDestReg = FpSrcReg2 * (log(FpSrcReg1) / log(2));
-        '''
-        op_class = 'FloatSqrtOp'
-
-    class PremFp(Fp3Op):
-        code = '''
-            RegVal new_fsw = FSW;
-            int src1_exp;
-            int src2_exp;
-            std::frexp(FpSrcReg1, &src1_exp);
-            std::frexp(FpSrcReg2, &src2_exp);
-
-            const int d = src2_exp - src1_exp;
-            if (d < 64) {
-                const int64_t q = std::trunc(FpSrcReg2 / FpSrcReg1);
-                FpDestReg = FpSrcReg2 - FpSrcReg1 * q;
-                new_fsw &= ~(CC0Bit | CC1Bit | CC2Bit | CC2Bit);
-                new_fsw |= (q & 0x1) ? CC1Bit : 0;
-                new_fsw |= (q & 0x2) ? CC3Bit : 0;
-                new_fsw |= (q & 0x4) ? CC0Bit : 0;
-            } else {
-                const int n = 42;
-                const int64_t qq = std::trunc(
-                    FpSrcReg2 / std::ldexp(FpSrcReg1, d - n));
-                FpDestReg = FpSrcReg2 - std::ldexp(FpSrcReg1 * qq, d - n);
-                new_fsw |= CC2Bit;
-            }
-        '''
-        op_class = 'FloatDivOp'
-
-        flag_code = 'FSW = new_fsw;'
-
-    class Compfp(Fp2Op):
-        operand_types = (FloatSrc1Op, FloatSrc2Op)
-        # This class sets the condition codes in rflags according to the
-        # rules for comparing floating point.
-        code = '''
-            //               ZF PF CF
-            // Unordered      1  1  1
-            // Greater than   0  0  0
-            // Less than      0  0  1
-            // Equal          1  0  0
-            //           OF = SF = AF = 0
-            ccFlagBits = ccFlagBits & ~(SFBit | AFBit | ZFBit | PFBit);
-            cfofBits = cfofBits & ~(OFBit | CFBit);
-
-            if (std::isnan(FpSrcReg1) || std::isnan(FpSrcReg2)) {
-                ccFlagBits = ccFlagBits | (ZFBit | PFBit);
-                cfofBits = cfofBits | CFBit;
-            }
-            else if(FpSrcReg1 < FpSrcReg2)
-                cfofBits = cfofBits | CFBit;
-            else if(FpSrcReg1 == FpSrcReg2)
-                ccFlagBits = ccFlagBits | ZFBit;
-        '''
-        op_class = 'FloatCmpOp'
-
-    class absfp(Fp2Op):
-        code = 'FpDestReg = fabs(FpSrcReg1);'
-        flag_code = 'FSW = FSW & (~CC1Bit);'
-
-    class chsfp(Fp2Op):
-        code = 'FpDestReg = (-1) * (FpSrcReg1);'
-        flag_code = 'FSW = FSW & (~CC1Bit);'
-
-    class Pop87(Fp0Op):
-        code = ''
-        op_class = 'IntAluOp'
-
     def buildCppClasses(cls, suffix="", flag_code=None, cond_check=None):

         if flag_code is None:
@@ -408,13 +149,10 @@

         # Generate the actual code (finally!)
         header_output += MicroFpOpDeclare.subst(iop_tag)
-        decoder_output += MicroFpOpConstructor.subst(iop_tag)
         exec_output += MicroFpOpExecute.subst(iop_tag)
         header_output += MicroFpOpDeclare.subst(iop_top)
-        decoder_output += MicroFpOpConstructor.subst(iop_top)
         exec_output += MicroFpOpExecute.subst(iop_top)
         header_output += MicroFpOpDeclare.subst(iop)
-        decoder_output += MicroFpOpConstructor.subst(iop)
         exec_output += MicroFpOpExecute.subst(iop)

     for cls in microopClasses.fpops:
diff --git a/src/arch/x86/ucasmlib/arch/x86/__init__.py b/src/arch/x86/ucasmlib/arch/x86/__init__.py
index 26fea5b..47c94c6 100644
--- a/src/arch/x86/ucasmlib/arch/x86/__init__.py
+++ b/src/arch/x86/ucasmlib/arch/x86/__init__.py
@@ -23,7 +23,7 @@
 # (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 .microops import classes as microopClasses
+from .microops import microops
 from .macroop import Macroop
 from .rom import Rom
 from .symbols import symbols
diff --git a/src/arch/x86/ucasmlib/arch/x86/microops.py b/src/arch/x86/ucasmlib/arch/x86/microops/__init__.py
similarity index 79%
copy from src/arch/x86/ucasmlib/arch/x86/microops.py
copy to src/arch/x86/ucasmlib/arch/x86/microops/__init__.py
index bcc432d..cf1c838 100644
--- a/src/arch/x86/ucasmlib/arch/x86/microops.py
+++ b/src/arch/x86/ucasmlib/arch/x86/microops/__init__.py
@@ -34,21 +34,10 @@

 class ExpandableDict(dict):
     pass
-classes = ExpandableDict()

-class X86Microop(object):
-    def __init__(self, name):
-        self.name = name
+microops = ExpandableDict()

-    def microFlagsText(self, flags):
-        wrapped = ("(1ULL << StaticInst::%s)" % flag for flag in flags)
-        return " | ".join(wrapped)
-
-    def getGenerator(self):
-        return f'''
-        [](const char *macrocodeBlock, const ExtMachInst &machInst,
-                const EmulEnv &env)
-        {{
-            using namespace rom_labels;
-            return {self.getAllocator(["IsMicroop", "IsDelayedCommit"])};
-        }}'''
+# Add the floating point microops.
+from . import fpop
+microops.update(fpop.microops)
+microops.fpops = fpop.fpops
diff --git a/src/arch/x86/ucasmlib/arch/x86/microops.py b/src/arch/x86/ucasmlib/arch/x86/microops/base.py
similarity index 96%
rename from src/arch/x86/ucasmlib/arch/x86/microops.py
rename to src/arch/x86/ucasmlib/arch/x86/microops/base.py
index bcc432d..d9ca4c3 100644
--- a/src/arch/x86/ucasmlib/arch/x86/microops.py
+++ b/src/arch/x86/ucasmlib/arch/x86/microops/base.py
@@ -32,10 +32,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-class ExpandableDict(dict):
-    pass
-classes = ExpandableDict()
-
 class X86Microop(object):
     def __init__(self, name):
         self.name = name
diff --git a/src/arch/x86/ucasmlib/arch/x86/microops/fpop.py b/src/arch/x86/ucasmlib/arch/x86/microops/fpop.py
new file mode 100644
index 0000000..5dda099
--- /dev/null
+++ b/src/arch/x86/ucasmlib/arch/x86/microops/fpop.py
@@ -0,0 +1,291 @@
+# Copyright 2007 The Hewlett-Packard Development Company
+# Copyright 2012-2013 Mark D. Hill and David A. Wood
+# Copyright 2015 Advanced Micro Devices, Inc.
+#
+# 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.
+
+from .base import X86Microop
+from .operands import *
+
+microops = {}
+fpops = []
+
+class FpOpMeta(type):
+    def __new__(mcls, Name, bases, dict):
+        dict.setdefault('abstract', False)
+        dict['className'] = Name
+        dict['mnemonic'] = Name.lower()
+
+        cls = super().__new__(mcls, Name, bases, dict)
+
+        if not cls.abstract:
+            # Hook into the microassembler dict
+            global microops, fpops
+            microops[cls.mnemonic] = cls
+            fpops.append(cls)
+
+        return cls
+
+class FpOp(X86Microop, metaclass=FpOpMeta):
+    # This class itself doesn't act as a microop
+    abstract = True
+
+    # Default template parameter values
+    flag_code = ""
+    cond_check = "true"
+    else_code = ";"
+    op_class = "FloatAddOp"
+
+    def __init__(self, *ops, spm=0,
+            SetStatus=False, UpdateFTW=True, dataSize="env.dataSize"):
+        self.ops = list(map(str, ops))
+        self.spm = spm
+        self.dataSize = dataSize
+        if SetStatus:
+            self.className += "Flags"
+        if spm:
+            self.className += "Top"
+        if spm and UpdateFTW:
+            self.className += "Tag"
+
+    def getAllocator(self, microFlags):
+        # Ensure there's at least one element to join with ","s.
+        op_iter = iter(self.ops)
+        ops = list([Type(op_iter).ctor_args() for
+                Type in self.operand_types])
+        spm_ops = [str(self.spm)] + ops
+        return '''new %(class_name)s(machInst, macrocodeBlock,
+                %(flags)s, %(dataSize)s, %(spm_ops)s)''' % {
+            "class_name" : self.className,
+            "flags" : self.microFlagsText(microFlags),
+            "dataSize" : self.dataSize,
+            "spm_ops" : ", ".join(spm_ops)}
+
+class Fp0Op(FpOp):
+    abstract = True
+    operand_types = ()
+    def __init__(self, **kwargs):
+        super().__init__(**kwargs)
+
+class Fp1Op(FpOp):
+    abstract = True
+    operand_types = (FloatDestOp)
+    def __init__(self, reg1, **kwargs):
+        super().__init__(reg1, **kwargs)
+
+class Fp2Op(FpOp):
+    abstract = True
+    operand_types = (FloatDestOp, FloatSrc1Op)
+    def __init__(self, reg1, reg2, **kwargs):
+        super().__init__(reg1, reg2, **kwargs)
+
+class Fp3Op(FpOp):
+    abstract = True
+    operand_types = (FloatDestOp, FloatSrc1Op, FloatSrc2Op)
+    def __init__(self, reg1, reg2, reg3, **kwargs):
+        super().__init__(reg1, reg2, reg3, **kwargs)
+
+class Movfp(Fp2Op):
+    code = 'FpDestReg_uqw = FpSrcReg1_uqw;'
+    else_code = 'FpDestReg_uqw = FpDestReg_uqw;'
+    cond_check = "checkCondition(ccFlagBits | cfofBits | dfBit | \
+                                 ecfBit | ezfBit, src1)"
+    op_class = 'IntAluOp'
+
+class Xorfp(Fp3Op):
+    code = 'FpDestReg_uqw = FpSrcReg1_uqw ^ FpSrcReg2_uqw;'
+
+class Sqrtfp(Fp2Op):
+    code = 'FpDestReg = sqrt(FpSrcReg1);'
+    op_class = 'FloatSqrtOp'
+
+class Cosfp(Fp2Op):
+    code = 'FpDestReg = cos(FpSrcReg1);'
+    op_class = 'FloatSqrtOp'
+
+class Sinfp(Fp2Op):
+    code = 'FpDestReg = sin(FpSrcReg1);'
+    op_class = 'FloatSqrtOp'
+
+class Tanfp(Fp2Op):
+    code = 'FpDestReg = tan(FpSrcReg1);'
+    op_class = 'FloatSqrtOp'
+
+
+# Conversion microops
+class ConvOp(Fp2Op):
+    abstract = True
+    op_class = 'FloatCvtOp'
+
+# These probably shouldn't look at the ExtMachInst directly to figure
+# out what size to use and should instead delegate that to the macroop's
+# constructor. That would be more efficient, and it would make the
+# microops a little more modular.
+class Cvtf_i2d(ConvOp):
+    operand_types = (FloatDestOp, IntSrc1Op)
+    code = '''
+        X86IntReg intReg = SrcReg1;
+        if (REX_W)
+            FpDestReg = intReg.SR;
+        else
+            FpDestReg = intReg.SE;
+        '''
+
+class Cvtf_i2d_hi(ConvOp):
+    operand_types = (FloatDestOp, IntSrc1Op)
+    code = 'FpDestReg = bits(SrcReg1, 63, 32);'
+
+class Cvtf_d2i(ConvOp):
+    operand_types = (FoldedDestOp, FloatSrc1Op)
+    code = '''
+        int64_t intSrcReg1 = static_cast<int64_t>(FpSrcReg1);
+        DestReg = merge(DestReg, dest, intSrcReg1, dataSize);
+        '''
+
+# Convert two integers registers representing an 80-bit floating
+# point number to an x87 register.
+class Cvtint_fp80(Fp3Op):
+    operand_types = (FloatDestOp, IntSrc1Op, IntSrc2Op)
+    code = '''
+        uint8_t bits[10];
+        *(uint64_t *)(bits + 0) = SrcReg1;
+        *(uint16_t *)(bits + 8) = (uint16_t)SrcReg2;
+        FpDestReg = loadFloat80(bits);
+        '''
+
+# Convert an x87 register (double) into extended precision and
+# extract the highest 64 bits.
+class Cvtfp80h_int(ConvOp):
+    operand_types = (IntDestOp, FloatSrc1Op)
+    code = '''
+        char bits[10];
+        storeFloat80(bits, FpSrcReg1);
+        DestReg = *(uint64_t *)(bits + 0);
+        '''
+
+# Convert an x87 register (double) into extended precision and
+# extract the lowest 16 bits.
+class Cvtfp80l_int(ConvOp):
+    operand_types = (IntDestOp, FloatSrc1Op)
+    code = '''
+        char bits[10];
+        storeFloat80(bits, FpSrcReg1);
+        DestReg = *(uint16_t *)(bits + 8);
+        '''
+
+# These need to consider size at some point. They'll always use doubles
+# for the moment.
+class Addfp(Fp3Op):
+    code = 'FpDestReg = FpSrcReg1 + FpSrcReg2;'
+
+class Mulfp(Fp3Op):
+    code = 'FpDestReg = FpSrcReg1 * FpSrcReg2;'
+    op_class = 'FloatMultOp'
+
+class Divfp(Fp3Op):
+    code = 'FpDestReg = FpSrcReg1 / FpSrcReg2;'
+    op_class = 'FloatDivOp'
+
+class Subfp(Fp3Op):
+    code = 'FpDestReg = FpSrcReg1 - FpSrcReg2;'
+
+class Yl2xFp(Fp3Op):
+    code = '''
+        FpDestReg = FpSrcReg2 * (log(FpSrcReg1) / log(2));
+    '''
+    op_class = 'FloatSqrtOp'
+
+class PremFp(Fp3Op):
+    code = '''
+        RegVal new_fsw = FSW;
+        int src1_exp;
+        int src2_exp;
+        std::frexp(FpSrcReg1, &src1_exp);
+        std::frexp(FpSrcReg2, &src2_exp);
+
+        const int d = src2_exp - src1_exp;
+        if (d < 64) {
+            const int64_t q = std::trunc(FpSrcReg2 / FpSrcReg1);
+            FpDestReg = FpSrcReg2 - FpSrcReg1 * q;
+            new_fsw &= ~(CC0Bit | CC1Bit | CC2Bit | CC2Bit);
+            new_fsw |= (q & 0x1) ? CC1Bit : 0;
+            new_fsw |= (q & 0x2) ? CC3Bit : 0;
+            new_fsw |= (q & 0x4) ? CC0Bit : 0;
+        } else {
+            const int n = 42;
+            const int64_t qq = std::trunc(
+                FpSrcReg2 / std::ldexp(FpSrcReg1, d - n));
+            FpDestReg = FpSrcReg2 - std::ldexp(FpSrcReg1 * qq, d - n);
+            new_fsw |= CC2Bit;
+        }
+    '''
+    op_class = 'FloatDivOp'
+
+    flag_code = 'FSW = new_fsw;'
+
+class Compfp(Fp2Op):
+    operand_types = (FloatSrc1Op, FloatSrc2Op)
+    # This class sets the condition codes in rflags according to the
+    # rules for comparing floating point.
+    code = '''
+        //               ZF PF CF
+        // Unordered      1  1  1
+        // Greater than   0  0  0
+        // Less than      0  0  1
+        // Equal          1  0  0
+        //           OF = SF = AF = 0
+        ccFlagBits = ccFlagBits & ~(SFBit | AFBit | ZFBit | PFBit);
+        cfofBits = cfofBits & ~(OFBit | CFBit);
+
+        if (std::isnan(FpSrcReg1) || std::isnan(FpSrcReg2)) {
+            ccFlagBits = ccFlagBits | (ZFBit | PFBit);
+            cfofBits = cfofBits | CFBit;
+        }
+        else if(FpSrcReg1 < FpSrcReg2)
+            cfofBits = cfofBits | CFBit;
+        else if(FpSrcReg1 == FpSrcReg2)
+            ccFlagBits = ccFlagBits | ZFBit;
+    '''
+    op_class = 'FloatCmpOp'
+
+class absfp(Fp2Op):
+    code = 'FpDestReg = fabs(FpSrcReg1);'
+    flag_code = 'FSW = FSW & (~CC1Bit);'
+
+class chsfp(Fp2Op):
+    code = 'FpDestReg = (-1) * (FpSrcReg1);'
+    flag_code = 'FSW = FSW & (~CC1Bit);'
+
+class Pop87(Fp0Op):
+    code = ''
+    op_class = 'IntAluOp'
diff --git a/src/arch/x86/ucasmlib/arch/x86/microops/operands.py b/src/arch/x86/ucasmlib/arch/x86/microops/operands.py
new file mode 100644
index 0000000..30d5093
--- /dev/null
+++ b/src/arch/x86/ucasmlib/arch/x86/microops/operands.py
@@ -0,0 +1,189 @@
+# Copyright 2007 The Hewlett-Packard Development Company
+#
+# 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.
+
+#########################################################################
+#
+# Base class for the python representation of x86 microops
+#
+#########################################################################
+
+class Operand(object):
+    @classmethod
+    def isDual(cls):
+        return False
+
+    @classmethod
+    def cxx_class(cls):
+        return 'X86ISA::' + cls.flavor + cls.idx_name + 'Op'
+
+class FlavorlessOperand(Operand):
+    @classmethod
+    def cxx_class(cls):
+        return 'X86ISA::' + cls.op_type
+
+    def __init__(self, it):
+        self.value = next(it)
+
+    def ctor_args(self):
+        return str(self.value)
+
+class UpcOp(FlavorlessOperand):
+    op_type = 'Upc'
+class FaultOp(FlavorlessOperand):
+    op_type = 'Fault'
+class AddrOp(FlavorlessOperand):
+    op_type = 'Addr'
+
+    def __init__(self, it):
+        self.segment = next(it)
+        [self.scale, self.index, self.base] = next(it)
+        self.disp = next(it)
+
+    def ctor_args(self):
+        args = [self.scale, self.index, self.base, self.disp, self.segment]
+        return ', '.join(map(str, args))
+
+class ImmOp(object):
+    idx_name = ''
+
+    def __init__(self, it):
+        self.value = next(it)
+        super().__init__()
+
+    def ctor_args(self):
+        return str(self.value)
+
+class Imm8Op(ImmOp, Operand):
+    flavor = 'Imm8'
+class Imm64Op(ImmOp, Operand):
+    flavor = 'Imm64'
+
+class DestOp(object):
+    idx_name = 'Dest'
+class Src1Op(object):
+    idx_name = 'Src1'
+class Src2Op(object):
+    idx_name = 'Src2'
+
+class RegisterOp(object):
+    def __init__(self, it):
+        self.idx = next(it)
+        super().__init__()
+
+    def ctor_args(self):
+        return str(self.idx)
+
+class FoldedOp(RegisterOp):
+    flavor = 'Folded'
+class DbgOp(RegisterOp):
+    flavor = 'Dbg'
+class CrOp(RegisterOp):
+    flavor = 'Cr'
+class SegOp(RegisterOp):
+    flavor = 'Seg'
+class MiscOp(RegisterOp):
+    flavor = 'Misc'
+class FloatOp(RegisterOp):
+    flavor = 'Float'
+class IntOp(RegisterOp):
+    flavor = 'Int'
+class DataOp(RegisterOp):
+    idx_name = 'Data'
+class DataHiOp(RegisterOp):
+    idx_name = 'DataHi'
+class DataLowOp(RegisterOp):
+    idx_name = 'DataLow'
+
+class FoldedDataOp(FoldedOp, DataOp, Operand):
+    pass
+class FloatDataOp(FloatOp, DataOp, Operand):
+    pass
+class FoldedDataHiOp(FoldedOp, DataHiOp, Operand):
+    pass
+class FoldedDataLowOp(FoldedOp, DataLowOp, Operand):
+    pass
+
+class FoldedDestOp(FoldedOp, DestOp, Operand):
+    pass
+class DbgDestOp(DbgOp, DestOp, Operand):
+    pass
+class CrDestOp(CrOp, DestOp, Operand):
+    pass
+class SegDestOp(SegOp, DestOp, Operand):
+    pass
+class MiscDestOp(MiscOp, DestOp, Operand):
+    pass
+class FloatDestOp(FloatOp, DestOp, Operand):
+    pass
+class IntDestOp(IntOp, DestOp, Operand):
+    pass
+
+class FoldedSrc1Op(FoldedOp, Src1Op, Operand):
+    pass
+class DbgSrc1Op(DbgOp, Src1Op, Operand):
+    pass
+class CrSrc1Op(CrOp, Src1Op, Operand):
+    pass
+class SegSrc1Op(SegOp, Src1Op, Operand):
+    pass
+class MiscSrc1Op(MiscOp, Src1Op, Operand):
+    pass
+class FloatSrc1Op(FloatOp, Src1Op, Operand):
+    pass
+class IntSrc1Op(IntOp, Src1Op, Operand):
+    pass
+
+class FoldedSrc2Op(FoldedOp, Src2Op, Operand):
+    pass
+class DbgSrc2Op(DbgOp, Src2Op, Operand):
+    pass
+class CrSrc2Op(CrOp, Src2Op, Operand):
+    pass
+class SegSrc2Op(SegOp, Src2Op, Operand):
+    pass
+class MiscSrc2Op(MiscOp, Src2Op, Operand):
+    pass
+class FloatSrc2Op(FloatOp, Src2Op, Operand):
+    pass
+class IntSrc2Op(IntOp, Src2Op, Operand):
+    pass
+
+class Op2(object):
+    @classmethod
+    def isDual(cls):
+        return True
+
+    RegType = FoldedSrc2Op
+    FloatType = FloatSrc2Op
+    ImmType = Imm8Op

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/56489
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ib1cd1b7f9048a89a5ef2cbfbb38463c4a1057f55
Gerrit-Change-Number: 56489
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <gabe.bl...@gmail.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to