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