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