| /* |
| * Copyright (c) 2013-2014, 2016,2018 ARM Limited |
| * All rights reserved |
| * |
| * The license below extends only to copyright in the software and shall |
| * not be construed as granting a license to any other intellectual |
| * property including but not limited to intellectual property relating |
| * to a hardware implementation of the functionality of the software |
| * licensed hereunder. You may use the software subject to the license |
| * terms below provided that you ensure that this notice is replicated |
| * unmodified and in its entirety in all distributions of the software, |
| * modified or unmodified, in source code or in binary form. |
| * |
| * 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. |
| */ |
| |
| #include "cpu/minor/dyn_inst.hh" |
| |
| #include <iomanip> |
| #include <sstream> |
| |
| #include "arch/isa.hh" |
| #include "arch/registers.hh" |
| #include "cpu/base.hh" |
| #include "cpu/minor/trace.hh" |
| #include "cpu/reg_class.hh" |
| #include "debug/MinorExecute.hh" |
| #include "enums/OpClass.hh" |
| |
| namespace Minor |
| { |
| |
| const InstSeqNum InstId::firstStreamSeqNum; |
| const InstSeqNum InstId::firstPredictionSeqNum; |
| const InstSeqNum InstId::firstLineSeqNum; |
| const InstSeqNum InstId::firstFetchSeqNum; |
| const InstSeqNum InstId::firstExecSeqNum; |
| |
| std::ostream & |
| operator <<(std::ostream &os, const InstId &id) |
| { |
| os << id.threadId << '/' << id.streamSeqNum << '.' |
| << id.predictionSeqNum << '/' << id.lineSeqNum; |
| |
| /* Not all structures have fetch and exec sequence numbers */ |
| if (id.fetchSeqNum != 0) { |
| os << '/' << id.fetchSeqNum; |
| if (id.execSeqNum != 0) |
| os << '.' << id.execSeqNum; |
| } |
| |
| return os; |
| } |
| |
| MinorDynInstPtr MinorDynInst::bubbleInst = NULL; |
| |
| void |
| MinorDynInst::init() |
| { |
| if (!bubbleInst) { |
| bubbleInst = new MinorDynInst(); |
| assert(bubbleInst->isBubble()); |
| /* Make bubbleInst immortal */ |
| bubbleInst->incref(); |
| } |
| } |
| |
| bool |
| MinorDynInst::isLastOpInInst() const |
| { |
| assert(staticInst); |
| return !(staticInst->isMicroop() && !staticInst->isLastMicroop()); |
| } |
| |
| bool |
| MinorDynInst::isNoCostInst() const |
| { |
| return isInst() && staticInst->opClass() == No_OpClass; |
| } |
| |
| void |
| MinorDynInst::reportData(std::ostream &os) const |
| { |
| if (isBubble()) |
| os << "-"; |
| else if (isFault()) |
| os << "F;" << id; |
| else if (translationFault != NoFault) |
| os << "TF;" << id; |
| else |
| os << id; |
| } |
| |
| std::ostream & |
| operator <<(std::ostream &os, const MinorDynInst &inst) |
| { |
| os << inst.id << " pc: 0x" |
| << std::hex << inst.pc.instAddr() << std::dec << " ("; |
| |
| if (inst.isFault()) |
| os << "fault: \"" << inst.fault->name() << '"'; |
| else if (inst.translationFault != NoFault) |
| os << "translation fault: \"" << inst.translationFault->name() << '"'; |
| else if (inst.staticInst) |
| os << inst.staticInst->getName(); |
| else |
| os << "bubble"; |
| |
| os << ')'; |
| |
| return os; |
| } |
| |
| /** Print a register in the form r<n>, f<n>, m<n>(<name>), z for integer, |
| * float, misc and zero registers given an 'architectural register number' */ |
| static void |
| printRegName(std::ostream &os, const RegId& reg) |
| { |
| switch (reg.classValue()) |
| { |
| case MiscRegClass: |
| { |
| RegIndex misc_reg = reg.index(); |
| |
| /* This is an ugly test because not all archs. have miscRegName */ |
| #if THE_ISA == ARM_ISA |
| os << 'm' << misc_reg << '(' << TheISA::miscRegName[misc_reg] << |
| ')'; |
| #else |
| os << 'n' << misc_reg; |
| #endif |
| } |
| break; |
| case FloatRegClass: |
| os << 'f' << static_cast<unsigned int>(reg.index()); |
| break; |
| case VecRegClass: |
| os << 'v' << static_cast<unsigned int>(reg.index()); |
| break; |
| case VecElemClass: |
| os << 'v' << static_cast<unsigned int>(reg.index()) << '[' << |
| static_cast<unsigned int>(reg.elemIndex()) << ']'; |
| break; |
| case IntRegClass: |
| if (reg.isZeroReg()) { |
| os << 'z'; |
| } else { |
| os << 'r' << static_cast<unsigned int>(reg.index()); |
| } |
| break; |
| case CCRegClass: |
| os << 'c' << static_cast<unsigned int>(reg.index()); |
| break; |
| default: |
| panic("Unknown register class: %d", (int)reg.classValue()); |
| } |
| } |
| |
| void |
| MinorDynInst::minorTraceInst(const Named &named_object) const |
| { |
| if (isFault()) { |
| MINORINST(&named_object, "id=F;%s addr=0x%x fault=\"%s\"\n", |
| id, pc.instAddr(), fault->name()); |
| } else { |
| unsigned int num_src_regs = staticInst->numSrcRegs(); |
| unsigned int num_dest_regs = staticInst->numDestRegs(); |
| |
| std::ostringstream regs_str; |
| |
| /* Format lists of src and dest registers for microops and |
| * 'full' instructions */ |
| if (!staticInst->isMacroop()) { |
| regs_str << " srcRegs="; |
| |
| unsigned int src_reg = 0; |
| while (src_reg < num_src_regs) { |
| printRegName(regs_str, staticInst->srcRegIdx(src_reg)); |
| |
| src_reg++; |
| if (src_reg != num_src_regs) |
| regs_str << ','; |
| } |
| |
| regs_str << " destRegs="; |
| |
| unsigned int dest_reg = 0; |
| while (dest_reg < num_dest_regs) { |
| printRegName(regs_str, staticInst->destRegIdx(dest_reg)); |
| |
| dest_reg++; |
| if (dest_reg != num_dest_regs) |
| regs_str << ','; |
| } |
| |
| ccprintf(regs_str, " extMachInst=%160x", staticInst->machInst); |
| } |
| |
| std::ostringstream flags; |
| staticInst->printFlags(flags, " "); |
| |
| MINORINST(&named_object, "id=%s addr=0x%x inst=\"%s\" class=%s" |
| " flags=\"%s\"%s%s\n", |
| id, pc.instAddr(), |
| (staticInst->opClass() == No_OpClass ? |
| "(invalid)" : staticInst->disassemble(0,NULL)), |
| Enums::OpClassStrings[staticInst->opClass()], |
| flags.str(), |
| regs_str.str(), |
| (predictedTaken ? " predictedTaken" : "")); |
| } |
| } |
| |
| MinorDynInst::~MinorDynInst() |
| { |
| if (traceData) |
| delete traceData; |
| } |
| |
| } |