amo64.isa revision 14150
114150Sjordi.vaquero@metempsy.com// -*- mode:c++ -*-
214150Sjordi.vaquero@metempsy.com
314150Sjordi.vaquero@metempsy.com// Copyright (c) 2018 Metempsy Technology Consulting
414150Sjordi.vaquero@metempsy.com// All rights reserved
514150Sjordi.vaquero@metempsy.com//
614150Sjordi.vaquero@metempsy.com// The license below extends only to copyright in the software and shall
714150Sjordi.vaquero@metempsy.com// not be construed as granting a license to any other intellectual
814150Sjordi.vaquero@metempsy.com// property including but not limited to intellectual property relating
914150Sjordi.vaquero@metempsy.com// to a hardware implementation of the functionality of the software
1014150Sjordi.vaquero@metempsy.com// licensed hereunder.  You may use the software subject to the license
1114150Sjordi.vaquero@metempsy.com// terms below provided that you ensure that this notice is replicated
1214150Sjordi.vaquero@metempsy.com// unmodified and in its entirety in all distributions of the software,
1314150Sjordi.vaquero@metempsy.com// modified or unmodified, in source code or in binary form.
1414150Sjordi.vaquero@metempsy.com//
1514150Sjordi.vaquero@metempsy.com// Redistribution and use in source and binary forms, with or without
1614150Sjordi.vaquero@metempsy.com// modification, are permitted provided that the following conditions are
1714150Sjordi.vaquero@metempsy.com// met: redistributions of source code must retain the above copyright
1814150Sjordi.vaquero@metempsy.com// notice, this list of conditions and the following disclaimer;
1914150Sjordi.vaquero@metempsy.com// redistributions in binary form must reproduce the above copyright
2014150Sjordi.vaquero@metempsy.com// notice, this list of conditions and the following disclaimer in the
2114150Sjordi.vaquero@metempsy.com// documentation and/or other materials provided with the distribution;
2214150Sjordi.vaquero@metempsy.com// neither the name of the copyright holders nor the names of its
2314150Sjordi.vaquero@metempsy.com// contributors may be used to endorse or promote products derived from
2414150Sjordi.vaquero@metempsy.com// this software without specific prior written permission.
2514150Sjordi.vaquero@metempsy.com//
2614150Sjordi.vaquero@metempsy.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2714150Sjordi.vaquero@metempsy.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2814150Sjordi.vaquero@metempsy.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2914150Sjordi.vaquero@metempsy.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3014150Sjordi.vaquero@metempsy.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3114150Sjordi.vaquero@metempsy.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3214150Sjordi.vaquero@metempsy.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3314150Sjordi.vaquero@metempsy.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3414150Sjordi.vaquero@metempsy.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3514150Sjordi.vaquero@metempsy.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3614150Sjordi.vaquero@metempsy.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3714150Sjordi.vaquero@metempsy.com//
3814150Sjordi.vaquero@metempsy.com// Authors: Jordi Vaquero
3914150Sjordi.vaquero@metempsy.com
4014150Sjordi.vaquero@metempsy.comlet {{
4114150Sjordi.vaquero@metempsy.com
4214150Sjordi.vaquero@metempsy.com    import math
4314150Sjordi.vaquero@metempsy.com
4414150Sjordi.vaquero@metempsy.com    OP_DICT = { "CAS" : 'if (a == *b){*b = c;}',
4514150Sjordi.vaquero@metempsy.com                "SWP" : '*b = c;',
4614150Sjordi.vaquero@metempsy.com                "ADD" : '*b += c;',
4714150Sjordi.vaquero@metempsy.com                "EOR" : '*b ^= c;',
4814150Sjordi.vaquero@metempsy.com                "CLR" : '*b &= ~c;',
4914150Sjordi.vaquero@metempsy.com                "SET" : '*b |= c;',
5014150Sjordi.vaquero@metempsy.com                "MAX" : '*b = std::max(*b, c);',
5114150Sjordi.vaquero@metempsy.com                "MIN" : '*b = std::min(*b, c);', }
5214150Sjordi.vaquero@metempsy.com
5314150Sjordi.vaquero@metempsy.com    MASKS = { 1: 0xFF,
5414150Sjordi.vaquero@metempsy.com              2: 0xFFFF,
5514150Sjordi.vaquero@metempsy.com              4: 0xFFFFFFFF,
5614150Sjordi.vaquero@metempsy.com              8: 0xFFFFFFFFFFFFFFFF,
5714150Sjordi.vaquero@metempsy.com             }
5814150Sjordi.vaquero@metempsy.com
5914150Sjordi.vaquero@metempsy.com    header_output = ""
6014150Sjordi.vaquero@metempsy.com    decoder_output = ""
6114150Sjordi.vaquero@metempsy.com    exec_output = ""
6214150Sjordi.vaquero@metempsy.com
6314150Sjordi.vaquero@metempsy.com    class AtomicInst64(LoadStoreInst):
6414150Sjordi.vaquero@metempsy.com        execBase = 'AtomicInst64'
6514150Sjordi.vaquero@metempsy.com        micro = False
6614150Sjordi.vaquero@metempsy.com
6714150Sjordi.vaquero@metempsy.com        def __init__(self, mnem, Name, size=4, user=False, flavor="normal",
6814150Sjordi.vaquero@metempsy.com                    unsign=True, top = False, paired=False):
6914150Sjordi.vaquero@metempsy.com            super(AtomicInst64, self).__init__()
7014150Sjordi.vaquero@metempsy.com
7114150Sjordi.vaquero@metempsy.com            self.name= mnem
7214150Sjordi.vaquero@metempsy.com            self.Name = Name
7314150Sjordi.vaquero@metempsy.com            self.size = size
7414150Sjordi.vaquero@metempsy.com            self.user = user
7514150Sjordi.vaquero@metempsy.com            self.flavor = flavor
7614150Sjordi.vaquero@metempsy.com            self.unsign = unsign
7714150Sjordi.vaquero@metempsy.com            self.top = top
7814150Sjordi.vaquero@metempsy.com            self.paired = paired
7914150Sjordi.vaquero@metempsy.com
8014150Sjordi.vaquero@metempsy.com            self.memFlags = ["ArmISA::TLB::MustBeOne"]
8114150Sjordi.vaquero@metempsy.com            self.instFlags = ["IsAtomic"]
8214150Sjordi.vaquero@metempsy.com            self.codeBlobs = { "postacc_code" : "" }
8314150Sjordi.vaquero@metempsy.com            self.codeBlobs['usrDecl'] = ""
8414150Sjordi.vaquero@metempsy.com
8514150Sjordi.vaquero@metempsy.com            # Add memory request flags where necessary
8614150Sjordi.vaquero@metempsy.com            if self.user:
8714150Sjordi.vaquero@metempsy.com                self.memFlags.append("ArmISA::TLB::UserMode")
8814150Sjordi.vaquero@metempsy.com
8914150Sjordi.vaquero@metempsy.com            sz = self.size*2 if paired else self.size
9014150Sjordi.vaquero@metempsy.com            self.memFlags.append("%d" % int(math.log(sz, 2)))
9114150Sjordi.vaquero@metempsy.com
9214150Sjordi.vaquero@metempsy.com            if self.micro:
9314150Sjordi.vaquero@metempsy.com                self.instFlags.append("IsMicroop")
9414150Sjordi.vaquero@metempsy.com
9514150Sjordi.vaquero@metempsy.com            if self.flavor in ("release", "acquire_release", "acquire"):
9614150Sjordi.vaquero@metempsy.com                self.instFlags.append("IsMemBarrier")
9714150Sjordi.vaquero@metempsy.com            if self.flavor in ("release", "acquire_release"):
9814150Sjordi.vaquero@metempsy.com                self.instFlags.append("IsWriteBarrier")
9914150Sjordi.vaquero@metempsy.com            if self.flavor in ("acquire_release", "acquire"):
10014150Sjordi.vaquero@metempsy.com                self.instFlags.append("IsReadBarrier")
10114150Sjordi.vaquero@metempsy.com            self.memFlags.append('Request::ATOMIC_RETURN_OP')
10214150Sjordi.vaquero@metempsy.com
10314150Sjordi.vaquero@metempsy.com        def emitHelper(self, base = 'Memory64', wbDecl = None, ):
10414150Sjordi.vaquero@metempsy.com            global header_output, decoder_output, exec_output
10514150Sjordi.vaquero@metempsy.com
10614150Sjordi.vaquero@metempsy.com            # If this is a microop itself, don't allow anything that would
10714150Sjordi.vaquero@metempsy.com            # require further microcoding.
10814150Sjordi.vaquero@metempsy.com            if self.micro:
10914150Sjordi.vaquero@metempsy.com                assert not wbDecl
11014150Sjordi.vaquero@metempsy.com
11114150Sjordi.vaquero@metempsy.com            fa_code = None
11214150Sjordi.vaquero@metempsy.com            if not self.micro :
11314150Sjordi.vaquero@metempsy.com            #and self.flavor in ("normal", "release"):
11414150Sjordi.vaquero@metempsy.com                fa_code = '''
11514150Sjordi.vaquero@metempsy.com                    fault->annotate(ArmFault::SAS, %s);
11614150Sjordi.vaquero@metempsy.com                    fault->annotate(ArmFault::SSE, false);
11714150Sjordi.vaquero@metempsy.com                    fault->annotate(ArmFault::SRT, dest);
11814150Sjordi.vaquero@metempsy.com                    fault->annotate(ArmFault::SF, %s);
11914150Sjordi.vaquero@metempsy.com                    fault->annotate(ArmFault::AR, %s);
12014150Sjordi.vaquero@metempsy.com                ''' % ("0" if self.size == 1 else
12114150Sjordi.vaquero@metempsy.com                       "1" if self.size == 2 else
12214150Sjordi.vaquero@metempsy.com                       "2" if self.size == 4 else "3",
12314150Sjordi.vaquero@metempsy.com                       "true" if self.size == 8 else "false",
12414150Sjordi.vaquero@metempsy.com                       "true" if self.flavor != "normal"  else "false")
12514150Sjordi.vaquero@metempsy.com            sas_code = "3"
12614150Sjordi.vaquero@metempsy.com            if self.size == 1 :
12714150Sjordi.vaquero@metempsy.com                sas_code = "0"
12814150Sjordi.vaquero@metempsy.com            elif self.size == 2:
12914150Sjordi.vaquero@metempsy.com                sas_code = "1"
13014150Sjordi.vaquero@metempsy.com            elif self.size == 4:
13114150Sjordi.vaquero@metempsy.com                sas_code = "2"
13214150Sjordi.vaquero@metempsy.com
13314150Sjordi.vaquero@metempsy.com            if self.paired and sas_code == "3":
13414150Sjordi.vaquero@metempsy.com                sas_code = "4"
13514150Sjordi.vaquero@metempsy.com            if self.paired and sas_code == "2":
13614150Sjordi.vaquero@metempsy.com                sas_code = "3"
13714150Sjordi.vaquero@metempsy.com
13814150Sjordi.vaquero@metempsy.com
13914150Sjordi.vaquero@metempsy.com            fa_code = '''
14014150Sjordi.vaquero@metempsy.com               fault->annotate(ArmFault::SAS, %s);
14114150Sjordi.vaquero@metempsy.com               fault->annotate(ArmFault::SSE, %s);
14214150Sjordi.vaquero@metempsy.com               fault->annotate(ArmFault::SRT, dest);
14314150Sjordi.vaquero@metempsy.com               fault->annotate(ArmFault::SF, %s);
14414150Sjordi.vaquero@metempsy.com               fault->annotate(ArmFault::AR, %s);
14514150Sjordi.vaquero@metempsy.com               ''' % (sas_code,
14614150Sjordi.vaquero@metempsy.com                     "true" if not self.unsign else "false",
14714150Sjordi.vaquero@metempsy.com                     "true" if self.size == 8 else "false",
14814150Sjordi.vaquero@metempsy.com                     "true" if self.flavor != "normal"  else "false")
14914150Sjordi.vaquero@metempsy.com
15014150Sjordi.vaquero@metempsy.com            (newHeader, newDecoder, newExec) = \
15114150Sjordi.vaquero@metempsy.com                self.fillTemplates(self.name, self.Name, self.codeBlobs,
15214150Sjordi.vaquero@metempsy.com                                   self.memFlags, self.instFlags,
15314150Sjordi.vaquero@metempsy.com                                   base, wbDecl, faCode=fa_code)
15414150Sjordi.vaquero@metempsy.com
15514150Sjordi.vaquero@metempsy.com            header_output += newHeader
15614150Sjordi.vaquero@metempsy.com            decoder_output += newDecoder
15714150Sjordi.vaquero@metempsy.com            exec_output += newExec
15814150Sjordi.vaquero@metempsy.com
15914150Sjordi.vaquero@metempsy.com        def buildEACode(self):
16014150Sjordi.vaquero@metempsy.com            # Address computation
16114150Sjordi.vaquero@metempsy.com            eaCode = SPAlignmentCheckCode + "EA = XBase"
16214150Sjordi.vaquero@metempsy.com            if self.size == 16:
16314150Sjordi.vaquero@metempsy.com                if self.top:
16414150Sjordi.vaquero@metempsy.com                    eaCode += " + (isBigEndian64(xc->tcBase()) ? 0 : 8)"
16514150Sjordi.vaquero@metempsy.com                else:
16614150Sjordi.vaquero@metempsy.com                    eaCode += " + (isBigEndian64(xc->tcBase()) ? 8 : 0)"
16714150Sjordi.vaquero@metempsy.com            if not self.post:
16814150Sjordi.vaquero@metempsy.com                eaCode += self.offset
16914150Sjordi.vaquero@metempsy.com            eaCode += ";"
17014150Sjordi.vaquero@metempsy.com            self.codeBlobs["ea_code"] = eaCode
17114150Sjordi.vaquero@metempsy.com
17214150Sjordi.vaquero@metempsy.com
17314150Sjordi.vaquero@metempsy.com    class AtomicSingleOp(AtomicInst64):
17414150Sjordi.vaquero@metempsy.com        decConstBase = 'AmoOp'
17514150Sjordi.vaquero@metempsy.com        base = 'ArmISA::MemoryEx64'
17614150Sjordi.vaquero@metempsy.com        writeback = True
17714150Sjordi.vaquero@metempsy.com        post = False
17814150Sjordi.vaquero@metempsy.com        execBase = 'AmoOp'
17914150Sjordi.vaquero@metempsy.com
18014150Sjordi.vaquero@metempsy.com        def __init__(self, *args, **kargs):
18114150Sjordi.vaquero@metempsy.com            super(AtomicSingleOp, self).__init__(*args, **kargs)
18214150Sjordi.vaquero@metempsy.com            self.suffix = buildMemSuffix(not self.unsign, self.size)
18314150Sjordi.vaquero@metempsy.com            if self.size == 8:
18414150Sjordi.vaquero@metempsy.com                self.res = 'XResult_ud' #if self.unsign else 'XResult_sd'
18514150Sjordi.vaquero@metempsy.com                self.des = 'XDest_ud' #if self.unsign else 'XDest_sd'
18614150Sjordi.vaquero@metempsy.com                self.tp = 'uint64_t' if self.unsign else 'int64_t'
18714150Sjordi.vaquero@metempsy.com                self.utp = 'uint64_t'
18814150Sjordi.vaquero@metempsy.com                self.suffix = '_sd' if not self.unsign else '_ud'
18914150Sjordi.vaquero@metempsy.com            elif self.size == 4:
19014150Sjordi.vaquero@metempsy.com                self.res = 'XResult_uw' #if self.unsign else 'XResult_sw'
19114150Sjordi.vaquero@metempsy.com                self.des = 'XDest_uw' #if self.unsign else 'XDest_sw'
19214150Sjordi.vaquero@metempsy.com                self.tp = 'uint32_t' if self.unsign else 'int32_t'
19314150Sjordi.vaquero@metempsy.com                self.utp = 'uint32_t'
19414150Sjordi.vaquero@metempsy.com            elif self.size == 2:
19514150Sjordi.vaquero@metempsy.com                self.res = 'XResult_uh' #if self.unsign else 'XResult_sh'
19614150Sjordi.vaquero@metempsy.com                self.des = 'XDest_uh' #if self.unsign else 'XDest_sh'
19714150Sjordi.vaquero@metempsy.com                self.tp = 'uint16_t' if self.unsign else 'int16_t'
19814150Sjordi.vaquero@metempsy.com                self.utp = 'uint16_t'
19914150Sjordi.vaquero@metempsy.com            elif self.size == 1:
20014150Sjordi.vaquero@metempsy.com                self.res = 'XResult_ub' #if self.unsign else 'XResult_sb'
20114150Sjordi.vaquero@metempsy.com                self.des = 'XDest_ub' #if self.unsign else 'XDest_sb'
20214150Sjordi.vaquero@metempsy.com                self.tp = 'uint8_t' if self.unsign else 'int8_t'
20314150Sjordi.vaquero@metempsy.com                self.utp = 'uint8_t'
20414150Sjordi.vaquero@metempsy.com            self.offset = ""
20514150Sjordi.vaquero@metempsy.com            store_res = '''
20614150Sjordi.vaquero@metempsy.com                        %(result)s = cSwap(Mem%(suffix)s,
20714150Sjordi.vaquero@metempsy.com                                         isBigEndian64(xc->tcBase()));
20814150Sjordi.vaquero@metempsy.com                      '''
20914150Sjordi.vaquero@metempsy.com            store_res = store_res % {"result":self.res, "suffix":self.suffix}
21014150Sjordi.vaquero@metempsy.com            self.codeBlobs["postacc_code"] = \
21114150Sjordi.vaquero@metempsy.com                    store_res + " SevMailbox = 1; LLSCLock = 0;"
21214150Sjordi.vaquero@metempsy.com
21314150Sjordi.vaquero@metempsy.com        def emit(self, op):
21414150Sjordi.vaquero@metempsy.com            self.buildEACode()
21514150Sjordi.vaquero@metempsy.com            usrDecl = "%(type)s valRs;\n" % {'type': self.tp}
21614150Sjordi.vaquero@metempsy.com            self.codeBlobs['usrDecl'] = usrDecl
21714150Sjordi.vaquero@metempsy.com
21814150Sjordi.vaquero@metempsy.com            opcode = "valRs = cSwap(%(dest)s,"\
21914150Sjordi.vaquero@metempsy.com                      " isBigEndian64(xc->tcBase()));\n"
22014150Sjordi.vaquero@metempsy.com            opcode += "TypedAtomicOpFunctor<%(type)s> *amo_op = "\
22114150Sjordi.vaquero@metempsy.com                      "new AtomicGeneric3Op<%(type)s>(Mem%(suffix)s,"\
22214150Sjordi.vaquero@metempsy.com                      " valRs, [](%(type)s* b, %(type)s a,"\
22314150Sjordi.vaquero@metempsy.com                      " %(type)s c){ %(op)s });\n"
22414150Sjordi.vaquero@metempsy.com
22514150Sjordi.vaquero@metempsy.com            opcode = opcode % {"suffix": self.suffix,
22614150Sjordi.vaquero@metempsy.com                               "type": self.tp ,
22714150Sjordi.vaquero@metempsy.com                               "dest": self.des,
22814150Sjordi.vaquero@metempsy.com                               "op": op}
22914150Sjordi.vaquero@metempsy.com            self.codeBlobs['amo_code'] = opcode
23014150Sjordi.vaquero@metempsy.com            accCode = "Mem%(suffix)s = cSwap(%(result)s,"\
23114150Sjordi.vaquero@metempsy.com                      " isBigEndian64(xc->tcBase()));"
23214150Sjordi.vaquero@metempsy.com            accCode = accCode % { "result": self.res, "type":self.tp,
23314150Sjordi.vaquero@metempsy.com                                  "suffix": self.suffix}
23414150Sjordi.vaquero@metempsy.com            self.codeBlobs["memacc_code"] = accCode
23514150Sjordi.vaquero@metempsy.com            self.emitHelper(self.base)
23614150Sjordi.vaquero@metempsy.com
23714150Sjordi.vaquero@metempsy.com
23814150Sjordi.vaquero@metempsy.com    AtomicSingleOp("cas",   "CAS64",   8, unsign=True,
23914150Sjordi.vaquero@metempsy.com                   flavor="normal").emit(OP_DICT['CAS'])
24014150Sjordi.vaquero@metempsy.com    AtomicSingleOp("casa",  "CASA64",  8, unsign=True,
24114150Sjordi.vaquero@metempsy.com                   flavor="acquire").emit(OP_DICT['CAS'])
24214150Sjordi.vaquero@metempsy.com    AtomicSingleOp("casal", "CASAL64", 8, unsign=True,
24314150Sjordi.vaquero@metempsy.com                   flavor="acquire_release").emit(OP_DICT['CAS'])
24414150Sjordi.vaquero@metempsy.com    AtomicSingleOp("casl",  "CASL64",  8, unsign=True,
24514150Sjordi.vaquero@metempsy.com                   flavor="release").emit(OP_DICT['CAS'])
24614150Sjordi.vaquero@metempsy.com
24714150Sjordi.vaquero@metempsy.com    AtomicSingleOp("casb",   "CASB",   1, unsign=True,
24814150Sjordi.vaquero@metempsy.com                   flavor="normal").emit(OP_DICT['CAS'])
24914150Sjordi.vaquero@metempsy.com    AtomicSingleOp("casab",  "CASAB",  1, unsign=True,
25014150Sjordi.vaquero@metempsy.com                   flavor="acquire").emit(OP_DICT['CAS'])
25114150Sjordi.vaquero@metempsy.com    AtomicSingleOp("casalb", "CASALB", 1, unsign=True,
25214150Sjordi.vaquero@metempsy.com                   flavor="acquire_release").emit(OP_DICT['CAS'])
25314150Sjordi.vaquero@metempsy.com    AtomicSingleOp("caslb",  "CASLB",  1, unsign=True,
25414150Sjordi.vaquero@metempsy.com                   flavor="release").emit(OP_DICT['CAS'])
25514150Sjordi.vaquero@metempsy.com
25614150Sjordi.vaquero@metempsy.com    AtomicSingleOp("cash",   "CASH",   2, unsign=True,
25714150Sjordi.vaquero@metempsy.com                   flavor="normal").emit(OP_DICT['CAS'])
25814150Sjordi.vaquero@metempsy.com    AtomicSingleOp("casah",  "CASAH",  2, unsign=True,
25914150Sjordi.vaquero@metempsy.com                   flavor="acquire").emit(OP_DICT['CAS'])
26014150Sjordi.vaquero@metempsy.com    AtomicSingleOp("casalh", "CASALH", 2, unsign=True,
26114150Sjordi.vaquero@metempsy.com                   flavor="acquire_release").emit(OP_DICT['CAS'])
26214150Sjordi.vaquero@metempsy.com    AtomicSingleOp("caslh",  "CASLH",  2, unsign=True,
26314150Sjordi.vaquero@metempsy.com                   flavor="release").emit(OP_DICT['CAS'])
26414150Sjordi.vaquero@metempsy.com
26514150Sjordi.vaquero@metempsy.com    AtomicSingleOp("cas",   "CAS32",   4, unsign=True,
26614150Sjordi.vaquero@metempsy.com                   flavor="normal").emit(OP_DICT['CAS'])
26714150Sjordi.vaquero@metempsy.com    AtomicSingleOp("casa",  "CASA32",  4, unsign=True,
26814150Sjordi.vaquero@metempsy.com                   flavor="acquire").emit(OP_DICT['CAS'])
26914150Sjordi.vaquero@metempsy.com    AtomicSingleOp("casal", "CASAL32", 4, unsign=True,
27014150Sjordi.vaquero@metempsy.com                   flavor="acquire_release").emit(OP_DICT['CAS'])
27114150Sjordi.vaquero@metempsy.com    AtomicSingleOp("casl",  "CASL32",  4, unsign=True,
27214150Sjordi.vaquero@metempsy.com                   flavor="release").emit(OP_DICT['CAS'])
27314150Sjordi.vaquero@metempsy.com
27414150Sjordi.vaquero@metempsy.com    class CasPair64(AtomicInst64):
27514150Sjordi.vaquero@metempsy.com        decConstBase = 'AmoPairOp'
27614150Sjordi.vaquero@metempsy.com        base = 'ArmISA::MemoryEx64'
27714150Sjordi.vaquero@metempsy.com        writeback = True
27814150Sjordi.vaquero@metempsy.com        post = False
27914150Sjordi.vaquero@metempsy.com        execBase = 'AmoOp'
28014150Sjordi.vaquero@metempsy.com
28114150Sjordi.vaquero@metempsy.com        def __init__(self, *args, **kargs):
28214150Sjordi.vaquero@metempsy.com            super(CasPair64, self).__init__(*args, **kargs)
28314150Sjordi.vaquero@metempsy.com            self.paired = True
28414150Sjordi.vaquero@metempsy.com            self.offset = ""
28514150Sjordi.vaquero@metempsy.com            if self.size == 8:
28614150Sjordi.vaquero@metempsy.com                self.res = 'XResult_ud'
28714150Sjordi.vaquero@metempsy.com                self.des = 'XDest_ud'
28814150Sjordi.vaquero@metempsy.com                self.tp = 'std::array<uint64_t, 2>'
28914150Sjordi.vaquero@metempsy.com                self.suffix = "_tud"
29014150Sjordi.vaquero@metempsy.com                store_res = '''
29114150Sjordi.vaquero@metempsy.com                            %(result)s = cSwap(Mem%(suffix)s[0],
29214150Sjordi.vaquero@metempsy.com                                          isBigEndian64(xc->tcBase()));
29314150Sjordi.vaquero@metempsy.com                            uint64_t result2 = cSwap(Mem%(suffix)s[1],
29414150Sjordi.vaquero@metempsy.com                                           isBigEndian64(xc->tcBase()));
29514150Sjordi.vaquero@metempsy.com                            xc->setIntRegOperand(this, r2_dst, (result2)
29614150Sjordi.vaquero@metempsy.com                                                    & mask(aarch64 ? 64 : 32));
29714150Sjordi.vaquero@metempsy.com                            '''
29814150Sjordi.vaquero@metempsy.com            elif self.size == 4:
29914150Sjordi.vaquero@metempsy.com                self.res = 'Result_uw'
30014150Sjordi.vaquero@metempsy.com                self.des = 'WDest_uw'
30114150Sjordi.vaquero@metempsy.com                self.tp = 'uint64_t'
30214150Sjordi.vaquero@metempsy.com                self.suffix = "_ud"
30314150Sjordi.vaquero@metempsy.com                store_res = '''
30414150Sjordi.vaquero@metempsy.com                    uint64_t data = cSwap(Mem%(suffix)s,
30514150Sjordi.vaquero@metempsy.com                                          isBigEndian64(xc->tcBase()));
30614150Sjordi.vaquero@metempsy.com                    %(result)s = isBigEndian64(xc->tcBase())
30714150Sjordi.vaquero@metempsy.com                                   ? (data >> 32)
30814150Sjordi.vaquero@metempsy.com                                   : (uint32_t)data;
30914150Sjordi.vaquero@metempsy.com                    uint32_t result2 = isBigEndian64(xc->tcBase())
31014150Sjordi.vaquero@metempsy.com                                   ? (uint32_t)data
31114150Sjordi.vaquero@metempsy.com                                   : (data >> 32);
31214150Sjordi.vaquero@metempsy.com                    xc->setIntRegOperand(this, r2_dst, (result2) &
31314150Sjordi.vaquero@metempsy.com                                                mask(aarch64 ? 64 : 32));
31414150Sjordi.vaquero@metempsy.com                            '''
31514150Sjordi.vaquero@metempsy.com
31614150Sjordi.vaquero@metempsy.com            store_res = store_res % {"result":self.res, "suffix":self.suffix}
31714150Sjordi.vaquero@metempsy.com            usrDecl = "%(type)s valRs;\n" % {'type': self.tp}
31814150Sjordi.vaquero@metempsy.com            self.codeBlobs['usrDecl'] = usrDecl
31914150Sjordi.vaquero@metempsy.com            self.codeBlobs["postacc_code"] = \
32014150Sjordi.vaquero@metempsy.com                    store_res + " SevMailbox = 1; LLSCLock = 0;"
32114150Sjordi.vaquero@metempsy.com
32214150Sjordi.vaquero@metempsy.com        def emit(self):
32314150Sjordi.vaquero@metempsy.com            self.buildEACode()
32414150Sjordi.vaquero@metempsy.com
32514150Sjordi.vaquero@metempsy.com            # Code that actually handles the access
32614150Sjordi.vaquero@metempsy.com
32714150Sjordi.vaquero@metempsy.com            if self.size == 4:
32814150Sjordi.vaquero@metempsy.com                accCode = \
32914150Sjordi.vaquero@metempsy.com                  "uint32_t result2 = ((xc->readIntRegOperand(this, r2_src))"\
33014150Sjordi.vaquero@metempsy.com                  " & mask(aarch64 ? 64 : 32)) ;\n"\
33114150Sjordi.vaquero@metempsy.com                  " uint32_t dest2 = ((xc->readIntRegOperand(this, d2_src)) "\
33214150Sjordi.vaquero@metempsy.com                  " & mask(aarch64 ? 64 : 32)) ;"
33314150Sjordi.vaquero@metempsy.com                accCode += '''
33414150Sjordi.vaquero@metempsy.com                     uint64_t data = dest2;
33514150Sjordi.vaquero@metempsy.com                     data = isBigEndian64(xc->tcBase())
33614150Sjordi.vaquero@metempsy.com                          ? ((uint64_t(WDest_uw) << 32) | data)
33714150Sjordi.vaquero@metempsy.com                                 : ((data << 32) | WDest_uw);
33814150Sjordi.vaquero@metempsy.com                     valRs = cSwap(data, isBigEndian64(xc->tcBase()));
33914150Sjordi.vaquero@metempsy.com                     uint64_t data2 = result2 ;
34014150Sjordi.vaquero@metempsy.com                     data2 = isBigEndian64(xc->tcBase())
34114150Sjordi.vaquero@metempsy.com                          ? ((uint64_t(Result_uw) << 32) | data2)
34214150Sjordi.vaquero@metempsy.com                                 : ((data2 << 32) | Result_uw);
34314150Sjordi.vaquero@metempsy.com                     Mem_ud = cSwap(data2, isBigEndian64(xc->tcBase()));
34414150Sjordi.vaquero@metempsy.com                     '''
34514150Sjordi.vaquero@metempsy.com
34614150Sjordi.vaquero@metempsy.com                opcode = "TypedAtomicOpFunctor<%(type)s> *amo_op = "\
34714150Sjordi.vaquero@metempsy.com                      "new AtomicGeneric3Op<%(type)s>(Mem%(suffix)s,"\
34814150Sjordi.vaquero@metempsy.com                      " valRs, [](%(type)s* b, %(type)s a,"\
34914150Sjordi.vaquero@metempsy.com                      " %(type)s c){ %(op)s });\n"
35014150Sjordi.vaquero@metempsy.com
35114150Sjordi.vaquero@metempsy.com            elif self.size == 8:
35214150Sjordi.vaquero@metempsy.com                accCode = ""\
35314150Sjordi.vaquero@metempsy.com                  "uint64_t result2 = ((xc->readIntRegOperand(this, r2_src))"\
35414150Sjordi.vaquero@metempsy.com                  " & mask(aarch64 ? 64 : 32)) ;\n"\
35514150Sjordi.vaquero@metempsy.com                  " uint64_t dest2 = ((xc->readIntRegOperand(this, d2_src)) "\
35614150Sjordi.vaquero@metempsy.com                  " & mask(aarch64 ? 64 : 32)) ;"
35714150Sjordi.vaquero@metempsy.com                accCode += '''
35814150Sjordi.vaquero@metempsy.com                   // This temporary needs to be here so that the parser
35914150Sjordi.vaquero@metempsy.com                   // will correctly identify this instruction as a store.
36014150Sjordi.vaquero@metempsy.com                   std::array<uint64_t, 2> temp;
36114150Sjordi.vaquero@metempsy.com                   temp[0] = cSwap(XDest_ud,isBigEndian64(xc->tcBase()));
36214150Sjordi.vaquero@metempsy.com                   temp[1] = cSwap(dest2,isBigEndian64(xc->tcBase()));
36314150Sjordi.vaquero@metempsy.com                   valRs = temp;
36414150Sjordi.vaquero@metempsy.com                   std::array<uint64_t, 2> temp2;
36514150Sjordi.vaquero@metempsy.com                   temp2[0] = cSwap(XResult_ud,isBigEndian64(xc->tcBase()));
36614150Sjordi.vaquero@metempsy.com                   temp2[1] = cSwap(result2,isBigEndian64(xc->tcBase()));
36714150Sjordi.vaquero@metempsy.com                   Mem_tud = temp2;
36814150Sjordi.vaquero@metempsy.com                     '''
36914150Sjordi.vaquero@metempsy.com
37014150Sjordi.vaquero@metempsy.com                opcode = "TypedAtomicOpFunctor<uint64_t> *amo_op = "\
37114150Sjordi.vaquero@metempsy.com                          "new AtomicGenericPair3Op<uint64_t>(Mem_tud, "\
37214150Sjordi.vaquero@metempsy.com                          "valRs, [](uint64_t* b, std::array<uint64_t,2> a,"\
37314150Sjordi.vaquero@metempsy.com                          '''
37414150Sjordi.vaquero@metempsy.com                          std::array<uint64_t,2> c){
37514150Sjordi.vaquero@metempsy.com                             if(a[0]==b[0] && a[1]==b[1]){
37614150Sjordi.vaquero@metempsy.com                                b[0] = c[0]; b[1] = c[1];
37714150Sjordi.vaquero@metempsy.com                             }
37814150Sjordi.vaquero@metempsy.com                          });'''
37914150Sjordi.vaquero@metempsy.com
38014150Sjordi.vaquero@metempsy.com            opcode = opcode % { "suffix" : self.suffix,
38114150Sjordi.vaquero@metempsy.com                                "type": self.tp,
38214150Sjordi.vaquero@metempsy.com                                "op": OP_DICT['CAS']}
38314150Sjordi.vaquero@metempsy.com            self.codeBlobs['amo_code'] = opcode
38414150Sjordi.vaquero@metempsy.com            self.codeBlobs["memacc_code"] = accCode % {"type": self.tp}
38514150Sjordi.vaquero@metempsy.com
38614150Sjordi.vaquero@metempsy.com            # Push it out to the output files
38714150Sjordi.vaquero@metempsy.com            self.emitHelper(self.base)
38814150Sjordi.vaquero@metempsy.com
38914150Sjordi.vaquero@metempsy.com    CasPair64("casp",   "CASP64",   8, flavor="normal", paired=True).emit()
39014150Sjordi.vaquero@metempsy.com    CasPair64("caspa",  "CASPA64",  8, flavor="acquire", paired=True).emit()
39114150Sjordi.vaquero@metempsy.com    CasPair64("caspal", "CASPAL64", 8, flavor="acquire_release",
39214150Sjordi.vaquero@metempsy.com            paired=True).emit()
39314150Sjordi.vaquero@metempsy.com    CasPair64("caspl",  "CASPL64",  8, flavor="release", paired=True).emit()
39414150Sjordi.vaquero@metempsy.com
39514150Sjordi.vaquero@metempsy.com    CasPair64("casp",   "CASP32",   4, flavor="normal", paired=True).emit()
39614150Sjordi.vaquero@metempsy.com    CasPair64("caspa",  "CASPA32",  4, flavor="acquire", paired=True).emit()
39714150Sjordi.vaquero@metempsy.com    CasPair64("caspal", "CASPAL32", 4, flavor="acquire_release",
39814150Sjordi.vaquero@metempsy.com            paired=True).emit()
39914150Sjordi.vaquero@metempsy.com    CasPair64("caspl",  "CASPL32",  4, flavor="release", paired=True).emit()
40014150Sjordi.vaquero@metempsy.com
40114150Sjordi.vaquero@metempsy.com}};
402