blob: 1583ef00ff7f970c1ef665ac6e54a8327ab96abd [file] [log] [blame]
// -*- mode:c++ -*-
// Copyright (c) 2010-2011,2017,2019-2020 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.
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().__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 = []
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().__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<OperatingMode>(regMode))) {
return undefinedFault32(tc, currEL(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,
int_reg::regInMode((OperatingMode)regMode,
int_reg::Sp),
int_reg::regInMode((OperatingMode)regMode,
int_reg::Sp),
%d);''' % wbDiff
(newHeader,
newDecoder,
newExec) = self.fillTemplates(self.name, self.Name, codeBlobs,
["ArmISA::MMU::AlignWord"], [], 'SrsOp', wbDecl)
header_output += newHeader
decoder_output += newDecoder
exec_output += newExec
class StoreImmInst(StoreInst):
def __init__(self, *args, **kargs):
super().__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().__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().__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::MMU::UserMode")
if self.flavor in ("exclusive", "relex"):
self.instFlags.append("IsStoreConditional")
self.memFlags.append("Request::LLSC")
elif self.flavor != "fp":
self.memFlags.append("ArmISA::MMU::AllowUnaligned")
if self.flavor in ("release", "relex"):
self.instFlags.extend(["IsWriteBarrier",
"IsReadBarrier"])
self.memFlags.append("Request::RELEASE")
# 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().__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().__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::MMU::AlignDoubleWord")
else:
self.memFlags.append("ArmISA::MMU::AlignWord")
if self.flavor in ("release", "relex"):
self.instFlags.extend(["IsWriteBarrier",
"IsReadBarrier"])
self.memFlags.append("Request::RELEASE")
# 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().__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()
}};