From: Sandipan Das Date: Thu, 7 Jun 2018 08:53:20 +0000 (+0530) Subject: arch-power: Fix fixed-point compare instructions X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=495772a704e65114af8702db6590be448cc2bbd3;p=gem5.git arch-power: Fix fixed-point compare instructions This fixes the following compare instructions: * Compare (cmp) * Compare Logical (cmpl) * Compare Immediate (cmpi) * Compare Logical Immediate (cmpli) Instead of always doing a 32-bit comparison, these instructions now use the length field to determine the type of comparison to be done. The comparison can either be based on the lower order 32 bits or on all 64 bits of the values. This also fixes disassembly generation for all of the above. Change-Id: I6a9f783efa9ef2f2ef3c16eada61074d6f798a20 Signed-off-by: Sandipan Das --- diff --git a/src/arch/power/insts/integer.cc b/src/arch/power/insts/integer.cc index e5692bb22..b55f75ccd 100644 --- a/src/arch/power/insts/integer.cc +++ b/src/arch/power/insts/integer.cc @@ -46,7 +46,7 @@ IntOp::generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const if (!myMnemonic.compare("or") && _srcRegIdx[0] == _srcRegIdx[1]) { myMnemonic = "mr"; printSecondSrc = false; - } else if (!myMnemonic.compare("mtlr") || !myMnemonic.compare("cmpi")) { + } else if (!myMnemonic.compare("mtlr")) { printDest = false; } else if (!myMnemonic.compare("mflr")) { printSrcs = false; @@ -106,7 +106,8 @@ IntImmOp::generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const string -IntArithOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +IntArithOp::generateDisassembly( + Addr pc, const Loader::SymbolTable *symtab) const { stringstream ss; bool printSecondSrc = true; @@ -163,7 +164,8 @@ IntArithOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const string -IntImmArithOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +IntImmArithOp::generateDisassembly( + Addr pc, const Loader::SymbolTable *symtab) const { stringstream ss; bool negateSimm = false; @@ -276,6 +278,185 @@ IntDispArithOp::generateDisassembly( } +string +IntCompOp::generateDisassembly( + Addr pc, const Loader::SymbolTable *symtab) const +{ + stringstream ss; + bool printFieldPrefix = false; + bool printLength = true; + + // Generate the correct mnemonic + string myMnemonic(mnemonic); + + // Special cases + if (!myMnemonic.compare("cmp")) { + if (length) { + myMnemonic = "cmpd"; + } else { + myMnemonic = "cmpw"; + } + printFieldPrefix = true; + printLength = false; + } else if (!myMnemonic.compare("cmpl")) { + if (length) { + myMnemonic = "cmpld"; + } else { + myMnemonic = "cmplw"; + } + printFieldPrefix = true; + printLength = false; + } + + ccprintf(ss, "%-10s ", myMnemonic); + + // Print the first destination only + if (printFieldPrefix) { + if (field > 0) { + ss << "cr" << field; + } + } else { + ss << field; + } + + // Print the length + if (printLength) { + if (!printFieldPrefix || field > 0) { + ss << ", "; + } + ss << length; + } + + // Print the first source register + if (_numSrcRegs > 0) { + if (!printFieldPrefix || field > 0 || printLength) { + ss << ", "; + } + printReg(ss, _srcRegIdx[0]); + + // Print the second source register + if (_numSrcRegs > 1) { + ss << ", "; + printReg(ss, _srcRegIdx[1]); + } + } + + return ss.str(); +} + + +string +IntImmCompOp::generateDisassembly( + Addr pc, const Loader::SymbolTable *symtab) const +{ + stringstream ss; + bool printFieldPrefix = false; + bool printLength = true; + + // Generate the correct mnemonic + string myMnemonic(mnemonic); + + // Special cases + if (!myMnemonic.compare("cmpi")) { + if (length) { + myMnemonic = "cmpdi"; + } else { + myMnemonic = "cmpwi"; + } + printFieldPrefix = true; + printLength = false; + } + + ccprintf(ss, "%-10s ", myMnemonic); + + // Print the first destination only + if (printFieldPrefix) { + if (field > 0) { + ss << "cr" << field; + } + } else { + ss << field; + } + + // Print the length + if (printLength) { + if (!printFieldPrefix || field > 0) { + ss << ", "; + } + ss << length; + } + + // Print the first source register + if (_numSrcRegs > 0) { + if (!printFieldPrefix || field > 0 || printLength) { + ss << ", "; + } + printReg(ss, _srcRegIdx[0]); + } + + // Print the immediate value + ss << ", " << simm; + + return ss.str(); +} + + +string +IntImmCompLogicOp::generateDisassembly(Addr pc, + const Loader::SymbolTable *symtab) const +{ + stringstream ss; + bool printFieldPrefix = false; + bool printLength = true; + + // Generate the correct mnemonic + string myMnemonic(mnemonic); + + // Special cases + if (!myMnemonic.compare("cmpli")) { + if (length) { + myMnemonic = "cmpldi"; + } else { + myMnemonic = "cmplwi"; + } + printFieldPrefix = true; + printLength = false; + } + + ccprintf(ss, "%-10s ", myMnemonic); + + // Print the first destination only + if (printFieldPrefix) { + if (field > 0) { + ss << "cr" << field; + } + } else { + ss << field; + } + + // Print the mode + if (printLength) { + if (!printFieldPrefix || field > 0) { + ss << ", "; + } + ss << length; + } + + // Print the first source register + if (_numSrcRegs > 0) { + if (!printFieldPrefix || field > 0 || printLength) { + ss << ", "; + } + printReg(ss, _srcRegIdx[0]); + } + + // Print the immediate value + ss << ", " << uimm; + + return ss.str(); +} + + string IntShiftOp::generateDisassembly( Addr pc, const Loader::SymbolTable *symtab) const diff --git a/src/arch/power/insts/integer.hh b/src/arch/power/insts/integer.hh index 61602af96..c691ad39b 100644 --- a/src/arch/power/insts/integer.hh +++ b/src/arch/power/insts/integer.hh @@ -414,6 +414,71 @@ class IntDispArithOp : public IntArithOp }; +/** + * Class for integer compare operations. + */ +class IntCompOp : public IntOp +{ + protected: + + uint32_t length; + uint32_t field; + + /// Constructor + IntCompOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : IntOp(mnem, _machInst, __opClass), + length(machInst.l), + field(machInst.bf) + { + } + + std::string generateDisassembly( + Addr pc, const SymbolTable *symtab) const override; +}; + + +/** + * Class for integer immediate compare operations. + */ +class IntImmCompOp : public IntCompOp +{ + protected: + + int32_t simm; + + /// Constructor + IntImmCompOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : IntCompOp(mnem, _machInst, __opClass), + simm((int16_t)machInst.si) + { + } + + std::string generateDisassembly( + Addr pc, const SymbolTable *symtab) const override; +}; + + +/** + * Class for integer immediate compare logical operations. + */ +class IntImmCompLogicOp : public IntCompOp +{ + protected: + + uint32_t uimm; + + /// Constructor + IntImmCompLogicOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : IntCompOp(mnem, _machInst, __opClass), + uimm(machInst.ui) + { + } + + std::string generateDisassembly( + Addr pc, const SymbolTable *symtab) const override; +}; + + /** * Class for integer operations with a shift. */ diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index 4857616b6..bf1eaf941 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -250,19 +250,26 @@ decode PO default Unknown::unknown() { } } - format IntImmOp { - 10: cmpli({{ - Xer xer = XER; - uint32_t cr = makeCRField(Ra, (uint32_t)uimm, xer.so); - CR = insertCRField(CR, BF, cr); - }}); + format IntImmCompOp { 11: cmpi({{ - Xer xer = XER; - uint32_t cr = makeCRField(Ra_sw, (int32_t)imm, xer.so); - CR = insertCRField(CR, BF, cr); - }}); + if (length) { + cr = makeCRField(Ra_sd, simm, xer.so); + } else { + cr = makeCRField((int32_t)Ra_sd, simm, xer.so); + } + }}); } + format IntImmCompLogicOp { + 10: cmpli({{ + if (length) { + cr = makeCRField(Ra, uimm, xer.so); + } else { + cr = makeCRField((uint32_t)Ra, uimm, xer.so); + } + }}); + } + format IntImmLogicOp { 24: ori({{ Ra = Rs | uimm; }}); 25: oris({{ Ra = Rs | (uimm << 16); }}); @@ -451,17 +458,21 @@ decode PO default Unknown::unknown() { }}); } - format IntOp { + format IntCompOp { 0: cmp({{ - Xer xer = XER; - uint32_t cr = makeCRField(Ra_sw, Rb_sw, xer.so); - CR = insertCRField(CR, BF, cr); + if (length) { + cr = makeCRField(Ra_sd, Rb_sd, xer.so); + } else { + cr = makeCRField((int32_t)Ra_sd, (int32_t)Rb_sd, xer.so); + } }}); 32: cmpl({{ - Xer xer = XER; - uint32_t cr = makeCRField(Ra, Rb, xer.so); - CR = insertCRField(CR, BF, cr); + if (length) { + cr = makeCRField(Ra, Rb, xer.so); + } else { + cr = makeCRField((uint32_t)Ra, (uint32_t)Rb, xer.so); + } }}); } diff --git a/src/arch/power/isa/formats/integer.isa b/src/arch/power/isa/formats/integer.isa index d4a60604f..3fa058bef 100644 --- a/src/arch/power/isa/formats/integer.isa +++ b/src/arch/power/isa/formats/integer.isa @@ -221,6 +221,57 @@ def format IntDispArithOp(code, inst_flags = []) {{ }}; +// Integer compare instructions. +def format IntCompOp(code, inst_flags = []) {{ + + # Add code to setup variables + code = 'uint32_t cr M5_VAR_USED = 0;\n' + code + code += 'CR = insertCRField(CR, field, 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 = 'uint32_t cr M5_VAR_USED = 0;\n' + code + code += 'CR = insertCRField(CR, field, 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 = 'uint32_t cr M5_VAR_USED = 0;\n' + code + code += 'CR = insertCRField(CR, field, 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. All instructions have 2 versions depending on // whether the Rc bit is set to compute the CR0 code. This is determined diff --git a/src/arch/power/types.hh b/src/arch/power/types.hh index 5fc887e44..db03781fb 100644 --- a/src/arch/power/types.hh +++ b/src/arch/power/types.hh @@ -51,12 +51,16 @@ BitUnion32(ExtMachInst) // Immediate fields Bitfield<15, 0> si; + Bitfield<15, 0> ui; Bitfield<15, 0> d; Bitfield<15, 2> ds; Bitfield<15, 6> d0; Bitfield<20, 16> d1; Bitfield< 1, 0> d2; + // Compare fields + Bitfield<21> l; + // Special purpose register identifier Bitfield<20, 11> spr; Bitfield<25, 2> li;