Update IGA

Change-Id: Ieb4e0c55ea8f63270492c9f32c71aed725f4c648
This commit is contained in:
poyuchen
2018-04-30 11:58:43 -07:00
committed by Aleksander Stojanowski
parent 8a5091dd1d
commit 1d3ef54716
21 changed files with 323 additions and 189 deletions

View File

@ -66,11 +66,6 @@ set_property( TARGET GEDLibrary APPEND PROPERTY
COMPILE_DEFINITIONS $<$<CONFIG:Debug>:GED_DEBUG>
)
if (IGC_BUILD AND MSVC)
#set up standard defines from the common WDK path.
bs_set_wdk(GEDLibrary)
endif()
# hidden visibility suppresses PLT entries from being created for GED and functions and trims the interface down to a minimal size
#Was manifested when IGA was used in GT-PIN which also uses GED. IGA ended up using GED library linked with GT-PIN not IGA one
#https://gcc.gnu.org/wiki/Visibility

View File

@ -24,4 +24,4 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
======================= end_copyright_notice ==================================*/
const char* gedVersion = "dev (8e84a7de)";
const char* gedVersion = "dev (fc70de55)";

View File

@ -80,7 +80,7 @@ private:
inline static bool HandleNonEnumEncodingRestrictions(const ged_ins_field_entry_t* dataEntry, NumType& val);
template<typename NumType>
static bool HandleNonEnumEncodingRestriction(GEDFORASSERT(const ged_ins_field_entry_t* dataEntry) COMMA
static bool HandleNonEnumEncodingRestriction(const ged_ins_field_entry_t* dataEntry,
const ged_field_restriction_t* restriction, NumType& val);
private:
@ -319,14 +319,14 @@ bool GEDRestrictionsHandler::HandleNonEnumEncodingRestrictions(const ged_ins_fie
for (unsigned int i = 0; i < 2; ++i)
{
if (NULL == dataEntry->_restrictions[i]) return true;
if (!HandleNonEnumEncodingRestriction(GEDFORASSERT(dataEntry) COMMA dataEntry->_restrictions[i], val)) return false;
if (!HandleNonEnumEncodingRestriction(dataEntry, dataEntry->_restrictions[i], val)) return false;
}
return true;
}
template<typename NumType>
bool GEDRestrictionsHandler::HandleNonEnumEncodingRestriction(GEDFORASSERT(const ged_ins_field_entry_t* dataEntry) COMMA
bool GEDRestrictionsHandler::HandleNonEnumEncodingRestriction(const ged_ins_field_entry_t* dataEntry,
const ged_field_restriction_t* restriction, NumType& val)
{
GEDASSERT(NULL != restriction);
@ -334,16 +334,16 @@ bool GEDRestrictionsHandler::HandleNonEnumEncodingRestriction(GEDFORASSERT(const
switch (restriction->_restrictionType)
{
case GED_FIELD_RESTRICTIONS_TYPE_VALUE:
GEDASSERT(CheckMaxValue(val, dataEntry->_bitSize));
if (!CheckMaxValue(val, dataEntry->_bitSize)) return false; // TODO: This was an assert, should switch back for optimization?
return VerifyValueRestriction(val, restriction->_value);
case GED_FIELD_RESTRICTIONS_TYPE_RANGE:
GEDASSERT(CheckMaxValue(val, dataEntry->_bitSize));
if (!CheckMaxValue(val, dataEntry->_bitSize)) return false; // TODO: This was an assert, should switch back for optimization?
return VerifyRangeRestriction(val, restriction->_range);
case GED_FIELD_RESTRICTIONS_TYPE_MASK:
GEDASSERT(CheckMaxValue(val, dataEntry->_bitSize));
if (!CheckMaxValue(val, dataEntry->_bitSize)) return false; // TODO: This was an assert, should switch back for optimization?
return VerifyMaskRestriction(val, restriction->_mask);
case GED_FIELD_RESTRICTIONS_TYPE_PADDING:
GEDASSERT(CheckMaxValue(val, dataEntry->_bitSize)); // TODO: This should probably be checked always, not as an assertion.
if (!CheckMaxValue(val, dataEntry->_bitSize)) return false;
return ((NumType)(restriction->_padding._value) == ((NumType)(restriction->_padding._mask) & val));
case GED_FIELD_RESTRICTIONS_TYPE_FIELD_TYPE:
GEDASSERT(GED_QWORD_BITS >= restriction->_fieldType._attr._bits);

View File

@ -246,8 +246,8 @@ typedef enum
* Channel Enable. Four channel enables are defined for controlling which channels will be written into the destination region.
* These channel mask bits are applied in a modulo-four manner to all ExecSize channels. There is 1-bit Channel Enable for each
* channel within the group of 4. If the bit is cleared, the write for the corresponding channel is disabled. If the bit is set,
* the write is enabled. Mnemonic for the bit being set for the group of 4 is "x", "y", "z", and "w",
* respectively, where "x" corresponds to Channel 0 in the group and "w" corresponds to channel 3 in the group.
* the write is enabled. Mnemonic for the bit being set for the group of 4 is "x", "y", "z", and "w", respectively, where "x"
* corresponds to Channel 0 in the group and "w" corresponds to channel 3 in the group.
*
* For a send instruction, this field applies to the CurrDst.
*
@ -321,8 +321,8 @@ typedef enum
/*!
* Channel Select. This field controls the channel swizzle for the first source operand (src0). The normally sequential channel
* assignment can be altered by explicitly identifying neighboring data elements for each channel. Out of the 8-bit field, 2 bits
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1
* ("y"), 2 ("z"), and 3 ("w") in the group, respectively.
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1 ("y"), 2
* ("z"), and 3 ("w") in the group, respectively.
*
* @par Models: all
*/
@ -437,8 +437,8 @@ typedef enum
/*!
* Channel Select. This field controls the channel swizzle for the second source operand (src1). The normally sequential channel
* assignment can be altered by explicitly identifying neighboring data elements for each channel. Out of the 8-bit field, 2 bits
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1
* ("y"), 2 ("z"), and 3 ("w") in the group, respectively.
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1 ("y"), 2
* ("z"), and 3 ("w") in the group, respectively.
*
* @par Models: all
*/
@ -586,8 +586,8 @@ typedef enum
/*!
* Channel Select. This field controls the channel swizzle for the third source operand (src2). The normally sequential channel
* assignment can be altered by explicitly identifying neighboring data elements for each channel. Out of the 8-bit field, 2 bits
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1
* ("y"), 2 ("z"), and 3 ("w") in the group, respectively.
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1 ("y"), 2
* ("z"), and 3 ("w") in the group, respectively.
*
* @par Models: all
*/

View File

@ -246,8 +246,8 @@ typedef enum
* Channel Enable. Four channel enables are defined for controlling which channels will be written into the destination region.
* These channel mask bits are applied in a modulo-four manner to all ExecSize channels. There is 1-bit Channel Enable for each
* channel within the group of 4. If the bit is cleared, the write for the corresponding channel is disabled. If the bit is set,
* the write is enabled. Mnemonic for the bit being set for the group of 4 is "x", "y", "z", and "w",
* respectively, where "x" corresponds to Channel 0 in the group and "w" corresponds to channel 3 in the group.
* the write is enabled. Mnemonic for the bit being set for the group of 4 is "x", "y", "z", and "w", respectively, where "x"
* corresponds to Channel 0 in the group and "w" corresponds to channel 3 in the group.
*
* For a send instruction, this field applies to the CurrDst.
*
@ -321,8 +321,8 @@ typedef enum
/*!
* Channel Select. This field controls the channel swizzle for the first source operand (src0). The normally sequential channel
* assignment can be altered by explicitly identifying neighboring data elements for each channel. Out of the 8-bit field, 2 bits
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1
* ("y"), 2 ("z"), and 3 ("w") in the group, respectively.
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1 ("y"), 2
* ("z"), and 3 ("w") in the group, respectively.
*
* @par Models: all
*/
@ -437,8 +437,8 @@ typedef enum
/*!
* Channel Select. This field controls the channel swizzle for the second source operand (src1). The normally sequential channel
* assignment can be altered by explicitly identifying neighboring data elements for each channel. Out of the 8-bit field, 2 bits
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1
* ("y"), 2 ("z"), and 3 ("w") in the group, respectively.
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1 ("y"), 2
* ("z"), and 3 ("w") in the group, respectively.
*
* @par Models: all
*/
@ -586,8 +586,8 @@ typedef enum
/*!
* Channel Select. This field controls the channel swizzle for the third source operand (src2). The normally sequential channel
* assignment can be altered by explicitly identifying neighboring data elements for each channel. Out of the 8-bit field, 2 bits
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1
* ("y"), 2 ("z"), and 3 ("w") in the group, respectively.
* are assigned for each channel within the group of 4. ChanSel[1:0], [3.2], [5.4] and [7,6] are for channel 0 ("x"), 1 ("y"), 2
* ("z"), and 3 ("w") in the group, respectively.
*
* @par Models: all
*/

View File

@ -369,15 +369,18 @@ namespace iga
return
decodeField<RegRef>(
iga::pstg12::FLAGREG,
fFLAGREG,
F0_0,"f0.0",
F0_1,"f0.1",
F1_0,"f1.0",
F1_1,"f1.1");
}
void decodeFlagModifierField(const Field &fFLAGMOD) {
RegRef flagReg = peekFlagRegRef(iga::pstg12::FLAGREG);
void decodeFlagModifierField(
const Field &fFLAGMOD,
const Field &fFLAGREG)
{
RegRef flagReg = peekFlagRegRef(fFLAGREG);
FlagModifier invalidModifier = static_cast<FlagModifier>(-1);
FlagModifier zeroValue = FlagModifier::NONE;
const char *zeroString = "";
@ -505,13 +508,14 @@ namespace iga
reportError("ERROR: expected 64b type");
}
ss << ")";
addDecodedField(iga::pstg12::BAS_SRC0_IMM32L, "LO32" + ss.str());
addDecodedField(iga::pstg12::BAS_SRC0_IMM32H, "HI32" + ss.str());
addDecodedField(fIMM32L, "LO32" + ss.str());
addDecodedField(fIMM32H, "HI32" + ss.str());
return immVal;
}
void decodeExecOffsetInfo(
const Field &fEXECSIZE, const Field &fCHANOFF)
const Field &fEXECSIZE,
const Field &fCHANOFF)
{
ExecSize execSize = decodeExecSizeBits(bits.getField(fEXECSIZE));
if (execSize == ExecSize::INVALID) {
@ -519,7 +523,7 @@ namespace iga
}
std::stringstream ssEs;
ssEs << "(" << ToSyntax(execSize) << "|...)";
addDecodedField(iga::pstg12::EXECSIZE, ssEs.str());
addDecodedField(fEXECSIZE, ssEs.str());
ChannelOffset chOff = decodeChannelOffsetBits(bits.getField(fCHANOFF));
if (chOff < ChannelOffset::M0 || chOff > ChannelOffset::M28) {
@ -532,9 +536,9 @@ namespace iga
builder.InstExecInfo(loc, execSize, loc, chOff);
}
DstModifier decodeDstModifier() {
DstModifier decodeDstModifier(const Field &fSATURATE) {
return
decodeField(iga::pstg12::SATURATE,
decodeField(fSATURATE,
DstModifier::NONE, "",
DstModifier::SAT, "(sat)");
}
@ -557,57 +561,47 @@ namespace iga
const Field &fSUBREG)
{
std::string typeValue;
if (os.isDpasSubfunc() && opIndex > OpIx::TER_SRC0) {
auto srb = bits.getField(fSUBREG); // ternary src's have all 5 bits
opInfo.regOpReg.subRegNum = BytesOffsetToSubReg(
(uint8_t)srb,
opInfo.regOpName,
opInfo.subBytePrecision);
typeValue = ToSyntax(opInfo.subBytePrecision);
} else {
peekRegularSubReg(opIndex, opInfo, fSUBREG, opInfo.type);
typeValue = ToSyntax(opInfo.type);
}
std::stringstream ss;
ss << "." << (int)opInfo.regOpReg.subRegNum << typeValue;
addDecodedField(fSUBREG, ss.str());
decodeSubRegWithType(
opIndex, opInfo, fSUBREG, opInfo.type, ToSyntax(opInfo.type));
}
void decodeRegularSubReg(
// e.g. for subregisters without proper types
void decodeSubRegWithImplicitType(
OpIx opIndex,
OperandInfo &opInfo,
const Field &fSUBREG,
Type type)
Type t)
{
peekRegularSubReg(opIndex, opInfo, fSUBREG, type);
std::stringstream ss;
ss << "." << (int)opInfo.regOpReg.subRegNum << ToSyntax(type);
addDecodedField(fSUBREG, ss.str());
std::string typeValue;
decodeSubRegWithType(opIndex, opInfo, fSUBREG, t, "");
}
void peekRegularSubReg(
void decodeSubRegWithType(
OpIx opIndex,
OperandInfo &opInfo,
const Field &fSUBREG,
Type type)
Type type,
std::string typeSyntax)
{
auto srb = (int)bits.getField(fSUBREG);
if (opIndex == OpIx::TER_DST) {
srb <<= 3; // ternary dst only stores high two bits
}
if (IsRegisterScaled(opInfo.regOpName)) {
auto typeSize = TypeSizeWithDefault(type,4);
if (srb % typeSize != 0) {
std::stringstream ess;
if (IsDst(opIndex)) {
ess << "dst";
} else {
ess << "src" << ToSrcIndex(opIndex);
}
ess << " subregister is not divisible by type size";
reportError(ess.str());
auto scaled = BytesOffsetToSubReg(srb, opInfo.regOpName, type);
auto unscaled = SubRegToBytesOffset((int)scaled, opInfo.regOpName, type);
if (unscaled != srb) {
std::stringstream ess;
if (IsDst(opIndex)) {
ess << "dst";
} else {
ess << "src" << ToSrcIndex(opIndex);
}
srb /= typeSize;
ess << " subregister offset is misaligned for type size";
reportError(ess.str());
}
opInfo.regOpReg.subRegNum = (uint8_t)srb;
opInfo.regOpReg.subRegNum = scaled;
std::stringstream ss;
ss << "." << (int)opInfo.regOpReg.subRegNum << typeSyntax;
addDecodedField(fSUBREG, ss.str());
}
void decodeRegDirectFields(
@ -627,7 +621,9 @@ namespace iga
opInfo.kind = Operand::Kind::DIRECT;
decodeSubReg(opIndex, opInfo, fSUBREG);
if (fSUBREG.length < 5) { // ternary has some reserved bits
addReserved(fSUBREG.offset - 5 + fSUBREG.length, 5 - fSUBREG.length);
addReserved(
fSUBREG.offset - 5 + fSUBREG.length,
5 - fSUBREG.length);
}
}
}
@ -665,15 +661,15 @@ namespace iga
ImplAcc decodeImplAccField(const Field &fSPCACC) {
return decodeField<ImplAcc>(fSPCACC, ImplAcc::INVALID,{
{ImplAcc::ACC2,".acc2"},
{ImplAcc::ACC3,".acc3"},
{ImplAcc::ACC4,".acc4"},
{ImplAcc::ACC5,".acc5"},
{ImplAcc::ACC6,".acc6"},
{ImplAcc::ACC7,".acc7"},
{ImplAcc::ACC8,".acc8"},
{ImplAcc::ACC9,".acc9"},
{ImplAcc::NOACC,".noacc"}});
{ImplAcc::ACC2,".sacc2"},
{ImplAcc::ACC3,".sacc3"},
{ImplAcc::ACC4,".sacc4"},
{ImplAcc::ACC5,".sacc5"},
{ImplAcc::ACC6,".sacc6"},
{ImplAcc::ACC7,".sacc7"},
{ImplAcc::ACC8,".sacc8"},
{ImplAcc::ACC9,".sacc9"},
{ImplAcc::NOACC,".nosacc"}});
}
bool decodeInstOpt(const Field &fINSTOPT, InstOpt opt) {

View File

@ -349,11 +349,20 @@ namespace iga
}
inline void InstEncoder::encode(const Field &f, ImplAcc acc) {
uint64_t val = 0;
switch (acc) {
case ImplAcc::INVALID: break;
default:
encodeFieldBits(f, static_cast<uint64_t>(acc));
ENCODING_CASE(ImplAcc::ACC2, 0x0);
ENCODING_CASE(ImplAcc::ACC3, 0x1);
ENCODING_CASE(ImplAcc::ACC4, 0x2);
ENCODING_CASE(ImplAcc::ACC5, 0x3);
ENCODING_CASE(ImplAcc::ACC6, 0x4);
ENCODING_CASE(ImplAcc::ACC7, 0x5);
ENCODING_CASE(ImplAcc::ACC8, 0x6);
ENCODING_CASE(ImplAcc::ACC9, 0x7);
ENCODING_CASE(ImplAcc::NOACC, 0x8);
default: internalErrorBadIR(f);
}
encodeFieldBits(f, val);
}
inline void InstEncoder::encode(const Field &f, Region::Vert vt) {

View File

@ -26,13 +26,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef _BUFFEREDLEXER_H
#define _BUFFEREDLEXER_H
#include "Lexemes.hpp"
#include "../IR/Loc.hpp"
#include "../asserts.hpp"
#include "../IR/Loc.hpp"
#include "Lexemes.hpp"
#include <string>
#include <sstream>
#include <iostream>
#include <ostream>
#include <sstream>
#include <string>
#include <vector>
// #define DUMP_LEXEMES
@ -182,11 +183,11 @@ public:
}
}
void DumpLookaheads(int n = 1) const {
DEBUG_TRACE("LEXER: Next %d lookaheads are:\n", n);
void DumpLookaheads(std::ostream &os, int n = 1) const {
os << "LEXER: Next " << n << " lookaheads are:\n";
for (int i = 0; i < n; i++) {
const Token &tk = Next(i);
DEBUG_TRACE(GetTokenString(tk, m_input).c_str());
os << " " << GetTokenString(tk, m_input).c_str() << "\n";
if (tk.lexeme == Lexeme::END_OF_FILE) {
break;
}
@ -208,16 +209,18 @@ public:
#endif
return true;
}
bool Consume(Lexeme lx, int i = 0) {
if (LookingAt(lx,i)) {
bool Consume(Lexeme lxm) {
if (LookingAt(lxm)) {
(void)Skip(1);
return true;
}
return false;
}
bool LookingAt(Lexeme lx, int i = 0) const {
bool LookingAt(Lexeme lxm) const {
return LookingAtFrom(0,lxm);
}
bool LookingAtFrom(int i, Lexeme lx) const {
return Next(i).lexeme == lx;
}

View File

@ -34,7 +34,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "../Models/Models.hpp"
#include "../strings.hpp"
#ifndef DISABLE_ENCODER_EXCEPTIONS
#include "../Backend/GED/Decoder.hpp"
#include "../Backend/GED/Interface.hpp"
#include "../Backend/Native/Interface.hpp"
#endif
#include "../Backend/GED/IGAToGEDTranslation.hpp"
#include "../Backend/Native/MInst.hpp"
@ -819,7 +820,7 @@ void Formatter::formatDstOp(const OpSpec &os, const Operand &dst) {
if (!os.hasImplicitDstRegion() ||
(dstRgn != os.implicitDstRegion() && dstRgn != Region::INVALID))
{
// math dpas does not have dst regions
// some instructions don't have dst regions
formatDstRegion(os, dst.getRegion());
}
formatDstType(os, dst.getType());
@ -1014,13 +1015,22 @@ void FormatInstruction(
std::ostream &o,
const FormatOpts &opts,
size_t startPc,
const void *bits)
const void *bits,
bool useNativeDecoder)
{
const iga::Model *model =
iga::Model::LookupModel(static_cast<iga::Platform>(opts.platform));
iga::Decoder dec(*model, e);
iga::Kernel *k = dec.decodeKernelNumeric(bits,
((const MInst *)bits)->isCompact() ? 8 : 16);
size_t instLen = ((const MInst *)bits)->isCompact() ? 8 : 16;
DecoderOpts dopts;
dopts.useNumericLabels = true;
iga::Kernel *k = nullptr;
if (useNativeDecoder && iga::native::IsDecodeSupported(*model, dopts)) {
k = iga::native::Decode(*model, dopts, e, bits, instLen);
} else {
k = iga::ged::Decode(*model, dopts, e, bits, instLen);
}
if (e.hasErrors()) {
for (const auto &err : e.getErrors()) {
o << err.message << "\n";

View File

@ -107,7 +107,8 @@ namespace iga {
std::ostream &o,
const FormatOpts &opts,
size_t startPc,
const void *bits);
const void *bits,
bool useNativeDecoder = false);
void FormatInstruction(
ErrorHandler &e,
std::ostream &o,

View File

@ -138,7 +138,7 @@ void GenParser::ParseExecInfo(
// jmpi (1) ...
// We resolve that by looking ahead two symbols
int execSizeVal = 1;
if (LookingAt(LPAREN) && (LookingAt(2,RPAREN) || LookingAt(2,PIPE))) {
if (LookingAt(LPAREN) && (LookingAtFrom(2,RPAREN) || LookingAtFrom(2,PIPE))) {
Skip();
execSizeLoc = NextLoc();
ConsumeIntLitOrFail(execSizeVal, "expected SIMD width");
@ -210,7 +210,7 @@ Type GenParser::ParseSendOperandTypeWithDefault(int srcIx) {
if (!LookingAt(IDENT)) {
Fail("expected a send operand type");
}
if (!IdentLookup(0, DST_TYPES, t)) {
if (!IdentLookupFrom(0, DST_TYPES, t)) {
Fail("unexpected operand type for send");
}
Skip();
@ -838,7 +838,9 @@ void GenParser::initSymbolMaps()
}
}
class KernelParser : GenParser {
class KernelParser : GenParser
{
// maps mnemonics and registers for faster lookup
std::map<std::string,const OpSpec*> opmap;
@ -1430,8 +1432,14 @@ private:
}
// Mnemoninc = Ident SubMnemonic? | Ident BrCtl
// SubMnemoninc = '.' [Ident]SubFunc
//
// Mnemoninc
// = Ident SubMnemonic?
// | Ident BrCtl
// SubMnemoninc
// = '.' Ident
// | '.' HEX_INT | '.' DEC_INT
//
// BrCtl = '.b'
//
const OpSpec *ParseMnemonic() {
@ -1441,25 +1449,8 @@ private:
return nullptr;
}
if (pOs->format == OpSpec::GROUP) {
// e.g. math.*, sync.*, send.*, etc...
ConsumeOrFail(DOT, "expected operation subfunction");
if (LookingAt(IDENT)) {
auto sfLoc = NextLoc();
auto sfIdent = GetTokenAsString(Next());
// look up the function by the fully qualified name
std::stringstream ss;
ss << pOs->mnemonic << "." << sfIdent;
auto itr = opmap.find(ss.str());
if (itr == opmap.end()) {
failWithUnexpectedSubfunction(sfLoc, sfIdent);
} else {
// resolve to idiv etc...
Skip();
pOs = itr->second;
}
} else {
Fail("expected subfunction");
}
// e.g. math.*, send.*, etc...
pOs = ParseSubOp(pOs);
}
if (!m_hasWrEn && pOs->op == Op::JMPI) {
Warning(mnemonicLoc,
@ -1483,8 +1474,8 @@ private:
Fail("saturation flag goes on destination operand: "
"e.g. op (..) (sat)dst ...");
} else if (
IdentLookup(1, FLAGMODS, fm) ||
IdentLookup(1, FLAGMODS_LEGACY, fm))
IdentLookupFrom(1, FLAGMODS, fm) ||
IdentLookupFrom(1, FLAGMODS_LEGACY, fm))
{
Fail("conditional modifier follows execution mask "
"info: e.g. op (16|M0) (le)f0.0 ...");
@ -1497,6 +1488,52 @@ private:
return pOs;
}
// SubMnemoninc
// = '.' Ident
// | '.' HEX_INT | '.' DEC_INT
//
// E.g.
// math.inv
// math.1
// math.0x1
const OpSpec* ParseSubOp(const OpSpec *pParent)
{
const OpSpec *pOp = nullptr;
ConsumeOrFail(DOT, "expected operation subfunction");
auto sfLoc = NextLoc();
if (LookingAt(IDENT)) {
auto sfIdent = GetTokenAsString(Next());
// look up the function by the fully qualified name
std::stringstream ss;
ss << pParent->mnemonic << "." << sfIdent;
auto itr = opmap.find(ss.str());
if (itr == opmap.end()) {
failWithUnexpectedSubfunction(sfLoc, sfIdent);
} else {
// resolve to idiv etc...
Skip();
pOp = itr->second;
if (pOp->format == OpSpec::GROUP) {
return ParseSubOp(pOp);
}
}
} else if (LookingAtAnyOf(INTLIT10,INTLIT16)) {
// e.g. math.0x1
unsigned sfVal;
ParseIntFrom<unsigned>(NextLoc(), sfVal);
Skip(1);
pOp = &m_model.lookupGroupSubOp(pParent->op, sfVal);
if (!pOp->isValid()) {
Fail(sfLoc, "subfunction is out of bounds");
}
} else {
Fail(sfLoc, "invalid subfunction");
}
return pOp;
}
// FlagModifierOpt = '(' FlagModif ')' FlagReg
void ParseFlagModOpt() {
@ -1532,9 +1569,9 @@ private:
if (!LookingAt(LPAREN)) {
return false;
}
if (!IdentLookup(1, FLAGMODS, flagMod)) {
if (!IdentLookupFrom(1, FLAGMODS, flagMod)) {
Loc loc = NextLoc(1);
if (!IdentLookup(1, FLAGMODS_LEGACY, flagMod)) {
if (!IdentLookupFrom(1, FLAGMODS_LEGACY, flagMod)) {
return false;
} else if (m_parseOpts.deprecatedSyntaxWarnings) {
// deprecated syntax
@ -1649,8 +1686,7 @@ private:
"expected implicit accumulator operand "
"(e.g. .noacc, .acc2, ..., .acc9)";
ConsumeOrFail(DOT, expected);
ConsumeIdentOneOfOrFail<ImplAcc>(
IMPLACCS, implAcc, expected, expected);
ConsumeIdentOneOfOrFail<ImplAcc>(IMPLACCS, implAcc, expected, expected);
return implAcc;
}
@ -2559,7 +2595,7 @@ private:
SrcModifier ParseSrcModifierOpt(bool &pipeAbs) {
if (!m_opSpec->supportsSourceModifiers()) {
if (LookingAt(SUB) &&
LookingAtAnyOf(1, {INTLIT02, INTLIT10, INTLIT16}))
LookingAtAnyOfFrom(1, {INTLIT02, INTLIT10, INTLIT16}))
{
// e.g. jmpi (...) -16:d
// ^ we will convert the literal
@ -2702,7 +2738,7 @@ private:
return Type::INVALID;
}
Type type = Type::INVALID;
if (IdentLookup(1, types, type)) {
if (IdentLookupFrom(1, types, type)) {
Skip(2);
}
return type;

View File

@ -23,12 +23,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
======================= end_copyright_notice ==================================*/
#ifndef _LEXEMES_HPP_
#define _LEXEMES_HPP_
#ifndef _IGA_LEXEMES_HPP_
#define _IGA_LEXEMES_HPP_
namespace iga {
enum Lexeme {
enum Lexeme
{
LEXICAL_ERROR = 0, // Windows GDI #define's "ERROR"
NEWLINE,

View File

@ -42,10 +42,10 @@ namespace iga
//////////////////////////////////////////////////////////////////////
// DEBUGGING
//
void Parser::ShowCurrentLexicalContext(const Loc &loc) const {
std::stringstream ss;
WriteTokenContext(m_lexer.GetSource(), loc, ss);
DEBUG_TRACE(ss.str().c_str());
void Parser::ShowCurrentLexicalContext(
std::ostream &os, const Loc &loc) const
{
WriteTokenContext(m_lexer.GetSource(), loc, os);
}
//////////////////////////////////////////////////////////////////////
@ -122,14 +122,14 @@ namespace iga
//////////////////////////////////////////////////////////////////////
// QUERYING (non-destructive lookahead)
bool Parser::LookingAt(int k, Lexeme lxm) const {
return m_lexer.LookingAt(lxm,k);
bool Parser::LookingAtFrom(int k, Lexeme lxm) const {
return m_lexer.LookingAtFrom(k, lxm);
}
bool Parser::LookingAtSeq(std::initializer_list<Lexeme> lxms) const {
int i = 0;
for (Lexeme lxm : lxms) {
if (!LookingAt(i++, lxm)) {
if (!LookingAtFrom(i++, lxm)) {
return false;
}
}
@ -137,15 +137,15 @@ namespace iga
}
bool Parser::LookingAtAnyOf(std::initializer_list<Lexeme> lxms) const {
return LookingAtAnyOf(0, lxms);
return LookingAtAnyOfFrom(0, lxms);
}
bool Parser::LookingAtAnyOf(int i, std::initializer_list<Lexeme> lxms)
bool Parser::LookingAtAnyOfFrom(int i, std::initializer_list<Lexeme> lxms)
const
{
int off = 0;
for (Lexeme lxm : lxms) {
if (LookingAt(off + i, lxm)) {
if (LookingAtFrom(off + i, lxm)) {
return true;
}
}

View File

@ -28,13 +28,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "BufferedLexer.hpp"
#include "../ErrorHandler.hpp"
// FIXME: needed for for ident_value<T> (want to make this agnostic IGA GEN IR types)
#include "../Models/Models.hpp"
#include "../IR/Loc.hpp"
#include <cstdarg>
#include <initializer_list>
#include <ostream>
#include <sstream>
#include <stdexcept>
#include <string>
@ -63,10 +63,12 @@ namespace iga
///////////////////////////////////////////////////////////////////////////
// Recursive descent parser.
// The nomaclaure for method names is roughly:
// Looking**** peeks at the token, doesn't consume
// Consume**** consume next token if some criteria is true
// Parse****** generally corresponds to a non-terminal or some
// complicated lexemes
// Looking**** peeks at the token, doesn't consume
// Looking**From peeks relative to the lexer's current offset
// Consume**** consume next token if some criteria is true
// Parse****** generally corresponds to a non-terminal or some
// complicated lexemes
//
//
class Parser {
protected:
@ -81,9 +83,11 @@ namespace iga
//////////////////////////////////////////////////////////////////////
// DEBUGGING
void DumpLookaheads(int n = 1) const {m_lexer.DumpLookaheads(n); }
void ShowCurrentLexicalContext() {ShowCurrentLexicalContext(NextLoc());}
void ShowCurrentLexicalContext(const Loc &loc) const;
// void DumpLookaheads(int n = 1) const {m_lexer.DumpLookaheads(n); }
void ShowCurrentLexicalContext(std::ostream &os) const {
ShowCurrentLexicalContext(os,NextLoc());
}
void ShowCurrentLexicalContext(std::ostream &os,const Loc &loc) const;
//////////////////////////////////////////////////////////////////////
// ERRORS and WARNINGS
@ -136,27 +140,25 @@ namespace iga
bool Skip(int k = 1) {return m_lexer.Skip(k);}
// be sure nothing else fits before you use this
std::string GetTokenAsString(const Token &token) const;
//////////////////////////////////////////////////////////////////////
// QUERYING (non-destructive lookahead)
bool LookingAt(Lexeme lxm) const {return LookingAt(0,lxm);}
bool LookingAt(int k, Lexeme lxm) const;
bool LookingAt(Lexeme lxm) const {return LookingAtFrom(0,lxm);}
bool LookingAtFrom(int k, Lexeme lxm) const;
bool LookingAtSeq(Lexeme lxm0, Lexeme lxm1) const {return LookingAtSeq({lxm0,lxm1});}
bool LookingAtSeq(std::initializer_list<Lexeme> lxms) const;
bool LookingAtAnyOf(Lexeme lxm0, Lexeme lxm1) const {return LookingAtAnyOf({lxm0,lxm1}); }
bool LookingAtAnyOf(std::initializer_list<Lexeme> lxms) const;
bool LookingAtAnyOf(int i, std::initializer_list<Lexeme> lxms) const;
bool LookingAtAnyOfFrom(int i, std::initializer_list<Lexeme> lxms) const;
bool LookingAtPrefix(const char *pfx) const;
//////////////////////////////////////////////////////////////////////
// CONSUMPTION (destructive lookahead)
bool Consume(Lexeme lxm) {return Consume(0, lxm);}
bool Consume(int k, Lexeme lxm) {return m_lexer.Consume(lxm,k);}
bool Consume(Lexeme lxm) {return m_lexer.Consume(lxm);}
void ConsumeOrFail(Lexeme lxm, const char *msg);
// same as above, but the error location chosen is the end of the
// previous token; i.e. the suffix is screwed up
@ -182,8 +184,8 @@ namespace iga
bool TokenEq(const Token &tk, const char *eq) const;
template <typename T>
bool IdentLookup(int k, const IdentMap<T> &map, T &value) const {
if (!LookingAt(k,IDENT)) {
bool IdentLookupFrom(int k, const IdentMap<T> &map, T &value) const {
if (!LookingAtFrom(k,IDENT)) {
return false;
}
for (const std::pair<const char *,T> &p : map) {
@ -205,7 +207,7 @@ namespace iga
if (!LookingAt(IDENT)) {
Fail(errExpecting);
}
if (!IdentLookup(0, map, value)) {
if (!IdentLookupFrom(0, map, value)) {
Fail(errInvalid);
}
Skip();
@ -213,7 +215,7 @@ namespace iga
template <typename T>
bool ConsumeIdentOneOf(const IdentMap<T> &map, T &value) {
if (LookingAt(IDENT) && IdentLookup(0, map, value)) {
if (LookingAt(IDENT) && IdentLookupFrom(0, map, value)) {
Skip();
return true;
}

View File

@ -24,11 +24,11 @@ set(IGA_IR_Open
${CMAKE_CURRENT_SOURCE_DIR}/Types.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Types.hpp
)
set(IGA_IR_Embargoed )
set(IGA_IR_Extended )
set(IGA_IR
${IGA_IR_Open}
${IGA_IR_Embargoed}
${IGA_IR_Extended}
PARENT_SCOPE
)

View File

@ -32,6 +32,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <cstdint>
#include <tuple>
#include "../EnumBitset.hpp"
#include "../Models/bxml/iga_bxml_enums.hpp"
@ -137,6 +138,79 @@ enum class ImplAcc
};
// how much to shift <right,left> to get to from byte offset
// to subregister offset
// I.e. subReg = (byteOff << left) >> right;
// this allows us to scale a subregister byte offset up OR down
static inline std::tuple<int,int> TypeSizeShiftsOffsetToSubreg(Type type)
{
int shl = 0, shr = 0; // by default no scaling
switch (type) {
// 1-byte types
case Type::UB:
case Type::B:
break;
// 2-byte types
case Type::UW:
case Type::W:
case Type::HF:
shr = 1;
break;
// 4-byte types
case Type::UD:
case Type::D:
case Type::F:
case Type::NF: // NF regions the same as F
shr = 2;
break;
case Type::UQ:
case Type::Q:
case Type::DF:
shr = 3;
break;
default: // invalid types
break;
}
return std::make_tuple(shl,shr);
}
// static inline bool TypeIsSubByte(Type t) {
// return std::get<1>(TypeSizeShiftsOffsetToSubreg(t)) > 0;
// }
// Returns the type size ***in bits****
//
// e.g. Type::UD == 32
static inline int TypeSizeInBits(Type t)
{
auto ti = TypeSizeShiftsOffsetToSubreg(t);
return (8 << std::get<1>(ti)) >> std::get<0>(ti);
}
static inline int TypeSizeInBitsWithDefault(Type type, int dft = 0)
{
return type == Type::INVALID ? dft : TypeSizeInBits(type);
}
static inline bool TypeIs64b(Type t)
{
return TypeSizeInBitsWithDefault(t,0) == 64;
}
static bool TypeIsFloating(Type t)
{
switch (t)
{
case Type::F:
case Type::HF:
case Type::DF:
case Type::VF:
case Type::NF:
return true;
default:
return false;
}
}
///////////////////////////////////////////////////////////////////
// DEPRECATED
static inline int LogTypeSize(Type type, int dft = -1)
{
switch (type)
@ -167,15 +241,21 @@ static inline int LogTypeSize(Type type, int dft = -1)
return dft;
}
}
///////////////////////////////////////////////////////////////////
// DEPRECATED
static inline int TypeSize(Type type)
{
return 1 << LogTypeSize(type);
}
///////////////////////////////////////////////////////////////////
// DEPRECATED
static inline int TypeSizeWithDefault(Type type, int dft = 0)
{
return type == Type::INVALID ? dft : TypeSize(type);
}
enum class FlagModifier
{
NONE = 0, // no flag modification

View File

@ -45,7 +45,7 @@ using namespace iga;
static std::string disassembleInst(
Platform platform,
bool useNativeDencoder,
bool useNativeDecoder,
size_t fromPc,
const void *bits)
{
@ -55,7 +55,8 @@ static std::string disassembleInst(
fopts.numericLabels = true;
// fopts.hexFloats = opts.printHexFloats;
fopts.hexFloats = false;
FormatInstruction(eh, ss, fopts, fromPc, bits);
FormatInstruction(eh, ss, fopts, fromPc, bits, useNativeDecoder);
return ss.str();
}
@ -206,13 +207,13 @@ static void decodeFieldHeaders(std::ostream &os)
}
static bool decodeFieldsForInst(
bool useNativeDencoder,
bool useNativeDecoder,
std::ostream &os,
size_t pc,
const Model &model,
const MInst *mi)
{
auto syntax = disassembleInst(model.platform, useNativeDencoder, pc, (const void *)mi);
auto syntax = disassembleInst(model.platform, useNativeDecoder, pc, (const void *)mi);
os << fmtPc(mi, pc) << " " << syntax << "\n";
os.flush();
bool success = true;
@ -274,7 +275,7 @@ static bool decodeFieldsForInst(
iga_status_t iga::DecodeFields(
Platform p,
bool useNativeDencoder, // TODO: use this once decoder is implemented
bool useNativeDecoder, // TODO: use this once decoder is implemented
std::ostream &os,
const uint8_t *bits,
size_t bitsLen)
@ -302,7 +303,7 @@ iga_status_t iga::DecodeFields(
break;
}
success &= decodeFieldsForInst(useNativeDencoder, os, pc, *model, mi);
success &= decodeFieldsForInst(useNativeDecoder, os, pc, *model, mi);
pc += iLen;
}
@ -717,7 +718,7 @@ static bool listInstructionCompaction(
iga_status_t iga::DebugCompaction(
Platform p,
bool useNativeDencoder,
bool useNativeDecoder,
std::ostream &os,
const uint8_t *bits,
size_t bitsLen)
@ -746,11 +747,11 @@ iga_status_t iga::DebugCompaction(
}
os << "============================================================\n";
auto syntax = disassembleInst(p, useNativeDencoder, pc, (const void *)mi);
auto syntax = disassembleInst(p, useNativeDecoder, pc, (const void *)mi);
os << fmtPc(mi, pc) << " " << syntax << "\n";
os.flush();
success &= listInstructionCompaction(
useNativeDencoder, os, cs, *model, pc, mi);
useNativeDecoder, os, cs, *model, pc, mi);
pc += iLen;
}
os << "\n";
@ -846,7 +847,7 @@ iga_status_t iga::DebugCompaction(
PC pc = missExample.first;
int totalMissesForThisPc = missExample.second;
os << " misses " << totalMissesForThisPc << ": "
<< disassembleInst(p, useNativeDencoder, pc, bits+pc)
<< disassembleInst(p, useNativeDecoder, pc, bits+pc)
<< "\n";
}
}

View File

@ -9,10 +9,10 @@ set(IGA_ModelsOpen
${CMAKE_CURRENT_SOURCE_DIR}/bxml/Model10.hpp
${CMAKE_CURRENT_SOURCE_DIR}/bxml/iga_bxml_enums.hpp
)
set(IGA_ModelsEmbargoed )
set(IGA_ModelsExteneded )
set(IGA_Models
${IGA_ModelsOpen}
${IGA_ModelsEmbargoed}
${IGA_ModelsExteneded}
PARENT_SCOPE
)

View File

@ -16,7 +16,7 @@ set(IGA_API_HeadersOpen
set(IGA_API_Headers
${IGA_API_HeadersOpen}
${IGA_API_HeadersEmbargoed}
${IGA_API_HeadersExtended}
PARENT_SCOPE
)

View File

@ -318,14 +318,14 @@ int32_t kv_get_opgroup(const kv_t *kv, int32_t pc)
case Op::ENDIF: return (int32_t)kv_opgroup_t::KV_OPGROUP_ENDIF;
case Op::ELSE: return (int32_t)kv_opgroup_t::KV_OPGROUP_ELSE;
case Op::WHILE: return (int32_t)kv_opgroup_t::KV_OPGROUP_WHILE;
case Op::SEND:
case Op::SENDS:
case Op::SENDC:
case Op::SENDSC:
if (inst->hasInstOpt(InstOpt::EOT)) {
default:
if (inst->getOpSpec().isSendOrSendsFamily() &&
inst->hasInstOpt(InstOpt::EOT))
{
return (int32_t)kv_opgroup_t::KV_OPGROUP_SEND_EOT;
} else {
return (int32_t)kv_opgroup_t::KV_OPGROUP_OTHER;
}
default: return (int32_t)kv_opgroup_t::KV_OPGROUP_OTHER;
}
}

View File

@ -26,7 +26,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef _IGA_VERSION_HPP_
#define _IGA_VERSION_HPP_
#define IGA_VERSION_STRING "2.1p0"
#define IGA_VERSION_STRING "2.1p1"
#endif // _IGA_VERSION_HPP_