| // -*- mode:c++ -*- |
| |
| // Copyright (c) 2009 The University of Edinburgh |
| // Copyright (c) 2021 IBM Corporation |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer; |
| // redistributions in binary form must reproduce the above copyright |
| // notice, this list of conditions and the following disclaimer in the |
| // documentation and/or other materials provided with the distribution; |
| // neither the name of the copyright holders nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| //////////////////////////////////////////////////////////////////// |
| // |
| // Integer ALU instructions |
| // |
| |
| let {{ |
| |
| readXERCode = '[[maybe_unused]] Xer xer = XER;' |
| |
| setXERCode = 'XER = xer;' |
| |
| computeCR0Code = ''' |
| { |
| Cr cr = CR; |
| Msr msr = MSR; |
| cr.cr0 = msr.sf ? |
| makeCRFieldSigned((int64_t)%(result)s, 0, xer.so) : |
| makeCRFieldSigned((int32_t)%(result)s, 0, xer.so); |
| CR = cr; |
| } |
| ''' |
| |
| computeCACode = ''' |
| { |
| Msr msr = MSR; |
| if (findCarry(32, %(result)s, %(inputa)s, %(inputb)s)) { |
| xer.ca = 1; |
| xer.ca32 = 1; |
| } else { |
| xer.ca = 0; |
| xer.ca32 = 0; |
| } |
| |
| if (msr.sf) { |
| if (findCarry(64, %(result)s, %(inputa)s, %(inputb)s)) { |
| xer.ca = 1; |
| } else { |
| xer.ca = 0; |
| } |
| } |
| } |
| ''' |
| |
| computeOVCode = ''' |
| { |
| Msr msr = MSR; |
| if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) { |
| xer.ov = 1; |
| xer.ov32 = 1; |
| } else { |
| xer.ov = 0; |
| xer.ov32 = 0; |
| } |
| |
| if (msr.sf) { |
| if (findOverflow(64, %(result)s, %(inputa)s, %(inputb)s)) { |
| xer.ov = 1; |
| } else { |
| xer.ov = 0; |
| } |
| } |
| |
| if (xer.ov) { |
| xer.so = 1; |
| } |
| } |
| ''' |
| |
| setCACode = ''' |
| if (setCA) { |
| xer.ca = 1; |
| xer.ca32 = 1; |
| } else { |
| xer.ca = 0; |
| xer.ca32 = 0; |
| } |
| ''' |
| |
| setOVCode = ''' |
| if (setOV) { |
| xer.ov = 1; |
| xer.ov32 = 1; |
| xer.so = 1; |
| } else { |
| xer.ov = 0; |
| xer.ov32 = 0; |
| } |
| ''' |
| |
| }}; |
| |
| |
| // A basic integer instruction. |
| def format IntOp(code, inst_flags = []) {{ |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntOp', code, inst_flags, BasicDecode, |
| BasicConstructor) |
| }}; |
| |
| |
| // Integer instructions with immediate (signed or unsigned). |
| def format IntImmOp(code, inst_flags = []) {{ |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode, |
| BasicConstructor) |
| }}; |
| |
| |
| // Integer instructions with immediate that perform arithmetic. |
| // These instructions all write to Rt and use an altered form of the |
| // value in source register Ra, hence the use of src to hold the actual |
| // value. The control flags include the use of code to compute the |
| // carry bit or the CR0 code. |
| def format IntImmArithOp(code, computeCA = 0, computeCR0 = 0, |
| inst_flags = []) {{ |
| |
| # Set up the dictionary |
| dict = {'result':'Rt', 'inputa':'src', 'inputb':'si'} |
| |
| # Deal with computing CR0 and carry |
| if computeCA or computeCR0: |
| code += readXERCode |
| if computeCA: |
| code += computeCACode % dict + setXERCode |
| if computeCR0: |
| code += computeCR0Code % dict |
| |
| # Generate the class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntImmArithOp', code, inst_flags, BasicDecode, |
| BasicConstructor) |
| }}; |
| |
| |
| // Integer instructions with immediate that perform arithmetic but use |
| // the value 0 when Ra == 0. We generate two versions of each instruction |
| // corresponding to these two different scenarios. The correct version is |
| // determined at decode (see the CheckRaDecode template). |
| def format IntImmArithCheckRaOp(code, code_ra0, inst_flags = []) {{ |
| |
| # First the version where Ra is non-zero |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntImmArithOp', code, inst_flags, |
| CheckRaDecode, BasicConstructor) |
| |
| # Now another version where Ra == 0 |
| (header_output_ra0, decoder_output_ra0, _, exec_output_ra0) = \ |
| GenAluOp(name, Name + 'RaZero', 'IntImmArithOp', code_ra0, inst_flags, |
| CheckRaDecode, BasicConstructor) |
| |
| # Finally, add to the other outputs |
| header_output += header_output_ra0 |
| decoder_output += decoder_output_ra0 |
| exec_output += exec_output_ra0 |
| }}; |
| |
| |
| // Integer instructions with immediate that perform logic operations. |
| // All instructions write to Ra and use Rs as a source register. Some |
| // also compute the CR0 code too. |
| def format IntImmLogicOp(code, computeCR0 = 0, inst_flags = []) {{ |
| |
| # Set up the dictionary and deal with computing CR0 |
| dict = {'result':'Ra'} |
| |
| # Code when Rc is set |
| if computeCR0: |
| code += readXERCode + computeCR0Code % dict |
| |
| # Generate the class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntImmLogicOp', code, inst_flags, BasicDecode, |
| BasicConstructor) |
| }}; |
| |
| |
| // Integer instructions with displacement that perform arithmetic. |
| // There are no control flags to set. |
| def format IntDispArithOp(code, inst_flags = []) {{ |
| |
| # Generate the class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntDispArithOp', code, inst_flags, BasicDecode, |
| BasicConstructor) |
| }}; |
| |
| |
| // Integer compare instructions. |
| def format IntCompOp(code, inst_flags = []) {{ |
| |
| # Add code to setup variables |
| code = '[[maybe_unused]] uint32_t cr = 0;\n' + code |
| code += 'CR = insertCRField(CR, bf, cr);\n' |
| |
| # Add code to access XER |
| code = readXERCode + code |
| |
| # Generate the class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntCompOp', code, inst_flags, BasicDecode, |
| BasicConstructor) |
| }}; |
| |
| |
| // Integer immediate compare instructions. |
| def format IntImmCompOp(code, inst_flags = []) {{ |
| |
| # Add code to setup variables |
| code = '[[maybe_unused]] uint32_t cr = 0;\n' + code |
| code += 'CR = insertCRField(CR, bf, cr);\n' |
| |
| # Add code to access XER |
| code = readXERCode + code |
| |
| # Generate the class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntImmCompOp', code, inst_flags, BasicDecode, |
| BasicConstructor) |
| }}; |
| |
| |
| // Integer immediate compare logical instructions. |
| def format IntImmCompLogicOp(code, inst_flags = []) {{ |
| |
| # Add code to setup variables |
| code = '[[maybe_unused]] uint32_t cr = 0;\n' + code |
| code += 'CR = insertCRField(CR, bf, cr);\n' |
| |
| # Add code to access XER |
| code = readXERCode + code |
| |
| # Generate the class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntImmCompLogicOp', code, inst_flags, |
| BasicDecode, BasicConstructor) |
| }}; |
| |
| |
| // Integer instructions that perform logic operations. The result is |
| // always written into Ra. Some instructions have 2 versions depending on |
| // whether the Rc bit is set to compute the CR0 code. This is determined |
| // at decode as before. |
| def format IntLogicOp(code, computeCR0 = 0, inst_flags = []) {{ |
| dict = {'result':'Ra'} |
| |
| # Deal with computing CR0 |
| if computeCR0: |
| # Setup the 2 code versions and add code to access XER if necessary |
| code_rc1 = code + readXERCode + computeCR0Code % dict |
| |
| # Generate the first class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntLogicOp', code, inst_flags, |
| CheckRcDecode, BasicConstructor) |
| |
| # Generate the second class |
| (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ |
| GenAluOp(name, Name + 'RcSet', 'IntLogicOp', code_rc1, inst_flags, |
| CheckRcDecode, BasicConstructor) |
| |
| # Finally, add to the other outputs |
| header_output += header_output_rc1 |
| decoder_output += decoder_output_rc1 |
| exec_output += exec_output_rc1 |
| |
| else: |
| # Generate the class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntLogicOp', code, inst_flags, |
| BasicDecode, BasicConstructor) |
| }}; |
| |
| |
| // Integer instructions that perform shift operations. All of these |
| // instructions write to Ra and use Rs as a source register. The shift |
| // value is obtained from an register or an instruction field. If it |
| // from a register, Rb is also used as a source register. In certain |
| // situations, the carry bits have to be set and this is dealt with |
| // using the 'setCA' boolean in decoder.isa. We need two versions for |
| // each instruction to deal with the Rc bit. |
| def format IntShiftOp(code, computeCA = 0, inst_flags = []) {{ |
| dict = {'result':'Ra'} |
| |
| # Add code to setup variables and access XER if necessary |
| code = '[[maybe_unused]] bool setCA = false;\n' + code |
| |
| # Code when Rc is set |
| code_rc1 = readXERCode + code + computeCR0Code % dict |
| |
| # Add code for calculating the carry, if needed |
| if computeCA: |
| code = readXERCode + code + setCACode + setXERCode |
| code_rc1 += setCACode + setXERCode |
| |
| # Generate the first class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntShiftOp', code, inst_flags, |
| CheckRcDecode, BasicConstructor) |
| |
| # Generate the second class |
| (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ |
| GenAluOp(name, Name + 'RcSet', 'IntShiftOp', code_rc1, inst_flags, |
| CheckRcDecode, BasicConstructor) |
| |
| # Finally, add to the other outputs |
| header_output += header_output_rc1 |
| decoder_output += decoder_output_rc1 |
| exec_output += exec_output_rc1 |
| }}; |
| |
| |
| // Instructions in this format are all reduced to the form Rt = src1 + src2, |
| // therefore we just give src1 and src2 definitions. In working out the |
| // template we first put in the definitions of the variables and then |
| // the code for the addition. We also deal with computing the carry flag |
| // if required. |
| // |
| // We generate 4 versions of each instruction. This correspond to the |
| // different combinations of having the OE bit set or unset (which controls |
| // whether the overflow flag is computed) and the Rc bit set or unset too |
| // (which controls whether the CR0 code is computed). |
| def format IntSumOp(src1, src2, ca = {{ 0 }}, computeCA = 0, |
| inst_flags = []) {{ |
| |
| # The result is always in Rt, but the source values vary |
| dict = {'result':'Rt', 'inputa':'src1', 'inputb':'src2'} |
| |
| # Add code to set up variables and do the sum |
| code = 'uint64_t src1 = ' + src1 + ';\n' |
| code += 'uint64_t src2 = ' + src2 + ';\n' |
| code += 'uint64_t ca = ' + ca + ';\n' |
| code += 'Rt = src1 + src2 + ca;\n' |
| |
| # Add code for calculating the carry, if needed |
| if computeCA: |
| code += computeCACode % dict + setXERCode |
| |
| # Setup the 4 code versions and add code to access XER if necessary |
| code_rc1 = readXERCode + code |
| code_oe1 = readXERCode + code + computeOVCode % dict + setXERCode |
| code_rc1_oe1 = readXERCode + code + computeOVCode % dict + setXERCode |
| if (computeCA or ca == 'xer.ca'): |
| code = readXERCode + code |
| code_rc1 += computeCR0Code % dict |
| code_rc1_oe1 += computeCR0Code % dict |
| |
| # Generate the classes |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntArithOp', code, inst_flags, |
| CheckRcOeDecode, BasicConstructor) |
| (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ |
| GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1, inst_flags, |
| CheckRcOeDecode, BasicConstructor) |
| (header_output_oe1, decoder_output_oe1, _, exec_output_oe1) = \ |
| GenAluOp(name, Name + 'OeSet', 'IntArithOp', code_oe1, inst_flags, |
| CheckRcOeDecode, BasicConstructor) |
| (header_output_rc1_oe1, decoder_output_rc1_oe1, _, exec_output_rc1_oe1) = \ |
| GenAluOp(name, Name + 'RcSetOeSet', 'IntArithOp', code_rc1_oe1, |
| inst_flags, CheckRcOeDecode, BasicConstructor) |
| |
| # Finally, add to the other outputs |
| header_output += \ |
| header_output_rc1 + header_output_oe1 + header_output_rc1_oe1 |
| decoder_output += \ |
| decoder_output_rc1 + decoder_output_oe1 + decoder_output_rc1_oe1 |
| exec_output += \ |
| exec_output_rc1 + exec_output_oe1 + exec_output_rc1_oe1 |
| |
| }}; |
| |
| // Instructions that use source registers Ra and Rb, with the result |
| // placed into Rt but do not check for carry, overflow or the Rc bit. |
| def format IntArithOp(code, inst_flags = []) {{ |
| |
| # Generate the class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntArithOp', code, inst_flags, BasicDecode, |
| BasicConstructor) |
| }}; |
| |
| |
| // Instructions that use source registers Ra and Rb, with the result |
| // placed into Rt. Basically multiply and divide instructions. The |
| // carry bit is never set, but overflow can be calculated. In certain |
| // situations, the overflow bits have to be set and this is dealt with |
| // using the 'setOV' boolean in decoder.isa. |
| // |
| // In case overflow is to be calculated, we generate four versions of |
| // each instruction to deal with different combinations of having the |
| // OE bit set or unset and the Rc bit set or unset too. Otherwise, we |
| // generate two versions of each instruction to deal with the Rc bit. |
| def format IntArithCheckRcOp(code, computeOV = 0, inst_flags = []) {{ |
| |
| # The result is always in Rt, but the source values vary |
| dict = {'result':'Rt', 'inputa':'src1', 'inputb':'src2'} |
| |
| # Deal with setting the overflow flag |
| if computeOV: |
| # Setup the 4 code versions and add code to access XER if necessary |
| code = '[[maybe_unused]] bool setOV = false;\n' + code |
| code_rc1 = readXERCode + code + computeCR0Code % dict |
| code_oe1 = readXERCode + code + setOVCode + setXERCode |
| code_rc1_oe1 = readXERCode + code + setOVCode + setXERCode |
| code_rc1_oe1 += computeCR0Code % dict |
| |
| # Generate the classes |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntArithOp', code, inst_flags, |
| CheckRcOeDecode, BasicConstructor) |
| (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ |
| GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1, inst_flags, |
| CheckRcOeDecode, BasicConstructor) |
| (header_output_oe1, decoder_output_oe1, _, exec_output_oe1) = \ |
| GenAluOp(name, Name + 'OeSet', 'IntArithOp', code_oe1, inst_flags, |
| CheckRcOeDecode, BasicConstructor) |
| (header_output_rc1_oe1, decoder_output_rc1_oe1, _, |
| exec_output_rc1_oe1) = \ |
| GenAluOp(name, Name + 'RcSetOeSet', 'IntArithOp', code_rc1_oe1, |
| inst_flags, CheckRcOeDecode, BasicConstructor) |
| |
| # Finally, add to the other outputs |
| header_output += \ |
| header_output_rc1 + header_output_oe1 + header_output_rc1_oe1 |
| decoder_output += \ |
| decoder_output_rc1 + decoder_output_oe1 + decoder_output_rc1_oe1 |
| exec_output += \ |
| exec_output_rc1 + exec_output_oe1 + exec_output_rc1_oe1 |
| |
| else: |
| # Setup the 2 code versions and add code to access XER if necessary |
| code_rc1 = readXERCode + code + computeCR0Code % dict |
| |
| # Generate the first class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntArithOp', code, inst_flags, |
| CheckRcDecode, BasicConstructor) |
| |
| # Generate the second class |
| (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ |
| GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1, inst_flags, |
| CheckRcDecode, BasicConstructor) |
| |
| # Finally, add to the other outputs |
| header_output += header_output_rc1 |
| decoder_output += decoder_output_rc1 |
| exec_output += exec_output_rc1 |
| }}; |
| |
| |
| // Integer instructions that also perform shift operations. Everything |
| // is same as above except if the shift value is not obtained from a |
| // register, two immediates need to be concatenated to get the final |
| // shift value. |
| def format IntConcatShiftOp(code, computeCA = 0, inst_flags = []) {{ |
| dict = {'result':'Ra'} |
| |
| # Add code to setup variables and access XER if necessary |
| code = '[[maybe_unused]] bool setCA = false;\n' + code |
| |
| # Code when Rc is set |
| code_rc1 = readXERCode + code + computeCR0Code % dict |
| |
| # Add code for calculating the carry, if needed |
| if computeCA: |
| code = readXERCode + code + setCACode + setXERCode |
| code_rc1 += setCACode + setXERCode |
| |
| # Generate the first class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntConcatShiftOp', code, inst_flags, |
| CheckRcDecode, BasicConstructor) |
| |
| # Generate the second class |
| (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ |
| GenAluOp(name, Name + 'RcSet', 'IntConcatShiftOp', code_rc1, |
| inst_flags, CheckRcDecode, BasicConstructor) |
| |
| # Finally, add to the other outputs |
| header_output += header_output_rc1 |
| decoder_output += decoder_output_rc1 |
| exec_output += exec_output_rc1 |
| }}; |
| |
| |
| // Integer instructions with or without immediate that perform rotate |
| // operations. All instructions write to Ra and use Rs as a source |
| // register. If immediate is not used, Rb is also used as a source |
| // register. We need two versions for each instruction to deal with |
| // the Rc bit. |
| def format IntRotateOp(code, inst_flags = []) {{ |
| |
| # The result is always in Ra |
| dict = {'result':'Ra'} |
| |
| # Code when Rc is set |
| code_rc1 = readXERCode + code + computeCR0Code % dict |
| |
| # Generate the first class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntRotateOp', code, inst_flags, |
| CheckRcDecode, BasicConstructor) |
| |
| # Generate the second class |
| (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ |
| GenAluOp(name, Name + 'RcSet', 'IntRotateOp', code_rc1, inst_flags, |
| CheckRcDecode, BasicConstructor) |
| |
| # Finally, add to the other outputs |
| header_output += header_output_rc1 |
| decoder_output += decoder_output_rc1 |
| exec_output += exec_output_rc1 |
| }}; |
| |
| |
| // Everything is same as above except that the immediates may need to be |
| // concatenated to get the final values for the mask bounds or the shift |
| // value. We need two versions for each instruction to deal with the Rc |
| // bit. |
| def format IntConcatRotateOp(code, inst_flags = []) {{ |
| |
| # The result is always in Ra |
| dict = {'result':'Ra'} |
| |
| # Code when Rc is set |
| code_rc1 = readXERCode + code + computeCR0Code % dict |
| |
| # Generate the first class |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntConcatRotateOp', code, inst_flags, |
| CheckRcDecode, BasicConstructor) |
| |
| # Generate the second class |
| (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ |
| GenAluOp(name, Name + 'RcSet', 'IntConcatRotateOp', code_rc1, |
| inst_flags, CheckRcDecode, BasicConstructor) |
| |
| # Finally, add to the other outputs |
| header_output += header_output_rc1 |
| decoder_output += decoder_output_rc1 |
| exec_output += exec_output_rc1 |
| }}; |
| |
| |
| def format IntTrapOp(src1, src2, inst_flags = []) {{ |
| |
| # Add code to set up variables and check for a trap |
| code = 'int64_t src1 = ' + src1 + ';\n' |
| code += 'int64_t src2 = ' + src2 + ';\n' |
| code += 'if (checkTrap(src1, src2)) {\n' |
| code += ' return std::make_shared<TrapFault>();\n' |
| code += '}\n' |
| |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntTrapOp', code, inst_flags, BasicDecode, |
| BasicConstructor) |
| }}; |
| |
| |
| def format IntImmTrapOp(src, inst_flags = []) {{ |
| |
| # Add code to set up variables and check for a trap |
| code = 'int64_t src = ' + src + ';\n' |
| code += 'if (checkTrap(src, si)) {\n' |
| code += ' return std::make_shared<TrapFault>();\n' |
| code += '}\n' |
| |
| (header_output, decoder_output, decode_block, exec_output) = \ |
| GenAluOp(name, Name, 'IntImmTrapOp', code, inst_flags, BasicDecode, |
| BasicConstructor) |
| }}; |