// -*- mode:c++ -*- // Copyright (c) 2010-2011,2017,2019 ARM Limited // All rights reserved // // The license below extends only to copyright in the software and shall // not be construed as granting a license to any other intellectual // property including but not limited to intellectual property relating // to a hardware implementation of the functionality of the software // licensed hereunder. You may use the software subject to the license // terms below provided that you ensure that this notice is replicated // unmodified and in its entirety in all distributions of the software, // modified or unmodified, in source code or in binary form. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer; // redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution; // neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: Gabe Black let {{ import math header_output = "" decoder_output = "" exec_output = "" class StoreInst(LoadStoreInst): execBase = 'Store' def __init__(self, mnem, post, add, writeback, size=4, sign=False, user=False, flavor="normal"): super(StoreInst, self).__init__() self.name = mnem self.post = post self.add = add self.writeback = writeback self.size = size self.sign = sign self.user = user self.flavor = flavor self.instFlags = [] if self.add: self.op = " +" else: self.op = " -" self.memFlags = ["ArmISA::TLB::MustBeOne"] self.codeBlobs = { "postacc_code" : "" } def emitHelper(self, base = 'Memory', wbDecl = None): global header_output, decoder_output, exec_output codeBlobs = self.codeBlobs codeBlobs["predicate_test"] = pickPredicate(codeBlobs) (newHeader, newDecoder, newExec) = self.fillTemplates(self.name, self.Name, codeBlobs, self.memFlags, self.instFlags, base, wbDecl, None, False, self.size, self.sign) header_output += newHeader decoder_output += newDecoder exec_output += newExec class SrsInst(LoadStoreInst): execBase = 'Store' decConstBase = 'Srs' def __init__(self, mnem, post, add, writeback): super(SrsInst, self).__init__() self.name = mnem self.post = post self.add = add self.writeback = writeback self.Name = "SRS_" + storeImmClassName(post, add, writeback, 8) def emit(self): offset = 0 if self.post != self.add: offset += 4 if not self.add: offset -= 8 eaCode = "EA = SpMode + %d;" % offset wbDiff = -8 if self.add: wbDiff = 8 accCode = ''' auto tc = xc->tcBase(); if (badMode32(tc, static_cast(regMode))) { return undefinedFault32(tc, opModeToEL(currOpMode(tc))); } CPSR cpsr = Cpsr; Mem_ud = (uint64_t)cSwap(LR_uw, cpsr.e) | ((uint64_t)cSwap(Spsr_uw, cpsr.e) << 32); ''' global header_output, decoder_output, exec_output codeBlobs = { "ea_code": eaCode, "memacc_code": accCode, "postacc_code": "" } codeBlobs["predicate_test"] = pickPredicate(codeBlobs) wbDecl = None if self.writeback: wbDecl = '''MicroAddiUop(machInst, intRegInMode((OperatingMode)regMode, INTREG_SP), intRegInMode((OperatingMode)regMode, INTREG_SP), %d);''' % wbDiff (newHeader, newDecoder, newExec) = self.fillTemplates(self.name, self.Name, codeBlobs, ["ArmISA::TLB::AlignWord", "ArmISA::TLB::MustBeOne"], [], 'SrsOp', wbDecl) header_output += newHeader decoder_output += newDecoder exec_output += newExec class StoreImmInst(StoreInst): def __init__(self, *args, **kargs): super(StoreImmInst, self).__init__(*args, **kargs) self.offset = self.op + " imm" if self.add: self.wbDecl = "MicroAddiUop(machInst, base, base, imm);" else: self.wbDecl = "MicroSubiUop(machInst, base, base, imm);" class StoreRegInst(StoreInst): def __init__(self, *args, **kargs): super(StoreRegInst, self).__init__(*args, **kargs) self.offset = self.op + " shift_rm_imm(Index, shiftAmt," + \ " shiftType, OptShiftRmCondCodesC)" if self.add: self.wbDecl = ''' MicroAddUop(machInst, base, base, index, shiftAmt, shiftType); ''' else: self.wbDecl = ''' MicroSubUop(machInst, base, base, index, shiftAmt, shiftType); ''' class StoreSingle(StoreInst): def __init__(self, *args, **kargs): super(StoreSingle, self).__init__(*args, **kargs) # Build the default class name self.Name = self.nameFunc(self.post, self.add, self.writeback, self.size, self.sign, self.user) # Add memory request flags where necessary self.memFlags.append("%d" % int(math.log(self.size, 2))) if self.user: self.memFlags.append("ArmISA::TLB::UserMode") if self.flavor in ("exclusive", "relex"): self.instFlags.append("IsStoreConditional") self.memFlags.append("Request::LLSC") elif self.flavor != "fp": self.memFlags.append("ArmISA::TLB::AllowUnaligned") if self.flavor in ("release", "relex"): self.instFlags.extend(["IsMemBarrier", "IsWriteBarrier", "IsReadBarrier"]) # Disambiguate the class name for different flavors of stores if self.flavor != "normal": self.Name = "%s_%s" % (self.name.upper(), self.Name) def emit(self): # Address computation eaCode = "EA = Base" if not self.post: eaCode += self.offset eaCode += ";" if self.flavor == "fp": eaCode += vfpEnabledCheckCode self.codeBlobs["ea_code"] = eaCode # Code that actually handles the access if self.flavor == "fp": accCode = 'Mem%(suffix)s = cSwap(FpDest_uw, ((CPSR)Cpsr).e);' else: accCode = \ 'Mem%(suffix)s = cSwap(Dest%(suffix)s, ((CPSR)Cpsr).e);' accCode = accCode % \ { "suffix" : buildMemSuffix(self.sign, self.size) } self.codeBlobs["memacc_code"] = accCode # Push it out to the output files base = buildMemBase(self.basePrefix, self.post, self.writeback) wbDecl = None if self.writeback: wbDecl = self.wbDecl self.emitHelper(base, wbDecl) def storeImmClassName(post, add, writeback, size=4, sign=False, user=False): return memClassName("STORE_IMM", post, add, writeback, size, sign, user) class StoreImmEx(StoreImmInst, StoreSingle): execBase = 'StoreEx' decConstBase = 'StoreExImm' basePrefix = 'MemoryExImm' nameFunc = staticmethod(storeImmClassName) def __init__(self, *args, **kargs): super(StoreImmEx, self).__init__(*args, **kargs) self.codeBlobs["postacc_code"] = \ "Result = !writeResult; SevMailbox = 1; LLSCLock = 0;" class StoreImm(StoreImmInst, StoreSingle): decConstBase = 'LoadStoreImm' basePrefix = 'MemoryImm' nameFunc = staticmethod(storeImmClassName) def storeRegClassName(post, add, writeback, size=4, sign=False, user=False): return memClassName("STORE_REG", post, add, writeback, size, sign, user) class StoreReg(StoreRegInst, StoreSingle): decConstBase = 'StoreReg' basePrefix = 'MemoryReg' nameFunc = staticmethod(storeRegClassName) class StoreDouble(StoreInst): def __init__(self, *args, **kargs): super(StoreDouble, self).__init__(*args, **kargs) # Build the default class name self.Name = self.nameFunc(self.post, self.add, self.writeback) # Add memory request flags where necessary if self.flavor in ("exclusive", "relex"): self.instFlags.append("IsStoreConditional") self.memFlags.append("Request::LLSC") self.memFlags.append("ArmISA::TLB::AlignDoubleWord") else: self.memFlags.append("ArmISA::TLB::AlignWord") if self.flavor in ("release", "relex"): self.instFlags.extend(["IsMemBarrier", "IsWriteBarrier", "IsReadBarrier"]) # Disambiguate the class name for different flavors of stores if self.flavor != "normal": self.Name = "%s_%s" % (self.name.upper(), self.Name) def emit(self): # Address computation code eaCode = "EA = Base" if not self.post: eaCode += self.offset eaCode += ";" if self.flavor == "fp": eaCode += vfpEnabledCheckCode self.codeBlobs["ea_code"] = eaCode # Code that actually handles the access if self.flavor == "fp": accCode = ''' uint64_t swappedMem = (uint64_t)FpDest_uw | ((uint64_t)FpDest2_uw << 32); Mem_ud = cSwap(swappedMem, ((CPSR)Cpsr).e); ''' else: accCode = ''' CPSR cpsr = Cpsr; Mem_ud = (uint64_t)cSwap(Dest_uw, cpsr.e) | ((uint64_t)cSwap(Dest2_uw, cpsr.e) << 32); ''' self.codeBlobs["memacc_code"] = accCode # Push it out to the output files base = buildMemBase(self.basePrefix, self.post, self.writeback) wbDecl = None if self.writeback: wbDecl = self.wbDecl self.emitHelper(base, wbDecl) def storeDoubleImmClassName(post, add, writeback): return memClassName("STORE_IMMD", post, add, writeback, 4, False, False) class StoreDoubleImmEx(StoreImmInst, StoreDouble): execBase = 'StoreEx' decConstBase = 'StoreExDImm' basePrefix = 'MemoryExDImm' nameFunc = staticmethod(storeDoubleImmClassName) def __init__(self, *args, **kargs): super(StoreDoubleImmEx, self).__init__(*args, **kargs) self.codeBlobs["postacc_code"] = \ "Result = !writeResult; SevMailbox = 1; LLSCLock = 0;" class StoreDoubleImm(StoreImmInst, StoreDouble): decConstBase = 'LoadStoreDImm' basePrefix = 'MemoryDImm' nameFunc = staticmethod(storeDoubleImmClassName) def storeDoubleRegClassName(post, add, writeback): return memClassName("STORE_REGD", post, add, writeback, 4, False, False) class StoreDoubleReg(StoreRegInst, StoreDouble): decConstBase = 'StoreDReg' basePrefix = 'MemoryDReg' nameFunc = staticmethod(storeDoubleRegClassName) def buildStores(mnem, size=4, sign=False, user=False): StoreImm(mnem, True, True, True, size, sign, user).emit() StoreReg(mnem, True, True, True, size, sign, user).emit() StoreImm(mnem, True, False, True, size, sign, user).emit() StoreReg(mnem, True, False, True, size, sign, user).emit() StoreImm(mnem, False, True, True, size, sign, user).emit() StoreReg(mnem, False, True, True, size, sign, user).emit() StoreImm(mnem, False, False, True, size, sign, user).emit() StoreReg(mnem, False, False, True, size, sign, user).emit() StoreImm(mnem, False, True, False, size, sign, user).emit() StoreReg(mnem, False, True, False, size, sign, user).emit() StoreImm(mnem, False, False, False, size, sign, user).emit() StoreReg(mnem, False, False, False, size, sign, user).emit() def buildDoubleStores(mnem): StoreDoubleImm(mnem, True, True, True).emit() StoreDoubleReg(mnem, True, True, True).emit() StoreDoubleImm(mnem, True, False, True).emit() StoreDoubleReg(mnem, True, False, True).emit() StoreDoubleImm(mnem, False, True, True).emit() StoreDoubleReg(mnem, False, True, True).emit() StoreDoubleImm(mnem, False, False, True).emit() StoreDoubleReg(mnem, False, False, True).emit() StoreDoubleImm(mnem, False, True, False).emit() StoreDoubleReg(mnem, False, True, False).emit() StoreDoubleImm(mnem, False, False, False).emit() StoreDoubleReg(mnem, False, False, False).emit() def buildSrsStores(mnem): SrsInst(mnem, True, True, True).emit() SrsInst(mnem, True, True, False).emit() SrsInst(mnem, True, False, True).emit() SrsInst(mnem, True, False, False).emit() SrsInst(mnem, False, True, True).emit() SrsInst(mnem, False, True, False).emit() SrsInst(mnem, False, False, True).emit() SrsInst(mnem, False, False, False).emit() buildStores("str") buildStores("strt", user=True) buildStores("strb", size=1) buildStores("strbt", size=1, user=True) buildStores("strh", size=2) buildStores("strht", size=2, user=True) buildSrsStores("srs") buildDoubleStores("strd") StoreImmEx("strex", False, True, False, size=4, flavor="exclusive").emit() StoreImmEx("strexh", False, True, False, size=2, flavor="exclusive").emit() StoreImmEx("strexb", False, True, False, size=1, flavor="exclusive").emit() StoreDoubleImmEx("strexd", False, True, False, flavor="exclusive").emit() StoreImm("stl", False, True, False, size=4, flavor="release").emit() StoreImm("stlh", False, True, False, size=2, flavor="release").emit() StoreImm("stlb", False, True, False, size=1, flavor="release").emit() StoreImmEx("stlex", False, True, False, size=4, flavor="relex").emit() StoreImmEx("stlexh", False, True, False, size=2, flavor="relex").emit() StoreImmEx("stlexb", False, True, False, size=1, flavor="relex").emit() StoreDoubleImmEx("stlexd", False, True, False, flavor="relex").emit() StoreImm("vstr", False, True, False, size=4, flavor="fp").emit() StoreImm("vstr", False, False, False, size=4, flavor="fp").emit() StoreDoubleImm("vstr", False, True, False, flavor="fp").emit() StoreDoubleImm("vstr", False, False, False, flavor="fp").emit() }};