cc6fd1a09ed7463bdb90e5ac729f8a4f698dca26
[gem5.git] / arch / alpha / isa / branch.isa
1 // -*- mode:c++ -*-
2
3 // Copyright (c) 2003-2005 The Regents of The University of Michigan
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met: redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer;
10 // redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution;
13 // neither the name of the copyright holders nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 output header {{
30
31 /**
32 * Base class for instructions whose disassembly is not purely a
33 * function of the machine instruction (i.e., it depends on the
34 * PC). This class overrides the disassemble() method to check
35 * the PC and symbol table values before re-using a cached
36 * disassembly string. This is necessary for branches and jumps,
37 * where the disassembly string includes the target address (which
38 * may depend on the PC and/or symbol table).
39 */
40 class PCDependentDisassembly : public AlphaStaticInst
41 {
42 protected:
43 typedef TheISA::Addr Addr;
44 protected:
45 /// Cached program counter from last disassembly
46 mutable Addr cachedPC;
47 /// Cached symbol table pointer from last disassembly
48 mutable const SymbolTable *cachedSymtab;
49
50 /// Constructor
51 PCDependentDisassembly(const char *mnem, MachInst _machInst,
52 OpClass __opClass)
53 : AlphaStaticInst(mnem, _machInst, __opClass),
54 cachedPC(0), cachedSymtab(0)
55 {
56 }
57
58 const std::string &
59 disassemble(Addr pc, const SymbolTable *symtab) const;
60 };
61
62 /**
63 * Base class for branches (PC-relative control transfers),
64 * conditional or unconditional.
65 */
66 class Branch : public PCDependentDisassembly
67 {
68 protected:
69 typedef TheISA::Addr Addr;
70 /// Displacement to target address (signed).
71 int32_t disp;
72
73 /// Constructor.
74 Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
75 : PCDependentDisassembly(mnem, _machInst, __opClass),
76 disp(BRDISP << 2)
77 {
78 }
79
80 Addr branchTarget(Addr branchPC) const;
81
82 std::string
83 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
84 };
85
86 /**
87 * Base class for jumps (register-indirect control transfers). In
88 * the Alpha ISA, these are always unconditional.
89 */
90 class Jump : public PCDependentDisassembly
91 {
92 protected:
93 typedef TheISA::Addr Addr;
94
95 /// Displacement to target address (signed).
96 int32_t disp;
97
98 public:
99 /// Constructor
100 Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
101 : PCDependentDisassembly(mnem, _machInst, __opClass),
102 disp(BRDISP)
103 {
104 }
105
106 Addr branchTarget(ExecContext *xc) const;
107
108 std::string
109 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
110 };
111 }};
112
113 output decoder {{
114 Addr
115 Branch::branchTarget(Addr branchPC) const
116 {
117 return branchPC + 4 + disp;
118 }
119
120 Addr
121 Jump::branchTarget(ExecContext *xc) const
122 {
123 Addr NPC = xc->readPC() + 4;
124 uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
125 return (Rb & ~3) | (NPC & 1);
126 }
127
128 const std::string &
129 PCDependentDisassembly::disassemble(Addr pc,
130 const SymbolTable *symtab) const
131 {
132 if (!cachedDisassembly ||
133 pc != cachedPC || symtab != cachedSymtab)
134 {
135 if (cachedDisassembly)
136 delete cachedDisassembly;
137
138 cachedDisassembly =
139 new std::string(generateDisassembly(pc, symtab));
140 cachedPC = pc;
141 cachedSymtab = symtab;
142 }
143
144 return *cachedDisassembly;
145 }
146
147 std::string
148 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
149 {
150 std::stringstream ss;
151
152 ccprintf(ss, "%-10s ", mnemonic);
153
154 // There's only one register arg (RA), but it could be
155 // either a source (the condition for conditional
156 // branches) or a destination (the link reg for
157 // unconditional branches)
158 if (_numSrcRegs > 0) {
159 printReg(ss, _srcRegIdx[0]);
160 ss << ",";
161 }
162 else if (_numDestRegs > 0) {
163 printReg(ss, _destRegIdx[0]);
164 ss << ",";
165 }
166
167 #ifdef SS_COMPATIBLE_DISASSEMBLY
168 if (_numSrcRegs == 0 && _numDestRegs == 0) {
169 printReg(ss, 31);
170 ss << ",";
171 }
172 #endif
173
174 Addr target = pc + 4 + disp;
175
176 std::string str;
177 if (symtab && symtab->findSymbol(target, str))
178 ss << str;
179 else
180 ccprintf(ss, "0x%x", target);
181
182 return ss.str();
183 }
184
185 std::string
186 Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
187 {
188 std::stringstream ss;
189
190 ccprintf(ss, "%-10s ", mnemonic);
191
192 #ifdef SS_COMPATIBLE_DISASSEMBLY
193 if (_numDestRegs == 0) {
194 printReg(ss, 31);
195 ss << ",";
196 }
197 #endif
198
199 if (_numDestRegs > 0) {
200 printReg(ss, _destRegIdx[0]);
201 ss << ",";
202 }
203
204 ccprintf(ss, "(r%d)", RB);
205
206 return ss.str();
207 }
208 }};
209
210 def template JumpOrBranchDecode {{
211 return (RA == 31)
212 ? (StaticInst *)new %(class_name)s(machInst)
213 : (StaticInst *)new %(class_name)sAndLink(machInst);
214 }};
215
216 def format CondBranch(code) {{
217 code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
218 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
219 ('IsDirectControl', 'IsCondControl'))
220 header_output = BasicDeclare.subst(iop)
221 decoder_output = BasicConstructor.subst(iop)
222 decode_block = BasicDecode.subst(iop)
223 exec_output = BasicExecute.subst(iop)
224 }};
225
226 let {{
227 def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
228 # Declare basic control transfer w/o link (i.e. link reg is R31)
229 nolink_code = 'NPC = %s;\n' % npc_expr
230 nolink_iop = InstObjParams(name, Name, base_class,
231 CodeBlock(nolink_code), flags)
232 header_output = BasicDeclare.subst(nolink_iop)
233 decoder_output = BasicConstructor.subst(nolink_iop)
234 exec_output = BasicExecute.subst(nolink_iop)
235
236 # Generate declaration of '*AndLink' version, append to decls
237 link_code = 'Ra = NPC & ~3;\n' + nolink_code
238 link_iop = InstObjParams(name, Name + 'AndLink', base_class,
239 CodeBlock(link_code), flags)
240 header_output += BasicDeclare.subst(link_iop)
241 decoder_output += BasicConstructor.subst(link_iop)
242 exec_output += BasicExecute.subst(link_iop)
243
244 # need to use link_iop for the decode template since it is expecting
245 # the shorter version of class_name (w/o "AndLink")
246
247 return (header_output, decoder_output,
248 JumpOrBranchDecode.subst(nolink_iop), exec_output)
249 }};
250
251 def format UncondBranch(*flags) {{
252 flags += ('IsUncondControl', 'IsDirectControl')
253 (header_output, decoder_output, decode_block, exec_output) = \
254 UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
255 }};
256
257 def format Jump(*flags) {{
258 flags += ('IsUncondControl', 'IsIndirectControl')
259 (header_output, decoder_output, decode_block, exec_output) = \
260 UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
261 }};
262
263