arch-power: Add character compare instructions
[gem5.git] / src / arch / power / isa / formats / integer.isa
1 // -*- mode:c++ -*-
2
3 // Copyright (c) 2009 The University of Edinburgh
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 ////////////////////////////////////////////////////////////////////
30 //
31 // Integer ALU instructions
32 //
33
34
35 // Instruction class constructor template when Rc is set.
36 def template IntRcConstructor {{
37 %(class_name)s::%(class_name)s(ExtMachInst machInst) :
38 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
39 {
40 %(set_reg_idx_arr)s;
41 %(constructor)s;
42 rcSet = true;
43 }
44 }};
45
46
47 // Instruction class constructor template when OE is set.
48 def template IntOeConstructor {{
49 %(class_name)s::%(class_name)s(ExtMachInst machInst) :
50 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
51 {
52 %(set_reg_idx_arr)s;
53 %(constructor)s;
54 oeSet = true;
55 }
56 }};
57
58
59 // Instruction class constructor template when both Rc and OE are set.
60 def template IntRcOeConstructor {{
61 %(class_name)s::%(class_name)s(ExtMachInst machInst) :
62 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
63 {
64 %(set_reg_idx_arr)s;
65 %(constructor)s;
66 rcSet = true;
67 oeSet = true;
68 }
69 }};
70
71
72 let {{
73
74 readXERCode = 'M5_VAR_USED Xer xer = XER;'
75
76 setXERCode = 'XER = xer;'
77
78 computeCR0Code = '''
79 Cr cr = CR;
80 cr.cr0 = makeCRField((int64_t)%(result)s, (int64_t)0, xer.so);
81 CR = cr;
82 '''
83
84 computeCACode = '''
85 if (findCarry(64, %(result)s, %(inputa)s, %(inputb)s)) {
86 xer.ca = 1;
87 } else {
88 xer.ca = 0;
89 }
90
91 if (findCarry(32, %(result)s, %(inputa)s, %(inputb)s)) {
92 xer.ca32 = 1;
93 } else {
94 xer.ca32 = 0;
95 }
96 '''
97
98 computeOVCode = '''
99 if (findOverflow(64, %(result)s, %(inputa)s, %(inputb)s)) {
100 xer.ov = 1;
101 xer.so = 1;
102 } else {
103 xer.ov = 0;
104 }
105
106 if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) {
107 xer.ov32 = 1;
108 } else {
109 xer.ov32 = 0;
110 }
111 '''
112
113 setOVCode = '''
114 if (setOV) {
115 xer.ov = 1;
116 xer.ov32 = 1;
117 xer.so = 1;
118 } else {
119 xer.ov = 0;
120 xer.ov32 = 0;
121 }
122 '''
123
124 }};
125
126
127 // A basic integer instruction.
128 def format IntOp(code, inst_flags = []) {{
129 (header_output, decoder_output, decode_block, exec_output) = \
130 GenAluOp(name, Name, 'IntOp', code, inst_flags, BasicDecode,
131 BasicConstructor)
132 }};
133
134
135 // Integer instructions with immediate (signed or unsigned).
136 def format IntImmOp(code, inst_flags = []) {{
137 (header_output, decoder_output, decode_block, exec_output) = \
138 GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode,
139 BasicConstructor)
140 }};
141
142
143 // Integer instructions with immediate that perform arithmetic.
144 // These instructions all write to Rt and use an altered form of the
145 // value in source register Ra, hence the use of src to hold the actual
146 // value. The control flags include the use of code to compute the
147 // carry bit or the CR0 code.
148 def format IntImmArithOp(code, computeCA = 0, computeCR0 = 0,
149 inst_flags = []) {{
150
151 # Set up the dictionary
152 dict = {'result':'Rt', 'inputa':'src', 'inputb':'simm'}
153
154 # Deal with computing CR0 and carry
155 if computeCA or computeCR0:
156 code += readXERCode
157 if computeCA:
158 code += computeCACode % dict + setXERCode
159 if computeCR0:
160 code += computeCR0Code % dict
161
162 # Generate the class
163 (header_output, decoder_output, decode_block, exec_output) = \
164 GenAluOp(name, Name, 'IntImmArithOp', code, inst_flags, BasicDecode,
165 BasicConstructor)
166 }};
167
168
169 // Integer instructions with immediate that perform arithmetic but use
170 // the value 0 when Ra == 0. We generate two versions of each instruction
171 // corresponding to these two different scenarios. The correct version is
172 // determined at decode (see the CheckRaDecode template).
173 def format IntImmArithCheckRaOp(code, code_ra0, inst_flags = []) {{
174
175 # First the version where Ra is non-zero
176 (header_output, decoder_output, decode_block, exec_output) = \
177 GenAluOp(name, Name, 'IntImmArithOp', code, inst_flags,
178 CheckRaDecode, BasicConstructor)
179
180 # Now another version where Ra == 0
181 (header_output_ra0, decoder_output_ra0, _, exec_output_ra0) = \
182 GenAluOp(name, Name + 'RaZero', 'IntImmArithOp', code_ra0, inst_flags,
183 CheckRaDecode, BasicConstructor)
184
185 # Finally, add to the other outputs
186 header_output += header_output_ra0
187 decoder_output += decoder_output_ra0
188 exec_output += exec_output_ra0
189 }};
190
191
192 // Integer instructions with immediate that perform logic operations.
193 // All instructions write to Ra and use Rs as a source register. Some
194 // also compute the CR0 code too.
195 def format IntImmLogicOp(code, computeCR0 = 0, inst_flags = []) {{
196
197 # Set up the dictionary and deal with computing CR0
198 dict = {'result':'Ra'}
199 if computeCR0:
200 code += readXERCode + computeCR0Code % dict
201
202 # Generate the class
203 (header_output, decoder_output, decode_block, exec_output) = \
204 GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode,
205 BasicConstructor)
206 }};
207
208
209 // Integer instructions with displacement that perform arithmetic.
210 // There are no control flags to set.
211 def format IntDispArithOp(code, inst_flags = []) {{
212
213 # Generate the class
214 (header_output, decoder_output, decode_block, exec_output) = \
215 GenAluOp(name, Name, 'IntDispArithOp', code, inst_flags, BasicDecode,
216 BasicConstructor)
217 }};
218
219
220 // Integer compare instructions.
221 def format IntCompOp(code, inst_flags = []) {{
222
223 # Add code to setup variables
224 code = 'M5_VAR_USED uint32_t cr = 0;\n' + code
225 code += 'CR = insertCRField(CR, field, cr);\n'
226
227 # Add code to access XER
228 code = readXERCode + code
229
230 # Generate the class
231 (header_output, decoder_output, decode_block, exec_output) = \
232 GenAluOp(name, Name, 'IntCompOp', code, inst_flags, BasicDecode,
233 BasicConstructor)
234 }};
235
236
237 // Integer immediate compare instructions.
238 def format IntImmCompOp(code, inst_flags = []) {{
239
240 # Add code to setup variables
241 code = 'M5_VAR_USED uint32_t cr = 0;\n' + code
242 code += 'CR = insertCRField(CR, field, cr);\n'
243
244 # Add code to access XER
245 code = readXERCode + code
246
247 # Generate the class
248 (header_output, decoder_output, decode_block, exec_output) = \
249 GenAluOp(name, Name, 'IntImmCompOp', code, inst_flags, BasicDecode,
250 BasicConstructor)
251 }};
252
253
254 // Integer immediate compare logical instructions.
255 def format IntImmCompLogicOp(code, inst_flags = []) {{
256
257 # Add code to setup variables
258 code = 'M5_VAR_USED uint32_t cr = 0;\n' + code
259 code += 'CR = insertCRField(CR, field, cr);\n'
260
261 # Add code to access XER
262 code = readXERCode + code
263
264 # Generate the class
265 (header_output, decoder_output, decode_block, exec_output) = \
266 GenAluOp(name, Name, 'IntImmCompLogicOp', code, inst_flags,
267 BasicDecode, BasicConstructor)
268 }};
269
270
271 // Integer instructions that perform logic operations. The result is
272 // always written into Ra. All instructions have 2 versions depending on
273 // whether the Rc bit is set to compute the CR0 code. This is determined
274 // at decode as before.
275 def format IntLogicOp(code, inst_flags = []) {{
276 dict = {'result':'Ra'}
277
278 # Code when Rc is set
279 code_rc1 = code + readXERCode + computeCR0Code % dict
280
281 # Generate the first class
282 (header_output, decoder_output, decode_block, exec_output) = \
283 GenAluOp(name, Name, 'IntOp', code, inst_flags,
284 CheckRcDecode, BasicConstructor)
285
286 # Generate the second class
287 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
288 GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags,
289 CheckRcDecode, IntRcConstructor)
290
291 # Finally, add to the other outputs
292 header_output += header_output_rc1
293 decoder_output += decoder_output_rc1
294 exec_output += exec_output_rc1
295 }};
296
297
298 // Integer instructions with a shift amount. As above, except inheriting
299 // from the IntShiftOp class.
300 def format IntShiftOp(code, inst_flags = []) {{
301 dict = {'result':'Ra'}
302
303 # Code when Rc is set
304 code_rc1 = code + readXERCode + computeCR0Code % dict
305
306 # Generate the first class
307 (header_output, decoder_output, decode_block, exec_output) = \
308 GenAluOp(name, Name, 'IntShiftOp', code, inst_flags,
309 CheckRcDecode, BasicConstructor)
310
311 # Generate the second class
312 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
313 GenAluOp(name, Name + 'RcSet', 'IntShiftOp', code_rc1, inst_flags,
314 CheckRcDecode, IntRcConstructor)
315
316 # Finally, add to the other outputs
317 header_output += header_output_rc1
318 decoder_output += decoder_output_rc1
319 exec_output += exec_output_rc1
320 }};
321
322
323 // Instructions in this format are all reduced to the form Rt = src1 + src2,
324 // therefore we just give src1 and src2 definitions. In working out the
325 // template we first put in the definitions of the variables and then
326 // the code for the addition. We also deal with computing the carry flag
327 // if required.
328 //
329 // We generate 4 versions of each instruction. This correspond to the
330 // different combinations of having the OE bit set or unset (which controls
331 // whether the overflow flag is computed) and the Rc bit set or unset too
332 // (which controls whether the CR0 code is computed).
333 def format IntSumOp(src1, src2, ca = {{ 0 }}, computeCA = 0,
334 inst_flags = []) {{
335
336 # The result is always in Rt, but the source values vary
337 dict = {'result':'Rt', 'inputa':'src1', 'inputb':'src2'}
338
339 # Add code to set up variables and do the sum
340 code = 'uint64_t src1 = ' + src1 + ';\n'
341 code += 'uint64_t src2 = ' + src2 + ';\n'
342 code += 'uint64_t ca = ' + ca + ';\n'
343 code += 'Rt = src1 + src2 + ca;\n'
344
345 # Add code for calculating the carry, if needed
346 if computeCA:
347 code += computeCACode % dict + setXERCode
348
349 # Setup the 4 code versions and add code to access XER if necessary
350 code_rc1 = readXERCode + code
351 code_oe1 = readXERCode + code + computeOVCode % dict + setXERCode
352 code_rc1_oe1 = readXERCode + code + computeOVCode % dict + setXERCode
353 if (computeCA or ca == 'xer.ca'):
354 code = readXERCode + code
355 code_rc1 += computeCR0Code % dict
356 code_rc1_oe1 += computeCR0Code % dict
357
358 # Generate the classes
359 (header_output, decoder_output, decode_block, exec_output) = \
360 GenAluOp(name, Name, 'IntArithOp', code, inst_flags,
361 CheckRcOeDecode, BasicConstructor)
362 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
363 GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1, inst_flags,
364 CheckRcOeDecode, IntRcConstructor)
365 (header_output_oe1, decoder_output_oe1, _, exec_output_oe1) = \
366 GenAluOp(name, Name + 'OeSet', 'IntArithOp', code_oe1, inst_flags,
367 CheckRcOeDecode, IntOeConstructor)
368 (header_output_rc1_oe1, decoder_output_rc1_oe1, _, exec_output_rc1_oe1) = \
369 GenAluOp(name, Name + 'RcSetOeSet', 'IntArithOp', code_rc1_oe1,
370 inst_flags, CheckRcOeDecode, IntRcOeConstructor)
371
372 # Finally, add to the other outputs
373 header_output += \
374 header_output_rc1 + header_output_oe1 + header_output_rc1_oe1
375 decoder_output += \
376 decoder_output_rc1 + decoder_output_oe1 + decoder_output_rc1_oe1
377 exec_output += \
378 exec_output_rc1 + exec_output_oe1 + exec_output_rc1_oe1
379
380 }};
381
382 // Instructions that use source registers Ra and Rb, with the result
383 // placed into Rt but do not check for carry, overflow or the Rc bit.
384 def format IntArithOp(code, inst_flags = []) {{
385
386 # Generate the class
387 (header_output, decoder_output, decode_block, exec_output) = \
388 GenAluOp(name, Name, 'IntArithOp', code, inst_flags, BasicDecode,
389 BasicConstructor)
390 }};
391
392
393 // Instructions that use source registers Ra and Rb, with the result
394 // placed into Rt. Basically multiply and divide instructions. The
395 // carry bit is never set, but overflow can be calculated. In certain
396 // situations, the overflow bits have to be set and this is dealt with
397 // using the 'setOV' boolean in decoder.isa.
398 //
399 // In case overflow is to be calculated, we generate four versions of
400 // each instruction to deal with different combinations of having the
401 // OE bit set or unset and the Rc bit set or unset too. Otherwise, we
402 // generate two versions of each instruction to deal with the Rc bit.
403 def format IntArithCheckRcOp(code, computeOV = 0, inst_flags = []) {{
404
405 # The result is always in Rt, but the source values vary
406 dict = {'result':'Rt', 'inputa':'src1', 'inputb':'src2'}
407
408 # Deal with setting the overflow flag
409 if computeOV:
410 # Setup the 4 code versions and add code to access XER if necessary
411 code = 'M5_VAR_USED bool setOV = false;\n' + code
412 code_rc1 = readXERCode + code + computeCR0Code % dict
413 code_oe1 = readXERCode + code + setOVCode + setXERCode
414 code_rc1_oe1 = readXERCode + code + setOVCode + setXERCode
415 code_rc1_oe1 += computeCR0Code % dict
416
417 # Generate the classes
418 (header_output, decoder_output, decode_block, exec_output) = \
419 GenAluOp(name, Name, 'IntArithOp', code, inst_flags,
420 CheckRcOeDecode, BasicConstructor)
421 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
422 GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1, inst_flags,
423 CheckRcOeDecode, IntRcConstructor)
424 (header_output_oe1, decoder_output_oe1, _, exec_output_oe1) = \
425 GenAluOp(name, Name + 'OeSet', 'IntArithOp', code_oe1, inst_flags,
426 CheckRcOeDecode, IntOeConstructor)
427 (header_output_rc1_oe1, decoder_output_rc1_oe1, _,
428 exec_output_rc1_oe1) = \
429 GenAluOp(name, Name + 'RcSetOeSet', 'IntArithOp', code_rc1_oe1,
430 inst_flags, CheckRcOeDecode, IntRcOeConstructor)
431
432 # Finally, add to the other outputs
433 header_output += \
434 header_output_rc1 + header_output_oe1 + header_output_rc1_oe1
435 decoder_output += \
436 decoder_output_rc1 + decoder_output_oe1 + decoder_output_rc1_oe1
437 exec_output += \
438 exec_output_rc1 + exec_output_oe1 + exec_output_rc1_oe1
439
440 else:
441 # Setup the 2 code versions and add code to access XER if necessary
442 code_rc1 = readXERCode + code + computeCR0Code % dict
443
444 # Generate the first class
445 (header_output, decoder_output, decode_block, exec_output) = \
446 GenAluOp(name, Name, 'IntArithOp', code, inst_flags,
447 CheckRcDecode, BasicConstructor)
448
449 # Generate the second class
450 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
451 GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1, inst_flags,
452 CheckRcDecode, IntRcConstructor)
453
454 # Finally, add to the other outputs
455 header_output += header_output_rc1
456 decoder_output += decoder_output_rc1
457 exec_output += exec_output_rc1
458 }};
459
460
461 // A special format for rotate instructions which use certain fields
462 // from the instruction's binary encoding. We need two versions for each
463 // instruction to deal with the Rc bit.
464 def format IntRotateOp(code, inst_flags = []) {{
465
466 # The result is always in Ra
467 dict = {'result':'Ra'}
468
469 # Setup the code for when Rc is set
470 code_rc1 = readXERCode + code + computeCR0Code % dict
471
472 # Generate the first class
473 (header_output, decoder_output, decode_block, exec_output) = \
474 GenAluOp(name, Name, 'IntRotateOp', code, inst_flags,
475 CheckRcDecode, BasicConstructor)
476
477 # Generate the second class
478 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
479 GenAluOp(name, Name + 'RcSet', 'IntRotateOp', code_rc1, inst_flags,
480 CheckRcDecode, IntRcConstructor)
481
482 # Finally, add to the other outputs
483 header_output += header_output_rc1
484 decoder_output += decoder_output_rc1
485 exec_output += exec_output_rc1
486 }};