util.isa revision 3439:b35c5f0ff57b
1// Copyright (c) 2006 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(%(CPU_exec_context)s *xc,
39                Trace::InstRecord *traceData) const
40        {
41            Fault fault = NoFault;
42            Addr EA;
43            %(op_decl)s;
44            %(op_rd)s;
45            %(ea_code)s;
46            DPRINTF(Sparc, "The address is 0x%x\n", EA);
47            %(fault_check)s;
48            if(fault == NoFault)
49            {
50                fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
51            }
52            if(fault == NoFault)
53            {
54                %(code)s;
55            }
56            if(fault == NoFault)
57            {
58                //Write the resulting state to the execution context
59                %(op_wb)s;
60            }
61
62            return fault;
63        }
64
65        Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
66                Trace::InstRecord * traceData) const
67        {
68            Fault fault = NoFault;
69            Addr EA;
70            uint%(mem_acc_size)s_t Mem;
71            %(ea_decl)s;
72            %(ea_rd)s;
73            %(ea_code)s;
74            %(fault_check)s;
75            if(fault == NoFault)
76            {
77                fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
78            }
79            return fault;
80        }
81
82        Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc,
83                Trace::InstRecord * traceData) const
84        {
85            Fault fault = NoFault;
86            %(code_decl)s;
87            %(code_rd)s;
88            Mem = pkt->get<typeof(Mem)>();
89            %(code)s;
90            if(fault == NoFault)
91            {
92                %(code_wb)s;
93            }
94            return fault;
95        }
96}};
97
98//This template provides the execute functions for a store
99def template StoreExecute {{
100        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
101                Trace::InstRecord *traceData) const
102        {
103            Fault fault = NoFault;
104            uint64_t write_result = 0;
105            //This is to support the conditional store in cas instructions.
106            //It should be optomized out in all the others
107            bool storeCond = true;
108            Addr EA;
109            %(op_decl)s;
110            %(op_rd)s;
111            %(ea_code)s;
112            DPRINTF(Sparc, "The address is 0x%x\n", EA);
113            %(fault_check)s;
114            if(fault == NoFault)
115            {
116                %(code)s;
117            }
118            if(storeCond && fault == NoFault)
119            {
120                fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
121            }
122            if(fault == NoFault)
123            {
124                //Write the resulting state to the execution context
125                %(op_wb)s;
126            }
127
128            return fault;
129        }
130
131        Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
132                Trace::InstRecord * traceData) const
133        {
134            Fault fault = NoFault;
135            uint64_t write_result = 0;
136            bool storeCond = true;
137            Addr EA;
138            %(op_decl)s;
139            %(op_rd)s;
140            %(ea_code)s;
141            DPRINTF(Sparc, "The address is 0x%x\n", EA);
142            %(fault_check)s;
143            if(fault == NoFault)
144            {
145                %(code)s;
146            }
147            if(storeCond && fault == NoFault)
148            {
149                fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
150            }
151            if(fault == NoFault)
152            {
153                //Write the resulting state to the execution context
154                %(op_wb)s;
155            }
156            return fault;
157        }
158
159        Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
160                Trace::InstRecord * traceData) const
161        {
162            return NoFault;
163        }
164}};
165
166//This delcares the initiateAcc function in memory operations
167def template InitiateAccDeclare {{
168    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
169}};
170
171//This declares the completeAcc function in memory operations
172def template CompleteAccDeclare {{
173    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
174}};
175
176//Here are some code snippets which check for various fault conditions
177let {{
178    # The LSB can be zero, since it's really the MSB in doubles and quads
179    # and we're dealing with doubles
180    BlockAlignmentFaultCheck = '''
181        if(RD & 0xe)
182            fault = new IllegalInstruction;
183        else if(EA & 0x3f)
184            fault = new MemAddressNotAligned;
185    '''
186    # XXX Need to take care of pstate.hpriv as well. The lower ASIs
187    # are split into ones that are available in priv and hpriv, and
188    # those that are only available in hpriv
189    AlternateASIPrivFaultCheck = '''
190        if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0)
191            fault = new PrivilegedAction;
192        else if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2))
193            fault = new PrivilegedAction;
194    '''
195
196}};
197
198//A simple function to generate the name of the macro op of a certain
199//instruction at a certain micropc
200let {{
201    def makeMicroName(name, microPc):
202        return name + "::" + name + "_" + str(microPc)
203}};
204
205//This function properly generates the execute functions for one of the
206//templates above. This is needed because in one case, ea computation,
207//fault checks and the actual code all occur in the same function,
208//and in the other they're distributed across two. Also note that for
209//execute functions, the name of the base class doesn't matter.
210let {{
211    def doSplitExecute(code, eaCode, execute,
212            faultCode, name, Name, opt_flags):
213        codeIop = InstObjParams(name, Name, '', code, opt_flags)
214        eaIop = InstObjParams(name, Name, '', eaCode,
215                opt_flags, {"fault_check": faultCode})
216        iop = InstObjParams(name, Name, '', code, opt_flags,
217                {"fault_check": faultCode, "ea_code" : eaCode})
218        (iop.ea_decl,
219         iop.ea_rd,
220         iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb)
221        (iop.code_decl,
222         iop.code_rd,
223         iop.code_wb) = (codeIop.op_decl, codeIop.op_rd, codeIop.op_wb)
224        return execute.subst(iop)
225
226
227    def doDualSplitExecute(code, eaRegCode, eaImmCode, execute,
228            faultCode, nameReg, nameImm, NameReg, NameImm, opt_flags):
229        executeCode = ''
230        for (eaCode, name, Name) in (
231                (eaRegCode, nameReg, NameReg),
232                (eaImmCode, nameImm, NameImm)):
233            executeCode += doSplitExecute(code, eaCode,
234                    execute, faultCode, name, Name, opt_flags)
235        return executeCode
236}};
237