| // Copyright (c) 2007-2008 The Hewlett-Packard Development Company |
| // Copyright (c) 2015 Advanced Micro Devices, Inc. |
| // All rights reserved. |
| // |
| // The license below extends only to copyright in the software and shall |
| // not be construed as granting a license to any other intellectual |
| // property including but not limited to intellectual property relating |
| // to a hardware implementation of the functionality of the software |
| // licensed hereunder. You may use the software subject to the license |
| // terms below provided that you ensure that this notice is replicated |
| // unmodified and in its entirety in all distributions of the software, |
| // modified or unmodified, in source code or in binary form. |
| // |
| // Copyright (c) 2007 The Regents of The University of Michigan |
| // Copyright (c) 2012 Mark D. Hill and David A. Wood |
| // Copyright (c) 2012-2013 Advanced Micro Devices, Inc. |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer; |
| // redistributions in binary form must reproduce the above copyright |
| // notice, this list of conditions and the following disclaimer in the |
| // documentation and/or other materials provided with the distribution; |
| // neither the name of the copyright holders nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| def operand_types {{ |
| 'sb' : 'int8_t', |
| 'ub' : 'uint8_t', |
| 'sw' : 'int16_t', |
| 'uw' : 'uint16_t', |
| 'sdw' : 'int32_t', |
| 'udw' : 'uint32_t', |
| 'sqw' : 'int64_t', |
| 'uqw' : 'uint64_t', |
| 'u2qw' : 'std::array<uint64_t, 2>', |
| 'sf' : 'float', |
| 'df' : 'double', |
| }}; |
| |
| let {{ |
| class IntReg(IntRegOp): |
| @overrideInOperand |
| def regId(self): |
| return f'(({self.reg_spec}) == gem5::X86ISA::int_reg::T0) ? ' \ |
| f'RegId() : {self.reg_class}[{self.reg_spec}]' |
| def __init__(self, idx, id, data_size='dataSize', *args, **kwargs): |
| super().__init__('uqw', idx, 'IsInteger', id, *args, **kwargs) |
| self.attrs['data_size'] = data_size |
| |
| class PickedReg(IntReg): |
| @overrideInOperand |
| def makeRead(self): |
| return f'{self.base_name} = pick(xc->getRegOperand(' \ |
| f'this, {self.src_reg_idx}), {self.reg_spec}, ' \ |
| f'{self.data_size});\n' |
| |
| def __init__(self, idx, id, data_size='dataSize'): |
| super().__init__(idx, id, data_size) |
| |
| class SignedPickedReg(IntReg): |
| @overrideInOperand |
| def makeRead(self): |
| return f'{self.base_name} = signedPick(xc->getRegOperand(' \ |
| f'this, {self.src_reg_idx}), {self.reg_spec}, ' \ |
| f'{self.data_size});\n' |
| |
| def __init__(self, idx, id, data_size='dataSize'): |
| super().__init__(idx, id, data_size) |
| |
| class FloatReg(FloatRegOp): |
| def __init__(self, idx, id): |
| super().__init__('df', idx, 'IsFloating', id) |
| |
| class CCReg(CCRegOp): |
| def __init__(self, idx, id): |
| super().__init__('uqw', idx, None, id) |
| |
| class CCRegPred(CCRegOp): |
| @overrideInOperand |
| def srcRegId(self): |
| return f'({self.readPredicate}) ? {self.regId()} : RegId()' |
| @overrideInOperand |
| def destRegId(self): |
| return f'({self.writePredicate}) ? {self.regId()} : RegId()' |
| def __init__(self, idx, id, *, read_predicate, write_predicate): |
| super().__init__('uqw', idx, None, id) |
| self.attrs['readPredicate'] = read_predicate |
| self.attrs['writePredicate'] = write_predicate |
| |
| class ControlReg(ControlRegOp): |
| def __init__(self, idx, id, ctype='uqw'): |
| super().__init__(ctype, idx, |
| (None, None, ['IsSerializeAfter', |
| 'IsSerializing', |
| 'IsNonSpeculative']), |
| id) |
| |
| class SquashCheckReg(ControlRegOp): |
| def __init__(self, idx, id, check, ctype='uqw'): |
| super().__init__(ctype, idx, |
| (None, None, |
| [f'(({check}) ? IsSquashAfter : IsSerializeAfter)', |
| 'IsSerializing', 'IsNonSpeculative']), |
| id) |
| |
| class SquashCReg(SquashCheckReg): |
| def __init__(self, idx, id, ctype='uqw'): |
| super().__init__(idx, id, 'true', ctype) |
| |
| class SquashCSReg(SquashCheckReg): |
| def __init__(self, idx, id, ctype='uqw'): |
| super().__init__(idx, id, 'dest == X86ISA::segment_idx::Cs', ctype) |
| |
| class SquashCR0Reg(SquashCheckReg): |
| def __init__(self, idx, id, ctype='uqw'): |
| super().__init__(idx, id, 'dest == 0', ctype) |
| }}; |
| |
| def operands {{ |
| 'SrcReg1': IntReg('src1', 1), |
| 'PSrcReg1': PickedReg('src1', 1), |
| 'PMSrcReg1': PickedReg('src1', 1, 'srcSize'), |
| 'SPSrcReg1': SignedPickedReg('src1', 1), |
| 'SrcReg2': IntReg('src2', 2), |
| 'PSrcReg2': PickedReg('src2', 2), |
| 'SPSrcReg2': SignedPickedReg('src2', 2), |
| 'Index': IntReg('index', 3), |
| 'Base': IntReg('base', 4), |
| 'DestReg': IntReg('dest', 5), |
| 'Data': IntReg('data', 6), |
| 'PData': PickedReg('data', 6), |
| 'DataLow': IntReg('dataLow', 6), |
| 'DataHi': IntReg('dataHi', 6), |
| 'ProdLow': IntReg('X86ISA::int_reg::Prodlow', 7), |
| 'ProdHi': IntReg('X86ISA::int_reg::Prodhi', 8), |
| 'Quotient': IntReg('X86ISA::int_reg::Quotient', 9), |
| 'Remainder': IntReg('X86ISA::int_reg::Remainder', 10), |
| 'Divisor': IntReg('X86ISA::int_reg::Divisor', 11), |
| 'DoubleBits': IntReg('X86ISA::int_reg::Doublebits', 11), |
| 'Rax': IntReg('X86ISA::int_reg::Rax', 12), |
| 'Rbx': IntReg('X86ISA::int_reg::Rbx', 13), |
| 'Rcx': IntReg('X86ISA::int_reg::Rcx', 14), |
| 'Rdx': IntReg('X86ISA::int_reg::Rdx', 15), |
| 'Rsp': IntReg('X86ISA::int_reg::Rsp', 16), |
| 'Rbp': IntReg('X86ISA::int_reg::Rbp', 17), |
| 'Rsi': IntReg('X86ISA::int_reg::Rsi', 18), |
| 'Rdi': IntReg('X86ISA::int_reg::Rdi', 19), |
| 'R8': IntReg('X86ISA::int_reg::R8', 20), |
| 'R9': IntReg('X86ISA::int_reg::R9', 21), |
| 'FpSrcReg1': FloatReg('src1', 22), |
| 'FpSrcReg2': FloatReg('src2', 23), |
| 'FpDestReg': FloatReg('dest', 24), |
| 'FpData': FloatReg('data', 25), |
| 'RIP': PCStateOp('uqw', 'pc', |
| (None, None, 'IsControl'), 50), |
| 'NRIP': PCStateOp('uqw', 'npc', |
| (None, None, 'IsControl'), 50), |
| 'nuIP': PCStateOp('uqw', 'nupc', |
| (None, None, 'IsControl'), 50), |
| # These registers hold the condition code portion of the flag |
| # register. The nccFlagBits version holds the rest. |
| 'ccFlagBits': CCReg('X86ISA::cc_reg::Zaps', 60), |
| 'cfofBits': CCReg('X86ISA::cc_reg::Cfof', 61), |
| 'dfBit': CCReg('X86ISA::cc_reg::Df', 62), |
| 'ecfBit': CCReg('X86ISA::cc_reg::Ecf', 63), |
| 'ezfBit': CCReg('X86ISA::cc_reg::Ezf', 64), |
| |
| # These Pred registers are to be used where reading the portions of |
| # condition code registers is possibly optional, depending on how the |
| # check evaluates. There are two checks being specified, one tests if |
| # a register needs to be read, the other tests whether the register |
| # needs to be written to. It is unlikely that these would need to be |
| # used in the actual operation of the instruction. It is expected |
| # that these are used only in the flag code. |
| |
| # Rationale behind the checks: at times, we need to partially update |
| # the condition code bits in a register. So we read the register even |
| # in the case when the all the bits will be written, or none of the |
| # bits will be written. The read predicate checks if any of the bits |
| # would be retained, the write predicate checks if any of the bits |
| # are being written. |
| |
| 'PredccFlagBits': CCRegPred('X86ISA::cc_reg::Zaps', 60, |
| read_predicate='(ext & X86ISA::CcFlagMask) != ' |
| 'X86ISA::CcFlagMask && (ext & X86ISA::CcFlagMask) != 0', |
| write_predicate='(ext & X86ISA::CcFlagMask) != 0'), |
| 'PredcfofBits': CCRegPred('X86ISA::cc_reg::Cfof', 61, |
| read_predicate='(ext & X86ISA::CfofMask) ' |
| '!= X86ISA::CfofMask && (ext & X86ISA::CfofMask) != 0', |
| write_predicate='(ext & X86ISA::CfofMask) != 0'), |
| 'PreddfBit': CCRegPred('X86ISA::cc_reg::Df', 62, |
| read_predicate='false', |
| write_predicate='(ext & X86ISA::DFBit) != 0'), |
| 'PredecfBit': CCRegPred('X86ISA::cc_reg::Ecf', 63, |
| read_predicate='false', |
| write_predicate='(ext & X86ISA::ECFBit) != 0'), |
| 'PredezfBit': CCRegPred('X86ISA::cc_reg::Ezf', 64, |
| read_predicate='false', |
| write_predicate='(ext & X86ISA::EZFBit) != 0'), |
| |
| # These register should needs to be more protected so that later |
| # instructions don't map their indexes with an old value. |
| 'nccFlagBits': ControlReg('X86ISA::misc_reg::Rflags', 65), |
| |
| # Registers related to the state of x87 floating point unit. |
| 'TOP': ControlReg('X86ISA::misc_reg::X87Top', 66, |
| ctype='ub'), |
| 'FSW': ControlReg('X86ISA::misc_reg::Fsw', 67, ctype='uw'), |
| 'FTW': ControlReg('X86ISA::misc_reg::Ftw', 68, ctype='uw'), |
| 'FCW': ControlReg('X86ISA::misc_reg::Fcw', 69, ctype='uw'), |
| |
| # The segment base as used by memory instructions. |
| 'SegBase': ControlReg('X86ISA::misc_reg::segEffBase(segment)', |
| 70), |
| |
| # Operands to get and set registers indexed by the operands of the |
| # original instruction. |
| 'ControlDest': SquashCR0Reg('X86ISA::misc_reg::cr(dest)', 100), |
| 'ControlSrc1': ControlReg('X86ISA::misc_reg::cr(src1)', 101), |
| 'DebugDest': ControlReg('X86ISA::misc_reg::dr(dest)', 102), |
| 'DebugSrc1': ControlReg('X86ISA::misc_reg::dr(src1)', 103), |
| 'SegBaseDest': SquashCSReg('X86ISA::misc_reg::segBase(dest)', 104), |
| 'SegBaseSrc1': ControlReg('X86ISA::misc_reg::segBase(src1)', 105), |
| 'SegLimitDest': SquashCSReg('X86ISA::misc_reg::segLimit(dest)', 106), |
| 'SegLimitSrc1': ControlReg('X86ISA::misc_reg::segLimit(src1)', 107), |
| 'SegSelDest': ControlReg('X86ISA::misc_reg::segSel(dest)', 108), |
| 'SegSelSrc1': ControlReg('X86ISA::misc_reg::segSel(src1)', 109), |
| 'SegAttrDest': SquashCSReg('X86ISA::misc_reg::segAttr(dest)', 110), |
| 'SegAttrSrc1': ControlReg('X86ISA::misc_reg::segAttr(src1)', 111), |
| |
| # Operands to access specific control registers directly. |
| 'EferOp': SquashCReg('X86ISA::misc_reg::Efer', 200), |
| 'CR4Op': ControlReg('X86ISA::misc_reg::Cr4', 201), |
| 'DR7Op': ControlReg('X86ISA::misc_reg::Dr7', 202), |
| 'LDTRBase': ControlReg('X86ISA::misc_reg::TslBase', 203), |
| 'LDTRLimit': ControlReg('X86ISA::misc_reg::TslLimit', 204), |
| 'LDTRSel': ControlReg('X86ISA::misc_reg::Tsl', 205), |
| 'GDTRBase': ControlReg('X86ISA::misc_reg::TsgBase', 206), |
| 'GDTRLimit': ControlReg('X86ISA::misc_reg::TsgLimit', 207), |
| 'CSBase': SquashCReg('X86ISA::misc_reg::CsEffBase', 208), |
| 'CSAttr': SquashCReg('X86ISA::misc_reg::CsAttr', 209), |
| 'MiscRegDest': ControlReg('dest', 210), |
| 'MiscRegSrc1': ControlReg('src1', 211), |
| 'TscOp': ControlReg('X86ISA::misc_reg::Tsc', 212), |
| 'M5Reg': SquashCReg('X86ISA::misc_reg::M5Reg', 213), |
| 'Mem': MemOp('uqw', None, (None, 'IsLoad', 'IsStore'), 300) |
| }}; |