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