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