blockmem.isa revision 3835:97b3b03865fb
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
211def template BlockMemDeclare {{
212        /**
213         * Static instruction class for a block memory operation
214         */
215        class %(class_name)s : public %(base_class)s
216        {
217          public:
218            //Constructor
219            %(class_name)s(ExtMachInst machInst);
220
221          protected:
222            class %(class_name)s_0 : public %(base_class)sMicro
223            {
224              public:
225                //Constructor
226                %(class_name)s_0(ExtMachInst machInst);
227                %(BasicExecDeclare)s
228                %(InitiateAccDeclare)s
229                %(CompleteAccDeclare)s
230            };
231
232            class %(class_name)s_1 : public %(base_class)sMicro
233            {
234              public:
235                //Constructor
236                %(class_name)s_1(ExtMachInst machInst);
237                %(BasicExecDeclare)s
238                %(InitiateAccDeclare)s
239                %(CompleteAccDeclare)s
240            };
241
242            class %(class_name)s_2 : public %(base_class)sMicro
243            {
244              public:
245                //Constructor
246                %(class_name)s_2(ExtMachInst machInst);
247                %(BasicExecDeclare)s
248                %(InitiateAccDeclare)s
249                %(CompleteAccDeclare)s
250            };
251
252            class %(class_name)s_3 : public %(base_class)sMicro
253            {
254              public:
255                //Constructor
256                %(class_name)s_3(ExtMachInst machInst);
257                %(BasicExecDeclare)s
258                %(InitiateAccDeclare)s
259                %(CompleteAccDeclare)s
260            };
261
262            class %(class_name)s_4 : public %(base_class)sMicro
263            {
264              public:
265                //Constructor
266                %(class_name)s_4(ExtMachInst machInst);
267                %(BasicExecDeclare)s
268                %(InitiateAccDeclare)s
269                %(CompleteAccDeclare)s
270            };
271
272            class %(class_name)s_5 : public %(base_class)sMicro
273            {
274              public:
275                //Constructor
276                %(class_name)s_5(ExtMachInst machInst);
277                %(BasicExecDeclare)s
278                %(InitiateAccDeclare)s
279                %(CompleteAccDeclare)s
280            };
281
282            class %(class_name)s_6 : public %(base_class)sMicro
283            {
284              public:
285                //Constructor
286                %(class_name)s_6(ExtMachInst machInst);
287                %(BasicExecDeclare)s
288                %(InitiateAccDeclare)s
289                %(CompleteAccDeclare)s
290            };
291
292            class %(class_name)s_7 : public %(base_class)sMicro
293            {
294              public:
295                //Constructor
296                %(class_name)s_7(ExtMachInst machInst);
297                %(BasicExecDeclare)s
298                %(InitiateAccDeclare)s
299                %(CompleteAccDeclare)s
300            };
301        };
302}};
303
304def template TwinMemDeclare {{
305        /**
306         * Static instruction class for a block memory operation
307         */
308        class %(class_name)s : public %(base_class)s
309        {
310          public:
311            //Constructor
312            %(class_name)s(ExtMachInst machInst);
313
314          protected:
315            class %(class_name)s_0 : public %(base_class)sMicro
316            {
317              public:
318                //Constructor
319                %(class_name)s_0(ExtMachInst machInst);
320                %(BasicExecDeclare)s
321                %(InitiateAccDeclare)s
322                %(CompleteAccDeclare)s
323            };
324
325            class %(class_name)s_1 : public %(base_class)sMicro
326            {
327              public:
328                //Constructor
329                %(class_name)s_1(ExtMachInst machInst);
330                %(BasicExecDeclare)s
331                %(InitiateAccDeclare)s
332                %(CompleteAccDeclare)s
333            };
334        };
335}};
336
337// Basic instruction class constructor template.
338def template BlockMemConstructor {{
339        inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
340            : %(base_class)s("%(mnemonic)s", machInst)
341        {
342            %(constructor)s;
343            microOps[0] = new %(class_name)s_0(machInst);
344            microOps[1] = new %(class_name)s_1(machInst);
345            microOps[2] = new %(class_name)s_2(machInst);
346            microOps[3] = new %(class_name)s_3(machInst);
347            microOps[4] = new %(class_name)s_4(machInst);
348            microOps[5] = new %(class_name)s_5(machInst);
349            microOps[6] = new %(class_name)s_6(machInst);
350            microOps[7] = new %(class_name)s_7(machInst);
351        }
352}};
353
354// Basic instruction class constructor template.
355def template TwinMemConstructor {{
356        inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
357            : %(base_class)s("%(mnemonic)s", machInst)
358        {
359            %(constructor)s;
360            microOps[0] = new %(class_name)s_0(machInst);
361            microOps[1] = new %(class_name)s_1(machInst);
362        }
363}};
364
365def template BlockMemMicroConstructor {{
366        inline %(class_name)s::
367            %(class_name)s_%(micro_pc)s::
368            %(class_name)s_%(micro_pc)s(ExtMachInst machInst) :
369                %(base_class)sMicro("%(mnemonic)s[%(micro_pc)s]",
370                        machInst, %(op_class)s, %(micro_pc)s * 8)
371    {
372        %(constructor)s;
373        %(set_flags)s;
374    }
375}};
376
377let {{
378
379    def doBlockMemFormat(code, faultCode, execute, name, Name, asi, opt_flags):
380        # XXX Need to take care of pstate.hpriv as well. The lower ASIs
381        # are split into ones that are available in priv and hpriv, and
382        # those that are only available in hpriv
383        addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
384        addrCalcImm = 'EA = Rs1 + imm + offset;'
385        iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags)
386        iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', code, opt_flags)
387        header_output = BlockMemDeclare.subst(iop) + BlockMemDeclare.subst(iop_imm)
388        decoder_output = BlockMemConstructor.subst(iop) + BlockMemConstructor.subst(iop_imm)
389        decode_block = ROrImmDecode.subst(iop)
390        matcher = re.compile(r'Frd_N')
391        exec_output = ''
392        for microPc in range(8):
393            flag_code = ''
394            if (microPc == 7):
395                flag_code = "flags[IsLastMicroOp] = true;"
396            else:
397                flag_code = "flags[IsDelayedCommit] = true;"
398            pcedCode = matcher.sub("Frd_%d" % microPc, code)
399            iop = InstObjParams(name, Name, 'BlockMem', pcedCode,
400                    opt_flags, {"ea_code": addrCalcReg,
401                    "fault_check": faultCode, "micro_pc": microPc,
402                    "set_flags": flag_code})
403            iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', pcedCode,
404                    opt_flags, {"ea_code": addrCalcImm,
405                    "fault_check": faultCode, "micro_pc": microPc,
406                    "set_flags": flag_code})
407            decoder_output += BlockMemMicroConstructor.subst(iop)
408            decoder_output += BlockMemMicroConstructor.subst(iop_imm)
409            exec_output += doDualSplitExecute(
410                    pcedCode, addrCalcReg, addrCalcImm, execute, faultCode,
411                    makeMicroName(name, microPc),
412                    makeMicroName(name + "Imm", microPc),
413                    makeMicroName(Name, microPc),
414                    makeMicroName(Name + "Imm", microPc),
415                    asi, opt_flags);
416            faultCode = ''
417        return (header_output, decoder_output, exec_output, decode_block)
418
419
420    def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags):
421        addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
422        addrCalcImm = 'EA = Rs1 + imm + offset;'
423        iop = InstObjParams(name, Name, 'TwinMem', code, opt_flags)
424        iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', code, opt_flags)
425        header_output = TwinMemDeclare.subst(iop) + TwinMemDeclare.subst(iop_imm)
426        decoder_output = TwinMemConstructor.subst(iop) + TwinMemConstructor.subst(iop_imm)
427        decode_block = ROrImmDecode.subst(iop)
428        matcher = re.compile(r'RdTwin')
429        exec_output = ''
430        for microPc in range(2):
431            flag_code = ''
432            pcedCode = ''
433            if (microPc == 1):
434                flag_code = "flags[IsLastMicroOp] = true;"
435                pcedCode = matcher.sub("RdHigh", code)
436            else:
437                flag_code = "flags[IsDelayedCommit] = true;"
438                pcedCode = matcher.sub("RdLow", code)
439            iop = InstObjParams(name, Name, 'TwinMem', pcedCode,
440                    opt_flags, {"ea_code": addrCalcReg,
441                    "fault_check": faultCode, "micro_pc": microPc,
442                    "set_flags": flag_code})
443            iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', pcedCode,
444                    opt_flags, {"ea_code": addrCalcImm,
445                    "fault_check": faultCode, "micro_pc": microPc,
446                    "set_flags": flag_code})
447            decoder_output += BlockMemMicroConstructor.subst(iop)
448            decoder_output += BlockMemMicroConstructor.subst(iop_imm)
449            exec_output += doDualSplitExecute(
450                    pcedCode, addrCalcReg, addrCalcImm, execute, faultCode,
451                    makeMicroName(name, microPc),
452                    makeMicroName(name + "Imm", microPc),
453                    makeMicroName(Name, microPc),
454                    makeMicroName(Name + "Imm", microPc),
455                    asi, opt_flags);
456            faultCode = ''
457        return (header_output, decoder_output, exec_output, decode_block)
458
459}};
460
461def format BlockLoad(code, asi, *opt_flags) {{
462        # We need to make sure to check the highest priority fault last.
463        # That way, if other faults have been detected, they'll be overwritten
464        # rather than the other way around.
465        faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck
466        (header_output,
467         decoder_output,
468         exec_output,
469         decode_block) = doBlockMemFormat(code, faultCode,
470             LoadExecute, name, Name, asi, opt_flags)
471}};
472
473def format BlockStore(code, asi, *opt_flags) {{
474        # We need to make sure to check the highest priority fault last.
475        # That way, if other faults have been detected, they'll be overwritten
476        # rather than the other way around.
477        faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck
478        (header_output,
479         decoder_output,
480         exec_output,
481         decode_block) = doBlockMemFormat(code, faultCode,
482             StoreExecute, name, Name, asi, opt_flags)
483}};
484
485def format TwinLoad(code, asi, *opt_flags) {{
486    faultCode = AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck
487    (header_output,
488     decoder_output,
489     exec_output,
490     decode_block) = doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags)
491}};
492