source: CLRX/CLRadeonExtender/trunk/amdasm/DisasmGallium.cpp @ 2377

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

CLRadeonExtender: Asm: Allow to define empty dimensions list in configuration. Disasm: Print empty dimensions in configuration.

File size: 10.8 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 <cstdio>
23#include <string>
24#include <ostream>
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/GalliumBinaries.h>
31#include <CLRX/amdasm/Disassembler.h>
32#include <CLRX/utils/GPUId.h>
33#include "DisasmInternals.h"
34
35using namespace CLRX;
36
37template<typename GalliumElfBinary>
38static void getGalliumDisasmInputFromBinaryBase(const GalliumBinary& binary,
39            const GalliumElfBinary& elfBin, Flags flags, GalliumDisasmInput* input)
40{
41    uint16_t rodataIndex = SHN_UNDEF;
42    try
43    { rodataIndex = elfBin.getSectionIndex(".rodata"); }
44    catch(const Exception& ex)
45    { }
46    const uint16_t textIndex = elfBin.getSectionIndex(".text");
47   
48    if (rodataIndex != SHN_UNDEF)
49    {
50        input->globalData = elfBin.getSectionContent(rodataIndex);
51        input->globalDataSize = ULEV(elfBin.getSectionHeader(rodataIndex).sh_size);
52    }
53    else
54    {
55        input->globalDataSize = 0;
56        input->globalData = nullptr;
57    }
58    // kernels
59    input->kernels.resize(binary.getKernelsNum());
60    for (cxuint i = 0; i < binary.getKernelsNum(); i++)
61    {
62        const GalliumKernel& kernel = binary.getKernel(i);
63        const GalliumProgInfoEntry* progInfo = elfBin.getProgramInfo(i);
64        GalliumProgInfoEntry outProgInfo[3];
65        for (cxuint k = 0; k < 3; k++)
66        {
67            outProgInfo[k].address = ULEV(progInfo[k].address);
68            outProgInfo[k].value = ULEV(progInfo[k].value);
69        }
70        input->kernels[i] = { kernel.kernelName,
71            {outProgInfo[0],outProgInfo[1],outProgInfo[2]}, kernel.offset,
72            std::vector<GalliumArgInfo>(kernel.argInfos.begin(), kernel.argInfos.end()) };
73    }
74    input->code = elfBin.getSectionContent(textIndex);
75    input->codeSize = ULEV(elfBin.getSectionHeader(textIndex).sh_size);
76}
77
78GalliumDisasmInput* CLRX::getGalliumDisasmInputFromBinary(GPUDeviceType deviceType,
79           const GalliumBinary& binary, Flags flags)
80{
81    std::unique_ptr<GalliumDisasmInput> input(new GalliumDisasmInput);
82    input->deviceType = deviceType;
83    if (!binary.is64BitElfBinary())
84    {
85        input->is64BitMode = false;
86        getGalliumDisasmInputFromBinaryBase(binary, binary.getElfBinary32(),
87                                flags, input.get());
88    }
89    else // 64-bit
90    {
91        input->is64BitMode = true;
92        getGalliumDisasmInputFromBinaryBase(binary, binary.getElfBinary64(),
93                                flags, input.get());
94    }
95    return input.release();
96}
97
98static const char* galliumArgTypeNamesTbl[] =
99{
100    "scalar", "constant", "global", "local", "image2d_rd", "image2d_wr", "image3d_rd",
101    "image3d_wr", "sampler"
102};
103
104static const char* galliumArgSemTypeNamesTbl[] =
105{
106    "general", "griddim", "gridoffset", "imgsize", "imgformat"
107};
108
109static void dumpKernelConfig(std::ostream& output, cxuint maxSgprsNum,
110             GPUArchitecture arch, const GalliumProgInfoEntry* progInfo)
111{
112    output.write("    .config\n", 12);
113    size_t bufSize;
114    char buf[100];
115    const cxuint ldsShift = arch<GPUArchitecture::GCN1_1 ? 8 : 9;
116    const uint32_t pgmRsrc1 = progInfo[0].value;
117    const uint32_t pgmRsrc2 = progInfo[1].value;
118    const uint32_t scratchVal = progInfo[2].value;
119   
120    const cxuint dimMask = (pgmRsrc2 >> 7) & 7;
121    strcpy(buf, "        .dims ");
122    bufSize = 14;
123    if ((dimMask & 1) != 0)
124        buf[bufSize++] = 'x';
125    if ((dimMask & 2) != 0)
126        buf[bufSize++] = 'y';
127    if ((dimMask & 4) != 0)
128        buf[bufSize++] = 'z';
129    buf[bufSize++] = '\n';
130    output.write(buf, bufSize);
131   
132    bufSize = snprintf(buf, 100, "        .sgprsnum %u\n",
133              std::min((((pgmRsrc1>>6) & 0xf)<<3)+8, maxSgprsNum));
134    output.write(buf, bufSize);
135    bufSize = snprintf(buf, 100, "        .vgprsnum %u\n", ((pgmRsrc1 & 0x3f)<<2)+4);
136    output.write(buf, bufSize);
137    if ((pgmRsrc1 & (1U<<20)) != 0)
138        output.write("        .privmode\n", 18);
139    if ((pgmRsrc1 & (1U<<22)) != 0)
140        output.write("        .debugmode\n", 19);
141    if ((pgmRsrc1 & (1U<<21)) != 0)
142        output.write("        .dx10clamp\n", 19);
143    if ((pgmRsrc1 & (1U<<23)) != 0)
144        output.write("        .ieeemode\n", 18);
145    if ((pgmRsrc2 & 0x400) != 0)
146        output.write("        .tgsize\n", 16);
147   
148    bufSize = snprintf(buf, 100, "        .floatmode 0x%02x\n", (pgmRsrc1>>12) & 0xff);
149    output.write(buf, bufSize);
150    bufSize = snprintf(buf, 100, "        .priority %u\n", (pgmRsrc1>>10) & 3);
151    output.write(buf, bufSize);
152    if (((pgmRsrc1>>24) & 0x7f) != 0)
153    {
154        bufSize = snprintf(buf, 100, "        .exceptions 0x%02x\n",
155                   (pgmRsrc1>>24) & 0x7f);
156        output.write(buf, bufSize);
157    }
158    const cxuint localSize = ((pgmRsrc2>>15) & 0x1ff) << ldsShift;
159    if (localSize!=0)
160    {
161        bufSize = snprintf(buf, 100, "        .localsize %u\n", localSize);
162        output.write(buf, bufSize);
163    }
164    bufSize = snprintf(buf, 100, "        .userdatanum %u\n", (pgmRsrc2>>1) & 0x1f);
165    output.write(buf, bufSize);
166    const cxuint scratchSize = ((scratchVal >> 12) << 10) >> 6;
167    if (scratchSize != 0) // scratch buffer
168    {
169        bufSize = snprintf(buf, 100, "        .scratchbuffer %u\n", scratchSize);
170        output.write(buf, bufSize);
171    }
172    bufSize = snprintf(buf, 100, "        .pgmrsrc1 0x%08x\n", pgmRsrc1);
173    output.write(buf, bufSize);
174    bufSize = snprintf(buf, 100, "        .pgmrsrc2 0x%08x\n", pgmRsrc2);
175    output.write(buf, bufSize);
176}
177
178void CLRX::disassembleGallium(std::ostream& output,
179          const GalliumDisasmInput* galliumInput, ISADisassembler* isaDisassembler,
180          size_t& sectionCount, Flags flags)
181{
182    const bool doDumpData = ((flags & DISASM_DUMPDATA) != 0);
183    const bool doMetadata = ((flags & (DISASM_METADATA|DISASM_CONFIG)) != 0);
184    const bool doDumpCode = ((flags & DISASM_DUMPCODE) != 0);
185    const bool doDumpConfig = ((flags & DISASM_CONFIG) != 0);
186   
187    if (galliumInput->is64BitMode)
188        output.write(".64bit\n", 7);
189    else
190        output.write(".32bit\n", 7);
191   
192    if (doDumpData && galliumInput->globalData != nullptr &&
193        galliumInput->globalDataSize != 0)
194    {   //
195        output.write(".rodata\n", 8);
196        printDisasmData(galliumInput->globalDataSize, galliumInput->globalData, output);
197    }
198   
199    const GPUArchitecture arch = getGPUArchitectureFromDeviceType(galliumInput->deviceType);
200    const cxuint maxSgprsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
201   
202    for (cxuint i = 0; i < galliumInput->kernels.size(); i++)
203    {
204        const GalliumDisasmKernelInput& kinput = galliumInput->kernels[i];
205        {
206            output.write(".kernel ", 8);
207            output.write(kinput.kernelName.c_str(), kinput.kernelName.size());
208            output.put('\n');
209        }
210        if (doMetadata)
211        {
212            char lineBuf[128];
213            output.write("    .args\n", 10);
214            for (const GalliumArgInfo& arg: kinput.argInfos)
215            {
216                ::memcpy(lineBuf, "        .arg ", 13);
217                size_t pos = 13;
218                // arg format: .arg TYPENAME, SIZE, TARGETSIZE, TALIGN, NUMEXT, SEMANTIC
219                if (arg.type <= GalliumArgType::MAX_VALUE)
220                {
221                    const char* typeStr = galliumArgTypeNamesTbl[cxuint(arg.type)];
222                    const size_t len = ::strlen(typeStr);
223                    ::memcpy(lineBuf+pos, typeStr, len);
224                    pos += len;
225                }
226                else
227                    pos += itocstrCStyle<cxuint>(cxuint(arg.type), lineBuf+pos, 16);
228               
229                lineBuf[pos++] = ',';
230                lineBuf[pos++] = ' ';
231                pos += itocstrCStyle<uint32_t>(arg.size, lineBuf+pos, 16);
232                lineBuf[pos++] = ',';
233                lineBuf[pos++] = ' ';
234                pos += itocstrCStyle<uint32_t>(arg.targetSize, lineBuf+pos, 16);
235                lineBuf[pos++] = ',';
236                lineBuf[pos++] = ' ';
237                pos += itocstrCStyle<uint32_t>(arg.targetAlign, lineBuf+pos, 16);
238                if (arg.signExtended)
239                    ::memcpy(lineBuf+pos, ", sext, ", 8);
240                else
241                    ::memcpy(lineBuf+pos, ", zext, ", 8);
242                pos += 8;
243                if (arg.semantic <= GalliumArgSemantic::MAX_VALUE)
244                {
245                    const char* typeStr = galliumArgSemTypeNamesTbl[cxuint(arg.semantic)];
246                    const size_t len = ::strlen(typeStr);
247                    ::memcpy(lineBuf+pos, typeStr, len);
248                    pos += len;
249                }
250                else
251                    pos += itocstrCStyle<cxuint>(cxuint(arg.semantic), lineBuf+pos, 16);
252                lineBuf[pos++] = '\n';
253                output.write(lineBuf, pos);
254            }
255            if (!doDumpConfig)
256            {   /// proginfo
257                output.write("    .proginfo\n", 14);
258                for (const GalliumProgInfoEntry& piEntry: kinput.progInfo)
259                {
260                    output.write("        .entry ", 15);
261                    char buf[32];
262                    size_t numSize = itocstrCStyle<uint32_t>(piEntry.address,
263                                 buf, 32, 16, 8);
264                    output.write(buf, numSize);
265                    output.write(", ", 2);
266                    numSize = itocstrCStyle<uint32_t>(piEntry.value, buf, 32, 16, 8);
267                    output.write(buf, numSize);
268                    output.write("\n", 1);
269                }
270            }
271            else
272                dumpKernelConfig(output, maxSgprsNum, arch, kinput.progInfo);
273        }
274        isaDisassembler->addNamedLabel(kinput.offset, kinput.kernelName);
275    }
276    if (doDumpCode && galliumInput->code != nullptr && galliumInput->codeSize != 0)
277    {   // print text
278        output.write(".text\n", 6);
279        isaDisassembler->setInput(galliumInput->codeSize, galliumInput->code);
280        isaDisassembler->beforeDisassemble();
281        isaDisassembler->disassemble();
282    }
283}
Note: See TracBrowser for help on using the repository browser.