macromem.isa (6725:c469a9365a4a) macromem.isa (6726:a5322e816a2a)
1// -*- mode:c++ -*-
2
3// Copyright (c) 2007-2008 The Florida State University
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: Stephen Hines
30// Gabe Black
31
32////////////////////////////////////////////////////////////////////
33//
34// Common microop templates
35//
36
37def template MicroConstructor {{
38 inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
39 RegIndex _ura,
40 RegIndex _urb,
41 uint8_t _imm)
42 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
43 _ura, _urb, _imm)
44 {
45 %(constructor)s;
46 }
47}};
48
49////////////////////////////////////////////////////////////////////
50//
51// Load/store microops
52//
53
54def template MicroMemDeclare {{
55 class %(class_name)s : public %(base_class)s
56 {
57 public:
58 %(class_name)s(ExtMachInst machInst,
59 RegIndex _ura, RegIndex _urb,
60 uint8_t _imm);
61 %(BasicExecDeclare)s
62 %(InitiateAccDeclare)s
63 %(CompleteAccDeclare)s
64 };
65}};
66
67let {{
68 microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
69 'MicroMemOp',
70 {'memacc_code': 'Ra = Mem;',
71 'ea_code': 'EA = Rb + (UP ? imm : -imm);',
72 'predicate_test': predicateTest},
73 ['IsMicroop'])
74
75 microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
76 'MicroMemOp',
77 {'memacc_code': 'Mem = Ra;',
78 'ea_code': 'EA = Rb + (UP ? imm : -imm);',
79 'predicate_test': predicateTest},
80 ['IsMicroop'])
81
82 header_output = MicroMemDeclare.subst(microLdrUopIop) + \
83 MicroMemDeclare.subst(microStrUopIop)
84 decoder_output = MicroConstructor.subst(microLdrUopIop) + \
85 MicroConstructor.subst(microStrUopIop)
86 exec_output = LoadExecute.subst(microLdrUopIop) + \
87 StoreExecute.subst(microStrUopIop) + \
88 LoadInitiateAcc.subst(microLdrUopIop) + \
89 StoreInitiateAcc.subst(microStrUopIop) + \
90 LoadCompleteAcc.subst(microLdrUopIop) + \
91 StoreCompleteAcc.subst(microStrUopIop)
92}};
93
94////////////////////////////////////////////////////////////////////
95//
96// Integer = Integer op Immediate microops
97//
98
99def template MicroIntDeclare {{
100 class %(class_name)s : public %(base_class)s
101 {
102 public:
103 %(class_name)s(ExtMachInst machInst,
104 RegIndex _ura, RegIndex _urb,
105 uint8_t _imm);
106 %(BasicExecDeclare)s
107 };
108}};
109
110let {{
111 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
112 'MicroIntOp',
113 {'code': 'Ra = Rb + imm;',
114 'predicate_test': predicateTest},
115 ['IsMicroop'])
116
117 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
118 'MicroIntOp',
119 {'code': 'Ra = Rb - imm;',
120 'predicate_test': predicateTest},
121 ['IsMicroop'])
122
123 header_output = MicroIntDeclare.subst(microAddiUopIop) + \
124 MicroIntDeclare.subst(microSubiUopIop)
125 decoder_output = MicroConstructor.subst(microAddiUopIop) + \
126 MicroConstructor.subst(microSubiUopIop)
127 exec_output = PredOpExecute.subst(microAddiUopIop) + \
128 PredOpExecute.subst(microSubiUopIop)
129}};
130
131////////////////////////////////////////////////////////////////////
132//
133// Moving to/from double floating point registers
134//
135
136let {{
137 microMvtdUopIop = InstObjParams('mvtd_uop', 'MicroMvtdUop',
138 'PredOp',
139 {'code': 'Fd.ud = (Rhi.ud << 32) | Rlo;',
140 'predicate_test': predicateTest},
141 ['IsMicroop'])
142
143 microMvfdUopIop = InstObjParams('mvfd_uop', 'MicroMvfdUop',
144 'PredOp',
145 {'code': '''Rhi = bits(Fd.ud, 63, 32);
146 Rlo = bits(Fd.ud, 31, 0);''',
147 'predicate_test': predicateTest},
148 ['IsMicroop'])
149
150 header_output = BasicDeclare.subst(microMvtdUopIop) + \
151 BasicDeclare.subst(microMvfdUopIop)
152 decoder_output = BasicConstructor.subst(microMvtdUopIop) + \
153 BasicConstructor.subst(microMvfdUopIop)
154 exec_output = PredOpExecute.subst(microMvtdUopIop) + \
155 PredOpExecute.subst(microMvfdUopIop)
156}};
157
158////////////////////////////////////////////////////////////////////
159//
160// Macro Memory-format instructions
161//
162
163def template MacroStoreDeclare {{
164/**
165 * Static instructions class for a store multiple instruction
166 */
167class %(class_name)s : public %(base_class)s
168{
169 public:
170 // Constructor
171 %(class_name)s(ExtMachInst machInst);
172 %(BasicExecDeclare)s
173};
174}};
175
176def template MacroStoreConstructor {{
177inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
178 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
179{
180 %(constructor)s;
181 uint32_t regs = reglist;
182 uint32_t addr = 0;
1// -*- mode:c++ -*-
2
3// Copyright (c) 2007-2008 The Florida State University
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: Stephen Hines
30// Gabe Black
31
32////////////////////////////////////////////////////////////////////
33//
34// Common microop templates
35//
36
37def template MicroConstructor {{
38 inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
39 RegIndex _ura,
40 RegIndex _urb,
41 uint8_t _imm)
42 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
43 _ura, _urb, _imm)
44 {
45 %(constructor)s;
46 }
47}};
48
49////////////////////////////////////////////////////////////////////
50//
51// Load/store microops
52//
53
54def template MicroMemDeclare {{
55 class %(class_name)s : public %(base_class)s
56 {
57 public:
58 %(class_name)s(ExtMachInst machInst,
59 RegIndex _ura, RegIndex _urb,
60 uint8_t _imm);
61 %(BasicExecDeclare)s
62 %(InitiateAccDeclare)s
63 %(CompleteAccDeclare)s
64 };
65}};
66
67let {{
68 microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
69 'MicroMemOp',
70 {'memacc_code': 'Ra = Mem;',
71 'ea_code': 'EA = Rb + (UP ? imm : -imm);',
72 'predicate_test': predicateTest},
73 ['IsMicroop'])
74
75 microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
76 'MicroMemOp',
77 {'memacc_code': 'Mem = Ra;',
78 'ea_code': 'EA = Rb + (UP ? imm : -imm);',
79 'predicate_test': predicateTest},
80 ['IsMicroop'])
81
82 header_output = MicroMemDeclare.subst(microLdrUopIop) + \
83 MicroMemDeclare.subst(microStrUopIop)
84 decoder_output = MicroConstructor.subst(microLdrUopIop) + \
85 MicroConstructor.subst(microStrUopIop)
86 exec_output = LoadExecute.subst(microLdrUopIop) + \
87 StoreExecute.subst(microStrUopIop) + \
88 LoadInitiateAcc.subst(microLdrUopIop) + \
89 StoreInitiateAcc.subst(microStrUopIop) + \
90 LoadCompleteAcc.subst(microLdrUopIop) + \
91 StoreCompleteAcc.subst(microStrUopIop)
92}};
93
94////////////////////////////////////////////////////////////////////
95//
96// Integer = Integer op Immediate microops
97//
98
99def template MicroIntDeclare {{
100 class %(class_name)s : public %(base_class)s
101 {
102 public:
103 %(class_name)s(ExtMachInst machInst,
104 RegIndex _ura, RegIndex _urb,
105 uint8_t _imm);
106 %(BasicExecDeclare)s
107 };
108}};
109
110let {{
111 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
112 'MicroIntOp',
113 {'code': 'Ra = Rb + imm;',
114 'predicate_test': predicateTest},
115 ['IsMicroop'])
116
117 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
118 'MicroIntOp',
119 {'code': 'Ra = Rb - imm;',
120 'predicate_test': predicateTest},
121 ['IsMicroop'])
122
123 header_output = MicroIntDeclare.subst(microAddiUopIop) + \
124 MicroIntDeclare.subst(microSubiUopIop)
125 decoder_output = MicroConstructor.subst(microAddiUopIop) + \
126 MicroConstructor.subst(microSubiUopIop)
127 exec_output = PredOpExecute.subst(microAddiUopIop) + \
128 PredOpExecute.subst(microSubiUopIop)
129}};
130
131////////////////////////////////////////////////////////////////////
132//
133// Moving to/from double floating point registers
134//
135
136let {{
137 microMvtdUopIop = InstObjParams('mvtd_uop', 'MicroMvtdUop',
138 'PredOp',
139 {'code': 'Fd.ud = (Rhi.ud << 32) | Rlo;',
140 'predicate_test': predicateTest},
141 ['IsMicroop'])
142
143 microMvfdUopIop = InstObjParams('mvfd_uop', 'MicroMvfdUop',
144 'PredOp',
145 {'code': '''Rhi = bits(Fd.ud, 63, 32);
146 Rlo = bits(Fd.ud, 31, 0);''',
147 'predicate_test': predicateTest},
148 ['IsMicroop'])
149
150 header_output = BasicDeclare.subst(microMvtdUopIop) + \
151 BasicDeclare.subst(microMvfdUopIop)
152 decoder_output = BasicConstructor.subst(microMvtdUopIop) + \
153 BasicConstructor.subst(microMvfdUopIop)
154 exec_output = PredOpExecute.subst(microMvtdUopIop) + \
155 PredOpExecute.subst(microMvfdUopIop)
156}};
157
158////////////////////////////////////////////////////////////////////
159//
160// Macro Memory-format instructions
161//
162
163def template MacroStoreDeclare {{
164/**
165 * Static instructions class for a store multiple instruction
166 */
167class %(class_name)s : public %(base_class)s
168{
169 public:
170 // Constructor
171 %(class_name)s(ExtMachInst machInst);
172 %(BasicExecDeclare)s
173};
174}};
175
176def template MacroStoreConstructor {{
177inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
178 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
179{
180 %(constructor)s;
181 uint32_t regs = reglist;
182 uint32_t addr = 0;
183 bool up = machInst.puswl.up;
183
184 if (!up)
185 addr = (ones << 2) - 4;
186
184
185 if (!up)
186 addr = (ones << 2) - 4;
187
187 if (prepost)
188 if (machInst.puswl.prepost)
188 addr += 4;
189
190 // Add 0 to Rn and stick it in ureg0.
191 // This is equivalent to a move.
192 microOps[0] = new MicroAddiUop(machInst, INTREG_UREG0, RN, 0);
193
194 unsigned reg = 0;
195 for (int i = 1; i < ones + 1; i++) {
196 // Find the next register.
197 while (!bits(regs, reg))
198 reg++;
199 replaceBits(regs, reg, 0);
200
189 addr += 4;
190
191 // Add 0 to Rn and stick it in ureg0.
192 // This is equivalent to a move.
193 microOps[0] = new MicroAddiUop(machInst, INTREG_UREG0, RN, 0);
194
195 unsigned reg = 0;
196 for (int i = 1; i < ones + 1; i++) {
197 // Find the next register.
198 while (!bits(regs, reg))
199 reg++;
200 replaceBits(regs, reg, 0);
201
201 if (loadop)
202 microOps[i] = new MicroLdrUop(machInst, reg, INTREG_UREG0, addr);
203 else
204 microOps[i] = new MicroStrUop(machInst, reg, INTREG_UREG0, addr);
202 unsigned regIdx = reg;
203 if (machInst.puswl.psruser) {
204 regIdx = intRegForceUser(regIdx);
205 }
205
206
207 if (machInst.puswl.loadOp) {
208 microOps[i] =
209 new MicroLdrUop(machInst, regIdx, INTREG_UREG0, addr);
210 } else {
211 microOps[i] =
212 new MicroStrUop(machInst, regIdx, INTREG_UREG0, addr);
213 }
214
206 if (up)
207 addr += 4;
208 else
209 addr -= 4;
210 }
211
212 StaticInstPtr &lastUop = microOps[numMicroops - 1];
215 if (up)
216 addr += 4;
217 else
218 addr -= 4;
219 }
220
221 StaticInstPtr &lastUop = microOps[numMicroops - 1];
213 if (writeback) {
222 if (machInst.puswl.writeback) {
214 if (up) {
215 lastUop = new MicroAddiUop(machInst, RN, RN, ones * 4);
216 } else {
217 lastUop = new MicroSubiUop(machInst, RN, RN, ones * 4);
218 }
219 }
220 lastUop->setLastMicroop();
221}
222
223}};
224
225def template MacroStoreExecute {{
226Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
227{
228 Fault fault = NoFault;
229
230 %(fp_enable_check)s;
231 %(op_decl)s;
232 %(op_rd)s;
233 %(code)s;
234 if (fault == NoFault)
235 {
236 %(op_wb)s;
237 }
238
239 return fault;
240}
241}};
242
243def template MacroFPAConstructor {{
244inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
245 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
246{
247 %(constructor)s;
248
249 uint32_t start_addr = 0;
250
251 if (prepost)
252 start_addr = disp8;
253 else
254 start_addr = 0;
255
256 emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr);
257
258 if (writeback)
259 {
260 if (up) {
261 microOps[numMicroops - 1] =
262 new MicroAddiUop(machInst, RN, RN, disp8);
263 } else {
264 microOps[numMicroops - 1] =
265 new MicroSubiUop(machInst, RN, RN, disp8);
266 }
267 }
268 microOps[numMicroops - 1]->setLastMicroop();
269}
270
271}};
272
273
274def template MacroFMConstructor {{
275inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
276 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
277{
278 %(constructor)s;
279
280 uint32_t start_addr = 0;
281
282 if (prepost)
283 start_addr = disp8;
284 else
285 start_addr = 0;
286
287 for (int i = 0; i < count; i++)
288 emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr);
289
290 if (writeback) {
291 if (up) {
292 microOps[numMicroops - 1] =
293 new MicroAddiUop(machInst, RN, RN, disp8);
294 } else {
295 microOps[numMicroops - 1] =
296 new MicroSubiUop(machInst, RN, RN, disp8);
297 }
298 }
299 microOps[numMicroops - 1]->setLastMicroop();
300}
301}};
302
303
304def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{
305 iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags)
306 header_output = MacroStoreDeclare.subst(iop)
307 decoder_output = MacroStoreConstructor.subst(iop)
308 decode_block = BasicDecode.subst(iop)
309 exec_output = MacroStoreExecute.subst(iop)
310}};
311
312def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
313 iop = InstObjParams(name, Name, 'ArmMacroFPAOp',
314 {"code": code,
315 "predicate_test": predicateTest},
316 opt_flags)
317 header_output = BasicDeclare.subst(iop)
318 decoder_output = MacroFPAConstructor.subst(iop)
319 decode_block = BasicDecode.subst(iop)
320 exec_output = PredOpExecute.subst(iop)
321}};
322
323def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
324 iop = InstObjParams(name, Name, 'ArmMacroFMOp',
325 {"code": code,
326 "predicate_test": predicateTest},
327 opt_flags)
328 header_output = BasicDeclare.subst(iop)
329 decoder_output = MacroFMConstructor.subst(iop)
330 decode_block = BasicDecode.subst(iop)
331 exec_output = PredOpExecute.subst(iop)
332}};
223 if (up) {
224 lastUop = new MicroAddiUop(machInst, RN, RN, ones * 4);
225 } else {
226 lastUop = new MicroSubiUop(machInst, RN, RN, ones * 4);
227 }
228 }
229 lastUop->setLastMicroop();
230}
231
232}};
233
234def template MacroStoreExecute {{
235Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
236{
237 Fault fault = NoFault;
238
239 %(fp_enable_check)s;
240 %(op_decl)s;
241 %(op_rd)s;
242 %(code)s;
243 if (fault == NoFault)
244 {
245 %(op_wb)s;
246 }
247
248 return fault;
249}
250}};
251
252def template MacroFPAConstructor {{
253inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
254 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
255{
256 %(constructor)s;
257
258 uint32_t start_addr = 0;
259
260 if (prepost)
261 start_addr = disp8;
262 else
263 start_addr = 0;
264
265 emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr);
266
267 if (writeback)
268 {
269 if (up) {
270 microOps[numMicroops - 1] =
271 new MicroAddiUop(machInst, RN, RN, disp8);
272 } else {
273 microOps[numMicroops - 1] =
274 new MicroSubiUop(machInst, RN, RN, disp8);
275 }
276 }
277 microOps[numMicroops - 1]->setLastMicroop();
278}
279
280}};
281
282
283def template MacroFMConstructor {{
284inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
285 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
286{
287 %(constructor)s;
288
289 uint32_t start_addr = 0;
290
291 if (prepost)
292 start_addr = disp8;
293 else
294 start_addr = 0;
295
296 for (int i = 0; i < count; i++)
297 emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr);
298
299 if (writeback) {
300 if (up) {
301 microOps[numMicroops - 1] =
302 new MicroAddiUop(machInst, RN, RN, disp8);
303 } else {
304 microOps[numMicroops - 1] =
305 new MicroSubiUop(machInst, RN, RN, disp8);
306 }
307 }
308 microOps[numMicroops - 1]->setLastMicroop();
309}
310}};
311
312
313def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{
314 iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags)
315 header_output = MacroStoreDeclare.subst(iop)
316 decoder_output = MacroStoreConstructor.subst(iop)
317 decode_block = BasicDecode.subst(iop)
318 exec_output = MacroStoreExecute.subst(iop)
319}};
320
321def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
322 iop = InstObjParams(name, Name, 'ArmMacroFPAOp',
323 {"code": code,
324 "predicate_test": predicateTest},
325 opt_flags)
326 header_output = BasicDeclare.subst(iop)
327 decoder_output = MacroFPAConstructor.subst(iop)
328 decode_block = BasicDecode.subst(iop)
329 exec_output = PredOpExecute.subst(iop)
330}};
331
332def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
333 iop = InstObjParams(name, Name, 'ArmMacroFMOp',
334 {"code": code,
335 "predicate_test": predicateTest},
336 opt_flags)
337 header_output = BasicDeclare.subst(iop)
338 decoder_output = MacroFMConstructor.subst(iop)
339 decode_block = BasicDecode.subst(iop)
340 exec_output = PredOpExecute.subst(iop)
341}};