mem.isa revision 11303:f694764d656d
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        %(BasicExecDeclare)s
48
49        %(InitiateAccDeclare)s
50
51        %(CompleteAccDeclare)s
52    };
53}};
54
55
56def template InitiateAccDeclare {{
57    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
58}};
59
60
61def template CompleteAccDeclare {{
62    Fault completeAcc(PacketPtr,  %(CPU_exec_context)s *, Trace::InstRecord *) const;
63}};
64
65
66def template LoadStoreConstructor {{
67    %(class_name)s::%(class_name)s(ExtMachInst machInst)
68         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
69    {
70        %(constructor)s;
71    }
72}};
73
74
75def template LoadExecute {{
76    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
77                                  Trace::InstRecord *traceData) const
78    {
79        Addr EA;
80        Fault fault = NoFault;
81
82        %(op_decl)s;
83        %(op_rd)s;
84        %(ea_code)s;
85
86        if (fault == NoFault) {
87            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
88            %(memacc_code)s;
89        }
90
91        if (fault == NoFault) {
92            %(op_wb)s;
93        }
94
95        return fault;
96    }
97}};
98
99
100def template LoadInitiateAcc {{
101    Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
102                                      Trace::InstRecord *traceData) const
103    {
104        Addr EA;
105        Fault fault = NoFault;
106
107        %(op_src_decl)s;
108        %(op_rd)s;
109        %(ea_code)s;
110
111        if (fault == NoFault) {
112            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
113            xc->setEA(EA);
114        }
115
116        return fault;
117    }
118}};
119
120
121def template LoadCompleteAcc {{
122    Fault %(class_name)s::completeAcc(PacketPtr pkt,
123                                      CPU_EXEC_CONTEXT *xc,
124                                      Trace::InstRecord *traceData) const
125    {
126        Addr M5_VAR_USED EA;
127        Fault fault = NoFault;
128
129        %(op_decl)s;
130        %(op_rd)s;
131
132        EA = xc->getEA();
133
134        getMem(pkt, Mem, traceData);
135
136        if (fault == NoFault) {
137            %(memacc_code)s;
138        }
139
140        if (fault == NoFault) {
141          %(op_wb)s;
142        }
143
144        return fault;
145    }
146}};
147
148
149def template StoreExecute {{
150    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
151                                  Trace::InstRecord *traceData) const
152    {
153        Addr EA;
154        Fault fault = NoFault;
155
156        %(op_decl)s;
157        %(op_rd)s;
158        %(ea_code)s;
159
160        if (fault == NoFault) {
161            %(memacc_code)s;
162        }
163
164        if (fault == NoFault) {
165            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
166                    NULL);
167        }
168
169        if (fault == NoFault) {
170            %(op_wb)s;
171        }
172
173        return fault;
174    }
175}};
176
177
178def template StoreInitiateAcc {{
179    Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
180                                      Trace::InstRecord *traceData) const
181    {
182        Addr EA;
183        Fault fault = NoFault;
184
185        %(op_decl)s;
186        %(op_rd)s;
187        %(ea_code)s;
188
189        if (fault == NoFault) {
190            %(memacc_code)s;
191        }
192
193        if (fault == NoFault) {
194            fault = writeMemTiming(xc, traceData, Mem, EA, memAccessFlags,
195                    NULL);
196        }
197
198        // Need to write back any potential address register update
199        if (fault == NoFault) {
200            %(op_wb)s;
201        }
202
203        return fault;
204    }
205}};
206
207
208def template StoreCompleteAcc {{
209    Fault %(class_name)s::completeAcc(PacketPtr pkt,
210                                      CPU_EXEC_CONTEXT *xc,
211                                      Trace::InstRecord *traceData) const
212    {
213        return NoFault;
214    }
215}};
216
217
218// The generic memory operation generator. This is called when two versions
219// of an instruction are needed - when Ra == 0 and otherwise. This is so
220// that instructions can use the value 0 when Ra == 0 but avoid having a
221// dependence on Ra.
222let {{
223
224def GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0, base,
225             load_or_store, mem_flags = [], inst_flags = []):
226
227    # First the version where Ra is non-zero
228    (header_output, decoder_output, decode_block, exec_output) = \
229        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
230                      base_class = base,
231                      decode_template = CheckRaDecode,
232                      exec_template_base = load_or_store)
233
234    # Now another version where Ra == 0
235    (header_output_ra0, decoder_output_ra0, _, exec_output_ra0) = \
236        LoadStoreBase(name, Name + 'RaZero', ea_code_ra0, memacc_code,
237                      mem_flags, inst_flags,
238                      base_class = base,
239                      exec_template_base = load_or_store)
240
241    # Finally, add to the other outputs
242    header_output += header_output_ra0
243    decoder_output += decoder_output_ra0
244    exec_output += exec_output_ra0
245    return (header_output, decoder_output, decode_block, exec_output)
246
247}};
248
249
250def format LoadIndexOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
251                       ea_code_ra0 = {{ EA = Rb; }},
252                       mem_flags = [], inst_flags = []) {{
253    (header_output, decoder_output, decode_block, exec_output) = \
254        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
255                 'MemOp', 'Load', mem_flags, inst_flags)
256}};
257
258
259def format StoreIndexOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
260                        ea_code_ra0 = {{ EA = Rb; }},
261                        mem_flags = [], inst_flags = []) {{
262    (header_output, decoder_output, decode_block, exec_output) = \
263        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
264                 'MemOp', 'Store', mem_flags, inst_flags)
265}};
266
267
268def format LoadIndexUpdateOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
269                             mem_flags = [], inst_flags = []) {{
270
271    # Add in the update code
272    memacc_code += 'Ra = EA;'
273
274    # Generate the class
275    (header_output, decoder_output, decode_block, exec_output) = \
276        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
277                      base_class = 'MemOp',
278                      exec_template_base = 'Load')
279}};
280
281
282def format StoreIndexUpdateOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
283                              mem_flags = [], inst_flags = []) {{
284
285    # Add in the update code
286    memacc_code += 'Ra = EA;'
287
288    # Generate the class
289    (header_output, decoder_output, decode_block, exec_output) = \
290        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
291                      base_class = 'MemOp',
292                      exec_template_base = 'Store')
293}};
294
295
296def format LoadDispOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
297                      ea_code_ra0 = {{ EA = disp; }},
298                      mem_flags = [], inst_flags = []) {{
299    (header_output, decoder_output, decode_block, exec_output) = \
300        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
301                 'MemDispOp', 'Load', mem_flags, inst_flags)
302}};
303
304
305def format StoreDispOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
306                       ea_code_ra0 = {{ EA = disp; }},
307                       mem_flags = [], inst_flags = []) {{
308    (header_output, decoder_output, decode_block, exec_output) = \
309        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
310                 'MemDispOp', 'Store', mem_flags, inst_flags)
311}};
312
313
314def format LoadDispUpdateOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
315                            mem_flags = [], inst_flags = []) {{
316
317    # Add in the update code
318    memacc_code += 'Ra = EA;'
319
320    # Generate the class
321    (header_output, decoder_output, decode_block, exec_output) = \
322        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
323                      base_class = 'MemDispOp',
324                      exec_template_base = 'Load')
325}};
326
327
328def format StoreDispUpdateOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
329                             mem_flags = [], inst_flags = []) {{
330
331    # Add in the update code
332    memacc_code += 'Ra = EA;'
333
334    # Generate the class
335    (header_output, decoder_output, decode_block, exec_output) = \
336        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
337                      base_class = 'MemDispOp',
338                      exec_template_base = 'Store')
339}};
340