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

Last change on this file since 3150 was 3150, checked in by matszpk, 2 years ago

CLRadeonExtender: CLRX: small typos. GalliumBinary/GalliumDisasm?: Add support new LLVM 3.9.0 (spilledGPR info) and new Mesa3D 17.0.

File size: 10.9 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2017 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, 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    input->isMesa170 = binary.isMesa170();
59    input->isLLVM390 = elfBin.isLLVM390();
60    // kernels
61    input->kernels.resize(binary.getKernelsNum());
62    for (cxuint i = 0; i < binary.getKernelsNum(); i++)
63    {
64        const GalliumKernel& kernel = binary.getKernel(i);
65        const GalliumProgInfoEntry* progInfo = elfBin.getProgramInfo(i);
66        GalliumProgInfoEntry outProgInfo[3];
67        for (cxuint k = 0; k < 3; k++)
68        {
69            outProgInfo[k].address = ULEV(progInfo[k].address);
70            outProgInfo[k].value = ULEV(progInfo[k].value);
71        }
72        input->kernels[i] = { kernel.kernelName,
73            {outProgInfo[0],outProgInfo[1],outProgInfo[2]}, kernel.offset,
74            std::vector<GalliumArgInfo>(kernel.argInfos.begin(), kernel.argInfos.end()) };
75    }
76    input->code = elfBin.getSectionContent(textIndex);
77    input->codeSize = ULEV(elfBin.getSectionHeader(textIndex).sh_size);
78}
79
80GalliumDisasmInput* CLRX::getGalliumDisasmInputFromBinary(GPUDeviceType deviceType,
81           const GalliumBinary& binary)
82{
83    std::unique_ptr<GalliumDisasmInput> input(new GalliumDisasmInput);
84    input->deviceType = deviceType;
85    if (!binary.is64BitElfBinary())
86    {
87        input->is64BitMode = false;
88        getGalliumDisasmInputFromBinaryBase(binary, binary.getElfBinary32(), input.get());
89    }
90    else // 64-bit
91    {
92        input->is64BitMode = true;
93        getGalliumDisasmInputFromBinaryBase(binary, binary.getElfBinary64(), 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    if (galliumInput->isLLVM390)
199        output.write(".llvm390\n", 9);
200    if (galliumInput->isMesa170)
201        output.write(".mesa170\n", 9);
202   
203    const GPUArchitecture arch = getGPUArchitectureFromDeviceType(galliumInput->deviceType);
204    const cxuint maxSgprsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
205   
206    for (cxuint i = 0; i < galliumInput->kernels.size(); i++)
207    {
208        const GalliumDisasmKernelInput& kinput = galliumInput->kernels[i];
209        {
210            output.write(".kernel ", 8);
211            output.write(kinput.kernelName.c_str(), kinput.kernelName.size());
212            output.put('\n');
213        }
214        if (doMetadata)
215        {
216            char lineBuf[128];
217            output.write("    .args\n", 10);
218            for (const GalliumArgInfo& arg: kinput.argInfos)
219            {
220                ::memcpy(lineBuf, "        .arg ", 13);
221                size_t pos = 13;
222                // arg format: .arg TYPENAME, SIZE, TARGETSIZE, TALIGN, NUMEXT, SEMANTIC
223                if (arg.type <= GalliumArgType::MAX_VALUE)
224                {
225                    const char* typeStr = galliumArgTypeNamesTbl[cxuint(arg.type)];
226                    const size_t len = ::strlen(typeStr);
227                    ::memcpy(lineBuf+pos, typeStr, len);
228                    pos += len;
229                }
230                else
231                    pos += itocstrCStyle<cxuint>(cxuint(arg.type), lineBuf+pos, 16);
232               
233                lineBuf[pos++] = ',';
234                lineBuf[pos++] = ' ';
235                pos += itocstrCStyle<uint32_t>(arg.size, lineBuf+pos, 16);
236                lineBuf[pos++] = ',';
237                lineBuf[pos++] = ' ';
238                pos += itocstrCStyle<uint32_t>(arg.targetSize, lineBuf+pos, 16);
239                lineBuf[pos++] = ',';
240                lineBuf[pos++] = ' ';
241                pos += itocstrCStyle<uint32_t>(arg.targetAlign, lineBuf+pos, 16);
242                if (arg.signExtended)
243                    ::memcpy(lineBuf+pos, ", sext, ", 8);
244                else
245                    ::memcpy(lineBuf+pos, ", zext, ", 8);
246                pos += 8;
247                if (arg.semantic <= GalliumArgSemantic::MAX_VALUE)
248                {
249                    const char* typeStr = galliumArgSemTypeNamesTbl[cxuint(arg.semantic)];
250                    const size_t len = ::strlen(typeStr);
251                    ::memcpy(lineBuf+pos, typeStr, len);
252                    pos += len;
253                }
254                else
255                    pos += itocstrCStyle<cxuint>(cxuint(arg.semantic), lineBuf+pos, 16);
256                lineBuf[pos++] = '\n';
257                output.write(lineBuf, pos);
258            }
259            if (!doDumpConfig)
260            {   /// proginfo
261                output.write("    .proginfo\n", 14);
262                for (const GalliumProgInfoEntry& piEntry: kinput.progInfo)
263                {
264                    output.write("        .entry ", 15);
265                    char buf[32];
266                    size_t numSize = itocstrCStyle<uint32_t>(piEntry.address,
267                                 buf, 32, 16, 8);
268                    output.write(buf, numSize);
269                    output.write(", ", 2);
270                    numSize = itocstrCStyle<uint32_t>(piEntry.value, buf, 32, 16, 8);
271                    output.write(buf, numSize);
272                    output.write("\n", 1);
273                }
274            }
275            else
276                dumpKernelConfig(output, maxSgprsNum, arch, kinput.progInfo);
277        }
278        isaDisassembler->addNamedLabel(kinput.offset, kinput.kernelName);
279    }
280    if (doDumpCode && galliumInput->code != nullptr && galliumInput->codeSize != 0)
281    {   // print text
282        output.write(".text\n", 6);
283        isaDisassembler->setInput(galliumInput->codeSize, galliumInput->code);
284        isaDisassembler->beforeDisassemble();
285        isaDisassembler->disassemble();
286    }
287}
Note: See TracBrowser for help on using the repository browser.