mem.isa revision 6301
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_dest_decl)s;
358
359        if (%(predicate_test)s)
360        {
361            if (fault == NoFault) {
362                %(op_wb)s;
363            }
364        }
365
366        return fault;
367    }
368}};
369
370def template StoreCondCompleteAcc {{
371    Fault %(class_name)s::completeAcc(PacketPtr pkt,
372                                      %(CPU_exec_context)s *xc,
373                                      Trace::InstRecord *traceData) const
374    {
375        Fault fault = NoFault;
376
377        %(op_dest_decl)s;
378
379        if (%(predicate_test)s)
380        {
381            if (fault == NoFault) {
382                %(op_wb)s;
383            }
384        }
385
386        return fault;
387    }
388}};
389
390
391def template MiscMemAccExecute {{
392    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
393                                          Trace::InstRecord *traceData) const
394    {
395        Addr EA;
396        Fault fault = NoFault;
397
398        %(op_decl)s;
399        %(op_rd)s;
400
401        if (%(predicate_test)s)
402        {
403            EA = xc->getEA();
404
405            if (fault == NoFault) {
406                %(memacc_code)s;
407            }
408        }
409
410        return NoFault;
411    }
412}};
413
414def template MiscExecute {{
415    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
416                                  Trace::InstRecord *traceData) const
417    {
418        Addr EA;
419        Fault fault = NoFault;
420
421        %(op_decl)s;
422        %(op_rd)s;
423        %(ea_code)s;
424
425        if (%(predicate_test)s)
426        {
427            if (fault == NoFault) {
428                %(memacc_code)s;
429            }
430        }
431
432        return NoFault;
433    }
434}};
435
436def template MiscInitiateAcc {{
437    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
438                                      Trace::InstRecord *traceData) const
439    {
440        panic("Misc instruction does not support split access method!");
441        return NoFault;
442    }
443}};
444
445
446def template MiscCompleteAcc {{
447    Fault %(class_name)s::completeAcc(PacketPtr pkt,
448                                      %(CPU_exec_context)s *xc,
449                                      Trace::InstRecord *traceData) const
450    {
451        panic("Misc instruction does not support split access method!");
452
453        return NoFault;
454    }
455}};
456
457let {{
458    def buildPUBWLCase(p, u, b, w, l):
459        return (p << 4) + (u << 3) + (b << 2) + (w << 1) + (l << 0)
460
461    def buildMode3Inst(p, u, i, w, type, code, mnem):
462        op = ("-", "+")[u]
463        offset = ("%s Rm", "%s hilo")[i] % op
464        ea_code = "EA = Rn %s;" % ("", offset)[p]
465        if p == 0 or w == 1:
466            code += "Rn = Rn %s;" % offset
467        suffix = "_P%dU%dI%dW%d" % (p, u, i, w)
468        return LoadStoreBase(mnem, mnem.capitalize() + suffix,
469                ea_code, code, mem_flags = [], inst_flags = [],
470                exec_template_base = type.capitalize())
471}};
472
473def format AddrMode3(l0Type, l0Code, l1Type, l1Code) {{
474    l0Code = ArmGenericCodeSubs(l0Code);
475    l1Code = ArmGenericCodeSubs(l1Code);
476
477    header_output = decoder_output = exec_output = ""
478    decode_block = "switch(PUBWL) {\n"
479    (l0Mnem, l1Mnem) = name.split("_");
480
481    # Loop over all the values of p, u, i, w and l and build instructions and
482    # a decode block for them.
483    for (l, type, code, mnem) in ((0, l0Type, l0Code, l0Mnem),
484                                  (1, l1Type, l1Code, l1Mnem)):
485        for p in (0, 1):
486            wset = (0, 1)
487            if (p == 0):
488                wset = (0,)
489            for u in (0, 1):
490                for i in (0, 1):
491                    for w in wset:
492                        (new_header_output,
493                         new_decoder_output,
494                         new_decode_block,
495                         new_exec_output) = buildMode3Inst(p, u, i, w,
496                                                           type, code, mnem)
497                        header_output += new_header_output
498                        decoder_output += new_decoder_output
499                        exec_output += new_exec_output
500                        decode_block += '''
501                            case %#x:
502                              {%s}
503                              break;
504                        ''' % (buildPUBWLCase(p,u,i,w,l), new_decode_block)
505
506    decode_block += '''
507        default:
508          return new Unknown(machInst);
509        break;
510    }'''
511}};
512
513def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
514                     mem_flags = [], inst_flags = []) {{
515    ea_code = ArmGenericCodeSubs(ea_code)
516    memacc_code = ArmGenericCodeSubs(memacc_code)
517    (header_output, decoder_output, decode_block, exec_output) = \
518        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
519                      decode_template = BasicDecode,
520                      exec_template_base = 'Load')
521}};
522
523def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
524                     mem_flags = [], inst_flags = []) {{
525    ea_code = ArmGenericCodeSubs(ea_code)
526    memacc_code = ArmGenericCodeSubs(memacc_code)
527    (header_output, decoder_output, decode_block, exec_output) = \
528        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
529                      exec_template_base = 'Store')
530}};
531
532