mem.isa revision 6307:067515d22824
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        newSuffix = "_%s_P%dU%dB%dW%d" % (suffix, p, u, b, w)
280        if b == 1:
281            mnem += "b"
282        return LoadStoreBase(mnem, mnem.capitalize() + newSuffix,
283                ea_code, code, mem_flags = [], inst_flags = [],
284                base_class = 'Memory' + suffix,
285                exec_template_base = type.capitalize())
286
287    def buildMode3Inst(p, u, i, w, type, code, mnem):
288        op = ("-", "+")[u]
289        offset = ("%s Rm", "%s hilo")[i] % op
290        ea_code = "EA = Rn %s;" % ("", offset)[p]
291        if p == 0 or w == 1:
292            code += "Rn = Rn %s;" % offset
293        newSuffix = "_P%dU%dI%dW%d" % (p, u, i, w)
294        suffix = ("Reg", "Hilo")[i]
295        return LoadStoreBase(mnem, mnem.capitalize() + newSuffix,
296                ea_code, code, mem_flags = [], inst_flags = [],
297                base_class = 'Memory' + suffix,
298                exec_template_base = type.capitalize())
299}};
300
301def format AddrMode2(suffix, offset) {{
302    header_output = decoder_output = exec_output = ""
303    decode_block = "switch(PUBWL) {\n"
304
305    # Loop over all the values of p, u, b, w and l and build instructions and
306    # a decode block for them.
307    for p in (0, 1):
308        for u in (0, 1):
309            for b in (0, 1):
310                for w in (0, 1):
311                    for l in (0, 1):
312                        (new_header_output,
313                         new_decoder_output,
314                         new_decode_block,
315                         new_exec_output) = buildMode2Inst(p, u, b, w, l,
316                                                           suffix, offset)
317                        header_output += new_header_output
318                        decoder_output += new_decoder_output
319                        exec_output += new_exec_output
320                        decode_block += '''
321                            case %#x:
322                              {%s}
323                              break;
324                        ''' % (buildPUBWLCase(p,u,b,w,l), new_decode_block)
325    decode_block += '''
326        default:
327          return new Unknown(machInst);
328        break;
329    }'''
330}};
331
332def format AddrMode3(l0Type, l0Code, l1Type, l1Code) {{
333    l0Code = ArmGenericCodeSubs(l0Code);
334    l1Code = ArmGenericCodeSubs(l1Code);
335
336    header_output = decoder_output = exec_output = ""
337    decode_block = "switch(PUBWL) {\n"
338    (l0Mnem, l1Mnem) = name.split("_");
339
340    # Loop over all the values of p, u, i, w and l and build instructions and
341    # a decode block for them.
342    for (l, type, code, mnem) in ((0, l0Type, l0Code, l0Mnem),
343                                  (1, l1Type, l1Code, l1Mnem)):
344        for p in (0, 1):
345            wset = (0, 1)
346            if (p == 0):
347                wset = (0,)
348            for u in (0, 1):
349                for i in (0, 1):
350                    for w in wset:
351                        (new_header_output,
352                         new_decoder_output,
353                         new_decode_block,
354                         new_exec_output) = buildMode3Inst(p, u, i, w,
355                                                           type, code, mnem)
356                        header_output += new_header_output
357                        decoder_output += new_decoder_output
358                        exec_output += new_exec_output
359                        decode_block += '''
360                            case %#x:
361                              {%s}
362                              break;
363                        ''' % (buildPUBWLCase(p,u,i,w,l), new_decode_block)
364
365    decode_block += '''
366        default:
367          return new Unknown(machInst);
368        break;
369    }'''
370}};
371
372def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
373                     mem_flags = [], inst_flags = []) {{
374    ea_code = ArmGenericCodeSubs(ea_code)
375    memacc_code = ArmGenericCodeSubs(memacc_code)
376    (header_output, decoder_output, decode_block, exec_output) = \
377        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
378                      decode_template = BasicDecode,
379                      exec_template_base = 'Load')
380}};
381
382def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
383                     mem_flags = [], inst_flags = []) {{
384    ea_code = ArmGenericCodeSubs(ea_code)
385    memacc_code = ArmGenericCodeSubs(memacc_code)
386    (header_output, decoder_output, decode_block, exec_output) = \
387        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
388                      exec_template_base = 'Store')
389}};
390
391