1// -*- mode:c++ -*-
2
3// Copyright (c) 2009 The University of Edinburgh
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met: redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer;
10// redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution;
13// neither the name of the copyright holders nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Authors: Timothy M. Jones
30
31////////////////////////////////////////////////////////////////////
32//
33// Memory-format instructions
34//
35
36def template LoadStoreDeclare {{
37    /**
38     * Static instruction class for "%(mnemonic)s".
39     */
40    class %(class_name)s : public %(base_class)s
41    {
42      public:
43
44        /// Constructor.
45        %(class_name)s(ExtMachInst machInst);
46
47        Fault execute(ExecContext *, Trace::InstRecord *) const override;
48        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
49        Fault completeAcc(PacketPtr, ExecContext *,
50                          Trace::InstRecord *) const override;
51    };
52}};
53
54
55def template LoadStoreConstructor {{
56    %(class_name)s::%(class_name)s(ExtMachInst machInst)
57         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
58    {
59        %(constructor)s;
60    }
61}};
62
63
64def template LoadExecute {{
65    Fault %(class_name)s::execute(ExecContext *xc,
66                                  Trace::InstRecord *traceData) const
67    {
68        Addr EA;
69        Fault fault = NoFault;
70
71        %(op_decl)s;
72        %(op_rd)s;
73        %(ea_code)s;
74
75        if (fault == NoFault) {
76            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
77            %(memacc_code)s;
78        }
79
80        if (fault == NoFault) {
81            %(op_wb)s;
82        }
83
84        return fault;
85    }
86}};
87
88
89def template LoadInitiateAcc {{
90    Fault %(class_name)s::initiateAcc(ExecContext *xc,
91                                      Trace::InstRecord *traceData) const
92    {
93        Addr EA;
94        Fault fault = NoFault;
95
96        %(op_src_decl)s;
97        %(op_rd)s;
98        %(ea_code)s;
99
100        if (fault == NoFault) {
101            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
102        }
103
104        return fault;
105    }
106}};
107
108
109def template LoadCompleteAcc {{
110    Fault %(class_name)s::completeAcc(PacketPtr pkt,
111                                      ExecContext *xc,
112                                      Trace::InstRecord *traceData) const
113    {
114        Addr M5_VAR_USED EA;
115        Fault fault = NoFault;
116
117        %(op_decl)s;
118        %(op_rd)s;
119
120        EA = pkt->req->getVaddr();
121
122        getMem(pkt, Mem, traceData);
123
124        if (fault == NoFault) {
125            %(memacc_code)s;
126        }
127
128        if (fault == NoFault) {
129          %(op_wb)s;
130        }
131
132        return fault;
133    }
134}};
135
136
137def template StoreExecute {{
138    Fault %(class_name)s::execute(ExecContext *xc,
139                                  Trace::InstRecord *traceData) const
140    {
141        Addr EA;
142        Fault fault = NoFault;
143
144        %(op_decl)s;
145        %(op_rd)s;
146        %(ea_code)s;
147
148        if (fault == NoFault) {
149            %(memacc_code)s;
150        }
151
152        if (fault == NoFault) {
153            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
154                    NULL);
155        }
156
157        if (fault == NoFault) {
158            %(op_wb)s;
159        }
160
161        return fault;
162    }
163}};
164
165
166def template StoreInitiateAcc {{
167    Fault %(class_name)s::initiateAcc(ExecContext *xc,
168                                      Trace::InstRecord *traceData) const
169    {
170        Addr EA;
171        Fault fault = NoFault;
172
173        %(op_decl)s;
174        %(op_rd)s;
175        %(ea_code)s;
176
177        if (fault == NoFault) {
178            %(memacc_code)s;
179        }
180
181        if (fault == NoFault) {
182            fault = writeMemTiming(xc, traceData, Mem, EA, memAccessFlags,
183                    NULL);
184        }
185
186        // Need to write back any potential address register update
187        if (fault == NoFault) {
188            %(op_wb)s;
189        }
190
191        return fault;
192    }
193}};
194
195
196def template StoreCompleteAcc {{
197    Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
198                                      Trace::InstRecord *traceData) const
199    {
200        return NoFault;
201    }
202}};
203
204
205// The generic memory operation generator. This is called when two versions
206// of an instruction are needed - when Ra == 0 and otherwise. This is so
207// that instructions can use the value 0 when Ra == 0 but avoid having a
208// dependence on Ra.
209let {{
210
211def GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0, base,
212             load_or_store, mem_flags = [], inst_flags = []):
213
214    # First the version where Ra is non-zero
215    (header_output, decoder_output, decode_block, exec_output) = \
216        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
217                      base_class = base,
218                      decode_template = CheckRaDecode,
219                      exec_template_base = load_or_store)
220
221    # Now another version where Ra == 0
222    (header_output_ra0, decoder_output_ra0, _, exec_output_ra0) = \
223        LoadStoreBase(name, Name + 'RaZero', ea_code_ra0, memacc_code,
224                      mem_flags, inst_flags,
225                      base_class = base,
226                      exec_template_base = load_or_store)
227
228    # Finally, add to the other outputs
229    header_output += header_output_ra0
230    decoder_output += decoder_output_ra0
231    exec_output += exec_output_ra0
232    return (header_output, decoder_output, decode_block, exec_output)
233
234}};
235
236
237def format LoadIndexOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
238                       ea_code_ra0 = {{ EA = Rb; }},
239                       mem_flags = [], inst_flags = []) {{
240    (header_output, decoder_output, decode_block, exec_output) = \
241        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
242                 'MemOp', 'Load', mem_flags, inst_flags)
243}};
244
245
246def format StoreIndexOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
247                        ea_code_ra0 = {{ EA = Rb; }},
248                        mem_flags = [], inst_flags = []) {{
249    (header_output, decoder_output, decode_block, exec_output) = \
250        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
251                 'MemOp', 'Store', mem_flags, inst_flags)
252}};
253
254
255def format LoadIndexUpdateOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
256                             mem_flags = [], inst_flags = []) {{
257
258    # Add in the update code
259    memacc_code += 'Ra = EA;'
260
261    # Generate the class
262    (header_output, decoder_output, decode_block, exec_output) = \
263        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
264                      base_class = 'MemOp',
265                      exec_template_base = 'Load')
266}};
267
268
269def format StoreIndexUpdateOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
270                              mem_flags = [], inst_flags = []) {{
271
272    # Add in the update code
273    memacc_code += 'Ra = EA;'
274
275    # Generate the class
276    (header_output, decoder_output, decode_block, exec_output) = \
277        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
278                      base_class = 'MemOp',
279                      exec_template_base = 'Store')
280}};
281
282
283def format LoadDispOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
284                      ea_code_ra0 = {{ EA = disp; }},
285                      mem_flags = [], inst_flags = []) {{
286    (header_output, decoder_output, decode_block, exec_output) = \
287        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
288                 'MemDispOp', 'Load', mem_flags, inst_flags)
289}};
290
291
292def format StoreDispOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
293                       ea_code_ra0 = {{ EA = disp; }},
294                       mem_flags = [], inst_flags = []) {{
295    (header_output, decoder_output, decode_block, exec_output) = \
296        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
297                 'MemDispOp', 'Store', mem_flags, inst_flags)
298}};
299
300
301def format LoadDispUpdateOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
302                            mem_flags = [], inst_flags = []) {{
303
304    # Add in the update code
305    memacc_code += 'Ra = EA;'
306
307    # Generate the class
308    (header_output, decoder_output, decode_block, exec_output) = \
309        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
310                      base_class = 'MemDispOp',
311                      exec_template_base = 'Load')
312}};
313
314
315def format StoreDispUpdateOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
316                             mem_flags = [], inst_flags = []) {{
317
318    # Add in the update code
319    memacc_code += 'Ra = EA;'
320
321    # Generate the class
322    (header_output, decoder_output, decode_block, exec_output) = \
323        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
324                      base_class = 'MemDispOp',
325                      exec_template_base = 'Store')
326}};
327