util.isa revision 12294:650a9d8b23cc
1// Copyright (c) 2006-2007 The Regents of The University of Michigan
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met: redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer;
8// redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution;
11// neither the name of the copyright holders nor the names of its
12// contributors may be used to endorse or promote products derived from
13// this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26//
27// Authors: Ali Saidi
28//          Gabe Black
29//          Steve Reinhardt
30
31////////////////////////////////////////////////////////////////////
32//
33// Mem utility templates and functions
34//
35
36// This template provides the execute functions for a load
37def template LoadExecute {{
38        Fault %(class_name)s::execute(ExecContext *xc,
39                Trace::InstRecord *traceData) const
40        {
41            Fault fault = NoFault;
42            Addr EA;
43            %(fp_enable_check)s;
44            %(op_decl)s;
45            %(op_rd)s;
46            %(ea_code)s;
47            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
48            %(fault_check)s;
49            if (fault == NoFault) {
50                %(EA_trunc)s
51                fault = readMemAtomic(xc, traceData, EA, Mem, %(asi_val)s);
52            }
53            if (fault == NoFault) {
54                %(code)s;
55            }
56            if (fault == NoFault) {
57                // Write the resulting state to the execution context
58                %(op_wb)s;
59            }
60
61            return fault;
62        }
63}};
64
65def template LoadInitiateAcc {{
66        Fault %(class_name)s::initiateAcc(ExecContext * xc,
67                Trace::InstRecord * traceData) const
68        {
69            Fault fault = NoFault;
70            Addr EA;
71            %(fp_enable_check)s;
72            %(op_decl)s;
73            %(op_rd)s;
74            %(ea_code)s;
75            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
76            %(fault_check)s;
77            if (fault == NoFault) {
78                %(EA_trunc)s
79                fault = initiateMemRead(xc, traceData, EA, Mem, %(asi_val)s);
80            }
81            return fault;
82        }
83}};
84
85def template LoadCompleteAcc {{
86        Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext * xc,
87                Trace::InstRecord * traceData) const
88        {
89            Fault fault = NoFault;
90            %(op_decl)s;
91            %(op_rd)s;
92            getMem(pkt, Mem, traceData);
93            %(code)s;
94            if (fault == NoFault) {
95                %(op_wb)s;
96            }
97            return fault;
98        }
99}};
100
101// This template provides the execute functions for a store
102def template StoreExecute {{
103        Fault %(class_name)s::execute(ExecContext *xc,
104                Trace::InstRecord *traceData) const
105        {
106            Fault fault = NoFault;
107            // This is to support the conditional store in cas instructions.
108            // It should be optomized out in all the others
109            bool storeCond = true;
110            Addr EA;
111            %(fp_enable_check)s;
112            %(op_decl)s;
113            %(op_rd)s;
114            %(ea_code)s;
115            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
116            %(fault_check)s;
117            if (fault == NoFault) {
118                %(code)s;
119            }
120            if (storeCond && fault == NoFault) {
121                %(EA_trunc)s
122                fault = writeMemAtomic(xc, traceData, Mem, EA, %(asi_val)s, 0);
123            }
124            if (fault == NoFault) {
125                // Write the resulting state to the execution context
126                %(op_wb)s;
127            }
128
129            return fault;
130        }
131}};
132
133def template StoreInitiateAcc {{
134        Fault %(class_name)s::initiateAcc(ExecContext * xc,
135                Trace::InstRecord * traceData) const
136        {
137            Fault fault = NoFault;
138            bool storeCond = true;
139            Addr EA;
140            %(fp_enable_check)s;
141            %(op_decl)s;
142
143            %(op_rd)s;
144            %(ea_code)s;
145            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
146            %(fault_check)s;
147            if (fault == NoFault) {
148                %(code)s;
149            }
150            if (storeCond && fault == NoFault) {
151                %(EA_trunc)s
152                fault = writeMemTiming(xc, traceData, Mem, EA, %(asi_val)s, 0);
153            }
154            return fault;
155        }
156}};
157
158def template StoreCompleteAcc {{
159        Fault %(class_name)s::completeAcc(PacketPtr, ExecContext * xc,
160                Trace::InstRecord * traceData) const
161        {
162            return NoFault;
163        }
164}};
165
166def template EACompExecute {{
167    Fault
168    %(class_name)s::eaComp(ExecContext *xc,
169                                   Trace::InstRecord *traceData) const
170    {
171        Addr EA;
172        Fault fault = NoFault;
173        %(op_decl)s;
174        %(op_rd)s;
175        %(ea_code)s;
176        %(fault_check)s;
177
178        // NOTE: Trace Data is written using execute or completeAcc templates
179        if (fault == NoFault) {
180            %(EA_trunc)s
181            xc->setEA(EA);
182        }
183
184        return fault;
185    }
186}};
187
188// Here are some code snippets which check for various fault conditions
189let {{
190    LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc]
191    StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc]
192
193    # The LSB can be zero, since it's really the MSB in doubles and quads
194    # and we're dealing with doubles
195    BlockAlignmentFaultCheck = '''
196        if (RD & 0xe)
197            fault = std::make_shared<IllegalInstruction>();
198        else if (EA & 0x3f)
199            fault = std::make_shared<MemAddressNotAligned>();
200    '''
201    TwinAlignmentFaultCheck = '''
202        if (RD & 0x1)
203            fault = std::make_shared<IllegalInstruction>();
204        else if (EA & 0xf)
205            fault = std::make_shared<MemAddressNotAligned>();
206    '''
207    # XXX Need to take care of pstate.hpriv as well. The lower ASIs
208    # are split into ones that are available in priv and hpriv, and
209    # those that are only available in hpriv
210    AlternateASIPrivFaultCheck = '''
211        if ((!Pstate.priv && !Hpstate.hpriv &&
212             !asiIsUnPriv((ASI)EXT_ASI)) ||
213            (!Hpstate.hpriv && asiIsHPriv((ASI)EXT_ASI)))
214            fault = std::make_shared<PrivilegedAction>();
215        else if (asiIsAsIfUser((ASI)EXT_ASI) && !Pstate.priv)
216            fault = std::make_shared<PrivilegedAction>();
217    '''
218
219    TruncateEA = '''
220        if (!FullSystem) {
221            EA = Pstate.am ? EA<31:0> : EA;
222        }
223    '''
224}};
225
226// A simple function to generate the name of the macro op of a certain
227// instruction at a certain micropc
228let {{
229    def makeMicroName(name, microPc):
230            return name + "::" + name + "_" + str(microPc)
231}};
232
233// This function properly generates the execute functions for one of the
234// templates above. This is needed because in one case, ea computation,
235// fault checks and the actual code all occur in the same function,
236// and in the other they're distributed across two. Also note that for
237// execute functions, the name of the base class doesn't matter.
238let {{
239    def doSplitExecute(execute, name, Name, asi, opt_flags, microParam):
240        microParam["asi_val"] = asi;
241        iop = InstObjParams(name, Name, '', microParam, opt_flags)
242        (execf, initf, compf) = execute
243        return execf.subst(iop) + initf.subst(iop) + compf.subst(iop)
244
245
246    def doDualSplitExecute(code, postacc_code, eaRegCode, eaImmCode, execute,
247            faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags):
248        executeCode = ''
249        for (eaCode, name, Name) in (
250                (eaRegCode, nameReg, NameReg),
251                (eaImmCode, nameImm, NameImm)):
252            microParams = {"code": code, "postacc_code" : postacc_code,
253                "ea_code": eaCode, "fault_check": faultCode,
254                "EA_trunc" : TruncateEA}
255            executeCode += doSplitExecute(execute, name, Name,
256                    asi, opt_flags, microParams)
257        return executeCode
258}};
259