diff --git a/src/arch/power/insts/floating.hh b/src/arch/power/insts/floating.hh index 02dbbb2ed2..ef069013df 100644 --- a/src/arch/power/insts/floating.hh +++ b/src/arch/power/insts/floating.hh @@ -43,11 +43,12 @@ class FloatOp : public PowerStaticInst { protected: - bool rcSet; + bool rc; /// Constructor FloatOp(const char *mnem, MachInst _machInst, OpClass __opClass) - : PowerStaticInst(mnem, _machInst, __opClass) + : PowerStaticInst(mnem, _machInst, __opClass), + rc(machInst.rc) { } diff --git a/src/arch/power/insts/integer.cc b/src/arch/power/insts/integer.cc index a65d7b716d..7da5bf5ff8 100644 --- a/src/arch/power/insts/integer.cc +++ b/src/arch/power/insts/integer.cc @@ -61,8 +61,10 @@ IntOp::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const } // Additional characters depending on isa bits being set - if (oeSet) myMnemonic = myMnemonic + "o"; - if (rcSet) myMnemonic = myMnemonic + "."; + if (oe) + myMnemonic = myMnemonic + "o"; + if (rc) + myMnemonic = myMnemonic + "."; ccprintf(ss, "%-10s ", myMnemonic); // Print the first destination only @@ -116,7 +118,7 @@ IntImmOp::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const } // Print the immediate value last - ss << ", " << (int32_t)imm; + ss << ", " << (int32_t)si; return ss.str(); } diff --git a/src/arch/power/insts/integer.hh b/src/arch/power/insts/integer.hh index 04222a19e0..a25e65c97d 100644 --- a/src/arch/power/insts/integer.hh +++ b/src/arch/power/insts/integer.hh @@ -51,8 +51,8 @@ class IntOp : public PowerStaticInst { protected: - bool rcSet; - bool oeSet; + bool rc; + bool oe; // Needed for srawi only uint32_t sh; @@ -60,7 +60,8 @@ class IntOp : public PowerStaticInst /// Constructor IntOp(const char *mnem, MachInst _machInst, OpClass __opClass) : PowerStaticInst(mnem, _machInst, __opClass), - rcSet(false), oeSet(false) + rc(machInst.rc), + oe(machInst.oe) { } @@ -104,14 +105,14 @@ class IntImmOp : public IntOp { protected: - int32_t imm; - uint32_t uimm; + int32_t si; + uint32_t ui; /// Constructor IntImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) : IntOp(mnem, _machInst, __opClass), - imm(sext<16>(machInst.si)), - uimm(machInst.si) + si(sext<16>(machInst.si)), + ui(machInst.si) { } @@ -120,6 +121,39 @@ class IntImmOp : public IntOp }; +/** + * Class for integer arithmetic operations. + */ +class IntArithOp : public IntOp +{ + protected: + + /// Constructor + IntArithOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : IntOp(mnem, _machInst, __opClass) + { + } +}; + + +/** + * Class for integer immediate arithmetic operations. + */ +class IntImmArithOp : public IntArithOp +{ + protected: + + int32_t si; + + /// Constructor + IntImmArithOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : IntArithOp(mnem, _machInst, __opClass), + si(sext<16>(machInst.si)) + { + } +}; + + /** * Class for integer operations with a shift. */ diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index 3f513866f3..e993a7bff5 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -39,42 +39,48 @@ decode PO default Unknown::unknown() { format IntImmArithOp { 7: mulli({{ int32_t src = Ra_sw; - int64_t prod = src * imm; + int64_t prod = src * si; Rt = (uint32_t)prod; }}); - 8: subfic({{ int32_t src = ~Ra; Rt = src + imm + 1; }}, - [computeCA]); + 8: subfic({{ + uint64_t src = ~Ra; + Rt = src + si + 1; + }}, true); } format IntImmOp { 10: cmpli({{ Xer xer = XER; - uint32_t cr = makeCRFieldUnsigned(Ra_uw, uimm, xer.so); + uint32_t cr = makeCRFieldUnsigned(Ra_uw, ui, xer.so); CR = insertCRField(CR, BF, cr); }}); 11: cmpi({{ Xer xer = XER; - uint32_t cr = makeCRFieldSigned(Ra_sw, imm, xer.so); + uint32_t cr = makeCRFieldSigned(Ra_sw, si, xer.so); CR = insertCRField(CR, BF, cr); }}); } format IntImmArithOp { - 12: addic({{ uint32_t src = Ra; Rt = src + imm; }}, - [computeCA]); + 12: addic({{ + uint64_t src = Ra; + Rt = src + si; + }}, true); - 13: addic_({{ uint32_t src = Ra; Rt = src + imm; }}, - [computeCA, computeCR0]); + 13: addic_({{ + uint64_t src = Ra; + Rt = src + si; + }}, true, true); } format IntImmArithCheckRaOp { - 14: addi({{ Rt = Ra + imm; }}, - {{ Rt = imm }}); + 14: addi({{ Rt = Ra + si; }}, + {{ Rt = si }}); - 15: addis({{ Rt = Ra + (imm << 16); }}, - {{ Rt = imm << 16; }}); + 15: addis({{ Rt = Ra + (si << 16); }}, + {{ Rt = si << 16; }}); } // Conditionally branch to a PC-relative or absoulute address based @@ -168,12 +174,12 @@ decode PO default Unknown::unknown() { } format IntImmLogicOp { - 24: ori({{ Ra = Rs | uimm; }}); - 25: oris({{ Ra = Rs | (uimm << 16); }}); - 26: xori({{ Ra = Rs ^ uimm; }}); - 27: xoris({{ Ra = Rs ^ (uimm << 16); }}); - 28: andi_({{ Ra = Rs & uimm; }}, true); - 29: andis_({{ Ra = Rs & (uimm << 16); }}, true); + 24: ori({{ Ra = Rs | ui; }}); + 25: oris({{ Ra = Rs | (ui << 16); }}); + 26: xori({{ Ra = Rs ^ ui; }}); + 27: xoris({{ Ra = Rs ^ (ui << 16); }}); + 28: andi_({{ Ra = Rs & ui; }}, true); + 29: andis_({{ Ra = Rs & (ui << 16); }}, true); } // There are a large number of instructions that have the same primary @@ -479,14 +485,14 @@ decode PO default Unknown::unknown() { 10: addc({{ Ra }}, {{ Rb }}, computeCA = true); } - 11: IntArithOp::mulhwu({{ + 11: IntArithCheckRcOp::mulhwu({{ uint64_t prod = Ra_ud * Rb_ud; Rt = prod >> 32; }}); 40: IntSumOp::subf({{ ~Ra }}, {{ Rb }}, {{ 1 }}); - 75: IntArithOp::mulhw({{ + 75: IntArithCheckRcOp::mulhw({{ int64_t prod = Ra_sd * Rb_sd; Rt = prod >> 32; }}); @@ -497,28 +503,21 @@ decode PO default Unknown::unknown() { 138: adde({{ Ra }}, {{ Rb }}, {{ xer.ca }}, true); 200: subfze({{ ~Ra }}, {{ xer.ca }}, computeCA = true); 202: addze({{ Ra }}, {{ xer.ca }}, computeCA = true); - 232: subfme({{ ~Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }}, true); - 234: addme({{ Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }}, true); + 232: subfme({{ ~Ra }}, {{ -1ULL }}, {{ xer.ca }}, true); + 234: addme({{ Ra }}, {{ -1ULL }}, {{ xer.ca }}, true); } - format IntArithOp { - 235: mullw({{ - int64_t prod = Ra_sd * Rb_sd; - Rt = prod; - }}); - - // Another variant of mullw decoded with the OE bit set - 747: mullwo({{ - int64_t src1 = Ra_sd; - int64_t src2 = Rb; - int64_t prod = src1 * src2; - Rt = prod; - }}, true); - } + 235: IntArithCheckRcOp::mullw({{ + int64_t prod = Ra_sd * Rb_sd; + Rt = prod; + if (prod != (int32_t)prod) { + setOV = true; + } + }}, true); 266: IntSumOp::add({{ Ra }}, {{ Rb }}); - format IntArithOp { + format IntArithCheckRcOp { 459: divwu({{ uint32_t src1 = Ra_sw; uint32_t src2 = Rb_sw; @@ -526,18 +525,7 @@ decode PO default Unknown::unknown() { Rt = src1 / src2; } else { Rt = 0; - } - }}); - - // Another variant of divwu decoded with the OE bit set - 971: divwuo({{ - uint32_t src1 = Ra_sw; - uint32_t src2 = Rb_sw; - if (src2 != 0) { - Rt = src1 / src2; - } else { - Rt = 0; - divSetOV = true; + setOV = true; } }}, true); @@ -549,19 +537,7 @@ decode PO default Unknown::unknown() { Rt = src1 / src2; } else { Rt = 0; - } - }}); - - // Another variant of divw decoded with the OE bit set - 1003: divwo({{ - int32_t src1 = Ra_sw; - int32_t src2 = Rb_sw; - if ((src1 != 0x80000000 || src2 != 0xffffffff) - && src2 != 0) { - Rt = src1 / src2; - } else { - Rt = 0; - divSetOV = true; + setOV = true; } }}, true); } diff --git a/src/arch/power/isa/formats/fp.isa b/src/arch/power/isa/formats/fp.isa index b607400c50..5f6d09dd57 100644 --- a/src/arch/power/isa/formats/fp.isa +++ b/src/arch/power/isa/formats/fp.isa @@ -71,7 +71,7 @@ def format FloatRCCheckOp(code, inst_flags = []) {{ # Generate the second class (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ GenAluOp(name, Name + 'RcSet', 'FloatOp', code_rc1, inst_flags, - CheckRcDecode, IntRcConstructor) + CheckRcDecode, BasicConstructor) # Finally, add to the other outputs header_output += header_output_rc1 @@ -96,7 +96,7 @@ def format FloatArithOp(code, inst_flags = []) {{ # Generate the second class (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ GenAluOp(name, Name + 'RcSet', 'FloatOp', code_rc1, inst_flags, - CheckRcDecode, IntRcConstructor) + CheckRcDecode, BasicConstructor) # Finally, add to the other outputs header_output += header_output_rc1 @@ -121,7 +121,7 @@ def format FloatConvertOp(code, inst_flags = []) {{ # Generate the second class (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ GenAluOp(name, Name + 'RcSet', 'FloatOp', code_rc1, inst_flags, - CheckRcDecode, IntRcConstructor) + CheckRcDecode, BasicConstructor) # Finally, add to the other outputs header_output += header_output_rc1 diff --git a/src/arch/power/isa/formats/integer.isa b/src/arch/power/isa/formats/integer.isa index f3ab30c236..b0840ce413 100644 --- a/src/arch/power/isa/formats/integer.isa +++ b/src/arch/power/isa/formats/integer.isa @@ -31,44 +31,6 @@ // Integer ALU instructions // - -// Instruction class constructor template when Rc is set. -def template IntRcConstructor {{ - %(class_name)s::%(class_name)s(ExtMachInst machInst) : - %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) - { - %(set_reg_idx_arr)s; - %(constructor)s; - rcSet = true; - } -}}; - - -// Instruction class constructor template when OE is set. -def template IntOeConstructor {{ - %(class_name)s::%(class_name)s(ExtMachInst machInst) : - %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) - { - %(set_reg_idx_arr)s; - %(constructor)s; - oeSet = true; - } -}}; - - -// Instruction class constructor template when both Rc and OE are set. -def template IntRcOeConstructor {{ - %(class_name)s::%(class_name)s(ExtMachInst machInst) : - %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) - { - %(set_reg_idx_arr)s; - %(constructor)s; - rcSet = true; - oeSet = true; - } -}}; - - let {{ readXERCode = 'Xer xer = XER;' @@ -98,17 +60,12 @@ computeOVCode = ''' } ''' -computeDivOVCode = ''' - if (divSetOV) { +setOVCode = ''' + if (setOV) { 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; - } + xer.ov = 0; } ''' @@ -136,21 +93,23 @@ def format IntImmOp(code, inst_flags = []) {{ // 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 = []) {{ +def format IntImmArithOp(code, computeCA = 0, computeCR0 = 0, + inst_flags = []) {{ - # Set up the dictionary and deal with control flags - dict = {'result':'Rt', 'inputa':'src', 'inputb':'imm'} - if ctrl_flags: + # Set up the dictionary + dict = {'result':'Rt', 'inputa':'src', 'inputb':'si'} + + # Deal with computing CR0 and carry + if computeCA or computeCR0: code += readXERCode - for val in ctrl_flags: - if val == 'computeCA': - code += computeCACode % dict + setXERCode - elif val == 'computeCR0': - code += computeCR0Code % dict + 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, 'IntImmOp', code, inst_flags, BasicDecode, + GenAluOp(name, Name, 'IntImmArithOp', code, inst_flags, BasicDecode, BasicConstructor) }}; @@ -163,12 +122,12 @@ 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, + 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', 'IntImmOp', code_ra0, inst_flags, + GenAluOp(name, Name + 'RaZero', 'IntImmArithOp', code_ra0, inst_flags, CheckRaDecode, BasicConstructor) # Finally, add to the other outputs @@ -213,7 +172,7 @@ def format IntLogicOp(code, inst_flags = []) {{ # Generate the second class (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags, - CheckRcDecode, IntRcConstructor) + CheckRcDecode, BasicConstructor) # Finally, add to the other outputs header_output += header_output_rc1 @@ -238,7 +197,7 @@ def format IntShiftOp(code, inst_flags = []) {{ # Generate the second class (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ GenAluOp(name, Name + 'RcSet', 'IntShiftOp', code_rc1, inst_flags, - CheckRcDecode, IntRcConstructor) + CheckRcDecode, BasicConstructor) # Finally, add to the other outputs header_output += header_output_rc1 @@ -264,9 +223,9 @@ def format IntSumOp(src1, src2, ca = {{ 0 }}, computeCA = 0, 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 = '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 @@ -284,17 +243,17 @@ def format IntSumOp(src1, src2, ca = {{ 0 }}, computeCA = 0, # Generate the classes (header_output, decoder_output, decode_block, exec_output) = \ - GenAluOp(name, Name, 'IntOp', code, inst_flags, + GenAluOp(name, Name, 'IntArithOp', 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) + GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1, inst_flags, + CheckRcOeDecode, BasicConstructor) (header_output_oe1, decoder_output_oe1, _, exec_output_oe1) = \ - GenAluOp(name, Name + 'OeSet', 'IntOp', code_oe1, inst_flags, - CheckRcOeDecode, IntOeConstructor) + 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', 'IntOp', code_rc1_oe1, - inst_flags, CheckRcOeDecode, IntRcOeConstructor) + GenAluOp(name, Name + 'RcSetOeSet', 'IntArithOp', code_rc1_oe1, + inst_flags, CheckRcOeDecode, BasicConstructor) # Finally, add to the other outputs header_output += \ @@ -309,39 +268,69 @@ def format IntSumOp(src1, src2, ca = {{ 0 }}, computeCA = 0, // 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 = []) {{ +// 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: - code = 'bool divSetOV = false;\n' + code - code += computeDivOVCode % dict + setXERCode + # Setup the 4 code versions and add code to access XER if necessary + code = 'GEM5_VAR_USED 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 - # 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, '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) - # Generate the classes - (header_output, decoder_output, decode_block, exec_output) = \ - GenAluOp(name, Name, 'IntOp', code, inst_flags, - CheckRcDecode, 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 - # Generate the second class - (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ - GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags, - CheckRcDecode, IntRcConstructor) + else: + # Setup the 2 code versions and add code to access XER if necessary + code_rc1 = readXERCode + code + computeCR0Code % dict - # Finally, add to the other outputs - header_output += header_output_rc1 - decoder_output += decoder_output_rc1 - exec_output += exec_output_rc1 + # 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 }}; @@ -364,7 +353,7 @@ def format IntRotateOp(code, inst_flags = []) {{ # Generate the second class (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ GenAluOp(name, Name + 'RcSet', 'IntRotateOp', code_rc1, inst_flags, - CheckRcDecode, IntRcConstructor) + CheckRcDecode, BasicConstructor) # Finally, add to the other outputs header_output += header_output_rc1 diff --git a/src/arch/power/types.hh b/src/arch/power/types.hh index bc5b4eecde..354da59ed0 100644 --- a/src/arch/power/types.hh +++ b/src/arch/power/types.hh @@ -52,6 +52,7 @@ BitUnion32(ExtMachInst) // Immediate fields Bitfield<15, 0> si; + Bitfield<15, 0> ui; Bitfield<15, 0> d; Bitfield<15, 2> ds; @@ -70,7 +71,7 @@ BitUnion32(ExtMachInst) Bitfield<0> lk; // Record bits - Bitfield<0> rc31; + Bitfield<0> rc; Bitfield<10> oe; // Condition register fields