source: CLRX/CLRadeonExtender/trunk/amdasm/AsmAmdCL2Format.cpp @ 3348

Last change on this file since 3348 was 3348, checked in by matszpk, 15 months ago

CLRadeonExtender: Move routines to calculate PGMRSRC1 and PGMRSRC2 to GPUId code. Apply these function in code.

File size: 90.7 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2017 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20#include <CLRX/Config.h>
21#include <cstdio>
22#include <cstring>
23#include <string>
24#include <stack>
25#include <vector>
26#include <utility>
27#include <algorithm>
28#include <CLRX/utils/Utilities.h>
29#include <CLRX/amdasm/Assembler.h>
30#include <CLRX/amdasm/AsmFormats.h>
31#include "AsmROCmInternals.h"
32#include "AsmAmdInternals.h"
33#include "AsmAmdCL2Internals.h"
34
35using namespace CLRX;
36
37static const char* amdCL2PseudoOpNamesTbl[] =
38{
39    "acl_version", "arch_minor", "arch_stepping",
40    "arg", "bssdata", "call_convention", "codeversion",
41    "compile_options", "config", "control_directive",
42    "cws", "debug_private_segment_buffer_sgpr",
43    "debug_wavefront_private_segment_offset_sgpr",
44    "debugmode", "default_hsa_features",
45    "dims", "driver_version", "dx10clamp", "exceptions",
46    "floatmode", "gds_segment_size", "gdssize", "get_driver_version",
47    "globaldata", "group_segment_align", "hsaconfig", "ieeemode", "inner",
48    "isametadata", "kernarg_segment_align",
49    "kernarg_segment_size", "kernel_code_entry_offset",
50    "kernel_code_prefetch_offset", "kernel_code_prefetch_size",
51    "localsize", "machine", "max_scratch_backing_memory",
52    "metadata", "pgmrsrc1", "pgmrsrc2", "priority",
53    "private_elem_size", "private_segment_align",
54    "privmode", "reserved_sgprs", "reserved_vgprs",
55    "runtime_loader_kernel_symbol", "rwdata", "sampler",
56    "samplerinit", "samplerreloc", "scratchbuffer", "setup",
57    "setupargs", "sgprsnum", "stub", "tgsize",
58    "use_debug_enabled", "use_dispatch_id",
59    "use_dispatch_ptr", "use_dynamic_call_stack",
60    "use_flat_scratch_init", "use_grid_workgroup_count",
61    "use_kernarg_segment_ptr", "use_ordered_append_gds",
62    "use_private_segment_buffer", "use_private_segment_size",
63    "use_ptr64", "use_queue_ptr", "use_xnack_enabled",
64    "useargs", "useenqueue", "usegeneric",
65    "userdatanum", "usesetup", "vgprsnum",
66    "wavefront_sgpr_count", "wavefront_size",  "workgroup_fbarrier_count",
67    "workgroup_group_segment_size", "workitem_private_segment_size",
68    "workitem_vgpr_count"
69};
70
71enum
72{
73    AMDCL2OP_ACL_VERSION = 0, AMDCL2OP_ARCH_MINOR, AMDCL2OP_ARCH_STEPPING,
74    AMDCL2OP_ARG, AMDCL2OP_BSSDATA, AMDCL2OP_CALL_CONVENTION, AMDCL2OP_CODEVERSION, 
75    AMDCL2OP_COMPILE_OPTIONS, AMDCL2OP_CONFIG, AMDCL2OP_CONTROL_DIRECTIVE,
76    AMDCL2OP_CWS, AMDCL2OP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR,
77    AMDCL2OP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR,
78    AMDCL2OP_DEBUGMODE, AMDCL2OP_DEFAULT_HSA_FEATURES,
79    AMDCL2OP_DIMS, AMDCL2OP_DRIVER_VERSION, AMDCL2OP_DX10CLAMP, AMDCL2OP_EXCEPTIONS,
80    AMDCL2OP_FLOATMODE, AMDCL2OP_GDS_SEGMENT_SIZE,
81    AMDCL2OP_GDSSIZE, AMDCL2OP_GET_DRIVER_VERSION,
82    AMDCL2OP_GLOBALDATA, AMDCL2OP_GROUP_SEGMENT_ALIGN,
83    AMDCL2OP_HSACONFIG, AMDCL2OP_IEEEMODE, AMDCL2OP_INNER,
84    AMDCL2OP_ISAMETADATA, AMDCL2OP_KERNARG_SEGMENT_ALIGN,
85    AMDCL2OP_KERNARG_SEGMENT_SIZE, AMDCL2OP_KERNEL_CODE_ENTRY_OFFSET,
86    AMDCL2OP_KERNEL_CODE_PREFETCH_OFFSET,
87    AMDCL2OP_KERNEL_CODE_PREFETCH_SIZE, AMDCL2OP_LOCALSIZE,
88    AMDCL2OP_MACHINE, AMDCL2OP_MAX_SCRATCH_BACKING_MEMORY,
89    AMDCL2OP_METADATA, AMDCL2OP_PGMRSRC1, AMDCL2OP_PGMRSRC2, AMDCL2OP_PRIORITY,
90    AMDCL2OP_PRIVATE_ELEM_SIZE, AMDCL2OP_PRIVATE_SEGMENT_ALIGN,
91    AMDCL2OP_PRIVMODE, AMDCL2OP_RESERVED_SGPRS, AMDCL2OP_RESERVED_VGPRS,
92    AMDCL2OP_RUNTIME_LOADER_KERNEL_SYMBOL, AMDCL2OP_RWDATA,
93    AMDCL2OP_SAMPLER, AMDCL2OP_SAMPLERINIT,
94    AMDCL2OP_SAMPLERRELOC, AMDCL2OP_SCRATCHBUFFER, AMDCL2OP_SETUP, AMDCL2OP_SETUPARGS,
95    AMDCL2OP_SGPRSNUM, AMDCL2OP_STUB, AMDCL2OP_TGSIZE,
96    AMDCL2OP_USE_DEBUG_ENABLED, AMDCL2OP_USE_DISPATCH_ID,
97    AMDCL2OP_USE_DISPATCH_PTR, AMDCL2OP_USE_DYNAMIC_CALL_STACK,
98    AMDCL2OP_USE_FLAT_SCRATCH_INIT, AMDCL2OP_USE_GRID_WORKGROUP_COUNT,
99    AMDCL2OP_USE_KERNARG_SEGMENT_PTR, AMDCL2OP_USE_ORDERED_APPEND_GDS,
100    AMDCL2OP_USE_PRIVATE_SEGMENT_BUFFER, AMDCL2OP_USE_PRIVATE_SEGMENT_SIZE,
101    AMDCL2OP_USE_PTR64, AMDCL2OP_USE_QUEUE_PTR, AMDCL2OP_USE_XNACK_ENABLED,
102    AMDCL2OP_USEARGS, AMDCL2OP_USEENQUEUE, AMDCL2OP_USEGENERIC,
103    AMDCL2OP_USERDATANUM, AMDCL2OP_USESETUP, AMDCL2OP_VGPRSNUM,
104    AMDCL2OP_WAVEFRONT_SGPR_COUNT, AMDCL2OP_WAVEFRONT_SIZE,
105    AMDCL2OP_WORKGROUP_FBARRIER_COUNT, AMDCL2OP_WORKGROUP_GROUP_SEGMENT_SIZE,
106    AMDCL2OP_WORKITEM_PRIVATE_SEGMENT_SIZE, AMDCL2OP_WORKITEM_VGPR_COUNT
107};
108
109void AsmAmdCL2Handler::Kernel::initializeKernelConfig()
110{
111    if (!hsaConfig)
112    {
113        hsaConfig.reset(new AsmAmdHsaKernelConfig{});
114        hsaConfig->initialize();
115    }
116}
117
118/*
119 * AmdCL2Catalyst format handler
120 */
121
122AsmAmdCL2Handler::AsmAmdCL2Handler(Assembler& assembler) : AsmFormatHandler(assembler),
123        output{}, rodataSection(0), dataSection(ASMSECT_NONE), bssSection(ASMSECT_NONE), 
124        samplerInitSection(ASMSECT_NONE), extraSectionCount(0),
125        innerExtraSectionCount(0)
126{
127    output.archMinor = output.archStepping = UINT32_MAX;
128    assembler.currentKernel = ASMKERN_GLOBAL;
129    assembler.currentSection = 0;
130    sections.push_back({ ASMKERN_INNER, AsmSectionType::DATA, ELFSECTID_RODATA,
131            ".rodata" });
132    savedSection = innerSavedSection = 0;
133    detectedDriverVersion = detectAmdDriverVersion();
134}
135
136AsmAmdCL2Handler::~AsmAmdCL2Handler()
137{
138    for (Kernel* kernel: kernelStates)
139        delete kernel;
140}
141
142void AsmAmdCL2Handler::saveCurrentSection()
143{   /// save previous section
144    if (assembler.currentKernel==ASMKERN_GLOBAL)
145        savedSection = assembler.currentSection;
146    else if (assembler.currentKernel==ASMKERN_INNER)
147        innerSavedSection = assembler.currentSection;
148    else
149        kernelStates[assembler.currentKernel]->savedSection = assembler.currentSection;
150}
151
152cxuint AsmAmdCL2Handler::getDriverVersion() const
153{
154    cxuint driverVersion = 0;
155    if (output.driverVersion==0)
156    {
157        if (assembler.driverVersion==0) // just detect driver version
158            driverVersion = detectedDriverVersion;
159        else // from assembler setup
160            driverVersion = assembler.driverVersion;
161    }
162    else
163        driverVersion = output.driverVersion;
164    return driverVersion;
165}
166
167void AsmAmdCL2Handler::restoreCurrentAllocRegs()
168{
169    if (assembler.currentKernel!=ASMKERN_GLOBAL &&
170        assembler.currentKernel!=ASMKERN_INNER &&
171        assembler.currentSection==kernelStates[assembler.currentKernel]->codeSection)
172        assembler.isaAssembler->setAllocatedRegisters(
173                kernelStates[assembler.currentKernel]->allocRegs,
174                kernelStates[assembler.currentKernel]->allocRegFlags);
175}
176
177void AsmAmdCL2Handler::saveCurrentAllocRegs()
178{
179    if (assembler.currentKernel!=ASMKERN_GLOBAL &&
180        assembler.currentKernel!=ASMKERN_INNER &&
181        assembler.currentSection==kernelStates[assembler.currentKernel]->codeSection)
182    {
183        size_t num;
184        cxuint* destRegs = kernelStates[assembler.currentKernel]->allocRegs;
185        const cxuint* regs = assembler.isaAssembler->getAllocatedRegisters(num,
186                       kernelStates[assembler.currentKernel]->allocRegFlags);
187        std::copy(regs, regs + num, destRegs);
188    }
189}
190
191cxuint AsmAmdCL2Handler::addKernel(const char* kernelName)
192{
193    cxuint thisKernel = output.kernels.size();
194    cxuint thisSection = sections.size();
195    output.addEmptyKernel(kernelName);
196    Kernel kernelState{ ASMSECT_NONE, ASMSECT_NONE, ASMSECT_NONE,
197            ASMSECT_NONE, ASMSECT_NONE, ASMSECT_NONE, thisSection, ASMSECT_NONE, false };
198    /* add new kernel and their section (.text) */
199    kernelStates.push_back(new Kernel(std::move(kernelState)));
200    sections.push_back({ thisKernel, AsmSectionType::CODE, ELFSECTID_TEXT, ".text" });
201   
202    saveCurrentAllocRegs();
203    saveCurrentSection();
204   
205    assembler.currentKernel = thisKernel;
206    assembler.currentSection = thisSection;
207    assembler.isaAssembler->setAllocatedRegisters();
208    return thisKernel;
209}
210
211cxuint AsmAmdCL2Handler::addSection(const char* sectionName, cxuint kernelId)
212{
213    const cxuint thisSection = sections.size();
214   
215    if (::strcmp(sectionName, ".rodata")==0 && (kernelId == ASMKERN_GLOBAL ||
216            kernelId == ASMKERN_INNER))
217    {
218        if (getDriverVersion() < 191205)
219            throw AsmFormatException("Global Data allowed only for new binary format");
220        rodataSection = sections.size();
221        sections.push_back({ ASMKERN_INNER,  AsmSectionType::DATA,
222                ELFSECTID_RODATA, ".rodata" });
223    }
224    else if (::strcmp(sectionName, ".data")==0 && (kernelId == ASMKERN_GLOBAL ||
225            kernelId == ASMKERN_INNER))
226    {
227        if (getDriverVersion() < 191205)
228            throw AsmFormatException("Global RWData allowed only for new binary format");
229        dataSection = sections.size();
230        sections.push_back({ ASMKERN_INNER,  AsmSectionType::AMDCL2_RWDATA,
231                ELFSECTID_DATA, ".data" });
232    }
233    else if (::strcmp(sectionName, ".bss")==0 && (kernelId == ASMKERN_GLOBAL ||
234            kernelId == ASMKERN_INNER))
235    {
236        if (getDriverVersion() < 191205)
237            throw AsmFormatException("Global BSS allowed only for new binary format");
238        bssSection = sections.size();
239        sections.push_back({ ASMKERN_INNER,  AsmSectionType::AMDCL2_BSS,
240                ELFSECTID_BSS, ".bss" });
241    }
242    else if (kernelId == ASMKERN_GLOBAL)
243    {
244        Section section;
245        section.kernelId = kernelId;
246        auto out = extraSectionMap.insert(std::make_pair(std::string(sectionName),
247                    thisSection));
248        if (!out.second)
249            throw AsmFormatException("Section already exists");
250        section.type = AsmSectionType::EXTRA_SECTION;
251        section.elfBinSectId = extraSectionCount++;
252        /// referfence entry is available and unchangeable by whole lifecycle of section map
253        section.name = out.first->first.c_str();
254        sections.push_back(section);
255    }
256    else // add inner section (even if we inside kernel)
257    {
258        if (getDriverVersion() < 191205)
259            throw AsmFormatException("Inner section are allowed "
260                        "only for new binary format");
261       
262        Section section;
263        section.kernelId = ASMKERN_INNER;
264        auto out = innerExtraSectionMap.insert(std::make_pair(std::string(sectionName),
265                    thisSection));
266        if (!out.second)
267            throw AsmFormatException("Section already exists");
268        section.type = AsmSectionType::EXTRA_SECTION;
269        section.elfBinSectId = innerExtraSectionCount++;
270        /// referfence entry is available and unchangeable by whole lifecycle of section map
271        section.name = out.first->first.c_str();
272        sections.push_back(section);
273    }
274   
275    saveCurrentAllocRegs();
276    saveCurrentSection();
277   
278    assembler.currentKernel = kernelId;
279    assembler.currentSection = thisSection;
280   
281    restoreCurrentAllocRegs();
282    return thisSection;
283}
284
285cxuint AsmAmdCL2Handler::getSectionId(const char* sectionName) const
286{
287    if (assembler.currentKernel == ASMKERN_GLOBAL)
288    {
289        if (::strcmp(sectionName, ".rodata")==0)
290            return rodataSection;
291        else if (::strcmp(sectionName, ".data")==0)
292            return dataSection;
293        else if (::strcmp(sectionName, ".bss")==0)
294            return bssSection;
295        SectionMap::const_iterator it = extraSectionMap.find(sectionName);
296        if (it != extraSectionMap.end())
297            return it->second;
298        return ASMSECT_NONE;
299    }
300    else
301    {
302        if (assembler.currentKernel != ASMKERN_INNER)
303        {
304            const Kernel& kernelState = *kernelStates[assembler.currentKernel];
305            if (::strcmp(sectionName, ".text") == 0)
306                return kernelState.codeSection;
307        }
308       
309        SectionMap::const_iterator it = innerExtraSectionMap.find(sectionName);
310        if (it != innerExtraSectionMap.end())
311            return it->second;
312        return ASMSECT_NONE;
313    }
314    return 0;
315}
316
317void AsmAmdCL2Handler::setCurrentKernel(cxuint kernel)
318{
319    if (kernel!=ASMKERN_GLOBAL && kernel!=ASMKERN_INNER && kernel >= kernelStates.size())
320        throw AsmFormatException("KernelId out of range");
321   
322    saveCurrentAllocRegs();
323    saveCurrentSection();
324    assembler.currentKernel = kernel;
325    if (kernel == ASMKERN_GLOBAL)
326        assembler.currentSection = savedSection;
327    else if (kernel == ASMKERN_INNER)
328        assembler.currentSection = innerSavedSection; // inner section
329    else // kernel
330        assembler.currentSection = kernelStates[kernel]->savedSection;
331    restoreCurrentAllocRegs();
332}
333
334void AsmAmdCL2Handler::setCurrentSection(cxuint sectionId)
335{
336    if (sectionId >= sections.size())
337        throw AsmFormatException("SectionId out of range");
338   
339    if (sections[sectionId].type == AsmSectionType::DATA)
340    {
341        if (getDriverVersion() < 191205)
342            throw AsmFormatException("Global Data allowed only for new binary format");
343    }
344    if (sections[sectionId].type == AsmSectionType::AMDCL2_RWDATA)
345    {
346        if (getDriverVersion() < 191205)
347            throw AsmFormatException("Global RWData allowed only for new binary format");
348    }
349    if (sections[sectionId].type == AsmSectionType::AMDCL2_BSS)
350    {
351        if (getDriverVersion() < 191205)
352            throw AsmFormatException("Global BSS allowed only for new binary format");
353    }
354   
355    saveCurrentAllocRegs();
356    saveCurrentSection();
357    assembler.currentKernel = sections[sectionId].kernelId;
358    assembler.currentSection = sectionId;
359    restoreCurrentAllocRegs();
360}
361
362AsmFormatHandler::SectionInfo AsmAmdCL2Handler::getSectionInfo(cxuint sectionId) const
363{
364    if (sectionId >= sections.size())
365        throw AsmFormatException("Section doesn't exists");
366    AsmFormatHandler::SectionInfo info;
367    info.type = sections[sectionId].type;
368    info.flags = 0;
369    if (info.type == AsmSectionType::CODE)
370        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE;
371    else if (info.type == AsmSectionType::AMDCL2_BSS ||
372            info.type == AsmSectionType::AMDCL2_RWDATA ||
373            info.type == AsmSectionType::DATA)
374    {   // global data, rwdata and bss are relocatable sections (we set unresolvable flag)
375        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_UNRESOLVABLE;
376        if (info.type != AsmSectionType::AMDCL2_BSS)
377            info.flags |= ASMSECT_WRITEABLE;
378    }
379    else if (info.type != AsmSectionType::CONFIG)
380        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE | ASMSECT_ABS_ADDRESSABLE;
381    info.name = sections[sectionId].name;
382    return info;
383}
384
385namespace CLRX
386{
387
388bool AsmAmdCL2PseudoOps::checkPseudoOpName(const CString& string)
389{
390    if (string.empty() || string[0] != '.')
391        return false;
392    const size_t pseudoOp = binaryFind(amdCL2PseudoOpNamesTbl, amdCL2PseudoOpNamesTbl +
393                sizeof(amdCL2PseudoOpNamesTbl)/sizeof(char*), string.c_str()+1,
394               CStringLess()) - amdCL2PseudoOpNamesTbl;
395    return pseudoOp < sizeof(amdCL2PseudoOpNamesTbl)/sizeof(char*);
396}
397
398void AsmAmdCL2PseudoOps::setAclVersion(AsmAmdCL2Handler& handler, const char* linePtr)
399{
400    Assembler& asmr = handler.assembler;
401    const char* end = asmr.line + asmr.lineSize;
402    skipSpacesToEnd(linePtr, end);
403    std::string out;
404    if (!asmr.parseString(out, linePtr))
405        return;
406    if (!checkGarbagesAtEnd(asmr, linePtr))
407        return;
408    handler.output.aclVersion = out;
409}
410
411void AsmAmdCL2PseudoOps::setArchMinor(AsmAmdCL2Handler& handler, const char* linePtr)
412{
413    Assembler& asmr = handler.assembler;
414    const char* end = asmr.line + asmr.lineSize;
415    skipSpacesToEnd(linePtr, end);
416    uint64_t value;
417    const char* valuePlace = linePtr;
418    if (!getAbsoluteValueArg(asmr, value, linePtr, true))
419        return;
420    asmr.printWarningForRange(sizeof(cxuint)<<3, value,
421                 asmr.getSourcePos(valuePlace), WS_UNSIGNED);
422    if (!checkGarbagesAtEnd(asmr, linePtr))
423        return;
424    handler.output.archMinor = value;
425}
426
427void AsmAmdCL2PseudoOps::setArchStepping(AsmAmdCL2Handler& handler, const char* linePtr)
428{
429    Assembler& asmr = handler.assembler;
430    const char* end = asmr.line + asmr.lineSize;
431    skipSpacesToEnd(linePtr, end);
432    uint64_t value;
433    const char* valuePlace = linePtr;
434    if (!getAbsoluteValueArg(asmr, value, linePtr, true))
435        return;
436    asmr.printWarningForRange(sizeof(cxuint)<<3, value,
437                 asmr.getSourcePos(valuePlace), WS_UNSIGNED);
438    if (!checkGarbagesAtEnd(asmr, linePtr))
439        return;
440    handler.output.archStepping = value;
441}
442
443void AsmAmdCL2PseudoOps::setCompileOptions(AsmAmdCL2Handler& handler, const char* linePtr)
444{
445    Assembler& asmr = handler.assembler;
446    const char* end = asmr.line + asmr.lineSize;
447    skipSpacesToEnd(linePtr, end);
448    std::string out;
449    if (!asmr.parseString(out, linePtr))
450        return;
451    if (!checkGarbagesAtEnd(asmr, linePtr))
452        return;
453    handler.output.compileOptions = out;
454}
455
456void AsmAmdCL2PseudoOps::setDriverVersion(AsmAmdCL2Handler& handler, const char* linePtr)
457{
458    Assembler& asmr = handler.assembler;
459    const char* end = asmr.line + asmr.lineSize;
460    skipSpacesToEnd(linePtr, end);
461    uint64_t value;
462    if (!getAbsoluteValueArg(asmr, value, linePtr, true))
463        return;
464    if (!checkGarbagesAtEnd(asmr, linePtr))
465        return;
466    handler.output.driverVersion = value;
467}
468
469void AsmAmdCL2PseudoOps::getDriverVersion(AsmAmdCL2Handler& handler, const char* linePtr)
470{
471    Assembler& asmr = handler.assembler;
472    const char* end = asmr.line + asmr.lineSize;
473    skipSpacesToEnd(linePtr, end);
474   
475    const char* symNamePlace = linePtr;
476    const CString symName = extractScopedSymName(linePtr, end, false);
477    if (symName.empty())
478        ASM_RETURN_BY_ERROR(symNamePlace, "Illegal symbol name")
479    size_t symNameLength = symName.size();
480    if (symNameLength >= 3 && symName.compare(symNameLength-3, 3, "::.")==0)
481        ASM_RETURN_BY_ERROR(symNamePlace, "Symbol '.' can be only in global scope")
482    if (!checkGarbagesAtEnd(asmr, linePtr))
483        return;
484   
485    cxuint driverVersion = handler.getDriverVersion();
486    std::pair<AsmSymbolEntry*, bool> res = asmr.insertSymbolInScope(symName,
487                AsmSymbol(ASMSECT_ABS, driverVersion));
488    if (!res.second)
489    {   // found
490        if (res.first->second.onceDefined && res.first->second.isDefined()) // if label
491            asmr.printError(symNamePlace, (std::string("Symbol '")+symName.c_str()+
492                        "' is already defined").c_str());
493        else // set value of symbol
494            asmr.setSymbol(*res.first, driverVersion, ASMSECT_ABS);
495    }
496}
497
498// go to inner binary
499void AsmAmdCL2PseudoOps::doInner(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
500                      const char* linePtr)
501{
502    Assembler& asmr = handler.assembler;
503    const char* end = asmr.line + asmr.lineSize;
504    skipSpacesToEnd(linePtr, end);
505    if (!checkGarbagesAtEnd(asmr, linePtr))
506        return;
507   
508    try
509    { handler.setCurrentKernel(ASMKERN_INNER); }
510    catch(const AsmFormatException& ex) // if error
511    {
512        asmr.printError(pseudoOpPlace, ex.what());
513        return;
514    }
515   
516    asmr.currentOutPos = asmr.sections[asmr.currentSection].getSize();
517}
518
519void AsmAmdCL2PseudoOps::doGlobalData(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
520                      const char* linePtr)
521{
522    Assembler& asmr = handler.assembler;
523    if (handler.getDriverVersion() < 191205)
524        PSEUDOOP_RETURN_BY_ERROR("Global Data allowed only for new binary format")
525    if (!checkGarbagesAtEnd(asmr, linePtr))
526        return;
527   
528    if (handler.rodataSection==ASMSECT_NONE)
529    {   /* add this section */
530        cxuint thisSection = handler.sections.size();
531        handler.sections.push_back({ ASMKERN_INNER,  AsmSectionType::DATA,
532            ELFSECTID_RODATA, ".rodata" });
533        handler.rodataSection = thisSection;
534    }
535    asmr.goToSection(pseudoOpPlace, handler.rodataSection);
536}
537
538void AsmAmdCL2PseudoOps::doRwData(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
539                      const char* linePtr)
540{
541    Assembler& asmr = handler.assembler;
542   
543    if (handler.getDriverVersion() < 191205)
544        PSEUDOOP_RETURN_BY_ERROR("Global RWData allowed only for new binary format")
545    if (!checkGarbagesAtEnd(asmr, linePtr))
546        return;
547   
548    if (handler.dataSection==ASMSECT_NONE)
549    {   /* add this section */
550        cxuint thisSection = handler.sections.size();
551        handler.sections.push_back({ ASMKERN_INNER,  AsmSectionType::AMDCL2_RWDATA,
552            ELFSECTID_DATA, ".data" });
553        handler.dataSection = thisSection;
554    }
555    asmr.goToSection(pseudoOpPlace, handler.dataSection);
556}
557
558void AsmAmdCL2PseudoOps::doBssData(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
559                      const char* linePtr)
560{
561    Assembler& asmr = handler.assembler;
562    const char* end = asmr.line + asmr.lineSize;
563   
564    if (handler.getDriverVersion() < 191205)
565        PSEUDOOP_RETURN_BY_ERROR("Global BSS allowed only for new binary format")
566   
567    uint64_t sectionAlign = 0;
568    bool good = true;
569    // parse alignment
570    skipSpacesToEnd(linePtr, end);
571    if (linePtr+6<end && ::strncasecmp(linePtr, "align", 5)==0 && !isAlpha(linePtr[5]))
572    {   // if alignment
573        linePtr+=5;
574        skipSpacesToEnd(linePtr, end);
575        if (linePtr!=end && *linePtr=='=')
576        {
577            skipCharAndSpacesToEnd(linePtr, end);
578            const char* valuePtr = linePtr;
579            if (getAbsoluteValueArg(asmr, sectionAlign, linePtr, true))
580            {
581                if (sectionAlign!=0 && (1ULL<<(63-CLZ64(sectionAlign))) != sectionAlign)
582                    ASM_NOTGOOD_BY_ERROR(valuePtr, "Alignment must be power of two or zero")
583            }
584            else
585                good = false;
586        }
587        else
588            ASM_NOTGOOD_BY_ERROR(linePtr, "Expected '=' after 'align'")
589    }
590   
591    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
592        return;
593   
594    if (handler.bssSection==ASMSECT_NONE)
595    {   /* add this section */
596        cxuint thisSection = handler.sections.size();
597        handler.sections.push_back({ ASMKERN_INNER,  AsmSectionType::AMDCL2_BSS,
598            ELFSECTID_BSS, ".bss" });
599        handler.bssSection = thisSection;
600    }
601   
602    asmr.goToSection(pseudoOpPlace, handler.bssSection, sectionAlign);
603}
604
605void AsmAmdCL2PseudoOps::doSamplerInit(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
606                      const char* linePtr)
607{
608    Assembler& asmr = handler.assembler;
609    if (handler.getDriverVersion() < 191205)
610        PSEUDOOP_RETURN_BY_ERROR("SamplerInit allowed only for new binary format")
611    if (handler.output.samplerConfig)
612        PSEUDOOP_RETURN_BY_ERROR("SamplerInit is illegal if sampler "
613                    "definitions are present")
614    if (!checkGarbagesAtEnd(asmr, linePtr))
615        return;
616   
617    if (handler.samplerInitSection==ASMSECT_NONE)
618    {   /* add this section */
619        cxuint thisSection = handler.sections.size();
620        handler.sections.push_back({ ASMKERN_INNER,  AsmSectionType::AMDCL2_SAMPLERINIT,
621            AMDCL2SECTID_SAMPLERINIT, nullptr });
622        handler.samplerInitSection = thisSection;
623    }
624    asmr.goToSection(pseudoOpPlace, handler.samplerInitSection);
625}
626
627void AsmAmdCL2PseudoOps::doSampler(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
628                      const char* linePtr)
629{
630    Assembler& asmr = handler.assembler;
631    if (asmr.currentKernel!=ASMKERN_GLOBAL && asmr.currentKernel!=ASMKERN_INNER &&
632        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
633        PSEUDOOP_RETURN_BY_ERROR("Illegal place of configuration pseudo-op")
634    if (handler.getDriverVersion() < 191205)
635        PSEUDOOP_RETURN_BY_ERROR("Sampler allowed only for new binary format")
636   
637    bool inMain = asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER;
638    const char* end = asmr.line + asmr.lineSize;
639    skipSpacesToEnd(linePtr, end);
640   
641    if (!inMain)
642    {
643        if (linePtr == end)
644            return; /* if no samplers */
645        AmdCL2KernelConfig& config = handler.output.kernels[asmr.currentKernel].config;
646        do {
647            uint64_t value = 0;
648            const char* valuePlace = linePtr;
649            if (getAbsoluteValueArg(asmr, value, linePtr, true))
650            {
651                asmr.printWarningForRange(sizeof(cxuint)<<3, value,
652                                 asmr.getSourcePos(valuePlace), WS_UNSIGNED);
653                config.samplers.push_back(value);
654            }
655        } while(skipCommaForMultipleArgs(asmr, linePtr));
656    }
657    else
658    {   // global sampler definitions
659        if (handler.samplerInitSection!=ASMSECT_NONE)
660            PSEUDOOP_RETURN_BY_ERROR("Illegal sampler definition if "
661                    "samplerinit was defined")
662        handler.output.samplerConfig = true;
663        if (linePtr == end)
664            return; /* if no samplers */
665        do {
666            uint64_t value = 0;
667            const char* valuePlace = linePtr;
668            if (getAbsoluteValueArg(asmr, value, linePtr, true))
669            {
670                asmr.printWarningForRange(sizeof(cxuint)<<3, value,
671                                 asmr.getSourcePos(valuePlace), WS_UNSIGNED);
672                handler.output.samplers.push_back(value);
673            }
674        } while(skipCommaForMultipleArgs(asmr, linePtr));
675    }
676    checkGarbagesAtEnd(asmr, linePtr);
677}
678
679void AsmAmdCL2PseudoOps::doSamplerReloc(AsmAmdCL2Handler& handler,
680                 const char* pseudoOpPlace, const char* linePtr)
681{
682    Assembler& asmr = handler.assembler;
683    const char* end = asmr.line + asmr.lineSize;
684   
685    if (asmr.currentKernel!=ASMKERN_GLOBAL && asmr.currentKernel!=ASMKERN_INNER)
686        PSEUDOOP_RETURN_BY_ERROR("Illegal place of samplerreloc pseudo-op")
687    if (handler.getDriverVersion() < 191205)
688        PSEUDOOP_RETURN_BY_ERROR("SamplerReloc allowed only for new binary format")
689   
690    skipSpacesToEnd(linePtr, end);
691    const char* offsetPlace = linePtr;
692    uint64_t samplerId = 0;
693    uint64_t offset = 0;
694    cxuint sectionId = 0;
695    bool good = getAnyValueArg(asmr, offset, sectionId, linePtr);
696    if (!skipRequiredComma(asmr, linePtr))
697        return;
698    good |= getAbsoluteValueArg(asmr, samplerId, linePtr, true);
699    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
700        return;
701   
702    if (sectionId != ASMSECT_ABS && sectionId != handler.rodataSection)
703        ASM_RETURN_BY_ERROR(offsetPlace, "Offset can be an absolute value "
704                        "or globaldata place")
705    // put to sampler offsets
706    if (handler.output.samplerOffsets.size() <= samplerId)
707        handler.output.samplerOffsets.resize(samplerId+1);
708    handler.output.samplerOffsets[samplerId] = offset;
709}
710
711void AsmAmdCL2PseudoOps::doControlDirective(AsmAmdCL2Handler& handler,
712              const char* pseudoOpPlace, const char* linePtr)
713{
714    Assembler& asmr = handler.assembler;
715    if (asmr.currentKernel==ASMKERN_GLOBAL)
716        PSEUDOOP_RETURN_BY_ERROR("Kernel control directive can be defined "
717                    "only inside kernel")
718    AsmAmdCL2Handler::Kernel& kernel = *handler.kernelStates[asmr.currentKernel];
719    if (kernel.metadataSection!=ASMSECT_NONE || kernel.isaMetadataSection!=ASMSECT_NONE ||
720        kernel.setupSection!=ASMSECT_NONE || kernel.stubSection!=ASMSECT_NONE)
721        PSEUDOOP_RETURN_BY_ERROR("Control directive "
722            "can't be defined if metadata,header,setup,stub section exists")
723    if (kernel.configSection != ASMSECT_NONE && !kernel.useHsaConfig)
724        // control directive only if hsa config
725        PSEUDOOP_RETURN_BY_ERROR("Config and Control directive can't be mixed")
726   
727    if (!checkGarbagesAtEnd(asmr, linePtr))
728        return;
729   
730    if (kernel.ctrlDirSection == ASMSECT_NONE)
731    {
732        cxuint thisSection = handler.sections.size();
733        handler.sections.push_back({ asmr.currentKernel,
734            AsmSectionType::AMDCL2_CONFIG_CTRL_DIRECTIVE,
735            ELFSECTID_UNDEF, nullptr });
736        kernel.ctrlDirSection = thisSection;
737    }
738    asmr.goToSection(pseudoOpPlace, kernel.ctrlDirSection);
739    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
740    kernel.useHsaConfig = true;
741    handler.output.kernels[asmr.currentKernel].hsaConfig = true;
742}
743
744
745void AsmAmdCL2PseudoOps::setConfigValue(AsmAmdCL2Handler& handler,
746         const char* pseudoOpPlace, const char* linePtr, AmdCL2ConfigValueTarget target)
747{
748    Assembler& asmr = handler.assembler;
749    const char* end = asmr.line + asmr.lineSize;
750   
751    if (asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER ||
752        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
753        PSEUDOOP_RETURN_BY_ERROR("Illegal place of configuration pseudo-op")
754    const bool useHsaConfig = handler.kernelStates[asmr.currentKernel]->useHsaConfig;
755    if (!useHsaConfig && (target >= AMDCL2CVAL_ONLY_HSA_FIRST_PARAM ||
756            target == AMDCL2CVAL_USERDATANUM))
757        PSEUDOOP_RETURN_BY_ERROR("HSAConfig pseudo-op only in HSAConfig")
758   
759    skipSpacesToEnd(linePtr, end);
760    const char* valuePlace = linePtr;
761    uint64_t value = BINGEN_NOTSUPPLIED;
762    bool good = getAbsoluteValueArg(asmr, value, linePtr, true);
763    /* ranges checking */
764    if (good)
765    {
766        if (useHsaConfig && target >= AMDCL2CVAL_HSA_FIRST_PARAM)
767            // hsa config
768            good = AsmROCmPseudoOps::checkConfigValue(asmr, valuePlace, 
769                    ROCmConfigValueTarget(cxuint(target) - AMDCL2CVAL_HSA_FIRST_PARAM),
770                    value);
771        else
772            switch(target)
773            {
774                case AMDCL2CVAL_SGPRSNUM:
775                {
776                    const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
777                                asmr.deviceType);
778                    cxuint maxSGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
779                    if (value > maxSGPRsNum)
780                    {
781                        char buf[64];
782                        snprintf(buf, 64,
783                                 "Used SGPRs number out of range (0-%u)", maxSGPRsNum);
784                        ASM_NOTGOOD_BY_ERROR(valuePlace, buf)
785                    }
786                    break;
787                }
788                case AMDCL2CVAL_VGPRSNUM:
789                {
790                    const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
791                                asmr.deviceType);
792                    cxuint maxVGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_VGPR, 0);
793                    if (value > maxVGPRsNum)
794                    {
795                        char buf[64];
796                        snprintf(buf, 64,
797                                 "Used VGPRs number out of range (0-%u)", maxVGPRsNum);
798                        ASM_NOTGOOD_BY_ERROR(valuePlace, buf)
799                    }
800                    break;
801                }
802                case AMDCL2CVAL_EXCEPTIONS:
803                    asmr.printWarningForRange(7, value,
804                                    asmr.getSourcePos(valuePlace), WS_UNSIGNED);
805                    value &= 0x7f;
806                    break;
807                case AMDCL2CVAL_FLOATMODE:
808                    asmr.printWarningForRange(8, value,
809                                    asmr.getSourcePos(valuePlace), WS_UNSIGNED);
810                    value &= 0xff;
811                    break;
812                case AMDCL2CVAL_PRIORITY:
813                    asmr.printWarningForRange(2, value,
814                                    asmr.getSourcePos(valuePlace), WS_UNSIGNED);
815                    value &= 3;
816                    break;
817                case AMDCL2CVAL_LOCALSIZE:
818                {
819                    const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
820                                asmr.deviceType);
821                    const cxuint maxLocalSize = getGPUMaxLocalSize(arch);
822                    if (value > maxLocalSize)
823                    {
824                        char buf[64];
825                        snprintf(buf, 64, "LocalSize out of range (0-%u)", maxLocalSize);
826                        ASM_NOTGOOD_BY_ERROR(valuePlace, buf)
827                    }
828                    break;
829                }
830                case AMDCL2CVAL_GDSSIZE:
831                {
832                    const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
833                                asmr.deviceType);
834                    const cxuint maxGDSSize = getGPUMaxGDSSize(arch);
835                    if (value > maxGDSSize)
836                    {
837                        char buf[64];
838                        snprintf(buf, 64, "GDSSize out of range (0-%u)", maxGDSSize);
839                        ASM_NOTGOOD_BY_ERROR(valuePlace, buf)
840                    }
841                    break;
842                }
843                case AMDCL2CVAL_PGMRSRC1:
844                case AMDCL2CVAL_PGMRSRC2:
845                    asmr.printWarningForRange(32, value,
846                                    asmr.getSourcePos(valuePlace), WS_UNSIGNED);
847                    break;
848                default:
849                    break;
850            }
851    }
852   
853    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
854        return;
855   
856    if (handler.kernelStates[asmr.currentKernel]->useHsaConfig &&
857        target >= AMDCL2CVAL_HSA_FIRST_PARAM)
858    {   // hsa config
859        AsmAmdHsaKernelConfig& config =
860                *(handler.kernelStates[asmr.currentKernel]->hsaConfig);
861       
862        AsmROCmPseudoOps::setConfigValueMain(config, ROCmConfigValueTarget(
863                cxuint(target) - AMDCL2CVAL_HSA_FIRST_PARAM), value);
864        return;
865    }
866   
867    AmdCL2KernelConfig& config = handler.output.kernels[asmr.currentKernel].config;
868    // set value
869    switch(target)
870    {
871        case AMDCL2CVAL_SGPRSNUM:
872            config.usedSGPRsNum = value;
873            break;
874        case AMDCL2CVAL_VGPRSNUM:
875            config.usedVGPRsNum = value;
876            break;
877        case AMDCL2CVAL_PGMRSRC1:
878            config.pgmRSRC1 = value;
879            break;
880        case AMDCL2CVAL_PGMRSRC2:
881            config.pgmRSRC2 = value;
882            break;
883        case AMDCL2CVAL_FLOATMODE:
884            config.floatMode = value;
885            break;
886        case AMDCL2CVAL_LOCALSIZE:
887            if (!useHsaConfig)
888                config.localSize = value;
889            else
890            {
891                AsmAmdHsaKernelConfig& hsaConfig = *(handler.
892                                kernelStates[asmr.currentKernel]->hsaConfig);
893                hsaConfig.workgroupGroupSegmentSize = value;
894            }
895            break;
896        case AMDCL2CVAL_GDSSIZE:
897            if (!useHsaConfig)
898                config.gdsSize = value;
899            else
900            {
901                AsmAmdHsaKernelConfig& hsaConfig = *(handler.
902                                kernelStates[asmr.currentKernel]->hsaConfig);
903                hsaConfig.gdsSegmentSize = value;
904            }
905            break;
906        case AMDCL2CVAL_SCRATCHBUFFER:
907            if (!useHsaConfig)
908                config.scratchBufferSize = value;
909            else
910            {
911                AsmAmdHsaKernelConfig& hsaConfig = *(handler.
912                                kernelStates[asmr.currentKernel]->hsaConfig);
913                hsaConfig.workitemPrivateSegmentSize = value;
914            }
915            break;
916        case AMDCL2CVAL_PRIORITY:
917            config.priority = value;
918            break;
919        case AMDCL2CVAL_EXCEPTIONS:
920            config.exceptions = value;
921            break;
922        default:
923            break;
924    }
925}
926
927void AsmAmdCL2PseudoOps::setConfigBoolValue(AsmAmdCL2Handler& handler,
928         const char* pseudoOpPlace, const char* linePtr, AmdCL2ConfigValueTarget target)
929{
930    Assembler& asmr = handler.assembler;
931   
932    if (asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER ||
933        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
934        PSEUDOOP_RETURN_BY_ERROR("Illegal place of configuration pseudo-op")
935   
936    const bool useHsaConfig = handler.kernelStates[asmr.currentKernel]->useHsaConfig;
937    if (useHsaConfig &&
938        (target == AMDCL2CVAL_USESETUP || target == AMDCL2CVAL_USEARGS ||
939         target == AMDCL2CVAL_USEENQUEUE || target == AMDCL2CVAL_USEGENERIC))
940        PSEUDOOP_RETURN_BY_ERROR("Illegal config pseudo-op in HSAConfig")
941    if (!useHsaConfig && target >= AMDCL2CVAL_ONLY_HSA_FIRST_PARAM)
942        PSEUDOOP_RETURN_BY_ERROR("HSAConfig pseudo-op only in HSAConfig")
943   
944    if (!checkGarbagesAtEnd(asmr, linePtr))
945        return;
946   
947    if (useHsaConfig)
948    {   // hsa config
949        AsmAmdHsaKernelConfig& config =
950                *(handler.kernelStates[asmr.currentKernel]->hsaConfig);
951       
952        AsmROCmPseudoOps::setConfigBoolValueMain(config, ROCmConfigValueTarget(
953                cxuint(target) - AMDCL2CVAL_HSA_FIRST_PARAM));
954        return;
955    }
956   
957    AmdCL2KernelConfig& config = handler.output.kernels[asmr.currentKernel].config;
958    switch(target)
959    {
960        case AMDCL2CVAL_DEBUGMODE:
961            config.debugMode = true;
962            break;
963        case AMDCL2CVAL_DX10CLAMP:
964            config.dx10Clamp = true;
965            break;
966        case AMDCL2CVAL_IEEEMODE:
967            config.ieeeMode = true;
968            break;
969        case AMDCL2CVAL_PRIVMODE:
970            config.privilegedMode = true;
971            break;
972        case AMDCL2CVAL_TGSIZE:
973            config.tgSize = true;
974            break;
975        case AMDCL2CVAL_USEARGS:
976            config.useArgs = true;
977            break;
978        case AMDCL2CVAL_USESETUP:
979            config.useSetup = true;
980            break;
981        case AMDCL2CVAL_USEENQUEUE:
982            config.useEnqueue = true;
983            break;
984        case AMDCL2CVAL_USEGENERIC:
985            config.useGeneric = true;
986            break;
987        default:
988            break;
989    }
990}
991
992void AsmAmdCL2PseudoOps::setDefaultHSAFeatures(AsmAmdCL2Handler& handler,
993                const char* pseudoOpPlace, const char* linePtr)
994{
995    Assembler& asmr = handler.assembler;
996    if (asmr.currentKernel==ASMKERN_GLOBAL ||
997        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
998        PSEUDOOP_RETURN_BY_ERROR("Illegal place of configuration pseudo-op")
999    if (!handler.kernelStates[asmr.currentKernel]->useHsaConfig)
1000        PSEUDOOP_RETURN_BY_ERROR("HSAConfig pseudo-op only in HSAConfig")
1001   
1002    if (!checkGarbagesAtEnd(asmr, linePtr))
1003        return;
1004   
1005    AsmAmdHsaKernelConfig* config =
1006            handler.kernelStates[asmr.currentKernel]->hsaConfig.get();
1007    config->enableSgprRegisterFlags = uint16_t(AMDHSAFLAG_USE_PRIVATE_SEGMENT_BUFFER|
1008                        AMDHSAFLAG_USE_KERNARG_SEGMENT_PTR);
1009    config->enableFeatureFlags = uint16_t((asmr._64bit ? AMDHSAFLAG_USE_PTR64 : 0) | 2);
1010}
1011
1012void AsmAmdCL2PseudoOps::setDimensions(AsmAmdCL2Handler& handler,
1013                   const char* pseudoOpPlace, const char* linePtr)
1014{
1015    Assembler& asmr = handler.assembler;
1016    if (asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER ||
1017        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
1018        PSEUDOOP_RETURN_BY_ERROR("Illegal place of configuration pseudo-op")
1019    cxuint dimMask = 0;
1020    if (!parseDimensions(asmr, linePtr, dimMask))
1021        return;
1022    if (!checkGarbagesAtEnd(asmr, linePtr))
1023        return;
1024    if (!handler.kernelStates[asmr.currentKernel]->useHsaConfig)
1025        handler.output.kernels[asmr.currentKernel].config.dimMask = dimMask;
1026    else // if HSA config
1027        handler.kernelStates[asmr.currentKernel]->hsaConfig->dimMask = dimMask;
1028}
1029
1030void AsmAmdCL2PseudoOps::setMachine(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
1031                      const char* linePtr)
1032{
1033    Assembler& asmr = handler.assembler;
1034    if (asmr.currentKernel==ASMKERN_GLOBAL ||
1035        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
1036        PSEUDOOP_RETURN_BY_ERROR("Illegal place of configuration pseudo-op")
1037    if (!handler.kernelStates[asmr.currentKernel]->useHsaConfig)
1038        PSEUDOOP_RETURN_BY_ERROR("HSAConfig pseudo-op only in HSAConfig")
1039   
1040    uint16_t kindValue = 0, majorValue = 0;
1041    uint16_t minorValue = 0, steppingValue = 0;
1042    if (!AsmROCmPseudoOps::parseMachine(asmr, linePtr, kindValue,
1043                    majorValue, minorValue, steppingValue))
1044        return;
1045   
1046    AsmAmdHsaKernelConfig* config =
1047            handler.kernelStates[asmr.currentKernel]->hsaConfig.get();
1048    config->amdMachineKind = kindValue;
1049    config->amdMachineMajor = majorValue;
1050    config->amdMachineMinor = minorValue;
1051    config->amdMachineStepping = steppingValue;
1052}
1053
1054void AsmAmdCL2PseudoOps::setCodeVersion(AsmAmdCL2Handler& handler,
1055                const char* pseudoOpPlace, const char* linePtr)
1056{
1057    Assembler& asmr = handler.assembler;
1058    if (asmr.currentKernel==ASMKERN_GLOBAL ||
1059        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
1060        PSEUDOOP_RETURN_BY_ERROR("Illegal place of configuration pseudo-op")
1061    if (!handler.kernelStates[asmr.currentKernel]->useHsaConfig)
1062        PSEUDOOP_RETURN_BY_ERROR("HSAConfig pseudo-op only in HSAConfig")
1063   
1064    uint16_t majorValue = 0, minorValue = 0;
1065    if (!AsmROCmPseudoOps::parseCodeVersion(asmr, linePtr, majorValue, minorValue))
1066        return;
1067   
1068    AsmAmdHsaKernelConfig* config =
1069            handler.kernelStates[asmr.currentKernel]->hsaConfig.get();
1070    config->amdCodeVersionMajor = majorValue;
1071    config->amdCodeVersionMinor = minorValue;
1072}
1073
1074void AsmAmdCL2PseudoOps::setReservedXgprs(AsmAmdCL2Handler& handler,
1075                const char* pseudoOpPlace, const char* linePtr, bool inVgpr)
1076{
1077    Assembler& asmr = handler.assembler;
1078    if (asmr.currentKernel==ASMKERN_GLOBAL ||
1079        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
1080        PSEUDOOP_RETURN_BY_ERROR("Illegal place of configuration pseudo-op")
1081    if (!handler.kernelStates[asmr.currentKernel]->useHsaConfig)
1082        PSEUDOOP_RETURN_BY_ERROR("HSAConfig pseudo-op only in HSAConfig")
1083   
1084    uint16_t gprFirst = 0, gprCount = 0;
1085    if (!AsmROCmPseudoOps::parseReservedXgprs(asmr, linePtr, inVgpr, gprFirst, gprCount))
1086        return;
1087   
1088    AsmAmdHsaKernelConfig* config =
1089            handler.kernelStates[asmr.currentKernel]->hsaConfig.get();
1090    if (inVgpr)
1091    {
1092        config->reservedVgprFirst = gprFirst;
1093        config->reservedVgprCount = gprCount;
1094    }
1095    else
1096    {
1097        config->reservedSgprFirst = gprFirst;
1098        config->reservedSgprCount = gprCount;
1099    }
1100}
1101
1102
1103void AsmAmdCL2PseudoOps::setUseGridWorkGroupCount(AsmAmdCL2Handler& handler,
1104                   const char* pseudoOpPlace, const char* linePtr)
1105{
1106    Assembler& asmr = handler.assembler;
1107    if (asmr.currentKernel==ASMKERN_GLOBAL ||
1108        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
1109        PSEUDOOP_RETURN_BY_ERROR("Illegal place of configuration pseudo-op")
1110    if (!handler.kernelStates[asmr.currentKernel]->useHsaConfig)
1111        PSEUDOOP_RETURN_BY_ERROR("HSAConfig pseudo-op only in HSAConfig")
1112   
1113    cxuint dimMask = 0;
1114    if (!parseDimensions(asmr, linePtr, dimMask))
1115        return;
1116    if (!checkGarbagesAtEnd(asmr, linePtr))
1117        return;
1118    uint16_t& flags = handler.kernelStates[asmr.currentKernel]->hsaConfig->
1119                enableSgprRegisterFlags;
1120    flags = (flags & ~(7<<AMDHSAFLAG_USE_GRID_WORKGROUP_COUNT_BIT)) |
1121            (dimMask<<AMDHSAFLAG_USE_GRID_WORKGROUP_COUNT_BIT);
1122}
1123
1124void AsmAmdCL2PseudoOps::setCWS(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
1125                      const char* linePtr)
1126{
1127    Assembler& asmr = handler.assembler;
1128    const char* end = asmr.line + asmr.lineSize;
1129    if (asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER ||
1130        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
1131        PSEUDOOP_RETURN_BY_ERROR("Illegal place of configuration pseudo-op")
1132   
1133    skipSpacesToEnd(linePtr, end);
1134    uint64_t out[3] = { 0, 0, 0 };
1135    if (!AsmAmdPseudoOps::parseCWS(asmr, pseudoOpPlace, linePtr, out))
1136        return;
1137    AmdCL2KernelConfig& config = handler.output.kernels[asmr.currentKernel].config;
1138    config.reqdWorkGroupSize[0] = out[0];
1139    config.reqdWorkGroupSize[1] = out[1];
1140    config.reqdWorkGroupSize[2] = out[2];
1141}
1142
1143void AsmAmdCL2PseudoOps::doArg(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
1144                      const char* linePtr)
1145{
1146    Assembler& asmr = handler.assembler;
1147    if (asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER ||
1148        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
1149        PSEUDOOP_RETURN_BY_ERROR("Illegal place of kernel argument")
1150   
1151    auto& kernelState = *handler.kernelStates[asmr.currentKernel];
1152    AmdKernelArgInput argInput;
1153    if (!AsmAmdPseudoOps::parseArg(asmr, pseudoOpPlace, linePtr, kernelState.argNamesSet,
1154                    argInput, true))
1155        return;
1156    /* setup argument */
1157    AmdCL2KernelConfig& config = handler.output.kernels[asmr.currentKernel].config;
1158    const CString argName = argInput.argName;
1159    config.args.push_back(std::move(argInput));
1160    /// put argName
1161    kernelState.argNamesSet.insert(argName);
1162}
1163
1164/// AMD OpenCL kernel argument description
1165struct CLRX_INTERNAL IntAmdCL2KernelArg
1166{
1167    const char* argName;
1168    const char* typeName;
1169    KernelArgType argType;
1170    KernelArgType pointerType;
1171    KernelPtrSpace ptrSpace;
1172    cxbyte ptrAccess;
1173    cxbyte used;
1174};
1175
1176static const IntAmdCL2KernelArg setupArgsTable64[] =
1177{
1178    { "_.global_offset_0", "size_t", KernelArgType::LONG, KernelArgType::VOID,
1179        KernelPtrSpace::NONE, KARG_PTR_NORMAL, 0 },
1180    { "_.global_offset_1", "size_t", KernelArgType::LONG, KernelArgType::VOID,
1181        KernelPtrSpace::NONE, KARG_PTR_NORMAL, 0 },
1182    { "_.global_offset_2", "size_t", KernelArgType::LONG, KernelArgType::VOID,
1183        KernelPtrSpace::NONE, KARG_PTR_NORMAL, 0 },
1184    { "_.printf_buffer", "size_t", KernelArgType::POINTER, KernelArgType::VOID,
1185        KernelPtrSpace::GLOBAL, KARG_PTR_NORMAL, AMDCL2_ARGUSED_READ_WRITE },
1186    { "_.vqueue_pointer", "size_t", KernelArgType::LONG, KernelArgType::VOID,
1187        KernelPtrSpace::NONE, KARG_PTR_NORMAL, 0 },
1188    { "_.aqlwrap_pointer", "size_t", KernelArgType::LONG, KernelArgType::VOID,
1189        KernelPtrSpace::NONE, KARG_PTR_NORMAL, 0 }
1190};
1191
1192static const IntAmdCL2KernelArg setupArgsTable32[] =
1193{
1194    { "_.global_offset_0", "size_t", KernelArgType::INT, KernelArgType::VOID,
1195        KernelPtrSpace::NONE, KARG_PTR_NORMAL, 0 },
1196    { "_.global_offset_1", "size_t", KernelArgType::INT, KernelArgType::VOID,
1197        KernelPtrSpace::NONE, KARG_PTR_NORMAL, 0 },
1198    { "_.global_offset_2", "size_t", KernelArgType::INT, KernelArgType::VOID,
1199        KernelPtrSpace::NONE, KARG_PTR_NORMAL, 0 },
1200    { "_.printf_buffer", "size_t", KernelArgType::POINTER, KernelArgType::VOID,
1201        KernelPtrSpace::GLOBAL, KARG_PTR_NORMAL, AMDCL2_ARGUSED_READ_WRITE },
1202    { "_.vqueue_pointer", "size_t", KernelArgType::INT, KernelArgType::VOID,
1203        KernelPtrSpace::NONE, KARG_PTR_NORMAL, 0 },
1204    { "_.aqlwrap_pointer", "size_t", KernelArgType::INT, KernelArgType::VOID,
1205        KernelPtrSpace::NONE, KARG_PTR_NORMAL, 0 }
1206};
1207
1208
1209void AsmAmdCL2PseudoOps::doSetupArgs(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
1210                       const char* linePtr)
1211{
1212    Assembler& asmr = handler.assembler;
1213    if (asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER ||
1214        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
1215        PSEUDOOP_RETURN_BY_ERROR("Illegal place of kernel argument")
1216   
1217    auto& kernelState = *handler.kernelStates[asmr.currentKernel];
1218    if (!kernelState.argNamesSet.empty())
1219        PSEUDOOP_RETURN_BY_ERROR("SetupArgs must be as first in argument list")
1220    if (!checkGarbagesAtEnd(asmr, linePtr))
1221        return;
1222   
1223    AmdCL2KernelConfig& config = handler.output.kernels[asmr.currentKernel].config;
1224    const IntAmdCL2KernelArg* argTable = asmr._64bit ? setupArgsTable64 : setupArgsTable32;
1225    for (size_t i = 0; i < 6; i++)
1226    {
1227        const IntAmdCL2KernelArg& arg = argTable[i];
1228        kernelState.argNamesSet.insert(arg.argName);
1229        config.args.push_back({arg.argName, arg.typeName, arg.argType, arg.pointerType,
1230                arg.ptrSpace, arg.ptrAccess, arg.used });
1231    }
1232}
1233
1234void AsmAmdCL2PseudoOps::addMetadata(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
1235                      const char* linePtr)
1236{
1237    Assembler& asmr = handler.assembler;
1238   
1239    if (asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER)
1240        PSEUDOOP_RETURN_BY_ERROR("Metadata can be defined only inside kernel")
1241    if (handler.kernelStates[asmr.currentKernel]->configSection!=ASMSECT_NONE)
1242        PSEUDOOP_RETURN_BY_ERROR("Metadata can't be defined if configuration was defined")
1243   
1244    if (!checkGarbagesAtEnd(asmr, linePtr))
1245        return;
1246   
1247    cxuint& metadataSection = handler.kernelStates[asmr.currentKernel]->metadataSection;
1248    if (metadataSection == ASMSECT_NONE)
1249    {
1250        cxuint thisSection = handler.sections.size();
1251        handler.sections.push_back({ asmr.currentKernel, AsmSectionType::AMDCL2_METADATA,
1252            ELFSECTID_UNDEF, nullptr });
1253        metadataSection = thisSection;
1254    }
1255    asmr.goToSection(pseudoOpPlace, metadataSection);
1256}
1257
1258void AsmAmdCL2PseudoOps::addISAMetadata(AsmAmdCL2Handler& handler,
1259                const char* pseudoOpPlace, const char* linePtr)
1260{
1261    Assembler& asmr = handler.assembler;
1262   
1263    if (asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER)
1264        PSEUDOOP_RETURN_BY_ERROR("ISAMetadata can be defined only inside kernel")
1265    if (handler.kernelStates[asmr.currentKernel]->configSection!=ASMSECT_NONE)
1266        PSEUDOOP_RETURN_BY_ERROR("ISAMetadata can't be defined if configuration "
1267                "was defined")
1268    if (handler.getDriverVersion() >= 191205)
1269        PSEUDOOP_RETURN_BY_ERROR("ISA Metadata allowed only for old binary format")
1270   
1271    if (!checkGarbagesAtEnd(asmr, linePtr))
1272        return;
1273   
1274    cxuint& isaMDSection = handler.kernelStates[asmr.currentKernel]->isaMetadataSection;
1275    if (isaMDSection == ASMSECT_NONE)
1276    {
1277        cxuint thisSection = handler.sections.size();
1278        handler.sections.push_back({ asmr.currentKernel,
1279                AsmSectionType::AMDCL2_ISAMETADATA, ELFSECTID_UNDEF, nullptr });
1280        isaMDSection = thisSection;
1281    }
1282    asmr.goToSection(pseudoOpPlace, isaMDSection);
1283}
1284
1285void AsmAmdCL2PseudoOps::addKernelSetup(AsmAmdCL2Handler& handler,
1286                const char* pseudoOpPlace, const char* linePtr)
1287{
1288    Assembler& asmr = handler.assembler;
1289   
1290    if (asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER)
1291        PSEUDOOP_RETURN_BY_ERROR("Setup can be defined only inside kernel")
1292    if (handler.kernelStates[asmr.currentKernel]->configSection!=ASMSECT_NONE)
1293        PSEUDOOP_RETURN_BY_ERROR("Setup can't be defined if configuration was defined")
1294   
1295    if (!checkGarbagesAtEnd(asmr, linePtr))
1296        return;
1297   
1298    cxuint& setupSection = handler.kernelStates[asmr.currentKernel]->setupSection;
1299    if (setupSection == ASMSECT_NONE)
1300    {
1301        cxuint thisSection = handler.sections.size();
1302        handler.sections.push_back({ asmr.currentKernel, AsmSectionType::AMDCL2_SETUP,
1303            ELFSECTID_UNDEF, nullptr });
1304        setupSection = thisSection;
1305    }
1306    asmr.goToSection(pseudoOpPlace, setupSection);
1307}
1308
1309void AsmAmdCL2PseudoOps::addKernelStub(AsmAmdCL2Handler& handler,
1310                const char* pseudoOpPlace, const char* linePtr)
1311{
1312    Assembler& asmr = handler.assembler;
1313   
1314    if (asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER)
1315        PSEUDOOP_RETURN_BY_ERROR("Stub can be defined only inside kernel")
1316    if (handler.kernelStates[asmr.currentKernel]->configSection!=ASMSECT_NONE)
1317        PSEUDOOP_RETURN_BY_ERROR("Stub can't be defined if configuration was defined")
1318    if (handler.getDriverVersion() >= 191205)
1319        PSEUDOOP_RETURN_BY_ERROR("Stub allowed only for old binary format")
1320   
1321    if (!checkGarbagesAtEnd(asmr, linePtr))
1322        return;
1323   
1324    cxuint& stubSection = handler.kernelStates[asmr.currentKernel]->stubSection;
1325    if (stubSection == ASMSECT_NONE)
1326    {
1327        cxuint thisSection = handler.sections.size();
1328        handler.sections.push_back({ asmr.currentKernel, AsmSectionType::AMDCL2_STUB,
1329            ELFSECTID_UNDEF, nullptr });
1330        stubSection = thisSection;
1331    }
1332    asmr.goToSection(pseudoOpPlace, stubSection);
1333}
1334
1335void AsmAmdCL2PseudoOps::doConfig(AsmAmdCL2Handler& handler, const char* pseudoOpPlace,
1336                      const char* linePtr, bool hsaConfig)
1337{
1338    Assembler& asmr = handler.assembler;
1339    if (asmr.currentKernel==ASMKERN_GLOBAL || asmr.currentKernel==ASMKERN_INNER)
1340        PSEUDOOP_RETURN_BY_ERROR("Kernel config can be defined only inside kernel")
1341    AsmAmdCL2Handler::Kernel& kernel = *handler.kernelStates[asmr.currentKernel];
1342    if (kernel.metadataSection!=ASMSECT_NONE || kernel.isaMetadataSection!=ASMSECT_NONE ||
1343        kernel.setupSection!=ASMSECT_NONE || kernel.stubSection!=ASMSECT_NONE)
1344        PSEUDOOP_RETURN_BY_ERROR("Config can't be defined if metadata,header,setup,"
1345                        "stub section exists")
1346    if (kernel.configSection != ASMSECT_NONE && kernel.useHsaConfig != hsaConfig)
1347        // if config defined and doesn't match type of config
1348        PSEUDOOP_RETURN_BY_ERROR("Config and HSAConfig can't be mixed")
1349   
1350    if (!checkGarbagesAtEnd(asmr, linePtr))
1351        return;
1352   
1353    if (kernel.configSection == ASMSECT_NONE)
1354    {
1355        cxuint thisSection = handler.sections.size();
1356        handler.sections.push_back({ asmr.currentKernel, AsmSectionType::CONFIG,
1357            ELFSECTID_UNDEF, nullptr });
1358        kernel.configSection = thisSection;
1359    }
1360    asmr.goToSection(pseudoOpPlace, kernel.configSection);
1361    kernel.useHsaConfig = hsaConfig;
1362    if (hsaConfig)
1363        handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
1364    handler.output.kernels[asmr.currentKernel].hsaConfig = hsaConfig;
1365    handler.output.kernels[asmr.currentKernel].useConfig = true;
1366}
1367
1368};
1369
1370bool AsmAmdCL2Handler::parsePseudoOp(const CString& firstName,
1371       const char* stmtPlace, const char* linePtr)
1372{
1373    const size_t pseudoOp = binaryFind(amdCL2PseudoOpNamesTbl, amdCL2PseudoOpNamesTbl +
1374                    sizeof(amdCL2PseudoOpNamesTbl)/sizeof(char*), firstName.c_str()+1,
1375                   CStringLess()) - amdCL2PseudoOpNamesTbl;
1376   
1377    switch(pseudoOp)
1378    {
1379        case AMDCL2OP_ACL_VERSION:
1380            AsmAmdCL2PseudoOps::setAclVersion(*this, linePtr);
1381            break;
1382        case AMDCL2OP_ARCH_MINOR:
1383            AsmAmdCL2PseudoOps::setArchMinor(*this, linePtr);
1384            break;
1385        case AMDCL2OP_ARCH_STEPPING:
1386            AsmAmdCL2PseudoOps::setArchStepping(*this, linePtr);
1387            break;
1388        case AMDCL2OP_ARG:
1389            AsmAmdCL2PseudoOps::doArg(*this, stmtPlace, linePtr);
1390            break;
1391        case AMDCL2OP_BSSDATA:
1392            AsmAmdCL2PseudoOps::doBssData(*this, stmtPlace, linePtr);
1393            break;
1394        case AMDCL2OP_CALL_CONVENTION:
1395            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1396                             AMDCL2CVAL_CALL_CONVENTION);
1397            break;
1398        case AMDCL2OP_CODEVERSION:
1399            AsmAmdCL2PseudoOps::setCodeVersion(*this, stmtPlace, linePtr);
1400            break;
1401        case AMDCL2OP_COMPILE_OPTIONS:
1402            AsmAmdCL2PseudoOps::setCompileOptions(*this, linePtr);
1403            break;
1404        case AMDCL2OP_CONFIG:
1405            AsmAmdCL2PseudoOps::doConfig(*this, stmtPlace, linePtr, false);
1406            break;
1407        case AMDCL2OP_CONTROL_DIRECTIVE:
1408            AsmAmdCL2PseudoOps::doControlDirective(*this, stmtPlace, linePtr);
1409            break;
1410        case AMDCL2OP_CWS:
1411            AsmAmdCL2PseudoOps::setCWS(*this, stmtPlace, linePtr);
1412            break;
1413        case AMDCL2OP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR:
1414            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1415                             AMDCL2CVAL_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR);
1416            break;
1417        case AMDCL2OP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR:
1418            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1419                         AMDCL2CVAL_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR);
1420            break;
1421        case AMDCL2OP_DEBUGMODE:
1422            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1423                       AMDCL2CVAL_DEBUGMODE);
1424            break;
1425        case AMDCL2OP_DEFAULT_HSA_FEATURES:
1426            AsmAmdCL2PseudoOps::setDefaultHSAFeatures(*this, stmtPlace, linePtr);
1427            break;
1428        case AMDCL2OP_DIMS:
1429            AsmAmdCL2PseudoOps::setDimensions(*this, stmtPlace, linePtr);
1430            break;
1431        case AMDCL2OP_DRIVER_VERSION:
1432            AsmAmdCL2PseudoOps::setDriverVersion(*this, linePtr);
1433            break;
1434        case AMDCL2OP_DX10CLAMP:
1435            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1436                       AMDCL2CVAL_DX10CLAMP);
1437            break;
1438        case AMDCL2OP_EXCEPTIONS:
1439            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1440                       AMDCL2CVAL_EXCEPTIONS);
1441            break;
1442        case AMDCL2OP_FLOATMODE:
1443            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1444                       AMDCL2CVAL_FLOATMODE);
1445            break;
1446        case AMDCL2OP_GDS_SEGMENT_SIZE:
1447            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1448                             AMDCL2CVAL_GDS_SEGMENT_SIZE);
1449            break;
1450        case AMDCL2OP_GROUP_SEGMENT_ALIGN:
1451            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1452                             AMDCL2CVAL_GROUP_SEGMENT_ALIGN);
1453            break;
1454        case AMDCL2OP_GDSSIZE:
1455            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1456                       AMDCL2CVAL_GDSSIZE);
1457            break;
1458        case AMDCL2OP_GET_DRIVER_VERSION:
1459            AsmAmdCL2PseudoOps::getDriverVersion(*this, linePtr);
1460            break;
1461        case AMDCL2OP_GLOBALDATA:
1462            AsmAmdCL2PseudoOps::doGlobalData(*this, stmtPlace, linePtr);
1463            break;
1464        case AMDCL2OP_HSACONFIG:
1465            AsmAmdCL2PseudoOps::doConfig(*this, stmtPlace, linePtr, true);
1466            break;
1467        case AMDCL2OP_IEEEMODE:
1468            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1469                       AMDCL2CVAL_IEEEMODE);
1470            break;
1471        case AMDCL2OP_INNER:
1472            AsmAmdCL2PseudoOps::doInner(*this, stmtPlace, linePtr);
1473            break;
1474        case AMDCL2OP_ISAMETADATA:
1475            AsmAmdCL2PseudoOps::addISAMetadata(*this, stmtPlace, linePtr);
1476            break;
1477        case AMDCL2OP_KERNARG_SEGMENT_ALIGN:
1478            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1479                             AMDCL2CVAL_KERNARG_SEGMENT_ALIGN);
1480            break;
1481        case AMDCL2OP_KERNARG_SEGMENT_SIZE:
1482            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1483                             AMDCL2CVAL_KERNARG_SEGMENT_SIZE);
1484            break;
1485        case AMDCL2OP_KERNEL_CODE_ENTRY_OFFSET:
1486            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1487                             AMDCL2CVAL_KERNEL_CODE_ENTRY_OFFSET);
1488            break;
1489        case AMDCL2OP_KERNEL_CODE_PREFETCH_OFFSET:
1490            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1491                             AMDCL2CVAL_KERNEL_CODE_PREFETCH_OFFSET);
1492            break;
1493        case AMDCL2OP_KERNEL_CODE_PREFETCH_SIZE:
1494            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1495                             AMDCL2CVAL_KERNEL_CODE_PREFETCH_SIZE);
1496            break;
1497        case AMDCL2OP_LOCALSIZE:
1498            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1499                       AMDCL2CVAL_LOCALSIZE);
1500            break;
1501        case AMDCL2OP_MACHINE:
1502            AsmAmdCL2PseudoOps::setMachine(*this, stmtPlace, linePtr);
1503            break;
1504        case AMDCL2OP_MAX_SCRATCH_BACKING_MEMORY:
1505            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1506                             AMDCL2CVAL_MAX_SCRATCH_BACKING_MEMORY);
1507            break;
1508        case AMDCL2OP_METADATA:
1509            AsmAmdCL2PseudoOps::addMetadata(*this, stmtPlace, linePtr);
1510            break;
1511        case AMDCL2OP_PRIVATE_ELEM_SIZE:
1512            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1513                             AMDCL2CVAL_PRIVATE_ELEM_SIZE);
1514            break;
1515        case AMDCL2OP_PRIVATE_SEGMENT_ALIGN:
1516            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1517                             AMDCL2CVAL_PRIVATE_SEGMENT_ALIGN);
1518            break;
1519        case AMDCL2OP_PRIVMODE:
1520            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1521                       AMDCL2CVAL_PRIVMODE);
1522            break;
1523        case AMDCL2OP_PGMRSRC1:
1524            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1525                       AMDCL2CVAL_PGMRSRC1);
1526            break;
1527        case AMDCL2OP_PGMRSRC2:
1528            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1529                       AMDCL2CVAL_PGMRSRC2);
1530            break;
1531        case AMDCL2OP_PRIORITY:
1532            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1533                       AMDCL2CVAL_PRIORITY);
1534            break;
1535        case AMDCL2OP_RESERVED_SGPRS:
1536            AsmAmdCL2PseudoOps::setReservedXgprs(*this, stmtPlace, linePtr, false);
1537            break;
1538        case AMDCL2OP_RESERVED_VGPRS:
1539            AsmAmdCL2PseudoOps::setReservedXgprs(*this, stmtPlace, linePtr, true);
1540            break;
1541        case AMDCL2OP_RUNTIME_LOADER_KERNEL_SYMBOL:
1542            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1543                             AMDCL2CVAL_RUNTIME_LOADER_KERNEL_SYMBOL);
1544            break;
1545        case AMDCL2OP_RWDATA:
1546            AsmAmdCL2PseudoOps::doRwData(*this, stmtPlace, linePtr);
1547            break;
1548        case AMDCL2OP_SAMPLER:
1549            AsmAmdCL2PseudoOps::doSampler(*this, stmtPlace, linePtr);
1550            break;
1551        case AMDCL2OP_SAMPLERINIT:
1552            AsmAmdCL2PseudoOps::doSamplerInit(*this, stmtPlace, linePtr);
1553            break;
1554        case AMDCL2OP_SAMPLERRELOC:
1555            AsmAmdCL2PseudoOps::doSamplerReloc(*this, stmtPlace, linePtr);
1556            break;
1557        case AMDCL2OP_SCRATCHBUFFER:
1558            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1559                       AMDCL2CVAL_SCRATCHBUFFER);
1560            break;
1561        case AMDCL2OP_SETUP:
1562            AsmAmdCL2PseudoOps::addKernelSetup(*this, stmtPlace, linePtr);
1563            break;
1564        case AMDCL2OP_SETUPARGS:
1565            AsmAmdCL2PseudoOps::doSetupArgs(*this, stmtPlace, linePtr);
1566            break;
1567        case AMDCL2OP_SGPRSNUM:
1568            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1569                       AMDCL2CVAL_SGPRSNUM);
1570            break;
1571        case AMDCL2OP_STUB:
1572            AsmAmdCL2PseudoOps::addKernelStub(*this, stmtPlace, linePtr);
1573            break;
1574        case AMDCL2OP_TGSIZE:
1575            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1576                       AMDCL2CVAL_TGSIZE);
1577            break;
1578        case AMDCL2OP_USE_DEBUG_ENABLED:
1579            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1580                             AMDCL2CVAL_USE_DEBUG_ENABLED);
1581            break;
1582        case AMDCL2OP_USE_DISPATCH_ID:
1583            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1584                             AMDCL2CVAL_USE_DISPATCH_ID);
1585            break;
1586        case AMDCL2OP_USE_DISPATCH_PTR:
1587            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1588                             AMDCL2CVAL_USE_DISPATCH_PTR);
1589            break;
1590        case AMDCL2OP_USE_DYNAMIC_CALL_STACK:
1591            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1592                             AMDCL2CVAL_USE_DYNAMIC_CALL_STACK);
1593            break;
1594        case AMDCL2OP_USE_FLAT_SCRATCH_INIT:
1595            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1596                             AMDCL2CVAL_USE_FLAT_SCRATCH_INIT);
1597            break;
1598        case AMDCL2OP_USE_GRID_WORKGROUP_COUNT:
1599            AsmAmdCL2PseudoOps::setUseGridWorkGroupCount(*this, stmtPlace, linePtr);
1600            break;
1601        case AMDCL2OP_USE_KERNARG_SEGMENT_PTR:
1602            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1603                             AMDCL2CVAL_USE_KERNARG_SEGMENT_PTR);
1604            break;
1605        case AMDCL2OP_USE_ORDERED_APPEND_GDS:
1606            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1607                             AMDCL2CVAL_USE_ORDERED_APPEND_GDS);
1608            break;
1609        case AMDCL2OP_USE_PRIVATE_SEGMENT_SIZE:
1610            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1611                             AMDCL2CVAL_USE_PRIVATE_SEGMENT_SIZE);
1612            break;
1613        case AMDCL2OP_USE_PTR64:
1614            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1615                             AMDCL2CVAL_USE_PTR64);
1616            break;
1617        case AMDCL2OP_USE_QUEUE_PTR:
1618            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1619                             AMDCL2CVAL_USE_QUEUE_PTR);
1620            break;
1621        case AMDCL2OP_USE_PRIVATE_SEGMENT_BUFFER:
1622            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1623                             AMDCL2CVAL_USE_PRIVATE_SEGMENT_BUFFER);
1624            break;
1625        case AMDCL2OP_USE_XNACK_ENABLED:
1626            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1627                             AMDCL2CVAL_USE_XNACK_ENABLED);
1628            break;
1629        case AMDCL2OP_USEARGS:
1630            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1631                       AMDCL2CVAL_USEARGS);
1632            break;
1633        case AMDCL2OP_USEENQUEUE:
1634            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1635                       AMDCL2CVAL_USEENQUEUE);
1636            break;
1637        case AMDCL2OP_USEGENERIC:
1638            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1639                       AMDCL2CVAL_USEGENERIC);
1640            break;
1641        case AMDCL2OP_USESETUP:
1642            AsmAmdCL2PseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1643                       AMDCL2CVAL_USESETUP);
1644            break;
1645        case AMDCL2OP_USERDATANUM:
1646            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1647                       AMDCL2CVAL_USERDATANUM);
1648            break;
1649        case AMDCL2OP_VGPRSNUM:
1650            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1651                       AMDCL2CVAL_VGPRSNUM);
1652            break;
1653        case AMDCL2OP_WAVEFRONT_SGPR_COUNT:
1654            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1655                             AMDCL2CVAL_WAVEFRONT_SGPR_COUNT);
1656            break;
1657        case AMDCL2OP_WAVEFRONT_SIZE:
1658            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1659                             AMDCL2CVAL_WAVEFRONT_SIZE);
1660            break;
1661        case AMDCL2OP_WORKITEM_VGPR_COUNT:
1662            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1663                             AMDCL2CVAL_WORKITEM_VGPR_COUNT);
1664            break;
1665        case AMDCL2OP_WORKGROUP_FBARRIER_COUNT:
1666            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1667                             AMDCL2CVAL_WORKGROUP_FBARRIER_COUNT);
1668            break;
1669        case AMDCL2OP_WORKGROUP_GROUP_SEGMENT_SIZE:
1670            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1671                             AMDCL2CVAL_WORKGROUP_GROUP_SEGMENT_SIZE);
1672            break;
1673        case AMDCL2OP_WORKITEM_PRIVATE_SEGMENT_SIZE:
1674            AsmAmdCL2PseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1675                             AMDCL2CVAL_WORKITEM_PRIVATE_SEGMENT_SIZE);
1676            break;
1677        default:
1678            return false;
1679    }
1680    return true;
1681}
1682
1683bool AsmAmdCL2Handler::prepareBinary()
1684{
1685    bool good = true;
1686    if (assembler.isaAssembler!=nullptr)
1687        saveCurrentAllocRegs(); // save last kernel allocated registers to kernel state
1688   
1689    output.is64Bit = assembler.is64Bit();
1690    output.deviceType = assembler.getDeviceType();
1691    /* initialize sections */
1692    const size_t sectionsNum = sections.size();
1693    const size_t kernelsNum = kernelStates.size();
1694    for (size_t i = 0; i < sectionsNum; i++)
1695    {
1696        const AsmSection& asmSection = assembler.sections[i];
1697        const Section& section = sections[i];
1698        const size_t sectionSize = asmSection.getSize();
1699        const cxbyte* sectionData = (!asmSection.content.empty()) ?
1700                asmSection.content.data() : (const cxbyte*)"";
1701        AmdCL2KernelInput* kernel = (section.kernelId!=ASMKERN_GLOBAL) ?
1702                    &output.kernels[section.kernelId] : nullptr;
1703       
1704        switch(asmSection.type)
1705        {
1706            case AsmSectionType::CODE:
1707                kernel->codeSize = sectionSize;
1708                kernel->code = sectionData;
1709                break;
1710            case AsmSectionType::AMDCL2_METADATA:
1711                kernel->metadataSize = sectionSize;
1712                kernel->metadata = sectionData;
1713                break;
1714            case AsmSectionType::AMDCL2_ISAMETADATA:
1715                kernel->isaMetadataSize = sectionSize;
1716                kernel->isaMetadata = sectionData;
1717                break;
1718            case AsmSectionType::DATA:
1719                output.globalDataSize = sectionSize;
1720                output.globalData = sectionData;
1721                break;
1722            case AsmSectionType::AMDCL2_RWDATA:
1723                output.rwDataSize = sectionSize;
1724                output.rwData = sectionData;
1725                break;
1726            case AsmSectionType::AMDCL2_BSS:
1727                output.bssAlignment = asmSection.alignment;
1728                output.bssSize = asmSection.getSize();
1729                break;
1730            case AsmSectionType::AMDCL2_SAMPLERINIT:
1731                output.samplerInitSize = sectionSize;
1732                output.samplerInit = sectionData;
1733                break;
1734            case AsmSectionType::AMDCL2_SETUP:
1735                kernel->setupSize = sectionSize;
1736                kernel->setup = sectionData;
1737                break;
1738            case AsmSectionType::AMDCL2_STUB:
1739                kernel->stubSize = sectionSize;
1740                kernel->stub = sectionData;
1741                break;
1742            case AsmSectionType::AMDCL2_CONFIG_CTRL_DIRECTIVE:
1743                if (sectionSize != 128)
1744                    assembler.printError(AsmSourcePos(),
1745                         (std::string("Section '.control_directive' for kernel '")+
1746                          assembler.kernels[section.kernelId].name+
1747                          "' have wrong size").c_str());
1748                break;
1749            case AsmSectionType::EXTRA_PROGBITS:
1750            case AsmSectionType::EXTRA_NOTE:
1751            case AsmSectionType::EXTRA_NOBITS:
1752            case AsmSectionType::EXTRA_SECTION:
1753            {
1754                uint32_t elfSectType =
1755                       (asmSection.type==AsmSectionType::EXTRA_NOTE) ? SHT_NOTE :
1756                       (asmSection.type==AsmSectionType::EXTRA_NOBITS) ? SHT_NOBITS :
1757                             SHT_PROGBITS;
1758                uint32_t elfSectFlags = 
1759                    ((asmSection.flags&ASMELFSECT_ALLOCATABLE) ? SHF_ALLOC : 0) |
1760                    ((asmSection.flags&ASMELFSECT_WRITEABLE) ? SHF_WRITE : 0) |
1761                    ((asmSection.flags&ASMELFSECT_EXECUTABLE) ? SHF_EXECINSTR : 0);
1762                // put extra sections to binary
1763                if (section.kernelId == ASMKERN_GLOBAL)
1764                    output.extraSections.push_back({section.name, sectionSize, sectionData,
1765                            asmSection.alignment!=0?asmSection.alignment:1, elfSectType,
1766                            elfSectFlags, ELFSECTID_NULL, 0, 0 });
1767                else // to inner binary
1768                    output.innerExtraSections.push_back({section.name, sectionSize,
1769                            sectionData, asmSection.alignment!=0?asmSection.alignment:1,
1770                            elfSectType, elfSectFlags, ELFSECTID_NULL, 0, 0 });
1771                break;
1772            }
1773            default: // ignore other sections
1774                break;
1775        }
1776    }
1777   
1778    const GPUArchitecture arch = getGPUArchitectureFromDeviceType(assembler.deviceType);
1779    cxuint maxTotalSgprsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
1780   
1781    // driver version setup
1782    if (output.driverVersion==0 && (assembler.flags&ASM_TESTRUN)==0)
1783    {
1784        if (assembler.driverVersion==0) // just detect driver version
1785            output.driverVersion = detectedDriverVersion;
1786        else // from assembler setup
1787            output.driverVersion = assembler.driverVersion;
1788    }
1789   
1790    // set up number of the allocated SGPRs and VGPRs for kernel
1791    for (size_t i = 0; i < kernelsNum; i++)
1792    {
1793        if (!output.kernels[i].useConfig)
1794            continue;
1795       
1796        if (!kernelStates[i]->useHsaConfig)
1797        {   // previous form of config (non-HSA)
1798            AmdCL2KernelConfig& config = output.kernels[i].config;
1799            cxuint userSGPRsNum = 4;
1800            if (config.useGeneric)
1801                userSGPRsNum = 12;
1802            else if (config.useEnqueue)
1803                userSGPRsNum = 10;
1804            else if (config.useSetup)
1805                userSGPRsNum = 8;
1806            else if (config.useArgs)
1807                userSGPRsNum = 6;
1808           
1809            /* include userData sgprs */
1810            cxuint dimMask = (config.dimMask!=BINGEN_DEFAULT) ? config.dimMask :
1811                    ((config.pgmRSRC2>>7)&7);
1812            cxuint minRegsNum[2];
1813            getGPUSetupMinRegistersNum(arch, dimMask, userSGPRsNum,
1814                    ((config.tgSize) ? GPUSETUP_TGSIZE_EN : 0) |
1815                    ((config.scratchBufferSize!=0) ? GPUSETUP_SCRATCH_EN : 0), minRegsNum);
1816           
1817            const cxuint neededExtraSGPRsNum = arch>=GPUArchitecture::GCN1_2 ? 6 : 4;
1818            const cxuint extraSGPRsNum = (config.useEnqueue || config.useGeneric) ?
1819                        neededExtraSGPRsNum : 2;
1820            if (config.usedSGPRsNum!=BINGEN_DEFAULT)
1821            {   // check only if sgprsnum set explicitly
1822                if (maxTotalSgprsNum-extraSGPRsNum < config.usedSGPRsNum)
1823                {
1824                    char numBuf[64];
1825                    snprintf(numBuf, 64, "(max %u)", maxTotalSgprsNum);
1826                    assembler.printError(assembler.kernels[i].sourcePos, (std::string(
1827                        "Number of total SGPRs for kernel '")+
1828                        output.kernels[i].kernelName.c_str()+"' is too high "
1829                        +numBuf).c_str());
1830                    good = false;
1831                }
1832            }
1833           
1834            if (config.usedSGPRsNum==BINGEN_DEFAULT)
1835                config.usedSGPRsNum = std::min(maxTotalSgprsNum-extraSGPRsNum, 
1836                    std::max(minRegsNum[0], kernelStates[i]->allocRegs[0]));
1837            if (config.usedVGPRsNum==BINGEN_DEFAULT)
1838                config.usedVGPRsNum = std::max(minRegsNum[1],
1839                                kernelStates[i]->allocRegs[1]);
1840        }
1841        else // setup HSA configuration
1842        {
1843            AsmAmdHsaKernelConfig& config = *kernelStates[i]->hsaConfig.get();
1844            const CString& kernelName = output.kernels[i].kernelName;
1845           
1846            const Kernel& kernel = *kernelStates[i];
1847           
1848            // setup some params: pgmRSRC1 and PGMRSRC2 and others
1849            // setup config
1850            // fill default values
1851            if (config.amdCodeVersionMajor == BINGEN_DEFAULT)
1852                config.amdCodeVersionMajor = 1;
1853            if (config.amdCodeVersionMinor == BINGEN_DEFAULT)
1854                config.amdCodeVersionMinor = 0;
1855            if (config.amdMachineKind == BINGEN16_DEFAULT)
1856                config.amdMachineKind = 1;
1857            if (config.amdMachineMajor == BINGEN16_DEFAULT)
1858                config.amdMachineMajor = 0;
1859            if (config.amdMachineMinor == BINGEN16_DEFAULT)
1860                config.amdMachineMinor = 0;
1861            if (config.amdMachineStepping == BINGEN16_DEFAULT)
1862                config.amdMachineStepping = 0;
1863            if (config.kernelCodeEntryOffset == BINGEN64_DEFAULT)
1864                config.kernelCodeEntryOffset = 256;
1865            if (config.kernelCodePrefetchOffset == BINGEN64_DEFAULT)
1866                config.kernelCodePrefetchOffset = 0;
1867            if (config.kernelCodePrefetchSize == BINGEN64_DEFAULT)
1868                config.kernelCodePrefetchSize = 0;
1869            if (config.maxScrachBackingMemorySize == BINGEN64_DEFAULT) // ??
1870                config.maxScrachBackingMemorySize = 0;
1871           
1872            if (config.workitemPrivateSegmentSize == BINGEN_DEFAULT) // scratch buffer
1873                config.workitemPrivateSegmentSize =  0;
1874            if (config.workgroupGroupSegmentSize == BINGEN_DEFAULT) // local size
1875                config.workgroupGroupSegmentSize = 0;
1876            if (config.gdsSegmentSize == BINGEN_DEFAULT)
1877                config.gdsSegmentSize = 0;
1878            if (config.kernargSegmentSize == BINGEN64_DEFAULT)
1879            {   // calculate kernel arg size
1880                const bool newBinaries = output.driverVersion >= 191205;
1881                config.kernargSegmentSize = 
1882                        output.kernels[i].config.calculateKernelArgSize(
1883                            assembler.is64Bit(), newBinaries);
1884            }
1885            if (config.workgroupFbarrierCount == BINGEN_DEFAULT)
1886                config.workgroupFbarrierCount = 0;
1887            if (config.debugWavefrontPrivateSegmentOffsetSgpr == BINGEN16_DEFAULT)
1888                config.debugWavefrontPrivateSegmentOffsetSgpr = 0;
1889            if (config.debugPrivateSegmentBufferSgpr == BINGEN16_DEFAULT)
1890                config.debugPrivateSegmentBufferSgpr = 0;
1891            if (config.kernargSegmentAlignment == BINGEN8_DEFAULT)
1892                config.kernargSegmentAlignment = 4; // 16 bytes
1893            if (config.groupSegmentAlignment == BINGEN8_DEFAULT)
1894                config.groupSegmentAlignment = 4; // 16 bytes
1895            if (config.privateSegmentAlignment == BINGEN8_DEFAULT)
1896                config.privateSegmentAlignment = 4; // 16 bytes
1897            if (config.wavefrontSize == BINGEN8_DEFAULT)
1898                config.wavefrontSize = 6; // 64 threads
1899           
1900            cxuint userSGPRsNum = 0;
1901            if (config.userDataNum == BINGEN8_DEFAULT)
1902            {   // calcuate userSGPRs
1903                const uint16_t sgprFlags = config.enableSgprRegisterFlags;
1904                userSGPRsNum =
1905                    ((sgprFlags&AMDHSAFLAG_USE_PRIVATE_SEGMENT_BUFFER)!=0 ? 4 : 0) +
1906                    ((sgprFlags&AMDHSAFLAG_USE_DISPATCH_PTR)!=0 ? 2 : 0) +
1907                    ((sgprFlags&AMDHSAFLAG_USE_QUEUE_PTR)!=0 ? 2 : 0) +
1908                    ((sgprFlags&AMDHSAFLAG_USE_KERNARG_SEGMENT_PTR)!=0 ? 2 : 0) +
1909                    ((sgprFlags&AMDHSAFLAG_USE_DISPATCH_ID)!=0 ? 2 : 0) +
1910                    ((sgprFlags&AMDHSAFLAG_USE_FLAT_SCRATCH_INIT)!=0 ? 2 : 0) +
1911                    ((sgprFlags&AMDHSAFLAG_USE_PRIVATE_SEGMENT_SIZE)!=0) +
1912                    /* use_grid_workgroup_count */
1913                    ((sgprFlags&AMDHSAFLAG_USE_GRID_WORKGROUP_COUNT_X)!=0) +
1914                    ((sgprFlags&AMDHSAFLAG_USE_GRID_WORKGROUP_COUNT_Y)!=0) +
1915                    ((sgprFlags&AMDHSAFLAG_USE_GRID_WORKGROUP_COUNT_Z)!=0);
1916                userSGPRsNum = std::min(16U, userSGPRsNum);
1917            }
1918            else // default
1919                userSGPRsNum = config.userDataNum;
1920           
1921            /* include userData sgprs */
1922            cxuint dimMask = (config.dimMask!=BINGEN_DEFAULT) ? config.dimMask :
1923                    ((config.computePgmRsrc2>>7)&7);
1924            // extra sgprs for dimensions
1925            cxuint minRegsNum[2];
1926            getGPUSetupMinRegistersNum(arch, dimMask, userSGPRsNum,
1927                    ((config.tgSize) ? GPUSETUP_TGSIZE_EN : 0) |
1928                    ((config.workitemPrivateSegmentSize!=0) ?
1929                            GPUSETUP_SCRATCH_EN : 0), minRegsNum);
1930           
1931            if (config.usedSGPRsNum!=BINGEN_DEFAULT &&
1932                    maxTotalSgprsNum < config.usedSGPRsNum)
1933            {   // check only if sgprsnum set explicitly
1934                char numBuf[64];
1935                snprintf(numBuf, 64, "(max %u)", maxTotalSgprsNum);
1936                assembler.printError(assembler.kernels[i].sourcePos, (std::string(
1937                        "Number of total SGPRs for kernel '")+
1938                        kernelName.c_str()+"' is too high "+numBuf).c_str());
1939                good = false;
1940            }
1941            // set usedSGPRsNum
1942            cxuint progSgprsNum = 0;
1943            cxuint flags = kernelStates[i]->allocRegFlags |
1944                // flat_scratch_init
1945                ((config.enableSgprRegisterFlags&AMDHSAFLAG_USE_FLAT_SCRATCH_INIT)!=0?
1946                            GCN_FLAT : 0) |
1947                // enable_xnack
1948                ((config.enableFeatureFlags&AMDHSAFLAG_USE_XNACK_ENABLED)!=0 ?
1949                            GCN_XNACK : 0);
1950            cxuint extraSgprsNum = getGPUExtraRegsNum(arch, REGTYPE_SGPR, flags|GCN_VCC);
1951           
1952            if (config.usedSGPRsNum==BINGEN_DEFAULT)
1953            {
1954                progSgprsNum = std::max(minRegsNum[0], kernelStates[i]->allocRegs[0]);
1955                config.usedSGPRsNum = std::min(progSgprsNum + extraSgprsNum,
1956                        maxTotalSgprsNum); // include all extra sgprs
1957            }
1958            else // calculate progs SPGRs num (without extra SGPR num)
1959                progSgprsNum = std::max(cxint(config.usedSGPRsNum - extraSgprsNum), 0);
1960           
1961            // set usedVGPRsNum
1962            if (config.usedVGPRsNum==BINGEN_DEFAULT)
1963                config.usedVGPRsNum = std::max(minRegsNum[1],
1964                                kernelStates[i]->allocRegs[1]);
1965           
1966            cxuint sgprsNum = std::max(config.usedSGPRsNum, 1U);
1967            cxuint vgprsNum = std::max(config.usedVGPRsNum, 1U);
1968            // computePGMRSRC1
1969            config.computePgmRsrc1 |= calculatePgmRSrc1(arch, vgprsNum, sgprsNum,
1970                        config.priority, config.floatMode, config.privilegedMode,
1971                        config.dx10Clamp, config.debugMode, config.ieeeMode);
1972            // computePGMRSRC2
1973            config.computePgmRsrc2 = (config.computePgmRsrc2 & 0xffffe440U) |
1974                    calculatePgmRSrc2(arch, (config.workitemPrivateSegmentSize != 0),
1975                            userSGPRsNum, false, config.dimMask,
1976                            (config.computePgmRsrc2 & 0x1b80U), config.tgSize,
1977                            0, config.exceptions);
1978           
1979            if (config.wavefrontSgprCount == BINGEN16_DEFAULT)
1980                config.wavefrontSgprCount = sgprsNum;
1981            if (config.workitemVgprCount == BINGEN16_DEFAULT)
1982                config.workitemVgprCount = vgprsNum;
1983            if (config.reservedVgprFirst == BINGEN16_DEFAULT)
1984                config.reservedVgprFirst = vgprsNum;
1985            if (config.reservedVgprCount == BINGEN16_DEFAULT)
1986                config.reservedVgprCount = 0;
1987            if (config.reservedSgprFirst == BINGEN16_DEFAULT)
1988                config.reservedSgprFirst = progSgprsNum;
1989            if (config.reservedSgprCount == BINGEN16_DEFAULT)
1990                config.reservedSgprCount = 0;
1991           
1992            if (config.callConvention == BINGEN_DEFAULT)
1993                config.callConvention = 0;
1994            if (config.runtimeLoaderKernelSymbol == BINGEN64_DEFAULT)
1995                config.runtimeLoaderKernelSymbol = 0;
1996           
1997            config.reserved1[0] = config.reserved1[1] = config.reserved1[2] = 0;
1998           
1999            config.toLE(); // to little-endian
2000            // put control directive section to config
2001            if (kernel.ctrlDirSection!=ASMSECT_NONE &&
2002                assembler.sections[kernel.ctrlDirSection].content.size()==128)
2003                ::memcpy(config.controlDirective, 
2004                    assembler.sections[kernel.ctrlDirSection].content.data(), 128);
2005            else // zeroing if not supplied
2006                ::memset(config.controlDirective, 0, 128);
2007           
2008            output.kernels[i].setupSize = 256;
2009            output.kernels[i].setup = reinterpret_cast<cxbyte*>(&config);
2010        }
2011    }
2012   
2013    /* put kernels relocations */
2014    for (const AsmRelocation& reloc: assembler.relocations)
2015    {   /* put only code relocations */
2016        cxuint kernelId = sections[reloc.sectionId].kernelId;
2017        cxuint symbol = sections[reloc.relSectionId].type==AsmSectionType::DATA ? 0 :
2018            (sections[reloc.relSectionId].type==AsmSectionType::AMDCL2_RWDATA ? 1 : 2);
2019        output.kernels[kernelId].relocations.push_back({reloc.offset, reloc.type,
2020                    symbol, size_t(reloc.addend) });
2021    }
2022   
2023    for (AmdCL2KernelInput& kernel: output.kernels)
2024        std::sort(kernel.relocations.begin(), kernel.relocations.end(),
2025                [](const AmdCL2RelInput& a, const AmdCL2RelInput& b)
2026                { return a.offset < b.offset; });
2027   
2028    /* put extra symbols */
2029    if (assembler.flags & ASM_FORCE_ADD_SYMBOLS)
2030    {
2031        std::vector<size_t> codeOffsets(kernelsNum);
2032        size_t codeOffset = 0;
2033        // make offset translation table
2034        for (size_t i = 0; i < kernelsNum; i++)
2035        {
2036            const AmdCL2KernelInput& kernel = output.kernels[i];
2037            codeOffset += (kernel.useConfig) ? 256 : kernel.setupSize;
2038            codeOffsets[i] = codeOffset;
2039            codeOffset += (kernel.codeSize+255)&~size_t(255);
2040        }
2041       
2042        for (const AsmSymbolEntry& symEntry: assembler.globalScope.symbolMap)
2043        {
2044            if (!symEntry.second.hasValue ||
2045                ELF32_ST_BIND(symEntry.second.info) == STB_LOCAL)
2046                continue; // unresolved or local
2047            cxuint binSectId = (symEntry.second.sectionId != ASMSECT_ABS) ?
2048                    sections[symEntry.second.sectionId].elfBinSectId : ELFSECTID_ABS;
2049            if (binSectId==ELFSECTID_UNDEF)
2050                continue; // no section
2051           
2052            BinSymbol binSym = { symEntry.first, symEntry.second.value,
2053                        symEntry.second.size, binSectId, false, symEntry.second.info,
2054                        symEntry.second.other };
2055           
2056            if (symEntry.second.sectionId == ASMSECT_ABS ||
2057                sections[symEntry.second.sectionId].kernelId == ASMKERN_GLOBAL)
2058                output.extraSymbols.push_back(std::move(binSym));
2059            else if (sections[symEntry.second.sectionId].kernelId == ASMKERN_INNER)
2060                // to kernel extra symbols.
2061                output.innerExtraSymbols.push_back(std::move(binSym));
2062            else if (sections[symEntry.second.sectionId].type == AsmSectionType::CODE)
2063            {
2064                binSym.value += codeOffsets[sections[symEntry.second.sectionId].kernelId];
2065                output.innerExtraSymbols.push_back(std::move(binSym));
2066            }
2067        }
2068    }
2069    return good;
2070}
2071
2072bool AsmAmdCL2Handler::resolveSymbol(const AsmSymbol& symbol, uint64_t& value,
2073                 cxuint& sectionId)
2074{
2075    if (!assembler.isResolvableSection(symbol.sectionId))
2076    {
2077        value = symbol.value;
2078        sectionId = symbol.sectionId;
2079        return true;
2080    }
2081    return false;
2082}
2083
2084bool AsmAmdCL2Handler::resolveRelocation(const AsmExpression* expr, uint64_t& outValue,
2085                 cxuint& outSectionId)
2086{
2087    const AsmExprTarget& target = expr->getTarget();
2088    const AsmExprTargetType tgtType = target.type;
2089    if ((tgtType!=ASMXTGT_DATA32 &&
2090        !assembler.isaAssembler->relocationIsFit(32, tgtType)))
2091    {
2092        assembler.printError(expr->getSourcePos(),
2093                        "Can't resolve expression for non 32-bit integer");
2094        return false;
2095    }
2096    if (target.sectionId==ASMSECT_ABS ||
2097        assembler.sections[target.sectionId].type!=AsmSectionType::CODE)
2098    {
2099        assembler.printError(expr->getSourcePos(), "Can't resolve expression outside "
2100                "code section");
2101        return false;
2102    }
2103    const Array<AsmExprOp>& ops = expr->getOps();
2104   
2105    size_t relOpStart = 0;
2106    size_t relOpEnd = ops.size();
2107    RelocType relType = RELTYPE_LOW_32BIT;
2108    // checking what is expression
2109    AsmExprOp lastOp = ops.back();
2110    if (lastOp==AsmExprOp::BIT_AND || lastOp==AsmExprOp::MODULO ||
2111        lastOp==AsmExprOp::SIGNED_MODULO || lastOp==AsmExprOp::DIVISION ||
2112        lastOp==AsmExprOp::SIGNED_DIVISION || lastOp==AsmExprOp::SHIFT_RIGHT)
2113    {   // check low or high relocation
2114        relOpStart = 0;
2115        relOpEnd = expr->toTop(ops.size()-2);
2116        /// evaluate second argument
2117        cxuint tmpSectionId;
2118        uint64_t secondArg;
2119        if (!expr->evaluate(assembler, relOpEnd, ops.size()-1, secondArg, tmpSectionId))
2120            return false;
2121        if (tmpSectionId!=ASMSECT_ABS)
2122        {   // must be absolute
2123            assembler.printError(expr->getSourcePos(),
2124                        "Second argument for relocation operand must be absolute");
2125            return false;
2126        }
2127        bool good = true;
2128        switch (lastOp)
2129        {
2130            case AsmExprOp::BIT_AND:
2131                relType = RELTYPE_LOW_32BIT;
2132                good = ((secondArg & 0xffffffffULL) == 0xffffffffULL);
2133                break;
2134            case AsmExprOp::MODULO:
2135            case AsmExprOp::SIGNED_MODULO:
2136                relType = RELTYPE_LOW_32BIT;
2137                good = ((secondArg>>32)!=0 && (secondArg & 0xffffffffULL) == 0);
2138                break;
2139            case AsmExprOp::DIVISION:
2140            case AsmExprOp::SIGNED_DIVISION:
2141                relType = RELTYPE_HIGH_32BIT;
2142                good = (secondArg == 0x100000000ULL);
2143                break;
2144            case AsmExprOp::SHIFT_RIGHT:
2145                relType = RELTYPE_HIGH_32BIT;
2146                good = (secondArg == 32);
2147                break;
2148            default:
2149                break;
2150        }
2151        if (!good)
2152        {
2153            assembler.printError(expr->getSourcePos(),
2154                        "Can't resolve relocation for this expression");
2155            return false;
2156        }
2157    }
2158    //
2159    cxuint relSectionId = 0;
2160    uint64_t relValue = 0;
2161    if (expr->evaluate(assembler, relOpStart, relOpEnd, relValue, relSectionId))
2162    {
2163        if (relSectionId!=rodataSection && relSectionId!=dataSection &&
2164            relSectionId!=bssSection)
2165        {
2166            assembler.printError(expr->getSourcePos(),
2167                     "Section of this expression must be a global data, rwdata or bss");
2168            return false;
2169        }
2170        outSectionId = ASMSECT_ABS;   // for filling values in code
2171        outValue = 0x55555555U; // for filling values in code
2172        size_t extraOffset = (tgtType!=ASMXTGT_DATA32) ? 4 : 0;
2173        AsmRelocation reloc = { target.sectionId, target.offset+extraOffset, relType };
2174        reloc.relSectionId = relSectionId;
2175        reloc.addend = relValue;
2176        assembler.relocations.push_back(reloc);
2177        return true;
2178    }
2179    return false;
2180}
2181
2182void AsmAmdCL2Handler::writeBinary(std::ostream& os) const
2183{
2184    AmdCL2GPUBinGenerator binGenerator(&output);
2185    binGenerator.generate(os);
2186}
2187
2188void AsmAmdCL2Handler::writeBinary(Array<cxbyte>& array) const
2189{
2190    AmdCL2GPUBinGenerator binGenerator(&output);
2191    binGenerator.generate(array);
2192}
Note: See TracBrowser for help on using the repository browser.