source: CLRX/CLRadeonExtender/trunk/amdasm/AsmROCmFormat.cpp @ 2603

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

CLRadeonExtender: AsmROCm: put config to code (prepareBinary). Add BINGENXX_XX enums.

File size: 50.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 <cstdio>
22#include <cstring>
23#include <string>
24#include <vector>
25#include <utility>
26#include <algorithm>
27#include <CLRX/utils/Utilities.h>
28#include <CLRX/amdasm/Assembler.h>
29#include "AsmInternals.h"
30
31using namespace CLRX;
32
33static const char* rocmPseudoOpNamesTbl[] =
34{
35    "call_convention", "codeversion", "config",
36    "control_directive", "debug_private_segment_buffer_sgpr",
37    "debug_wavefront_private_segment_offset_sgpr",
38    "debugmode", "dims", "dx10clamp",
39    "exceptions", "fkernel", "floatmode", "gds_segment_size",
40    "group_segment_align", "ieeemode", "kcode",
41    "kcodeend", "kernarg_segment_align",
42    "kernarg_segment_size", "kernel_code_entry_offset",
43    "kernel_code_prefetch_offset", "kernel_code_prefetch_size",
44    "localsize", "machine", "max_scratch_backing_memory",
45    "pgmrsrc1", "pgmrsrc2", "priority", "private_segment_align",
46    "privmode", "reserved_sgpr_count", "reserved_sgpr_first",
47    "reserved_vgpr_count", "reserved_vgpr_first",
48    "runtime_loader_kernel_symbol",
49    "scratchbuffer", "sgprsnum", "tgsize",
50    "use_debug_enabled", "use_dispatch_id",
51    "use_dispatch_ptr", "use_dynamic_call_stack",
52    "use_flat_scratch_init", "use_grid_workgroup_count",
53    "use_kernarg_segment_ptr", "use_ordered_append_gds",
54    "use_private_segment_size", "use_ptr64", "use_queue_ptr",
55    "use_private_segment_buffer", "use_xnack_enabled",
56    "userdatanum", "vgprsnum", "wavefront_sgpr_count",
57    "wavefront_size", "workitem_vgpr_count",
58    "workgroup_fbarrier_count", "workgroup_group_segment_size",
59    "workitem_private_segment_size"
60};
61
62enum
63{
64    ROCMOP_CALL_CONVENTION, ROCMOP_CODEVERSION, ROCMOP_CONFIG,
65    ROCMOP_CONTROL_DIRECTIVE, ROCMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR,
66    ROCMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR,
67    ROCMOP_DEBUGMODE, ROCMOP_DIMS, ROCMOP_DX10CLAMP,
68    ROCMOP_EXCEPTIONS, ROCMOP_FKERNEL, ROCMOP_FLOATMODE, ROCMOP_GDS_SEGMENT_SIZE,
69    ROCMOP_GROUP_SEGMENT_ALIGN, ROCMOP_IEEEMODE, ROCMOP_KCODE,
70    ROCMOP_KCODEEND, ROCMOP_KERNARG_SEGMENT_ALIGN,
71    ROCMOP_KERNARG_SEGMENT_SIZE, ROCMOP_KERNEL_CODE_ENTRY_OFFSET,
72    ROCMOP_KERNEL_CODE_PREFETCH_OFFSET, ROCMOP_KERNEL_CODE_PREFETCH_SIZE,
73    ROCMOP_LOCALSIZE, ROCMOP_MACHINE, ROCMOP_MAX_SCRATCH_BACKING_MEMORY,
74    ROCMOP_PGMRSRC1, ROCMOP_PGMRSRC2, ROCMOP_PRIORITY, ROCMOP_PRIVATE_SEGMENT_ALIGN,
75    ROCMOP_PRIVMODE, ROCMOP_RESERVED_SGPR_COUNT, ROCMOP_RESERVED_SGPR_FIRST,
76    ROCMOP_RESERVED_VGPR_COUNT, ROCMOP_RESERVED_VGPR_FIRST,
77    ROCMOP_RUNTIME_LOADER_KERNEL_SYMBOL,
78    ROCMOP_SCRATCHBUFFER, ROCMOP_SGPRSNUM, ROCMOP_TGSIZE,
79    ROCMOP_USE_DEBUG_ENABLED, ROCMOP_USE_DISPATCH_ID,
80    ROCMOP_USE_DISPATCH_PTR, ROCMOP_USE_DYNAMIC_CALL_STACK,
81    ROCMOP_USE_FLAT_SCRATCH_INIT, ROCMOP_USE_GRID_WORKGROUP_COUNT,
82    ROCMOP_USE_KERNARG_SEGMENT_PTR, ROCMOP_USE_ORDERED_APPEND_GDS,
83    ROCMOP_USE_PRIVATE_SEGMENT_SIZE, ROCMOP_USE_PTR64, ROCMOP_USE_QUEUE_PTR,
84    ROCMOP_USE_PRIVATE_SEGMENT_BUFFER, ROCMOP_USE_XNACK_ENABLED,
85    ROCMOP_USERDATANUM, ROCMOP_VGPRSNUM, ROCMOP_WAVEFRONT_SGPR_COUNT,
86    ROCMOP_WAVEFRONT_SIZE, ROCMOP_WORKITEM_VGPR_COUNT,
87    ROCMOP_WORKGROUP_FBARRIER_COUNT, ROCMOP_WORKGROUP_GROUP_SEGMENT_SIZE,
88    ROCMOP_WORKITEM_PRIVATE_SEGMENT_SIZE
89};
90
91/*
92 * ROCm format handler
93 */
94
95AsmROCmHandler::AsmROCmHandler(Assembler& assembler): AsmFormatHandler(assembler),
96             output{}, codeSection(0), commentSection(ASMSECT_NONE),
97             extraSectionCount(0)
98{
99    assembler.currentKernel = ASMKERN_GLOBAL;
100    assembler.currentSection = 0;
101    sections.push_back({ ASMKERN_GLOBAL, AsmSectionType::CODE,
102                ELFSECTID_TEXT, ".text" });
103    currentKcodeKernel = ASMKERN_GLOBAL;
104    savedSection = 0;
105}
106
107AsmROCmHandler::~AsmROCmHandler()
108{
109    for (Kernel* kernel: kernelStates)
110        delete kernel;
111}
112
113cxuint AsmROCmHandler::addKernel(const char* kernelName)
114{
115    cxuint thisKernel = output.symbols.size();
116    cxuint thisSection = sections.size();
117    output.addEmptyKernel(kernelName);
118    /// add kernel config section
119    sections.push_back({ thisKernel, AsmSectionType::CONFIG, ELFSECTID_UNDEF, nullptr });
120    kernelStates.push_back(
121        new Kernel{ thisSection, nullptr, false, ASMSECT_NONE, thisSection });
122   
123    if (assembler.currentKernel == ASMKERN_GLOBAL)
124        savedSection = assembler.currentSection;
125   
126    assembler.currentKernel = thisKernel;
127    assembler.currentSection = thisSection;
128    return thisKernel;
129}
130
131cxuint AsmROCmHandler::addSection(const char* sectionName, cxuint kernelId)
132{
133    const cxuint thisSection = sections.size();
134    Section section;
135    section.kernelId = ASMKERN_GLOBAL;  // we ignore input kernelId, we go to main
136       
137    if (::strcmp(sectionName, ".text") == 0) // code
138    {
139        if (codeSection!=ASMSECT_NONE)
140            throw AsmFormatException("Only one section '.text' can be in binary");
141        codeSection = thisSection;
142        section.type = AsmSectionType::CODE;
143        section.elfBinSectId = ELFSECTID_TEXT;
144        section.name = ".text"; // set static name (available by whole lifecycle)
145    }
146    else if (::strcmp(sectionName, ".comment") == 0) // comment
147    {
148        if (commentSection!=ASMSECT_NONE)
149            throw AsmFormatException("Only one section '.comment' can be in binary");
150        commentSection = thisSection;
151        section.type = AsmSectionType::GALLIUM_COMMENT;
152        section.elfBinSectId = ELFSECTID_COMMENT;
153        section.name = ".comment"; // set static name (available by whole lifecycle)
154    }
155    else
156    {
157        auto out = extraSectionMap.insert(std::make_pair(CString(sectionName),
158                    thisSection));
159        if (!out.second)
160            throw AsmFormatException("Section already exists");
161        section.type = AsmSectionType::EXTRA_SECTION;
162        section.elfBinSectId = extraSectionCount++;
163        /// reference entry is available and unchangeable by whole lifecycle of section map
164        section.name = out.first->first.c_str();
165    }
166    sections.push_back(section);
167   
168    assembler.currentKernel = ASMKERN_GLOBAL;
169    assembler.currentSection = thisSection;
170    return thisSection;
171}
172
173cxuint AsmROCmHandler::getSectionId(const char* sectionName) const
174{
175    if (::strcmp(sectionName, ".text") == 0) // code
176        return codeSection;
177    else if (::strcmp(sectionName, ".comment") == 0) // comment
178        return commentSection;
179    else
180    {
181        SectionMap::const_iterator it = extraSectionMap.find(sectionName);
182        if (it != extraSectionMap.end())
183            return it->second;
184    }
185    return ASMSECT_NONE;
186}
187
188void AsmROCmHandler::setCurrentKernel(cxuint kernel)
189{
190    if (kernel != ASMKERN_GLOBAL && kernel >= kernelStates.size())
191        throw AsmFormatException("KernelId out of range");
192   
193    if (assembler.currentKernel == ASMKERN_GLOBAL)
194        savedSection = assembler.currentSection;
195    else // if kernel
196        kernelStates[assembler.currentKernel]->savedSection = assembler.currentSection;
197   
198    assembler.currentKernel = kernel;
199    if (kernel != ASMKERN_GLOBAL)
200        assembler.currentSection = kernelStates[kernel]->savedSection;
201    else // default main section
202        assembler.currentSection = savedSection;
203}
204
205void AsmROCmHandler::setCurrentSection(cxuint sectionId)
206{
207    if (sectionId >= sections.size())
208        throw AsmFormatException("SectionId out of range");
209   
210    if (assembler.currentKernel == ASMKERN_GLOBAL)
211        savedSection = assembler.currentSection;
212    else // if kernel
213        kernelStates[assembler.currentKernel]->savedSection = assembler.currentSection;
214   
215    assembler.currentSection = sectionId;
216    assembler.currentKernel = sections[sectionId].kernelId;
217}
218
219
220AsmFormatHandler::SectionInfo AsmROCmHandler::getSectionInfo(cxuint sectionId) const
221{
222    if (sectionId >= sections.size())
223        throw AsmFormatException("Section doesn't exists");
224   
225    AsmFormatHandler::SectionInfo info;
226    info.type = sections[sectionId].type;
227    info.flags = 0;
228    if (info.type == AsmSectionType::CODE)
229        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE;
230    else if (info.type != AsmSectionType::CONFIG)
231        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE | ASMSECT_ABS_ADDRESSABLE;
232   
233    info.name = sections[sectionId].name;
234    return info;
235}
236
237void AsmROCmHandler::restoreKcodeCurrentAllocRegs()
238{
239    if (currentKcodeKernel != ASMKERN_GLOBAL)
240    {
241        Kernel& newKernel = *kernelStates[currentKcodeKernel];
242        assembler.isaAssembler->setAllocatedRegisters(newKernel.allocRegs,
243                            newKernel.allocRegFlags);
244    }
245}
246
247void AsmROCmHandler::saveKcodeCurrentAllocRegs()
248{
249    if (currentKcodeKernel != ASMKERN_GLOBAL)
250    {   // save other state
251        size_t regTypesNum;
252        Kernel& oldKernel = *kernelStates[currentKcodeKernel];
253        const cxuint* regs = assembler.isaAssembler->getAllocatedRegisters(
254                            regTypesNum, oldKernel.allocRegFlags);
255        std::copy(regs, regs+2, oldKernel.allocRegs);
256    }
257}
258
259
260void AsmROCmHandler::handleLabel(const CString& label)
261{
262    if (assembler.sections[assembler.currentSection].type != AsmSectionType::CODE)
263        return;
264    auto kit = assembler.kernelMap.find(label);
265    if (kit == assembler.kernelMap.end())
266        return;
267    if (!kcodeSelection.empty())
268        return; // do not change if inside kcode
269    // save other state
270    saveKcodeCurrentAllocRegs();
271    // restore this state
272    currentKcodeKernel = kit->second;
273    restoreKcodeCurrentAllocRegs();
274}
275
276void AsmROCmHandler::Kernel::initializeKernelConfig()
277{
278    if (!config)
279    {
280        config.reset(new AsmROCmKernelConfig{});
281        ::memset(config.get(), 0, sizeof(AsmROCmKernelConfig));
282        config->amdCodeVersionMajor = BINGEN_DEFAULT;
283        config->amdCodeVersionMinor = BINGEN_DEFAULT;
284    }
285}
286
287namespace CLRX
288{
289
290bool AsmROCmPseudoOps::checkPseudoOpName(const CString& string)
291{
292    if (string.empty() || string[0] != '.')
293        return false;
294    const size_t pseudoOp = binaryFind(rocmPseudoOpNamesTbl, rocmPseudoOpNamesTbl +
295                sizeof(rocmPseudoOpNamesTbl)/sizeof(char*), string.c_str()+1,
296               CStringLess()) - rocmPseudoOpNamesTbl;
297    return pseudoOp < sizeof(rocmPseudoOpNamesTbl)/sizeof(char*);
298}
299   
300void AsmROCmPseudoOps::doConfig(AsmROCmHandler& handler, const char* pseudoOpPlace,
301                  const char* linePtr)
302{
303    Assembler& asmr = handler.assembler;
304    const char* end = asmr.line + asmr.lineSize;
305    if (asmr.currentKernel==ASMKERN_GLOBAL)
306    {
307        asmr.printError(pseudoOpPlace, "Kernel config can be defined only inside kernel");
308        return;
309    }
310   
311    if (handler.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
312    {
313        asmr.printError(pseudoOpPlace, "Configuration outside kernel definition");
314        return;
315    }
316    skipSpacesToEnd(linePtr, end);
317    if (!checkGarbagesAtEnd(asmr, linePtr))
318        return;
319    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
320}
321
322void AsmROCmPseudoOps::doControlDirective(AsmROCmHandler& handler,
323              const char* pseudoOpPlace, const char* linePtr)
324{
325    Assembler& asmr = handler.assembler;
326    if (asmr.currentKernel==ASMKERN_GLOBAL)
327    {
328        asmr.printError(pseudoOpPlace, "Kernel control directive can be defined "
329                    "only inside kernel");
330        return;
331    }
332    if (!checkGarbagesAtEnd(asmr, linePtr))
333        return;
334   
335    AsmROCmHandler::Kernel& kernel = *handler.kernelStates[asmr.currentKernel];
336    if (kernel.ctrlDirSection == ASMSECT_NONE)
337    {
338        cxuint thisSection = handler.sections.size();
339        handler.sections.push_back({ asmr.currentKernel,
340            AsmSectionType::ROCM_CONFIG_CTRL_DIRECTIVE,
341            ELFSECTID_UNDEF, nullptr });
342        kernel.ctrlDirSection = thisSection;
343    }
344    asmr.goToSection(pseudoOpPlace, kernel.ctrlDirSection);
345    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
346}
347
348void AsmROCmPseudoOps::doFKernel(AsmROCmHandler& handler, const char* pseudoOpPlace,
349                      const char* linePtr)
350{
351    Assembler& asmr = handler.assembler;
352    if (asmr.currentKernel==ASMKERN_GLOBAL)
353    {
354        asmr.printError(pseudoOpPlace, ".fkernel can be only inside kernel");
355        return;
356    }
357    if (!checkGarbagesAtEnd(asmr, linePtr))
358        return;
359    handler.kernelStates[asmr.currentKernel]->isFKernel = true;
360}
361
362void AsmROCmPseudoOps::setConfigValue(AsmROCmHandler& handler, const char* pseudoOpPlace,
363                  const char* linePtr, ROCmConfigValueTarget target)
364{
365    Assembler& asmr = handler.assembler;
366    const char* end = asmr.line + asmr.lineSize;
367   
368    if (asmr.currentKernel==ASMKERN_GLOBAL ||
369        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
370    {
371        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
372        return;
373    }
374   
375    skipSpacesToEnd(linePtr, end);
376    const char* valuePlace = linePtr;
377    uint64_t value = BINGEN64_NOTSUPPLIED;
378    bool good = getAbsoluteValueArg(asmr, value, linePtr, true);
379    /* ranges checking */
380    if (good)
381    {
382        switch(target)
383        {
384            case ROCMCVAL_SGPRSNUM:
385            {
386                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
387                            asmr.deviceType);
388                cxuint maxSGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
389                if (value > maxSGPRsNum)
390                {
391                    char buf[64];
392                    snprintf(buf, 64, "Used SGPRs number out of range (0-%u)", maxSGPRsNum);
393                    asmr.printError(valuePlace, buf);
394                    good = false;
395                }
396                break;
397            }
398            case ROCMCVAL_VGPRSNUM:
399            {
400                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
401                            asmr.deviceType);
402                cxuint maxVGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_VGPR, 0);
403                if (value > maxVGPRsNum)
404                {
405                    char buf[64];
406                    snprintf(buf, 64, "Used VGPRs number out of range (0-%u)", maxVGPRsNum);
407                    asmr.printError(valuePlace, buf);
408                    good = false;
409                }
410                break;
411            }
412            case ROCMCVAL_EXCEPTIONS:
413                asmr.printWarningForRange(7, value,
414                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
415                value &= 0x7f;
416                break;
417            case ROCMCVAL_FLOATMODE:
418                asmr.printWarningForRange(8, value,
419                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
420                value &= 0xff;
421                break;
422            case ROCMCVAL_PRIORITY:
423                asmr.printWarningForRange(2, value,
424                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
425                value &= 3;
426                break;
427            case ROCMCVAL_LOCALSIZE:
428            {
429                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
430                            asmr.deviceType);
431                const cxuint maxLocalSize = getGPUMaxLocalSize(arch);
432                if (value > maxLocalSize)
433                {
434                    char buf[64];
435                    snprintf(buf, 64, "LocalSize out of range (0-%u)", maxLocalSize);
436                    asmr.printError(valuePlace, buf);
437                    good = false;
438                }
439                break;
440            }
441            case ROCMCVAL_USERDATANUM:
442                if (value > 16)
443                {
444                    asmr.printError(valuePlace, "UserDataNum out of range (0-16)");
445                    good = false;
446                }
447                break;
448            default:
449                break;
450        }
451    }
452    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
453        return;
454   
455    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
456    AsmROCmKernelConfig& config = *(handler.kernelStates[asmr.currentKernel]->config);
457    // set value
458    switch(target)
459    {
460        case ROCMCVAL_SGPRSNUM:
461            config.usedSGPRsNum = value;
462            break;
463        case ROCMCVAL_VGPRSNUM:
464            config.usedVGPRsNum = value;
465            break;
466        case ROCMCVAL_PGMRSRC1:
467            config.computePgmRsrc1 = value;
468            break;
469        case ROCMCVAL_PGMRSRC2:
470            config.computePgmRsrc2 = value;
471            break;
472        case ROCMCVAL_FLOATMODE:
473            config.floatMode = value;
474            break;
475        case ROCMCVAL_LOCALSIZE:
476            config.localSize = value;
477            break;
478        case ROCMCVAL_SCRATCHBUFFER:
479            config.scratchBufferSize = value;
480            break;
481        case ROCMCVAL_PRIORITY:
482            config.priority = value;
483            break;
484        case ROCMCVAL_USERDATANUM:
485            config.userDataNum = value;
486            break;
487        case ROCMCVAL_EXCEPTIONS:
488            config.exceptions = value;
489            break;
490        case ROCMCVAL_KERNEL_CODE_ENTRY_OFFSET:
491            config.kernelCodeEntryOffset = value;
492            break;
493        case ROCMCVAL_KERNEL_CODE_PREFETCH_OFFSET:
494            config.kernelCodePrefetchOffset = value;
495            break;
496        case ROCMCVAL_KERNEL_CODE_PREFETCH_SIZE:
497            config.kernelCodePrefetchSize = value;
498            break;
499        case ROCMCVAL_MAX_SCRATCH_BACKING_MEMORY:
500            config.maxScrachBackingMemorySize = value;
501            break;
502        case ROCMCVAL_WORKITEM_PRIVATE_SEGMENT_SIZE:
503            config.workitemPrivateSegmentSize = value;
504            break;
505        case ROCMCVAL_WORKGROUP_GROUP_SEGMENT_SIZE:
506            config.workgroupGroupSegmentSize = value;
507            break;
508        case ROCMCVAL_GDS_SEGMENT_SIZE:
509            config.gdsSegmentSize = value;
510            break;
511        case ROCMCVAL_KERNARG_SEGMENT_SIZE:
512            config.kernargSegmentSize = value;
513            break;
514        case ROCMCVAL_WORKGROUP_FBARRIER_COUNT:
515            config.workgroupFbarrierCount = value;
516            break;
517        case ROCMCVAL_WAVEFRONT_SGPR_COUNT:
518            config.wavefrontSgprCount = value;
519            break;
520        case ROCMCVAL_WORKITEM_VGPR_COUNT:
521            config.workitemVgprCount = value;
522            break;
523        case ROCMCVAL_RESERVED_VGPR_FIRST:
524            config.reservedVgprFirst = value;
525            break;
526        case ROCMCVAL_RESERVED_VGPR_COUNT:
527            config.reservedVgprCount = value;
528            break;
529        case ROCMCVAL_RESERVED_SGPR_FIRST:
530            config.reservedSgprFirst = value;
531            break;
532        case ROCMCVAL_RESERVED_SGPR_COUNT:
533            config.reservedSgprCount = value;
534            break;
535        case ROCMCVAL_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR:
536            config.debugWavefrontPrivateSegmentOffsetSgpr = value;
537            break;
538        case ROCMCVAL_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR:
539            config.debugPrivateSegmentBufferSgpr = value;
540            break;
541        case ROCMCVAL_KERNARG_SEGMENT_ALIGN:
542            config.kernargSegmentAlignment = value;
543            break;
544        case ROCMCVAL_GROUP_SEGMENT_ALIGN:
545            config.groupSegmentAlignment = value;
546            break;
547        case ROCMCVAL_PRIVATE_SEGMENT_ALIGN:
548            config.privateSegmentAlignment = value;
549            break;
550        case ROCMCVAL_WAVEFRONT_SIZE:
551            config.wavefrontSize = value;
552            break;
553        case ROCMCVAL_CALL_CONVENTION:
554            config.callConvention = value;
555            break;
556        case ROCMCVAL_RUNTIME_LOADER_KERNEL_SYMBOL:
557            config.runtimeLoaderKernelSymbol = value;
558            break;
559        default:
560            break;
561    }
562}
563
564void AsmROCmPseudoOps::setConfigBoolValue(AsmROCmHandler& handler,
565          const char* pseudoOpPlace, const char* linePtr, ROCmConfigValueTarget target)
566{
567    Assembler& asmr = handler.assembler;
568    const char* end = asmr.line + asmr.lineSize;
569   
570    if (asmr.currentKernel==ASMKERN_GLOBAL ||
571        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
572    {
573        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
574        return;
575    }
576   
577    skipSpacesToEnd(linePtr, end);
578    if (!checkGarbagesAtEnd(asmr, linePtr))
579        return;
580   
581    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
582    AsmROCmKernelConfig& config = *(handler.kernelStates[asmr.currentKernel]->config);
583   
584    switch(target)
585    {
586        case ROCMCVAL_PRIVMODE:
587            config.privilegedMode = true;
588            break;
589        case ROCMCVAL_DEBUGMODE:
590            config.debugMode = true;
591            break;
592        case ROCMCVAL_DX10CLAMP:
593            config.dx10Clamp = true;
594            break;
595        case ROCMCVAL_IEEEMODE:
596            config.ieeeMode = true;
597            break;
598        case ROCMCVAL_TGSIZE:
599            config.tgSize = true;
600            break;
601        case ROCMCVAL_USE_PRIVATE_SEGMENT_BUFFER:
602            config.enableSpgrRegisterFlags |= 1;
603            break;
604        case ROCMCVAL_USE_DISPATCH_PTR:
605            config.enableSpgrRegisterFlags |= 2;
606            break;
607        case ROCMCVAL_USE_QUEUE_PTR:
608            config.enableSpgrRegisterFlags |= 4;
609            break;
610        case ROCMCVAL_USE_KERNARG_SEGMENT_PTR:
611            config.enableSpgrRegisterFlags |= 8;
612            break;
613        case ROCMCVAL_USE_DISPATCH_ID:
614            config.enableSpgrRegisterFlags |= 16;
615            break;
616        case ROCMCVAL_USE_FLAT_SCRATCH_INIT:
617            config.enableSpgrRegisterFlags |= 32;
618            break;
619        case ROCMCVAL_USE_PRIVATE_SEGMENT_SIZE:
620            config.enableSpgrRegisterFlags |= 64;
621            break;
622        case ROCMCVAL_USE_ORDERED_APPEND_GDS:
623            config.enableFeatureFlags |= 1;
624            break;
625        case ROCMCVAL_USE_PTR64:
626            config.enableFeatureFlags |= 8;
627            break;
628        case ROCMCVAL_USE_DYNAMIC_CALL_STACK:
629            config.enableFeatureFlags |= 16;
630            break;
631        case ROCMCVAL_USE_DEBUG_ENABLED:
632            config.enableFeatureFlags |= 32;
633            break;
634        case ROCMCVAL_USE_XNACK_ENABLED:
635            config.enableFeatureFlags |= 64;
636            break;
637        default:
638            break;
639    }
640}
641
642void AsmROCmPseudoOps::setDimensions(AsmROCmHandler& handler, const char* pseudoOpPlace,
643                  const char* linePtr)
644{
645    Assembler& asmr = handler.assembler;
646    if (asmr.currentKernel==ASMKERN_GLOBAL ||
647        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
648    {
649        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
650        return;
651    }
652    cxuint dimMask = 0;
653    if (!parseDimensions(asmr, linePtr, dimMask))
654        return;
655    if (!checkGarbagesAtEnd(asmr, linePtr))
656        return;
657    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
658    handler.kernelStates[asmr.currentKernel]->config->dimMask = dimMask;
659}
660
661void AsmROCmPseudoOps::setMachine(AsmROCmHandler& handler, const char* pseudoOpPlace,
662                      const char* linePtr)
663{
664    Assembler& asmr = handler.assembler;
665    const char* end = asmr.line + asmr.lineSize;
666    if (asmr.currentKernel==ASMKERN_GLOBAL ||
667        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
668    {
669        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
670        return;
671    }
672   
673    skipSpacesToEnd(linePtr, end);
674    uint64_t kindValue = BINGEN_NOTSUPPLIED;
675    uint64_t majorValue = BINGEN_NOTSUPPLIED;
676    uint64_t minorValue = BINGEN_NOTSUPPLIED;
677    uint64_t steppingValue = BINGEN_NOTSUPPLIED;
678    bool good = getAbsoluteValueArg(asmr, kindValue, linePtr, true);
679    if (!skipRequiredComma(asmr, linePtr))
680        return;
681    good &= getAbsoluteValueArg(asmr, majorValue, linePtr, true);
682    if (!skipRequiredComma(asmr, linePtr))
683        return;
684    good &= getAbsoluteValueArg(asmr, minorValue, linePtr, true);
685    if (!skipRequiredComma(asmr, linePtr))
686        return;
687    good &= getAbsoluteValueArg(asmr, steppingValue, linePtr, true);
688   
689    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
690        return;
691   
692    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
693    AsmROCmKernelConfig* config = handler.kernelStates[asmr.currentKernel]->config.get();
694    config->amdMachineKind = kindValue;
695    config->amdMachineMajor = majorValue;
696    config->amdMachineMinor = minorValue;
697    config->amdMachineStepping = steppingValue;
698}
699
700void AsmROCmPseudoOps::setCodeVersion(AsmROCmHandler& handler, const char* pseudoOpPlace,
701                  const char* linePtr)
702{
703    Assembler& asmr = handler.assembler;
704    const char* end = asmr.line + asmr.lineSize;
705    if (asmr.currentKernel==ASMKERN_GLOBAL ||
706        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
707    {
708        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
709        return;
710    }
711   
712    skipSpacesToEnd(linePtr, end);
713    uint64_t majorValue = BINGEN_NOTSUPPLIED;
714    uint64_t minorValue = BINGEN_NOTSUPPLIED;
715    bool good = getAbsoluteValueArg(asmr, majorValue, linePtr, true);
716    if (!skipRequiredComma(asmr, linePtr))
717        return;
718    good &= getAbsoluteValueArg(asmr, minorValue, linePtr, true);
719   
720    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
721        return;
722   
723    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
724    AsmROCmKernelConfig* config = handler.kernelStates[asmr.currentKernel]->config.get();
725    config->amdCodeVersionMajor = majorValue;
726    config->amdCodeVersionMinor = minorValue;
727}
728
729void AsmROCmPseudoOps::setUseGridWorkGroupCount(AsmROCmHandler& handler,
730                   const char* pseudoOpPlace, const char* linePtr)
731{
732    Assembler& asmr = handler.assembler;
733    if (asmr.currentKernel==ASMKERN_GLOBAL ||
734        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
735    {
736        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
737        return;
738    }
739    cxuint dimMask = 0;
740    if (!parseDimensions(asmr, linePtr, dimMask))
741        return;
742    if (!checkGarbagesAtEnd(asmr, linePtr))
743        return;
744    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
745    uint16_t& flags = handler.kernelStates[asmr.currentKernel]->config->
746                enableSpgrRegisterFlags;
747    flags = (flags & ~(7<<7)) | dimMask<<7;
748}
749
750void AsmROCmPseudoOps::updateKCodeSel(AsmROCmHandler& handler,
751                  const std::vector<cxuint>& oldset)
752{
753    Assembler& asmr = handler.assembler;
754    // old elements - join current regstate with all them
755    size_t regTypesNum;
756    for (auto it = oldset.begin(); it != oldset.end(); ++it)
757    {
758        Flags curAllocRegFlags;
759        const cxuint* curAllocRegs = asmr.isaAssembler->getAllocatedRegisters(regTypesNum,
760                               curAllocRegFlags);
761        cxuint newAllocRegs[2];
762        AsmROCmHandler::Kernel& kernel = *(handler.kernelStates[*it]);
763        newAllocRegs[0] = std::max(curAllocRegs[0], kernel.allocRegs[0]);
764        newAllocRegs[1] = std::max(curAllocRegs[1], kernel.allocRegs[1]);
765        kernel.allocRegFlags |= curAllocRegFlags;
766        std::copy(newAllocRegs, newAllocRegs+2, kernel.allocRegs);
767    }
768    asmr.isaAssembler->setAllocatedRegisters();
769}
770
771void AsmROCmPseudoOps::doKCode(AsmROCmHandler& handler, const char* pseudoOpPlace,
772                  const char* linePtr)
773{
774    Assembler& asmr = handler.assembler;
775    const char* end = asmr.line + asmr.lineSize;
776    bool good = true;
777    skipSpacesToEnd(linePtr, end);
778    if (linePtr==end)
779        return;
780    std::unordered_set<cxuint> newSel(handler.kcodeSelection.begin(),
781                          handler.kcodeSelection.end());
782    do {
783        CString kname;
784        const char* knamePlace = linePtr;
785        skipSpacesToEnd(linePtr, end);
786        bool removeKernel = false;
787        if (linePtr!=end && *linePtr=='-')
788        {   // '-' - remove this kernel from current kernel selection
789            removeKernel = true;
790            linePtr++;
791        }
792        else if (linePtr!=end && *linePtr=='+')
793        {
794            linePtr++;
795            skipSpacesToEnd(linePtr, end);
796            if (linePtr==end)
797            {   // add all kernels
798                for (cxuint k = 0; k < handler.kernelStates.size(); k++)
799                    newSel.insert(k);
800                break;
801            }
802        }
803       
804        if (!getNameArg(asmr, kname, linePtr, "kernel"))
805        { good = false; continue; }
806        auto kit = asmr.kernelMap.find(kname);
807        if (kit == asmr.kernelMap.end())
808        {
809            asmr.printError(knamePlace, "Kernel not found");
810            continue;
811        }
812        if (!removeKernel)
813            newSel.insert(kit->second);
814        else // remove kernel
815            newSel.erase(kit->second);
816    } while (skipCommaForMultipleArgs(asmr, linePtr));
817   
818    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
819        return;
820   
821    if (handler.sections[asmr.currentSection].type != AsmSectionType::CODE)
822    {
823        asmr.printError(pseudoOpPlace, "KCode outside code");
824        return;
825    }
826    if (handler.kcodeSelStack.empty())
827        handler.saveKcodeCurrentAllocRegs();
828    // push to stack
829    handler.kcodeSelStack.push(handler.kcodeSelection);
830    // set current sel
831    handler.kcodeSelection.assign(newSel.begin(), newSel.end());
832   
833    std::sort(handler.kcodeSelection.begin(), handler.kcodeSelection.end());
834    updateKCodeSel(handler, handler.kcodeSelStack.top());
835}
836
837void AsmROCmPseudoOps::doKCodeEnd(AsmROCmHandler& handler, const char* pseudoOpPlace,
838                  const char* linePtr)
839{
840    Assembler& asmr = handler.assembler;
841    if (handler.sections[asmr.currentSection].type != AsmSectionType::CODE)
842    {
843        asmr.printError(pseudoOpPlace, "KCodeEnd outside code");
844        return;
845    }
846    if (handler.kcodeSelStack.empty())
847    {
848        asmr.printError(pseudoOpPlace, "'.kcodeend' without '.kcode'");
849        return;
850    }
851    updateKCodeSel(handler, handler.kcodeSelection);
852    handler.kcodeSelection = handler.kcodeSelStack.top();
853    handler.kcodeSelStack.pop();
854    if (handler.kcodeSelStack.empty())
855        handler.restoreKcodeCurrentAllocRegs();
856}
857
858}
859
860bool AsmROCmHandler::parsePseudoOp(const CString& firstName, const char* stmtPlace,
861               const char* linePtr)
862{
863    const size_t pseudoOp = binaryFind(rocmPseudoOpNamesTbl, rocmPseudoOpNamesTbl +
864                    sizeof(rocmPseudoOpNamesTbl)/sizeof(char*), firstName.c_str()+1,
865                   CStringLess()) - rocmPseudoOpNamesTbl;
866   
867    switch(pseudoOp)
868    {
869        case ROCMOP_CALL_CONVENTION:
870            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
871                             ROCMCVAL_CALL_CONVENTION);
872            break;
873        case ROCMOP_CODEVERSION:
874            AsmROCmPseudoOps::setCodeVersion(*this, stmtPlace, linePtr);
875            break;
876        case ROCMOP_CONFIG:
877            AsmROCmPseudoOps::doConfig(*this, stmtPlace, linePtr);
878            break;
879        case ROCMOP_CONTROL_DIRECTIVE:
880            AsmROCmPseudoOps::doControlDirective(*this, stmtPlace, linePtr);
881            break;
882        case ROCMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR:
883            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
884                             ROCMCVAL_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR);
885            break;
886        case ROCMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR:
887            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
888                         ROCMCVAL_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR);
889            break;
890        case ROCMOP_DEBUGMODE:
891            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
892                             ROCMCVAL_DEBUGMODE);
893            break;
894        case ROCMOP_DIMS:
895            AsmROCmPseudoOps::setDimensions(*this, stmtPlace, linePtr);
896            break;
897        case ROCMOP_DX10CLAMP:
898            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
899                             ROCMCVAL_DX10CLAMP);
900            break;
901        case ROCMOP_EXCEPTIONS:
902            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
903                             ROCMCVAL_EXCEPTIONS);
904            break;
905        case ROCMOP_FKERNEL:
906            AsmROCmPseudoOps::doFKernel(*this, stmtPlace, linePtr);
907            break;
908        case ROCMOP_FLOATMODE:
909            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
910                             ROCMCVAL_FLOATMODE);
911            break;
912        case ROCMOP_GDS_SEGMENT_SIZE:
913            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
914                             ROCMCVAL_GDS_SEGMENT_SIZE);
915            break;
916        case ROCMOP_GROUP_SEGMENT_ALIGN:
917            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
918                             ROCMCVAL_GROUP_SEGMENT_ALIGN);
919            break;
920        case ROCMOP_IEEEMODE:
921            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
922                             ROCMCVAL_IEEEMODE);
923            break;
924        case ROCMOP_KCODE:
925            AsmROCmPseudoOps::doKCode(*this, stmtPlace, linePtr);
926            break;
927        case ROCMOP_KCODEEND:
928            AsmROCmPseudoOps::doKCodeEnd(*this, stmtPlace, linePtr);
929            break;
930        case ROCMOP_KERNARG_SEGMENT_ALIGN:
931            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
932                             ROCMCVAL_KERNARG_SEGMENT_ALIGN);
933            break;
934        case ROCMOP_KERNARG_SEGMENT_SIZE:
935            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
936                             ROCMCVAL_KERNARG_SEGMENT_SIZE);
937            break;
938        case ROCMOP_KERNEL_CODE_ENTRY_OFFSET:
939            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
940                             ROCMCVAL_KERNEL_CODE_ENTRY_OFFSET);
941            break;
942        case ROCMOP_KERNEL_CODE_PREFETCH_OFFSET:
943            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
944                             ROCMCVAL_KERNEL_CODE_PREFETCH_OFFSET);
945            break;
946        case ROCMOP_KERNEL_CODE_PREFETCH_SIZE:
947            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
948                             ROCMCVAL_KERNEL_CODE_PREFETCH_SIZE);
949            break;
950        case ROCMOP_LOCALSIZE:
951            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
952                             ROCMCVAL_LOCALSIZE);
953            break;
954        case ROCMOP_MACHINE:
955            AsmROCmPseudoOps::setMachine(*this, stmtPlace, linePtr);
956            break;
957        case ROCMOP_MAX_SCRATCH_BACKING_MEMORY:
958            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
959                             ROCMCVAL_MAX_SCRATCH_BACKING_MEMORY);
960            break;
961        case ROCMOP_PGMRSRC1:
962            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PGMRSRC1);
963            break;
964        case ROCMOP_PGMRSRC2:
965            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PGMRSRC2);
966            break;
967        case ROCMOP_PRIORITY:
968            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PRIORITY);
969            break;
970        case ROCMOP_PRIVATE_SEGMENT_ALIGN:
971            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
972                             ROCMCVAL_PRIVATE_SEGMENT_ALIGN);
973            break;
974        case ROCMOP_PRIVMODE:
975            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
976                             ROCMCVAL_PRIVMODE);
977            break;
978        case ROCMOP_RESERVED_SGPR_COUNT:
979            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
980                             ROCMCVAL_RESERVED_SGPR_COUNT);
981            break;
982        case ROCMOP_RESERVED_SGPR_FIRST:
983            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
984                             ROCMCVAL_RESERVED_SGPR_FIRST);
985            break;
986        case ROCMOP_RESERVED_VGPR_COUNT:
987            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
988                             ROCMCVAL_RESERVED_VGPR_COUNT);
989            break;
990        case ROCMOP_RESERVED_VGPR_FIRST:
991            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
992                             ROCMCVAL_RESERVED_VGPR_FIRST);
993            break;
994        case ROCMOP_RUNTIME_LOADER_KERNEL_SYMBOL:
995            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
996                             ROCMCVAL_RUNTIME_LOADER_KERNEL_SYMBOL);
997            break;
998        case ROCMOP_SCRATCHBUFFER:
999            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1000                             ROCMCVAL_SCRATCHBUFFER);
1001            break;
1002        case ROCMOP_SGPRSNUM:
1003            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1004                             ROCMCVAL_SGPRSNUM);
1005            break;
1006        case ROCMOP_TGSIZE:
1007            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1008                             ROCMCVAL_TGSIZE);
1009            break;
1010        case ROCMOP_USE_DEBUG_ENABLED:
1011            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1012                             ROCMCVAL_USE_DEBUG_ENABLED);
1013            break;
1014        case ROCMOP_USE_DISPATCH_ID:
1015            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1016                             ROCMCVAL_USE_DISPATCH_ID);
1017            break;
1018        case ROCMOP_USE_DISPATCH_PTR:
1019            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1020                             ROCMCVAL_USE_DISPATCH_PTR);
1021            break;
1022        case ROCMOP_USE_DYNAMIC_CALL_STACK:
1023            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1024                             ROCMCVAL_USE_DYNAMIC_CALL_STACK);
1025            break;
1026        case ROCMOP_USE_FLAT_SCRATCH_INIT:
1027            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1028                             ROCMCVAL_USE_FLAT_SCRATCH_INIT);
1029            break;
1030        case ROCMOP_USE_GRID_WORKGROUP_COUNT:
1031            AsmROCmPseudoOps::setUseGridWorkGroupCount(*this, stmtPlace, linePtr);
1032            break;
1033        case ROCMOP_USE_KERNARG_SEGMENT_PTR:
1034            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1035                             ROCMCVAL_USE_KERNARG_SEGMENT_PTR);
1036            break;
1037        case ROCMOP_USE_ORDERED_APPEND_GDS:
1038            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1039                             ROCMCVAL_USE_ORDERED_APPEND_GDS);
1040            break;
1041        case ROCMOP_USE_PRIVATE_SEGMENT_SIZE:
1042            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1043                             ROCMCVAL_USE_PRIVATE_SEGMENT_SIZE);
1044            break;
1045        case ROCMOP_USE_PTR64:
1046            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1047                             ROCMCVAL_USE_PTR64);
1048            break;
1049        case ROCMOP_USE_QUEUE_PTR:
1050            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1051                             ROCMCVAL_USE_QUEUE_PTR);
1052            break;
1053        case ROCMOP_USE_PRIVATE_SEGMENT_BUFFER:
1054            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1055                             ROCMCVAL_USE_PRIVATE_SEGMENT_BUFFER);
1056            break;
1057        case ROCMOP_USE_XNACK_ENABLED:
1058            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1059                             ROCMCVAL_USE_XNACK_ENABLED);
1060            break;
1061        case ROCMOP_USERDATANUM:
1062            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1063                             ROCMCVAL_USERDATANUM);
1064            break;
1065        case ROCMOP_VGPRSNUM:
1066            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_VGPRSNUM);
1067            break;
1068        case ROCMOP_WAVEFRONT_SGPR_COUNT:
1069            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1070                             ROCMCVAL_WAVEFRONT_SGPR_COUNT);
1071            break;
1072        case ROCMOP_WAVEFRONT_SIZE:
1073            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1074                             ROCMCVAL_WAVEFRONT_SIZE);
1075            break;
1076        case ROCMOP_WORKITEM_VGPR_COUNT:
1077            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1078                             ROCMCVAL_WORKITEM_VGPR_COUNT);
1079            break;
1080        case ROCMOP_WORKGROUP_FBARRIER_COUNT:
1081            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1082                             ROCMCVAL_WORKGROUP_FBARRIER_COUNT);
1083            break;
1084        case ROCMOP_WORKGROUP_GROUP_SEGMENT_SIZE:
1085            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1086                             ROCMCVAL_WORKGROUP_GROUP_SEGMENT_SIZE);
1087            break;
1088        case ROCMOP_WORKITEM_PRIVATE_SEGMENT_SIZE:
1089            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1090                             ROCMCVAL_WORKITEM_PRIVATE_SEGMENT_SIZE);
1091            break;
1092        default:
1093            return false;
1094    }
1095    return true;
1096}
1097
1098bool AsmROCmHandler::prepareBinary()
1099{
1100    bool good = true;
1101    size_t sectionsNum = sections.size();
1102    size_t kernelsNum = kernelStates.size();
1103    output.deviceType = assembler.getDeviceType();
1104   
1105    if (assembler.isaAssembler!=nullptr)
1106    {   // make last kernel registers pool updates
1107        if (kcodeSelStack.empty())
1108            saveKcodeCurrentAllocRegs();
1109        else
1110            while (!kcodeSelStack.empty())
1111            {   // pop from kcode stack and apply changes
1112                AsmROCmPseudoOps::updateKCodeSel(*this, kcodeSelection);
1113                kcodeSelection = kcodeSelStack.top();
1114                kcodeSelStack.pop();
1115            }
1116    }
1117   
1118    for (size_t i = 0; i < sectionsNum; i++)
1119    {
1120        const AsmSection& asmSection = assembler.sections[i];
1121        const Section& section = sections[i];
1122        const size_t sectionSize = asmSection.getSize();
1123        const cxbyte* sectionData = (!asmSection.content.empty()) ?
1124                asmSection.content.data() : (const cxbyte*)"";
1125        switch(asmSection.type)
1126        {
1127            case AsmSectionType::CODE:
1128                output.codeSize = sectionSize;
1129                output.code = sectionData;
1130                break;
1131            case AsmSectionType::EXTRA_PROGBITS:
1132            case AsmSectionType::EXTRA_NOTE:
1133            case AsmSectionType::EXTRA_NOBITS:
1134            case AsmSectionType::EXTRA_SECTION:
1135            {
1136                uint32_t elfSectType =
1137                       (asmSection.type==AsmSectionType::EXTRA_NOTE) ? SHT_NOTE :
1138                       (asmSection.type==AsmSectionType::EXTRA_NOBITS) ? SHT_NOBITS :
1139                             SHT_PROGBITS;
1140                uint32_t elfSectFlags = 
1141                    ((asmSection.flags&ASMELFSECT_ALLOCATABLE) ? SHF_ALLOC : 0) |
1142                    ((asmSection.flags&ASMELFSECT_WRITEABLE) ? SHF_WRITE : 0) |
1143                    ((asmSection.flags&ASMELFSECT_EXECUTABLE) ? SHF_EXECINSTR : 0);
1144                output.extraSections.push_back({section.name, sectionSize, sectionData,
1145                    asmSection.alignment!=0?asmSection.alignment:1, elfSectType,
1146                    elfSectFlags, ELFSECTID_NULL, 0, 0 });
1147                break;
1148            }
1149            case AsmSectionType::ROCM_CONFIG_CTRL_DIRECTIVE:
1150                if (sectionSize != 128)
1151                    assembler.printError(AsmSourcePos(),
1152                         (std::string("Section '.control_directive' for kernel '")+
1153                          assembler.kernels[section.kernelId].name+
1154                          "' have wrong size").c_str());
1155                break;
1156            case AsmSectionType::ROCM_COMMENT:
1157                output.commentSize = sectionSize;
1158                output.comment = (const char*)sectionData;
1159                break;
1160            default:
1161                break;
1162        }
1163    }
1164   
1165    GPUArchitecture arch = getGPUArchitectureFromDeviceType(assembler.deviceType);
1166    // set up number of the allocated SGPRs and VGPRs for kernel
1167    cxuint maxSGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
1168    // prepare kernels configuration
1169    for (size_t i = 0; i < kernelStates.size(); i++)
1170    {
1171        const Kernel& kernel = *kernelStates[i];
1172        if (kernel.config.get() == nullptr)
1173            continue;
1174        const CString& kernelName = assembler.kernels[i].name;
1175        AsmROCmKernelConfig& config = *kernel.config.get();
1176        // setup config
1177        //config.enableSpgrRegisterFlags = (config.enableSpgrRegisterFlags&~64) |
1178        cxuint userSGPRsNum = config.userDataNum;
1179        /* include userData sgprs */
1180        cxuint dimMask = (config.dimMask!=BINGEN_DEFAULT) ? config.dimMask :
1181                ((config.computePgmRsrc2>>7)&7);
1182        // extra sgprs for dimensions
1183        cxuint minRegsNum[2];
1184        getGPUSetupMinRegistersNum(arch, dimMask, userSGPRsNum,
1185                   ((config.tgSize) ? GPUSETUP_TGSIZE_EN : 0) |
1186                   ((config.scratchBufferSize!=0) ? GPUSETUP_SCRATCH_EN : 0), minRegsNum);
1187       
1188        if (config.usedSGPRsNum!=BINGEN_DEFAULT && maxSGPRsNum < config.usedSGPRsNum)
1189        {   // check only if sgprsnum set explicitly
1190            char numBuf[64];
1191            snprintf(numBuf, 64, "(max %u)", maxSGPRsNum);
1192            assembler.printError(assembler.kernels[i].sourcePos, (std::string(
1193                    "Number of total SGPRs for kernel '")+
1194                    kernelName.c_str()+"' is too high "+numBuf).c_str());
1195            good = false;
1196        }
1197       
1198        if (config.usedSGPRsNum==BINGEN_DEFAULT)
1199        {
1200            config.usedSGPRsNum = std::min(
1201                std::max(minRegsNum[0], kernelStates[i]->allocRegs[0]) +
1202                    getGPUExtraRegsNum(arch, REGTYPE_SGPR, kernelStates[i]->allocRegFlags),
1203                    maxSGPRsNum); // include all extra sgprs
1204        }
1205        if (config.usedVGPRsNum==BINGEN_DEFAULT)
1206            config.usedVGPRsNum = std::max(minRegsNum[1], kernelStates[i]->allocRegs[1]);
1207        // to little endian
1208        SLEV(config.amdCodeVersionMajor, config.amdCodeVersionMajor);
1209        SLEV(config.amdCodeVersionMinor, config.amdCodeVersionMinor);
1210        SLEV(config.amdMachineKind, config.amdMachineKind);
1211        SLEV(config.amdMachineMajor, config.amdMachineMajor);
1212        SLEV(config.amdMachineMinor, config.amdMachineMinor);
1213        SLEV(config.amdMachineStepping, config.amdMachineStepping);
1214        SLEV(config.kernelCodeEntryOffset, config.kernelCodeEntryOffset);
1215        SLEV(config.kernelCodePrefetchOffset, config.kernelCodePrefetchOffset);
1216        SLEV(config.kernelCodePrefetchSize, config.kernelCodePrefetchSize);
1217        SLEV(config.maxScrachBackingMemorySize, config.maxScrachBackingMemorySize);
1218        SLEV(config.computePgmRsrc1, config.computePgmRsrc1);
1219        SLEV(config.computePgmRsrc2, config.computePgmRsrc2);
1220        SLEV(config.enableSpgrRegisterFlags, config.enableSpgrRegisterFlags);
1221        SLEV(config.enableFeatureFlags, config.enableFeatureFlags);
1222        SLEV(config.workitemPrivateSegmentSize, config.workitemPrivateSegmentSize);
1223        SLEV(config.workgroupGroupSegmentSize, config.workgroupGroupSegmentSize);
1224        SLEV(config.gdsSegmentSize, config.gdsSegmentSize);
1225        SLEV(config.kernargSegmentSize, config.kernargSegmentSize);
1226        SLEV(config.workgroupFbarrierCount, config.workgroupFbarrierCount);
1227        SLEV(config.wavefrontSgprCount, config.wavefrontSgprCount);
1228        SLEV(config.workitemVgprCount, config.workitemVgprCount);
1229        SLEV(config.reservedVgprFirst, config.reservedVgprFirst);
1230        SLEV(config.reservedVgprCount, config.reservedVgprCount);
1231        SLEV(config.reservedSgprFirst, config.reservedSgprFirst);
1232        SLEV(config.reservedSgprCount, config.reservedSgprCount);
1233        SLEV(config.debugWavefrontPrivateSegmentOffsetSgpr,
1234             config.debugWavefrontPrivateSegmentOffsetSgpr);
1235        SLEV(config.debugPrivateSegmentBufferSgpr, config.debugPrivateSegmentBufferSgpr);
1236        SLEV(config.callConvention, config.callConvention);
1237        SLEV(config.runtimeLoaderKernelSymbol, config.runtimeLoaderKernelSymbol);
1238        // put control directive section to config
1239        if (kernel.ctrlDirSection!=ASMSECT_NONE)
1240            ::memcpy(config.controlDirective, 
1241                 assembler.sections[kernel.ctrlDirSection].content.data(), 128);
1242    }
1243   
1244    const AsmSymbolMap& symbolMap = assembler.getSymbolMap();
1245    for (size_t ki = 0; ki < output.symbols.size(); ki++)
1246    {
1247        ROCmSymbolInput& kinput = output.symbols[ki];
1248        auto it = symbolMap.find(kinput.symbolName);
1249        if (it == symbolMap.end() || !it->second.isDefined())
1250        {   // error, undefined
1251            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1252                        "Symbol for kernel '")+kinput.symbolName.c_str()+
1253                        "' is undefined").c_str());
1254            good = false;
1255            continue;
1256        }
1257        const AsmSymbol& symbol = it->second;
1258        if (!symbol.hasValue)
1259        {   // error, unresolved
1260            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1261                    "Symbol for kernel '") + kinput.symbolName.c_str() +
1262                    "' is not resolved").c_str());
1263            good = false;
1264            continue;
1265        }
1266        if (symbol.sectionId != codeSection)
1267        {   /// error, wrong section
1268            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1269                    "Symbol for kernel '")+kinput.symbolName.c_str()+
1270                    "' is defined for section other than '.text'").c_str());
1271            good = false;
1272            continue;
1273        }
1274        const Kernel& kernel = *kernelStates[ki];
1275        kinput.offset = symbol.value;
1276        if (kernel.config!=nullptr) // put config to code section
1277            ::memcpy(assembler.sections[codeSection].content.data() + symbol.value,
1278                     kernel.config.get(), sizeof(ROCmKernelConfig));
1279        // set symbol type
1280        kinput.type = kernel.isFKernel ? ROCmRegionType::FKERNEL : ROCmRegionType::KERNEL;
1281    }
1282    return good;
1283}
1284
1285void AsmROCmHandler::writeBinary(std::ostream& os) const
1286{
1287    ROCmBinGenerator binGenerator(&output);
1288    binGenerator.generate(os);
1289}
1290
1291void AsmROCmHandler::writeBinary(Array<cxbyte>& array) const
1292{
1293    ROCmBinGenerator binGenerator(&output);
1294    binGenerator.generate(array);
1295}
Note: See TracBrowser for help on using the repository browser.