branch.isa revision 2632:1bb2f91485ea
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: Gabe Black
28//          Steve Reinhardt
29
30////////////////////////////////////////////////////////////////////
31//
32// Branch instructions
33//
34
35output header {{
36        /**
37         * Base class for branch operations.
38         */
39        class Branch : public SparcStaticInst
40        {
41          protected:
42            // Constructor
43            Branch(const char *mnem, MachInst _machInst, OpClass __opClass) :
44                SparcStaticInst(mnem, _machInst, __opClass)
45            {
46            }
47
48            std::string generateDisassembly(Addr pc,
49                    const SymbolTable *symtab) const;
50        };
51
52        /**
53         * Base class for branch operations with an immediate displacement.
54         */
55        class BranchDisp : public Branch
56        {
57          protected:
58            // Constructor
59            BranchDisp(const char *mnem, MachInst _machInst,
60                    OpClass __opClass) :
61                Branch(mnem, _machInst, __opClass)
62            {
63            }
64
65            std::string generateDisassembly(Addr pc,
66                    const SymbolTable *symtab) const;
67
68            int32_t disp;
69        };
70
71        /**
72         * Base class for branches with 19 bit displacements.
73         */
74        class Branch19 : public BranchDisp
75        {
76          protected:
77            // Constructor
78            Branch19(const char *mnem, MachInst _machInst,
79                    OpClass __opClass) :
80                BranchDisp(mnem, _machInst, __opClass)
81            {
82                disp = sign_ext(DISP19 << 2, 21);
83            }
84        };
85
86        /**
87         * Base class for branches with 22 bit displacements.
88         */
89        class Branch22 : public BranchDisp
90        {
91          protected:
92            // Constructor
93            Branch22(const char *mnem, MachInst _machInst,
94                    OpClass __opClass) :
95                BranchDisp(mnem, _machInst, __opClass)
96            {
97                disp = sign_ext(DISP22 << 2, 24);
98            }
99        };
100
101        /**
102         * Base class for branches with 30 bit displacements.
103         */
104        class Branch30 : public BranchDisp
105        {
106          protected:
107            // Constructor
108            Branch30(const char *mnem, MachInst _machInst,
109                    OpClass __opClass) :
110                BranchDisp(mnem, _machInst, __opClass)
111            {
112                disp = sign_ext(DISP30 << 2, 32);
113            }
114        };
115
116        /**
117         * Base class for 16bit split displacements.
118         */
119        class BranchSplit : public BranchDisp
120        {
121          protected:
122            // Constructor
123            BranchSplit(const char *mnem, MachInst _machInst,
124                    OpClass __opClass) :
125                BranchDisp(mnem, _machInst, __opClass)
126            {
127                disp = sign_ext((D16HI << 16) | (D16LO << 2), 18);
128            }
129        };
130
131        /**
132         * Base class for branches that use an immediate and a register to
133         * compute their displacements.
134         */
135        class BranchImm13 : public Branch
136        {
137          protected:
138            // Constructor
139            BranchImm13(const char *mnem, MachInst _machInst, OpClass __opClass) :
140                Branch(mnem, _machInst, __opClass), imm(sign_ext(SIMM13, 13))
141            {
142            }
143
144            std::string generateDisassembly(Addr pc,
145                    const SymbolTable *symtab) const;
146
147            int32_t imm;
148        };
149}};
150
151output decoder {{
152        std::string Branch::generateDisassembly(Addr pc,
153                const SymbolTable *symtab) const
154        {
155            std::stringstream response;
156
157            printMnemonic(response, mnemonic);
158
159            if (_numSrcRegs > 0)
160            {
161                printReg(response, _srcRegIdx[0]);
162                for(int x = 1; x < _numSrcRegs; x++)
163                {
164                    response << ", ";
165                    printReg(response, _srcRegIdx[x]);
166                }
167            }
168
169            if (_numDestRegs > 0)
170            {
171                if(_numSrcRegs > 0)
172                    response << ", ";
173                printReg(response, _destRegIdx[0]);
174            }
175
176            return response.str();
177        }
178
179        std::string BranchImm13::generateDisassembly(Addr pc,
180                const SymbolTable *symtab) const
181        {
182            std::stringstream response;
183
184            printMnemonic(response, mnemonic);
185
186            if (_numSrcRegs > 0)
187            {
188                printReg(response, _srcRegIdx[0]);
189                for(int x = 1; x < _numSrcRegs; x++)
190                {
191                    response << ", ";
192                    printReg(response, _srcRegIdx[x]);
193                }
194            }
195
196            if(_numSrcRegs > 0)
197                response << ", ";
198
199            ccprintf(response, "0x%x", imm);
200
201            if (_numDestRegs > 0)
202            {
203                response << ", ";
204                printReg(response, _destRegIdx[0]);
205            }
206
207            return response.str();
208        }
209
210        std::string BranchDisp::generateDisassembly(Addr pc,
211                const SymbolTable *symtab) const
212        {
213            std::stringstream response;
214            std::string symbol;
215            Addr symbolAddr;
216
217            Addr target = disp + pc;
218
219            printMnemonic(response, mnemonic);
220            ccprintf(response, "0x%x", target);
221
222            if(symtab->findNearestSymbol(target, symbol, symbolAddr))
223            {
224                ccprintf(response, " <%s", symbol);
225                if(symbolAddr != target)
226                    ccprintf(response, "+%d>", target - symbolAddr);
227                else
228                    ccprintf(response, ">");
229            }
230
231            return response.str();
232        }
233}};
234
235def template BranchExecute {{
236        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
237                Trace::InstRecord *traceData) const
238        {
239            //Attempt to execute the instruction
240            Fault fault = NoFault;
241
242            %(op_decl)s;
243            %(op_rd)s;
244
245            NNPC = xc->readNextNPC();
246            %(code)s;
247
248            if(fault == NoFault)
249            {
250                //Write the resulting state to the execution context
251                %(op_wb)s;
252            }
253
254            return fault;
255        }
256}};
257
258let {{
259    handle_annul = '''
260    {
261        if(A)
262        {
263            NPC = xc->readNextNPC();
264            NNPC = NPC + 4;
265        }
266        else
267        {
268            NPC = xc->readNextPC();
269            NNPC = xc->readNextNPC();
270        }
271    }'''
272}};
273
274// Primary format for branch instructions:
275def format Branch(code, *opt_flags) {{
276        code = re.sub(r'handle_annul', handle_annul, code)
277        (usesImm, code, immCode,
278         rString, iString) = splitOutImm(code)
279        iop = InstObjParams(name, Name, 'Branch', code, opt_flags)
280        header_output = BasicDeclare.subst(iop)
281        decoder_output = BasicConstructor.subst(iop)
282        exec_output = BranchExecute.subst(iop)
283        if usesImm:
284            imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString,
285                    immCode, opt_flags)
286            header_output += BasicDeclare.subst(imm_iop)
287            decoder_output += BasicConstructor.subst(imm_iop)
288            exec_output += BranchExecute.subst(imm_iop)
289            decode_block = ROrImmDecode.subst(iop)
290        else:
291            decode_block = BasicDecode.subst(iop)
292}};
293
294// Primary format for branch instructions:
295def format Branch19(code, *opt_flags) {{
296        code = re.sub(r'handle_annul', handle_annul, code)
297        codeBlk = CodeBlock(code)
298        iop = InstObjParams(name, Name, 'Branch19', codeBlk, opt_flags)
299        header_output = BasicDeclare.subst(iop)
300        decoder_output = BasicConstructor.subst(iop)
301        exec_output = BranchExecute.subst(iop)
302        decode_block = BasicDecode.subst(iop)
303}};
304
305// Primary format for branch instructions:
306def format Branch22(code, *opt_flags) {{
307        code = re.sub(r'handle_annul', handle_annul, code)
308        codeBlk = CodeBlock(code)
309        iop = InstObjParams(name, Name, 'Branch22', codeBlk, opt_flags)
310        header_output = BasicDeclare.subst(iop)
311        decoder_output = BasicConstructor.subst(iop)
312        exec_output = BranchExecute.subst(iop)
313        decode_block = BasicDecode.subst(iop)
314}};
315
316// Primary format for branch instructions:
317def format Branch30(code, *opt_flags) {{
318        code = re.sub(r'handle_annul', handle_annul, code)
319        codeBlk = CodeBlock(code)
320        iop = InstObjParams(name, Name, 'Branch30', codeBlk, opt_flags)
321        header_output = BasicDeclare.subst(iop)
322        decoder_output = BasicConstructor.subst(iop)
323        exec_output = BranchExecute.subst(iop)
324        decode_block = BasicDecode.subst(iop)
325}};
326
327// Primary format for branch instructions:
328def format BranchSplit(code, *opt_flags) {{
329        code = re.sub(r'handle_annul', handle_annul, code)
330        codeBlk = CodeBlock(code)
331        iop = InstObjParams(name, Name, 'BranchSplit', codeBlk, opt_flags)
332        header_output = BasicDeclare.subst(iop)
333        decoder_output = BasicConstructor.subst(iop)
334        exec_output = BranchExecute.subst(iop)
335        decode_block = BasicDecode.subst(iop)
336}};
337
338