source: CLRX/CLRadeonExtender/trunk/amdasm/DisasmAmdCL2.cpp @ 2495

Last change on this file since 2495 was 2495, checked in by matszpk, 4 years ago

CLRadeonExtender: Checking arch major .

File size: 38.3 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2016 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20#include <CLRX/Config.h>
21#include <cstdint>
22#include <string>
23#include <ostream>
24#include <cstdio>
25#include <memory>
26#include <vector>
27#include <utility>
28#include <CLRX/utils/Utilities.h>
29#include <CLRX/utils/MemAccess.h>
30#include <CLRX/amdbin/AmdCL2Binaries.h>
31#include <CLRX/amdbin/AmdCL2BinGen.h>
32#include <CLRX/amdasm/Disassembler.h>
33#include <CLRX/utils/GPUId.h>
34#include "DisasmInternals.h"
35
36using namespace CLRX;
37
38/* helpers for main Disassembler class */
39
40struct CLRX_INTERNAL CL2GPUDeviceCodeEntry
41{
42    uint32_t elfFlags;
43    GPUDeviceType deviceType;
44};
45
46/* 1912.05 driver device table list */
47static const CL2GPUDeviceCodeEntry cl2GpuDeviceCodeTable[] =
48{
49    { 6, GPUDeviceType::BONAIRE },
50    { 1, GPUDeviceType::SPECTRE },
51    { 2, GPUDeviceType::SPOOKY },
52    { 3, GPUDeviceType::KALINDI },
53    { 7, GPUDeviceType::HAWAII },
54    { 8, GPUDeviceType::ICELAND },
55    { 9, GPUDeviceType::TONGA },
56    { 4, GPUDeviceType::MULLINS },
57    { 17, GPUDeviceType::FIJI },
58    { 16, GPUDeviceType::CARRIZO },
59    { 15, GPUDeviceType::DUMMY }
60};
61
62/* 2004.06 driver device table list */
63static const CL2GPUDeviceCodeEntry cl2_16_3GpuDeviceCodeTable[] =
64{
65    { 6, GPUDeviceType::BONAIRE },
66    { 1, GPUDeviceType::SPECTRE },
67    { 2, GPUDeviceType::SPOOKY },
68    { 3, GPUDeviceType::KALINDI },
69    { 7, GPUDeviceType::HAWAII },
70    { 8, GPUDeviceType::ICELAND },
71    { 9, GPUDeviceType::TONGA },
72    { 4, GPUDeviceType::MULLINS },
73    { 16, GPUDeviceType::FIJI },
74    { 15, GPUDeviceType::CARRIZO },
75    { 13, GPUDeviceType::GOOSE },
76    { 12, GPUDeviceType::HORSE },
77    { 17, GPUDeviceType::STONEY }
78};
79
80/* 1801.05 driver device table list */
81static const CL2GPUDeviceCodeEntry cl2_15_7GpuDeviceCodeTable[] =
82{
83    { 6, GPUDeviceType::BONAIRE },
84    { 1, GPUDeviceType::SPECTRE },
85    { 2, GPUDeviceType::SPOOKY },
86    { 3, GPUDeviceType::KALINDI },
87    { 7, GPUDeviceType::HAWAII },
88    { 8, GPUDeviceType::ICELAND },
89    { 9, GPUDeviceType::TONGA },
90    { 4, GPUDeviceType::MULLINS },
91    { 16, GPUDeviceType::FIJI },
92    { 15, GPUDeviceType::CARRIZO }
93};
94
95/* driver version: 2036.3 */
96static const CL2GPUDeviceCodeEntry cl2GPUPROGpuDeviceCodeTable[] =
97{
98    { 6, GPUDeviceType::BONAIRE },
99    { 1, GPUDeviceType::SPECTRE },
100    { 2, GPUDeviceType::SPOOKY },
101    { 3, GPUDeviceType::KALINDI },
102    { 7, GPUDeviceType::HAWAII },
103    { 8, GPUDeviceType::ICELAND },
104    { 9, GPUDeviceType::TONGA },
105    { 4, GPUDeviceType::MULLINS },
106    { 14, GPUDeviceType::FIJI },
107    { 13, GPUDeviceType::CARRIZO },
108    { 17, GPUDeviceType::ELLESMERE },
109    { 16, GPUDeviceType::BAFFIN },
110    { 15, GPUDeviceType::STONEY }
111};
112
113AmdCL2DisasmInput* CLRX::getAmdCL2DisasmInputFromBinary(const AmdCL2MainGPUBinary& binary)
114{
115    std::unique_ptr<AmdCL2DisasmInput> input(new AmdCL2DisasmInput);
116    const uint32_t elfFlags = ULEV(binary.getHeader().e_flags);
117    // detect GPU device from elfMachine field from ELF header
118    cxuint entriesNum = 0;
119    const CL2GPUDeviceCodeEntry* gpuCodeTable = nullptr;
120    input->driverVersion = binary.getDriverVersion();
121    if (input->driverVersion < 191205)
122    {
123        gpuCodeTable = cl2_15_7GpuDeviceCodeTable;
124        entriesNum = sizeof(cl2_15_7GpuDeviceCodeTable)/sizeof(CL2GPUDeviceCodeEntry);
125    }
126    else if (input->driverVersion < 200406)
127    {
128        gpuCodeTable = cl2GpuDeviceCodeTable;
129        entriesNum = sizeof(cl2GpuDeviceCodeTable)/sizeof(CL2GPUDeviceCodeEntry);
130    }
131    else if (input->driverVersion < 203603)
132    {
133        gpuCodeTable = cl2_16_3GpuDeviceCodeTable;
134        entriesNum = sizeof(cl2_16_3GpuDeviceCodeTable)/sizeof(CL2GPUDeviceCodeEntry);
135    }
136    else
137    {
138        gpuCodeTable = cl2GPUPROGpuDeviceCodeTable;
139        entriesNum = sizeof(cl2GPUPROGpuDeviceCodeTable)/sizeof(CL2GPUDeviceCodeEntry);
140    }
141    //const cxuint entriesNum = sizeof(cl2GpuDeviceCodeTable)/sizeof(CL2GPUDeviceCodeEntry);
142    cxuint index;
143    for (index = 0; index < entriesNum; index++)
144        if (gpuCodeTable[index].elfFlags == elfFlags)
145            break;
146    if (entriesNum == index)
147        throw Exception("Can't determine GPU device type");
148   
149    input->deviceType = gpuCodeTable[index].deviceType;
150    GPUArchitecture arch = getGPUArchitectureFromDeviceType(input->deviceType);
151    input->archMinor = 0;
152    input->archStepping = 0;
153    input->compileOptions = binary.getCompileOptions();
154    input->aclVersionString = binary.getAclVersionString();
155    bool isInnerNewBinary = binary.hasInnerBinary() &&
156                binary.getDriverVersion()>=191205;
157   
158    input->samplerInitSize = 0;
159    input->samplerInit = nullptr;
160    input->globalDataSize = 0;
161    input->globalData = nullptr;
162    input->rwDataSize = 0;
163    input->rwData = nullptr;
164    input->bssAlignment = input->bssSize = 0;
165    std::vector<std::pair<size_t, size_t> > sortedRelocs; // by offset
166    const cxbyte* textPtr = nullptr;
167    const size_t kernelInfosNum = binary.getKernelInfosNum();
168   
169    uint16_t gDataSectionIdx = SHN_UNDEF;
170    uint16_t rwDataSectionIdx = SHN_UNDEF;
171    uint16_t bssDataSectionIdx = SHN_UNDEF;
172   
173    if (isInnerNewBinary)
174    {
175        const AmdCL2InnerGPUBinary& innerBin = binary.getInnerBinary();
176        input->globalDataSize = innerBin.getGlobalDataSize();
177        input->globalData = innerBin.getGlobalData();
178        input->rwDataSize = innerBin.getRwDataSize();
179        input->rwData = innerBin.getRwData();
180        input->samplerInitSize = innerBin.getSamplerInitSize();
181        input->samplerInit = innerBin.getSamplerInit();
182        input->bssAlignment = innerBin.getBssAlignment();
183        input->bssSize = innerBin.getBssSize();
184       
185        {
186            const cxbyte* noteContent = innerBin.getSectionContent(".note");
187            size_t notesSize = innerBin.getSectionHeader(".note").sh_size;
188            // find note about AMDGPU
189            for (size_t offset = 0; offset < notesSize; )
190            {
191                const Elf64_Nhdr* nhdr = (const Elf64_Nhdr*)(noteContent + offset);
192                size_t namesz = ULEV(nhdr->n_namesz);
193                size_t descsz = ULEV(nhdr->n_descsz);
194                if (usumGt(offset, namesz+descsz, notesSize))
195                    throw Exception("Note offset+size out of range");
196                if (ULEV(nhdr->n_type) == 0x3 && namesz==4 && descsz>=0x1a &&
197                    ::strcmp((const char*)noteContent+offset+sizeof(Elf64_Nhdr), "AMD")==0)
198                {    // AMDGPU type
199                    const uint32_t* content = (const uint32_t*)
200                            (noteContent+offset+sizeof(Elf64_Nhdr) + 4);
201                    uint32_t major = ULEV(content[1]);
202                    if ((arch==GPUArchitecture::GCN1_2 && major!=8) ||
203                        (arch==GPUArchitecture::GCN1_1 && major!=7))
204                        throw Exception("Wrong arch major for GPU architecture");
205                    input->archMinor = ULEV(content[2]);
206                    input->archStepping = ULEV(content[3]);
207                }
208                size_t align = (((namesz+descsz)&3)!=0) ? 4-((namesz+descsz)&3) : 0;
209                offset += sizeof(Elf64_Nhdr) + namesz + descsz + align;
210            }
211        }
212       
213        // if no kernels and data
214        if (kernelInfosNum==0)
215            return input.release();
216       
217        size_t relaNum = innerBin.getTextRelaEntriesNum();
218        for (size_t i = 0; i < relaNum; i++)
219        {
220            const Elf64_Rela& rel = innerBin.getTextRelaEntry(i);
221            sortedRelocs.push_back(std::make_pair(size_t(ULEV(rel.r_offset)), i));
222        }
223        // sort map
224        mapSort(sortedRelocs.begin(), sortedRelocs.end());
225        // get code section pointer for determine relocation position kernel code
226        textPtr = innerBin.getSectionContent(".hsatext");
227       
228        try
229        { gDataSectionIdx = innerBin.getSectionIndex(".hsadata_readonly_agent"); }
230        catch(const Exception& ex)
231        { }
232        try
233        { rwDataSectionIdx = innerBin.getSectionIndex(".hsadata_global_agent"); }
234        catch(const Exception& ex)
235        { }
236        try
237        { bssDataSectionIdx = innerBin.getSectionIndex(".hsabss_global_agent"); }
238        catch(const Exception& ex)
239        { }
240        // relocations for global data section (sampler symbols)
241        relaNum = innerBin.getGlobalDataRelaEntriesNum();
242        // section index for samplerinit (will be used for comparing sampler symbol section
243        uint16_t samplerInitSecIndex = SHN_UNDEF;
244        try
245        { samplerInitSecIndex = innerBin.getSectionIndex(".hsaimage_samplerinit"); }
246        catch(const Exception& ex)
247        { }
248       
249        for (size_t i = 0; i < relaNum; i++)
250        {
251            const Elf64_Rela& rel = innerBin.getGlobalDataRelaEntry(i);
252            size_t symIndex = ELF64_R_SYM(ULEV(rel.r_info));
253            const Elf64_Sym& sym = innerBin.getSymbol(symIndex);
254            // check symbol type, section and value
255            if (ELF64_ST_TYPE(sym.st_info) != 12)
256                throw Exception("Wrong sampler symbol");
257            uint64_t value = ULEV(sym.st_value);
258            if (ULEV(sym.st_shndx) != samplerInitSecIndex)
259                throw Exception("Wrong section for sampler symbol");
260            if ((value&7) != 0)
261                throw Exception("Wrong value of sampler symbol");
262            input->samplerRelocs.push_back({ size_t(ULEV(rel.r_offset)),
263                size_t(value>>3) });
264        }
265    }
266    else if (kernelInfosNum==0)
267        return input.release();
268   
269    input->kernels.resize(kernelInfosNum);
270    auto sortedRelocIter = sortedRelocs.begin();
271   
272    for (cxuint i = 0; i < kernelInfosNum; i++)
273    {
274        const KernelInfo& kernelInfo = binary.getKernelInfo(i);
275        AmdCL2DisasmKernelInput& kinput = input->kernels[i];
276        kinput.kernelName = kernelInfo.kernelName;
277        kinput.metadataSize = binary.getMetadataSize(i);
278        kinput.metadata = binary.getMetadata(i);
279       
280        kinput.isaMetadataSize = 0;
281        kinput.isaMetadata = nullptr;
282        // setup isa metadata content
283        const AmdCL2GPUKernelMetadata* isaMetadata = nullptr;
284        if (i < binary.getISAMetadatasNum())
285            isaMetadata = &binary.getISAMetadataEntry(i);
286        if (isaMetadata == nullptr || isaMetadata->kernelName != kernelInfo.kernelName)
287        {   // fallback if not in order
288            try
289            { isaMetadata = &binary.getISAMetadataEntry(
290                            kernelInfo.kernelName.c_str()); }
291            catch(const Exception& ex) // failed
292            { isaMetadata = nullptr; }
293        }
294        if (isaMetadata!=nullptr)
295        {
296            kinput.isaMetadataSize = isaMetadata->size;
297            kinput.isaMetadata = isaMetadata->data;
298        }
299       
300        kinput.code = nullptr;
301        kinput.codeSize = 0;
302        kinput.setup = nullptr;
303        kinput.setupSize = 0;
304        kinput.stub = nullptr;
305        kinput.stubSize = 0;
306        if (!binary.hasInnerBinary())
307            continue; // nothing else to set
308       
309        // get kernel code, setup and stub content
310        const AmdCL2InnerGPUBinaryBase& innerBin = binary.getInnerBinaryBase();
311        const AmdCL2GPUKernel* kernelData = nullptr;
312        if (i < innerBin.getKernelsNum())
313            kernelData = &innerBin.getKernelData(i);
314        if (kernelData==nullptr || kernelData->kernelName != kernelInfo.kernelName)
315            kernelData = &innerBin.getKernelData(kernelInfo.kernelName.c_str());
316       
317        if (kernelData!=nullptr)
318        {
319            kinput.code = kernelData->code;
320            kinput.codeSize = kernelData->codeSize;
321            kinput.setup = kernelData->setup;
322            kinput.setupSize = kernelData->setupSize;
323        }
324        if (!isInnerNewBinary)
325        {   // old drivers
326            const AmdCL2OldInnerGPUBinary& oldInnerBin = binary.getOldInnerBinary();
327            const AmdCL2GPUKernelStub* kstub = nullptr;
328            if (i < innerBin.getKernelsNum())
329                kstub = &oldInnerBin.getKernelStub(i);
330            if (kstub==nullptr || kernelData->kernelName != kernelInfo.kernelName)
331                kstub = &oldInnerBin.getKernelStub(kernelInfo.kernelName.c_str());
332            if (kstub!=nullptr)
333            {
334                kinput.stubSize = kstub->size;
335                kinput.stub = kstub->data;
336            }
337        }
338        else
339        {   // relocations
340            const AmdCL2InnerGPUBinary& innerBin = binary.getInnerBinary();
341           
342            if (sortedRelocIter != sortedRelocs.end() &&
343                    sortedRelocIter->first < size_t(kinput.code-textPtr))
344                throw Exception("Code relocation offset outside kernel code");
345           
346            if (sortedRelocIter != sortedRelocs.end())
347            {
348                size_t end = kinput.code+kinput.codeSize-textPtr;
349                for (; sortedRelocIter != sortedRelocs.end() &&
350                    sortedRelocIter->first<=end; ++sortedRelocIter)
351                {   // add relocations
352                    const Elf64_Rela& rela = innerBin.getTextRelaEntry(
353                                sortedRelocIter->second);
354                    uint32_t symIndex = ELF64_R_SYM(ULEV(rela.r_info));
355                    int64_t addend = ULEV(rela.r_addend);
356                    cxuint rsym = 0;
357                    // check this symbol
358                    const Elf64_Sym& sym = innerBin.getSymbol(symIndex);
359                    uint16_t symShndx = ULEV(sym.st_shndx);
360                    if (symShndx!=gDataSectionIdx && symShndx!=rwDataSectionIdx &&
361                        symShndx!=bssDataSectionIdx)
362                        throw Exception("Symbol is not placed in global or "
363                                "rwdata data or bss is illegal");
364                    addend += ULEV(sym.st_value);
365                    rsym = (symShndx==rwDataSectionIdx) ? 1 : 
366                        ((symShndx==bssDataSectionIdx) ? 2 : 0);
367                   
368                    RelocType relocType;
369                    uint32_t rtype = ELF64_R_TYPE(ULEV(rela.r_info));
370                    if (rtype==1)
371                        relocType = RELTYPE_LOW_32BIT;
372                    else if (rtype==2)
373                        relocType = RELTYPE_HIGH_32BIT;
374                    else
375                        throw Exception("Unknown relocation type");
376                    // put text relocs. compute offset by subtracting current code offset
377                    kinput.textRelocs.push_back(AmdCL2RelaEntry{sortedRelocIter->first-
378                        (kinput.code-textPtr), relocType, rsym, addend });
379                }
380            }
381        }
382    }
383    if (sortedRelocIter != sortedRelocs.end())
384        throw Exception("Code relocation offset outside kernel code");
385    return input.release();
386}
387
388struct CLRX_INTERNAL IntAmdCL2SetupData
389{
390    uint32_t pgmRSRC1;
391    uint32_t pgmRSRC2;
392    uint16_t setup1;
393    uint16_t archInd;
394    uint32_t scratchBufferSize;
395    uint32_t localSize; // in bytes
396    uint32_t zero1;
397    uint32_t kernelArgsSize;
398    uint32_t zeroes[2];
399    uint16_t sgprsNumAll;
400    uint16_t vgprsNum16;
401    uint32_t vgprsNum;
402    uint32_t sgprsNum;
403    uint32_t zero3;
404    uint32_t version; // ??
405};
406
407static const size_t disasmArgTypeNameMapSize = sizeof(disasmArgTypeNameMap)/
408            sizeof(std::pair<const char*, KernelArgType>);
409
410static const KernelArgType cl20ArgTypeVectorTable[] =
411{
412    KernelArgType::CHAR,
413    KernelArgType::CHAR2,
414    KernelArgType::CHAR3,
415    KernelArgType::CHAR4,
416    KernelArgType::CHAR8,
417    KernelArgType::CHAR16,
418    KernelArgType::SHORT,
419    KernelArgType::SHORT2,
420    KernelArgType::SHORT3,
421    KernelArgType::SHORT4,
422    KernelArgType::SHORT8,
423    KernelArgType::SHORT16,
424    KernelArgType::INT,
425    KernelArgType::INT2,
426    KernelArgType::INT3,
427    KernelArgType::INT4,
428    KernelArgType::INT8,
429    KernelArgType::INT16,
430    KernelArgType::LONG,
431    KernelArgType::LONG2,
432    KernelArgType::LONG3,
433    KernelArgType::LONG4,
434    KernelArgType::LONG8,
435    KernelArgType::LONG16,
436    KernelArgType::VOID,
437    KernelArgType::VOID,
438    KernelArgType::VOID,
439    KernelArgType::VOID,
440    KernelArgType::VOID,
441    KernelArgType::VOID,
442    KernelArgType::FLOAT,
443    KernelArgType::FLOAT2,
444    KernelArgType::FLOAT3,
445    KernelArgType::FLOAT4,
446    KernelArgType::FLOAT8,
447    KernelArgType::FLOAT16,
448    KernelArgType::DOUBLE,
449    KernelArgType::DOUBLE2,
450    KernelArgType::DOUBLE3,
451    KernelArgType::DOUBLE4,
452    KernelArgType::DOUBLE8,
453    KernelArgType::DOUBLE16
454};
455
456static const cxuint vectorIdTable[17] =
457{ UINT_MAX, 0, 1, 2, 3, UINT_MAX, UINT_MAX, UINT_MAX, 4,
458  UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, 5 };
459
460static AmdCL2KernelConfig genKernelConfig(size_t metadataSize, const cxbyte* metadata,
461        size_t setupSize, const cxbyte* setup, const std::vector<size_t> samplerOffsets,
462        const std::vector<AmdCL2RelaEntry>& textRelocs)
463{
464    AmdCL2KernelConfig config{};
465    const AmdCL2GPUMetadataHeader* mdHdr =
466            reinterpret_cast<const AmdCL2GPUMetadataHeader*>(metadata);
467    size_t headerSize = ULEV(mdHdr->size);
468    for (size_t i = 0; i < 3; i++)
469        config.reqdWorkGroupSize[i] = ULEV(mdHdr->reqdWorkGroupSize[i]);
470    const IntAmdCL2SetupData* setupData =
471            reinterpret_cast<const IntAmdCL2SetupData*>(setup + 48);
472    uint32_t pgmRSRC1 = ULEV(setupData->pgmRSRC1);
473    uint32_t pgmRSRC2 = ULEV(setupData->pgmRSRC2);
474    /* initializing fields from PGM_RSRC1 and PGM_RSRC2 */
475    config.dimMask = (pgmRSRC2>>7)&7;
476    config.ieeeMode = (pgmRSRC1>>23)&1;
477    config.exceptions = (pgmRSRC2>>24)&0xff;
478    config.floatMode = (pgmRSRC1>>12)&0xff;
479    config.priority = (pgmRSRC1>>10)&3;
480    config.tgSize = (pgmRSRC2>>10)&1;
481    config.privilegedMode = (pgmRSRC1>>20)&1;
482    config.dx10Clamp = (pgmRSRC1>>21)&1;
483    config.debugMode = (pgmRSRC1>>22)&1;
484    config.pgmRSRC2 = pgmRSRC2;
485    config.pgmRSRC1 = pgmRSRC1;
486    config.usedVGPRsNum = ULEV(setupData->vgprsNum);
487    config.usedSGPRsNum = ULEV(setupData->sgprsNum);
488    config.scratchBufferSize = ULEV(setupData->scratchBufferSize);
489    config.localSize = ULEV(setupData->localSize);
490    uint16_t ksetup1 = ULEV(setupData->setup1);
491    config.useSetup = (ksetup1&2)!=0;
492    config.useArgs = (ksetup1&8)!=0;
493    config.useGeneric = config.useEnqueue = false;
494    if (ksetup1==0x2f) // if generic pointer support
495        config.useGeneric = true;
496    else
497        config.useEnqueue = (ksetup1&0x20)!=0;
498   
499    // get samplers
500    for (const AmdCL2RelaEntry& reloc: textRelocs)
501    {   // check if sampler
502        auto it = std::find(samplerOffsets.begin(), samplerOffsets.end(), reloc.addend);
503        if (it!=samplerOffsets.end())
504            config.samplers.push_back(it-samplerOffsets.begin());
505    }
506    std::sort(config.samplers.begin(), config.samplers.end());
507    config.samplers.resize(std::unique(config.samplers.begin(), config.samplers.end()) -
508                config.samplers.begin());
509    // get kernel args
510    size_t argOffset = headerSize + ULEV(mdHdr->firstNameLength) + 
511            ULEV(mdHdr->secondNameLength)+2;
512    if (ULEV(*((const uint32_t*)(metadata+argOffset))) == 0x5800)
513        argOffset++;    // fix for AMD GPUPRO driver (2036.03) */
514    const AmdCL2GPUKernelArgEntry* argPtr = reinterpret_cast<
515            const AmdCL2GPUKernelArgEntry*>(metadata + argOffset);
516    const uint32_t argsNum = ULEV(mdHdr->argsNum);
517    const char* strBase = (const char*)metadata;
518    size_t strOffset = argOffset + sizeof(AmdCL2GPUKernelArgEntry)*(argsNum+1);
519   
520    for (uint32_t i = 0; i < argsNum; i++, argPtr++)
521    {
522        AmdKernelArgInput arg{};
523        size_t nameSize = ULEV(argPtr->argNameSize);
524        arg.argName.assign(strBase+strOffset, nameSize);
525        strOffset += nameSize+1;
526        nameSize = ULEV(argPtr->typeNameSize);
527        arg.typeName.assign(strBase+strOffset, nameSize);
528        strOffset += nameSize+1;
529       
530        uint32_t vectorSize = ULEV(argPtr->vectorLength);
531        uint32_t argType = ULEV(argPtr->argType);
532        uint32_t kindOfType = ULEV(argPtr->kindOfType);
533       
534        arg.ptrSpace = KernelPtrSpace::NONE;
535        arg.ptrAccess = KARG_PTR_NORMAL;
536        arg.argType = KernelArgType::VOID;
537       
538        if (ULEV(argPtr->isConst))
539            arg.ptrAccess |= KARG_PTR_CONST;
540        arg.used = AMDCL2_ARGUSED_READ_WRITE; // default is used
541       
542        if (!ULEV(argPtr->isPointerOrPipe))
543        { // if not point or pipe (get regular type: scalar, image, sampler,...)
544            switch(argType)
545            {
546                case 0:
547                    if (kindOfType!=1) // not sampler
548                        throw Exception("Wrong kernel argument type");
549                    arg.argType = KernelArgType::SAMPLER;
550                    break;
551                case 1:  // read_only image
552                case 2:  // write_only image
553                case 3:  // read_write image
554                    if (kindOfType==2) // not image
555                    {
556                        arg.argType = KernelArgType::IMAGE;
557                        arg.ptrAccess = (argType==1) ? KARG_PTR_READ_ONLY : (argType==2) ?
558                                 KARG_PTR_WRITE_ONLY : KARG_PTR_READ_WRITE;
559                        arg.ptrSpace = KernelPtrSpace::GLOBAL;
560                    }
561                    else if (argType==2 || argType == 3)
562                    {
563                        if (kindOfType!=4) // not scalar
564                            throw Exception("Wrong kernel argument type");
565                        arg.argType = (argType==3) ?
566                            KernelArgType::SHORT : KernelArgType::CHAR;
567                    }
568                    else
569                        throw Exception("Wrong kernel argument type");
570                    break;
571                case 4: // int
572                case 5: // long
573                    if (kindOfType!=4) // not scalar
574                        throw Exception("Wrong kernel argument type");
575                    arg.argType = (argType==5) ?
576                        KernelArgType::LONG : KernelArgType::INT;
577                    break;
578                case 6: // char
579                case 7: // short
580                case 8: // int
581                case 9: // long
582                case 11: // float
583                case 12: // double
584                {
585                    if (kindOfType!=4) // not scalar
586                        throw Exception("Wrong kernel argument type");
587                    const cxuint vectorId = vectorIdTable[vectorSize];
588                    if (vectorId == UINT_MAX)
589                        throw Exception("Wrong vector size");
590                    arg.argType = cl20ArgTypeVectorTable[(argType-6)*6 + vectorId];
591                    break;
592                }
593                case 15:
594                    if (kindOfType!=4) // not scalar
595                        throw Exception("Wrong kernel argument type");
596                    arg.argType = KernelArgType::STRUCTURE;
597                    break;
598                case 18:
599                    if (kindOfType!=7) // not scalar
600                        throw Exception("Wrong kernel argument type");
601                    arg.argType = KernelArgType::CMDQUEUE;
602                    break;
603                default:
604                    throw Exception("Wrong kernel argument type");
605                    break;
606            }
607           
608            auto it = binaryMapFind(disasmArgTypeNameMap,
609                        disasmArgTypeNameMap + disasmArgTypeNameMapSize,
610                        arg.typeName.c_str(), CStringLess());
611            if (it != disasmArgTypeNameMap + disasmArgTypeNameMapSize) // if found
612                arg.argType = it->second;
613           
614            if (arg.argType == KernelArgType::STRUCTURE)
615                arg.structSize = ULEV(argPtr->structSize);
616            else if (isKernelArgImage(arg.argType) || arg.argType==KernelArgType::SAMPLER)
617                arg.resId = LEV(argPtr->resId); // sampler and images have resource id
618        }
619        else
620        {   // pointer or pipe
621            if (argPtr->isPipe)
622                arg.used = (ULEV(argPtr->isPointerOrPipe))==3;
623            else
624                arg.used = (ULEV(argPtr->isPointerOrPipe));
625            uint32_t ptrType = ULEV(argPtr->ptrType);
626            uint32_t ptrSpace = ULEV(argPtr->ptrSpace);
627            if (argType == 7) // pointer or pipe
628                arg.argType = (argPtr->isPipe==0) ? KernelArgType::POINTER :
629                    KernelArgType::PIPE;
630            else if (argType == 15)
631                arg.argType = KernelArgType::POINTER;
632            if (arg.argType == KernelArgType::POINTER)
633            {   // if pointer
634                if (ptrSpace==3)
635                    arg.ptrSpace = KernelPtrSpace::LOCAL;
636                else if (ptrSpace==4)
637                    arg.ptrSpace = KernelPtrSpace::GLOBAL;
638                else if (ptrSpace==5)
639                    arg.ptrSpace = KernelPtrSpace::CONSTANT;
640                else
641                    throw Exception("Illegal pointer space");
642                // set access qualifiers (volatile, restrict, const)
643                arg.ptrAccess |= KARG_PTR_NORMAL;
644                if (argPtr->isRestrict)
645                    arg.ptrAccess |= KARG_PTR_RESTRICT;
646                if (argPtr->isVolatile)
647                    arg.ptrAccess |= KARG_PTR_VOLATILE;
648            }
649            else
650            {
651                if (ptrSpace!=4)
652                    throw Exception("Illegal pipe space");
653                arg.ptrSpace = KernelPtrSpace::GLOBAL;
654            }
655           
656            if (arg.argType == KernelArgType::POINTER)
657            {
658                size_t ptrTypeNameSize=0;
659                if (arg.typeName.empty()) // ctx_struct_fld1
660                {
661                    if (ptrType >= 6 && ptrType <= 12)
662                        arg.pointerType = cl20ArgTypeVectorTable[(ptrType-6)*6];
663                    else
664                        arg.pointerType = KernelArgType::FLOAT;
665                }
666                else
667                {
668                    arg.pointerType = KernelArgType::VOID;
669                    switch (ptrType)
670                    {
671                        case 6: // char
672                        case 7: // short
673                        case 8: // int
674                        case 9: // long
675                        case 11: // float
676                        case 12: // double
677                            arg.pointerType = cl20ArgTypeVectorTable[(ptrType-6)*6];
678                            break;
679                    }
680                   
681                    while (isAlnum(arg.typeName[ptrTypeNameSize]) ||
682                        arg.typeName[ptrTypeNameSize]=='_') ptrTypeNameSize++;
683                    CString ptrTypeName(arg.typeName.c_str(), ptrTypeNameSize);
684                    if (arg.typeName.find('*')!=CString::npos) // assume 'void*'
685                    {
686                        auto it = binaryMapFind(disasmArgTypeNameMap,
687                                    disasmArgTypeNameMap + disasmArgTypeNameMapSize,
688                                    ptrTypeName.c_str(), CStringLess());
689                        if (it != disasmArgTypeNameMap + disasmArgTypeNameMapSize)
690                            // if found
691                            arg.pointerType = it->second;
692                        else if (arg.pointerType==KernelArgType::VOID)
693                            arg.pointerType = KernelArgType::STRUCTURE;
694                    }
695                    else if (ptrType==18)
696                    {   /* if clkevent */
697                        arg.argType = KernelArgType::CLKEVENT;
698                        arg.pointerType = KernelArgType::VOID;
699                    }
700                    else /* unknown type of pointer */
701                        arg.pointerType = KernelArgType::VOID;
702                       
703                    if (arg.pointerType == KernelArgType::STRUCTURE)
704                        arg.structSize = ULEV(argPtr->ptrAlignment);
705                }
706            }
707        }
708        config.args.push_back(arg);
709    }
710    return config;
711}
712
713static void dumpAmdCL2KernelConfig(std::ostream& output, const AmdCL2KernelConfig& config)
714{
715    size_t bufSize;
716    char buf[100];
717    output.write("    .config\n", 12);
718    if (config.dimMask != BINGEN_DEFAULT)
719    {
720        strcpy(buf, "        .dims ");
721        bufSize = 14;
722        if ((config.dimMask & 1) != 0)
723            buf[bufSize++] = 'x';
724        if ((config.dimMask & 2) != 0)
725            buf[bufSize++] = 'y';
726        if ((config.dimMask & 4) != 0)
727            buf[bufSize++] = 'z';
728        buf[bufSize++] = '\n';
729        output.write(buf, bufSize);
730    }
731    bufSize = 0;
732    if (config.reqdWorkGroupSize[2] != 0)
733        bufSize = snprintf(buf, 100, "        .cws %u, %u, %u\n",
734               config.reqdWorkGroupSize[0], config.reqdWorkGroupSize[1],
735               config.reqdWorkGroupSize[2]);
736    else if (config.reqdWorkGroupSize[1] != 0)
737        bufSize = snprintf(buf, 100, "        .cws %u, %u\n", config.reqdWorkGroupSize[0],
738                   config.reqdWorkGroupSize[1]);
739    else if (config.reqdWorkGroupSize[0] != 0)
740        bufSize = snprintf(buf, 100, "        .cws %u\n", config.reqdWorkGroupSize[0]);
741    if (bufSize != 0) // if we have cws
742        output.write(buf, bufSize);
743   
744    bufSize = snprintf(buf, 100, "        .sgprsnum %u\n", config.usedSGPRsNum);
745    output.write(buf, bufSize);
746    bufSize = snprintf(buf, 100, "        .vgprsnum %u\n", config.usedVGPRsNum);
747    output.write(buf, bufSize);
748   
749    if (config.localSize!=0)
750    {
751        bufSize = snprintf(buf, 100, "        .localsize %llu\n",
752                       cxullong(config.localSize));
753        output.write(buf, bufSize);
754    }
755    bufSize = snprintf(buf, 100, "        .floatmode 0x%02x\n", config.floatMode);
756    output.write(buf, bufSize);
757    if (config.scratchBufferSize!=0)
758    {
759        bufSize = snprintf(buf, 100, "        .scratchbuffer %u\n",
760                           config.scratchBufferSize);
761        output.write(buf, bufSize);
762    }
763    bufSize = snprintf(buf, 100, "        .pgmrsrc1 0x%08x\n", config.pgmRSRC1);
764    output.write(buf, bufSize);
765    bufSize = snprintf(buf, 100, "        .pgmrsrc2 0x%08x\n", config.pgmRSRC2);
766    output.write(buf, bufSize);
767    if (config.privilegedMode)
768        output.write("        .privmode\n", 18);
769    if (config.debugMode)
770        output.write("        .debugmode\n", 19);
771    if (config.dx10Clamp)
772        output.write("        .dx10clamp\n", 19);
773    if (config.ieeeMode)
774        output.write("        .ieeemode\n", 18);
775    if (config.tgSize)
776        output.write("        .tgsize\n", 16);
777    if ((config.exceptions & 0x7f) != 0)
778    {
779        bufSize = snprintf(buf, 100, "        .exceptions 0x%02x\n",
780                   cxuint(config.exceptions));
781        output.write(buf, bufSize);
782    }
783    if (config.useArgs)
784        output.write("        .useargs\n", 17);
785    if (config.useSetup)
786        output.write("        .usesetup\n", 18);
787    if (config.useEnqueue)
788        output.write("        .useenqueue\n", 20);
789    if (config.useGeneric)
790        output.write("        .usegeneric\n", 20);
791    bufSize = snprintf(buf, 100, "        .priority %u\n", config.priority);
792    output.write(buf, bufSize);
793    // arguments
794    for (const AmdKernelArgInput& arg: config.args)
795        dumpAmdKernelArg(output, arg, true);
796    // samplers
797    for (cxuint sampler: config.samplers)
798    {
799        bufSize = snprintf(buf, 100, "        .sampler %u\n", sampler);
800        output.write(buf, bufSize);
801    }
802}
803
804void CLRX::disassembleAmdCL2(std::ostream& output, const AmdCL2DisasmInput* amdCL2Input,
805       ISADisassembler* isaDisassembler, size_t& sectionCount, Flags flags)
806{
807    const bool doMetadata = ((flags & DISASM_METADATA) != 0);
808    const bool doDumpData = ((flags & DISASM_DUMPDATA) != 0);
809    const bool doDumpCode = ((flags & DISASM_DUMPCODE) != 0);
810    const bool doDumpConfig = ((flags & DISASM_CONFIG) != 0);
811    const bool doSetup = ((flags & DISASM_SETUP) != 0);
812   
813    {
814        char buf[40];
815        size_t size = snprintf(buf, 40, ".arch_minor %u\n", amdCL2Input->archMinor);
816        output.write(buf, size);
817        size = snprintf(buf, 40, ".arch_stepping %u\n", amdCL2Input->archStepping);
818        output.write(buf, size);
819        size = snprintf(buf, 40, ".driver_version %u\n",
820                   amdCL2Input->driverVersion);
821        output.write(buf, size);
822    }
823   
824    if (doMetadata)
825    {
826        output.write(".compile_options \"", 18);
827        const std::string escapedCompileOptions = 
828                escapeStringCStyle(amdCL2Input->compileOptions);
829        output.write(escapedCompileOptions.c_str(), escapedCompileOptions.size());
830        output.write("\"\n.acl_version \"", 16);
831        const std::string escapedAclVersionString =
832                escapeStringCStyle(amdCL2Input->aclVersionString);
833        output.write(escapedAclVersionString.c_str(), escapedAclVersionString.size());
834        output.write("\"\n", 2);
835    }
836    if (doSetup && !doDumpCode)
837    {
838        if (amdCL2Input->samplerInit!=nullptr && amdCL2Input->samplerInitSize!=0)
839        {   /// sampler init entries
840            output.write(".samplerinit\n", 13);
841            printDisasmData(amdCL2Input->samplerInitSize,
842                            amdCL2Input->samplerInit, output);
843        }
844    }
845    else if (doDumpConfig && amdCL2Input->samplerInit!=nullptr)
846    {   // print sampler values instead raw samler data in .samplerinit
847        char buf[50];
848        const size_t samplersNum = amdCL2Input->samplerInitSize>>3;
849        for (size_t i = 0; i < samplersNum; i++)
850        {
851            size_t bufSize = snprintf(buf, 50, ".sampler 0x%08x\n",
852                      ULEV(((const uint32_t*)amdCL2Input->samplerInit)[i*2+1]));
853            output.write(buf, bufSize);
854        }
855    }
856   
857    if (doDumpData && amdCL2Input->globalData != nullptr &&
858        amdCL2Input->globalDataSize != 0)
859    {
860        output.write(".globaldata\n", 12);
861        output.write(".gdata:\n", 8); /// symbol used by text relocations
862        printDisasmData(amdCL2Input->globalDataSize, amdCL2Input->globalData, output);
863        /// put sampler relocations at global data section
864        for (auto v: amdCL2Input->samplerRelocs)
865        {
866            output.write("    .samplerreloc ", 18);
867            char buf[64];
868            size_t bufPos = itocstrCStyle<size_t>(v.first, buf, 22);
869            buf[bufPos++] = ',';
870            buf[bufPos++] = ' ';
871            bufPos += itocstrCStyle<size_t>(v.second, buf+bufPos, 22);
872            buf[bufPos++] = '\n';
873            output.write(buf, bufPos);
874        }
875    }
876    if (doDumpData && amdCL2Input->rwData != nullptr &&
877        amdCL2Input->rwDataSize != 0)
878    {
879        output.write(".data\n", 6);
880        output.write(".ddata:\n", 8); /// symbol used by text relocations
881        printDisasmData(amdCL2Input->rwDataSize, amdCL2Input->rwData, output);
882    }
883   
884    if (doDumpData && amdCL2Input->bssSize)
885    {
886        output.write(".section .bss align=", 20);
887        char buf[64];
888        size_t bufPos = itocstrCStyle<size_t>(amdCL2Input->bssAlignment, buf, 22);
889        buf[bufPos++] = '\n';
890        output.write(buf, bufPos);
891        output.write(".bdata:\n", 8); /// symbol used by text relocations
892        output.write("    .skip ", 10);
893        bufPos = itocstrCStyle<size_t>(amdCL2Input->bssSize, buf, 22);
894        buf[bufPos++] = '\n';
895        output.write(buf, bufPos);
896    }
897   
898    std::vector<size_t> samplerOffsets;
899    if (doDumpConfig)
900    {
901        for (auto reloc: amdCL2Input->samplerRelocs)
902        {
903            if (samplerOffsets.size() >= reloc.second)
904                samplerOffsets.resize(reloc.second+1);
905            samplerOffsets[reloc.second] = reloc.first;
906        }
907    }
908   
909    for (const AmdCL2DisasmKernelInput& kinput: amdCL2Input->kernels)
910    {
911        output.write(".kernel ", 8);
912        output.write(kinput.kernelName.c_str(), kinput.kernelName.size());
913        output.put('\n');
914        if (doMetadata && !doDumpConfig)
915        {
916            if (kinput.metadata != nullptr && kinput.metadataSize != 0)
917            {   // if kernel metadata available
918                output.write("    .metadata\n", 14);
919                printDisasmData(kinput.metadataSize, kinput.metadata, output, true);
920            }
921            if (kinput.isaMetadata != nullptr && kinput.isaMetadataSize != 0)
922            {   // if kernel isametadata available
923                output.write("    .isametadata\n", 17);
924                printDisasmData(kinput.isaMetadataSize, kinput.isaMetadata, output, true);
925            }
926        }
927        if (doSetup && !doDumpConfig)
928        {
929            if (kinput.stub != nullptr && kinput.stubSize != 0)
930            {   // if kernel setup available
931                output.write("    .stub\n", 10);
932                printDisasmData(kinput.stubSize, kinput.stub, output, true);
933            }
934            if (kinput.setup != nullptr && kinput.setupSize != 0)
935            {   // if kernel setup available
936                output.write("    .setup\n", 11);
937                printDisasmData(kinput.setupSize, kinput.setup, output, true);
938            }
939        }
940       
941        if (doDumpConfig)
942        {
943            const AmdCL2KernelConfig config = genKernelConfig(kinput.metadataSize,
944                    kinput.metadata, kinput.setupSize, kinput.setup, samplerOffsets,
945                    kinput.textRelocs);
946            dumpAmdCL2KernelConfig(output, config);
947        }
948       
949        if (doDumpCode && kinput.code != nullptr && kinput.codeSize != 0)
950        {   // input kernel code (main disassembly)
951            isaDisassembler->clearRelocations();
952            isaDisassembler->addRelSymbol(".gdata");
953            isaDisassembler->addRelSymbol(".ddata"); // rw data
954            isaDisassembler->addRelSymbol(".bdata"); // .bss data
955            for (const AmdCL2RelaEntry& entry: kinput.textRelocs)
956                isaDisassembler->addRelocation(entry.offset, entry.type, 
957                               cxuint(entry.symbol), entry.addend);
958   
959            output.write("    .text\n", 10);
960            isaDisassembler->setInput(kinput.codeSize, kinput.code);
961            isaDisassembler->beforeDisassemble();
962            isaDisassembler->disassemble();
963            sectionCount++;
964        }
965    }
966}
Note: See TracBrowser for help on using the repository browser.