branch.isa revision 2516
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, "+0x%x>", 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
229// Primary format for branch instructions:
230def format Branch(code, *opt_flags) {{
231        (usesImm, code, immCode,
232         rString, iString) = splitOutImm(code)
233        codeBlk = CodeBlock(code)
234        iop = InstObjParams(name, Name, 'Branch', codeBlk, opt_flags)
235        header_output = BasicDeclare.subst(iop)
236        decoder_output = BasicConstructor.subst(iop)
237        exec_output = BranchExecute.subst(iop)
238        if usesImm:
239            imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString,
240                    codeBlk, opt_flags)
241            header_output += BasicDeclare.subst(imm_iop)
242            decoder_output += BasicConstructor.subst(imm_iop)
243            exec_output += BranchExecute.subst(imm_iop)
244            decode_block = ROrImmDecode.subst(iop)
245        else:
246            decode_block = BasicDecode.subst(iop)
247}};
248
249// Primary format for branch instructions:
250def format Branch19(code, *opt_flags) {{
251        codeBlk = CodeBlock(code)
252        iop = InstObjParams(name, Name, 'Branch19', codeBlk, opt_flags)
253        header_output = BasicDeclare.subst(iop)
254        decoder_output = BasicConstructor.subst(iop)
255        exec_output = BranchExecute.subst(iop)
256        decode_block = BasicDecode.subst(iop)
257}};
258
259// Primary format for branch instructions:
260def format Branch22(code, *opt_flags) {{
261        codeBlk = CodeBlock(code)
262        iop = InstObjParams(name, Name, 'Branch22', codeBlk, opt_flags)
263        header_output = BasicDeclare.subst(iop)
264        decoder_output = BasicConstructor.subst(iop)
265        exec_output = BranchExecute.subst(iop)
266        decode_block = BasicDecode.subst(iop)
267}};
268
269// Primary format for branch instructions:
270def format Branch30(code, *opt_flags) {{
271        codeBlk = CodeBlock(code)
272        iop = InstObjParams(name, Name, 'Branch30', codeBlk, opt_flags)
273        header_output = BasicDeclare.subst(iop)
274        decoder_output = BasicConstructor.subst(iop)
275        exec_output = BranchExecute.subst(iop)
276        decode_block = BasicDecode.subst(iop)
277}};
278
279// Primary format for branch instructions:
280def format BranchSplit(code, *opt_flags) {{
281        codeBlk = CodeBlock(code)
282        iop = InstObjParams(name, Name, 'BranchSplit', codeBlk, opt_flags)
283        header_output = BasicDeclare.subst(iop)
284        decoder_output = BasicConstructor.subst(iop)
285        exec_output = BranchExecute.subst(iop)
286        decode_block = BasicDecode.subst(iop)
287}};
288
289