blockmem.isa revision 3956:4f306596983e
1// Copyright (c) 2006 The Regents of The University of Michigan
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met: redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer;
8// redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution;
11// neither the name of the copyright holders nor the names of its
12// contributors may be used to endorse or promote products derived from
13// this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26//
27// Authors: Ali Saidi
28//          Gabe Black
29
30////////////////////////////////////////////////////////////////////
31//
32// Block Memory instructions
33//
34
35output header {{
36
37        class BlockMem : public SparcMacroInst
38        {
39          protected:
40
41            // Constructor
42            // We make the assumption that all block memory operations
43            // Will take 8 instructions to execute
44            BlockMem(const char *mnem, ExtMachInst _machInst) :
45                SparcMacroInst(mnem, _machInst, No_OpClass, 8)
46            {}
47        };
48
49        class BlockMemImm : public BlockMem
50        {
51          protected:
52
53            // Constructor
54            BlockMemImm(const char *mnem, ExtMachInst _machInst) :
55                BlockMem(mnem, _machInst)
56            {}
57        };
58
59        class BlockMemMicro : public SparcMicroInst
60        {
61          protected:
62
63            // Constructor
64            BlockMemMicro(const char *mnem, ExtMachInst _machInst,
65                    OpClass __opClass, int8_t _offset) :
66                SparcMicroInst(mnem, _machInst, __opClass),
67                offset(_offset)
68            {}
69
70            std::string generateDisassembly(Addr pc,
71                const SymbolTable *symtab) const;
72
73            const int8_t offset;
74        };
75
76        class BlockMemImmMicro : public BlockMemMicro
77        {
78          protected:
79
80            // Constructor
81            BlockMemImmMicro(const char *mnem, ExtMachInst _machInst,
82                    OpClass __opClass, int8_t _offset) :
83                BlockMemMicro(mnem, _machInst, __opClass, _offset),
84                imm(sext<13>(SIMM13))
85            {}
86
87            std::string generateDisassembly(Addr pc,
88                const SymbolTable *symtab) const;
89
90            const int32_t imm;
91        };
92}};
93
94output header {{
95
96        class TwinMem : public SparcMacroInst
97        {
98          protected:
99
100            // Constructor
101            // We make the assumption that all block memory operations
102            // Will take 8 instructions to execute
103            TwinMem(const char *mnem, ExtMachInst _machInst) :
104                SparcMacroInst(mnem, _machInst, No_OpClass, 8)
105            {}
106        };
107
108        class TwinMemImm : public BlockMem
109        {
110          protected:
111
112            // Constructor
113            TwinMemImm(const char *mnem, ExtMachInst _machInst) :
114                BlockMem(mnem, _machInst)
115            {}
116        };
117
118        class TwinMemMicro : public SparcMicroInst
119        {
120          protected:
121
122            // Constructor
123            TwinMemMicro(const char *mnem, ExtMachInst _machInst,
124                    OpClass __opClass, int8_t _offset) :
125                SparcMicroInst(mnem, _machInst, __opClass),
126                offset(_offset)
127            {}
128
129            std::string generateDisassembly(Addr pc,
130                const SymbolTable *symtab) const;
131
132            const int8_t offset;
133        };
134
135        class TwinMemImmMicro : public BlockMemMicro
136        {
137          protected:
138
139            // Constructor
140            TwinMemImmMicro(const char *mnem, ExtMachInst _machInst,
141                    OpClass __opClass, int8_t _offset) :
142                BlockMemMicro(mnem, _machInst, __opClass, _offset),
143                imm(sext<13>(SIMM13))
144            {}
145
146            std::string generateDisassembly(Addr pc,
147                const SymbolTable *symtab) const;
148
149            const int32_t imm;
150        };
151}};
152
153output decoder {{
154        std::string BlockMemMicro::generateDisassembly(Addr pc,
155                const SymbolTable *symtab) const
156        {
157            std::stringstream response;
158            bool load = flags[IsLoad];
159            bool save = flags[IsStore];
160
161            printMnemonic(response, mnemonic);
162            if(save)
163            {
164                printReg(response, _srcRegIdx[0]);
165                ccprintf(response, ", ");
166            }
167            ccprintf(response, "[ ");
168            printReg(response, _srcRegIdx[!save ? 0 : 1]);
169            ccprintf(response, " + ");
170            printReg(response, _srcRegIdx[!save ? 1 : 2]);
171            ccprintf(response, " ]");
172            if(load)
173            {
174                ccprintf(response, ", ");
175                printReg(response, _destRegIdx[0]);
176            }
177
178            return response.str();
179        }
180
181        std::string BlockMemImmMicro::generateDisassembly(Addr pc,
182                const SymbolTable *symtab) const
183        {
184            std::stringstream response;
185            bool load = flags[IsLoad];
186            bool save = flags[IsStore];
187
188            printMnemonic(response, mnemonic);
189            if(save)
190            {
191                printReg(response, _srcRegIdx[1]);
192                ccprintf(response, ", ");
193            }
194            ccprintf(response, "[ ");
195            printReg(response, _srcRegIdx[0]);
196            if(imm >= 0)
197                ccprintf(response, " + 0x%x ]", imm);
198            else
199                ccprintf(response, " + -0x%x ]", -imm);
200            if(load)
201            {
202                ccprintf(response, ", ");
203                printReg(response, _destRegIdx[0]);
204            }
205
206            return response.str();
207        }
208
209}};
210
211output decoder {{
212        std::string TwinMemMicro::generateDisassembly(Addr pc,
213                const SymbolTable *symtab) const
214        {
215            std::stringstream response;
216            bool load = flags[IsLoad];
217            bool save = flags[IsStore];
218
219            printMnemonic(response, mnemonic);
220            if(save)
221            {
222                printReg(response, _srcRegIdx[0]);
223                ccprintf(response, ", ");
224            }
225            ccprintf(response, "[ ");
226            printReg(response, _srcRegIdx[!save ? 0 : 1]);
227            ccprintf(response, " + ");
228            printReg(response, _srcRegIdx[!save ? 1 : 2]);
229            ccprintf(response, " ]");
230            if(load)
231            {
232                ccprintf(response, ", ");
233                printReg(response, _destRegIdx[0]);
234            }
235
236            return response.str();
237        }
238
239        std::string TwinMemImmMicro::generateDisassembly(Addr pc,
240                const SymbolTable *symtab) const
241        {
242            std::stringstream response;
243            bool load = flags[IsLoad];
244            bool save = flags[IsStore];
245
246            printMnemonic(response, mnemonic);
247            if(save)
248            {
249                printReg(response, _srcRegIdx[1]);
250                ccprintf(response, ", ");
251            }
252            ccprintf(response, "[ ");
253            printReg(response, _srcRegIdx[0]);
254            if(imm >= 0)
255                ccprintf(response, " + 0x%x ]", imm);
256            else
257                ccprintf(response, " + -0x%x ]", -imm);
258            if(load)
259            {
260                ccprintf(response, ", ");
261                printReg(response, _destRegIdx[0]);
262            }
263
264            return response.str();
265        }
266
267}};
268
269def template BlockMemDeclare {{
270        /**
271         * Static instruction class for a block memory operation
272         */
273        class %(class_name)s : public %(base_class)s
274        {
275          public:
276            //Constructor
277            %(class_name)s(ExtMachInst machInst);
278
279          protected:
280            class %(class_name)s_0 : public %(base_class)sMicro
281            {
282              public:
283                //Constructor
284                %(class_name)s_0(ExtMachInst machInst);
285                %(BasicExecDeclare)s
286                %(InitiateAccDeclare)s
287                %(CompleteAccDeclare)s
288            };
289
290            class %(class_name)s_1 : public %(base_class)sMicro
291            {
292              public:
293                //Constructor
294                %(class_name)s_1(ExtMachInst machInst);
295                %(BasicExecDeclare)s
296                %(InitiateAccDeclare)s
297                %(CompleteAccDeclare)s
298            };
299
300            class %(class_name)s_2 : public %(base_class)sMicro
301            {
302              public:
303                //Constructor
304                %(class_name)s_2(ExtMachInst machInst);
305                %(BasicExecDeclare)s
306                %(InitiateAccDeclare)s
307                %(CompleteAccDeclare)s
308            };
309
310            class %(class_name)s_3 : public %(base_class)sMicro
311            {
312              public:
313                //Constructor
314                %(class_name)s_3(ExtMachInst machInst);
315                %(BasicExecDeclare)s
316                %(InitiateAccDeclare)s
317                %(CompleteAccDeclare)s
318            };
319
320            class %(class_name)s_4 : public %(base_class)sMicro
321            {
322              public:
323                //Constructor
324                %(class_name)s_4(ExtMachInst machInst);
325                %(BasicExecDeclare)s
326                %(InitiateAccDeclare)s
327                %(CompleteAccDeclare)s
328            };
329
330            class %(class_name)s_5 : public %(base_class)sMicro
331            {
332              public:
333                //Constructor
334                %(class_name)s_5(ExtMachInst machInst);
335                %(BasicExecDeclare)s
336                %(InitiateAccDeclare)s
337                %(CompleteAccDeclare)s
338            };
339
340            class %(class_name)s_6 : public %(base_class)sMicro
341            {
342              public:
343                //Constructor
344                %(class_name)s_6(ExtMachInst machInst);
345                %(BasicExecDeclare)s
346                %(InitiateAccDeclare)s
347                %(CompleteAccDeclare)s
348            };
349
350            class %(class_name)s_7 : public %(base_class)sMicro
351            {
352              public:
353                //Constructor
354                %(class_name)s_7(ExtMachInst machInst);
355                %(BasicExecDeclare)s
356                %(InitiateAccDeclare)s
357                %(CompleteAccDeclare)s
358            };
359        };
360}};
361
362def template TwinMemDeclare {{
363        /**
364         * Static instruction class for a block memory operation
365         */
366        class %(class_name)s : public %(base_class)s
367        {
368          public:
369            //Constructor
370            %(class_name)s(ExtMachInst machInst);
371
372          protected:
373            class %(class_name)s_0 : public %(base_class)sMicro
374            {
375              public:
376                //Constructor
377                %(class_name)s_0(ExtMachInst machInst);
378                %(BasicExecDeclare)s
379                %(InitiateAccDeclare)s
380                %(CompleteAccDeclare)s
381            };
382
383            class %(class_name)s_1 : public %(base_class)sMicro
384            {
385              public:
386                //Constructor
387                %(class_name)s_1(ExtMachInst machInst);
388                %(BasicExecDeclare)s
389                %(InitiateAccDeclare)s
390                %(CompleteAccDeclare)s
391            };
392        };
393}};
394
395// Basic instruction class constructor template.
396def template BlockMemConstructor {{
397        inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
398            : %(base_class)s("%(mnemonic)s", machInst)
399        {
400            %(constructor)s;
401            microOps[0] = new %(class_name)s_0(machInst);
402            microOps[1] = new %(class_name)s_1(machInst);
403            microOps[2] = new %(class_name)s_2(machInst);
404            microOps[3] = new %(class_name)s_3(machInst);
405            microOps[4] = new %(class_name)s_4(machInst);
406            microOps[5] = new %(class_name)s_5(machInst);
407            microOps[6] = new %(class_name)s_6(machInst);
408            microOps[7] = new %(class_name)s_7(machInst);
409        }
410}};
411
412// Basic instruction class constructor template.
413def template TwinMemConstructor {{
414        inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
415            : %(base_class)s("%(mnemonic)s", machInst)
416        {
417            %(constructor)s;
418            microOps[0] = new %(class_name)s_0(machInst);
419            microOps[1] = new %(class_name)s_1(machInst);
420        }
421}};
422
423def template BlockMemMicroConstructor {{
424        inline %(class_name)s::
425            %(class_name)s_%(micro_pc)s::
426            %(class_name)s_%(micro_pc)s(ExtMachInst machInst) :
427                %(base_class)sMicro("%(mnemonic)s[%(micro_pc)s]",
428                        machInst, %(op_class)s, %(micro_pc)s * 8)
429    {
430        %(constructor)s;
431        %(set_flags)s;
432    }
433}};
434
435let {{
436
437    def doBlockMemFormat(code, faultCode, execute, name, Name, asi, opt_flags):
438        # XXX Need to take care of pstate.hpriv as well. The lower ASIs
439        # are split into ones that are available in priv and hpriv, and
440        # those that are only available in hpriv
441        addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
442        addrCalcImm = 'EA = Rs1 + imm + offset;'
443        iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags)
444        iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', code, opt_flags)
445        header_output = BlockMemDeclare.subst(iop) + BlockMemDeclare.subst(iop_imm)
446        decoder_output = BlockMemConstructor.subst(iop) + BlockMemConstructor.subst(iop_imm)
447        decode_block = ROrImmDecode.subst(iop)
448        matcher = re.compile(r'Frd_N')
449        exec_output = ''
450        for microPc in range(8):
451            flag_code = ''
452            if (microPc == 7):
453                flag_code = "flags[IsLastMicroOp] = true;"
454            else:
455                flag_code = "flags[IsDelayedCommit] = true;"
456            pcedCode = matcher.sub("Frd_%d" % microPc, code)
457            iop = InstObjParams(name, Name, 'BlockMem',
458                    {"code": pcedCode, "ea_code": addrCalcReg,
459                    "fault_check": faultCode, "micro_pc": microPc,
460                    "set_flags": flag_code}, opt_flags)
461            iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm',
462                    {"code": pcedCode, "ea_code": addrCalcImm,
463                    "fault_check": faultCode, "micro_pc": microPc,
464                    "set_flags": flag_code}, opt_flags)
465            decoder_output += BlockMemMicroConstructor.subst(iop)
466            decoder_output += BlockMemMicroConstructor.subst(iop_imm)
467            exec_output += doDualSplitExecute(
468                    pcedCode, addrCalcReg, addrCalcImm, execute, faultCode,
469                    makeMicroName(name, microPc),
470                    makeMicroName(name + "Imm", microPc),
471                    makeMicroName(Name, microPc),
472                    makeMicroName(Name + "Imm", microPc),
473                    asi, opt_flags);
474            faultCode = ''
475        return (header_output, decoder_output, exec_output, decode_block)
476
477
478    def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags):
479        addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
480        addrCalcImm = 'EA = Rs1 + imm + offset;'
481        iop = InstObjParams(name, Name, 'TwinMem', code, opt_flags)
482        iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', code, opt_flags)
483        header_output = TwinMemDeclare.subst(iop) + TwinMemDeclare.subst(iop_imm)
484        decoder_output = TwinMemConstructor.subst(iop) + TwinMemConstructor.subst(iop_imm)
485        decode_block = ROrImmDecode.subst(iop)
486        matcher = re.compile(r'RdTwin')
487        exec_output = ''
488        for microPc in range(2):
489            flag_code = ''
490            pcedCode = ''
491            if (microPc == 1):
492                flag_code = "flags[IsLastMicroOp] = true;"
493                pcedCode = matcher.sub("RdHigh", code)
494            else:
495                flag_code = "flags[IsDelayedCommit] = true;"
496                pcedCode = matcher.sub("RdLow", code)
497            iop = InstObjParams(name, Name, 'TwinMem',
498                    {"code": pcedCode, "ea_code": addrCalcReg,
499                    "fault_check": faultCode, "micro_pc": microPc,
500                    "set_flags": flag_code}, opt_flags)
501            iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm',
502                    {"code": pcedCode, "ea_code": addrCalcImm,
503                    "fault_check": faultCode, "micro_pc": microPc,
504                    "set_flags": flag_code}, opt_flags)
505            decoder_output += BlockMemMicroConstructor.subst(iop)
506            decoder_output += BlockMemMicroConstructor.subst(iop_imm)
507            exec_output += doDualSplitExecute(
508                    pcedCode, addrCalcReg, addrCalcImm, LoadFuncs, faultCode,
509                    makeMicroName(name, microPc),
510                    makeMicroName(name + "Imm", microPc),
511                    makeMicroName(Name, microPc),
512                    makeMicroName(Name + "Imm", microPc),
513                    asi, opt_flags);
514            faultCode = ''
515        return (header_output, decoder_output, exec_output, decode_block)
516
517}};
518
519def format BlockLoad(code, asi, *opt_flags) {{
520        # We need to make sure to check the highest priority fault last.
521        # That way, if other faults have been detected, they'll be overwritten
522        # rather than the other way around.
523        faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck
524        (header_output,
525         decoder_output,
526         exec_output,
527         decode_block) = doBlockMemFormat(code, faultCode,
528             LoadFuncs, name, Name, asi, opt_flags)
529}};
530
531def format BlockStore(code, asi, *opt_flags) {{
532        # We need to make sure to check the highest priority fault last.
533        # That way, if other faults have been detected, they'll be overwritten
534        # rather than the other way around.
535        faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck
536        (header_output,
537         decoder_output,
538         exec_output,
539         decode_block) = doBlockMemFormat(code, faultCode,
540             StoreFuncs, name, Name, asi, opt_flags)
541}};
542
543def format TwinLoad(code, asi, *opt_flags) {{
544    faultCode = AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck
545    (header_output,
546     decoder_output,
547     exec_output,
548     decode_block) = doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags)
549}};
550