mem.isa revision 6302
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      protected:
43
44        /**
45         * "Fake" effective address computation class for "%(mnemonic)s".
46         */
47        class EAComp : public %(base_class)s
48        {
49          public:
50            /// Constructor
51            EAComp(ExtMachInst machInst);
52
53            %(BasicExecDeclare)s
54        };
55
56        /**
57         * "Fake" memory access instruction class for "%(mnemonic)s".
58         */
59        class MemAcc : public %(base_class)s
60        {
61          public:
62            /// Constructor
63            MemAcc(ExtMachInst machInst);
64
65            %(BasicExecDeclare)s
66        };
67
68      public:
69
70        /// Constructor.
71        %(class_name)s(ExtMachInst machInst);
72
73        %(BasicExecDeclare)s
74
75        %(InitiateAccDeclare)s
76
77        %(CompleteAccDeclare)s
78    };
79}};
80
81
82def template InitiateAccDeclare {{
83    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
84}};
85
86
87def template CompleteAccDeclare {{
88    Fault completeAcc(PacketPtr,  %(CPU_exec_context)s *, Trace::InstRecord *) const;
89}};
90
91
92def template EACompConstructor {{
93    inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst)
94        : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
95    {
96        %(constructor)s;
97    }
98}};
99
100
101def template MemAccConstructor {{
102    inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
103        : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
104    {
105        %(constructor)s;
106    }
107}};
108
109
110def template LoadStoreConstructor {{
111    inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
112         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
113                          new EAComp(machInst), new MemAcc(machInst))
114    {
115        %(constructor)s;
116    }
117}};
118
119
120def template EACompExecute {{
121    Fault
122    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
123                                   Trace::InstRecord *traceData) const
124    {
125        Addr EA;
126        Fault fault = NoFault;
127
128        %(op_decl)s;
129        %(op_rd)s;
130        %(ea_code)s;
131
132        if (%(predicate_test)s)
133        {
134            if (fault == NoFault) {
135                %(op_wb)s;
136                xc->setEA(EA);
137            }
138        }
139
140        return fault;
141    }
142}};
143
144def template LoadMemAccExecute {{
145    Fault
146    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
147                                   Trace::InstRecord *traceData) const
148    {
149        Addr EA;
150        Fault fault = NoFault;
151
152        %(op_decl)s;
153        %(op_rd)s;
154        EA = xc->getEA();
155
156        if (%(predicate_test)s)
157        {
158            if (fault == NoFault) {
159                fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
160                %(memacc_code)s;
161            }
162
163            if (fault == NoFault) {
164                %(op_wb)s;
165            }
166        }
167
168        return fault;
169    }
170}};
171
172
173def template LoadExecute {{
174    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
175                                  Trace::InstRecord *traceData) const
176    {
177        Addr EA;
178        Fault fault = NoFault;
179
180        %(op_decl)s;
181        %(op_rd)s;
182        %(ea_code)s;
183
184        if (%(predicate_test)s)
185        {
186            if (fault == NoFault) {
187                fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
188                %(memacc_code)s;
189            }
190
191            if (fault == NoFault) {
192                %(op_wb)s;
193            }
194        }
195
196        return fault;
197    }
198}};
199
200
201def template LoadInitiateAcc {{
202    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
203                                      Trace::InstRecord *traceData) const
204    {
205        Addr EA;
206        Fault fault = NoFault;
207
208        %(op_src_decl)s;
209        %(op_rd)s;
210        %(ea_code)s;
211
212        if (%(predicate_test)s)
213        {
214            if (fault == NoFault) {
215                fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
216            }
217        }
218
219        return fault;
220    }
221}};
222
223
224def template LoadCompleteAcc {{
225    Fault %(class_name)s::completeAcc(PacketPtr pkt,
226                                      %(CPU_exec_context)s *xc,
227                                      Trace::InstRecord *traceData) const
228    {
229        Fault fault = NoFault;
230
231        %(op_decl)s;
232        %(op_rd)s;
233
234        if (%(predicate_test)s)
235        {
236            // ARM instructions will not have a pkt if the predicate is false
237            Mem = pkt->get<typeof(Mem)>();
238
239            if (fault == NoFault) {
240                %(memacc_code)s;
241            }
242
243            if (fault == NoFault) {
244                %(op_wb)s;
245            }
246        }
247
248        return fault;
249    }
250}};
251
252
253def template StoreMemAccExecute {{
254    Fault
255    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
256                                   Trace::InstRecord *traceData) const
257    {
258        Addr EA;
259        Fault fault = NoFault;
260
261        %(op_decl)s;
262        %(op_rd)s;
263
264        if (%(predicate_test)s)
265        {
266            EA = xc->getEA();
267
268            if (fault == NoFault) {
269                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
270                                  memAccessFlags, NULL);
271                if (traceData) { traceData->setData(Mem); }
272            }
273
274            if (fault == NoFault) {
275                %(op_wb)s;
276            }
277        }
278
279        return fault;
280    }
281}};
282
283
284def template StoreExecute {{
285    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
286                                  Trace::InstRecord *traceData) const
287    {
288        Addr EA;
289        Fault fault = NoFault;
290
291        %(op_decl)s;
292        %(op_rd)s;
293        %(ea_code)s;
294
295        if (%(predicate_test)s)
296        {
297            if (fault == NoFault) {
298                %(memacc_code)s;
299            }
300
301            if (fault == NoFault) {
302                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
303                                  memAccessFlags, NULL);
304                if (traceData) { traceData->setData(Mem); }
305            }
306
307            if (fault == NoFault) {
308                %(op_wb)s;
309            }
310        }
311
312        return fault;
313    }
314}};
315
316def template StoreInitiateAcc {{
317    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
318                                      Trace::InstRecord *traceData) const
319    {
320        Addr EA;
321        Fault fault = NoFault;
322
323        %(op_decl)s;
324        %(op_rd)s;
325        %(ea_code)s;
326
327        if (%(predicate_test)s)
328        {
329            if (fault == NoFault) {
330                %(memacc_code)s;
331            }
332
333            if (fault == NoFault) {
334                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
335                                  memAccessFlags, NULL);
336                if (traceData) { traceData->setData(Mem); }
337            }
338
339            // Need to write back any potential address register update
340            if (fault == NoFault) {
341                %(op_wb)s;
342            }
343        }
344
345        return fault;
346    }
347}};
348
349
350def template StoreCompleteAcc {{
351    Fault %(class_name)s::completeAcc(PacketPtr pkt,
352                                      %(CPU_exec_context)s *xc,
353                                      Trace::InstRecord *traceData) const
354    {
355        Fault fault = NoFault;
356
357        %(op_decl)s;
358        %(op_rd)s;
359
360        if (%(predicate_test)s)
361        {
362            if (fault == NoFault) {
363                %(op_wb)s;
364            }
365        }
366
367        return fault;
368    }
369}};
370
371def template StoreCondCompleteAcc {{
372    Fault %(class_name)s::completeAcc(PacketPtr pkt,
373                                      %(CPU_exec_context)s *xc,
374                                      Trace::InstRecord *traceData) const
375    {
376        Fault fault = NoFault;
377
378        %(op_dest_decl)s;
379
380        if (%(predicate_test)s)
381        {
382            if (fault == NoFault) {
383                %(op_wb)s;
384            }
385        }
386
387        return fault;
388    }
389}};
390
391
392def template MiscMemAccExecute {{
393    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
394                                          Trace::InstRecord *traceData) const
395    {
396        Addr EA;
397        Fault fault = NoFault;
398
399        %(op_decl)s;
400        %(op_rd)s;
401
402        if (%(predicate_test)s)
403        {
404            EA = xc->getEA();
405
406            if (fault == NoFault) {
407                %(memacc_code)s;
408            }
409        }
410
411        return NoFault;
412    }
413}};
414
415def template MiscExecute {{
416    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
417                                  Trace::InstRecord *traceData) const
418    {
419        Addr EA;
420        Fault fault = NoFault;
421
422        %(op_decl)s;
423        %(op_rd)s;
424        %(ea_code)s;
425
426        if (%(predicate_test)s)
427        {
428            if (fault == NoFault) {
429                %(memacc_code)s;
430            }
431        }
432
433        return NoFault;
434    }
435}};
436
437def template MiscInitiateAcc {{
438    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
439                                      Trace::InstRecord *traceData) const
440    {
441        panic("Misc instruction does not support split access method!");
442        return NoFault;
443    }
444}};
445
446
447def template MiscCompleteAcc {{
448    Fault %(class_name)s::completeAcc(PacketPtr pkt,
449                                      %(CPU_exec_context)s *xc,
450                                      Trace::InstRecord *traceData) const
451    {
452        panic("Misc instruction does not support split access method!");
453
454        return NoFault;
455    }
456}};
457
458let {{
459    def buildPUBWLCase(p, u, b, w, l):
460        return (p << 4) + (u << 3) + (b << 2) + (w << 1) + (l << 0)
461
462    def buildMode3Inst(p, u, i, w, type, code, mnem):
463        op = ("-", "+")[u]
464        offset = ("%s Rm", "%s hilo")[i] % op
465        ea_code = "EA = Rn %s;" % ("", offset)[p]
466        if p == 0 or w == 1:
467            code += "Rn = Rn %s;" % offset
468        suffix = "_P%dU%dI%dW%d" % (p, u, i, w)
469        return LoadStoreBase(mnem, mnem.capitalize() + suffix,
470                ea_code, code, mem_flags = [], inst_flags = [],
471                exec_template_base = type.capitalize())
472}};
473
474def format AddrMode3(l0Type, l0Code, l1Type, l1Code) {{
475    l0Code = ArmGenericCodeSubs(l0Code);
476    l1Code = ArmGenericCodeSubs(l1Code);
477
478    header_output = decoder_output = exec_output = ""
479    decode_block = "switch(PUBWL) {\n"
480    (l0Mnem, l1Mnem) = name.split("_");
481
482    # Loop over all the values of p, u, i, w and l and build instructions and
483    # a decode block for them.
484    for (l, type, code, mnem) in ((0, l0Type, l0Code, l0Mnem),
485                                  (1, l1Type, l1Code, l1Mnem)):
486        for p in (0, 1):
487            wset = (0, 1)
488            if (p == 0):
489                wset = (0,)
490            for u in (0, 1):
491                for i in (0, 1):
492                    for w in wset:
493                        (new_header_output,
494                         new_decoder_output,
495                         new_decode_block,
496                         new_exec_output) = buildMode3Inst(p, u, i, w,
497                                                           type, code, mnem)
498                        header_output += new_header_output
499                        decoder_output += new_decoder_output
500                        exec_output += new_exec_output
501                        decode_block += '''
502                            case %#x:
503                              {%s}
504                              break;
505                        ''' % (buildPUBWLCase(p,u,i,w,l), new_decode_block)
506
507    decode_block += '''
508        default:
509          return new Unknown(machInst);
510        break;
511    }'''
512}};
513
514def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
515                     mem_flags = [], inst_flags = []) {{
516    ea_code = ArmGenericCodeSubs(ea_code)
517    memacc_code = ArmGenericCodeSubs(memacc_code)
518    (header_output, decoder_output, decode_block, exec_output) = \
519        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
520                      decode_template = BasicDecode,
521                      exec_template_base = 'Load')
522}};
523
524def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
525                     mem_flags = [], inst_flags = []) {{
526    ea_code = ArmGenericCodeSubs(ea_code)
527    memacc_code = ArmGenericCodeSubs(memacc_code)
528    (header_output, decoder_output, decode_block, exec_output) = \
529        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
530                      exec_template_base = 'Store')
531}};
532
533