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