summaryrefslogtreecommitdiff
path: root/src/arch/power/isa/formats/integer.isa
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/power/isa/formats/integer.isa')
-rw-r--r--src/arch/power/isa/formats/integer.isa369
1 files changed, 369 insertions, 0 deletions
diff --git a/src/arch/power/isa/formats/integer.isa b/src/arch/power/isa/formats/integer.isa
new file mode 100644
index 000000000..0766826ec
--- /dev/null
+++ b/src/arch/power/isa/formats/integer.isa
@@ -0,0 +1,369 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2009 The University of Edinburgh
+// 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.
+//
+// Authors: Timothy M. Jones
+
+////////////////////////////////////////////////////////////////////
+//
+// Integer ALU instructions
+//
+
+
+// Instruction class constructor template when Rc is set.
+def template IntRcConstructor {{
+ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ rcSet = true;
+ }
+}};
+
+
+// Instruction class constructor template when OE is set.
+def template IntOeConstructor {{
+ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ oeSet = true;
+ }
+}};
+
+
+// Instruction class constructor template when both Rc and OE are set.
+def template IntRcOeConstructor {{
+ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ rcSet = true;
+ oeSet = true;
+ }
+}};
+
+
+let {{
+
+readXERCode = 'Xer xer = XER;'
+
+setXERCode = 'XER = xer;'
+
+computeCR0Code = '''
+ Cr cr = CR;
+ cr.cr0 = makeCRField((int32_t)%(result)s, (int32_t)0, xer.so);
+ CR = cr;
+'''
+
+computeCACode = '''
+ if (findCarry(32, %(result)s, %(inputa)s, %(inputb)s)) {
+ xer.ca = 1;
+ } else {
+ xer.ca = 0;
+ }
+'''
+
+computeOVCode = '''
+ if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) {
+ xer.ov = 1;
+ xer.so = 1;
+ } else {
+ xer.ov = 0;
+ }
+'''
+
+computeDivOVCode = '''
+ if (divSetOV) {
+ xer.ov = 1;
+ xer.so = 1;
+ } else {
+ if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) {
+ xer.ov = 1;
+ xer.so = 1;
+ } else {
+ xer.ov = 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, ctrl_flags = [], inst_flags = []) {{
+
+ # Set up the dictionary and deal with control flags
+ dict = {'result':'Rt', 'inputa':'src', 'inputb':'imm'}
+ if ctrl_flags:
+ code += readXERCode
+ for val in ctrl_flags:
+ if val == 'computeCA':
+ code += computeCACode % dict + setXERCode
+ elif val == 'computeCR0':
+ code += computeCR0Code % dict
+
+ # Generate the class
+ (header_output, decoder_output, decode_block, exec_output) = \
+ GenAluOp(name, Name, 'IntImmOp', 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, 'IntImmOp', code, inst_flags,
+ CheckRaDecode, BasicConstructor)
+
+ # Now another version where Ra == 0
+ (header_output_ra0, decoder_output_ra0, _, exec_output_ra0) = \
+ GenAluOp(name, Name + 'RaZero', 'IntImmOp', 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'}
+ if computeCR0:
+ code += readXERCode + computeCR0Code % dict
+
+ # Generate the class
+ (header_output, decoder_output, decode_block, exec_output) = \
+ GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode,
+ BasicConstructor)
+}};
+
+
+// Integer instructions that perform logic operations. The result is
+// always written into Ra. All 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, inst_flags = []) {{
+ dict = {'result':'Ra'}
+
+ # Code when Rc is set
+ code_rc1 = code + readXERCode + computeCR0Code % dict
+
+ # Generate the first class
+ (header_output, decoder_output, decode_block, exec_output) = \
+ GenAluOp(name, Name, 'IntOp', code, inst_flags,
+ CheckRcDecode, BasicConstructor)
+
+ # Generate the second class
+ (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
+ GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags,
+ CheckRcDecode, IntRcConstructor)
+
+ # Finally, add to the other outputs
+ header_output += header_output_rc1
+ decoder_output += decoder_output_rc1
+ exec_output += exec_output_rc1
+}};
+
+
+// Integer instructions with a shift amount. As above, except inheriting
+// from the IntShiftOp class.
+def format IntShiftOp(code, inst_flags = []) {{
+ dict = {'result':'Ra'}
+
+ # Code when Rc is set
+ code_rc1 = code + readXERCode + computeCR0Code % dict
+
+ # 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, IntRcConstructor)
+
+ # 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 = 'uint32_t src1 = ' + src1 + ';\n'
+ code += 'uint32_t src2 = ' + src2 + ';\n'
+ code += 'uint32_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, 'IntOp', code, inst_flags,
+ CheckRcOeDecode, BasicConstructor)
+ (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
+ GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags,
+ CheckRcOeDecode, IntRcConstructor)
+ (header_output_oe1, decoder_output_oe1, _, exec_output_oe1) = \
+ GenAluOp(name, Name + 'OeSet', 'IntOp', code_oe1, inst_flags,
+ CheckRcOeDecode, IntOeConstructor)
+ (header_output_rc1_oe1, decoder_output_rc1_oe1, _, exec_output_rc1_oe1) = \
+ GenAluOp(name, Name + 'RcSetOeSet', 'IntOp', code_rc1_oe1,
+ inst_flags, CheckRcOeDecode, IntRcOeConstructor)
+
+ # 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. Basically multiply and divide instructions. The
+// carry bit is never set, but overflow can be calculated. Division
+// explicitly sets the overflow bit in certain situations and this is
+// dealt with using the 'divSetOV' boolean in decoder.isa. We generate
+// two versions of each instruction to deal with the Rc bit.
+def format IntArithOp(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:
+ code = 'bool divSetOV = false;\n' + code
+ code += computeDivOVCode % dict + setXERCode
+
+ # Setup the 2 code versions and add code to access XER if necessary
+ code_rc1 = readXERCode + code + computeCR0Code % dict
+ if computeOV:
+ code = readXERCode + code
+
+ # Generate the classes
+ (header_output, decoder_output, decode_block, exec_output) = \
+ GenAluOp(name, Name, 'IntOp', code, inst_flags,
+ CheckRcDecode, BasicConstructor)
+
+ # Generate the second class
+ (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
+ GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags,
+ CheckRcDecode, IntRcConstructor)
+
+ # Finally, add to the other outputs
+ header_output += header_output_rc1
+ decoder_output += decoder_output_rc1
+ exec_output += exec_output_rc1
+}};
+
+
+// A special format for rotate instructions which use certain fields
+// from the instruction's binary encoding. 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'}
+
+ # Setup the code for 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, IntRcConstructor)
+
+ # Finally, add to the other outputs
+ header_output += header_output_rc1
+ decoder_output += decoder_output_rc1
+ exec_output += exec_output_rc1
+}};