sparc: Pull StaticInst base classes out of the ISA description.

Also, do some minor refactoring to use a BitUnion to pull apart
condition codes, etc.

Change-Id: I0c88878b07a731d0c0fe30f264f53dd795db99ae
Reviewed-on: https://gem5-review.googlesource.com/5421
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
Gabe Black
2017-11-05 15:41:59 -08:00
parent 205add5769
commit d626f4f7aa
6 changed files with 598 additions and 517 deletions

View File

@@ -0,0 +1,35 @@
# -*- mode:python -*-
# Copyright (c) 2004-2005 The Regents of The University of Michigan
# 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: Gabe Black
# Steve Reinhardt
Import('*')
if env['TARGET_ISA'] == 'sparc':
Source('static_inst.cc')

View File

@@ -0,0 +1,372 @@
/*
* Copyright (c) 2006-2007 The Regents of The University of Michigan
* All rights reserved
* Copyright 2017 Google Inc.
*
* 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: Gabe Black
*/
#include "arch/sparc/insts/static_inst.hh"
namespace SparcISA
{
const char *CondTestAbbrev[] =
{
[Never] = "nev",
[Equal] = "e",
[LessOrEqual] = "le",
[Less] = "l",
[LessOrEqualUnsigned] = "leu",
[CarrySet] = "c",
[Negative] = "n",
[OverflowSet] = "o",
[Always] = "a",
[NotEqual] = "ne",
[Greater] = "g",
[GreaterOrEqual] = "ge",
[GreaterUnsigned] = "gu",
[CarryClear] = "cc",
[Positive] = "p",
[OverflowClear] = "oc"
};
void
SparcStaticInst::printMnemonic(std::ostream &os, const char *mnemonic)
{
ccprintf(os, "\t%s ", mnemonic);
}
void
SparcStaticInst::printRegArray(std::ostream &os, const RegId indexArray[],
int num) const
{
if (num <= 0)
return;
printReg(os, indexArray[0]);
for (int x = 1; x < num; x++) {
os << ", ";
printReg(os, indexArray[x]);
}
}
void
SparcStaticInst::advancePC(SparcISA::PCState &pcState) const
{
pcState.advance();
}
void
SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
{
if (_numSrcRegs > reg)
printReg(os, _srcRegIdx[reg]);
}
void
SparcStaticInst::printDestReg(std::ostream &os, int reg) const
{
if (_numDestRegs > reg)
printReg(os, _destRegIdx[reg]);
}
void
SparcStaticInst::printReg(std::ostream &os, RegId reg)
{
const int MaxGlobal = 8;
const int MaxOutput = 16;
const int MaxLocal = 24;
const int MaxInput = 32;
const int MaxMicroReg = 40;
RegIndex reg_idx = reg.index();
if (reg.isIntReg()) {
// If we used a register from the next or previous window,
// take out the offset.
while (reg_idx >= MaxMicroReg)
reg_idx -= MaxMicroReg;
if (reg_idx == FramePointerReg)
ccprintf(os, "%%fp");
else if (reg_idx == StackPointerReg)
ccprintf(os, "%%sp");
else if (reg_idx < MaxGlobal)
ccprintf(os, "%%g%d", reg_idx);
else if (reg_idx < MaxOutput)
ccprintf(os, "%%o%d", reg_idx - MaxGlobal);
else if (reg_idx < MaxLocal)
ccprintf(os, "%%l%d", reg_idx - MaxOutput);
else if (reg_idx < MaxInput)
ccprintf(os, "%%i%d", reg_idx - MaxLocal);
else if (reg_idx < MaxMicroReg)
ccprintf(os, "%%u%d", reg_idx - MaxInput);
// The fake int regs that are really control regs
else {
switch (reg_idx - MaxMicroReg) {
case 1:
ccprintf(os, "%%y");
break;
case 2:
ccprintf(os, "%%ccr");
break;
case 3:
ccprintf(os, "%%cansave");
break;
case 4:
ccprintf(os, "%%canrestore");
break;
case 5:
ccprintf(os, "%%cleanwin");
break;
case 6:
ccprintf(os, "%%otherwin");
break;
case 7:
ccprintf(os, "%%wstate");
break;
}
}
} else if (reg.isFloatReg()) {
ccprintf(os, "%%f%d", reg_idx);
} else {
switch (reg_idx) {
case MISCREG_ASI:
ccprintf(os, "%%asi");
break;
case MISCREG_FPRS:
ccprintf(os, "%%fprs");
break;
case MISCREG_PCR:
ccprintf(os, "%%pcr");
break;
case MISCREG_PIC:
ccprintf(os, "%%pic");
break;
case MISCREG_GSR:
ccprintf(os, "%%gsr");
break;
case MISCREG_SOFTINT:
ccprintf(os, "%%softint");
break;
case MISCREG_SOFTINT_SET:
ccprintf(os, "%%softint_set");
break;
case MISCREG_SOFTINT_CLR:
ccprintf(os, "%%softint_clr");
break;
case MISCREG_TICK_CMPR:
ccprintf(os, "%%tick_cmpr");
break;
case MISCREG_STICK:
ccprintf(os, "%%stick");
break;
case MISCREG_STICK_CMPR:
ccprintf(os, "%%stick_cmpr");
break;
case MISCREG_TPC:
ccprintf(os, "%%tpc");
break;
case MISCREG_TNPC:
ccprintf(os, "%%tnpc");
break;
case MISCREG_TSTATE:
ccprintf(os, "%%tstate");
break;
case MISCREG_TT:
ccprintf(os, "%%tt");
break;
case MISCREG_TICK:
ccprintf(os, "%%tick");
break;
case MISCREG_TBA:
ccprintf(os, "%%tba");
break;
case MISCREG_PSTATE:
ccprintf(os, "%%pstate");
break;
case MISCREG_TL:
ccprintf(os, "%%tl");
break;
case MISCREG_PIL:
ccprintf(os, "%%pil");
break;
case MISCREG_CWP:
ccprintf(os, "%%cwp");
break;
case MISCREG_GL:
ccprintf(os, "%%gl");
break;
case MISCREG_HPSTATE:
ccprintf(os, "%%hpstate");
break;
case MISCREG_HTSTATE:
ccprintf(os, "%%htstate");
break;
case MISCREG_HINTP:
ccprintf(os, "%%hintp");
break;
case MISCREG_HTBA:
ccprintf(os, "%%htba");
break;
case MISCREG_HSTICK_CMPR:
ccprintf(os, "%%hstick_cmpr");
break;
case MISCREG_HVER:
ccprintf(os, "%%hver");
break;
case MISCREG_STRAND_STS_REG:
ccprintf(os, "%%strand_sts_reg");
break;
case MISCREG_FSR:
ccprintf(os, "%%fsr");
break;
default:
ccprintf(os, "%%ctrl%d", reg_idx);
}
}
}
std::string
SparcStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss, mnemonic);
// just print the first two source regs... if there's
// a third one, it's a read-modify-write dest (Rc),
// e.g. for CMOVxx
if (_numSrcRegs > 0)
printReg(ss, _srcRegIdx[0]);
if (_numSrcRegs > 1) {
ss << ",";
printReg(ss, _srcRegIdx[1]);
}
// just print the first dest... if there's a second one,
// it's generally implicit
if (_numDestRegs > 0) {
if (_numSrcRegs > 0)
ss << ",";
printReg(ss, _destRegIdx[0]);
}
return ss.str();
}
bool
SparcStaticInst::passesFpCondition(uint32_t fcc, uint32_t condition)
{
bool u = (fcc == 3);
bool g = (fcc == 2);
bool l = (fcc == 1);
bool e = (fcc == 0);
switch (condition) {
case FAlways:
return 1;
case FNever:
return 0;
case FUnordered:
return u;
case FGreater:
return g;
case FUnorderedOrGreater:
return u || g;
case FLess:
return l;
case FUnorderedOrLess:
return u || l;
case FLessOrGreater:
return l || g;
case FNotEqual:
return l || g || u;
case FEqual:
return e;
case FUnorderedOrEqual:
return u || e;
case FGreaterOrEqual:
return g || e;
case FUnorderedOrGreaterOrEqual:
return u || g || e;
case FLessOrEqual:
return l || e;
case FUnorderedOrLessOrEqual:
return u || l || e;
case FOrdered:
return e || l || g;
}
panic("Tried testing condition nonexistant condition code %d", condition);
}
bool
SparcStaticInst::passesCondition(uint32_t codes, uint32_t condition)
{
BitUnion32(CondCodes)
Bitfield<0> c;
Bitfield<1> v;
Bitfield<2> z;
Bitfield<3> n;
EndBitUnion(CondCodes)
CondCodes condCodes = codes;
switch (condition) {
case Always:
return true;
case Never:
return false;
case NotEqual:
return !condCodes.z;
case Equal:
return condCodes.z;
case Greater:
return !(condCodes.z | (condCodes.n ^ condCodes.v));
case LessOrEqual:
return condCodes.z | (condCodes.n ^ condCodes.v);
case GreaterOrEqual:
return !(condCodes.n ^ condCodes.v);
case Less:
return (condCodes.n ^ condCodes.v);
case GreaterUnsigned:
return !(condCodes.c | condCodes.z);
case LessOrEqualUnsigned:
return (condCodes.c | condCodes.z);
case CarryClear:
return !condCodes.c;
case CarrySet:
return condCodes.c;
case Positive:
return !condCodes.n;
case Negative:
return condCodes.n;
case OverflowClear:
return !condCodes.v;
case OverflowSet:
return condCodes.v;
}
panic("Tried testing condition nonexistant "
"condition code %d", condition);
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2006-2007 The Regents of The University of Michigan
* All rights reserved.
* Copyright 2017 Google Inc.
*
* 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: Gabe Black
*/
#ifndef __ARCH_SPARC_INSTS_STATIC_INST_HH__
#define __ARCH_SPARC_INSTS_STATIC_INST_HH__
#include <cstdint>
#include "base/trace.hh"
#include "cpu/exec_context.hh"
#include "cpu/static_inst.hh"
namespace SparcISA
{
enum CondTest
{
Always=0x8,
Never=0x0,
NotEqual=0x9,
Equal=0x1,
Greater=0xA,
LessOrEqual=0x2,
GreaterOrEqual=0xB,
Less=0x3,
GreaterUnsigned=0xC,
LessOrEqualUnsigned=0x4,
CarryClear=0xD,
CarrySet=0x5,
Positive=0xE,
Negative=0x6,
OverflowClear=0xF,
OverflowSet=0x7
};
extern const char *CondTestAbbrev[];
enum FpCondTest
{
FAlways=0x8,
FNever=0x0,
FUnordered=0x7,
FGreater=0x6,
FUnorderedOrGreater=0x5,
FLess=0x4,
FUnorderedOrLess=0x3,
FLessOrGreater=0x2,
FNotEqual=0x1,
FEqual=0x9,
FUnorderedOrEqual=0xA,
FGreaterOrEqual=0xB,
FUnorderedOrGreaterOrEqual=0xC,
FLessOrEqual=0xD,
FUnorderedOrLessOrEqual=0xE,
FOrdered=0xF
};
/**
* Base class for all SPARC static instructions.
*/
class SparcStaticInst : public StaticInst
{
protected:
using StaticInst::StaticInst;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
static void printMnemonic(std::ostream &os, const char *mnemonic);
static void printReg(std::ostream &os, RegId reg);
void printSrcReg(std::ostream &os, int reg) const;
void printDestReg(std::ostream &os, int reg) const;
void printRegArray(std::ostream &os,
const RegId indexArray[], int num) const;
void advancePC(PCState &pcState) const;
static bool passesFpCondition(uint32_t fcc, uint32_t condition);
static bool passesCondition(uint32_t codes, uint32_t condition);
};
}
#endif //__ARCH_SPARC_INSTS_STATIC_INST_HH__

View File

@@ -28,128 +28,6 @@
// Gabe Black
// Steve Reinhardt
////////////////////////////////////////////////////////////////////
//
// Base class for sparc instructions, and some support functions
//
output header {{
union CondCodes
{
struct
{
uint8_t c:1;
uint8_t v:1;
uint8_t z:1;
uint8_t n:1;
};
uint32_t bits;
};
enum CondTest
{
Always=0x8,
Never=0x0,
NotEqual=0x9,
Equal=0x1,
Greater=0xA,
LessOrEqual=0x2,
GreaterOrEqual=0xB,
Less=0x3,
GreaterUnsigned=0xC,
LessOrEqualUnsigned=0x4,
CarryClear=0xD,
CarrySet=0x5,
Positive=0xE,
Negative=0x6,
OverflowClear=0xF,
OverflowSet=0x7
};
enum FpCondTest
{
FAlways=0x8,
FNever=0x0,
FUnordered=0x7,
FGreater=0x6,
FUnorderedOrGreater=0x5,
FLess=0x4,
FUnorderedOrLess=0x3,
FLessOrGreater=0x2,
FNotEqual=0x1,
FEqual=0x9,
FUnorderedOrEqual=0xA,
FGreaterOrEqual=0xB,
FUnorderedOrGreaterOrEqual=0xC,
FLessOrEqual=0xD,
FUnorderedOrLessOrEqual=0xE,
FOrdered=0xF
};
extern const char *CondTestAbbrev[];
/**
* Base class for all SPARC static instructions.
*/
class SparcStaticInst : public StaticInst
{
protected:
// Constructor.
SparcStaticInst(const char *mnem,
ExtMachInst _machInst, OpClass __opClass)
: StaticInst(mnem, _machInst, __opClass)
{
}
std::string generateDisassembly(Addr pc,
const SymbolTable *symtab) const;
void printReg(std::ostream &os, RegId reg) const;
void printSrcReg(std::ostream &os, int reg) const;
void printDestReg(std::ostream &os, int reg) const;
void printRegArray(std::ostream &os,
const RegId indexArray[], int num) const;
void advancePC(SparcISA::PCState &pcState) const;
};
bool passesFpCondition(uint32_t fcc, uint32_t condition);
bool passesCondition(uint32_t codes, uint32_t condition);
inline int64_t
sign_ext(uint64_t data, int origWidth)
{
int shiftAmount = 64 - origWidth;
return (((int64_t)data) << shiftAmount) >> shiftAmount;
}
}};
output decoder {{
const char *CondTestAbbrev[] =
{
"nev", // Never
"e", // Equal
"le", // Less or Equal
"l", // Less
"leu", // Less or Equal Unsigned
"c", // Carry set
"n", // Negative
"o", // Overflow set
"a", // Always
"ne", // Not Equal
"g", // Greater
"ge", // Greater or Equal
"gu", // Greater Unsigned
"cc", // Carry clear
"p", // Positive
"oc" // Overflow Clear
};
}};
def template ROrImmDecode {{
{
return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst))
@@ -243,322 +121,6 @@ let {{
return (True, code, imm_code, rString, iString)
}};
output decoder {{
inline void printMnemonic(std::ostream &os, const char * mnemonic)
{
ccprintf(os, "\t%s ", mnemonic);
}
void SparcStaticInst::printRegArray(std::ostream &os,
const RegId indexArray[], int num) const
{
if (num <= 0)
return;
printReg(os, indexArray[0]);
for (int x = 1; x < num; x++) {
os << ", ";
printReg(os, indexArray[x]);
}
}
void
SparcStaticInst::advancePC(SparcISA::PCState &pcState) const
{
pcState.advance();
}
void
SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
{
if (_numSrcRegs > reg)
printReg(os, _srcRegIdx[reg]);
}
void
SparcStaticInst::printDestReg(std::ostream &os, int reg) const
{
if (_numDestRegs > reg)
printReg(os, _destRegIdx[reg]);
}
void
SparcStaticInst::printReg(std::ostream &os, RegId reg) const
{
const int MaxGlobal = 8;
const int MaxOutput = 16;
const int MaxLocal = 24;
const int MaxInput = 32;
const int MaxMicroReg = 40;
RegIndex reg_idx = reg.index();
if (reg.isIntReg()) {
// If we used a register from the next or previous window,
// take out the offset.
while (reg_idx >= MaxMicroReg)
reg_idx -= MaxMicroReg;
if (reg_idx == FramePointerReg)
ccprintf(os, "%%fp");
else if (reg_idx == StackPointerReg)
ccprintf(os, "%%sp");
else if (reg_idx < MaxGlobal)
ccprintf(os, "%%g%d", reg_idx);
else if (reg_idx < MaxOutput)
ccprintf(os, "%%o%d", reg_idx - MaxGlobal);
else if (reg_idx < MaxLocal)
ccprintf(os, "%%l%d", reg_idx - MaxOutput);
else if (reg_idx < MaxInput)
ccprintf(os, "%%i%d", reg_idx - MaxLocal);
else if (reg_idx < MaxMicroReg)
ccprintf(os, "%%u%d", reg_idx - MaxInput);
// The fake int regs that are really control regs
else {
switch (reg_idx - MaxMicroReg) {
case 1:
ccprintf(os, "%%y");
break;
case 2:
ccprintf(os, "%%ccr");
break;
case 3:
ccprintf(os, "%%cansave");
break;
case 4:
ccprintf(os, "%%canrestore");
break;
case 5:
ccprintf(os, "%%cleanwin");
break;
case 6:
ccprintf(os, "%%otherwin");
break;
case 7:
ccprintf(os, "%%wstate");
break;
}
}
} else if (reg.isFloatReg()) {
ccprintf(os, "%%f%d", reg_idx);
} else {
switch (reg_idx) {
case MISCREG_ASI:
ccprintf(os, "%%asi");
break;
case MISCREG_FPRS:
ccprintf(os, "%%fprs");
break;
case MISCREG_PCR:
ccprintf(os, "%%pcr");
break;
case MISCREG_PIC:
ccprintf(os, "%%pic");
break;
case MISCREG_GSR:
ccprintf(os, "%%gsr");
break;
case MISCREG_SOFTINT:
ccprintf(os, "%%softint");
break;
case MISCREG_SOFTINT_SET:
ccprintf(os, "%%softint_set");
break;
case MISCREG_SOFTINT_CLR:
ccprintf(os, "%%softint_clr");
break;
case MISCREG_TICK_CMPR:
ccprintf(os, "%%tick_cmpr");
break;
case MISCREG_STICK:
ccprintf(os, "%%stick");
break;
case MISCREG_STICK_CMPR:
ccprintf(os, "%%stick_cmpr");
break;
case MISCREG_TPC:
ccprintf(os, "%%tpc");
break;
case MISCREG_TNPC:
ccprintf(os, "%%tnpc");
break;
case MISCREG_TSTATE:
ccprintf(os, "%%tstate");
break;
case MISCREG_TT:
ccprintf(os, "%%tt");
break;
case MISCREG_TICK:
ccprintf(os, "%%tick");
break;
case MISCREG_TBA:
ccprintf(os, "%%tba");
break;
case MISCREG_PSTATE:
ccprintf(os, "%%pstate");
break;
case MISCREG_TL:
ccprintf(os, "%%tl");
break;
case MISCREG_PIL:
ccprintf(os, "%%pil");
break;
case MISCREG_CWP:
ccprintf(os, "%%cwp");
break;
case MISCREG_GL:
ccprintf(os, "%%gl");
break;
case MISCREG_HPSTATE:
ccprintf(os, "%%hpstate");
break;
case MISCREG_HTSTATE:
ccprintf(os, "%%htstate");
break;
case MISCREG_HINTP:
ccprintf(os, "%%hintp");
break;
case MISCREG_HTBA:
ccprintf(os, "%%htba");
break;
case MISCREG_HSTICK_CMPR:
ccprintf(os, "%%hstick_cmpr");
break;
case MISCREG_HVER:
ccprintf(os, "%%hver");
break;
case MISCREG_STRAND_STS_REG:
ccprintf(os, "%%strand_sts_reg");
break;
case MISCREG_FSR:
ccprintf(os, "%%fsr");
break;
default:
ccprintf(os, "%%ctrl%d", reg_idx);
}
}
}
std::string
SparcStaticInst::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss, mnemonic);
// just print the first two source regs... if there's
// a third one, it's a read-modify-write dest (Rc),
// e.g. for CMOVxx
if (_numSrcRegs > 0)
printReg(ss, _srcRegIdx[0]);
if (_numSrcRegs > 1) {
ss << ",";
printReg(ss, _srcRegIdx[1]);
}
// just print the first dest... if there's a second one,
// it's generally implicit
if (_numDestRegs > 0) {
if (_numSrcRegs > 0)
ss << ",";
printReg(ss, _destRegIdx[0]);
}
return ss.str();
}
bool
passesFpCondition(uint32_t fcc, uint32_t condition)
{
bool u = (fcc == 3);
bool g = (fcc == 2);
bool l = (fcc == 1);
bool e = (fcc == 0);
switch (condition) {
case FAlways:
return 1;
case FNever:
return 0;
case FUnordered:
return u;
case FGreater:
return g;
case FUnorderedOrGreater:
return u || g;
case FLess:
return l;
case FUnorderedOrLess:
return u || l;
case FLessOrGreater:
return l || g;
case FNotEqual:
return l || g || u;
case FEqual:
return e;
case FUnorderedOrEqual:
return u || e;
case FGreaterOrEqual:
return g || e;
case FUnorderedOrGreaterOrEqual:
return u || g || e;
case FLessOrEqual:
return l || e;
case FUnorderedOrLessOrEqual:
return u || l || e;
case FOrdered:
return e || l || g;
}
panic("Tried testing condition nonexistant "
"condition code %d", condition);
}
bool
passesCondition(uint32_t codes, uint32_t condition)
{
CondCodes condCodes;
condCodes.bits = 0;
condCodes.c = codes & 0x1 ? 1 : 0;
condCodes.v = codes & 0x2 ? 1 : 0;
condCodes.z = codes & 0x4 ? 1 : 0;
condCodes.n = codes & 0x8 ? 1 : 0;
switch (condition) {
case Always:
return true;
case Never:
return false;
case NotEqual:
return !condCodes.z;
case Equal:
return condCodes.z;
case Greater:
return !(condCodes.z | (condCodes.n ^ condCodes.v));
case LessOrEqual:
return condCodes.z | (condCodes.n ^ condCodes.v);
case GreaterOrEqual:
return !(condCodes.n ^ condCodes.v);
case Less:
return (condCodes.n ^ condCodes.v);
case GreaterUnsigned:
return !(condCodes.c | condCodes.z);
case LessOrEqualUnsigned:
return (condCodes.c | condCodes.z);
case CarryClear:
return !condCodes.c;
case CarrySet:
return condCodes.c;
case Positive:
return !condCodes.n;
case Negative:
return condCodes.n;
case OverflowClear:
return !condCodes.v;
case OverflowSet:
return condCodes.v;
}
panic("Tried testing condition nonexistant "
"condition code %d", condition);
}
}};
output exec {{
/// Check "FP enabled" machine status bit. Called when executing any FP
/// instruction.
@@ -578,6 +140,7 @@ output exec {{
return NoFault;
}
}
static inline Fault
checkVecEnableFault(ExecContext *xc)
{

View File

@@ -30,121 +30,119 @@
// Basic instruction class declaration template.
def template BasicDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
public:
// Constructor.
%(class_name)s(ExtMachInst machInst);
Fault execute(ExecContext *, Trace::InstRecord *) const;
};
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
public:
// Constructor.
%(class_name)s(ExtMachInst machInst);
Fault execute(ExecContext *, Trace::InstRecord *) const;
};
}};
// Basic instruction class declaration template.
def template FpBasicDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
public:
// Constructor.
%(class_name)s(ExtMachInst machInst);
Fault execute(ExecContext *, Trace::InstRecord *) const;
Fault doFpOp(ExecContext *,
Trace::InstRecord *) const M5_NO_INLINE;
};
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
public:
// Constructor.
%(class_name)s(ExtMachInst machInst);
Fault execute(ExecContext *, Trace::InstRecord *) const;
Fault doFpOp(ExecContext *, Trace::InstRecord *) const M5_NO_INLINE;
};
}};
// Basic instruction class declaration template.
def template BasicDeclareWithMnemonic {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
public:
// Constructor.
%(class_name)s(const char * mnemonic, ExtMachInst machInst);
Fault execute(ExecContext *, Trace::InstRecord *) const;
};
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
public:
// Constructor.
%(class_name)s(const char *mnemonic, ExtMachInst machInst);
Fault execute(ExecContext *, Trace::InstRecord *) const;
};
}};
// Basic instruction class constructor template.
def template BasicConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
{
%(constructor)s;
}
%(class_name)s::%(class_name)s(ExtMachInst machInst) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
{
%(constructor)s;
}
}};
// Basic instruction class constructor template.
def template BasicConstructorWithMnemonic {{
%(class_name)s::%(class_name)s(const char * mnemonic,
ExtMachInst machInst)
: %(base_class)s(mnemonic, machInst, %(op_class)s)
{
%(constructor)s;
}
%(class_name)s::%(class_name)s(const char *mnemonic, ExtMachInst machInst) :
%(base_class)s(mnemonic, machInst, %(op_class)s)
{
%(constructor)s;
}
}};
// Basic instruction class execute method template.
def template BasicExecute {{
Fault
%(class_name)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
Fault
%(class_name)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(fp_enable_check)s;
%(op_decl)s;
%(op_rd)s;
%(code)s;
%(fp_enable_check)s;
%(op_decl)s;
%(op_rd)s;
%(code)s;
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template DoFpOpExecute {{
Fault
%(class_name)s::doFpOp(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(fp_code)s;
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
Fault
%(class_name)s::doFpOp(ExecContext *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(fp_code)s;
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
// Basic decode template.
def template BasicDecode {{
return new %(class_name)s(machInst);
return new %(class_name)s(machInst);
}};
// Basic decode template, passing mnemonic in as string arg to constructor.
def template BasicDecodeWithMnemonic {{
return new %(class_name)s("%(mnemonic)s", machInst);
return new %(class_name)s("%(mnemonic)s", machInst);
}};
// The most basic instruction format... used only for a few misc. insts
def format BasicOperate(code, *flags) {{
code = filterDoubles(code)
iop = InstObjParams(name, Name, 'SparcStaticInst', code, flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = BasicDecode.subst(iop)
exec_output = BasicExecute.subst(iop)
code = filterDoubles(code)
iop = InstObjParams(name, Name, 'SparcStaticInst', code, flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = BasicDecode.subst(iop)
exec_output = BasicExecute.subst(iop)
}};
def format FpBasic(code, *flags) {{
@@ -168,7 +166,7 @@ def format FpBasic(code, *flags) {{
"""
fp_code = filterDoubles(code)
iop = InstObjParams(name, Name, 'SparcStaticInst',
{ "code" : exec_code, "fp_code" : fp_code }, flags)
{ "code" : exec_code, "fp_code" : fp_code }, flags)
header_output = FpBasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = BasicDecode.subst(iop)

View File

@@ -39,6 +39,7 @@ output header {{
#include <sstream>
#include "arch/sparc/faults.hh"
#include "arch/sparc/insts/static_inst.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/registers.hh"
#include "base/condcodes.hh"