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

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

CLRadeonExtender: Change Copyright dates.

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