blob: 1b43fc80772ca39e7d94e56668836f29d81ca168 [file] [log] [blame]
/*
* 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;
}
}