mem.isa revision 6691
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    inline %(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)s *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 = xc->read(EA, (uint%(mem_acc_size)d_t&)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)s *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 = xc->read(EA, (uint%(mem_acc_size)d_t &)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)s *xc,
124                                      Trace::InstRecord *traceData) const
125    {
126        Addr EA;
127        Fault fault = NoFault;
128        uint%(mem_acc_size)d_t val;
129
130        %(op_decl)s;
131        %(op_rd)s;
132
133        EA = xc->getEA();
134
135        val = pkt->get<uint%(mem_acc_size)d_t>();
136        *((uint%(mem_acc_size)d_t*)&Mem) = val;
137
138        if (fault == NoFault) {
139            %(memacc_code)s;
140        }
141
142        if (fault == NoFault) {
143          %(op_wb)s;
144        }
145
146        return fault;
147    }
148}};
149
150
151def template StoreExecute {{
152    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
153                                  Trace::InstRecord *traceData) const
154    {
155        Addr EA;
156        Fault fault = NoFault;
157
158        %(op_decl)s;
159        %(op_rd)s;
160        %(ea_code)s;
161
162        if (fault == NoFault) {
163            %(memacc_code)s;
164        }
165
166        if (fault == NoFault) {
167            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
168                              memAccessFlags, NULL);
169            if (traceData) { traceData->setData(Mem); }
170        }
171
172        if (fault == NoFault) {
173            %(op_wb)s;
174        }
175
176        return fault;
177    }
178}};
179
180
181def template StoreInitiateAcc {{
182    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
183                                      Trace::InstRecord *traceData) const
184    {
185        Addr EA;
186        Fault fault = NoFault;
187
188        %(op_decl)s;
189        %(op_rd)s;
190        %(ea_code)s;
191
192        if (fault == NoFault) {
193            %(memacc_code)s;
194        }
195
196        if (fault == NoFault) {
197            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
198                              memAccessFlags, NULL);
199            if (traceData) { traceData->setData(Mem); }
200        }
201
202        // Need to write back any potential address register update
203        if (fault == NoFault) {
204            %(op_wb)s;
205        }
206
207        return fault;
208    }
209}};
210
211
212def template StoreCompleteAcc {{
213    Fault %(class_name)s::completeAcc(PacketPtr pkt,
214                                      %(CPU_exec_context)s *xc,
215                                      Trace::InstRecord *traceData) const
216    {
217        Fault fault = NoFault;
218
219        %(op_dest_decl)s;
220
221        if (fault == NoFault) {
222          %(op_wb)s;
223        }
224
225        return fault;
226    }
227}};
228
229
230// The generic memory operation generator. This is called when two versions
231// of an instruction are needed - when Ra == 0 and otherwise. This is so
232// that instructions can use the value 0 when Ra == 0 but avoid having a
233// dependence on Ra.
234let {{
235
236def GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0, base,
237             load_or_store, mem_flags = [], inst_flags = []):
238
239    # First the version where Ra is non-zero
240    (header_output, decoder_output, decode_block, exec_output) = \
241        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
242                      base_class = base,
243                      decode_template = CheckRaDecode,
244                      exec_template_base = load_or_store)
245
246    # Now another version where Ra == 0
247    (header_output_ra0, decoder_output_ra0, _, exec_output_ra0) = \
248        LoadStoreBase(name, Name + 'RaZero', ea_code_ra0, memacc_code,
249                      mem_flags, inst_flags,
250                      base_class = base,
251                      exec_template_base = load_or_store)
252
253    # Finally, add to the other outputs
254    header_output += header_output_ra0
255    decoder_output += decoder_output_ra0
256    exec_output += exec_output_ra0
257    return (header_output, decoder_output, decode_block, exec_output)
258
259}};
260
261
262def format LoadIndexOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
263                       ea_code_ra0 = {{ EA = Rb; }},
264                       mem_flags = [], inst_flags = []) {{
265    (header_output, decoder_output, decode_block, exec_output) = \
266        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
267                 'MemOp', 'Load', mem_flags, inst_flags)
268}};
269
270
271def format StoreIndexOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
272                        ea_code_ra0 = {{ EA = Rb; }},
273                        mem_flags = [], inst_flags = []) {{
274    (header_output, decoder_output, decode_block, exec_output) = \
275        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
276                 'MemOp', 'Store', mem_flags, inst_flags)
277}};
278
279
280def format LoadIndexUpdateOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
281                             mem_flags = [], inst_flags = []) {{
282
283    # Add in the update code
284    memacc_code += 'Ra = EA;'
285
286    # Generate the class
287    (header_output, decoder_output, decode_block, exec_output) = \
288        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
289                      base_class = 'MemOp',
290                      exec_template_base = 'Load')
291}};
292
293
294def format StoreIndexUpdateOp(memacc_code, ea_code = {{ EA = Ra + Rb; }},
295                              mem_flags = [], inst_flags = []) {{
296
297    # Add in the update code
298    memacc_code += 'Ra = EA;'
299
300    # Generate the class
301    (header_output, decoder_output, decode_block, exec_output) = \
302        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
303                      base_class = 'MemOp',
304                      exec_template_base = 'Store')
305}};
306
307
308def format LoadDispOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
309                      ea_code_ra0 = {{ EA = disp; }},
310                      mem_flags = [], inst_flags = []) {{
311    (header_output, decoder_output, decode_block, exec_output) = \
312        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
313                 'MemDispOp', 'Load', mem_flags, inst_flags)
314}};
315
316
317def format StoreDispOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
318                       ea_code_ra0 = {{ EA = disp; }},
319                       mem_flags = [], inst_flags = []) {{
320    (header_output, decoder_output, decode_block, exec_output) = \
321        GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0,
322                 'MemDispOp', 'Store', mem_flags, inst_flags)
323}};
324
325
326def format LoadDispUpdateOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
327                            mem_flags = [], inst_flags = []) {{
328
329    # Add in the update code
330    memacc_code += 'Ra = EA;'
331
332    # Generate the class
333    (header_output, decoder_output, decode_block, exec_output) = \
334        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
335                      base_class = 'MemDispOp',
336                      exec_template_base = 'Load')
337}};
338
339
340def format StoreDispUpdateOp(memacc_code, ea_code = {{ EA = Ra + disp; }},
341                             mem_flags = [], inst_flags = []) {{
342
343    # Add in the update code
344    memacc_code += 'Ra = EA;'
345
346    # Generate the class
347    (header_output, decoder_output, decode_block, exec_output) = \
348        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
349                      base_class = 'MemDispOp',
350                      exec_template_base = 'Store')
351}};
352