mem.isa revision 7045:e21fe6a62b1c
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            }
176
177            if (fault == NoFault) {
178                %(op_wb)s;
179            }
180        }
181
182        return fault;
183    }
184}};
185
186def template StoreInitiateAcc {{
187    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
188                                      Trace::InstRecord *traceData) const
189    {
190        Addr EA;
191        Fault fault = NoFault;
192
193        %(op_decl)s;
194        %(op_rd)s;
195        %(ea_code)s;
196
197        if (%(predicate_test)s)
198        {
199            if (fault == NoFault) {
200                %(memacc_code)s;
201            }
202
203            if (fault == NoFault) {
204                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
205                                  memAccessFlags, NULL);
206            }
207
208            // Need to write back any potential address register update
209            if (fault == NoFault) {
210                %(op_wb)s;
211            }
212        }
213
214        return fault;
215    }
216}};
217
218
219def template StoreCompleteAcc {{
220    Fault %(class_name)s::completeAcc(PacketPtr pkt,
221                                      %(CPU_exec_context)s *xc,
222                                      Trace::InstRecord *traceData) const
223    {
224        Fault fault = NoFault;
225
226        %(op_decl)s;
227        %(op_rd)s;
228
229        if (%(predicate_test)s)
230        {
231            if (fault == NoFault) {
232                %(op_wb)s;
233            }
234        }
235
236        return fault;
237    }
238}};
239
240def template StoreCondCompleteAcc {{
241    Fault %(class_name)s::completeAcc(PacketPtr pkt,
242                                      %(CPU_exec_context)s *xc,
243                                      Trace::InstRecord *traceData) const
244    {
245        Fault fault = NoFault;
246
247        %(op_dest_decl)s;
248
249        if (%(predicate_test)s)
250        {
251            if (fault == NoFault) {
252                %(op_wb)s;
253            }
254        }
255
256        return fault;
257    }
258}};
259
260let {{
261    def buildPUBWLCase(p, u, b, w, l):
262        return (p << 4) + (u << 3) + (b << 2) + (w << 1) + (l << 0)
263
264    def buildMode2Inst(p, u, b, w, l, suffix, offset):
265        mnem = ("str", "ldr")[l]
266        op = ("-", "+")[u]
267        offset = op + ArmGenericCodeSubs(offset);
268        mem = ("Mem", "Mem.ub")[b]
269        code = ("%s = Rd;", "Rd = %s;")[l] % mem
270        ea_code = "EA = Rn %s;" % ("", offset)[p]
271        if p == 0 or w == 1:
272            code += "Rn = Rn %s;" % offset
273        if p == 0 and w == 0:
274            # Here's where we'll tack on a flag to make this a usermode access.
275            mnem += "t"
276        type = ("Store", "Load")[l]
277        newSuffix = "_%s_P%dU%dB%dW%d" % (suffix, p, u, b, w)
278        if b == 1:
279            mnem += "b"
280        return LoadStoreBase(mnem, mnem.capitalize() + newSuffix,
281                ea_code, code, mem_flags = [], inst_flags = [],
282                base_class = 'Memory' + suffix,
283                exec_template_base = type.capitalize())
284
285    def buildMode3Inst(p, u, i, w, type, code, mnem):
286        op = ("-", "+")[u]
287        offset = ("%s Rm", "%s hilo")[i] % op
288        ea_code = "EA = Rn %s;" % ("", offset)[p]
289        if p == 0 or w == 1:
290            code += "Rn = Rn %s;" % offset
291        newSuffix = "_P%dU%dI%dW%d" % (p, u, i, w)
292        suffix = ("Reg", "Hilo")[i]
293        return LoadStoreBase(mnem, mnem.capitalize() + newSuffix,
294                ea_code, code, mem_flags = [], inst_flags = [],
295                base_class = 'Memory' + suffix,
296                exec_template_base = type.capitalize())
297}};
298
299def format AddrMode2(suffix, offset) {{
300    header_output = decoder_output = exec_output = ""
301    decode_block = "switch(PUBWL) {\n"
302
303    # Loop over all the values of p, u, b, w and l and build instructions and
304    # a decode block for them.
305    for p in (0, 1):
306        for u in (0, 1):
307            for b in (0, 1):
308                for w in (0, 1):
309                    for l in (0, 1):
310                        (new_header_output,
311                         new_decoder_output,
312                         new_decode_block,
313                         new_exec_output) = buildMode2Inst(p, u, b, w, l,
314                                                           suffix, offset)
315                        header_output += new_header_output
316                        decoder_output += new_decoder_output
317                        exec_output += new_exec_output
318                        decode_block += '''
319                            case %#x:
320                              {%s}
321                              break;
322                        ''' % (buildPUBWLCase(p,u,b,w,l), new_decode_block)
323    decode_block += '''
324        default:
325          return new Unknown(machInst);
326        break;
327    }'''
328}};
329
330def format AddrMode3(l0Type, l0Code, l1Type, l1Code) {{
331    l0Code = ArmGenericCodeSubs(l0Code);
332    l1Code = ArmGenericCodeSubs(l1Code);
333
334    header_output = decoder_output = exec_output = ""
335    decode_block = "switch(PUBWL) {\n"
336    (l0Mnem, l1Mnem) = name.split("_");
337
338    # Loop over all the values of p, u, i, w and l and build instructions and
339    # a decode block for them.
340    for (l, type, code, mnem) in ((0, l0Type, l0Code, l0Mnem),
341                                  (1, l1Type, l1Code, l1Mnem)):
342        for p in (0, 1):
343            wset = (0, 1)
344            if (p == 0):
345                wset = (0,)
346            for u in (0, 1):
347                for i in (0, 1):
348                    for w in wset:
349                        (new_header_output,
350                         new_decoder_output,
351                         new_decode_block,
352                         new_exec_output) = buildMode3Inst(p, u, i, w,
353                                                           type, code, mnem)
354                        header_output += new_header_output
355                        decoder_output += new_decoder_output
356                        exec_output += new_exec_output
357                        decode_block += '''
358                            case %#x:
359                              {%s}
360                              break;
361                        ''' % (buildPUBWLCase(p,u,i,w,l), new_decode_block)
362
363    decode_block += '''
364        default:
365          return new Unknown(machInst);
366        break;
367    }'''
368}};
369
370def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
371                     mem_flags = [], inst_flags = []) {{
372    ea_code = ArmGenericCodeSubs(ea_code)
373    memacc_code = ArmGenericCodeSubs(memacc_code)
374    (header_output, decoder_output, decode_block, exec_output) = \
375        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
376                      decode_template = BasicDecode,
377                      exec_template_base = 'Load')
378}};
379
380def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
381                     mem_flags = [], inst_flags = []) {{
382    ea_code = ArmGenericCodeSubs(ea_code)
383    memacc_code = ArmGenericCodeSubs(memacc_code)
384    (header_output, decoder_output, decode_block, exec_output) = \
385        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
386                      exec_template_base = 'Store')
387}};
388
389