dd473ecd57
(thanks to Gabe's include feature!). arch/alpha/isa/main.isa: Split out into multiple .isa files. --HG-- extra : convert_revision : 30d8edf74ea194d4a208febf1e66edc72a7dbd5d
300 lines
10 KiB
C++
300 lines
10 KiB
C++
// -*- mode:c++ -*-
|
|
|
|
// Copyright (c) 2003-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.
|
|
|
|
output exec {{
|
|
/// Check "FP enabled" machine status bit. Called when executing any FP
|
|
/// instruction in full-system mode.
|
|
/// @retval Full-system mode: No_Fault if FP is enabled, Fen_Fault
|
|
/// if not. Non-full-system mode: always returns No_Fault.
|
|
#if FULL_SYSTEM
|
|
inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
|
|
{
|
|
Fault fault = No_Fault; // dummy... this ipr access should not fault
|
|
if (!EV5::ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
|
|
fault = Fen_Fault;
|
|
}
|
|
return fault;
|
|
}
|
|
#else
|
|
inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
|
|
{
|
|
return No_Fault;
|
|
}
|
|
#endif
|
|
}};
|
|
|
|
output header {{
|
|
/**
|
|
* Base class for general floating-point instructions. Includes
|
|
* support for various Alpha rounding and trapping modes. Only FP
|
|
* instructions that require this support are derived from this
|
|
* class; the rest derive directly from AlphaStaticInst.
|
|
*/
|
|
class AlphaFP : public AlphaStaticInst
|
|
{
|
|
public:
|
|
/// Alpha FP rounding modes.
|
|
enum RoundingMode {
|
|
Chopped = 0, ///< round toward zero
|
|
Minus_Infinity = 1, ///< round toward minus infinity
|
|
Normal = 2, ///< round to nearest (default)
|
|
Dynamic = 3, ///< use FPCR setting (in instruction)
|
|
Plus_Infinity = 3 ///< round to plus inifinity (in FPCR)
|
|
};
|
|
|
|
/// Alpha FP trapping modes.
|
|
/// For instructions that produce integer results, the
|
|
/// "Underflow Enable" modes really mean "Overflow Enable", and
|
|
/// the assembly modifier is V rather than U.
|
|
enum TrappingMode {
|
|
/// default: nothing enabled
|
|
Imprecise = 0, ///< no modifier
|
|
/// underflow/overflow traps enabled, inexact disabled
|
|
Underflow_Imprecise = 1, ///< /U or /V
|
|
Underflow_Precise = 5, ///< /SU or /SV
|
|
/// underflow/overflow and inexact traps enabled
|
|
Underflow_Inexact_Precise = 7 ///< /SUI or /SVI
|
|
};
|
|
|
|
protected:
|
|
/// Map Alpha rounding mode to C99 constants from <fenv.h>.
|
|
static const int alphaToC99RoundingMode[];
|
|
|
|
/// Map enum RoundingMode values to disassembly suffixes.
|
|
static const char *roundingModeSuffix[];
|
|
/// Map enum TrappingMode values to FP disassembly suffixes.
|
|
static const char *fpTrappingModeSuffix[];
|
|
/// Map enum TrappingMode values to integer disassembly suffixes.
|
|
static const char *intTrappingModeSuffix[];
|
|
|
|
/// This instruction's rounding mode.
|
|
RoundingMode roundingMode;
|
|
/// This instruction's trapping mode.
|
|
TrappingMode trappingMode;
|
|
|
|
/// Have we warned about this instruction's unsupported
|
|
/// rounding mode (if applicable)?
|
|
mutable bool warnedOnRounding;
|
|
|
|
/// Have we warned about this instruction's unsupported
|
|
/// trapping mode (if applicable)?
|
|
mutable bool warnedOnTrapping;
|
|
|
|
/// Constructor
|
|
AlphaFP(const char *mnem, MachInst _machInst, OpClass __opClass)
|
|
: AlphaStaticInst(mnem, _machInst, __opClass),
|
|
roundingMode((enum RoundingMode)FP_ROUNDMODE),
|
|
trappingMode((enum TrappingMode)FP_TRAPMODE),
|
|
warnedOnRounding(false),
|
|
warnedOnTrapping(false)
|
|
{
|
|
}
|
|
|
|
int getC99RoundingMode(uint64_t fpcr_val) const;
|
|
|
|
// This differs from the AlphaStaticInst version only in
|
|
// printing suffixes for non-default rounding & trapping modes.
|
|
std::string
|
|
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
|
};
|
|
|
|
}};
|
|
|
|
|
|
output decoder {{
|
|
int
|
|
AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
|
|
{
|
|
if (roundingMode == Dynamic) {
|
|
return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
|
|
}
|
|
else {
|
|
return alphaToC99RoundingMode[roundingMode];
|
|
}
|
|
}
|
|
|
|
std::string
|
|
AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
|
{
|
|
std::string mnem_str(mnemonic);
|
|
|
|
#ifndef SS_COMPATIBLE_DISASSEMBLY
|
|
std::string suffix("");
|
|
suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
|
|
? fpTrappingModeSuffix[trappingMode]
|
|
: intTrappingModeSuffix[trappingMode]);
|
|
suffix += roundingModeSuffix[roundingMode];
|
|
|
|
if (suffix != "") {
|
|
mnem_str = csprintf("%s/%s", mnemonic, suffix);
|
|
}
|
|
#endif
|
|
|
|
std::stringstream ss;
|
|
ccprintf(ss, "%-10s ", mnem_str.c_str());
|
|
|
|
// 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();
|
|
}
|
|
|
|
const int AlphaFP::alphaToC99RoundingMode[] = {
|
|
FE_TOWARDZERO, // Chopped
|
|
FE_DOWNWARD, // Minus_Infinity
|
|
FE_TONEAREST, // Normal
|
|
FE_UPWARD // Dynamic in inst, Plus_Infinity in FPCR
|
|
};
|
|
|
|
const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
|
|
// mark invalid trapping modes, but don't fail on them, because
|
|
// you could decode anything on a misspeculated path
|
|
const char *AlphaFP::fpTrappingModeSuffix[] =
|
|
{ "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
|
|
const char *AlphaFP::intTrappingModeSuffix[] =
|
|
{ "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
|
|
}};
|
|
|
|
// FP instruction class execute method template. Handles non-standard
|
|
// rounding modes.
|
|
def template FloatingPointExecute {{
|
|
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
|
|
Trace::InstRecord *traceData) const
|
|
{
|
|
if (trappingMode != Imprecise && !warnedOnTrapping) {
|
|
warn("%s: non-standard trapping mode not supported",
|
|
generateDisassembly(0, NULL));
|
|
warnedOnTrapping = true;
|
|
}
|
|
|
|
Fault fault = No_Fault;
|
|
|
|
%(fp_enable_check)s;
|
|
%(op_decl)s;
|
|
%(op_rd)s;
|
|
#if USE_FENV
|
|
if (roundingMode == Normal) {
|
|
%(code)s;
|
|
} else {
|
|
fesetround(getC99RoundingMode(xc->readFpcr()));
|
|
%(code)s;
|
|
fesetround(FE_TONEAREST);
|
|
}
|
|
#else
|
|
if (roundingMode != Normal && !warnedOnRounding) {
|
|
warn("%s: non-standard rounding mode not supported",
|
|
generateDisassembly(0, NULL));
|
|
warnedOnRounding = true;
|
|
}
|
|
%(code)s;
|
|
#endif
|
|
|
|
if (fault == No_Fault) {
|
|
%(op_wb)s;
|
|
}
|
|
|
|
return fault;
|
|
}
|
|
}};
|
|
|
|
// FP instruction class execute method template where no dynamic
|
|
// rounding mode control is needed. Like BasicExecute, but includes
|
|
// check & warning for non-standard trapping mode.
|
|
def template FPFixedRoundingExecute {{
|
|
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
|
|
Trace::InstRecord *traceData) const
|
|
{
|
|
if (trappingMode != Imprecise && !warnedOnTrapping) {
|
|
warn("%s: non-standard trapping mode not supported",
|
|
generateDisassembly(0, NULL));
|
|
warnedOnTrapping = true;
|
|
}
|
|
|
|
Fault fault = No_Fault;
|
|
|
|
%(fp_enable_check)s;
|
|
%(op_decl)s;
|
|
%(op_rd)s;
|
|
%(code)s;
|
|
|
|
if (fault == No_Fault) {
|
|
%(op_wb)s;
|
|
}
|
|
|
|
return fault;
|
|
}
|
|
}};
|
|
|
|
def template FloatingPointDecode {{
|
|
{
|
|
AlphaStaticInst *i = new %(class_name)s(machInst);
|
|
if (FC == 31) {
|
|
i = makeNop(i);
|
|
}
|
|
return i;
|
|
}
|
|
}};
|
|
|
|
// General format for floating-point operate instructions:
|
|
// - Checks trapping and rounding mode flags. Trapping modes
|
|
// currently unimplemented (will fail).
|
|
// - Generates NOP if FC == 31.
|
|
def format FloatingPointOperate(code, *opt_args) {{
|
|
iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
|
|
decode_block = FloatingPointDecode.subst(iop)
|
|
header_output = BasicDeclare.subst(iop)
|
|
decoder_output = BasicConstructor.subst(iop)
|
|
exec_output = FloatingPointExecute.subst(iop)
|
|
}};
|
|
|
|
// Special format for cvttq where rounding mode is pre-decoded
|
|
def format FPFixedRounding(code, class_suffix, *opt_args) {{
|
|
Name += class_suffix
|
|
iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
|
|
decode_block = FloatingPointDecode.subst(iop)
|
|
header_output = BasicDeclare.subst(iop)
|
|
decoder_output = BasicConstructor.subst(iop)
|
|
exec_output = FPFixedRoundingExecute.subst(iop)
|
|
}};
|
|
|