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