Changeset 4835 in CLRX


Ignore:
Timestamp:
Jul 24, 2019, 4:36:55 PM (4 weeks ago)
Author:
matszpk
Message:

CLRadeonExtender: GCNAsm: Add literals for VOP3 (for GFX10). Add testcases for long (more than 2 dwords) instructions.

Location:
CLRadeonExtender/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • CLRadeonExtender/trunk/CLRX/amdasm/GCNDefs.h

    r4661 r4835  
    4747    GCNTGT_SMEMOFFSETVEGA,
    4848    GCNTGT_INSTOFFSET,
    49     GCNTGT_INSTOFFSET_S
     49    GCNTGT_INSTOFFSET_S,
     50    GCNTGT_VOP3LITIMM
    5051};
    5152
  • CLRadeonExtender/trunk/amdasm/GCNAsmEncode1.cpp

    r4831 r4835  
    19461946    const GCNInsnMode mode1 = (gcnInsn.mode & GCN_MASK1);
    19471947    const GCNInsnMode mode2 = (gcnInsn.mode & GCN_MASK2);
     1948    const GCNInsnMode fltmode = (gcnInsn.mode & GCN_LITMASK);
    19481949    const bool isGCN12 = (arch & ARCH_GCN_1_2_4_5)!=0;
    19491950    const bool isGCN14 = (arch & ARCH_GCN_1_4_5)!=0;
     1951    const bool isGCN15 = (arch & ARCH_GCN_1_5)!=0;
    19501952    const bool vop3p = (gcnInsn.mode & GCN_VOP3_VOP3P) != 0;
    19511953    if (gcnVOPEnc!=GCNVOPEnc::NORMAL)
     
    19561958    RegRange sdstReg(0, 0);
    19571959    GCNOperand src0Op{};
     1960    std::unique_ptr<AsmExpression> src0OpExpr;
    19581961    GCNOperand src1Op{};
     1962    std::unique_ptr<AsmExpression> src1OpExpr;
    19591963    GCNOperand src2Op{};
     1964    std::unique_ptr<AsmExpression> src2OpExpr;
    19601965   
    19611966    const bool vccImplRead = (gcnInsn.mode & GCN_VCC_IMPL_READ)!=0;
     
    19721977    VOPOpModifiers opMods{ 0, 0, 0, cxbyte(vop3p ? 7<<4 : 0) };
    19731978    cxuint operands = 1;
     1979    const Flags onlyInlineConsts = (!isGCN15) ?
     1980                INSTROP_ONLYINLINECONSTS|INSTROP_NOLITERALERROR : 0;
     1981   
    19741982    if (mode1 != GCN_VOP_ARG_NONE)
    19751983    {
     
    20132021        }
    20142022       
    2015         const Flags literalConstsFlags = (mode2==GCN_FLOATLIT) ? INSTROP_FLOAT :
    2016                 (mode2==GCN_F16LIT) ? INSTROP_F16 : INSTROP_INT;
     2023        const Flags literalConstsFlags = (fltmode==GCN_FLOATLIT) ? INSTROP_FLOAT :
     2024                (fltmode==GCN_F16LIT) ? INSTROP_F16 : INSTROP_INT;
    20172025       
    20182026        cxuint regsNum;
     
    20222030            gcnAsm->setCurrentRVU(2);
    20232031            regsNum = (gcnInsn.mode&GCN_REG_SRC0_64)?2:1;
    2024             good &= parseOperand(asmr, linePtr, src0Op, nullptr, arch, regsNum,
     2032            std::unique_ptr<AsmExpression>* src0OpExprPtr =
     2033                                    isGCN15 ? &src0OpExpr : nullptr;
     2034            good &= parseOperand(asmr, linePtr, src0Op, src0OpExprPtr, arch, regsNum,
    20252035                    correctOpType(regsNum, literalConstsFlags)|INSTROP_VREGS|
    20262036                    INSTROP_SGPR_UNALIGNED|INSTROP_SSOURCE|INSTROP_SREGS|INSTROP_LDS|
    2027                     vop3Mods|INSTROP_ONLYINLINECONSTS|INSTROP_NOLITERALERROR|INSTROP_READ,
    2028                     GCNFIELD_VOP3_SRC0);
     2037                    vop3Mods|onlyInlineConsts|INSTROP_READ, GCNFIELD_VOP3_SRC0);
    20292038            operands++;
    20302039        }
     
    21252134            // parse SRC1 (can be VGPR, SGPR, source scalar, constant)
    21262135            gcnAsm->setCurrentRVU(3);
    2127             good &= parseOperand(asmr, linePtr, src1Op, nullptr, arch, regsNum,
     2136            std::unique_ptr<AsmExpression>* src1OpExprPtr =
     2137                                    isGCN15 ? &src1OpExpr : nullptr;
     2138            good &= parseOperand(asmr, linePtr, src1Op, src1OpExprPtr, arch, regsNum,
    21282139                    correctOpType(regsNum, literalConstsFlags)|INSTROP_VREGS|
    21292140                    INSTROP_SGPR_UNALIGNED|INSTROP_SSOURCE|INSTROP_SREGS|vop3Mods|
    2130                     INSTROP_ONLYINLINECONSTS|INSTROP_NOLITERALERROR|INSTROP_READ,
    2131                     GCNFIELD_VOP3_SRC1);
     2141                    onlyInlineConsts|INSTROP_READ, GCNFIELD_VOP3_SRC1);
    21322142            operands++;
    21332143           
     
    21392149                // parse SRC2 (can be VGPR, SGPR, source scalar, constant)
    21402150                gcnAsm->setCurrentRVU(4);
    2141                 good &= parseOperand(asmr, linePtr, src2Op, nullptr, arch,
     2151                std::unique_ptr<AsmExpression>* src2OpExprPtr =
     2152                                    isGCN15 ? &src2OpExpr : nullptr;
     2153                good &= parseOperand(asmr, linePtr, src2Op, src2OpExprPtr, arch,
    21422154                        is128Ops ? 4 : regsNum,
    21432155                        correctOpType(regsNum, literalConstsFlags)|INSTROP_SGPR_UNALIGNED|
    21442156                        INSTROP_VREGS|INSTROP_SSOURCE|INSTROP_SREGS|INSTROP_READ|
    2145                         vop3Mods|INSTROP_ONLYINLINECONSTS|INSTROP_NOLITERALERROR,
    2146                         GCNFIELD_VOP3_SRC2);
     2157                        vop3Mods|onlyInlineConsts, GCNFIELD_VOP3_SRC2);
    21472158                operands++;
    21482159            }
     
    22122223        }
    22132224    }
     2225   
     2226    if (src0OpExpr!=nullptr)
     2227        src0OpExpr->setTarget(AsmExprTarget(GCNTGT_VOP3LITIMM, asmr.currentSection,
     2228                      output.size()));
     2229    if (src1OpExpr!=nullptr)
     2230        src1OpExpr->setTarget(AsmExprTarget(GCNTGT_VOP3LITIMM, asmr.currentSection,
     2231                      output.size()));
     2232    if (src2OpExpr!=nullptr)
     2233        src2OpExpr->setTarget(AsmExprTarget(GCNTGT_VOP3LITIMM, asmr.currentSection,
     2234                      output.size()));
    22142235   
    22152236    // put data (instruction words)
     
    22642285    }
    22652286    if (wordsNum==2)
     2287    {
    22662288        // second instruction's word
    22672289        SLEV(words[1], src0Op.range.bstart() | (uint32_t(src1Op.range.bstart())<<9) |
     
    22732295                ((src1Op.vopMods & VOPOP_NEG) ? (1U<<30) : 0) |
    22742296                ((src2Op.vopMods & VOPOP_NEG) ? (1U<<31) : 0));
     2297        if (src0Op.range.isVal(255)) // we check for immediate/literal value
     2298            SLEV(words[wordsNum++], src0Op.value);
     2299        else if (src1Op.range.isVal(255))
     2300            // literal from SRC1
     2301            SLEV(words[wordsNum++], src1Op.value);
     2302        else if (src2Op.range.isVal(255))
     2303            // literal from SRC2
     2304            SLEV(words[wordsNum++], src2Op.value);
     2305    }
    22752306   
    22762307    if (!checkGCNEncodingSize(asmr, instrPlace, gcnEncSize, wordsNum))
     
    22782309    output.insert(output.end(), reinterpret_cast<cxbyte*>(words),
    22792310            reinterpret_cast<cxbyte*>(words + wordsNum));
     2311    /// prevent freeing expression
     2312    src0OpExpr.release();
     2313    src1OpExpr.release();
     2314    src2OpExpr.release();
    22802315   
    22812316    // update register pool (VGPR and SGPR counting)
  • CLRadeonExtender/trunk/amdasm/GCNAssembler.cpp

    r4832 r4835  
    454454                    ((value&0x1f00)>>8);
    455455            printWarningForRange(13, value, sourcePos, WS_BOTH);
     456            return true;
     457        case GCNTGT_VOP3LITIMM:
     458            // VOP3 literal in instruction
     459            if (sectionId != ASMSECT_ABS)
     460                GCN_FAIL_BY_ERROR(sourcePos,
     461                        "Relative value is illegal in literal expressions")
     462            SULEV(*reinterpret_cast<uint32_t*>(sectionData+offset+8), value);
     463            printWarningForRange(32, value, sourcePos);
    456464            return true;
    457465        default:
  • CLRadeonExtender/trunk/tests/amdasm/GCNAsmOpc.h

    r4788 r4835  
    3232};
    3333
     34struct GCNAsmOpcodeCase2
     35{
     36    const char* input;
     37    uint32_t expWords[6];
     38    cxuint expWordsNum;
     39    bool good;
     40    const char* errorMessages;
     41};
     42
     43
    3444extern const GCNAsmOpcodeCase encGCNOpcodeCases[];
    3545extern const GCNAsmOpcodeCase encGCN11OpcodeCases[];
     
    3848extern const GCNAsmOpcodeCase encGCN141OpcodeCases[];
    3949extern const GCNAsmOpcodeCase encGCN15OpcodeCases[];
     50extern const GCNAsmOpcodeCase2 encGCN15OpcodeCases2[];
    4051
    4152#endif
  • CLRadeonExtender/trunk/tests/amdasm/GCNAsmOpc15.cpp

    r4831 r4835  
    22442244        0xd5400037U, 0x004ac64fU, true, true, "" },
    22452245    /* VOP3 errors */
    2246     { "v_mad_legacy_f32 v55, 66, v166, v229", 0, 0, false, false,
    2247         "test.s:1:23: Error: Literal in VOP3 is illegal\n" },
    2248     { "v_mad_legacy_f32 v55, s79, 743, v229", 0, 0, false, false,
    2249         "test.s:1:28: Error: Literal in VOP3 is illegal\n" },
    2250     { "v_mad_legacy_f32 v55, s79, v44, 6434", 0, 0, false, false,
    2251         "test.s:1:33: Error: Literal in VOP3 is illegal\n" },
    22522246    { "    v_mad_legacy_f32 v55, s79, s166, v229", 0, 0, false, false,
    22532247        "test.s:1:32: Error: Scalar register number out of range\n" },
     
    23392333    { nullptr, 0, 0, false, false, 0 }
    23402334};
     2335
     2336const GCNAsmOpcodeCase2 encGCN15OpcodeCases2[] =
     2337{
     2338    /* VOP3 with literal */
     2339    { "v_mad_legacy_f32 v55, 66, v166, v229",
     2340        { 0xd5400037U, 0x7974cffU, 66 }, 3, true, "" },
     2341    { "zx=5; zy=61; v_mad_legacy_f32 v55, zx*zy, v166, v229",
     2342        { 0xd5400037U, 0x7974cffU, 305 }, 3, true, "" },
     2343    { "v_mad_legacy_f32 v55, zx*zy, v166, v229; zx=5; zy=61",
     2344        { 0xd5400037U, 0x7974cffU, 305 }, 3, true, "" },
     2345    { "v_mad_legacy_f32 v55, v166, 385, v229",
     2346        { 0xd5400037U, 0x795ffa6U, 385 }, 3, true, "" },
     2347    { "aa=14; ac=7; v_mad_legacy_f32 v55, v166, aa*ac, v229",
     2348        { 0xd5400037U, 0x795ffa6U, 98 }, 3, true, "" },
     2349    { "v_mad_legacy_f32 v55, v166, aa*ac, v229; aa=14; ac=9",
     2350        { 0xd5400037U, 0x795ffa6U, 126 }, 3, true, "" },
     2351    { "v_mad_legacy_f32 v55, v166, v229, 267",
     2352        { 0xd5400037U, 0x3ffcba6U, 267 }, 3, true, "" },
     2353    { "v_min3_f32 v55, 6.9551627e+13, v166, v229\n",
     2354        { 0xd5510037U, 0x07974cffU, 0x567d0700U }, 3, true, "" },
     2355    { "v_min3_f32 v55, v107, 6.9551627e+13, v229\n",
     2356        { 0xd5510037U, 0x0795ff6bU, 0x567d0700U }, 3, true, "" },
     2357    { "v_min3_f32 v55, v122, v166, 6.9551627e+13\n",
     2358        { 0xd5510037U, 0x03ff4d7aU, 0x567d0700U }, 3, true, "" },
     2359    { "v_med3_f16 v55, 1.3242, v166, v229\n",
     2360        { 0xd7570037U, 0x07974cffU, 0x3d4c }, 3, true, "" },
     2361    { "v_med3_f16 v55, v180, 1.3242h, v229\n",
     2362        { 0xd7570037U, 0x0795ffb4U, 0x3d4c }, 3, true, "" },
     2363    { "v_med3_f16 v55, s71, v166, 1.3242\n",
     2364        { 0xd7570037U, 0x03ff4c47U, 0x3d4c }, 3, true, "" },
     2365    { nullptr, { }, 0, false, 0 }
     2366};
  • CLRadeonExtender/trunk/tests/amdasm/GCNAsmOpcodes.cpp

    r4791 r4835  
    9494}
    9595
     96static void testEncGCNOpcodes2(cxuint i, const GCNAsmOpcodeCase2& testCase,
     97                      GPUDeviceType deviceType)
     98{
     99    std::istringstream input(testCase.input);
     100    std::ostringstream errorStream;
     101   
     102    // create assembler with input stream (content is string
     103    Assembler assembler("test.s", input, ASM_ALL&~ASM_ALTMACRO,
     104                    BinaryFormat::GALLIUM, deviceType, errorStream);
     105    // try to assemble code
     106    bool good = assembler.assemble();
     107    std::ostringstream oss;
     108    oss << getGPUDeviceTypeName(deviceType) << " encGCNCase#" << i;
     109    const std::string testCaseName = oss.str();
     110    // check is good match in testcase
     111    assertValue<bool>("testEncGCNOpcodes", testCaseName+".good", testCase.good, good);
     112    if (assembler.getSections().size()<1)
     113    {
     114        std::ostringstream oss;
     115        oss << "FAILED for " << getGPUDeviceTypeName(deviceType) <<
     116            " encGCNCase#" << i;
     117        throw Exception(oss.str());
     118    }
     119    const AsmSection& section = assembler.getSections()[0];
     120    const size_t codeSize = section.content.size();
     121    const size_t expectedSize = (testCase.good) ? (testCase.expWordsNum<<2) : 0;
     122    // check size of output content
     123    if (good && codeSize != expectedSize)
     124    {
     125        std::ostringstream oss;
     126        oss << "FAILED for " << getGPUDeviceTypeName(deviceType) <<
     127            " encGCNCase#" << i << ". Wrong code size: " << expectedSize << "!=" <<
     128            codeSize;
     129        throw Exception(oss.str());
     130    }
     131    // check content
     132    if (expectedSize!=0)
     133    {
     134        bool good = true;
     135        for (cxuint i = 0; i < testCase.expWordsNum; i++)
     136        {
     137            uint32_t resultWord = ULEV(*reinterpret_cast<const uint32_t*>(
     138                    section.content.data()+i*4));
     139            if (testCase.expWords[i] != resultWord)
     140            {
     141                good = false;
     142                break;
     143            }
     144        }
     145       
     146        if (!good)
     147        {
     148            // if content doesn't match
     149            std::ostringstream oss;
     150            oss << "FAILED for " << getGPUDeviceTypeName(deviceType) <<
     151                " encGCNCase#" << i << ". Content doesn't match";
     152            for (cxuint i = 0; i < testCase.expWordsNum; i++)
     153            {
     154                uint32_t resultWord = ULEV(*reinterpret_cast<const uint32_t*>(
     155                    section.content.data()+i*4));
     156                oss << (i==0 ? ':' : ',') << " 0x" << std::hex << testCase.expWords[i] <<
     157                        "!=0x" << resultWord << std::dec;
     158            }
     159            throw Exception(oss.str());
     160        }
     161    }
     162    // check error messages
     163    assertString("testEncGCNOpcodes", testCaseName+".errorMessages",
     164              testCase.errorMessages, errorStream.str());
     165}
     166
     167
    96168int main(int argc, const char** argv)
    97169{
     
    145217            retVal = 1;
    146218        }
     219    for (cxuint i = 0; encGCN15OpcodeCases2[i].input!=nullptr; i++)
     220        try
     221        { testEncGCNOpcodes2(i, encGCN15OpcodeCases2[i], GPUDeviceType::GFX1010); }
     222        catch(const std::exception& ex)
     223        {
     224            std::cerr << ex.what() << std::endl;
     225            retVal = 1;
     226        }
    147227    return retVal;
    148228}
Note: See TracChangeset for help on using the changeset viewer.