3 // Copyright (c) 2009 The University of Edinburgh
4 // Copyright (c) 2021 IBM Corporation
5 // All rights reserved.
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are
9 // met: redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer;
11 // redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution;
14 // neither the name of the copyright holders nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 ////////////////////////////////////////////////////////////////////
32 // Integer ALU instructions
36 // Instruction class constructor template when Rc is set.
37 def template IntRcConstructor {{
38 %(class_name)s::%(class_name)s(ExtMachInst machInst) :
39 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
48 // Instruction class constructor template when OE is set.
49 def template IntOeConstructor {{
50 %(class_name)s::%(class_name)s(ExtMachInst machInst) :
51 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
60 // Instruction class constructor template when both Rc and OE are set.
61 def template IntRcOeConstructor {{
62 %(class_name)s::%(class_name)s(ExtMachInst machInst) :
63 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
75 readXERCode = 'M5_VAR_USED Xer xer = XER;'
77 setXERCode = 'XER = xer;'
84 makeCRField((int64_t)%(result)s, (int64_t)0, xer.so) :
85 makeCRField((int32_t)%(result)s, (int32_t)0, xer.so);
93 if (findCarry(32, %(result)s, %(inputa)s, %(inputb)s)) {
102 if (findCarry(64, %(result)s, %(inputa)s, %(inputb)s)) {
114 if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) {
123 if (findOverflow(64, %(result)s, %(inputa)s, %(inputb)s)) {
160 // A basic integer instruction.
161 def format IntOp(code, inst_flags = []) {{
162 (header_output, decoder_output, decode_block, exec_output) = \
163 GenAluOp(name, Name, 'IntOp', code, inst_flags, BasicDecode,
168 // Integer instructions with immediate (signed or unsigned).
169 def format IntImmOp(code, inst_flags = []) {{
170 (header_output, decoder_output, decode_block, exec_output) = \
171 GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode,
176 // Integer instructions with immediate that perform arithmetic.
177 // These instructions all write to Rt and use an altered form of the
178 // value in source register Ra, hence the use of src to hold the actual
179 // value. The control flags include the use of code to compute the
180 // carry bit or the CR0 code.
181 def format IntImmArithOp(code, computeCA = 0, computeCR0 = 0,
184 # Set up the dictionary
185 dict = {'result':'Rt', 'inputa':'src', 'inputb':'simm'}
187 # Deal with computing CR0 and carry
188 if computeCA or computeCR0:
191 code += computeCACode % dict + setXERCode
193 code += computeCR0Code % dict
196 (header_output, decoder_output, decode_block, exec_output) = \
197 GenAluOp(name, Name, 'IntImmArithOp', code, inst_flags, BasicDecode,
202 // Integer instructions with immediate that perform arithmetic but use
203 // the value 0 when Ra == 0. We generate two versions of each instruction
204 // corresponding to these two different scenarios. The correct version is
205 // determined at decode (see the CheckRaDecode template).
206 def format IntImmArithCheckRaOp(code, code_ra0, inst_flags = []) {{
208 # First the version where Ra is non-zero
209 (header_output, decoder_output, decode_block, exec_output) = \
210 GenAluOp(name, Name, 'IntImmArithOp', code, inst_flags,
211 CheckRaDecode, BasicConstructor)
213 # Now another version where Ra == 0
214 (header_output_ra0, decoder_output_ra0, _, exec_output_ra0) = \
215 GenAluOp(name, Name + 'RaZero', 'IntImmArithOp', code_ra0, inst_flags,
216 CheckRaDecode, BasicConstructor)
218 # Finally, add to the other outputs
219 header_output += header_output_ra0
220 decoder_output += decoder_output_ra0
221 exec_output += exec_output_ra0
225 // Integer instructions with immediate that perform logic operations.
226 // All instructions write to Ra and use Rs as a source register. Some
227 // also compute the CR0 code too.
228 def format IntImmLogicOp(code, computeCR0 = 0, inst_flags = []) {{
230 # Set up the dictionary and deal with computing CR0
231 dict = {'result':'Ra'}
233 # Code when Rc is set
235 code += readXERCode + computeCR0Code % dict
238 (header_output, decoder_output, decode_block, exec_output) = \
239 GenAluOp(name, Name, 'IntImmLogicOp', code, inst_flags, BasicDecode,
244 // Integer instructions with displacement that perform arithmetic.
245 // There are no control flags to set.
246 def format IntDispArithOp(code, inst_flags = []) {{
249 (header_output, decoder_output, decode_block, exec_output) = \
250 GenAluOp(name, Name, 'IntDispArithOp', code, inst_flags, BasicDecode,
255 // Integer compare instructions.
256 def format IntCompOp(code, inst_flags = []) {{
258 # Add code to setup variables
259 code = 'M5_VAR_USED uint32_t cr = 0;\n' + code
260 code += 'CR = insertCRField(CR, field, cr);\n'
262 # Add code to access XER
263 code = readXERCode + code
266 (header_output, decoder_output, decode_block, exec_output) = \
267 GenAluOp(name, Name, 'IntCompOp', code, inst_flags, BasicDecode,
272 // Integer immediate compare instructions.
273 def format IntImmCompOp(code, inst_flags = []) {{
275 # Add code to setup variables
276 code = 'M5_VAR_USED uint32_t cr = 0;\n' + code
277 code += 'CR = insertCRField(CR, field, cr);\n'
279 # Add code to access XER
280 code = readXERCode + code
283 (header_output, decoder_output, decode_block, exec_output) = \
284 GenAluOp(name, Name, 'IntImmCompOp', code, inst_flags, BasicDecode,
289 // Integer immediate compare logical instructions.
290 def format IntImmCompLogicOp(code, inst_flags = []) {{
292 # Add code to setup variables
293 code = 'M5_VAR_USED uint32_t cr = 0;\n' + code
294 code += 'CR = insertCRField(CR, field, cr);\n'
296 # Add code to access XER
297 code = readXERCode + code
300 (header_output, decoder_output, decode_block, exec_output) = \
301 GenAluOp(name, Name, 'IntImmCompLogicOp', code, inst_flags,
302 BasicDecode, BasicConstructor)
306 // Integer instructions that perform logic operations. The result is
307 // always written into Ra. Some instructions have 2 versions depending on
308 // whether the Rc bit is set to compute the CR0 code. This is determined
309 // at decode as before.
310 def format IntLogicOp(code, computeCR0 = 0, inst_flags = []) {{
311 dict = {'result':'Ra'}
313 # Deal with computing CR0
315 # Setup the 2 code versions and add code to access XER if necessary
316 code_rc1 = code + readXERCode + computeCR0Code % dict
318 # Generate the first class
319 (header_output, decoder_output, decode_block, exec_output) = \
320 GenAluOp(name, Name, 'IntLogicOp', code, inst_flags,
321 CheckRcDecode, BasicConstructor)
323 # Generate the second class
324 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
325 GenAluOp(name, Name + 'RcSet', 'IntLogicOp', code_rc1, inst_flags,
326 CheckRcDecode, IntRcConstructor)
328 # Finally, add to the other outputs
329 header_output += header_output_rc1
330 decoder_output += decoder_output_rc1
331 exec_output += exec_output_rc1
335 (header_output, decoder_output, decode_block, exec_output) = \
336 GenAluOp(name, Name, 'IntLogicOp', code, inst_flags,
337 BasicDecode, BasicConstructor)
341 // Integer instructions that perform shift operations. All of these
342 // instructions write to Ra and use Rs as a source register. The shift
343 // value is obtained from an register or an instruction field. If it
344 // from a register, Rb is also used as a source register. In certain
345 // situations, the carry bits have to be set and this is dealt with
346 // using the 'setCA' boolean in decoder.isa. We need two versions for
347 // each instruction to deal with the Rc bit.
348 def format IntShiftOp(code, computeCA = 0, inst_flags = []) {{
349 dict = {'result':'Ra'}
351 # Add code to setup variables and access XER if necessary
352 code = 'M5_VAR_USED bool setCA = false;\n' + code
354 # Code when Rc is set
355 code_rc1 = readXERCode + code + computeCR0Code % dict
357 # Add code for calculating the carry, if needed
359 code = readXERCode + code + setCACode + setXERCode
360 code_rc1 += setCACode + setXERCode
362 # Generate the first class
363 (header_output, decoder_output, decode_block, exec_output) = \
364 GenAluOp(name, Name, 'IntShiftOp', code, inst_flags,
365 CheckRcDecode, BasicConstructor)
367 # Generate the second class
368 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
369 GenAluOp(name, Name + 'RcSet', 'IntShiftOp', code_rc1, inst_flags,
370 CheckRcDecode, IntRcConstructor)
372 # Finally, add to the other outputs
373 header_output += header_output_rc1
374 decoder_output += decoder_output_rc1
375 exec_output += exec_output_rc1
379 // Instructions in this format are all reduced to the form Rt = src1 + src2,
380 // therefore we just give src1 and src2 definitions. In working out the
381 // template we first put in the definitions of the variables and then
382 // the code for the addition. We also deal with computing the carry flag
385 // We generate 4 versions of each instruction. This correspond to the
386 // different combinations of having the OE bit set or unset (which controls
387 // whether the overflow flag is computed) and the Rc bit set or unset too
388 // (which controls whether the CR0 code is computed).
389 def format IntSumOp(src1, src2, ca = {{ 0 }}, computeCA = 0,
392 # The result is always in Rt, but the source values vary
393 dict = {'result':'Rt', 'inputa':'src1', 'inputb':'src2'}
395 # Add code to set up variables and do the sum
396 code = 'uint64_t src1 = ' + src1 + ';\n'
397 code += 'uint64_t src2 = ' + src2 + ';\n'
398 code += 'uint64_t ca = ' + ca + ';\n'
399 code += 'Rt = src1 + src2 + ca;\n'
401 # Add code for calculating the carry, if needed
403 code += computeCACode % dict + setXERCode
405 # Setup the 4 code versions and add code to access XER if necessary
406 code_rc1 = readXERCode + code
407 code_oe1 = readXERCode + code + computeOVCode % dict + setXERCode
408 code_rc1_oe1 = readXERCode + code + computeOVCode % dict + setXERCode
409 if (computeCA or ca == 'xer.ca'):
410 code = readXERCode + code
411 code_rc1 += computeCR0Code % dict
412 code_rc1_oe1 += computeCR0Code % dict
414 # Generate the classes
415 (header_output, decoder_output, decode_block, exec_output) = \
416 GenAluOp(name, Name, 'IntArithOp', code, inst_flags,
417 CheckRcOeDecode, BasicConstructor)
418 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
419 GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1, inst_flags,
420 CheckRcOeDecode, IntRcConstructor)
421 (header_output_oe1, decoder_output_oe1, _, exec_output_oe1) = \
422 GenAluOp(name, Name + 'OeSet', 'IntArithOp', code_oe1, inst_flags,
423 CheckRcOeDecode, IntOeConstructor)
424 (header_output_rc1_oe1, decoder_output_rc1_oe1, _, exec_output_rc1_oe1) = \
425 GenAluOp(name, Name + 'RcSetOeSet', 'IntArithOp', code_rc1_oe1,
426 inst_flags, CheckRcOeDecode, IntRcOeConstructor)
428 # Finally, add to the other outputs
430 header_output_rc1 + header_output_oe1 + header_output_rc1_oe1
432 decoder_output_rc1 + decoder_output_oe1 + decoder_output_rc1_oe1
434 exec_output_rc1 + exec_output_oe1 + exec_output_rc1_oe1
438 // Instructions that use source registers Ra and Rb, with the result
439 // placed into Rt but do not check for carry, overflow or the Rc bit.
440 def format IntArithOp(code, inst_flags = []) {{
443 (header_output, decoder_output, decode_block, exec_output) = \
444 GenAluOp(name, Name, 'IntArithOp', code, inst_flags, BasicDecode,
449 // Instructions that use source registers Ra and Rb, with the result
450 // placed into Rt. Basically multiply and divide instructions. The
451 // carry bit is never set, but overflow can be calculated. In certain
452 // situations, the overflow bits have to be set and this is dealt with
453 // using the 'setOV' boolean in decoder.isa.
455 // In case overflow is to be calculated, we generate four versions of
456 // each instruction to deal with different combinations of having the
457 // OE bit set or unset and the Rc bit set or unset too. Otherwise, we
458 // generate two versions of each instruction to deal with the Rc bit.
459 def format IntArithCheckRcOp(code, computeOV = 0, inst_flags = []) {{
461 # The result is always in Rt, but the source values vary
462 dict = {'result':'Rt', 'inputa':'src1', 'inputb':'src2'}
464 # Deal with setting the overflow flag
466 # Setup the 4 code versions and add code to access XER if necessary
467 code = 'M5_VAR_USED bool setOV = false;\n' + code
468 code_rc1 = readXERCode + code + computeCR0Code % dict
469 code_oe1 = readXERCode + code + setOVCode + setXERCode
470 code_rc1_oe1 = readXERCode + code + setOVCode + setXERCode
471 code_rc1_oe1 += computeCR0Code % dict
473 # Generate the classes
474 (header_output, decoder_output, decode_block, exec_output) = \
475 GenAluOp(name, Name, 'IntArithOp', code, inst_flags,
476 CheckRcOeDecode, BasicConstructor)
477 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
478 GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1, inst_flags,
479 CheckRcOeDecode, IntRcConstructor)
480 (header_output_oe1, decoder_output_oe1, _, exec_output_oe1) = \
481 GenAluOp(name, Name + 'OeSet', 'IntArithOp', code_oe1, inst_flags,
482 CheckRcOeDecode, IntOeConstructor)
483 (header_output_rc1_oe1, decoder_output_rc1_oe1, _,
484 exec_output_rc1_oe1) = \
485 GenAluOp(name, Name + 'RcSetOeSet', 'IntArithOp', code_rc1_oe1,
486 inst_flags, CheckRcOeDecode, IntRcOeConstructor)
488 # Finally, add to the other outputs
490 header_output_rc1 + header_output_oe1 + header_output_rc1_oe1
492 decoder_output_rc1 + decoder_output_oe1 + decoder_output_rc1_oe1
494 exec_output_rc1 + exec_output_oe1 + exec_output_rc1_oe1
497 # Setup the 2 code versions and add code to access XER if necessary
498 code_rc1 = readXERCode + code + computeCR0Code % dict
500 # Generate the first class
501 (header_output, decoder_output, decode_block, exec_output) = \
502 GenAluOp(name, Name, 'IntArithOp', code, inst_flags,
503 CheckRcDecode, BasicConstructor)
505 # Generate the second class
506 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
507 GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1, inst_flags,
508 CheckRcDecode, IntRcConstructor)
510 # Finally, add to the other outputs
511 header_output += header_output_rc1
512 decoder_output += decoder_output_rc1
513 exec_output += exec_output_rc1
517 // Integer instructions that also perform shift operations. Everything
518 // is same as above except if the shift value is not obtained from a
519 // register, two immediates need to be concatenated to get the final
521 def format IntConcatShiftOp(code, computeCA = 0, inst_flags = []) {{
522 dict = {'result':'Ra'}
524 # Add code to setup variables and access XER if necessary
525 code = 'M5_VAR_USED bool setCA = false;\n' + code
527 # Code when Rc is set
528 code_rc1 = readXERCode + code + computeCR0Code % dict
530 # Add code for calculating the carry, if needed
532 code = readXERCode + code + setCACode + setXERCode
533 code_rc1 += setCACode + setXERCode
535 # Generate the first class
536 (header_output, decoder_output, decode_block, exec_output) = \
537 GenAluOp(name, Name, 'IntConcatShiftOp', code, inst_flags,
538 CheckRcDecode, BasicConstructor)
540 # Generate the second class
541 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
542 GenAluOp(name, Name + 'RcSet', 'IntConcatShiftOp', code_rc1,
543 inst_flags, CheckRcDecode, IntRcConstructor)
545 # Finally, add to the other outputs
546 header_output += header_output_rc1
547 decoder_output += decoder_output_rc1
548 exec_output += exec_output_rc1
552 // Integer instructions with or without immediate that perform rotate
553 // operations. All instructions write to Ra and use Rs as a source
554 // register. If immediate is not used, Rb is also used as a source
555 // register. We need two versions for each instruction to deal with
557 def format IntRotateOp(code, inst_flags = []) {{
559 # The result is always in Ra
560 dict = {'result':'Ra'}
562 # Code when Rc is set
563 code_rc1 = readXERCode + code + computeCR0Code % dict
565 # Generate the first class
566 (header_output, decoder_output, decode_block, exec_output) = \
567 GenAluOp(name, Name, 'IntRotateOp', code, inst_flags,
568 CheckRcDecode, BasicConstructor)
570 # Generate the second class
571 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
572 GenAluOp(name, Name + 'RcSet', 'IntRotateOp', code_rc1, inst_flags,
573 CheckRcDecode, IntRcConstructor)
575 # Finally, add to the other outputs
576 header_output += header_output_rc1
577 decoder_output += decoder_output_rc1
578 exec_output += exec_output_rc1
582 // Everything is same as above except that the immediates may need to be
583 // concatenated to get the final values for the mask bounds or the shift
584 // value. We need two versions for each instruction to deal with the Rc
586 def format IntConcatRotateOp(code, inst_flags = []) {{
588 # The result is always in Ra
589 dict = {'result':'Ra'}
591 # Code when Rc is set
592 code_rc1 = readXERCode + code + computeCR0Code % dict
594 # Generate the first class
595 (header_output, decoder_output, decode_block, exec_output) = \
596 GenAluOp(name, Name, 'IntConcatRotateOp', code, inst_flags,
597 CheckRcDecode, BasicConstructor)
599 # Generate the second class
600 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
601 GenAluOp(name, Name + 'RcSet', 'IntConcatRotateOp', code_rc1,
602 inst_flags, CheckRcDecode, IntRcConstructor)
604 # Finally, add to the other outputs
605 header_output += header_output_rc1
606 decoder_output += decoder_output_rc1
607 exec_output += exec_output_rc1
611 def format IntTrapOp(src1, src2, inst_flags = []) {{
613 # Add code to set up variables and check for a trap
614 code = 'int64_t src1 = ' + src1 + ';\n'
615 code += 'int64_t src2 = ' + src2 + ';\n'
616 code += 'if (checkTrap(src1, src2)) {\n'
617 code += ' panic("trap generated at %#x", xc->pcState().pc());\n'
618 code += ' return std::make_shared<TrapFault>();\n'
621 (header_output, decoder_output, decode_block, exec_output) = \
622 GenAluOp(name, Name, 'IntTrapOp', code, inst_flags, BasicDecode,
627 def format IntImmTrapOp(src, inst_flags = []) {{
629 # Add code to set up variables and check for a trap
630 code = 'int64_t src = ' + src + ';\n'
631 code += 'if (checkTrap(src, this->simm)) {\n'
632 code += ' panic("trap generated at %#x", xc->pcState().pc());\n'
633 code += ' return std::make_shared<TrapFault>();\n'
636 (header_output, decoder_output, decode_block, exec_output) = \
637 GenAluOp(name, Name, 'IntImmTrapOp', code, inst_flags, BasicDecode,