mem.isa revision 6305
1// -*- mode:c++ -*-
2
3// Copyright (c) 2007-2008 The Florida State University
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: Stephen Hines
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 (%(predicate_test)s)
87        {
88            if (fault == NoFault) {
89                fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
90                %(memacc_code)s;
91            }
92
93            if (fault == NoFault) {
94                %(op_wb)s;
95            }
96        }
97
98        return fault;
99    }
100}};
101
102
103def template LoadInitiateAcc {{
104    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
105                                      Trace::InstRecord *traceData) const
106    {
107        Addr EA;
108        Fault fault = NoFault;
109
110        %(op_src_decl)s;
111        %(op_rd)s;
112        %(ea_code)s;
113
114        if (%(predicate_test)s)
115        {
116            if (fault == NoFault) {
117                fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
118            }
119        }
120
121        return fault;
122    }
123}};
124
125
126def template LoadCompleteAcc {{
127    Fault %(class_name)s::completeAcc(PacketPtr pkt,
128                                      %(CPU_exec_context)s *xc,
129                                      Trace::InstRecord *traceData) const
130    {
131        Fault fault = NoFault;
132
133        %(op_decl)s;
134        %(op_rd)s;
135
136        if (%(predicate_test)s)
137        {
138            // ARM instructions will not have a pkt if the predicate is false
139            Mem = pkt->get<typeof(Mem)>();
140
141            if (fault == NoFault) {
142                %(memacc_code)s;
143            }
144
145            if (fault == NoFault) {
146                %(op_wb)s;
147            }
148        }
149
150        return fault;
151    }
152}};
153
154
155def template StoreExecute {{
156    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
157                                  Trace::InstRecord *traceData) const
158    {
159        Addr EA;
160        Fault fault = NoFault;
161
162        %(op_decl)s;
163        %(op_rd)s;
164        %(ea_code)s;
165
166        if (%(predicate_test)s)
167        {
168            if (fault == NoFault) {
169                %(memacc_code)s;
170            }
171
172            if (fault == NoFault) {
173                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
174                                  memAccessFlags, NULL);
175                if (traceData) { traceData->setData(Mem); }
176            }
177
178            if (fault == NoFault) {
179                %(op_wb)s;
180            }
181        }
182
183        return fault;
184    }
185}};
186
187def template StoreInitiateAcc {{
188    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
189                                      Trace::InstRecord *traceData) const
190    {
191        Addr EA;
192        Fault fault = NoFault;
193
194        %(op_decl)s;
195        %(op_rd)s;
196        %(ea_code)s;
197
198        if (%(predicate_test)s)
199        {
200            if (fault == NoFault) {
201                %(memacc_code)s;
202            }
203
204            if (fault == NoFault) {
205                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
206                                  memAccessFlags, NULL);
207                if (traceData) { traceData->setData(Mem); }
208            }
209
210            // Need to write back any potential address register update
211            if (fault == NoFault) {
212                %(op_wb)s;
213            }
214        }
215
216        return fault;
217    }
218}};
219
220
221def template StoreCompleteAcc {{
222    Fault %(class_name)s::completeAcc(PacketPtr pkt,
223                                      %(CPU_exec_context)s *xc,
224                                      Trace::InstRecord *traceData) const
225    {
226        Fault fault = NoFault;
227
228        %(op_decl)s;
229        %(op_rd)s;
230
231        if (%(predicate_test)s)
232        {
233            if (fault == NoFault) {
234                %(op_wb)s;
235            }
236        }
237
238        return fault;
239    }
240}};
241
242def template StoreCondCompleteAcc {{
243    Fault %(class_name)s::completeAcc(PacketPtr pkt,
244                                      %(CPU_exec_context)s *xc,
245                                      Trace::InstRecord *traceData) const
246    {
247        Fault fault = NoFault;
248
249        %(op_dest_decl)s;
250
251        if (%(predicate_test)s)
252        {
253            if (fault == NoFault) {
254                %(op_wb)s;
255            }
256        }
257
258        return fault;
259    }
260}};
261
262let {{
263    def buildPUBWLCase(p, u, b, w, l):
264        return (p << 4) + (u << 3) + (b << 2) + (w << 1) + (l << 0)
265
266    def buildMode2Inst(p, u, b, w, l, suffix, offset):
267        mnem = ("str", "ldr")[l]
268        op = ("-", "+")[u]
269        offset = op + ArmGenericCodeSubs(offset);
270        mem = ("Mem", "Mem.ub")[b]
271        code = ("%s = Rd;", "Rd = %s;")[l] % mem
272        ea_code = "EA = Rn %s;" % ("", offset)[p]
273        if p == 0 or w == 1:
274            code += "Rn = Rn %s;" % offset
275        if p == 0 and w == 0:
276            # Here's where we'll tack on a flag to make this a usermode access.
277            mnem += "t"
278        type = ("Store", "Load")[l]
279        suffix = "_%s_P%dU%dB%dW%d" % (suffix, p, u, b, w)
280        if b == 1:
281            mnem += "b"
282        return LoadStoreBase(mnem, mnem.capitalize() + suffix,
283                ea_code, code, mem_flags = [], inst_flags = [],
284                exec_template_base = type.capitalize())
285
286    def buildMode3Inst(p, u, i, w, type, code, mnem):
287        op = ("-", "+")[u]
288        offset = ("%s Rm", "%s hilo")[i] % op
289        ea_code = "EA = Rn %s;" % ("", offset)[p]
290        if p == 0 or w == 1:
291            code += "Rn = Rn %s;" % offset
292        suffix = "_P%dU%dI%dW%d" % (p, u, i, w)
293        return LoadStoreBase(mnem, mnem.capitalize() + suffix,
294                ea_code, code, mem_flags = [], inst_flags = [],
295                exec_template_base = type.capitalize())
296}};
297
298def format AddrMode2(suffix, offset) {{
299    header_output = decoder_output = exec_output = ""
300    decode_block = "switch(PUBWL) {\n"
301
302    # Loop over all the values of p, u, b, w and l and build instructions and
303    # a decode block for them.
304    for p in (0, 1):
305        for u in (0, 1):
306            for b in (0, 1):
307                for w in (0, 1):
308                    for l in (0, 1):
309                        (new_header_output,
310                         new_decoder_output,
311                         new_decode_block,
312                         new_exec_output) = buildMode2Inst(p, u, b, w, l,
313                                                           suffix, offset)
314                        header_output += new_header_output
315                        decoder_output += new_decoder_output
316                        exec_output += new_exec_output
317                        decode_block += '''
318                            case %#x:
319                              {%s}
320                              break;
321                        ''' % (buildPUBWLCase(p,u,b,w,l), new_decode_block)
322    decode_block += '''
323        default:
324          return new Unknown(machInst);
325        break;
326    }'''
327}};
328
329def format AddrMode3(l0Type, l0Code, l1Type, l1Code) {{
330    l0Code = ArmGenericCodeSubs(l0Code);
331    l1Code = ArmGenericCodeSubs(l1Code);
332
333    header_output = decoder_output = exec_output = ""
334    decode_block = "switch(PUBWL) {\n"
335    (l0Mnem, l1Mnem) = name.split("_");
336
337    # Loop over all the values of p, u, i, w and l and build instructions and
338    # a decode block for them.
339    for (l, type, code, mnem) in ((0, l0Type, l0Code, l0Mnem),
340                                  (1, l1Type, l1Code, l1Mnem)):
341        for p in (0, 1):
342            wset = (0, 1)
343            if (p == 0):
344                wset = (0,)
345            for u in (0, 1):
346                for i in (0, 1):
347                    for w in wset:
348                        (new_header_output,
349                         new_decoder_output,
350                         new_decode_block,
351                         new_exec_output) = buildMode3Inst(p, u, i, w,
352                                                           type, code, mnem)
353                        header_output += new_header_output
354                        decoder_output += new_decoder_output
355                        exec_output += new_exec_output
356                        decode_block += '''
357                            case %#x:
358                              {%s}
359                              break;
360                        ''' % (buildPUBWLCase(p,u,i,w,l), new_decode_block)
361
362    decode_block += '''
363        default:
364          return new Unknown(machInst);
365        break;
366    }'''
367}};
368
369def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
370                     mem_flags = [], inst_flags = []) {{
371    ea_code = ArmGenericCodeSubs(ea_code)
372    memacc_code = ArmGenericCodeSubs(memacc_code)
373    (header_output, decoder_output, decode_block, exec_output) = \
374        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
375                      decode_template = BasicDecode,
376                      exec_template_base = 'Load')
377}};
378
379def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
380                     mem_flags = [], inst_flags = []) {{
381    ea_code = ArmGenericCodeSubs(ea_code)
382    memacc_code = ArmGenericCodeSubs(memacc_code)
383    (header_output, decoder_output, decode_block, exec_output) = \
384        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
385                      exec_template_base = 'Store')
386}};
387
388