source: CLRX/CLRadeonExtender/trunk/amdasm/DisasmROCm.cpp @ 3662

Last change on this file since 3662 was 3662, checked in by matszpk, 3 years ago

CLRadeonExtender: ROCm: Add eflags support (allow to set or get various e_flags value in ELF header).

File size: 23.4 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2018 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 <inttypes.h>
24#include <string>
25#include <ostream>
26#include <memory>
27#include <vector>
28#include <utility>
29#include <CLRX/utils/Utilities.h>
30#include <CLRX/utils/MemAccess.h>
31#include <CLRX/amdbin/ROCmBinaries.h>
32#include <CLRX/amdasm/Disassembler.h>
33#include <CLRX/utils/GPUId.h>
34#include "DisasmInternals.h"
35
36using namespace CLRX;
37
38ROCmDisasmInput* CLRX::getROCmDisasmInputFromBinary(const ROCmBinary& binary)
39{
40    std::unique_ptr<ROCmDisasmInput> input(new ROCmDisasmInput);
41    input->deviceType = binary.determineGPUDeviceType(input->archMinor,
42                              input->archStepping);
43   
44    const size_t regionsNum = binary.getRegionsNum();
45    input->regions.resize(regionsNum);
46    size_t codeOffset = binary.getCode()-binary.getBinaryCode();
47    // ger regions of code
48    for (size_t i = 0; i < regionsNum; i++)
49    {
50        const ROCmRegion& region = binary.getRegion(i);
51        input->regions[i] = { region.regionName, size_t(region.size),
52            size_t(region.offset - codeOffset), region.type };
53    }
54    // setup code
55    input->eflags = ULEV(binary.getHeader().e_flags);
56    input->code = binary.getCode();
57    input->codeSize = binary.getCodeSize();
58    return input.release();
59}
60
61void CLRX::dumpAMDHSAConfig(std::ostream& output, cxuint maxSgprsNum,
62             GPUArchitecture arch, const ROCmKernelConfig& config, bool amdhsaPrefix)
63{
64    // convert to native-endian
65    uint32_t amdCodeVersionMajor = ULEV(config.amdCodeVersionMajor);
66    uint32_t amdCodeVersionMinor = ULEV(config.amdCodeVersionMinor);
67    uint16_t amdMachineKind = ULEV(config.amdMachineKind);
68    uint16_t amdMachineMajor = ULEV(config.amdMachineMajor);
69    uint16_t amdMachineMinor = ULEV(config.amdMachineMinor);
70    uint16_t amdMachineStepping = ULEV(config.amdMachineStepping);
71    uint64_t kernelCodeEntryOffset = ULEV(config.kernelCodeEntryOffset);
72    uint64_t kernelCodePrefetchOffset = ULEV(config.kernelCodePrefetchOffset);
73    uint64_t kernelCodePrefetchSize = ULEV(config.kernelCodePrefetchSize);
74    uint64_t maxScrachBackingMemorySize = ULEV(config.maxScrachBackingMemorySize);
75    uint32_t computePgmRsrc1 = ULEV(config.computePgmRsrc1);
76    uint32_t computePgmRsrc2 = ULEV(config.computePgmRsrc2);
77    uint16_t enableSgprRegisterFlags = ULEV(config.enableSgprRegisterFlags);
78    uint16_t enableFeatureFlags = ULEV(config.enableFeatureFlags);
79    uint32_t workitemPrivateSegmentSize = ULEV(config.workitemPrivateSegmentSize);
80    uint32_t workgroupGroupSegmentSize = ULEV(config.workgroupGroupSegmentSize);
81    uint32_t gdsSegmentSize = ULEV(config.gdsSegmentSize);
82    uint64_t kernargSegmentSize = ULEV(config.kernargSegmentSize);
83    uint32_t workgroupFbarrierCount = ULEV(config.workgroupFbarrierCount);
84    uint16_t wavefrontSgprCount = ULEV(config.wavefrontSgprCount);
85    uint16_t workitemVgprCount = ULEV(config.workitemVgprCount);
86    uint16_t reservedVgprFirst = ULEV(config.reservedVgprFirst);
87    uint16_t reservedVgprCount = ULEV(config.reservedVgprCount);
88    uint16_t reservedSgprFirst = ULEV(config.reservedSgprFirst);
89    uint16_t reservedSgprCount = ULEV(config.reservedSgprCount);
90    uint16_t debugWavefrontPrivateSegmentOffsetSgpr =
91            ULEV(config.debugWavefrontPrivateSegmentOffsetSgpr);
92    uint16_t debugPrivateSegmentBufferSgpr = ULEV(config.debugPrivateSegmentBufferSgpr);
93    uint32_t callConvention = ULEV(config.callConvention);
94    uint64_t runtimeLoaderKernelSymbol = ULEV(config.runtimeLoaderKernelSymbol);
95   
96    size_t bufSize;
97    char buf[100];
98    const cxuint ldsShift = arch<GPUArchitecture::GCN1_1 ? 8 : 9;
99    const uint32_t pgmRsrc1 = computePgmRsrc1;
100    const uint32_t pgmRsrc2 = computePgmRsrc2;
101   
102    const cxuint dimMask = (pgmRsrc2 >> 7) & 7;
103    // print dims (hsadims for gallium): .[hsa_]dims xyz
104    if (!amdhsaPrefix)
105    {
106        strcpy(buf, "        .dims ");
107        bufSize = 14;
108    }
109    else
110    {
111        strcpy(buf, "        .hsa_dims ");
112        bufSize = 18;
113    }
114    if ((dimMask & 1) != 0)
115        buf[bufSize++] = 'x';
116    if ((dimMask & 2) != 0)
117        buf[bufSize++] = 'y';
118    if ((dimMask & 4) != 0)
119        buf[bufSize++] = 'z';
120    buf[bufSize++] = '\n';
121    output.write(buf, bufSize);
122   
123    if (!amdhsaPrefix)
124    {
125        // print in original form
126        // get sgprsnum and vgprsnum from PGMRSRC1
127        bufSize = snprintf(buf, 100, "        .sgprsnum %u\n",
128                std::min((((pgmRsrc1>>6) & 0xf)<<3)+8, maxSgprsNum));
129        output.write(buf, bufSize);
130        bufSize = snprintf(buf, 100, "        .vgprsnum %u\n", ((pgmRsrc1 & 0x3f)<<2)+4);
131        output.write(buf, bufSize);
132        if ((pgmRsrc1 & (1U<<20)) != 0)
133            output.write("        .privmode\n", 18);
134        if ((pgmRsrc1 & (1U<<22)) != 0)
135            output.write("        .debugmode\n", 19);
136        if ((pgmRsrc1 & (1U<<21)) != 0)
137            output.write("        .dx10clamp\n", 19);
138        if ((pgmRsrc1 & (1U<<23)) != 0)
139            output.write("        .ieeemode\n", 18);
140        if ((pgmRsrc2 & 0x400) != 0)
141            output.write("        .tgsize\n", 16);
142       
143        bufSize = snprintf(buf, 100, "        .floatmode 0x%02x\n", (pgmRsrc1>>12) & 0xff);
144        output.write(buf, bufSize);
145        bufSize = snprintf(buf, 100, "        .priority %u\n", (pgmRsrc1>>10) & 3);
146        output.write(buf, bufSize);
147        if (((pgmRsrc1>>24) & 0x7f) != 0)
148        {
149            bufSize = snprintf(buf, 100, "        .exceptions 0x%02x\n",
150                    (pgmRsrc1>>24) & 0x7f);
151            output.write(buf, bufSize);
152        }
153        const cxuint localSize = ((pgmRsrc2>>15) & 0x1ff) << ldsShift;
154        if (localSize!=0)
155        {
156            bufSize = snprintf(buf, 100, "        .localsize %u\n", localSize);
157            output.write(buf, bufSize);
158        }
159        bufSize = snprintf(buf, 100, "        .userdatanum %u\n", (pgmRsrc2>>1) & 0x1f);
160        output.write(buf, bufSize);
161       
162        bufSize = snprintf(buf, 100, "        .pgmrsrc1 0x%08x\n", pgmRsrc1);
163        output.write(buf, bufSize);
164        bufSize = snprintf(buf, 100, "        .pgmrsrc2 0x%08x\n", pgmRsrc2);
165        output.write(buf, bufSize);
166    }
167    else
168    {
169        // print with 'hsa_' prefix (for gallium)
170        // get sgprsnum and vgprsnum from PGMRSRC1
171        bufSize = snprintf(buf, 100, "        .hsa_sgprsnum %u\n",
172                std::min((((pgmRsrc1>>6) & 0xf)<<3)+8, maxSgprsNum));
173        output.write(buf, bufSize);
174        bufSize = snprintf(buf, 100, "        .hsa_vgprsnum %u\n", ((pgmRsrc1 & 0x3f)<<2)+4);
175        output.write(buf, bufSize);
176        if ((pgmRsrc1 & (1U<<20)) != 0)
177            output.write("        .hsa_privmode\n", 22);
178        if ((pgmRsrc1 & (1U<<22)) != 0)
179            output.write("        .hsa_debugmode\n", 23);
180        if ((pgmRsrc1 & (1U<<21)) != 0)
181            output.write("        .hsa_dx10clamp\n", 23);
182        if ((pgmRsrc1 & (1U<<23)) != 0)
183            output.write("        .hsa_ieeemode\n", 22);
184        if ((pgmRsrc2 & 0x400) != 0)
185            output.write("        .hsa_tgsize\n", 20);
186       
187        bufSize = snprintf(buf, 100, "        .hsa_floatmode 0x%02x\n",
188                    (pgmRsrc1>>12) & 0xff);
189        output.write(buf, bufSize);
190        bufSize = snprintf(buf, 100, "        .hsa_priority %u\n",
191                    (pgmRsrc1>>10) & 3);
192        output.write(buf, bufSize);
193        if (((pgmRsrc1>>24) & 0x7f) != 0)
194        {
195            bufSize = snprintf(buf, 100, "        .hsa_exceptions 0x%02x\n",
196                    (pgmRsrc1>>24) & 0x7f);
197            output.write(buf, bufSize);
198        }
199        const cxuint localSize = ((pgmRsrc2>>15) & 0x1ff) << ldsShift;
200        if (localSize!=0)
201        {
202            bufSize = snprintf(buf, 100, "        .hsa_localsize %u\n", localSize);
203            output.write(buf, bufSize);
204        }
205        bufSize = snprintf(buf, 100, "        .hsa_userdatanum %u\n", (pgmRsrc2>>1) & 0x1f);
206        output.write(buf, bufSize);
207       
208        bufSize = snprintf(buf, 100, "        .hsa_pgmrsrc1 0x%08x\n", pgmRsrc1);
209        output.write(buf, bufSize);
210        bufSize = snprintf(buf, 100, "        .hsa_pgmrsrc2 0x%08x\n", pgmRsrc2);
211        output.write(buf, bufSize);
212    }
213   
214    bufSize = snprintf(buf, 100, "        .codeversion %u, %u\n",
215                   amdCodeVersionMajor, amdCodeVersionMinor);
216    output.write(buf, bufSize);
217    bufSize = snprintf(buf, 100, "        .machine %hu, %hu, %hu, %hu\n",
218                   amdMachineKind, amdMachineMajor,
219                   amdMachineMinor, amdMachineStepping);
220    output.write(buf, bufSize);
221    bufSize = snprintf(buf, 100, "        .kernel_code_entry_offset 0x%" PRIx64 "\n",
222                       kernelCodeEntryOffset);
223    output.write(buf, bufSize);
224    if (kernelCodePrefetchOffset!=0)
225    {
226        bufSize = snprintf(buf, 100,
227                   "        .kernel_code_prefetch_offset 0x%" PRIx64 "\n",
228                           kernelCodePrefetchOffset);
229        output.write(buf, bufSize);
230    }
231    if (kernelCodePrefetchSize!=0)
232    {
233        bufSize = snprintf(buf, 100, "        .kernel_code_prefetch_size %" PRIu64 "\n",
234                           kernelCodePrefetchSize);
235        output.write(buf, bufSize);
236    }
237    if (maxScrachBackingMemorySize!=0)
238    {
239        bufSize = snprintf(buf, 100, "        .max_scratch_backing_memory %" PRIu64 "\n",
240                           maxScrachBackingMemorySize);
241        output.write(buf, bufSize);
242    }
243   
244    const uint16_t sgprFlags = enableSgprRegisterFlags;
245    // print SGPRregister flags (features)
246    if ((sgprFlags&ROCMFLAG_USE_PRIVATE_SEGMENT_BUFFER) != 0)
247        output.write("        .use_private_segment_buffer\n", 36);
248    if ((sgprFlags&ROCMFLAG_USE_DISPATCH_PTR) != 0)
249        output.write("        .use_dispatch_ptr\n", 26);
250    if ((sgprFlags&ROCMFLAG_USE_QUEUE_PTR) != 0)
251        output.write("        .use_queue_ptr\n", 23);
252    if ((sgprFlags&ROCMFLAG_USE_KERNARG_SEGMENT_PTR) != 0)
253        output.write("        .use_kernarg_segment_ptr\n", 33);
254    if ((sgprFlags&ROCMFLAG_USE_DISPATCH_ID) != 0)
255        output.write("        .use_dispatch_id\n", 25);
256    if ((sgprFlags&ROCMFLAG_USE_FLAT_SCRATCH_INIT) != 0)
257        output.write("        .use_flat_scratch_init\n", 31);
258    if ((sgprFlags&ROCMFLAG_USE_PRIVATE_SEGMENT_SIZE) != 0)
259        output.write("        .use_private_segment_size\n", 34);
260   
261    if ((sgprFlags&(7U<<ROCMFLAG_USE_GRID_WORKGROUP_COUNT_BIT)) != 0)
262    {
263        // print .use_grid_workgroup_count xyz (dimensions)
264        strcpy(buf, "        .use_grid_workgroup_count ");
265        bufSize = 34;
266        if ((sgprFlags&ROCMFLAG_USE_GRID_WORKGROUP_COUNT_X) != 0)
267            buf[bufSize++] = 'x';
268        if ((sgprFlags&ROCMFLAG_USE_GRID_WORKGROUP_COUNT_Y) != 0)
269            buf[bufSize++] = 'y';
270        if ((sgprFlags&ROCMFLAG_USE_GRID_WORKGROUP_COUNT_Z) != 0)
271            buf[bufSize++] = 'z';
272        buf[bufSize++] = '\n';
273        output.write(buf, bufSize);
274    }
275   
276    const uint16_t featureFlags = enableFeatureFlags;
277    if ((featureFlags&ROCMFLAG_USE_ORDERED_APPEND_GDS) != 0)
278        output.write("        .use_ordered_append_gds\n", 32);
279    bufSize = snprintf(buf, 100, "        .private_elem_size %u\n",
280                       2U<<((featureFlags>>ROCMFLAG_PRIVATE_ELEM_SIZE_BIT)&3));
281    output.write(buf, bufSize);
282    if ((featureFlags&ROCMFLAG_USE_PTR64) != 0)
283        output.write("        .use_ptr64\n", 19);
284    if ((featureFlags&ROCMFLAG_USE_DYNAMIC_CALL_STACK) != 0)
285        output.write("        .use_dynamic_call_stack\n", 32);
286    if ((featureFlags&ROCMFLAG_USE_DEBUG_ENABLED) != 0)
287        output.write("        .use_debug_enabled\n", 27);
288    if ((featureFlags&ROCMFLAG_USE_XNACK_ENABLED) != 0)
289        output.write("        .use_xnack_enabled\n", 27);
290   
291    if (workitemPrivateSegmentSize!=0)
292    {
293        bufSize = snprintf(buf, 100, "        .workitem_private_segment_size %u\n",
294                         workitemPrivateSegmentSize);
295        output.write(buf, bufSize);
296    }
297    if (workgroupGroupSegmentSize!=0)
298    {
299        bufSize = snprintf(buf, 100, "        .workgroup_group_segment_size %u\n",
300                         workgroupGroupSegmentSize);
301        output.write(buf, bufSize);
302    }
303    if (gdsSegmentSize!=0)
304    {
305        bufSize = snprintf(buf, 100, "        .gds_segment_size %u\n",
306                         gdsSegmentSize);
307        output.write(buf, bufSize);
308    }
309    if (kernargSegmentSize!=0)
310    {
311        bufSize = snprintf(buf, 100, "        .kernarg_segment_size %" PRIu64 "\n",
312                         kernargSegmentSize);
313        output.write(buf, bufSize);
314    }
315    if (workgroupFbarrierCount!=0)
316    {
317        bufSize = snprintf(buf, 100, "        .workgroup_fbarrier_count %u\n",
318                         workgroupFbarrierCount);
319        output.write(buf, bufSize);
320    }
321    if (wavefrontSgprCount!=0)
322    {
323        bufSize = snprintf(buf, 100, "        .wavefront_sgpr_count %hu\n",
324                         wavefrontSgprCount);
325        output.write(buf, bufSize);
326    }
327    if (workitemVgprCount!=0)
328    {
329        bufSize = snprintf(buf, 100, "        .workitem_vgpr_count %hu\n",
330                         workitemVgprCount);
331        output.write(buf, bufSize);
332    }
333    if (reservedVgprCount!=0)
334    {
335        bufSize = snprintf(buf, 100, "        .reserved_vgprs %hu, %hu\n",
336                     reservedVgprFirst, uint16_t(reservedVgprFirst+reservedVgprCount-1));
337        output.write(buf, bufSize);
338    }
339    if (reservedSgprCount!=0)
340    {
341        bufSize = snprintf(buf, 100, "        .reserved_sgprs %hu, %hu\n",
342                     reservedSgprFirst, uint16_t(reservedSgprFirst+reservedSgprCount-1));
343        output.write(buf, bufSize);
344    }
345    if (debugWavefrontPrivateSegmentOffsetSgpr!=0)
346    {
347        bufSize = snprintf(buf, 100, "        "
348                        ".debug_wavefront_private_segment_offset_sgpr %hu\n",
349                         debugWavefrontPrivateSegmentOffsetSgpr);
350        output.write(buf, bufSize);
351    }
352    if (debugPrivateSegmentBufferSgpr!=0)
353    {
354        bufSize = snprintf(buf, 100, "        .debug_private_segment_buffer_sgpr %hu\n",
355                         debugPrivateSegmentBufferSgpr);
356        output.write(buf, bufSize);
357    }
358    bufSize = snprintf(buf, 100, "        .kernarg_segment_align %u\n",
359                     1U<<(config.kernargSegmentAlignment));
360    output.write(buf, bufSize);
361    bufSize = snprintf(buf, 100, "        .group_segment_align %u\n",
362                     1U<<(config.groupSegmentAlignment));
363    output.write(buf, bufSize);
364    bufSize = snprintf(buf, 100, "        .private_segment_align %u\n",
365                     1U<<(config.privateSegmentAlignment));
366    output.write(buf, bufSize);
367    bufSize = snprintf(buf, 100, "        .wavefront_size %u\n",
368                     1U<<(config.wavefrontSize));
369    output.write(buf, bufSize);
370    bufSize = snprintf(buf, 100, "        .call_convention 0x%x\n",
371                     callConvention);
372    output.write(buf, bufSize);
373    if (runtimeLoaderKernelSymbol!=0)
374    {
375        bufSize = snprintf(buf, 100,
376                   "        .runtime_loader_kernel_symbol 0x%" PRIx64 "\n",
377                         runtimeLoaderKernelSymbol);
378        output.write(buf, bufSize);
379    }
380    // new section, control_directive, outside .config
381    output.write("    .control_directive\n", 23);
382    printDisasmData(sizeof config.controlDirective, config.controlDirective, output, true);
383}
384
385static void dumpKernelConfig(std::ostream& output, cxuint maxSgprsNum,
386             GPUArchitecture arch, const ROCmKernelConfig& config)
387{
388    output.write("    .config\n", 12);
389    dumpAMDHSAConfig(output, maxSgprsNum, arch, config);
390}
391
392// routine to disassembly code in AMD HSA form (kernel with HSA config)
393void CLRX::disassembleAMDHSACode(std::ostream& output,
394            const std::vector<ROCmDisasmRegionInput>& regions,
395            size_t codeSize, const cxbyte* code, ISADisassembler* isaDisassembler,
396            Flags flags)
397{
398    const bool doDumpData = ((flags & DISASM_DUMPDATA) != 0);
399    const bool doMetadata = ((flags & (DISASM_METADATA|DISASM_CONFIG)) != 0);
400    const bool doDumpCode = ((flags & DISASM_DUMPCODE) != 0);
401    const bool doDumpConfig = ((flags & DISASM_CONFIG) != 0);
402   
403    const size_t regionsNum = regions.size();
404    typedef std::pair<size_t, size_t> SortEntry;
405    std::unique_ptr<SortEntry[]> sorted(new SortEntry[regionsNum]);
406    for (size_t i = 0; i < regionsNum; i++)
407        sorted[i] = std::make_pair(regions[i].offset, i);
408    mapSort(sorted.get(), sorted.get() + regionsNum);
409   
410    output.write(".text\n", 6);
411    // clear labels
412    isaDisassembler->clearNumberedLabels();
413   
414    /// analyze code with collecting labels
415    for (size_t i = 0; i < regionsNum; i++)
416    {
417        const ROCmDisasmRegionInput& region = regions[sorted[i].second];
418        if ((region.type==ROCmRegionType::KERNEL ||
419             region.type==ROCmRegionType::FKERNEL) && doDumpCode)
420        {
421            // kernel code begin after HSA config
422            isaDisassembler->setInput(region.size-256, code + region.offset+256,
423                                region.offset+256);
424            isaDisassembler->analyzeBeforeDisassemble();
425        }
426        isaDisassembler->addNamedLabel(region.offset, region.regionName);
427    }
428    isaDisassembler->prepareLabelsAndRelocations();
429   
430    ISADisassembler::LabelIter curLabel;
431    ISADisassembler::NamedLabelIter curNamedLabel;
432    const auto& labels = isaDisassembler->getLabels();
433    const auto& namedLabels = isaDisassembler->getNamedLabels();
434    // real disassemble
435    size_t prevRegionPos = 0;
436    for (size_t i = 0; i < regionsNum; i++)
437    {
438        const ROCmDisasmRegionInput& region = regions[sorted[i].second];
439        // set labelIters to previous position
440        isaDisassembler->setInput(prevRegionPos, code + region.offset,
441                                region.offset, prevRegionPos);
442        curLabel = std::lower_bound(labels.begin(), labels.end(), prevRegionPos);
443        curNamedLabel = std::lower_bound(namedLabels.begin(), namedLabels.end(),
444            std::make_pair(prevRegionPos, CString()),
445                [](const std::pair<size_t,CString>& a,
446                                const std::pair<size_t, CString>& b)
447                { return a.first < b.first; });
448        // write labels to current region position
449        isaDisassembler->writeLabelsToPosition(0, curLabel, curNamedLabel);
450        isaDisassembler->flushOutput();
451       
452        size_t dataSize = codeSize - region.offset;
453        if (i+1<regionsNum)
454        {
455            // if not last region, then set size as (next_offset - this_offset)
456            const ROCmDisasmRegionInput& newRegion = regions[sorted[i+1].second];
457            dataSize = newRegion.offset - region.offset;
458        }
459        if (region.type!=ROCmRegionType::DATA)
460        {
461            if (doMetadata)
462            {
463                if (!doDumpConfig)
464                    printDisasmData(0x100, code + region.offset, output, true);
465                else    // skip, config was dumped in kernel configuration
466                    output.write(".skip 256\n", 10);
467            }
468           
469            if (doDumpCode)
470            {
471                // dump code of region
472                isaDisassembler->setInput(dataSize-256, code + region.offset+256,
473                                region.offset+256, region.offset+1);
474                isaDisassembler->setDontPrintLabels(i+1<regionsNum);
475                isaDisassembler->disassemble();
476            }
477            prevRegionPos = region.offset + dataSize + 1;
478        }
479        else if (doDumpData)
480        {
481            output.write(".global ", 8);
482            output.write(region.regionName.c_str(), region.regionName.size());
483            output.write("\n", 1);
484            printDisasmData(dataSize, code + region.offset, output, true);
485            prevRegionPos = region.offset+1;
486        }
487    }
488   
489    if (regionsNum!=0 && regions[sorted[regionsNum-1].second].type==ROCmRegionType::DATA)
490    {
491        // if last region is data then finishing dumping data
492        const ROCmDisasmRegionInput& region = regions[sorted[regionsNum-1].second];
493        // set labelIters to previous position
494        isaDisassembler->setInput(prevRegionPos, code + region.offset+region.size,
495                                region.offset+region.size, prevRegionPos);
496        curLabel = std::lower_bound(labels.begin(), labels.end(), prevRegionPos);
497        curNamedLabel = std::lower_bound(namedLabels.begin(), namedLabels.end(),
498            std::make_pair(prevRegionPos, CString()),
499                [](const std::pair<size_t,CString>& a,
500                                const std::pair<size_t, CString>& b)
501                { return a.first < b.first; });
502        // if last region is not kernel, then print labels after last region
503        isaDisassembler->writeLabelsToPosition(0, curLabel, curNamedLabel);
504        isaDisassembler->flushOutput();
505        isaDisassembler->writeLabelsToEnd(region.size, curLabel, curNamedLabel);
506        isaDisassembler->flushOutput();
507    }
508}
509
510void CLRX::disassembleROCm(std::ostream& output, const ROCmDisasmInput* rocmInput,
511           ISADisassembler* isaDisassembler, Flags flags)
512{
513    const bool doMetadata = ((flags & (DISASM_METADATA|DISASM_CONFIG)) != 0);
514    const bool doDumpConfig = ((flags & DISASM_CONFIG) != 0);
515   
516    const GPUArchitecture arch = getGPUArchitectureFromDeviceType(rocmInput->deviceType);
517    const cxuint maxSgprsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
518   
519    if (rocmInput->eflags != 0)
520    {
521        // print eflags if not zero
522        char buf[40];
523        size_t size = snprintf(buf, 40, ".eflags %u\n", rocmInput->eflags);
524        output.write(buf, size);
525    }
526   
527    {
528        // print AMD architecture version
529        char buf[40];
530        size_t size = snprintf(buf, 40, ".arch_minor %u\n", rocmInput->archMinor);
531        output.write(buf, size);
532        size = snprintf(buf, 40, ".arch_stepping %u\n", rocmInput->archStepping);
533        output.write(buf, size);
534    }
535   
536    // dump kernel config
537    for (const ROCmDisasmRegionInput& rinput: rocmInput->regions)
538        if (rinput.type != ROCmRegionType::DATA)
539        {
540            output.write(".kernel ", 8);
541            output.write(rinput.regionName.c_str(), rinput.regionName.size());
542            output.put('\n');
543            if (rinput.type == ROCmRegionType::FKERNEL)
544                output.write("    .fkernel\n", 13);
545            if (doMetadata && doDumpConfig)
546                dumpKernelConfig(output, maxSgprsNum, arch,
547                     *reinterpret_cast<const ROCmKernelConfig*>(
548                             rocmInput->code + rinput.offset));
549        }
550   
551    // disassembly code in HSA form
552    if (rocmInput->code != nullptr && rocmInput->codeSize != 0)
553        disassembleAMDHSACode(output, rocmInput->regions,
554                        rocmInput->codeSize, rocmInput->code, isaDisassembler, flags);
555}
Note: See TracBrowser for help on using the repository browser.