Merge zizzer.eecs.umich.edu:/z/m5/Bitkeeper/m5
[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 /// Cached program counter from last disassembly
44 mutable Addr cachedPC;
45 /// Cached symbol table pointer from last disassembly
46 mutable const SymbolTable *cachedSymtab;
47
48 /// Constructor
49 PCDependentDisassembly(const char *mnem, MachInst _machInst,
50 OpClass __opClass)
51 : AlphaStaticInst(mnem, _machInst, __opClass),
52 cachedPC(0), cachedSymtab(0)
53 {
54 }
55
56 const std::string &
57 disassemble(Addr pc, const SymbolTable *symtab) const;
58 };
59
60 /**
61 * Base class for branches (PC-relative control transfers),
62 * conditional or unconditional.
63 */
64 class Branch : public PCDependentDisassembly
65 {
66 protected:
67 /// Displacement to target address (signed).
68 int32_t disp;
69
70 /// Constructor.
71 Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
72 : PCDependentDisassembly(mnem, _machInst, __opClass),
73 disp(BRDISP << 2)
74 {
75 }
76
77 Addr branchTarget(Addr branchPC) const;
78
79 std::string
80 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
81 };
82
83 /**
84 * Base class for jumps (register-indirect control transfers). In
85 * the Alpha ISA, these are always unconditional.
86 */
87 class Jump : public PCDependentDisassembly
88 {
89 protected:
90
91 /// Displacement to target address (signed).
92 int32_t disp;
93
94 public:
95 /// Constructor
96 Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
97 : PCDependentDisassembly(mnem, _machInst, __opClass),
98 disp(BRDISP)
99 {
100 }
101
102 Addr branchTarget(ExecContext *xc) const;
103
104 std::string
105 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
106 };
107 }};
108
109 output decoder {{
110 Addr
111 Branch::branchTarget(Addr branchPC) const
112 {
113 return branchPC + 4 + disp;
114 }
115
116 Addr
117 Jump::branchTarget(ExecContext *xc) const
118 {
119 Addr NPC = xc->readPC() + 4;
120 uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
121 return (Rb & ~3) | (NPC & 1);
122 }
123
124 const std::string &
125 PCDependentDisassembly::disassemble(Addr pc,
126 const SymbolTable *symtab) const
127 {
128 if (!cachedDisassembly ||
129 pc != cachedPC || symtab != cachedSymtab)
130 {
131 if (cachedDisassembly)
132 delete cachedDisassembly;
133
134 cachedDisassembly =
135 new std::string(generateDisassembly(pc, symtab));
136 cachedPC = pc;
137 cachedSymtab = symtab;
138 }
139
140 return *cachedDisassembly;
141 }
142
143 std::string
144 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
145 {
146 std::stringstream ss;
147
148 ccprintf(ss, "%-10s ", mnemonic);
149
150 // There's only one register arg (RA), but it could be
151 // either a source (the condition for conditional
152 // branches) or a destination (the link reg for
153 // unconditional branches)
154 if (_numSrcRegs > 0) {
155 printReg(ss, _srcRegIdx[0]);
156 ss << ",";
157 }
158 else if (_numDestRegs > 0) {
159 printReg(ss, _destRegIdx[0]);
160 ss << ",";
161 }
162
163 #ifdef SS_COMPATIBLE_DISASSEMBLY
164 if (_numSrcRegs == 0 && _numDestRegs == 0) {
165 printReg(ss, 31);
166 ss << ",";
167 }
168 #endif
169
170 Addr target = pc + 4 + disp;
171
172 std::string str;
173 if (symtab && symtab->findSymbol(target, str))
174 ss << str;
175 else
176 ccprintf(ss, "0x%x", target);
177
178 return ss.str();
179 }
180
181 std::string
182 Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
183 {
184 std::stringstream ss;
185
186 ccprintf(ss, "%-10s ", mnemonic);
187
188 #ifdef SS_COMPATIBLE_DISASSEMBLY
189 if (_numDestRegs == 0) {
190 printReg(ss, 31);
191 ss << ",";
192 }
193 #endif
194
195 if (_numDestRegs > 0) {
196 printReg(ss, _destRegIdx[0]);
197 ss << ",";
198 }
199
200 ccprintf(ss, "(r%d)", RB);
201
202 return ss.str();
203 }
204 }};
205
206 def template JumpOrBranchDecode {{
207 return (RA == 31)
208 ? (StaticInst<AlphaISA> *)new %(class_name)s(machInst)
209 : (StaticInst<AlphaISA> *)new %(class_name)sAndLink(machInst);
210 }};
211
212 def format CondBranch(code) {{
213 code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
214 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
215 ('IsDirectControl', 'IsCondControl'))
216 header_output = BasicDeclare.subst(iop)
217 decoder_output = BasicConstructor.subst(iop)
218 decode_block = BasicDecode.subst(iop)
219 exec_output = BasicExecute.subst(iop)
220 }};
221
222 let {{
223 def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
224 # Declare basic control transfer w/o link (i.e. link reg is R31)
225 nolink_code = 'NPC = %s;\n' % npc_expr
226 nolink_iop = InstObjParams(name, Name, base_class,
227 CodeBlock(nolink_code), flags)
228 header_output = BasicDeclare.subst(nolink_iop)
229 decoder_output = BasicConstructor.subst(nolink_iop)
230 exec_output = BasicExecute.subst(nolink_iop)
231
232 # Generate declaration of '*AndLink' version, append to decls
233 link_code = 'Ra = NPC & ~3;\n' + nolink_code
234 link_iop = InstObjParams(name, Name + 'AndLink', base_class,
235 CodeBlock(link_code), flags)
236 header_output += BasicDeclare.subst(link_iop)
237 decoder_output += BasicConstructor.subst(link_iop)
238 exec_output += BasicExecute.subst(link_iop)
239
240 # need to use link_iop for the decode template since it is expecting
241 # the shorter version of class_name (w/o "AndLink")
242
243 return (header_output, decoder_output,
244 JumpOrBranchDecode.subst(nolink_iop), exec_output)
245 }};
246
247 def format UncondBranch(*flags) {{
248 flags += ('IsUncondControl', 'IsDirectControl')
249 (header_output, decoder_output, decode_block, exec_output) = \
250 UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
251 }};
252
253 def format Jump(*flags) {{
254 flags += ('IsUncondControl', 'IsIndirectControl')
255 (header_output, decoder_output, decode_block, exec_output) = \
256 UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
257 }};
258
259