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

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

CLRadeonExtender: Use new methods to access to notes in DisasmAmdCL2.

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