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

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

CLRadeonExtender: AsmROCm: update.

File size: 38.0 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 <cstring>
22#include <string>
23#include <vector>
24#include <utility>
25#include <algorithm>
26#include <CLRX/utils/Utilities.h>
27#include <CLRX/amdasm/Assembler.h>
28#include "AsmInternals.h"
29
30using namespace CLRX;
31
32static const char* rocmPseudoOpNamesTbl[] =
33{
34    "call_convention", "codeversion", "config",
35    "control_directive", "debug_private_segment_buffer_sgpr",
36    "debug_wavefront_private_segment_offset_sgpr",
37    "debugmode", "dims", "dx10clamp",
38    "exceptions", "floatmode", "gds_segment_size",
39    "group_segment_align", "ieeemode", "kcode",
40    "kcodeend", "kernarg_segment_align",
41    "kernarg_segment_size", "kernel_code_entry_offset",
42    "kernel_code_prefetch_offset", "kernel_code_prefetch_size",
43    "localsize", "machine", "max_scratch_backing_memory",
44    "pgmrsrc1", "pgmrsrc2", "priority", "private_segment_align",
45    "privmode", "reserved_sgpr_count", "reserved_sgpr_first",
46    "reserved_vgpr_count", "reserved_vgpr_first",
47    "runtime_loader_kernel_symbol",
48    "scratchbuffer", "sgprsnum", "tgsize",
49    "use_debug_enabled", "use_dispatch_id",
50    "use_dispatch_ptr", "use_dynamic_call_stack",
51    "use_flat_scratch_init", "use_grid_workgroup_count",
52    "use_kernarg_segment_ptr", "use_ordered_append_gds",
53    "use_private_segment_size", "use_ptr64", "use_queue_ptr",
54    "use_private_segment_buffer", "use_xnack_enabled",
55    "userdatanum", "vgprsnum", "wavefront_sgpr_count",
56    "wavefront_size", "workitem_vgpr_count",
57    "workgroup_fbarrier_count", "workgroup_group_segment_size",
58    "workitem_private_segment_size"
59};
60
61enum
62{
63    ROCMOP_CALL_CONVENTION, ROCMOP_CODEVERSION, ROCMOP_CONFIG,
64    ROCMOP_CONTROL_DIRECTIVE, ROCMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR,
65    ROCMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR,
66    ROCMOP_DEBUGMODE, ROCMOP_DIMS, ROCMOP_DX10CLAMP,
67    ROCMOP_EXCEPTIONS, ROCMOP_FLOATMODE, ROCMOP_GDS_SEGMENT_SIZE,
68    ROCMOP_GROUP_SEGMENT_ALIGN, ROCMOP_IEEEMODE, ROCMOP_KCODE,
69    ROCMOP_KCODEEND, ROCMOP_KERNARG_SEGMENT_ALIGN,
70    ROCMOP_KERNARG_SEGMENT_SIZE, ROCMOP_KERNEL_CODE_ENTRY_OFFSET,
71    ROCMOP_KERNEL_CODE_PREFETCH_OFFSET, ROCMOP_KERNEL_CODE_PREFETCH_SIZE,
72    ROCMOP_LOCALSIZE, ROCMOP_MACHINE, ROCMOP_MAX_SCRATCH_BACKING_MEMORY,
73    ROCMOP_PGMRSRC1, ROCMOP_PGMRSRC2, ROCMOP_PRIORITY, ROCMOP_PRIVATE_SEGMENT_ALIGN,
74    ROCMOP_PRIVMODE, ROCMOP_RESERVED_SGPR_COUNT, ROCMOP_RESERVED_SGPR_FIRST,
75    ROCMOP_RESERVED_VGPR_COUNT, ROCMOP_RESERVED_VGPR_FIRST,
76    ROCMOP_RUNTIME_LOADER_KERNEL_SYMBOL,
77    ROCMOP_SCRATCHBUFFER, ROCMOP_SGPRSNUM, ROCMOP_TGSIZE,
78    ROCMOP_USE_DEBUG_ENABLED, ROCMOP_USE_DISPATCH_ID,
79    ROCMOP_USE_DISPATCH_PTR, ROCMOP_USE_DYNAMIC_CALL_STACK,
80    ROCMOP_USE_FLAT_SCRATCH_INIT, ROCMOP_USE_GRID_WORKGROUP_COUNT,
81    ROCMOP_USE_KERNARG_SEGMENT_PTR, ROCMOP_USE_ORDERED_APPEND_GDS,
82    ROCMOP_USE_PRIVATE_SEGMENT_SIZE, ROCMOP_USE_PTR64, ROCMOP_USE_QUEUE_PTR,
83    ROCMOP_USE_PRIVATE_SEGMENT_BUFFER, ROCMOP_USE_XNACK_ENABLED,
84    ROCMOP_USERDATANUM, ROCMOP_VGPRSNUM, ROCMOP_WAVEFRONT_SGPR_COUNT,
85    ROCMOP_WAVEFRONT_SIZE, ROCMOP_WORKITEM_VGPR_COUNT,
86    ROCMOP_WORKGROUP_FBARRIER_COUNT, ROCMOP_WORKGROUP_GROUP_SEGMENT_SIZE,
87    ROCMOP_WORKITEM_PRIVATE_SEGMENT_SIZE
88};
89
90/*
91 * ROCm format handler
92 */
93
94AsmROCmHandler::AsmROCmHandler(Assembler& assembler): AsmFormatHandler(assembler),
95             output{}, codeSection(0), commentSection(ASMSECT_NONE),
96             extraSectionCount(0)
97{
98    assembler.currentKernel = ASMKERN_GLOBAL;
99    assembler.currentSection = 0;
100    sections.push_back({ ASMKERN_GLOBAL, AsmSectionType::CODE,
101                ELFSECTID_TEXT, ".text" });
102    currentKcodeKernel = ASMKERN_GLOBAL;
103    savedSection = 0;
104}
105
106AsmROCmHandler::~AsmROCmHandler()
107{
108    for (Kernel* kernel: kernelStates)
109        delete kernel;
110}
111
112cxuint AsmROCmHandler::addKernel(const char* kernelName)
113{
114    cxuint thisKernel = output.symbols.size();
115    cxuint thisSection = sections.size();
116    output.addEmptyKernel(kernelName);
117    /// add kernel config section
118    sections.push_back({ thisKernel, AsmSectionType::CONFIG, ELFSECTID_UNDEF, nullptr });
119    kernelStates.push_back(new Kernel{ thisSection, nullptr, ASMSECT_NONE, thisSection });
120   
121    if (assembler.currentKernel == ASMKERN_GLOBAL)
122        savedSection = assembler.currentSection;
123   
124    assembler.currentKernel = thisKernel;
125    assembler.currentSection = thisSection;
126    return thisKernel;
127}
128
129cxuint AsmROCmHandler::addSection(const char* sectionName, cxuint kernelId)
130{
131    const cxuint thisSection = sections.size();
132    Section section;
133    section.kernelId = ASMKERN_GLOBAL;  // we ignore input kernelId, we go to main
134       
135    if (::strcmp(sectionName, ".text") == 0) // code
136    {
137        if (codeSection!=ASMSECT_NONE)
138            throw AsmFormatException("Only one section '.text' can be in binary");
139        codeSection = thisSection;
140        section.type = AsmSectionType::CODE;
141        section.elfBinSectId = ELFSECTID_TEXT;
142        section.name = ".text"; // set static name (available by whole lifecycle)
143    }
144    else if (::strcmp(sectionName, ".comment") == 0) // comment
145    {
146        if (commentSection!=ASMSECT_NONE)
147            throw AsmFormatException("Only one section '.comment' can be in binary");
148        commentSection = thisSection;
149        section.type = AsmSectionType::GALLIUM_COMMENT;
150        section.elfBinSectId = ELFSECTID_COMMENT;
151        section.name = ".comment"; // set static name (available by whole lifecycle)
152    }
153    else
154    {
155        auto out = extraSectionMap.insert(std::make_pair(CString(sectionName),
156                    thisSection));
157        if (!out.second)
158            throw AsmFormatException("Section already exists");
159        section.type = AsmSectionType::EXTRA_SECTION;
160        section.elfBinSectId = extraSectionCount++;
161        /// reference entry is available and unchangeable by whole lifecycle of section map
162        section.name = out.first->first.c_str();
163    }
164    sections.push_back(section);
165   
166    assembler.currentKernel = ASMKERN_GLOBAL;
167    assembler.currentSection = thisSection;
168    return thisSection;
169}
170
171cxuint AsmROCmHandler::getSectionId(const char* sectionName) const
172{
173    if (::strcmp(sectionName, ".text") == 0) // code
174        return codeSection;
175    else if (::strcmp(sectionName, ".comment") == 0) // comment
176        return commentSection;
177    else
178    {
179        SectionMap::const_iterator it = extraSectionMap.find(sectionName);
180        if (it != extraSectionMap.end())
181            return it->second;
182    }
183    return ASMSECT_NONE;
184}
185
186void AsmROCmHandler::setCurrentKernel(cxuint kernel)
187{
188    if (kernel != ASMKERN_GLOBAL && kernel >= kernelStates.size())
189        throw AsmFormatException("KernelId out of range");
190   
191    if (assembler.currentKernel == ASMKERN_GLOBAL)
192        savedSection = assembler.currentSection;
193    else // if kernel
194        kernelStates[assembler.currentKernel]->savedSection = assembler.currentSection;
195   
196    assembler.currentKernel = kernel;
197    if (kernel != ASMKERN_GLOBAL)
198        assembler.currentSection = kernelStates[kernel]->savedSection;
199    else // default main section
200        assembler.currentSection = savedSection;
201}
202
203void AsmROCmHandler::setCurrentSection(cxuint sectionId)
204{
205    if (sectionId >= sections.size())
206        throw AsmFormatException("SectionId out of range");
207   
208    if (assembler.currentKernel == ASMKERN_GLOBAL)
209        savedSection = assembler.currentSection;
210    else // if kernel
211        kernelStates[assembler.currentKernel]->savedSection = assembler.currentSection;
212   
213    assembler.currentSection = sectionId;
214    assembler.currentKernel = sections[sectionId].kernelId;
215}
216
217
218AsmFormatHandler::SectionInfo AsmROCmHandler::getSectionInfo(cxuint sectionId) const
219{
220    if (sectionId >= sections.size())
221        throw AsmFormatException("Section doesn't exists");
222   
223    AsmFormatHandler::SectionInfo info;
224    info.type = sections[sectionId].type;
225    info.flags = 0;
226    if (info.type == AsmSectionType::CODE)
227        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE;
228    else if (info.type != AsmSectionType::CONFIG)
229        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE | ASMSECT_ABS_ADDRESSABLE;
230   
231    info.name = sections[sectionId].name;
232    return info;
233}
234
235void AsmROCmHandler::restoreKcodeCurrentAllocRegs()
236{
237    if (currentKcodeKernel != ASMKERN_GLOBAL)
238    {
239        Kernel& newKernel = *kernelStates[currentKcodeKernel];
240        assembler.isaAssembler->setAllocatedRegisters(newKernel.allocRegs,
241                            newKernel.allocRegFlags);
242    }
243}
244
245void AsmROCmHandler::saveKcodeCurrentAllocRegs()
246{
247    if (currentKcodeKernel != ASMKERN_GLOBAL)
248    {   // save other state
249        size_t regTypesNum;
250        Kernel& oldKernel = *kernelStates[currentKcodeKernel];
251        const cxuint* regs = assembler.isaAssembler->getAllocatedRegisters(
252                            regTypesNum, oldKernel.allocRegFlags);
253        std::copy(regs, regs+2, oldKernel.allocRegs);
254    }
255}
256
257
258void AsmROCmHandler::handleLabel(const CString& label)
259{
260    if (assembler.sections[assembler.currentSection].type != AsmSectionType::CODE)
261        return;
262    auto kit = assembler.kernelMap.find(label);
263    if (kit == assembler.kernelMap.end())
264        return;
265    if (!kcodeSelection.empty())
266        return; // do not change if inside kcode
267    // save other state
268    saveKcodeCurrentAllocRegs();
269    // restore this state
270    currentKcodeKernel = kit->second;
271    restoreKcodeCurrentAllocRegs();
272}
273
274void AsmROCmHandler::Kernel::initializeKernelConfig()
275{
276    if (!config)
277    {
278        config.reset(new AsmROCmKernelConfig{});
279        ::memset(config.get(), 0, sizeof(AsmROCmKernelConfig));
280    }
281}
282
283namespace CLRX
284{
285
286bool AsmROCmPseudoOps::checkPseudoOpName(const CString& string)
287{
288    if (string.empty() || string[0] != '.')
289        return false;
290    const size_t pseudoOp = binaryFind(rocmPseudoOpNamesTbl, rocmPseudoOpNamesTbl +
291                sizeof(rocmPseudoOpNamesTbl)/sizeof(char*), string.c_str()+1,
292               CStringLess()) - rocmPseudoOpNamesTbl;
293    return pseudoOp < sizeof(rocmPseudoOpNamesTbl)/sizeof(char*);
294}
295   
296void AsmROCmPseudoOps::doConfig(AsmROCmHandler& handler, const char* pseudoOpPlace,
297                  const char* linePtr)
298{
299    Assembler& asmr = handler.assembler;
300    const char* end = asmr.line + asmr.lineSize;
301    if (asmr.currentKernel==ASMKERN_GLOBAL)
302    {
303        asmr.printError(pseudoOpPlace, "Kernel config can be defined only inside kernel");
304        return;
305    }
306   
307    if (handler.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
308    {
309        asmr.printError(pseudoOpPlace, "Configuration outside kernel definition");
310        return;
311    }
312    skipSpacesToEnd(linePtr, end);
313    if (!checkGarbagesAtEnd(asmr, linePtr))
314        return;
315    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
316}
317
318void AsmROCmPseudoOps::doControlDirective(AsmROCmHandler& handler,
319              const char* pseudoOpPlace, const char* linePtr)
320{
321    Assembler& asmr = handler.assembler;
322    const char* end = asmr.line + asmr.lineSize;
323    if (asmr.currentKernel==ASMKERN_GLOBAL)
324    {
325        asmr.printError(pseudoOpPlace, "Kernel control directive can be defined "
326                    "only inside kernel");
327        return;
328    }
329    skipSpacesToEnd(linePtr, end);
330    if (!checkGarbagesAtEnd(asmr, linePtr))
331        return;
332   
333    AsmROCmHandler::Kernel& kernel = *handler.kernelStates[asmr.currentKernel];
334    if (kernel.ctrlDirSection == ASMSECT_NONE)
335    {
336        cxuint thisSection = handler.sections.size();
337        handler.sections.push_back({ asmr.currentKernel,
338            AsmSectionType::ROCM_CONFIG_CTRL_DIRECTIVE,
339            ELFSECTID_UNDEF, nullptr });
340        kernel.ctrlDirSection = thisSection;
341    }
342    asmr.goToSection(pseudoOpPlace, kernel.ctrlDirSection);
343    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
344}
345
346void AsmROCmPseudoOps::setConfigValue(AsmROCmHandler& handler, const char* pseudoOpPlace,
347                  const char* linePtr, ROCmConfigValueTarget target)
348{
349    Assembler& asmr = handler.assembler;
350    const char* end = asmr.line + asmr.lineSize;
351   
352    if (asmr.currentKernel==ASMKERN_GLOBAL ||
353        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
354    {
355        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
356        return;
357    }
358   
359    skipSpacesToEnd(linePtr, end);
360    const char* valuePlace = linePtr;
361    uint64_t value = BINGEN64_NOTSUPPLIED;
362    bool good = getAbsoluteValueArg(asmr, value, linePtr, true);
363    /* ranges checking */
364    if (good)
365    {
366        switch(target)
367        {
368            case ROCMCVAL_SGPRSNUM:
369            {
370                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
371                            asmr.deviceType);
372                cxuint maxSGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
373                if (value > maxSGPRsNum)
374                {
375                    char buf[64];
376                    snprintf(buf, 64, "Used SGPRs number out of range (0-%u)", maxSGPRsNum);
377                    asmr.printError(valuePlace, buf);
378                    good = false;
379                }
380                break;
381            }
382            case ROCMCVAL_VGPRSNUM:
383            {
384                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
385                            asmr.deviceType);
386                cxuint maxVGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_VGPR, 0);
387                if (value > maxVGPRsNum)
388                {
389                    char buf[64];
390                    snprintf(buf, 64, "Used VGPRs number out of range (0-%u)", maxVGPRsNum);
391                    asmr.printError(valuePlace, buf);
392                    good = false;
393                }
394                break;
395            }
396            case ROCMCVAL_EXCEPTIONS:
397                asmr.printWarningForRange(7, value,
398                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
399                value &= 0x7f;
400                break;
401            case ROCMCVAL_FLOATMODE:
402                asmr.printWarningForRange(8, value,
403                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
404                value &= 0xff;
405                break;
406            case ROCMCVAL_PRIORITY:
407                asmr.printWarningForRange(2, value,
408                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
409                value &= 3;
410                break;
411            case ROCMCVAL_LOCALSIZE:
412            {
413                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
414                            asmr.deviceType);
415                const cxuint maxLocalSize = getGPUMaxLocalSize(arch);
416                if (value > maxLocalSize)
417                {
418                    char buf[64];
419                    snprintf(buf, 64, "LocalSize out of range (0-%u)", maxLocalSize);
420                    asmr.printError(valuePlace, buf);
421                    good = false;
422                }
423                break;
424            }
425            case ROCMCVAL_USERDATANUM:
426                if (value > 16)
427                {
428                    asmr.printError(valuePlace, "UserDataNum out of range (0-16)");
429                    good = false;
430                }
431                break;
432            default:
433                break;
434        }
435    }
436    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
437        return;
438   
439    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
440    AsmROCmKernelConfig& config = *(handler.kernelStates[asmr.currentKernel]->config);
441    // set value
442    switch(target)
443    {
444        case ROCMCVAL_SGPRSNUM:
445            config.usedSGPRsNum = value;
446            break;
447        case ROCMCVAL_VGPRSNUM:
448            config.usedVGPRsNum = value;
449            break;
450        case ROCMCVAL_PGMRSRC1:
451            config.computePgmRsrc1 = value;
452            break;
453        case ROCMCVAL_PGMRSRC2:
454            config.computePgmRsrc2 = value;
455            break;
456        case ROCMCVAL_FLOATMODE:
457            config.floatMode = value;
458            break;
459        case ROCMCVAL_LOCALSIZE:
460            config.localSize = value;
461            break;
462        case ROCMCVAL_SCRATCHBUFFER:
463            config.scratchBufferSize = value;
464            break;
465        case ROCMCVAL_PRIORITY:
466            config.priority = value;
467            break;
468        case ROCMCVAL_USERDATANUM:
469            config.userDataNum = value;
470            break;
471        case ROCMCVAL_EXCEPTIONS:
472            config.exceptions = value;
473            break;
474        case ROCMCVAL_KERNEL_CODE_ENTRY_OFFSET:
475            config.kernelCodeEntryOffset = value;
476            break;
477        case ROCMCVAL_KERNEL_CODE_PREFETCH_OFFSET:
478            config.kernelCodePrefetchOffset = value;
479            break;
480        case ROCMCVAL_KERNEL_CODE_PREFETCH_SIZE:
481            config.kernelCodePrefetchSize = value;
482            break;
483        case ROCMCVAL_MAX_SCRATCH_BACKING_MEMORY:
484            config.maxScrachBackingMemorySize = value;
485            break;
486        case ROCMCVAL_WORKITEM_PRIVATE_SEGMENT_SIZE:
487            config.workitemPrivateSegmentSize = value;
488            break;
489        case ROCMCVAL_WORKGROUP_GROUP_SEGMENT_SIZE:
490            config.workgroupGroupSegmentSize = value;
491            break;
492        case ROCMCVAL_GDS_SEGMENT_SIZE:
493            config.gdsSegmentSize = value;
494            break;
495        case ROCMCVAL_KERNARG_SEGMENT_SIZE:
496            config.kernargSegmentSize = value;
497            break;
498        case ROCMCVAL_WORKGROUP_FBARRIER_COUNT:
499            config.workgroupFbarrierCount = value;
500            break;
501        case ROCMCVAL_WAVEFRONT_SGPR_COUNT:
502            config.wavefrontSgprCount = value;
503            break;
504        case ROCMCVAL_WORKITEM_VGPR_COUNT:
505            config.workitemVgprCount = value;
506            break;
507        case ROCMCVAL_RESERVED_VGPR_FIRST:
508            config.reservedVgprFirst = value;
509            break;
510        case ROCMCVAL_RESERVED_VGPR_COUNT:
511            config.reservedVgprCount = value;
512            break;
513        case ROCMCVAL_RESERVED_SGPR_FIRST:
514            config.reservedSgprFirst = value;
515            break;
516        case ROCMCVAL_RESERVED_SGPR_COUNT:
517            config.reservedSgprCount = value;
518            break;
519        case ROCMCVAL_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR:
520            config.debugWavefrontPrivateSegmentOffsetSgpr = value;
521            break;
522        case ROCMCVAL_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR:
523            config.debugPrivateSegmentBufferSgpr = value;
524            break;
525        case ROCMCVAL_KERNARG_SEGMENT_ALIGN:
526            config.kernargSegmentAlignment = value;
527            break;
528        case ROCMCVAL_GROUP_SEGMENT_ALIGN:
529            config.groupSegmentAlignment = value;
530            break;
531        case ROCMCVAL_PRIVATE_SEGMENT_ALIGN:
532            config.privateSegmentAlignment = value;
533            break;
534        case ROCMCVAL_WAVEFRONT_SIZE:
535            config.wavefrontSize = value;
536            break;
537        case ROCMCVAL_CALL_CONVENTION:
538            config.callConvention = value;
539            break;
540        case ROCMCVAL_RUNTIME_LOADER_KERNEL_SYMBOL:
541            config.runtimeLoaderKernelSymbol = value;
542            break;
543        default:
544            break;
545    }
546}
547
548void AsmROCmPseudoOps::setConfigBoolValue(AsmROCmHandler& handler,
549          const char* pseudoOpPlace, const char* linePtr, ROCmConfigValueTarget target)
550{
551    Assembler& asmr = handler.assembler;
552    const char* end = asmr.line + asmr.lineSize;
553   
554    if (asmr.currentKernel==ASMKERN_GLOBAL ||
555        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
556    {
557        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
558        return;
559    }
560   
561    skipSpacesToEnd(linePtr, end);
562    if (!checkGarbagesAtEnd(asmr, linePtr))
563        return;
564   
565    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
566    AsmROCmKernelConfig& config = *(handler.kernelStates[asmr.currentKernel]->config);
567   
568    switch(target)
569    {
570        case ROCMCVAL_PRIVMODE:
571            config.privilegedMode = true;
572            break;
573        case ROCMCVAL_DEBUGMODE:
574            config.debugMode = true;
575            break;
576        case ROCMCVAL_DX10CLAMP:
577            config.dx10Clamp = true;
578            break;
579        case ROCMCVAL_IEEEMODE:
580            config.ieeeMode = true;
581            break;
582        case ROCMCVAL_TGSIZE:
583            config.tgSize = true;
584            break;
585        case ROCMCVAL_USE_PRIVATE_SEGMENT_BUFFER:
586            config.enableSpgrRegisterFlags |= 1;
587            break;
588        case ROCMCVAL_USE_DISPATCH_PTR:
589            config.enableSpgrRegisterFlags |= 2;
590            break;
591        case ROCMCVAL_USE_QUEUE_PTR:
592            config.enableSpgrRegisterFlags |= 4;
593            break;
594        case ROCMCVAL_USE_KERNARG_SEGMENT_PTR:
595            config.enableSpgrRegisterFlags |= 8;
596            break;
597        case ROCMCVAL_USE_DISPATCH_ID:
598            config.enableSpgrRegisterFlags |= 16;
599            break;
600        case ROCMCVAL_USE_FLAT_SCRATCH_INIT:
601            config.enableSpgrRegisterFlags |= 32;
602            break;
603        case ROCMCVAL_USE_PRIVATE_SEGMENT_SIZE:
604            config.enableSpgrRegisterFlags |= 64;
605            break;
606        case ROCMCVAL_USE_ORDERED_APPEND_GDS:
607            config.enableFeatureFlags |= 1;
608            break;
609        case ROCMCVAL_USE_PTR64:
610            config.enableFeatureFlags |= 8;
611            break;
612        case ROCMCVAL_USE_DYNAMIC_CALL_STACK:
613            config.enableFeatureFlags |= 16;
614            break;
615        case ROCMCVAL_USE_DEBUG_ENABLED:
616            config.enableFeatureFlags |= 32;
617            break;
618        case ROCMCVAL_USE_XNACK_ENABLED:
619            config.enableFeatureFlags |= 64;
620            break;
621        default:
622            break;
623    }
624}
625
626void AsmROCmPseudoOps::setDimensions(AsmROCmHandler& handler, const char* pseudoOpPlace,
627                  const char* linePtr)
628{
629    Assembler& asmr = handler.assembler;
630    if (asmr.currentKernel==ASMKERN_GLOBAL ||
631        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
632    {
633        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
634        return;
635    }
636    cxuint dimMask = 0;
637    if (!parseDimensions(asmr, linePtr, dimMask))
638        return;
639    if (!checkGarbagesAtEnd(asmr, linePtr))
640        return;
641    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
642    handler.kernelStates[asmr.currentKernel]->config->dimMask = dimMask;
643}
644
645void AsmROCmPseudoOps::setUseGridWorkGroupCount(AsmROCmHandler& handler,
646                   const char* pseudoOpPlace, const char* linePtr)
647{
648    Assembler& asmr = handler.assembler;
649    if (asmr.currentKernel==ASMKERN_GLOBAL ||
650        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
651    {
652        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
653        return;
654    }
655    cxuint dimMask = 0;
656    if (!parseDimensions(asmr, linePtr, dimMask))
657        return;
658    if (!checkGarbagesAtEnd(asmr, linePtr))
659        return;
660    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
661    uint16_t& flags = handler.kernelStates[asmr.currentKernel]->config->
662                enableSpgrRegisterFlags;
663    flags = (flags & ~(7<<7)) | dimMask<<7;
664}
665
666void AsmROCmPseudoOps::updateKCodeSel(AsmROCmHandler& handler,
667                  const std::vector<cxuint>& oldset)
668{
669    Assembler& asmr = handler.assembler;
670    // old elements - join current regstate with all them
671    size_t regTypesNum;
672    for (auto it = oldset.begin(); it != oldset.end(); ++it)
673    {
674        Flags curAllocRegFlags;
675        const cxuint* curAllocRegs = asmr.isaAssembler->getAllocatedRegisters(regTypesNum,
676                               curAllocRegFlags);
677        cxuint newAllocRegs[2];
678        AsmROCmHandler::Kernel& kernel = *(handler.kernelStates[*it]);
679        newAllocRegs[0] = std::max(curAllocRegs[0], kernel.allocRegs[0]);
680        newAllocRegs[1] = std::max(curAllocRegs[1], kernel.allocRegs[1]);
681        kernel.allocRegFlags |= curAllocRegFlags;
682        std::copy(newAllocRegs, newAllocRegs+2, kernel.allocRegs);
683    }
684    asmr.isaAssembler->setAllocatedRegisters();
685}
686
687void AsmROCmPseudoOps::doKCode(AsmROCmHandler& handler, const char* pseudoOpPlace,
688                  const char* linePtr)
689{
690    Assembler& asmr = handler.assembler;
691    const char* end = asmr.line + asmr.lineSize;
692    bool good = true;
693    skipSpacesToEnd(linePtr, end);
694    if (linePtr==end)
695        return;
696    std::unordered_set<cxuint> newSel(handler.kcodeSelection.begin(),
697                          handler.kcodeSelection.end());
698    do {
699        CString kname;
700        const char* knamePlace = linePtr;
701        skipSpacesToEnd(linePtr, end);
702        bool removeKernel = false;
703        if (linePtr!=end && *linePtr=='-')
704        {   // '-' - remove this kernel from current kernel selection
705            removeKernel = true;
706            linePtr++;
707        }
708        else if (linePtr!=end && *linePtr=='+')
709        {
710            linePtr++;
711            skipSpacesToEnd(linePtr, end);
712            if (linePtr==end)
713            {   // add all kernels
714                for (cxuint k = 0; k < handler.kernelStates.size(); k++)
715                    newSel.insert(k);
716                break;
717            }
718        }
719       
720        if (!getNameArg(asmr, kname, linePtr, "kernel"))
721        { good = false; continue; }
722        auto kit = asmr.kernelMap.find(kname);
723        if (kit == asmr.kernelMap.end())
724        {
725            asmr.printError(knamePlace, "Kernel not found");
726            continue;
727        }
728        if (!removeKernel)
729            newSel.insert(kit->second);
730        else // remove kernel
731            newSel.erase(kit->second);
732    } while (skipCommaForMultipleArgs(asmr, linePtr));
733   
734    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
735        return;
736   
737    if (handler.sections[asmr.currentSection].type != AsmSectionType::CODE)
738    {
739        asmr.printError(pseudoOpPlace, "KCode outside code");
740        return;
741    }
742    if (handler.kcodeSelStack.empty())
743        handler.saveKcodeCurrentAllocRegs();
744    // push to stack
745    handler.kcodeSelStack.push(handler.kcodeSelection);
746    // set current sel
747    handler.kcodeSelection.assign(newSel.begin(), newSel.end());
748   
749    std::sort(handler.kcodeSelection.begin(), handler.kcodeSelection.end());
750    updateKCodeSel(handler, handler.kcodeSelStack.top());
751}
752
753void AsmROCmPseudoOps::doKCodeEnd(AsmROCmHandler& handler, const char* pseudoOpPlace,
754                  const char* linePtr)
755{
756    Assembler& asmr = handler.assembler;
757    if (handler.sections[asmr.currentSection].type != AsmSectionType::CODE)
758    {
759        asmr.printError(pseudoOpPlace, "KCodeEnd outside code");
760        return;
761    }
762    if (handler.kcodeSelStack.empty())
763    {
764        asmr.printError(pseudoOpPlace, "'.kcodeend' without '.kcode'");
765        return;
766    }
767    updateKCodeSel(handler, handler.kcodeSelection);
768    handler.kcodeSelection = handler.kcodeSelStack.top();
769    handler.kcodeSelStack.pop();
770    if (handler.kcodeSelStack.empty())
771        handler.restoreKcodeCurrentAllocRegs();
772}
773
774}
775
776bool AsmROCmHandler::parsePseudoOp(const CString& firstName, const char* stmtPlace,
777               const char* linePtr)
778{
779    const size_t pseudoOp = binaryFind(rocmPseudoOpNamesTbl, rocmPseudoOpNamesTbl +
780                    sizeof(rocmPseudoOpNamesTbl)/sizeof(char*), firstName.c_str()+1,
781                   CStringLess()) - rocmPseudoOpNamesTbl;
782   
783    switch(pseudoOp)
784    {
785        case ROCMOP_CALL_CONVENTION:
786            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
787                             ROCMCVAL_CALL_CONVENTION);
788            break;
789        case ROCMOP_CODEVERSION:
790            break;
791        case ROCMOP_CONFIG:
792            AsmROCmPseudoOps::doConfig(*this, stmtPlace, linePtr);
793            break;
794        case ROCMOP_CONTROL_DIRECTIVE:
795            break;
796        case ROCMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR:
797            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
798                             ROCMCVAL_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR);
799            break;
800        case ROCMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR:
801            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
802                         ROCMCVAL_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR);
803            break;
804        case ROCMOP_DEBUGMODE:
805            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
806                             ROCMCVAL_DEBUGMODE);
807            break;
808        case ROCMOP_DIMS:
809            AsmROCmPseudoOps::setDimensions(*this, stmtPlace, linePtr);
810            break;
811        case ROCMOP_DX10CLAMP:
812            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
813                             ROCMCVAL_DX10CLAMP);
814            break;
815        case ROCMOP_EXCEPTIONS:
816            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
817                             ROCMCVAL_EXCEPTIONS);
818            break;
819        case ROCMOP_FLOATMODE:
820            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
821                             ROCMCVAL_FLOATMODE);
822            break;
823        case ROCMOP_GDS_SEGMENT_SIZE:
824            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
825                             ROCMCVAL_GDS_SEGMENT_SIZE);
826            break;
827        case ROCMOP_GROUP_SEGMENT_ALIGN:
828            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
829                             ROCMCVAL_GROUP_SEGMENT_ALIGN);
830            break;
831        case ROCMOP_IEEEMODE:
832            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
833                             ROCMCVAL_IEEEMODE);
834            break;
835        case ROCMOP_KCODE:
836            AsmROCmPseudoOps::doKCode(*this, stmtPlace, linePtr);
837            break;
838        case ROCMOP_KCODEEND:
839            AsmROCmPseudoOps::doKCodeEnd(*this, stmtPlace, linePtr);
840            break;
841        case ROCMOP_KERNARG_SEGMENT_ALIGN:
842            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
843                             ROCMCVAL_KERNARG_SEGMENT_ALIGN);
844            break;
845        case ROCMOP_KERNARG_SEGMENT_SIZE:
846            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
847                             ROCMCVAL_KERNARG_SEGMENT_SIZE);
848            break;
849        case ROCMOP_KERNEL_CODE_ENTRY_OFFSET:
850            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
851                             ROCMCVAL_KERNEL_CODE_ENTRY_OFFSET);
852            break;
853        case ROCMOP_KERNEL_CODE_PREFETCH_OFFSET:
854            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
855                             ROCMCVAL_KERNEL_CODE_PREFETCH_OFFSET);
856            break;
857        case ROCMOP_KERNEL_CODE_PREFETCH_SIZE:
858            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
859                             ROCMCVAL_KERNEL_CODE_PREFETCH_SIZE);
860            break;
861        case ROCMOP_LOCALSIZE:
862            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
863                             ROCMCVAL_LOCALSIZE);
864            break;
865        case ROCMOP_MACHINE:
866            break;
867        case ROCMOP_MAX_SCRATCH_BACKING_MEMORY:
868            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
869                             ROCMCVAL_MAX_SCRATCH_BACKING_MEMORY);
870            break;
871        case ROCMOP_PGMRSRC1:
872            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PGMRSRC1);
873            break;
874        case ROCMOP_PGMRSRC2:
875            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PGMRSRC2);
876            break;
877        case ROCMOP_PRIORITY:
878            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PRIORITY);
879            break;
880        case ROCMOP_PRIVATE_SEGMENT_ALIGN:
881            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
882                             ROCMCVAL_PRIVATE_SEGMENT_ALIGN);
883            break;
884        case ROCMOP_PRIVMODE:
885            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
886                             ROCMCVAL_PRIVMODE);
887            break;
888        case ROCMOP_RESERVED_SGPR_COUNT:
889            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
890                             ROCMCVAL_RESERVED_SGPR_COUNT);
891            break;
892        case ROCMOP_RESERVED_SGPR_FIRST:
893            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
894                             ROCMCVAL_RESERVED_SGPR_FIRST);
895            break;
896        case ROCMOP_RESERVED_VGPR_COUNT:
897            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
898                             ROCMCVAL_RESERVED_VGPR_COUNT);
899            break;
900        case ROCMOP_RESERVED_VGPR_FIRST:
901            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
902                             ROCMCVAL_RESERVED_VGPR_FIRST);
903            break;
904        case ROCMOP_RUNTIME_LOADER_KERNEL_SYMBOL:
905            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
906                             ROCMCVAL_RUNTIME_LOADER_KERNEL_SYMBOL);
907            break;
908        case ROCMOP_SCRATCHBUFFER:
909            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
910                             ROCMCVAL_SCRATCHBUFFER);
911            break;
912        case ROCMOP_SGPRSNUM:
913            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
914                             ROCMCVAL_SGPRSNUM);
915            break;
916        case ROCMOP_TGSIZE:
917            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
918                             ROCMCVAL_TGSIZE);
919            break;
920        case ROCMOP_USE_DEBUG_ENABLED:
921            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
922                             ROCMCVAL_USE_DEBUG_ENABLED);
923            break;
924        case ROCMOP_USE_DISPATCH_ID:
925            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
926                             ROCMCVAL_USE_DISPATCH_ID);
927            break;
928        case ROCMOP_USE_DISPATCH_PTR:
929            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
930                             ROCMCVAL_USE_DISPATCH_PTR);
931            break;
932        case ROCMOP_USE_DYNAMIC_CALL_STACK:
933            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
934                             ROCMCVAL_USE_DYNAMIC_CALL_STACK);
935            break;
936        case ROCMOP_USE_FLAT_SCRATCH_INIT:
937            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
938                             ROCMCVAL_USE_FLAT_SCRATCH_INIT);
939            break;
940        case ROCMOP_USE_GRID_WORKGROUP_COUNT:
941            AsmROCmPseudoOps::setUseGridWorkGroupCount(*this, stmtPlace, linePtr);
942            break;
943        case ROCMOP_USE_KERNARG_SEGMENT_PTR:
944            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
945                             ROCMCVAL_USE_KERNARG_SEGMENT_PTR);
946            break;
947        case ROCMOP_USE_ORDERED_APPEND_GDS:
948            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
949                             ROCMCVAL_USE_ORDERED_APPEND_GDS);
950            break;
951        case ROCMOP_USE_PRIVATE_SEGMENT_SIZE:
952            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
953                             ROCMCVAL_USE_PRIVATE_SEGMENT_SIZE);
954            break;
955        case ROCMOP_USE_PTR64:
956            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
957                             ROCMCVAL_USE_PTR64);
958            break;
959        case ROCMOP_USE_QUEUE_PTR:
960            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
961                             ROCMCVAL_USE_QUEUE_PTR);
962            break;
963        case ROCMOP_USE_PRIVATE_SEGMENT_BUFFER:
964            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
965                             ROCMCVAL_USE_PRIVATE_SEGMENT_BUFFER);
966            break;
967        case ROCMOP_USE_XNACK_ENABLED:
968            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
969                             ROCMCVAL_USE_XNACK_ENABLED);
970            break;
971        case ROCMOP_USERDATANUM:
972            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
973                             ROCMCVAL_USERDATANUM);
974            break;
975        case ROCMOP_VGPRSNUM:
976            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_VGPRSNUM);
977            break;
978        case ROCMOP_WAVEFRONT_SGPR_COUNT:
979            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
980                             ROCMCVAL_WAVEFRONT_SGPR_COUNT);
981            break;
982        case ROCMOP_WAVEFRONT_SIZE:
983            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
984                             ROCMCVAL_WAVEFRONT_SIZE);
985            break;
986        case ROCMOP_WORKITEM_VGPR_COUNT:
987            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
988                             ROCMCVAL_WORKITEM_VGPR_COUNT);
989            break;
990        case ROCMOP_WORKGROUP_FBARRIER_COUNT:
991            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
992                             ROCMCVAL_WORKGROUP_FBARRIER_COUNT);
993            break;
994        case ROCMOP_WORKGROUP_GROUP_SEGMENT_SIZE:
995            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
996                             ROCMCVAL_WORKGROUP_GROUP_SEGMENT_SIZE);
997            break;
998        case ROCMOP_WORKITEM_PRIVATE_SEGMENT_SIZE:
999            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1000                             ROCMCVAL_WORKITEM_PRIVATE_SEGMENT_SIZE);
1001            break;
1002        default:
1003            return false;
1004    }
1005    return true;
1006}
1007
1008bool AsmROCmHandler::prepareBinary()
1009{
1010    return false;
1011}
1012
1013void AsmROCmHandler::writeBinary(std::ostream& os) const
1014{
1015}
1016
1017void AsmROCmHandler::writeBinary(Array<cxbyte>& array) const
1018{
1019}
Note: See TracBrowser for help on using the repository browser.