parent
979bb6c2a1
commit
207a08c2cf
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{92e25b44-aaeb-40a2-b8c9-7eab6c210e8d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Theodosius.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,28 @@
|
||||
#include "Theodosius.h"
|
||||
|
||||
extern "C" int MessageBoxA(
|
||||
unsigned hWnd,
|
||||
char* lpText,
|
||||
char* lpCaption,
|
||||
unsigned uType
|
||||
);
|
||||
|
||||
void UsermodeNoObfuscation()
|
||||
{
|
||||
for (auto idx = 0u; idx < 5; ++idx)
|
||||
MessageBoxA(0, "Demo", "Hello From Non-Obfuscated Routine!", 0);
|
||||
}
|
||||
|
||||
MutateRoutine
|
||||
void UsermodeMutateDemo()
|
||||
{
|
||||
MessageBoxA(0, "Demo", "Hello From Mutated Routine!", 0);
|
||||
}
|
||||
|
||||
ObfuscateRoutine
|
||||
extern "C" int ModuleEntry()
|
||||
{
|
||||
MessageBoxA(0, "Demo", "Hello From Obfuscated Routine!", 0);
|
||||
UsermodeMutateDemo();
|
||||
UsermodeNoObfuscation();
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
#define ObfuscateRoutine __declspec(code_seg(".theo"), noinline)
|
||||
#define MutateRoutine __declspec(code_seg(".theo1"), noinline)
|
@ -0,0 +1,589 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Zydis">
|
||||
<UniqueIdentifier>{8d07ce7e-3b56-4b27-bb05-d12987f22384}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Zydis\Generated">
|
||||
<UniqueIdentifier>{77c3f715-9d9f-488e-a1d5-542124a490b0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Zydis\Internal">
|
||||
<UniqueIdentifier>{c89c1fbb-39b5-4954-9774-0c2600773705}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Zycore">
|
||||
<UniqueIdentifier>{db8b5110-ec16-4fc2-80cc-7241ccbfec1c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Zycore\API">
|
||||
<UniqueIdentifier>{c51e3b93-1496-49d7-838f-825d75b29ee6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\asmjit">
|
||||
<UniqueIdentifier>{d28d9202-4139-42a0-9f49-71beb5e01670}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\asmjit\core">
|
||||
<UniqueIdentifier>{a847dc8c-08a3-4ea7-a20d-157963dd41a8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\asmjit">
|
||||
<UniqueIdentifier>{706001e9-56f5-41d2-b209-9f5543d0bd11}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\asmjit\core">
|
||||
<UniqueIdentifier>{a8e52093-e1b2-4ef3-b427-ebea8772bbbf}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\asmjit\x86">
|
||||
<UniqueIdentifier>{da6ded33-7d62-4f83-b8e7-4d343fe49cd7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\asmjit\x86">
|
||||
<UniqueIdentifier>{244a52bf-80cb-43ac-ac0d-a6aad89b9eb0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="linker\linker.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="obfuscation\obfuscation.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\archtraits.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\assembler.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\builder.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\codeholder.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\codewriter.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\compiler.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\constpool.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\cpuinfo.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\emithelper.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\emitter.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\emitterutils.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\environment.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\errorhandler.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\formatter.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\func.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\funcargscontext.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\globals.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\inst.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\jitallocator.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\jitruntime.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\logger.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\operand.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\osutils.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\ralocal.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\rapass.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\rastack.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\string.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\support.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\target.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\type.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\virtmem.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\zone.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\zonehash.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\zonelist.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\zonestack.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\zonetree.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\core\zonevector.cpp">
|
||||
<Filter>Source Files\asmjit\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\x86\x86assembler.cpp">
|
||||
<Filter>Source Files\asmjit\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\x86\x86builder.cpp">
|
||||
<Filter>Source Files\asmjit\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\x86\x86compiler.cpp">
|
||||
<Filter>Source Files\asmjit\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\x86\x86emithelper.cpp">
|
||||
<Filter>Source Files\asmjit\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\x86\x86features.cpp">
|
||||
<Filter>Source Files\asmjit\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\x86\x86formatter.cpp">
|
||||
<Filter>Source Files\asmjit\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\x86\x86func.cpp">
|
||||
<Filter>Source Files\asmjit\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\x86\x86instapi.cpp">
|
||||
<Filter>Source Files\asmjit\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\x86\x86instdb.cpp">
|
||||
<Filter>Source Files\asmjit\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\x86\x86operand.cpp">
|
||||
<Filter>Source Files\asmjit\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asmjit\x86\x86rapass.cpp">
|
||||
<Filter>Source Files\asmjit\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="msrexec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="theo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Zydis\Generated\EnumInstructionCategory.h">
|
||||
<Filter>Header Files\Zydis\Generated</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Generated\EnumISAExt.h">
|
||||
<Filter>Header Files\Zydis\Generated</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Generated\EnumISASet.h">
|
||||
<Filter>Header Files\Zydis\Generated</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Generated\EnumMnemonic.h">
|
||||
<Filter>Header Files\Zydis\Generated</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Generated\EnumRegister.h">
|
||||
<Filter>Header Files\Zydis\Generated</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Internal\DecoderData.h">
|
||||
<Filter>Header Files\Zydis\Internal</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Internal\FormatterATT.h">
|
||||
<Filter>Header Files\Zydis\Internal</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Internal\FormatterBase.h">
|
||||
<Filter>Header Files\Zydis\Internal</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Internal\FormatterIntel.h">
|
||||
<Filter>Header Files\Zydis\Internal</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Internal\SharedData.h">
|
||||
<Filter>Header Files\Zydis\Internal</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Internal\String.h">
|
||||
<Filter>Header Files\Zydis\Internal</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ia32.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="loadup.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Decoder.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\DecoderTypes.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Formatter.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\FormatterBuffer.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\MetaInfo.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Mnemonic.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Register.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\SharedTypes.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\ShortString.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Status.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Utils.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\Zydis.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\Allocator.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\ArgParse.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\Bitset.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\Comparison.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\Defines.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\Format.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\LibC.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\List.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\Object.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\Status.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\String.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\Types.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\Vector.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\Zycore.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\API\Memory.h">
|
||||
<Filter>Header Files\Zycore\API</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\API\Process.h">
|
||||
<Filter>Header Files\Zycore\API</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\API\Synchronization.h">
|
||||
<Filter>Header Files\Zycore\API</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\API\Terminal.h">
|
||||
<Filter>Header Files\Zycore\API</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\API\Thread.h">
|
||||
<Filter>Header Files\Zycore\API</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zydis\ZydisExportConfig.h">
|
||||
<Filter>Header Files\Zydis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Zycore\ZycoreExportConfig.h">
|
||||
<Filter>Header Files\Zycore</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="linker\linker.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="utils.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="obfuscation\obfuscation.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\asmjit.h">
|
||||
<Filter>Header Files\asmjit</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\asmjit-scope-begin.h">
|
||||
<Filter>Header Files\asmjit</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\asmjit-scope-end.h">
|
||||
<Filter>Header Files\asmjit</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core.h">
|
||||
<Filter>Header Files\asmjit</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86.h">
|
||||
<Filter>Header Files\asmjit</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\api-build_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\api-config.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\archcommons.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\archtraits.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\assembler.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\builder.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\codebuffer.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\codeholder.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\codewriter_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\compiler.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\compilerdefs.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\constpool.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\cpuinfo.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\datatypes.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\emithelper_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\emitter.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\emitterutils_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\environment.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\errorhandler.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\features.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\formatter.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\func.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\funcargscontext_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\globals.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\inst.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\jitallocator.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\jitruntime.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\logger.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\misc_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\operand.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\osutils.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\osutils_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\raassignment_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\rabuilders_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\radefs_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\ralocal_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\rapass_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\rastack_p.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\string.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\support.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\target.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\type.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\virtmem.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\zone.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\zonehash.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\zonelist.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\zonestack.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\zonestring.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\zonetree.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\core\zonevector.h">
|
||||
<Filter>Header Files\asmjit\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86archtraits_p.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86assembler.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86builder.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86compiler.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86emithelper_p.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86emitter.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86features.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86formatter_p.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86func_p.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86globals.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86instapi_p.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86instdb.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86instdb_p.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86opcode_p.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86operand.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asmjit\x86\x86rapass_p.h">
|
||||
<Filter>Header Files\asmjit\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="msrexec.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="raw_driver.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="syscall_handler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vdm.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="theo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="syscall_handler.asm">
|
||||
<Filter>Source Files</Filter>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerCommandArguments>
|
||||
</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LocalDebuggerCommandArguments>
|
||||
</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
Binary file not shown.
@ -0,0 +1,134 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_API_MEMORY_H
|
||||
#define ZYCORE_API_MEMORY_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
# include <windows.h>
|
||||
#elif defined(ZYAN_POSIX)
|
||||
# include <sys/mman.h>
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanMemoryPageProtection` enum.
|
||||
*/
|
||||
typedef enum ZyanMemoryPageProtection_
|
||||
{
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
|
||||
ZYAN_PAGE_READONLY = PAGE_READONLY,
|
||||
ZYAN_PAGE_READWRITE = PAGE_READWRITE,
|
||||
ZYAN_PAGE_EXECUTE = PAGE_EXECUTE,
|
||||
ZYAN_PAGE_EXECUTE_READ = PAGE_EXECUTE_READ,
|
||||
ZYAN_PAGE_EXECUTE_READWRITE = PAGE_EXECUTE_READWRITE
|
||||
|
||||
#elif defined(ZYAN_POSIX)
|
||||
|
||||
ZYAN_PAGE_READONLY = PROT_READ,
|
||||
ZYAN_PAGE_READWRITE = PROT_READ | PROT_WRITE,
|
||||
ZYAN_PAGE_EXECUTE = PROT_EXEC,
|
||||
ZYAN_PAGE_EXECUTE_READ = PROT_EXEC | PROT_READ,
|
||||
ZYAN_PAGE_EXECUTE_READWRITE = PROT_EXEC | PROT_READ | PROT_WRITE
|
||||
|
||||
#endif
|
||||
} ZyanMemoryPageProtection;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the system page size.
|
||||
*
|
||||
* @return The system page size.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemPageSize();
|
||||
|
||||
/**
|
||||
* Returns the system allocation granularity.
|
||||
*
|
||||
* The system allocation granularity specifies the minimum amount of bytes which can be allocated
|
||||
* at a specific address by a single call of `ZyanMemoryVirtualAlloc`.
|
||||
*
|
||||
* This value is typically 64KiB on Windows systems and equal to the page size on most POSIX
|
||||
* platforms.
|
||||
*
|
||||
* @return The system allocation granularity.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemAllocationGranularity();
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Changes the memory protection value of one or more pages.
|
||||
*
|
||||
* @param address The start address aligned to a page boundary.
|
||||
* @param size The size.
|
||||
* @param protection The new page protection value.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualProtect(void* address, ZyanUSize size,
|
||||
ZyanMemoryPageProtection protection);
|
||||
|
||||
/**
|
||||
* Releases one or more memory pages starting at the given address.
|
||||
*
|
||||
* @param address The start address aligned to a page boundary.
|
||||
* @param size The size.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualFree(void* address, ZyanUSize size);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif /* ZYCORE_API_MEMORY_H */
|
@ -0,0 +1,67 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_API_PROCESS_H
|
||||
#define ZYCORE_API_PROCESS_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Flushes the process instruction cache.
|
||||
*
|
||||
* @param address The address.
|
||||
* @param size The size.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanProcessFlushInstructionCache(void* address, ZyanUSize size);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif /* ZYCORE_API_PROCESS_H */
|
@ -0,0 +1,133 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_API_SYNCHRONIZATION_H
|
||||
#define ZYCORE_API_SYNCHRONIZATION_H
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_POSIX)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Critical Section */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
typedef pthread_mutex_t ZyanCriticalSection;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(ZYAN_WINDOWS)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Critical Section */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
typedef CRITICAL_SECTION ZyanCriticalSection;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Critical Section */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Initializes a critical section.
|
||||
*
|
||||
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionInitialize(ZyanCriticalSection* critical_section);
|
||||
|
||||
/**
|
||||
* Enters a critical section.
|
||||
*
|
||||
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionEnter(ZyanCriticalSection* critical_section);
|
||||
|
||||
/**
|
||||
* Tries to enter a critical section.
|
||||
*
|
||||
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the critical section was successfully entered or `ZYAN_FALSE`,
|
||||
* if not.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanBool ZyanCriticalSectionTryEnter(ZyanCriticalSection* critical_section);
|
||||
|
||||
/**
|
||||
* Leaves a critical section.
|
||||
*
|
||||
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionLeave(ZyanCriticalSection* critical_section);
|
||||
|
||||
/**
|
||||
* Deletes a critical section.
|
||||
*
|
||||
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionDelete(ZyanCriticalSection* critical_section);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYAN_NO_LIBC */
|
||||
|
||||
#endif /* ZYCORE_API_SYNCHRONIZATION_H */
|
@ -0,0 +1,163 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file Provides cross-platform terminal helper functions.
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_API_TERMINAL_H
|
||||
#define ZYCORE_API_TERMINAL_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/LibC.h>
|
||||
#include <Zycore/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* VT100 CSI SGR sequences */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYAN_VT100SGR_RESET "\033[0m"
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Foreground colors */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYAN_VT100SGR_FG_DEFAULT "\033[39m"
|
||||
|
||||
#define ZYAN_VT100SGR_FG_BLACK "\033[30m"
|
||||
#define ZYAN_VT100SGR_FG_RED "\033[31m"
|
||||
#define ZYAN_VT100SGR_FG_GREEN "\033[32m"
|
||||
#define ZYAN_VT100SGR_FG_YELLOW "\033[33m"
|
||||
#define ZYAN_VT100SGR_FG_BLUE "\033[34m"
|
||||
#define ZYAN_VT100SGR_FG_MAGENTA "\033[35m"
|
||||
#define ZYAN_VT100SGR_FG_CYAN "\033[36m"
|
||||
#define ZYAN_VT100SGR_FG_WHITE "\033[37m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_BLACK "\033[90m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_RED "\033[91m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_GREEN "\033[92m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_YELLOW "\033[93m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_BLUE "\033[94m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_MAGENTA "\033[95m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_CYAN "\033[96m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_WHITE "\033[97m"
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Background color */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYAN_VT100SGR_BG_DEFAULT "\033[49m"
|
||||
|
||||
#define ZYAN_VT100SGR_BG_BLACK "\033[40m"
|
||||
#define ZYAN_VT100SGR_BG_RED "\033[41m"
|
||||
#define ZYAN_VT100SGR_BG_GREEN "\033[42m"
|
||||
#define ZYAN_VT100SGR_BG_YELLOW "\033[43m"
|
||||
#define ZYAN_VT100SGR_BG_BLUE "\033[44m"
|
||||
#define ZYAN_VT100SGR_BG_MAGENTA "\033[45m"
|
||||
#define ZYAN_VT100SGR_BG_CYAN "\033[46m"
|
||||
#define ZYAN_VT100SGR_BG_WHITE "\033[47m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_BLACK "\033[100m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_RED "\033[101m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_GREEN "\033[102m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_YELLOW "\033[103m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_BLUE "\033[104m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_MAGENTA "\033[105m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_CYAN "\033[106m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_WHITE "\033[107m"
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Declares the `ZyanStandardStream` enum.
|
||||
*/
|
||||
typedef enum ZyanStandardStream_
|
||||
{
|
||||
/**
|
||||
* The default input stream.
|
||||
*/
|
||||
ZYAN_STDSTREAM_IN,
|
||||
/**
|
||||
* The default output stream.
|
||||
*/
|
||||
ZYAN_STDSTREAM_OUT,
|
||||
/**
|
||||
* The default error stream.
|
||||
*/
|
||||
ZYAN_STDSTREAM_ERR
|
||||
} ZyanStandardStream;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Enables VT100 ansi escape codes for the given stream.
|
||||
*
|
||||
* @param stream Either `ZYAN_STDSTREAM_OUT` or `ZYAN_STDSTREAM_ERR`.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This functions returns `ZYAN_STATUS_SUCCESS` on all non-Windows systems without performing any
|
||||
* operations, assuming that VT100 is supported by default.
|
||||
*
|
||||
* On Windows systems, VT100 functionality is only supported on Windows 10 build 1607 (anniversary
|
||||
* update) and later.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanTerminalEnableVT100(ZyanStandardStream stream);
|
||||
|
||||
/**
|
||||
* Checks, if the given standard stream reads from or writes to a terminal.
|
||||
*
|
||||
* @param stream The standard stream to check.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if the stream is bound to a terminal, `ZYAN_STATUS_FALSE` if not,
|
||||
* or another zyan status code if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanTerminalIsTTY(ZyanStandardStream stream);
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_API_TERMINAL_H */
|
@ -0,0 +1,244 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_API_THREAD_H
|
||||
#define ZYCORE_API_THREAD_H
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_POSIX)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThread` data-type.
|
||||
*/
|
||||
typedef pthread_t ZyanThread;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadId` data-type.
|
||||
*/
|
||||
typedef ZyanU64 ZyanThreadId;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Thread Local Storage (TLS) */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadTlsIndex` data-type.
|
||||
*/
|
||||
typedef pthread_key_t ZyanThreadTlsIndex;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadTlsCallback` function prototype.
|
||||
*/
|
||||
typedef void(*ZyanThreadTlsCallback)(void* data);
|
||||
|
||||
/**
|
||||
* Declares a Thread Local Storage (TLS) callback function.
|
||||
*
|
||||
* @param name The callback function name.
|
||||
* @param param_type The callback data parameter type.
|
||||
* @param param_name The callback data parameter name.
|
||||
*/
|
||||
#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \
|
||||
void name(param_type* param_name)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(ZYAN_WINDOWS)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThread` data-type.
|
||||
*/
|
||||
typedef HANDLE ZyanThread;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadId` data-type.
|
||||
*/
|
||||
typedef DWORD ZyanThreadId;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Thread Local Storage (TLS) */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadTlsIndex` data-type.
|
||||
*/
|
||||
typedef DWORD ZyanThreadTlsIndex;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadTlsCallback` function prototype.
|
||||
*/
|
||||
typedef PFLS_CALLBACK_FUNCTION ZyanThreadTlsCallback;
|
||||
|
||||
/**
|
||||
* Declares a Thread Local Storage (TLS) callback function.
|
||||
*
|
||||
* @param name The callback function name.
|
||||
* @param param_type The callback data parameter type.
|
||||
* @param param_name The callback data parameter name.
|
||||
*/
|
||||
#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \
|
||||
VOID NTAPI name(param_type* param_name)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the handle of the current thread.
|
||||
*
|
||||
* @param thread Receives the handle of the current thread.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThread(ZyanThread* thread);
|
||||
|
||||
/**
|
||||
* Returns the unique id of the current thread.
|
||||
*
|
||||
* @param thread_id Receives the unique id of the current thread.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThreadId(ZyanThreadId* thread_id);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Thread Local Storage (TLS) */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Allocates a new Thread Local Storage (TLS) slot.
|
||||
*
|
||||
* @param index Receives the TLS slot index.
|
||||
* @param destructor A pointer to a destructor callback which is invoked to finalize the data
|
||||
* in the TLS slot or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* The maximum available number of TLS slots is implementation specific and different on each
|
||||
* platform:
|
||||
* - Windows
|
||||
* - A total amount of 128 slots per process are guaranteed
|
||||
* - POSIX
|
||||
* - A total amount of 128 slots per process are guaranteed
|
||||
* - Some systems guarantee larger amounts like e.g. 1024 slots per process
|
||||
*
|
||||
* Note that the invocation rules for the destructor callback are implementation specific and
|
||||
* different on each platform:
|
||||
* - Windows
|
||||
* - The callback is invoked when a thread exits
|
||||
* - The callback is invoked when the process exits
|
||||
* - The callback is invoked when the TLS slot is released
|
||||
* - POSIX
|
||||
* - The callback is invoked when a thread exits and the stored value is not null
|
||||
* - The callback is NOT invoked when the process exits
|
||||
* - The callback is NOT invoked when the TLS slot is released
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsAlloc(ZyanThreadTlsIndex* index,
|
||||
ZyanThreadTlsCallback destructor);
|
||||
|
||||
/**
|
||||
* Releases a Thread Local Storage (TLS) slot.
|
||||
*
|
||||
* @param index The TLS slot index.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsFree(ZyanThreadTlsIndex index);
|
||||
|
||||
/**
|
||||
* Returns the value inside the given Thread Local Storage (TLS) slot for the
|
||||
* calling thread.
|
||||
*
|
||||
* @param index The TLS slot index.
|
||||
* @param data Receives the value inside the given Thread Local Storage
|
||||
* (TLS) slot for the calling thread.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsGetValue(ZyanThreadTlsIndex index, void** data);
|
||||
|
||||
/**
|
||||
* Set the value of the given Thread Local Storage (TLS) slot for the calling thread.
|
||||
*
|
||||
* @param index The TLS slot index.
|
||||
* @param data The value to store inside the given Thread Local Storage (TLS) slot for the
|
||||
* calling thread
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsSetValue(ZyanThreadTlsIndex index, void* data);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYAN_NO_LIBC */
|
||||
|
||||
#endif /* ZYCORE_API_THREAD_H */
|
@ -0,0 +1,143 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_ALLOCATOR_H
|
||||
#define ZYCORE_ALLOCATOR_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
struct ZyanAllocator_;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanAllocatorAllocate` function prototype.
|
||||
*
|
||||
* @param allocator A pointer to the `ZyanAllocator` instance.
|
||||
* @param p Receives a pointer to the first memory block sufficient to hold an
|
||||
* array of `n` elements with a size of `element_size`.
|
||||
* @param element_size The size of a single element.
|
||||
* @param n The number of elements to allocate storage for.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This prototype is used for the `allocate()` and `reallocate()` functions.
|
||||
*
|
||||
* The result of the `reallocate()` function is undefined, if `p` does not point to a memory block
|
||||
* previously obtained by `(re-)allocate()`.
|
||||
*/
|
||||
typedef ZyanStatus (*ZyanAllocatorAllocate)(struct ZyanAllocator_* allocator, void** p,
|
||||
ZyanUSize element_size, ZyanUSize n);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanAllocatorDeallocate` function prototype.
|
||||
*
|
||||
* @param allocator A pointer to the `ZyanAllocator` instance.
|
||||
* @param p The pointer obtained from `(re-)allocate()`.
|
||||
* @param element_size The size of a single element.
|
||||
* @param n The number of elements earlier passed to `(re-)allocate()`.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
typedef ZyanStatus (*ZyanAllocatorDeallocate)(struct ZyanAllocator_* allocator, void* p,
|
||||
ZyanUSize element_size, ZyanUSize n);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanAllocator` struct.
|
||||
*
|
||||
* This is the base class for all custom allocator implementations.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZyanAllocator_
|
||||
{
|
||||
/**
|
||||
* The allocate function.
|
||||
*/
|
||||
ZyanAllocatorAllocate allocate;
|
||||
/**
|
||||
* The reallocate function.
|
||||
*/
|
||||
ZyanAllocatorAllocate reallocate;
|
||||
/**
|
||||
* The deallocate function.
|
||||
*/
|
||||
ZyanAllocatorDeallocate deallocate;
|
||||
} ZyanAllocator;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanAllocator` instance.
|
||||
*
|
||||
* @param allocator A pointer to the `ZyanAllocator` instance.
|
||||
* @param allocate The allocate function.
|
||||
* @param reallocate The reallocate function.
|
||||
* @param deallocate The deallocate function.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanAllocatorInit(ZyanAllocator* allocator, ZyanAllocatorAllocate allocate,
|
||||
ZyanAllocatorAllocate reallocate, ZyanAllocatorDeallocate deallocate);
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Returns the default `ZyanAllocator` instance.
|
||||
*
|
||||
* @return A pointer to the default `ZyanAllocator` instance.
|
||||
*
|
||||
* The default allocator uses the default memory manager to allocate memory on the heap.
|
||||
*
|
||||
* You should in no case modify the returned allocator instance to avoid unexpected behavior.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanAllocator* ZyanAllocatorDefault(void);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_ALLOCATOR_H */
|
@ -0,0 +1,173 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements command-line argument parsing.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_ARGPARSE_H
|
||||
#define ZYCORE_ARGPARSE_H
|
||||
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Vector.h>
|
||||
#include <Zycore/String.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Structs and other types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Definition of a single argument.
|
||||
*/
|
||||
typedef struct ZyanArgParseDefinition_
|
||||
{
|
||||
/**
|
||||
* The argument name, e.g. `--help`.
|
||||
*
|
||||
* Must start with either one or two dashes. Single dash arguments must consist of a single
|
||||
* character, (e.g. `-n`), double-dash arguments can be of arbitrary length.
|
||||
*/
|
||||
const char* name;
|
||||
/**
|
||||
* Whether the argument is boolean or expects a value.
|
||||
*/
|
||||
ZyanBool boolean;
|
||||
/**
|
||||
* Whether this argument is required (error if missing).
|
||||
*/
|
||||
ZyanBool required;
|
||||
} ZyanArgParseDefinition;
|
||||
|
||||
/**
|
||||
* Configuration for argument parsing.
|
||||
*/
|
||||
typedef struct ZyanArgParseConfig_
|
||||
{
|
||||
/**
|
||||
* `argv` argument passed to `main` by LibC.
|
||||
*/
|
||||
const char** argv;
|
||||
/**
|
||||
* `argc` argument passed to `main` by LibC.
|
||||
*/
|
||||
ZyanUSize argc;
|
||||
/**
|
||||
* Minimum # of accepted unnamed / anonymous arguments.
|
||||
*/
|
||||
ZyanUSize min_unnamed_args;
|
||||
/**
|
||||
* Maximum # of accepted unnamed / anonymous arguments.
|
||||
*/
|
||||
ZyanUSize max_unnamed_args;
|
||||
/**
|
||||
* Argument definition array, or `ZYAN_NULL`.
|
||||
*
|
||||
* Expects a pointer to an array of `ZyanArgParseDefinition` instances. The array is
|
||||
* terminated by setting the `.name` field of the last element to `ZYAN_NULL`. If no named
|
||||
* arguments should be parsed, you can also set this to `ZYAN_NULL`.
|
||||
*/
|
||||
ZyanArgParseDefinition* args;
|
||||
} ZyanArgParseConfig;
|
||||
|
||||
/**
|
||||
* Information about a parsed argument.
|
||||
*/
|
||||
typedef struct ZyanArgParseArg_
|
||||
{
|
||||
/**
|
||||
* Corresponding argument definition, or `ZYAN_NULL` for unnamed args.
|
||||
*
|
||||
* This pointer is borrowed from the `cfg` pointer passed to `ZyanArgParse`.
|
||||
*/
|
||||
const ZyanArgParseDefinition* def;
|
||||
/**
|
||||
* Whether the argument has a value (is non-boolean).
|
||||
*/
|
||||
ZyanBool has_value;
|
||||
/**
|
||||
* If `has_value == true`, then the argument value.
|
||||
*
|
||||
* This is a view into the `argv` string array passed to `ZyanArgParse` via the `cfg` argument.
|
||||
*/
|
||||
ZyanStringView value;
|
||||
} ZyanArgParseArg;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Parse arguments according to a `ZyanArgParseConfig` definition.
|
||||
*
|
||||
* @param cfg Argument parser config to use.
|
||||
* @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is
|
||||
* transferred to the user. Input is expected to be uninitialized. On error,
|
||||
* the vector remains uninitialized.
|
||||
* @param error_token On error, if it makes sense, receives the argument fragment causing the
|
||||
* error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg`
|
||||
* struct and doesn't have to be freed by the user.
|
||||
*
|
||||
* @return A `ZyanStatus` status determining whether the parsing succeeded.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanArgParse(const ZyanArgParseConfig *cfg, ZyanVector* parsed,
|
||||
const char** error_token);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Parse arguments according to a `ZyanArgParseConfig` definition.
|
||||
*
|
||||
* This version allows specification of a custom memory allocator and thus supports no-libc.
|
||||
*
|
||||
* @param cfg Argument parser config to use.
|
||||
* @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is
|
||||
* transferred to the user. Input is expected to be uninitialized. On error,
|
||||
* the vector remains uninitialized.
|
||||
* @param error_token On error, if it makes sense, receives the argument fragment causing the
|
||||
* error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg`
|
||||
* struct and doesn't have to be freed by the user.
|
||||
* @param allocator The `ZyanAllocator` to be used for allocating the output vector's data.
|
||||
*
|
||||
* @return A `ZyanStatus` status determining whether the parsing succeeded.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanArgParseEx(const ZyanArgParseConfig *cfg, ZyanVector* parsed,
|
||||
const char** error_token, ZyanAllocator* allocator);
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_ARGPARSE_H */
|
@ -0,0 +1,484 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements the bitset class.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_BITSET_H
|
||||
#define ZYCORE_BITSET_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Allocator.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zycore/Vector.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVector` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZyanBitset_
|
||||
{
|
||||
/**
|
||||
* The bitset size.
|
||||
*/
|
||||
ZyanUSize size;
|
||||
/**
|
||||
* The bitset data.
|
||||
*/
|
||||
ZyanVector bits;
|
||||
} ZyanBitset;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanBitsetByteOperation` function prototype.
|
||||
*
|
||||
* @param v1 A pointer to the first byte. This value receives the result after performing the
|
||||
* desired operation.
|
||||
* @param v2 A pointer to the second byte.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function is used to perform byte-wise operations on two `ZyanBitset` instances.
|
||||
*/
|
||||
typedef ZyanStatus (*ZyanBitsetByteOperation)(ZyanU8* v1, const ZyanU8* v2);
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constructor and destructor */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param count The initial amount of bits.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The space for the bitset is dynamically allocated by the default allocator using the default
|
||||
* growth factor of `2.0f` and the default shrink threshold of `0.5f`.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanBitsetInit(ZyanBitset* bitset, ZyanUSize count);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanBitset` instance and sets a custom `allocator` and memory
|
||||
* allocation/deallocation parameters.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param count The initial amount of bits.
|
||||
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||
* @param growth_factor The growth factor (from `1.0f` to `x.xf`).
|
||||
* @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`).
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables
|
||||
* dynamic shrinking.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetInitEx(ZyanBitset* bitset, ZyanUSize count,
|
||||
ZyanAllocator* allocator, float growth_factor, float shrink_threshold);
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanBitset` instance and configures it to use a custom user
|
||||
* defined buffer with a fixed size.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param count The initial amount of bits.
|
||||
* @param buffer A pointer to the buffer that is used as storage for the bits.
|
||||
* @param capacity The maximum capacity (number of bytes) of the buffer.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetInitBuffer(ZyanBitset* bitset, ZyanUSize count, void* buffer,
|
||||
ZyanUSize capacity);
|
||||
|
||||
/**
|
||||
* Destroys the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetDestroy(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Logical operations */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Performs a byte-wise `operation` for every byte in the given `ZyanBitset` instances.
|
||||
*
|
||||
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||
* as the destination.
|
||||
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||
* @param operation A pointer to the function that performs the desired operation.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The `operation` callback is invoked once for every byte in the smallest of the `ZyanBitset`
|
||||
* instances.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetPerformByteOperation(ZyanBitset* destination,
|
||||
const ZyanBitset* source, ZyanBitsetByteOperation operation);
|
||||
|
||||
/**
|
||||
* Performs a logical `AND` operation on the given `ZyanBitset` instances.
|
||||
*
|
||||
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||
* as the destination.
|
||||
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* If the destination bitmask contains more bits than the source one, the state of the remaining
|
||||
* bits will be undefined.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetAND(ZyanBitset* destination, const ZyanBitset* source);
|
||||
|
||||
/**
|
||||
* Performs a logical `OR` operation on the given `ZyanBitset` instances.
|
||||
*
|
||||
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||
* as the destination.
|
||||
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* If the destination bitmask contains more bits than the source one, the state of the remaining
|
||||
* bits will be undefined.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetOR (ZyanBitset* destination, const ZyanBitset* source);
|
||||
|
||||
/**
|
||||
* Performs a logical `XOR` operation on the given `ZyanBitset` instances.
|
||||
*
|
||||
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||
* as the destination.
|
||||
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* If the destination bitmask contains more bits than the source one, the state of the remaining
|
||||
* bits will be undefined.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetXOR(ZyanBitset* destination, const ZyanBitset* source);
|
||||
|
||||
/**
|
||||
* Flips all bits of the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetFlip(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Bit access */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Sets the bit at `index` of the given `ZyanBitset` instance to `1`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param index The bit index.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetSet(ZyanBitset* bitset, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Sets the bit at `index` of the given `ZyanBitset` instance to `0`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param index The bit index.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetReset(ZyanBitset* bitset, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Sets the bit at `index` of the given `ZyanBitset` instance to the specified `value`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param index The bit index.
|
||||
* @param value The new value.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetAssign(ZyanBitset* bitset, ZyanUSize index, ZyanBool value);
|
||||
|
||||
/**
|
||||
* Toggles the bit at `index` of the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param index The bit index.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetToggle(ZyanBitset* bitset, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Returns the value of the bit at `index`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param index The bit index.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not, Another zyan
|
||||
* status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetTest(ZyanBitset* bitset, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Returns the value of the most significant bit.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||
* status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetTestMSB(ZyanBitset* bitset);
|
||||
|
||||
/**
|
||||
* Returns the value of the least significant bit.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||
* status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetTestLSB(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Sets all bits of the given `ZyanBitset` instance to `1`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetSetAll(ZyanBitset* bitset);
|
||||
|
||||
/**
|
||||
* Sets all bits of the given `ZyanBitset` instance to `0`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetResetAll(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Size management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Adds a new bit at the end of the bitset.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param value The value of the new bit.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetPush(ZyanBitset* bitset, ZyanBool value);
|
||||
|
||||
/**
|
||||
* Removes the last bit of the bitset.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetPop(ZyanBitset* bitset);
|
||||
|
||||
/**
|
||||
* Deletes all bits of the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetClear(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Changes the capacity of the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param count The new capacity (number of bits).
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetReserve(ZyanBitset* bitset, ZyanUSize count);
|
||||
|
||||
/**
|
||||
* Shrinks the capacity of the given bitset to match it's size.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetShrinkToFit(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Information */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the current size of the bitset in bits.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param size Receives the size of the bitset in bits.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSize(const ZyanBitset* bitset, ZyanUSize* size);
|
||||
|
||||
/**
|
||||
* Returns the current capacity of the bitset in bits.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param capacity Receives the size of the bitset in bits.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacity(const ZyanBitset* bitset, ZyanUSize* capacity);
|
||||
|
||||
/**
|
||||
* Returns the current size of the bitset in bytes.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param size Receives the size of the bitset in bytes.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSizeBytes(const ZyanBitset* bitset, ZyanUSize* size);
|
||||
|
||||
/**
|
||||
* Returns the current capacity of the bitset in bytes.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param capacity Receives the size of the bitset in bytes.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacityBytes(const ZyanBitset* bitset, ZyanUSize* capacity);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the amount of bits set in the given bitset.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param count Receives the amount of bits set in the given bitset.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetCount(const ZyanBitset* bitset, ZyanUSize* count);
|
||||
|
||||
/**
|
||||
* Checks, if all bits of the given bitset are set.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if all bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||
* status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetAll(const ZyanBitset* bitset);
|
||||
|
||||
/**
|
||||
* Checks, if at least one bit of the given bitset is set.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if at least one bit is set, `ZYAN_STATUS_FALSE`, if not. Another
|
||||
* zyan status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetAny(const ZyanBitset* bitset);
|
||||
|
||||
/**
|
||||
* Checks, if none bits of the given bitset are set.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if none bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||
* status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetNone(const ZyanBitset* bitset);
|
||||
|
||||
///* ---------------------------------------------------------------------------------------------- */
|
||||
//
|
||||
///**
|
||||
// * Returns a 32-bit unsigned integer representation of the data.
|
||||
// *
|
||||
// * @param bitset A pointer to the `ZyanBitset` instance.
|
||||
// * @param value Receives the 32-bit unsigned integer representation of the data.
|
||||
// *
|
||||
// * @return A zyan status code.
|
||||
// */
|
||||
//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU32(const ZyanBitset* bitset, ZyanU32* value);
|
||||
//
|
||||
///**
|
||||
// * Returns a 64-bit unsigned integer representation of the data.
|
||||
// *
|
||||
// * @param bitset A pointer to the `ZyanBitset` instance.
|
||||
// * @param value Receives the 64-bit unsigned integer representation of the data.
|
||||
// *
|
||||
// * @return A zyan status code.
|
||||
// */
|
||||
//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU64(const ZyanBitset* bitset, ZyanU64* value);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_BITSET_H */
|
@ -0,0 +1,316 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines prototypes of general-purpose comparison functions.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_COMPARISON_H
|
||||
#define ZYCORE_COMPARISON_H
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanEqualityComparison` function prototype.
|
||||
*
|
||||
* @param left A pointer to the first element.
|
||||
* @param right A pointer to the second element.
|
||||
*
|
||||
* @return This function should return `ZYAN_TRUE` if the `left` element equals the `right` one
|
||||
* or `ZYAN_FALSE`, if not.
|
||||
*/
|
||||
typedef ZyanBool (*ZyanEqualityComparison)(const void* left, const void* right);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanComparison` function prototype.
|
||||
*
|
||||
* @param left A pointer to the first element.
|
||||
* @param right A pointer to the second element.
|
||||
*
|
||||
* @return This function should return values in the following range:
|
||||
* `left == right -> result == 0`
|
||||
* `left < right -> result < 0`
|
||||
* `left > right -> result > 0`
|
||||
*/
|
||||
typedef ZyanI32 (*ZyanComparison)(const void* left, const void* right);
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Equality comparison functions */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Declares a generic equality comparison function for an integral data-type.
|
||||
*
|
||||
* @param name The name of the function.
|
||||
* @param type The name of the integral data-type.
|
||||
*/
|
||||
#define ZYAN_DECLARE_EQUALITY_COMPARISON(name, type) \
|
||||
ZyanBool name(const type* left, const type* right) \
|
||||
{ \
|
||||
ZYAN_ASSERT(left); \
|
||||
ZYAN_ASSERT(right); \
|
||||
\
|
||||
return (*left == *right) ? ZYAN_TRUE : ZYAN_FALSE; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares a generic equality comparison function that compares a single integral
|
||||
* data-type field of a struct.
|
||||
*
|
||||
* @param name The name of the function.
|
||||
* @param type The name of the integral data-type.
|
||||
* @param field_name The name of the struct field.
|
||||
*/
|
||||
#define ZYAN_DECLARE_EQUALITY_COMPARISON_FOR_FIELD(name, type, field_name) \
|
||||
ZyanBool name(const type* left, const type* right) \
|
||||
{ \
|
||||
ZYAN_ASSERT(left); \
|
||||
ZYAN_ASSERT(right); \
|
||||
\
|
||||
return (left->field_name == right->field_name) ? ZYAN_TRUE : ZYAN_FALSE; \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Comparison functions */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Declares a generic comparison function for an integral data-type.
|
||||
*
|
||||
* @param name The name of the function.
|
||||
* @param type The name of the integral data-type.
|
||||
*/
|
||||
#define ZYAN_DECLARE_COMPARISON(name, type) \
|
||||
ZyanI32 name(const type* left, const type* right) \
|
||||
{ \
|
||||
ZYAN_ASSERT(left); \
|
||||
ZYAN_ASSERT(right); \
|
||||
\
|
||||
if (*left < *right) \
|
||||
{ \
|
||||
return -1; \
|
||||
} \
|
||||
if (*left > *right) \
|
||||
{ \
|
||||
return 1; \
|
||||
} \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares a generic comparison function that compares a single integral data-type field
|
||||
* of a struct.
|
||||
*
|
||||
* @param name The name of the function.
|
||||
* @param type The name of the integral data-type.
|
||||
* @param field_name The name of the struct field.
|
||||
*/
|
||||
#define ZYAN_DECLARE_COMPARISON_FOR_FIELD(name, type, field_name) \
|
||||
ZyanI32 name(const type* left, const type* right) \
|
||||
{ \
|
||||
ZYAN_ASSERT(left); \
|
||||
ZYAN_ASSERT(right); \
|
||||
\
|
||||
if (left->field_name < right->field_name) \
|
||||
{ \
|
||||
return -1; \
|
||||
} \
|
||||
if (left->field_name > right->field_name) \
|
||||
{ \
|
||||
return 1; \
|
||||
} \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Default equality comparison functions */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for pointer values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsPointer, void* const)
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for `ZyanBool` values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsBool, ZyanBool)
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for 8-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric8, ZyanU8)
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for 16-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric16, ZyanU16)
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for 32-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric32, ZyanU32)
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for 64-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric64, ZyanU64)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Default comparison functions */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for pointer values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanComparePointer, void* const)
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for `ZyanBool` values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareBool, ZyanBool)
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for 8-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric8, ZyanU8)
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for 16-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric16, ZyanU16)
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for 32-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric32, ZyanU32)
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for 64-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric64, ZyanU64)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_COMPARISON_H */
|
@ -0,0 +1,443 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* General helper and platform detection macros.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_DEFINES_H
|
||||
#define ZYCORE_DEFINES_H
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Meta macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Concatenates two values using the stringify operator (`##`).
|
||||
*
|
||||
* @param x The first value.
|
||||
* @param y The second value.
|
||||
*
|
||||
* @return The combined string of the given values.
|
||||
*/
|
||||
#define ZYAN_MACRO_CONCAT(x, y) x ## y
|
||||
|
||||
/**
|
||||
* Concatenates two values using the stringify operator (`##`) and expands the value to
|
||||
* be used in another macro.
|
||||
*
|
||||
* @param x The first value.
|
||||
* @param y The second value.
|
||||
*
|
||||
* @return The combined string of the given values.
|
||||
*/
|
||||
#define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y)
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Compiler detection */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(__clang__)
|
||||
# define ZYAN_CLANG
|
||||
# define ZYAN_GNUC
|
||||
#elif defined(__ICC) || defined(__INTEL_COMPILER)
|
||||
# define ZYAN_ICC
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
# define ZYAN_GCC
|
||||
# define ZYAN_GNUC
|
||||
#elif defined(_MSC_VER)
|
||||
# define ZYAN_MSVC
|
||||
#elif defined(__BORLANDC__)
|
||||
# define ZYAN_BORLAND
|
||||
#else
|
||||
# define ZYAN_UNKNOWN_COMPILER
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Platform detection */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define ZYAN_WINDOWS
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
# define ZYAN_EMSCRIPTEN
|
||||
#elif defined(__APPLE__)
|
||||
# define ZYAN_APPLE
|
||||
# define ZYAN_POSIX
|
||||
#elif defined(__linux)
|
||||
# define ZYAN_LINUX
|
||||
# define ZYAN_POSIX
|
||||
#elif defined(__FreeBSD__)
|
||||
# define ZYAN_FREEBSD
|
||||
# define ZYAN_POSIX
|
||||
#elif defined(sun) || defined(__sun)
|
||||
# define ZYAN_SOLARIS
|
||||
# define ZYAN_POSIX
|
||||
#elif defined(__unix)
|
||||
# define ZYAN_UNIX
|
||||
# define ZYAN_POSIX
|
||||
#elif defined(__posix)
|
||||
# define ZYAN_POSIX
|
||||
#else
|
||||
# define ZYAN_UNKNOWN_PLATFORM
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Kernel mode detection */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \
|
||||
(defined(ZYAN_APPLE) && defined(KERNEL)) || \
|
||||
(defined(ZYAN_LINUX) && defined(__KERNEL__)) || \
|
||||
(defined(__FreeBSD_kernel__))
|
||||
# define ZYAN_KERNEL
|
||||
#else
|
||||
# define ZYAN_USER
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Architecture detection */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(_M_AMD64) || defined(__x86_64__)
|
||||
# define ZYAN_X64
|
||||
#elif defined(_M_IX86) || defined(__i386__)
|
||||
# define ZYAN_X86
|
||||
#elif defined(_M_ARM64) || defined(__aarch64__)
|
||||
# define ZYAN_AARCH64
|
||||
#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__)
|
||||
# define ZYAN_ARM
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
// Nothing to do, `ZYAN_EMSCRIPTEN` is both platform and arch macro for this one.
|
||||
#else
|
||||
# error "Unsupported architecture detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Debug/Release detection */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
|
||||
# ifdef _DEBUG
|
||||
# define ZYAN_DEBUG
|
||||
# else
|
||||
# define ZYAN_RELEASE
|
||||
# endif
|
||||
#elif defined(ZYAN_GNUC) || defined(ZYAN_ICC)
|
||||
# ifdef NDEBUG
|
||||
# define ZYAN_RELEASE
|
||||
# else
|
||||
# define ZYAN_DEBUG
|
||||
# endif
|
||||
#else
|
||||
# define ZYAN_RELEASE
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Misc compatibility macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_CLANG)
|
||||
# define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
|
||||
#else
|
||||
# define ZYAN_NO_SANITIZE(what)
|
||||
#endif
|
||||
|
||||
#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
|
||||
# define ZYAN_INLINE __inline
|
||||
#else
|
||||
# define ZYAN_INLINE static inline
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Debugging and optimization macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Runtime debug assertion.
|
||||
*/
|
||||
#if defined(ZYAN_NO_LIBC)
|
||||
# define ZYAN_ASSERT(condition) (void)(condition)
|
||||
#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
|
||||
# include <wdm.h>
|
||||
# define ZYAN_ASSERT(condition) NT_ASSERT(condition)
|
||||
#else
|
||||
# include <assert.h>
|
||||
# define ZYAN_ASSERT(condition) assert(condition)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Compiler-time assertion.
|
||||
*/
|
||||
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
|
||||
# define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x)
|
||||
#elif (defined(__cplusplus) && __cplusplus >= 201103L) || \
|
||||
(defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \
|
||||
(defined (_MSC_VER) && (_MSC_VER >= 1800))
|
||||
# define ZYAN_STATIC_ASSERT(x) static_assert(x, #x)
|
||||
#else
|
||||
# define ZYAN_STATIC_ASSERT(x) \
|
||||
typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Marks the current code path as unreachable.
|
||||
*/
|
||||
#if defined(ZYAN_RELEASE)
|
||||
# if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs.
|
||||
# if __has_builtin(__builtin_unreachable)
|
||||
# define ZYAN_UNREACHABLE __builtin_unreachable()
|
||||
# else
|
||||
# define ZYAN_UNREACHABLE for(;;)
|
||||
# endif
|
||||
# elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4)
|
||||
# define ZYAN_UNREACHABLE __builtin_unreachable()
|
||||
# elif defined(ZYAN_ICC)
|
||||
# ifdef ZYAN_WINDOWS
|
||||
# include <stdlib.h> // "missing return statement" workaround
|
||||
# define ZYAN_UNREACHABLE __assume(0); (void)abort()
|
||||
# else
|
||||
# define ZYAN_UNREACHABLE __builtin_unreachable()
|
||||
# endif
|
||||
# elif defined(ZYAN_MSVC)
|
||||
# define ZYAN_UNREACHABLE __assume(0)
|
||||
# else
|
||||
# define ZYAN_UNREACHABLE for(;;)
|
||||
# endif
|
||||
#elif defined(ZYAN_NO_LIBC)
|
||||
# define ZYAN_UNREACHABLE for(;;)
|
||||
#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
|
||||
# define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} }
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
# define ZYAN_UNREACHABLE { assert(0); abort(); }
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Utils */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General purpose */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Marks the specified parameter as unused.
|
||||
*
|
||||
* @param x The name of the unused parameter.
|
||||
*/
|
||||
#define ZYAN_UNUSED(x) (void)(x)
|
||||
|
||||
/**
|
||||
* Intentional fallthrough.
|
||||
*/
|
||||
#if defined(ZYAN_GCC) && __GNUC__ >= 7
|
||||
# define ZYAN_FALLTHROUGH __attribute__((fallthrough))
|
||||
#else
|
||||
# define ZYAN_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Declares a bitfield.
|
||||
*
|
||||
* @param x The size (in bits) of the bitfield.
|
||||
*/
|
||||
#define ZYAN_BITFIELD(x) : x
|
||||
|
||||
/**
|
||||
* Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`).
|
||||
*/
|
||||
#define ZYAN_REQUIRES_LIBC
|
||||
|
||||
/**
|
||||
* Decorator for `printf`-style functions.
|
||||
*
|
||||
* @param format_index The 1-based index of the format string parameter.
|
||||
* @param first_to_check The 1-based index of the format arguments parameter.
|
||||
*/
|
||||
#if defined(__RESHARPER__)
|
||||
# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
|
||||
[[gnu::format(printf, format_index, first_to_check)]]
|
||||
#elif defined(ZYAN_GCC)
|
||||
# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
|
||||
__attribute__((format(printf, format_index, first_to_check)))
|
||||
#else
|
||||
# define ZYAN_PRINTF_ATTR(format_index, first_to_check)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Decorator for `wprintf`-style functions.
|
||||
*
|
||||
* @param format_index The 1-based index of the format string parameter.
|
||||
* @param first_to_check The 1-based index of the format arguments parameter.
|
||||
*/
|
||||
#if defined(__RESHARPER__)
|
||||
# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \
|
||||
[[rscpp::format(wprintf, format_index, first_to_check)]]
|
||||
#else
|
||||
# define ZYAN_WPRINTF_ATTR(format_index, first_to_check)
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Arrays */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the length (number of elements) of an array.
|
||||
*
|
||||
* @param a The name of the array.
|
||||
*
|
||||
* @return The number of elements of the given array.
|
||||
*/
|
||||
#define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Arithmetic */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the smaller value of `a` or `b`.
|
||||
*
|
||||
* @param a The first value.
|
||||
* @param b The second value.
|
||||
*
|
||||
* @return The smaller value of `a` or `b`.
|
||||
*/
|
||||
#define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
/**
|
||||
* Returns the bigger value of `a` or `b`.
|
||||
*
|
||||
* @param a The first value.
|
||||
* @param b The second value.
|
||||
*
|
||||
* @return The bigger value of `a` or `b`.
|
||||
*/
|
||||
#define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
/**
|
||||
* Returns the absolute value of `a`.
|
||||
*
|
||||
* @param a The value.
|
||||
*
|
||||
* @return The absolute value of `a`.
|
||||
*/
|
||||
#define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
|
||||
|
||||
/**
|
||||
* Checks, if the given value is a power of 2.
|
||||
*
|
||||
* @param x The value.
|
||||
*
|
||||
* @return `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not.
|
||||
*
|
||||
* Note that this macro always returns `ZYAN_TRUE` for `x == 0`.
|
||||
*/
|
||||
#define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
|
||||
|
||||
/**
|
||||
* Checks, if the given value is properly aligned.
|
||||
*
|
||||
* Note that this macro only works for powers of 2.
|
||||
*/
|
||||
#define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
|
||||
|
||||
/**
|
||||
* Aligns the value to the nearest given alignment boundary (by rounding it up).
|
||||
*
|
||||
* @param x The value.
|
||||
* @param align The desired alignment.
|
||||
*
|
||||
* @return The aligned value.
|
||||
*
|
||||
* Note that this macro only works for powers of 2.
|
||||
*/
|
||||
#define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
|
||||
|
||||
/**
|
||||
* Aligns the value to the nearest given alignment boundary (by rounding it down).
|
||||
*
|
||||
* @param x The value.
|
||||
* @param align The desired alignment.
|
||||
*
|
||||
* @return The aligned value.
|
||||
*
|
||||
* Note that this macro only works for powers of 2.
|
||||
*/
|
||||
#define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Bit operations */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Checks, if the bit at index `b` is required to present the ordinal value `n`.
|
||||
*
|
||||
* @param n The ordinal value.
|
||||
* @param b The bit index.
|
||||
*
|
||||
* @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or
|
||||
* `ZYAN_FALSE`, if not.
|
||||
*
|
||||
* Note that this macro always returns `ZYAN_FALSE` for `n == 0`.
|
||||
*/
|
||||
#define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0)
|
||||
|
||||
/*
|
||||
* Returns the number of bits required to represent the ordinal value `n`.
|
||||
*
|
||||
* @param n The ordinal value.
|
||||
*
|
||||
* @return The number of bits required to represent the ordinal value `n`.
|
||||
*
|
||||
* Note that this macro returns `0` for `n == 0`.
|
||||
*/
|
||||
#define ZYAN_BITS_TO_REPRESENT(n) \
|
||||
( \
|
||||
ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \
|
||||
ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \
|
||||
ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \
|
||||
ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \
|
||||
ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \
|
||||
ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \
|
||||
ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \
|
||||
ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \
|
||||
ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \
|
||||
ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \
|
||||
ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \
|
||||
ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \
|
||||
ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \
|
||||
ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \
|
||||
ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \
|
||||
ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif /* ZYCORE_DEFINES_H */
|
@ -0,0 +1,286 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides helper functions for performant number to string conversion.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_FORMAT_H
|
||||
#define ZYCORE_FORMAT_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/String.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helpers */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the absolute value of a 64 bit int.
|
||||
*
|
||||
* @param x The value to process.
|
||||
* @return The absolute, unsigned value.
|
||||
*
|
||||
* This gracefully deals with the special case of `x` being `INT_MAX`.
|
||||
*/
|
||||
ZYAN_INLINE ZyanU64 ZyanAbsI64(ZyanI64 x)
|
||||
{
|
||||
// INT_MIN special case. Can't use the value directly because GCC thinks
|
||||
// it's too big for an INT64 literal, however is perfectly happy to accept
|
||||
// this expression. This is also hit INT64_MIN is defined in `stdint.h`.
|
||||
if (x == (-0x7fffffffffffffff - 1))
|
||||
{
|
||||
return 0x8000000000000000u;
|
||||
}
|
||||
|
||||
return (ZyanU64)(x < 0 ? -x : x);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Insertion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Inserts formatted text in the destination string at the given `index`.
|
||||
*
|
||||
* @param string The destination string.
|
||||
* @param index The insert index.
|
||||
* @param format The format string.
|
||||
* @param ... The format arguments.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYAN_PRINTF_ATTR(3, 4)
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringInsertFormat(ZyanString* string, ZyanUSize index,
|
||||
const char* format, ...);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Formats the given unsigned ordinal `value` to its decimal text-representation and
|
||||
* inserts it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param index The insert index.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecU(ZyanString* string, ZyanUSize index, ZyanU64 value,
|
||||
ZyanU8 padding_length);
|
||||
|
||||
/**
|
||||
* Formats the given signed ordinal `value` to its decimal text-representation and
|
||||
* inserts it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param index The insert index.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecS(ZyanString* string, ZyanUSize index, ZyanI64 value,
|
||||
ZyanU8 padding_length, ZyanBool force_sign, const ZyanString* prefix);
|
||||
|
||||
/**
|
||||
* Formats the given unsigned ordinal `value` to its hexadecimal text-representation and
|
||||
* inserts it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param index The insert index.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||
* ones ('a'-'f').
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexU(ZyanString* string, ZyanUSize index, ZyanU64 value,
|
||||
ZyanU8 padding_length, ZyanBool uppercase);
|
||||
|
||||
/**
|
||||
* Formats the given signed ordinal `value` to its hexadecimal text-representation and
|
||||
* inserts it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param index The insert index.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||
* ones ('a'-'f').
|
||||
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexS(ZyanString* string, ZyanUSize index, ZyanI64 value,
|
||||
ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanString* prefix);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Appending */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Appends formatted text to the destination string.
|
||||
*
|
||||
* @param string The destination string.
|
||||
* @param format The format string.
|
||||
* @param ... The format arguments.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYAN_PRINTF_ATTR(2, 3)
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringAppendFormat(
|
||||
ZyanString* string, const char* format, ...);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Formats the given unsigned ordinal `value` to its decimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecU(ZyanString* string, ZyanU64 value,
|
||||
ZyanU8 padding_length);
|
||||
|
||||
/**
|
||||
* Formats the given signed ordinal `value` to its decimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecS(ZyanString* string, ZyanI64 value,
|
||||
ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView* prefix);
|
||||
|
||||
/**
|
||||
* Formats the given unsigned ordinal `value` to its hexadecimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||
* ones ('a'-'f').
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexU(ZyanString* string, ZyanU64 value,
|
||||
ZyanU8 padding_length, ZyanBool uppercase);
|
||||
|
||||
/**
|
||||
* Formats the given signed ordinal `value` to its hexadecimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||
* ones ('a'-'f').
|
||||
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexS(ZyanString* string, ZyanI64 value,
|
||||
ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ZYCORE_FORMAT_H
|
@ -0,0 +1,511 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides a simple LibC abstraction and fallback routines.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_LIBC_H
|
||||
#define ZYCORE_LIBC_H
|
||||
|
||||
#ifndef ZYAN_CUSTOM_LIBC
|
||||
|
||||
// Include a custom LibC header and define `ZYAN_CUSTOM_LIBC` to provide your own LibC
|
||||
// replacement functions
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* LibC is available */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* errno.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define ZYAN_ERRNO errno
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdarg.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVAList` datatype.
|
||||
*/
|
||||
typedef va_list ZyanVAList;
|
||||
|
||||
#define ZYAN_VA_START va_start
|
||||
#define ZYAN_VA_ARG va_arg
|
||||
#define ZYAN_VA_END va_end
|
||||
#define ZYAN_VA_COPY(dest, source) va_copy((dest), (source))
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdio.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define ZYAN_FPUTS fputs
|
||||
#define ZYAN_FPUTC fputc
|
||||
#define ZYAN_FPRINTF fprintf
|
||||
#define ZYAN_PRINTF printf
|
||||
#define ZYAN_PUTC putc
|
||||
#define ZYAN_PUTS puts
|
||||
#define ZYAN_SCANF scanf
|
||||
#define ZYAN_SSCANF sscanf
|
||||
#define ZYAN_VSNPRINTF vsnprintf
|
||||
|
||||
/**
|
||||
* Defines the `ZyanFile` datatype.
|
||||
*/
|
||||
typedef FILE ZyanFile;
|
||||
|
||||
#define ZYAN_STDIN stdin
|
||||
#define ZYAN_STDOUT stdout
|
||||
#define ZYAN_STDERR stderr
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdlib.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#include <stdlib.h>
|
||||
#define ZYAN_CALLOC calloc
|
||||
#define ZYAN_FREE free
|
||||
#define ZYAN_MALLOC malloc
|
||||
#define ZYAN_REALLOC realloc
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* string.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#include <string.h>
|
||||
#define ZYAN_MEMCHR memchr
|
||||
#define ZYAN_MEMCMP memcmp
|
||||
#define ZYAN_MEMCPY memcpy
|
||||
#define ZYAN_MEMMOVE memmove
|
||||
#define ZYAN_MEMSET memset
|
||||
#define ZYAN_STRCAT strcat
|
||||
#define ZYAN_STRCHR strchr
|
||||
#define ZYAN_STRCMP strcmp
|
||||
#define ZYAN_STRCOLL strcoll
|
||||
#define ZYAN_STRCPY strcpy
|
||||
#define ZYAN_STRCSPN strcspn
|
||||
#define ZYAN_STRLEN strlen
|
||||
#define ZYAN_STRNCAT strncat
|
||||
#define ZYAN_STRNCMP strncmp
|
||||
#define ZYAN_STRNCPY strncpy
|
||||
#define ZYAN_STRPBRK strpbrk
|
||||
#define ZYAN_STRRCHR strrchr
|
||||
#define ZYAN_STRSPN strspn
|
||||
#define ZYAN_STRSTR strstr
|
||||
#define ZYAN_STRTOK strtok
|
||||
#define ZYAN_STRXFRM strxfrm
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#else // if ZYAN_NO_LIBC
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* No LibC available, use our own functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
/*
|
||||
* These implementations are by no means optimized and will be outperformed by pretty much any
|
||||
* libc implementation out there. We do not aim towards providing competetive implementations here,
|
||||
* but towards providing a last resort fallback for environments without a working libc.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdarg.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(ZYAN_MSVC) || defined(ZYAN_ICC)
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVAList` datatype.
|
||||
*/
|
||||
typedef char* ZyanVAList;
|
||||
|
||||
# define ZYAN_VA_START __crt_va_start
|
||||
# define ZYAN_VA_ARG __crt_va_arg
|
||||
# define ZYAN_VA_END __crt_va_end
|
||||
# define ZYAN_VA_COPY(destination, source) ((destination) = (source))
|
||||
|
||||
#elif defined(ZYAN_GNUC)
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVAList` datatype.
|
||||
*/
|
||||
typedef __builtin_va_list ZyanVAList;
|
||||
|
||||
# define ZYAN_VA_START(v, l) __builtin_va_start(v, l)
|
||||
# define ZYAN_VA_END(v) __builtin_va_end(v)
|
||||
# define ZYAN_VA_ARG(v, l) __builtin_va_arg(v, l)
|
||||
# define ZYAN_VA_COPY(d, s) __builtin_va_copy(d, s)
|
||||
|
||||
#else
|
||||
# error "Unsupported compiler for no-libc mode."
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdio.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
// ZYAN_INLINE int ZYAN_VSNPRINTF (char* const buffer, ZyanUSize const count,
|
||||
// char const* const format, ZyanVAList args)
|
||||
// {
|
||||
// // We cant provide a fallback implementation for this function
|
||||
// ZYAN_UNUSED(buffer);
|
||||
// ZYAN_UNUSED(count);
|
||||
// ZYAN_UNUSED(format);
|
||||
// ZYAN_UNUSED(args);
|
||||
// return ZYAN_NULL;
|
||||
// }
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdlib.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
// ZYAN_INLINE void* ZYAN_CALLOC(ZyanUSize nitems, ZyanUSize size)
|
||||
// {
|
||||
// // We cant provide a fallback implementation for this function
|
||||
// ZYAN_UNUSED(nitems);
|
||||
// ZYAN_UNUSED(size);
|
||||
// return ZYAN_NULL;
|
||||
// }
|
||||
//
|
||||
// ZYAN_INLINE void ZYAN_FREE(void *p)
|
||||
// {
|
||||
// // We cant provide a fallback implementation for this function
|
||||
// ZYAN_UNUSED(p);
|
||||
// }
|
||||
//
|
||||
// ZYAN_INLINE void* ZYAN_MALLOC(ZyanUSize n)
|
||||
// {
|
||||
// // We cant provide a fallback implementation for this function
|
||||
// ZYAN_UNUSED(n);
|
||||
// return ZYAN_NULL;
|
||||
// }
|
||||
//
|
||||
// ZYAN_INLINE void* ZYAN_REALLOC(void* p, ZyanUSize n)
|
||||
// {
|
||||
// // We cant provide a fallback implementation for this function
|
||||
// ZYAN_UNUSED(p);
|
||||
// ZYAN_UNUSED(n);
|
||||
// return ZYAN_NULL;
|
||||
// }
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* string.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZYAN_INLINE void* ZYAN_MEMCHR(const void* str, int c, ZyanUSize n)
|
||||
{
|
||||
const ZyanU8* p = (ZyanU8*)str;
|
||||
while (n--)
|
||||
{
|
||||
if (*p != (ZyanU8)c)
|
||||
{
|
||||
p++;
|
||||
} else
|
||||
{
|
||||
return (void*)p;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE int ZYAN_MEMCMP(const void* s1, const void* s2, ZyanUSize n)
|
||||
{
|
||||
const ZyanU8* p1 = s1, *p2 = s2;
|
||||
while (n--)
|
||||
{
|
||||
if (*p1 != *p2)
|
||||
{
|
||||
return *p1 - *p2;
|
||||
}
|
||||
p1++, p2++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE void* ZYAN_MEMCPY(void* dst, const void* src, ZyanUSize n)
|
||||
{
|
||||
volatile ZyanU8* dp = dst;
|
||||
const ZyanU8* sp = src;
|
||||
while (n--)
|
||||
{
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
ZYAN_INLINE void* ZYAN_MEMMOVE(void* dst, const void* src, ZyanUSize n)
|
||||
{
|
||||
volatile ZyanU8* pd = dst;
|
||||
const ZyanU8* ps = src;
|
||||
if (ps < pd)
|
||||
{
|
||||
for (pd += n, ps += n; n--;)
|
||||
{
|
||||
*--pd = *--ps;
|
||||
}
|
||||
} else
|
||||
{
|
||||
while (n--)
|
||||
{
|
||||
*pd++ = *ps++;
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
ZYAN_INLINE void* ZYAN_MEMSET(void* dst, int val, ZyanUSize n)
|
||||
{
|
||||
volatile ZyanU8* p = dst;
|
||||
while (n--)
|
||||
{
|
||||
*p++ = (unsigned char)val;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRCAT(char* dest, const char* src)
|
||||
{
|
||||
char* ret = dest;
|
||||
while (*dest)
|
||||
{
|
||||
dest++;
|
||||
}
|
||||
while ((*dest++ = *src++));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRCHR(const char* s, int c)
|
||||
{
|
||||
while (*s != (char)c)
|
||||
{
|
||||
if (!*s++)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return (char*)s;
|
||||
}
|
||||
|
||||
ZYAN_INLINE int ZYAN_STRCMP(const char* s1, const char* s2)
|
||||
{
|
||||
while (*s1 && (*s1 == *s2))
|
||||
{
|
||||
s1++, s2++;
|
||||
}
|
||||
return *(const ZyanU8*)s1 - *(const ZyanU8*)s2;
|
||||
}
|
||||
|
||||
ZYAN_INLINE int ZYAN_STRCOLL(const char *s1, const char *s2)
|
||||
{
|
||||
// TODO: Implement
|
||||
|
||||
ZYAN_UNUSED(s1);
|
||||
ZYAN_UNUSED(s2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRCPY(char* dest, const char* src)
|
||||
{
|
||||
char* ret = dest;
|
||||
while ((*dest++ = *src++));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE ZyanUSize ZYAN_STRCSPN(const char *s1, const char *s2)
|
||||
{
|
||||
ZyanUSize ret = 0;
|
||||
while (*s1)
|
||||
{
|
||||
if (ZYAN_STRCHR(s2, *s1))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
s1++, ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE ZyanUSize ZYAN_STRLEN(const char* str)
|
||||
{
|
||||
const char* p = str;
|
||||
while (*str)
|
||||
{
|
||||
++str;
|
||||
}
|
||||
return str - p;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRNCAT(char* dest, const char* src, ZyanUSize n)
|
||||
{
|
||||
char* ret = dest;
|
||||
while (*dest)
|
||||
{
|
||||
dest++;
|
||||
}
|
||||
while (n--)
|
||||
{
|
||||
if (!(*dest++ = *src++))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
*dest = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE int ZYAN_STRNCMP(const char* s1, const char* s2, ZyanUSize n)
|
||||
{
|
||||
while (n--)
|
||||
{
|
||||
if (*s1++ != *s2++)
|
||||
{
|
||||
return *(unsigned char*)(s1 - 1) - *(unsigned char*)(s2 - 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRNCPY(char* dest, const char* src, ZyanUSize n)
|
||||
{
|
||||
char* ret = dest;
|
||||
do
|
||||
{
|
||||
if (!n--)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
} while ((*dest++ = *src++));
|
||||
while (n--)
|
||||
{
|
||||
*dest++ = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRPBRK(const char* s1, const char* s2)
|
||||
{
|
||||
while (*s1)
|
||||
{
|
||||
if(ZYAN_STRCHR(s2, *s1++))
|
||||
{
|
||||
return (char*)--s1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRRCHR(const char* s, int c)
|
||||
{
|
||||
char* ret = 0;
|
||||
do
|
||||
{
|
||||
if (*s == (char)c)
|
||||
{
|
||||
ret = (char*)s;
|
||||
}
|
||||
} while (*s++);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE ZyanUSize ZYAN_STRSPN(const char* s1, const char* s2)
|
||||
{
|
||||
ZyanUSize ret = 0;
|
||||
while (*s1 && ZYAN_STRCHR(s2, *s1++))
|
||||
{
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRSTR(const char* s1, const char* s2)
|
||||
{
|
||||
const ZyanUSize n = ZYAN_STRLEN(s2);
|
||||
while (*s1)
|
||||
{
|
||||
if (!ZYAN_MEMCMP(s1++, s2, n))
|
||||
{
|
||||
return (char*)(s1 - 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRTOK(char* str, const char* delim)
|
||||
{
|
||||
static char* p = 0;
|
||||
if (str)
|
||||
{
|
||||
p = str;
|
||||
} else
|
||||
if (!p)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
str = p + ZYAN_STRSPN(p, delim);
|
||||
p = str + ZYAN_STRCSPN(str, delim);
|
||||
if (p == str)
|
||||
{
|
||||
return p = 0;
|
||||
}
|
||||
p = *p ? *p = 0, p + 1 : 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
ZYAN_INLINE ZyanUSize ZYAN_STRXFRM(char* dest, const char* src, ZyanUSize n)
|
||||
{
|
||||
const ZyanUSize n2 = ZYAN_STRLEN(src);
|
||||
if (n > n2)
|
||||
{
|
||||
ZYAN_STRCPY(dest, src);
|
||||
}
|
||||
return n2;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif /* ZYCORE_LIBC_H */
|
@ -0,0 +1,574 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements a doubly linked list.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_LIST_H
|
||||
#define ZYCORE_LIST_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Allocator.h>
|
||||
#include <Zycore/Object.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanListNode` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZyanListNode_
|
||||
{
|
||||
/**
|
||||
* A pointer to the previous list node.
|
||||
*/
|
||||
struct ZyanListNode_* prev;
|
||||
/**
|
||||
* A pointer to the next list node.
|
||||
*/
|
||||
struct ZyanListNode_* next;
|
||||
} ZyanListNode;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanList` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZyanList_
|
||||
{
|
||||
/**
|
||||
* The memory allocator.
|
||||
*/
|
||||
ZyanAllocator* allocator;
|
||||
/**
|
||||
* The current number of elements in the list.
|
||||
*/
|
||||
ZyanUSize size;
|
||||
/**
|
||||
* The size of a single element in bytes.
|
||||
*/
|
||||
ZyanUSize element_size;
|
||||
/**
|
||||
* The element destructor callback.
|
||||
*/
|
||||
ZyanMemberProcedure destructor;
|
||||
/**
|
||||
* The head node.
|
||||
*/
|
||||
ZyanListNode* head;
|
||||
/**
|
||||
* The tail node.
|
||||
*/
|
||||
ZyanListNode* tail;
|
||||
/**
|
||||
* The data buffer.
|
||||
*
|
||||
* Only used for instances created by `ZyanListInitCustomBuffer`.
|
||||
*/
|
||||
void* buffer;
|
||||
/**
|
||||
* The data buffer capacity (number of bytes).
|
||||
*
|
||||
* Only used for instances created by `ZyanListInitCustomBuffer`.
|
||||
*/
|
||||
ZyanUSize capacity;
|
||||
/**
|
||||
* The first unused node.
|
||||
*
|
||||
* When removing a node, the first-unused value is updated to point at the removed node and the
|
||||
* next node of the removed node will be updated to point at the old first-unused node.
|
||||
*
|
||||
* When appending the memory of the first unused-node is recycled to store the new node. The
|
||||
* value of the first-unused node is then updated to point at the reused nodes next node.
|
||||
*
|
||||
* If the first-unused value is `ZYAN_NULL`, any new node will be "allocated" behind the tail
|
||||
* node (if there is enough space left in the fixed size buffer).
|
||||
*
|
||||
* Only used for instances created by `ZyanListInitCustomBuffer`.
|
||||
*/
|
||||
ZyanListNode* first_unused;
|
||||
} ZyanList;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines an uninitialized `ZyanList` instance.
|
||||
*/
|
||||
#define ZYAN_LIST_INITIALIZER \
|
||||
{ \
|
||||
/* allocator */ ZYAN_NULL, \
|
||||
/* size */ 0, \
|
||||
/* element_size */ 0, \
|
||||
/* head */ ZYAN_NULL, \
|
||||
/* destructor */ ZYAN_NULL, \
|
||||
/* tail */ ZYAN_NULL, \
|
||||
/* buffer */ ZYAN_NULL, \
|
||||
/* capacity */ 0, \
|
||||
/* first_unused */ ZYAN_NULL \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helper macros */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the data value of the given `node`.
|
||||
*
|
||||
* @param type The desired value type.
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
*
|
||||
* @result The data value of the given `node`.
|
||||
*
|
||||
* Note that this function is unsafe and might dereference a null-pointer.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define ZYAN_LIST_GET(type, node) \
|
||||
(*reinterpret_cast<const type*>(ZyanListGetNodeData(node)))
|
||||
#else
|
||||
#define ZYAN_LIST_GET(type, node) \
|
||||
(*(const type*)ZyanListGetNodeData(node))
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constructor and destructor */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanList` instance.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||
* `ZYAN_NULL` if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The memory for the list elements is dynamically allocated by the default allocator.
|
||||
*
|
||||
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListInit(ZyanList* list, ZyanUSize element_size,
|
||||
ZyanMemberProcedure destructor);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanList` instance and sets a custom `allocator`.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||
* `ZYAN_NULL` if not needed.
|
||||
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListInitEx(ZyanList* list, ZyanUSize element_size,
|
||||
ZyanMemberProcedure destructor, ZyanAllocator* allocator);
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanList` instance and configures it to use a custom user
|
||||
* defined buffer with a fixed size.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||
* `ZYAN_NULL` if not needed.
|
||||
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||
* @param capacity The maximum capacity (number of bytes) of the buffer including the
|
||||
* space required for the list-nodes.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The buffer capacity required to store `n` elements of type `T` is be calculated by:
|
||||
* `size = n * sizeof(ZyanListNode) + n * sizeof(T)`
|
||||
*
|
||||
* Finalization is not required for instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListInitCustomBuffer(ZyanList* list, ZyanUSize element_size,
|
||||
ZyanMemberProcedure destructor, void* buffer, ZyanUSize capacity);
|
||||
|
||||
/**
|
||||
* Destroys the given `ZyanList` instance.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListDestroy(ZyanList* list);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Duplication */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanList` instance by duplicating an existing list.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanList` instance.
|
||||
* @param source A pointer to the source list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The memory for the list is dynamically allocated by the default allocator.
|
||||
*
|
||||
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListDuplicate(ZyanList* destination,
|
||||
const ZyanList* source);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanList` instance by duplicating an existing list and sets a
|
||||
* custom `allocator`.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanList` instance.
|
||||
* @param source A pointer to the source list.
|
||||
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
|
||||
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListDuplicateEx(ZyanList* destination, const ZyanList* source,
|
||||
ZyanAllocator* allocator);
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanList` instance by duplicating an existing list and
|
||||
* configures it to use a custom user defined buffer with a fixed size.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanList` instance.
|
||||
* @param source A pointer to the source list.
|
||||
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||
* @param capacity The maximum capacity (number of bytes) of the buffer including the
|
||||
* space required for the list-nodes.
|
||||
|
||||
* This function will fail, if the capacity of the buffer is not sufficient
|
||||
* to store all elements of the source list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The buffer capacity required to store `n` elements of type `T` is be calculated by:
|
||||
* `size = n * sizeof(ZyanListNode) + n * sizeof(T)`
|
||||
*
|
||||
* Finalization is not required for instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListDuplicateCustomBuffer(ZyanList* destination,
|
||||
const ZyanList* source, void* buffer, ZyanUSize capacity);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Item access */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns a pointer to the first `ZyanListNode` struct of the given list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param node Receives a pointer to the first `ZyanListNode` struct of the list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetHeadNode(const ZyanList* list, const ZyanListNode** node);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the last `ZyanListNode` struct of the given list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param node Receives a pointer to the last `ZyanListNode` struct of the list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetTailNode(const ZyanList* list, const ZyanListNode** node);
|
||||
|
||||
/**
|
||||
* Receives a pointer to the previous `ZyanListNode` struct linked to the passed one.
|
||||
*
|
||||
* @param node Receives a pointer to the previous `ZyanListNode` struct linked to the passed
|
||||
* one.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetPrevNode(const ZyanListNode** node);
|
||||
|
||||
/**
|
||||
* Receives a pointer to the next `ZyanListNode` struct linked to the passed one.
|
||||
*
|
||||
* @param node Receives a pointer to the next `ZyanListNode` struct linked to the passed one.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetNextNode(const ZyanListNode** node);
|
||||
|
||||
/**
|
||||
* Returns a constant pointer to the data of the given `node`.
|
||||
*
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
*
|
||||
* @return A constant pointer to the the data of the given `node` or `ZYAN_NULL`, if an error
|
||||
* occured.
|
||||
*
|
||||
* Take a look at `ZyanListGetNodeDataEx`, if you need a function that returns a zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT const void* ZyanListGetNodeData(const ZyanListNode* node);
|
||||
|
||||
/**
|
||||
* Returns a constant pointer to the data of the given `node`..
|
||||
*
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
* @param value Receives a constant pointer to the data of the given `node`.
|
||||
*
|
||||
* Take a look at `ZyanListGetNodeData`, if you need a function that directly returns a pointer.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataEx(const ZyanListNode* node, const void** value);
|
||||
|
||||
/**
|
||||
* Returns a mutable pointer to the data of the given `node`.
|
||||
*
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
*
|
||||
* @return A mutable pointer to the the data of the given `node` or `ZYAN_NULL`, if an error
|
||||
* occured.
|
||||
*
|
||||
* Take a look at `ZyanListGetPointerMutableEx` instead, if you need a function that returns a
|
||||
* zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT void* ZyanListGetNodeDataMutable(const ZyanListNode* node);
|
||||
|
||||
/**
|
||||
* Returns a mutable pointer to the data of the given `node`..
|
||||
*
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
* @param value Receives a mutable pointer to the data of the given `node`.
|
||||
*
|
||||
* Take a look at `ZyanListGetNodeDataMutable`, if you need a function that directly returns a
|
||||
* pointer.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataMutableEx(const ZyanListNode* node, void** value);
|
||||
|
||||
/**
|
||||
* Assigns a new data value to the given `node`.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
* @param value The value to assign.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListSetNodeData(const ZyanList* list, const ZyanListNode* node,
|
||||
const void* value);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Insertion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Adds a new `item` to the end of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param item A pointer to the item to add.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListPushBack(ZyanList* list, const void* item);
|
||||
|
||||
/**
|
||||
* Adds a new `item` to the beginning of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param item A pointer to the item to add.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListPushFront(ZyanList* list, const void* item);
|
||||
|
||||
/**
|
||||
* Constructs an `item` in-place at the end of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param item Receives a pointer to the new item.
|
||||
* @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in
|
||||
* undefined state, if no constructor was passed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListEmplaceBack(ZyanList* list, void** item,
|
||||
ZyanMemberFunction constructor);
|
||||
|
||||
/**
|
||||
* Constructs an `item` in-place at the beginning of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param item Receives a pointer to the new item.
|
||||
* @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in
|
||||
* undefined state, if no constructor was passed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListEmplaceFront(ZyanList* list, void** item,
|
||||
ZyanMemberFunction constructor);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Deletion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Removes the last element of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListPopBack(ZyanList* list);
|
||||
|
||||
/**
|
||||
* Removes the firstelement of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListPopFront(ZyanList* list);
|
||||
|
||||
/**
|
||||
* Removes the given `node` from the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListRemove(ZyanList* list, const ZyanListNode* node);
|
||||
|
||||
/**
|
||||
* Removes multiple nodes from the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param first A pointer to the first node.
|
||||
* @param last A pointer to the last node.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListRemoveRange(ZyanList* list, const ZyanListNode* first,
|
||||
const ZyanListNode* last);
|
||||
|
||||
/**
|
||||
* Erases all elements of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListClear(ZyanList* list);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Searching */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
// TODO:
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Resizes the given `ZyanList` instance.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param size The new size of the list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListResize(ZyanList* list, ZyanUSize size);
|
||||
|
||||
/**
|
||||
* Resizes the given `ZyanList` instance.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param size The new size of the list.
|
||||
* @param initializer A pointer to a value to be used as initializer for new items.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListResizeEx(ZyanList* list, ZyanUSize size, const void* initializer);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Information */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the current size of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param size Receives the size of the list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetSize(const ZyanList* list, ZyanUSize* size);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_VECTOR_H */
|
@ -0,0 +1,84 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines some generic object-related datatypes.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_OBJECT_H
|
||||
#define ZYCORE_OBJECT_H
|
||||
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanMemberProcedure` function prototype.
|
||||
*
|
||||
* @param object A pointer to the object.
|
||||
*/
|
||||
typedef void (*ZyanMemberProcedure)(void* object);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanConstMemberProcedure` function prototype.
|
||||
*
|
||||
* @param object A pointer to the object.
|
||||
*/
|
||||
typedef void (*ZyanConstMemberProcedure)(const void* object);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanMemberFunction` function prototype.
|
||||
*
|
||||
* @param object A pointer to the object.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
typedef ZyanStatus (*ZyanMemberFunction)(void* object);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanConstMemberFunction` function prototype.
|
||||
*
|
||||
* @param object A pointer to the object.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
typedef ZyanStatus (*ZyanConstMemberFunction)(const void* object);
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_OBJECT_H */
|
@ -0,0 +1,287 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zyan-C)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Status code definitions and check macros.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_STATUS_H
|
||||
#define ZYCORE_STATUS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanStatus` data type.
|
||||
*/
|
||||
typedef ZyanU32 ZyanStatus;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Definition */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines a zyan status code.
|
||||
*
|
||||
* @param error `1`, if the status code signals an error or `0`, if not.
|
||||
* @param module The module id.
|
||||
* @param code The actual code.
|
||||
*
|
||||
* @return The zyan status code.
|
||||
*/
|
||||
#define ZYAN_MAKE_STATUS(error, module, code) \
|
||||
(ZyanStatus)((((error) & 0x01u) << 31u) | (((module) & 0x7FFu) << 20u) | ((code) & 0xFFFFFu))
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Checks */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Checks if a zyan operation was successful.
|
||||
*
|
||||
* @param status The zyan status-code to check.
|
||||
*
|
||||
* @return `ZYAN_TRUE`, if the operation succeeded or `ZYAN_FALSE`, if not.
|
||||
*/
|
||||
#define ZYAN_SUCCESS(status) \
|
||||
(!((status) & 0x80000000u))
|
||||
|
||||
/**
|
||||
* Checks if a zyan operation failed.
|
||||
*
|
||||
* @param status The zyan status-code to check.
|
||||
*
|
||||
* @return `ZYAN_TRUE`, if the operation failed or `ZYAN_FALSE`, if not.
|
||||
*/
|
||||
#define ZYAN_FAILED(status) \
|
||||
((status) & 0x80000000u)
|
||||
|
||||
/**
|
||||
* Checks if a zyan operation was successful and returns with the status-code, if not.
|
||||
*
|
||||
* @param status The zyan status-code to check.
|
||||
*/
|
||||
#define ZYAN_CHECK(status) \
|
||||
do \
|
||||
{ \
|
||||
const ZyanStatus status_047620348 = (status); \
|
||||
if (!ZYAN_SUCCESS(status_047620348)) \
|
||||
{ \
|
||||
return status_047620348; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Information */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the module id of a zyan status-code.
|
||||
*
|
||||
* @param status The zyan status-code.
|
||||
*
|
||||
* @return The module id of the zyan status-code.
|
||||
*/
|
||||
#define ZYAN_STATUS_MODULE(status) \
|
||||
(((status) >> 20) & 0x7FFu)
|
||||
|
||||
/**
|
||||
* Returns the code of a zyan status-code.
|
||||
*
|
||||
* @param status The zyan status-code.
|
||||
*
|
||||
* @return The code of the zyan status-code.
|
||||
*/
|
||||
#define ZYAN_STATUS_CODE(status) \
|
||||
((status) & 0xFFFFFu)
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Status codes */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Module IDs */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The zycore generic module id.
|
||||
*/
|
||||
#define ZYAN_MODULE_ZYCORE 0x001u
|
||||
|
||||
/**
|
||||
* The zycore arg-parse submodule id.
|
||||
*/
|
||||
#define ZYAN_MODULE_ARGPARSE 0x003u
|
||||
|
||||
/**
|
||||
* The base module id for user-defined status codes.
|
||||
*/
|
||||
#define ZYAN_MODULE_USER 0x3FFu
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Status codes (general purpose) */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The operation completed successfully.
|
||||
*/
|
||||
#define ZYAN_STATUS_SUCCESS \
|
||||
ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x00u)
|
||||
|
||||
/**
|
||||
* The operation failed with an generic error.
|
||||
*/
|
||||
#define ZYAN_STATUS_FAILED \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x01u)
|
||||
|
||||
/**
|
||||
* The operation completed successfully and returned `ZYAN_TRUE`.
|
||||
*/
|
||||
#define ZYAN_STATUS_TRUE \
|
||||
ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x02u)
|
||||
|
||||
/**
|
||||
* The operation completed successfully and returned `ZYAN_FALSE`.
|
||||
*/
|
||||
#define ZYAN_STATUS_FALSE \
|
||||
ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x03u)
|
||||
|
||||
/**
|
||||
* An invalid argument was passed to a function.
|
||||
*/
|
||||
#define ZYAN_STATUS_INVALID_ARGUMENT \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x04u)
|
||||
|
||||
/**
|
||||
* An attempt was made to perform an invalid operation.
|
||||
*/
|
||||
#define ZYAN_STATUS_INVALID_OPERATION \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x05u)
|
||||
|
||||
/**
|
||||
* Insufficient privileges to perform the requested operation.
|
||||
*/
|
||||
#define ZYAN_STATUS_ACCESS_DENIED \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x06u)
|
||||
|
||||
/**
|
||||
* The requested entity was not found.
|
||||
*/
|
||||
#define ZYAN_STATUS_NOT_FOUND \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x07u)
|
||||
|
||||
/**
|
||||
* An index passed to a function was out of bounds.
|
||||
*/
|
||||
#define ZYAN_STATUS_OUT_OF_RANGE \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x08u)
|
||||
|
||||
/**
|
||||
* A buffer passed to a function was too small to complete the requested operation.
|
||||
*/
|
||||
#define ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x09u)
|
||||
|
||||
/**
|
||||
* Insufficient memory to perform the operation.
|
||||
*/
|
||||
#define ZYAN_STATUS_NOT_ENOUGH_MEMORY \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Au)
|
||||
|
||||
/**
|
||||
* An unknown error occurred during a system function call.
|
||||
*/
|
||||
#define ZYAN_STATUS_BAD_SYSTEMCALL \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Bu)
|
||||
|
||||
/**
|
||||
* The process ran out of resources while performing an operation.
|
||||
*/
|
||||
#define ZYAN_STATUS_OUT_OF_RESOURCES \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Cu)
|
||||
|
||||
/**
|
||||
* A dependency library was not found or does have an unexpected version number or
|
||||
* feature-set.
|
||||
*/
|
||||
#define ZYAN_STATUS_MISSING_DEPENDENCY \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Du)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Status codes (arg parse) */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Argument was not expected.
|
||||
*/
|
||||
#define ZYAN_STATUS_ARG_NOT_UNDERSTOOD \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x00u)
|
||||
|
||||
/**
|
||||
* Too few arguments were provided.
|
||||
*/
|
||||
#define ZYAN_STATUS_TOO_FEW_ARGS \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x01u)
|
||||
|
||||
/**
|
||||
* Too many arguments were provided.
|
||||
*/
|
||||
#define ZYAN_STATUS_TOO_MANY_ARGS \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x02u)
|
||||
|
||||
/**
|
||||
* An argument that expected a value misses its value.
|
||||
*/
|
||||
#define ZYAN_STATUS_ARG_MISSES_VALUE \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x03u)
|
||||
|
||||
/**
|
||||
* A required argument is missing.
|
||||
*/
|
||||
#define ZYAN_STATUS_REQUIRED_ARG_MISSING \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x04u)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_STATUS_H */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,195 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zyan-C)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Includes and defines some default data types.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_TYPES_H
|
||||
#define ZYCORE_TYPES_H
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Integer types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_NO_LIBC) || \
|
||||
(defined(ZYAN_MSVC) && defined(ZYAN_KERNEL)) // The WDK LibC lacks stdint.h.
|
||||
// No LibC mode, use compiler built-in types / macros.
|
||||
# if defined(ZYAN_MSVC) || defined(ZYAN_ICC)
|
||||
typedef unsigned __int8 ZyanU8;
|
||||
typedef unsigned __int16 ZyanU16;
|
||||
typedef unsigned __int32 ZyanU32;
|
||||
typedef unsigned __int64 ZyanU64;
|
||||
typedef signed __int8 ZyanI8;
|
||||
typedef signed __int16 ZyanI16;
|
||||
typedef signed __int32 ZyanI32;
|
||||
typedef signed __int64 ZyanI64;
|
||||
# if _WIN64
|
||||
typedef ZyanU64 ZyanUSize;
|
||||
typedef ZyanI64 ZyanISize;
|
||||
typedef ZyanU64 ZyanUPointer;
|
||||
typedef ZyanI64 ZyanIPointer;
|
||||
# else
|
||||
typedef ZyanU32 ZyanUSize;
|
||||
typedef ZyanI32 ZyanISize;
|
||||
typedef ZyanU32 ZyanUPointer;
|
||||
typedef ZyanI32 ZyanIPointer;
|
||||
# endif
|
||||
# elif defined(ZYAN_GNUC)
|
||||
typedef __UINT8_TYPE__ ZyanU8;
|
||||
typedef __UINT16_TYPE__ ZyanU16;
|
||||
typedef __UINT32_TYPE__ ZyanU32;
|
||||
typedef __UINT64_TYPE__ ZyanU64;
|
||||
typedef __INT8_TYPE__ ZyanI8;
|
||||
typedef __INT16_TYPE__ ZyanI16;
|
||||
typedef __INT32_TYPE__ ZyanI32;
|
||||
typedef __INT64_TYPE__ ZyanI64;
|
||||
typedef __SIZE_TYPE__ ZyanUSize;
|
||||
typedef __PTRDIFF_TYPE__ ZyanISize;
|
||||
typedef __UINTPTR_TYPE__ ZyanUPointer;
|
||||
typedef __INTPTR_TYPE__ ZyanIPointer;
|
||||
# else
|
||||
# error "Unsupported compiler for no-libc mode."
|
||||
# endif
|
||||
#else
|
||||
// If is LibC present, we use stdint types.
|
||||
# include <stdint.h>
|
||||
# include <stddef.h>
|
||||
typedef uint8_t ZyanU8;
|
||||
typedef uint16_t ZyanU16;
|
||||
typedef uint32_t ZyanU32;
|
||||
typedef uint64_t ZyanU64;
|
||||
typedef int8_t ZyanI8;
|
||||
typedef int16_t ZyanI16;
|
||||
typedef int32_t ZyanI32;
|
||||
typedef int64_t ZyanI64;
|
||||
typedef size_t ZyanUSize;
|
||||
typedef ptrdiff_t ZyanISize;
|
||||
typedef uintptr_t ZyanUPointer;
|
||||
typedef intptr_t ZyanIPointer;
|
||||
#endif
|
||||
|
||||
// Verify size assumptions.
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanU8 ) == 1 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanU16 ) == 2 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanU32 ) == 4 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanU64 ) == 8 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanI8 ) == 1 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanI16 ) == 2 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanI32 ) == 4 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanI64 ) == 8 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanUSize ) == sizeof(void*)); // TODO: This one is incorrect!
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanISize ) == sizeof(void*)); // TODO: This one is incorrect!
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanUPointer) == sizeof(void*));
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanIPointer) == sizeof(void*));
|
||||
|
||||
// Verify signedness assumptions (relies on size checks above).
|
||||
ZYAN_STATIC_ASSERT((ZyanI8 )-1 >> 1 < (ZyanI8 )((ZyanU8 )-1 >> 1));
|
||||
ZYAN_STATIC_ASSERT((ZyanI16)-1 >> 1 < (ZyanI16)((ZyanU16)-1 >> 1));
|
||||
ZYAN_STATIC_ASSERT((ZyanI32)-1 >> 1 < (ZyanI32)((ZyanU32)-1 >> 1));
|
||||
ZYAN_STATIC_ASSERT((ZyanI64)-1 >> 1 < (ZyanI64)((ZyanU64)-1 >> 1));
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Pointer */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVoidPointer` data-type.
|
||||
*/
|
||||
typedef char* ZyanVoidPointer;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanConstVoidPointer` data-type.
|
||||
*/
|
||||
typedef const void* ZyanConstVoidPointer;
|
||||
|
||||
#define ZYAN_NULL ((void*)0)
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Logic types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Boolean */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYAN_FALSE 0
|
||||
#define ZYAN_TRUE 1
|
||||
|
||||
/**
|
||||
* Defines the `ZyanBool` data-type.
|
||||
*
|
||||
* Represents a default boolean data-type where `0` is interpreted as `false` and all other values
|
||||
* as `true`.
|
||||
*/
|
||||
typedef ZyanU8 ZyanBool;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Ternary */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanTernary` data-type.
|
||||
*
|
||||
* The `ZyanTernary` is a balanced ternary type that uses three truth values indicating `true`,
|
||||
* `false` and an indeterminate third value.
|
||||
*/
|
||||
typedef ZyanI8 ZyanTernary;
|
||||
|
||||
#define ZYAN_TERNARY_FALSE (-1)
|
||||
#define ZYAN_TERNARY_UNKNOWN 0x00
|
||||
#define ZYAN_TERNARY_TRUE 0x01
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* String types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* C-style strings */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanCharPointer` data-type.
|
||||
*
|
||||
* This type is most often used to represent null-terminated strings aka. C-style strings.
|
||||
*/
|
||||
typedef char* ZyanCharPointer;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanConstCharPointer` data-type.
|
||||
*
|
||||
* This type is most often used to represent null-terminated strings aka. C-style strings.
|
||||
*/
|
||||
typedef const char* ZyanConstCharPointer;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif /* ZYCORE_TYPES_H */
|
@ -0,0 +1,723 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements the vector container class.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_VECTOR_H
|
||||
#define ZYCORE_VECTOR_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Allocator.h>
|
||||
#include <Zycore/Comparison.h>
|
||||
#include <Zycore/Object.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Constants */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* The initial minimum capacity (number of elements) for all dynamically allocated vector
|
||||
* instances.
|
||||
*/
|
||||
#define ZYAN_VECTOR_MIN_CAPACITY 1
|
||||
|
||||
/**
|
||||
* The default growth factor for all vector instances.
|
||||
*/
|
||||
#define ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR 2.00f
|
||||
|
||||
/**
|
||||
* The default shrink threshold for all vector instances.
|
||||
*/
|
||||
#define ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD 0.25f
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVector` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZyanVector_
|
||||
{
|
||||
/**
|
||||
* The memory allocator.
|
||||
*/
|
||||
ZyanAllocator* allocator;
|
||||
/**
|
||||
* The growth factor.
|
||||
*/
|
||||
float growth_factor;
|
||||
/**
|
||||
* The shrink threshold.
|
||||
*/
|
||||
float shrink_threshold;
|
||||
/**
|
||||
* The current number of elements in the vector.
|
||||
*/
|
||||
ZyanUSize size;
|
||||
/**
|
||||
* The maximum capacity (number of elements).
|
||||
*/
|
||||
ZyanUSize capacity;
|
||||
/**
|
||||
* The size of a single element in bytes.
|
||||
*/
|
||||
ZyanUSize element_size;
|
||||
/**
|
||||
* The element destructor callback.
|
||||
*/
|
||||
ZyanMemberProcedure destructor;
|
||||
/**
|
||||
* The data pointer.
|
||||
*/
|
||||
void* data;
|
||||
} ZyanVector;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines an uninitialized `ZyanVector` instance.
|
||||
*/
|
||||
#define ZYAN_VECTOR_INITIALIZER \
|
||||
{ \
|
||||
/* allocator */ ZYAN_NULL, \
|
||||
/* growth_factor */ 0.0f, \
|
||||
/* shrink_threshold */ 0.0f, \
|
||||
/* size */ 0, \
|
||||
/* capacity */ 0, \
|
||||
/* element_size */ 0, \
|
||||
/* destructor */ ZYAN_NULL, \
|
||||
/* data */ ZYAN_NULL \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helper macros */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the value of the element at the given `index`.
|
||||
*
|
||||
* @param type The desired value type.
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
*
|
||||
* @result The value of the desired element in the vector.
|
||||
*
|
||||
* Note that this function is unsafe and might dereference a null-pointer.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define ZYAN_VECTOR_GET(type, vector, index) \
|
||||
(*reinterpret_cast<const type*>(ZyanVectorGet(vector, index)))
|
||||
#else
|
||||
#define ZYAN_VECTOR_GET(type, vector, index) \
|
||||
(*(const type*)ZyanVectorGet(vector, index))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Loops through all elements of the vector.
|
||||
*
|
||||
* @param type The desired value type.
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param item_name The name of the iterator item.
|
||||
* @param body The body to execute for each item in the vector.
|
||||
*/
|
||||
#define ZYAN_VECTOR_FOREACH(type, vector, item_name, body) \
|
||||
{ \
|
||||
const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \
|
||||
for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \
|
||||
++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \
|
||||
{ \
|
||||
const type item_name = ZYAN_VECTOR_GET(type, vector, \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \
|
||||
body \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops through all elements of the vector.
|
||||
*
|
||||
* @param type The desired value type.
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param item_name The name of the iterator item.
|
||||
* @param body The body to execute for each item in the vector.
|
||||
*/
|
||||
#define ZYAN_VECTOR_FOREACH_MUTABLE(type, vector, item_name, body) \
|
||||
{ \
|
||||
const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \
|
||||
for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \
|
||||
++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \
|
||||
{ \
|
||||
type* const item_name = ZyanVectorGetMutable(vector, \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \
|
||||
body \
|
||||
} \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constructor and destructor */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param capacity The initial capacity (number of elements).
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||
* `ZYAN_NULL` if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The memory for the vector elements is dynamically allocated by the default allocator using the
|
||||
* default growth factor of `2.0f` and the default shrink threshold of `0.25f`.
|
||||
*
|
||||
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorInit(ZyanVector* vector,
|
||||
ZyanUSize element_size, ZyanUSize capacity, ZyanMemberProcedure destructor);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanVector` instance and sets a custom `allocator` and memory
|
||||
* allocation/deallocation parameters.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param capacity The initial capacity (number of elements).
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted,
|
||||
* or `ZYAN_NULL` if not needed.
|
||||
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||
* @param growth_factor The growth factor (from `1.0f` to `x.xf`).
|
||||
* @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`).
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables
|
||||
* dynamic shrinking.
|
||||
*
|
||||
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorInitEx(ZyanVector* vector, ZyanUSize element_size,
|
||||
ZyanUSize capacity, ZyanMemberProcedure destructor, ZyanAllocator* allocator,
|
||||
float growth_factor, float shrink_threshold);
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanVector` instance and configures it to use a custom user
|
||||
* defined buffer with a fixed size.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||
* @param capacity The maximum capacity (number of elements) of the buffer.
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||
* `ZYAN_NULL` if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* Finalization is not required for instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorInitCustomBuffer(ZyanVector* vector, ZyanUSize element_size,
|
||||
void* buffer, ZyanUSize capacity, ZyanMemberProcedure destructor);
|
||||
|
||||
/**
|
||||
* Destroys the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance..
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorDestroy(ZyanVector* vector);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Duplication */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanVector` instance by duplicating an existing vector.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanVector` instance.
|
||||
* @param source A pointer to the source vector.
|
||||
* @param capacity The initial capacity (number of elements).
|
||||
*
|
||||
* This value is automatically adjusted to the size of the source vector, if
|
||||
* a smaller value was passed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The memory for the vector is dynamically allocated by the default allocator using the default
|
||||
* growth factor of `2.0f` and the default shrink threshold of `0.25f`.
|
||||
*
|
||||
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorDuplicate(ZyanVector* destination,
|
||||
const ZyanVector* source, ZyanUSize capacity);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanVector` instance by duplicating an existing vector and sets a
|
||||
* custom `allocator` and memory allocation/deallocation parameters.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanVector` instance.
|
||||
* @param source A pointer to the source vector.
|
||||
* @param capacity The initial capacity (number of elements).
|
||||
|
||||
* This value is automatically adjusted to the size of the source
|
||||
* vector, if a smaller value was passed.
|
||||
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||
* @param growth_factor The growth factor (from `1.0f` to `x.xf`).
|
||||
* @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`).
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables
|
||||
* dynamic shrinking.
|
||||
*
|
||||
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateEx(ZyanVector* destination, const ZyanVector* source,
|
||||
ZyanUSize capacity, ZyanAllocator* allocator, float growth_factor, float shrink_threshold);
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanVector` instance by duplicating an existing vector and
|
||||
* configures it to use a custom user defined buffer with a fixed size.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanVector` instance.
|
||||
* @param source A pointer to the source vector.
|
||||
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||
* @param capacity The maximum capacity (number of elements) of the buffer.
|
||||
|
||||
* This function will fail, if the capacity of the buffer is less than the
|
||||
* size of the source vector.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* Finalization is not required for instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateCustomBuffer(ZyanVector* destination,
|
||||
const ZyanVector* source, void* buffer, ZyanUSize capacity);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Element access */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns a constant pointer to the element at the given `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
*
|
||||
* @return A constant pointer to the desired element in the vector or `ZYAN_NULL`, if an error
|
||||
* occured.
|
||||
*
|
||||
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||
*
|
||||
* Take a look at `ZyanVectorGetPointer` instead, if you need a function that returns a zyan status
|
||||
* code.
|
||||
*/
|
||||
ZYCORE_EXPORT const void* ZyanVectorGet(const ZyanVector* vector, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Returns a mutable pointer to the element at the given `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
*
|
||||
* @return A mutable pointer to the desired element in the vector or `ZYAN_NULL`, if an error
|
||||
* occured.
|
||||
*
|
||||
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||
*
|
||||
* Take a look at `ZyanVectorGetPointerMutable` instead, if you need a function that returns a
|
||||
* zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT void* ZyanVectorGetMutable(const ZyanVector* vector, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Returns a constant pointer to the element at the given `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
* @param value Receives a constant pointer to the desired element in the vector.
|
||||
*
|
||||
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointer(const ZyanVector* vector, ZyanUSize index,
|
||||
const void** value);
|
||||
|
||||
/**
|
||||
* Returns a mutable pointer to the element at the given `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
* @param value Receives a mutable pointer to the desired element in the vector.
|
||||
*
|
||||
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointerMutable(const ZyanVector* vector, ZyanUSize index,
|
||||
void** value);
|
||||
|
||||
/**
|
||||
* Assigns a new value to the element at the given `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The value index.
|
||||
* @param value The value to assign.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorSet(ZyanVector* vector, ZyanUSize index,
|
||||
const void* value);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Insertion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Adds a new `element` to the end of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element A pointer to the element to add.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorPushBack(ZyanVector* vector, const void* element);
|
||||
|
||||
/**
|
||||
* Inserts an `element` at the given `index` of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The insert index.
|
||||
* @param element A pointer to the element to insert.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorInsert(ZyanVector* vector, ZyanUSize index,
|
||||
const void* element);
|
||||
|
||||
/**
|
||||
* Inserts multiple `elements` at the given `index` of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The insert index.
|
||||
* @param elements A pointer to the first element.
|
||||
* @param count The number of elements to insert.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorInsertRange(ZyanVector* vector, ZyanUSize index,
|
||||
const void* elements, ZyanUSize count);
|
||||
|
||||
/**
|
||||
* Constructs an `element` in-place at the end of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element Receives a pointer to the new element.
|
||||
* @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in
|
||||
* undefined state, if no constructor was passed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorEmplace(ZyanVector* vector, void** element,
|
||||
ZyanMemberFunction constructor);
|
||||
|
||||
/**
|
||||
* Constructs an `element` in-place and inserts it at the given `index` of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The insert index.
|
||||
* @param element Receives a pointer to the new element.
|
||||
* @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in
|
||||
* undefined state, if no constructor was passed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorEmplaceEx(ZyanVector* vector, ZyanUSize index,
|
||||
void** element, ZyanMemberFunction constructor);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Utils */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Swaps the element at `index_first` with the element at `index_second`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index_first The index of the first element.
|
||||
* @param index_second The index of the second element.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function requires the vector to have spare capacity for one temporary element. Call
|
||||
* `ZyanVectorReserve` before this function to increase capacity, if needed.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorSwapElements(ZyanVector* vector, ZyanUSize index_first,
|
||||
ZyanUSize index_second);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Deletion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Deletes the element at the given `index` of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorDelete(ZyanVector* vector, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Deletes multiple elements from the given vector, starting at `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The index of the first element to delete.
|
||||
* @param count The number of elements to delete.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorDeleteRange(ZyanVector* vector, ZyanUSize index,
|
||||
ZyanUSize count);
|
||||
|
||||
/**
|
||||
* Removes the last element of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorPopBack(ZyanVector* vector);
|
||||
|
||||
/**
|
||||
* Erases all elements of the given vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorClear(ZyanVector* vector);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Searching */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Sequentially searches for the first occurrence of `element` in the given vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element A pointer to the element to search for.
|
||||
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||
* @param comparison The comparison function to use.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||
* zyan status code if an error occured.
|
||||
*
|
||||
* The `found_index` is set to `-1`, if the element was not found.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorFind(const ZyanVector* vector, const void* element,
|
||||
ZyanISize* found_index, ZyanEqualityComparison comparison);
|
||||
|
||||
/**
|
||||
* Sequentially searches for the first occurrence of `element` in the given vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element A pointer to the element to search for.
|
||||
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||
* @param comparison The comparison function to use.
|
||||
* @param index The start index.
|
||||
* @param count The maximum number of elements to iterate, beginning from the start `index`.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||
* zyan status code if an error occured.
|
||||
*
|
||||
* The `found_index` is set to `-1`, if the element was not found.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorFindEx(const ZyanVector* vector, const void* element,
|
||||
ZyanISize* found_index, ZyanEqualityComparison comparison, ZyanUSize index, ZyanUSize count);
|
||||
|
||||
/**
|
||||
* Searches for the first occurrence of `element` in the given vector using a binary-
|
||||
* search algorithm.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element A pointer to the element to search for.
|
||||
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||
* @param comparison The comparison function to use.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||
* zyan status code if an error occured.
|
||||
*
|
||||
* If found, `found_index` contains the zero-based index of `element`. If not found, `found_index`
|
||||
* contains the index of the first entry larger than `element`.
|
||||
*
|
||||
* This function requires all elements in the vector to be strictly ordered (sorted).
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearch(const ZyanVector* vector, const void* element,
|
||||
ZyanUSize* found_index, ZyanComparison comparison);
|
||||
|
||||
/**
|
||||
* Searches for the first occurrence of `element` in the given vector using a binary-
|
||||
* search algorithm.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element A pointer to the element to search for.
|
||||
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||
* @param comparison The comparison function to use.
|
||||
* @param index The start index.
|
||||
* @param count The maximum number of elements to iterate, beginning from the start `index`.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||
* zyan status code if an error occured.
|
||||
*
|
||||
* If found, `found_index` contains the zero-based index of `element`. If not found, `found_index`
|
||||
* contains the index of the first entry larger than `element`.
|
||||
*
|
||||
* This function requires all elements in the vector to be strictly ordered (sorted).
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearchEx(const ZyanVector* vector, const void* element,
|
||||
ZyanUSize* found_index, ZyanComparison comparison, ZyanUSize index, ZyanUSize count);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Resizes the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param size The new size of the vector.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorResize(ZyanVector* vector, ZyanUSize size);
|
||||
|
||||
/**
|
||||
* Resizes the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param size The new size of the vector.
|
||||
* @param initializer A pointer to a value to be used as initializer for new items.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorResizeEx(ZyanVector* vector, ZyanUSize size,
|
||||
const void* initializer);
|
||||
|
||||
/**
|
||||
* Changes the capacity of the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param capacity The new minimum capacity of the vector.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorReserve(ZyanVector* vector, ZyanUSize capacity);
|
||||
|
||||
/**
|
||||
* Shrinks the capacity of the given vector to match it's size.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorShrinkToFit(ZyanVector* vector);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Information */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the current capacity of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param capacity Receives the size of the vector.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorGetCapacity(const ZyanVector* vector, ZyanUSize* capacity);
|
||||
|
||||
/**
|
||||
* Returns the current size of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param size Receives the size of the vector.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorGetSize(const ZyanVector* vector, ZyanUSize* size);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_VECTOR_H */
|
@ -0,0 +1,111 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Master include file, including everything else.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_H
|
||||
#define ZYCORE_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
// TODO:
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constants */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* A macro that defines the zycore version.
|
||||
*/
|
||||
#define ZYCORE_VERSION (ZyanU64)0x0001000000000000
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helper macros */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Extracts the major-part of the zycore version.
|
||||
*
|
||||
* @param version The zycore version value
|
||||
*/
|
||||
#define ZYCORE_VERSION_MAJOR(version) (ZyanU16)((version & 0xFFFF000000000000) >> 48)
|
||||
|
||||
/**
|
||||
* Extracts the minor-part of the zycore version.
|
||||
*
|
||||
* @param version The zycore version value
|
||||
*/
|
||||
#define ZYCORE_VERSION_MINOR(version) (ZyanU16)((version & 0x0000FFFF00000000) >> 32)
|
||||
|
||||
/**
|
||||
* Extracts the patch-part of the zycore version.
|
||||
*
|
||||
* @param version The zycore version value
|
||||
*/
|
||||
#define ZYCORE_VERSION_PATCH(version) (ZyanU16)((version & 0x00000000FFFF0000) >> 16)
|
||||
|
||||
/**
|
||||
* Extracts the build-part of the zycore version.
|
||||
*
|
||||
* @param version The zycore version value
|
||||
*/
|
||||
#define ZYCORE_VERSION_BUILD(version) (ZyanU16)(version & 0x000000000000FFFF)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Returns the zycore version.
|
||||
*
|
||||
* @return The zycore version.
|
||||
*
|
||||
* Use the macros provided in this file to extract the major, minor, patch and build part from the
|
||||
* returned version value.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanU64 ZycoreGetVersion(void);
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_H */
|
@ -0,0 +1,42 @@
|
||||
|
||||
#ifndef ZYCORE_EXPORT_H
|
||||
#define ZYCORE_EXPORT_H
|
||||
|
||||
#ifdef ZYCORE_STATIC_DEFINE
|
||||
# define ZYCORE_EXPORT
|
||||
# define ZYCORE_NO_EXPORT
|
||||
#else
|
||||
# ifndef ZYCORE_EXPORT
|
||||
# ifdef Zycore_EXPORTS
|
||||
/* We are building this library */
|
||||
# define ZYCORE_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
/* We are using this library */
|
||||
# define ZYCORE_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef ZYCORE_NO_EXPORT
|
||||
# define ZYCORE_NO_EXPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZYCORE_DEPRECATED
|
||||
# define ZYCORE_DEPRECATED __declspec(deprecated)
|
||||
#endif
|
||||
|
||||
#ifndef ZYCORE_DEPRECATED_EXPORT
|
||||
# define ZYCORE_DEPRECATED_EXPORT ZYCORE_EXPORT ZYCORE_DEPRECATED
|
||||
#endif
|
||||
|
||||
#ifndef ZYCORE_DEPRECATED_NO_EXPORT
|
||||
# define ZYCORE_DEPRECATED_NO_EXPORT ZYCORE_NO_EXPORT ZYCORE_DEPRECATED
|
||||
#endif
|
||||
|
||||
#if 0 /* DEFINE_NO_DEPRECATED */
|
||||
# ifndef ZYCORE_NO_DEPRECATED
|
||||
# define ZYCORE_NO_DEPRECATED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_EXPORT_H */
|
Binary file not shown.
@ -0,0 +1,237 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Functions for decoding instructions.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_DECODER_H
|
||||
#define ZYDIS_DECODER_H
|
||||
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zydis/DecoderTypes.h>
|
||||
#include <Zydis/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Decoder mode */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisDecoderMode` enum.
|
||||
*/
|
||||
typedef enum ZydisDecoderMode_
|
||||
{
|
||||
/**
|
||||
* Enables minimal instruction decoding without semantic analysis.
|
||||
*
|
||||
* This mode provides access to the mnemonic, the instruction-length, the effective
|
||||
* operand-size, the effective address-width, some attributes (e.g. `ZYDIS_ATTRIB_IS_RELATIVE`)
|
||||
* and all of the information in the `raw` field of the `ZydisDecodedInstruction` struct.
|
||||
*
|
||||
* Operands, most attributes and other specific information (like `AVX` info) are not
|
||||
* accessible in this mode.
|
||||
*
|
||||
* This mode is NOT enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_MINIMAL,
|
||||
/**
|
||||
* Enables the `AMD`-branch mode.
|
||||
*
|
||||
* Intel ignores the operand-size override-prefix (`0x66`) for all branches with 32-bit
|
||||
* immediates and forces the operand-size of the instruction to 64-bit in 64-bit mode.
|
||||
* In `AMD`-branch mode `0x66` is not ignored and changes the operand-size and the size of the
|
||||
* immediate to 16-bit.
|
||||
*
|
||||
* This mode is NOT enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_AMD_BRANCHES,
|
||||
/**
|
||||
* Enables `KNC` compatibility-mode.
|
||||
*
|
||||
* `KNC` and `KNL+` chips are sharing opcodes and encodings for some mask-related instructions.
|
||||
* Enable this mode to use the old `KNC` specifications (different mnemonics, operands, ..).
|
||||
*
|
||||
* This mode is NOT enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_KNC,
|
||||
/**
|
||||
* Enables the `MPX` mode.
|
||||
*
|
||||
* The `MPX` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||
*
|
||||
* This mode is enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_MPX,
|
||||
/**
|
||||
* Enables the `CET` mode.
|
||||
*
|
||||
* The `CET` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||
*
|
||||
* This mode is enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_CET,
|
||||
/**
|
||||
* Enables the `LZCNT` mode.
|
||||
*
|
||||
* The `LZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||
*
|
||||
* This mode is enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_LZCNT,
|
||||
/**
|
||||
* Enables the `TZCNT` mode.
|
||||
*
|
||||
* The `TZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||
*
|
||||
* This mode is enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_TZCNT,
|
||||
/**
|
||||
* Enables the `WBNOINVD` mode.
|
||||
*
|
||||
* The `WBINVD` instruction is interpreted as `WBNOINVD` on ICL chips, if a `F3` prefix is
|
||||
* used.
|
||||
*
|
||||
* This mode is disabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_WBNOINVD,
|
||||
/**
|
||||
* Enables the `CLDEMOTE` mode.
|
||||
*
|
||||
* The `CLDEMOTE` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||
*
|
||||
* This mode is enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_CLDEMOTE,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_MAX_VALUE = ZYDIS_DECODER_MODE_CLDEMOTE,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_DECODER_MODE_MAX_VALUE)
|
||||
} ZydisDecoderMode;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Decoder struct */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisDecoder` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZydisDecoder_
|
||||
{
|
||||
/**
|
||||
* The machine mode.
|
||||
*/
|
||||
ZydisMachineMode machine_mode;
|
||||
/**
|
||||
* The address width.
|
||||
*/
|
||||
ZydisAddressWidth address_width;
|
||||
/**
|
||||
* The decoder mode array.
|
||||
*/
|
||||
ZyanBool decoder_mode[ZYDIS_DECODER_MODE_MAX_VALUE + 1];
|
||||
} ZydisDecoder;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* @addtogroup decoder Decoder
|
||||
* Functions allowing decoding of instruction bytes to a machine interpretable struct.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initializes the given `ZydisDecoder` instance.
|
||||
*
|
||||
* @param decoder A pointer to the `ZydisDecoder` instance.
|
||||
* @param machine_mode The machine mode.
|
||||
* @param address_width The address width.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machine_mode,
|
||||
ZydisAddressWidth address_width);
|
||||
|
||||
/**
|
||||
* Enables or disables the specified decoder-mode.
|
||||
*
|
||||
* @param decoder A pointer to the `ZydisDecoder` instance.
|
||||
* @param mode The decoder mode.
|
||||
* @param enabled `ZYAN_TRUE` to enable, or `ZYAN_FALSE` to disable the specified decoder-mode.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecoderMode mode,
|
||||
ZyanBool enabled);
|
||||
|
||||
/**
|
||||
* Decodes the instruction in the given input `buffer`.
|
||||
*
|
||||
* @param decoder A pointer to the `ZydisDecoder` instance.
|
||||
* @param buffer A pointer to the input buffer.
|
||||
* @param length The length of the input buffer. Note that this can be bigger than the
|
||||
* actual size of the instruction -- you don't have to know the size up
|
||||
* front. This length is merely used to prevent Zydis from doing
|
||||
* out-of-bounds reads on your buffer.
|
||||
* @param instruction A pointer to the `ZydisDecodedInstruction` struct, that receives the
|
||||
* details about the decoded instruction.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisDecoderDecodeBuffer(const ZydisDecoder* decoder,
|
||||
const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction);
|
||||
|
||||
/** @} */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_DECODER_H */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,306 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements the `ZydisFormatterToken` type and provides functions to use it.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_FORMATTER_TOKEN_H
|
||||
#define ZYDIS_FORMATTER_TOKEN_H
|
||||
|
||||
#include <ZydisExportConfig.h>
|
||||
#include <Zycore/String.h>
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zydis/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Constants */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Token types */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @biref Defines the `ZydisTokenType` data-type.
|
||||
*/
|
||||
typedef ZyanU8 ZydisTokenType;
|
||||
|
||||
#define ZYDIS_TOKEN_INVALID 0x00
|
||||
/**
|
||||
* A whitespace character.
|
||||
*/
|
||||
#define ZYDIS_TOKEN_WHITESPACE 0x01
|
||||
/**
|
||||
* A delimiter character (like `','`, `':'`, `'+'`, `'-'`, `'*'`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_DELIMITER 0x02
|
||||
/**
|
||||
* An opening parenthesis character (like `'('`, `'['`, `'{'`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_PARENTHESIS_OPEN 0x03
|
||||
/**
|
||||
* A closing parenthesis character (like `')'`, `']'`, `'}'`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_PARENTHESIS_CLOSE 0x04
|
||||
/**
|
||||
* A prefix literal (like `"LOCK"`, `"REP"`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_PREFIX 0x05
|
||||
/**
|
||||
* A mnemonic literal (like `"MOV"`, `"VCMPPSD"`, `"LCALL"`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_MNEMONIC 0x06
|
||||
/**
|
||||
* A register literal (like `"RAX"`, `"DS"`, `"%ECX"`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_REGISTER 0x07
|
||||
/**
|
||||
* An absolute address literal (like `0x00400000`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_ADDRESS_ABS 0x08
|
||||
/**
|
||||
* A relative address literal (like `-0x100`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_ADDRESS_REL 0x09
|
||||
/**
|
||||
* A displacement literal (like `0xFFFFFFFF`, `-0x100`, `+0x1234`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_DISPLACEMENT 0x0A
|
||||
/**
|
||||
* An immediate literal (like `0xC0`, `-0x1234`, `$0x0000`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_IMMEDIATE 0x0B
|
||||
/**
|
||||
* A typecast literal (like `DWORD PTR`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_TYPECAST 0x0C
|
||||
/**
|
||||
* A decorator literal (like `"Z"`, `"1TO4"`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_DECORATOR 0x0D
|
||||
/**
|
||||
* A symbol literal.
|
||||
*/
|
||||
#define ZYDIS_TOKEN_SYMBOL 0x0E
|
||||
|
||||
/**
|
||||
* The base for user-defined token types.
|
||||
*/
|
||||
#define ZYDIS_TOKEN_USER 0x80
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Token */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/**
|
||||
* Defines the `ZydisFormatterToken` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZydisFormatterToken_
|
||||
{
|
||||
/**
|
||||
* The token type.
|
||||
*/
|
||||
ZydisTokenType type;
|
||||
/**
|
||||
* An offset to the next token, or `0`.
|
||||
*/
|
||||
ZyanU8 next;
|
||||
} ZydisFormatterToken;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* Defines the `ZydisFormatterTokenConst` data-type.
|
||||
*/
|
||||
typedef const ZydisFormatterToken ZydisFormatterTokenConst;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Buffer */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisFormatterBuffer` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may
|
||||
* lead to unexpected behavior.
|
||||
*/
|
||||
typedef struct ZydisFormatterBuffer_
|
||||
{
|
||||
/**
|
||||
* `ZYAN_TRUE`, if the buffer contains a token stream or `ZYAN_FALSE, if it
|
||||
* contains a simple string.
|
||||
*/
|
||||
ZyanBool is_token_list;
|
||||
/**
|
||||
* The remaining capacity of the buffer.
|
||||
*/
|
||||
ZyanUSize capacity;
|
||||
/**
|
||||
* The `ZyanString` instance that refers to the literal value of the most
|
||||
* recently added token.
|
||||
*/
|
||||
ZyanString string;
|
||||
} ZydisFormatterBuffer;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Token */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the `type` and the string `value` of the given `token`.
|
||||
*
|
||||
* @param token A pointer to the `ZydisFormatterToken` struct.
|
||||
* @param type Receives the token type.
|
||||
* @param value Receives a pointer to the string value of the token.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenGetValue(const ZydisFormatterToken* token,
|
||||
ZydisTokenType* type, ZyanConstCharPointer* value);
|
||||
|
||||
/**
|
||||
* Obtains the next `token` linked to the passed one.
|
||||
*
|
||||
* @param token Receives a pointer to the next `ZydisFormatterToken` struct
|
||||
* linked to the passed one.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Buffer */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the current (most recently added) token.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param token Receives a pointer to the current token.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least
|
||||
* one token.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* buffer,
|
||||
ZydisFormatterTokenConst** token);
|
||||
|
||||
/**
|
||||
* Returns the `ZyanString` instance associated with the given buffer.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param string Receives a pointer to the `ZyanString` instance associated with the given
|
||||
* buffer.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least
|
||||
* one token.
|
||||
*
|
||||
* The returned string always refers to the literal value of the current (most recently added)
|
||||
* token and will remain valid until the buffer is destroyed.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buffer,
|
||||
ZyanString** string);
|
||||
|
||||
/**
|
||||
* Appends a new token to the `buffer`.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param type The type of the new token.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will
|
||||
* automatically be updated by calling this function.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer,
|
||||
ZydisTokenType type);
|
||||
|
||||
/**
|
||||
* Returns a snapshot of the buffer-state.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param state Receives a snapshot of the buffer-state.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* Note that the buffer-state is saved inside the buffer itself and thus becomes invalid as soon
|
||||
* as the buffer gets overwritten or destroyed.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer,
|
||||
ZyanUPointer* state);
|
||||
|
||||
/**
|
||||
* Restores a previously saved buffer-state.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param state The buffer-state to restore.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* All tokens added after obtaining the given `state` snapshot will be removed. This function
|
||||
* does NOT restore any string content.
|
||||
*
|
||||
* Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will
|
||||
* automatically be updated by calling this function.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer,
|
||||
ZyanUPointer state);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_FORMATTER_TOKEN_H */
|
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Defines the `ZydisISAExt` enum.
|
||||
*/
|
||||
typedef enum ZydisISAExt_
|
||||
{
|
||||
ZYDIS_ISA_EXT_INVALID,
|
||||
ZYDIS_ISA_EXT_ADOX_ADCX,
|
||||
ZYDIS_ISA_EXT_AES,
|
||||
ZYDIS_ISA_EXT_AMD3DNOW,
|
||||
ZYDIS_ISA_EXT_AMD3DNOW_PREFETCH,
|
||||
ZYDIS_ISA_EXT_AMD_INVLPGB,
|
||||
ZYDIS_ISA_EXT_AMX_BF16,
|
||||
ZYDIS_ISA_EXT_AMX_INT8,
|
||||
ZYDIS_ISA_EXT_AMX_TILE,
|
||||
ZYDIS_ISA_EXT_AVX,
|
||||
ZYDIS_ISA_EXT_AVX2,
|
||||
ZYDIS_ISA_EXT_AVX2GATHER,
|
||||
ZYDIS_ISA_EXT_AVX512EVEX,
|
||||
ZYDIS_ISA_EXT_AVX512VEX,
|
||||
ZYDIS_ISA_EXT_AVXAES,
|
||||
ZYDIS_ISA_EXT_BASE,
|
||||
ZYDIS_ISA_EXT_BMI1,
|
||||
ZYDIS_ISA_EXT_BMI2,
|
||||
ZYDIS_ISA_EXT_CET,
|
||||
ZYDIS_ISA_EXT_CLDEMOTE,
|
||||
ZYDIS_ISA_EXT_CLFLUSHOPT,
|
||||
ZYDIS_ISA_EXT_CLFSH,
|
||||
ZYDIS_ISA_EXT_CLWB,
|
||||
ZYDIS_ISA_EXT_CLZERO,
|
||||
ZYDIS_ISA_EXT_ENQCMD,
|
||||
ZYDIS_ISA_EXT_F16C,
|
||||
ZYDIS_ISA_EXT_FMA,
|
||||
ZYDIS_ISA_EXT_FMA4,
|
||||
ZYDIS_ISA_EXT_GFNI,
|
||||
ZYDIS_ISA_EXT_INVPCID,
|
||||
ZYDIS_ISA_EXT_KNC,
|
||||
ZYDIS_ISA_EXT_KNCE,
|
||||
ZYDIS_ISA_EXT_KNCV,
|
||||
ZYDIS_ISA_EXT_LONGMODE,
|
||||
ZYDIS_ISA_EXT_LZCNT,
|
||||
ZYDIS_ISA_EXT_MCOMMIT,
|
||||
ZYDIS_ISA_EXT_MMX,
|
||||
ZYDIS_ISA_EXT_MONITOR,
|
||||
ZYDIS_ISA_EXT_MONITORX,
|
||||
ZYDIS_ISA_EXT_MOVBE,
|
||||
ZYDIS_ISA_EXT_MOVDIR,
|
||||
ZYDIS_ISA_EXT_MPX,
|
||||
ZYDIS_ISA_EXT_PADLOCK,
|
||||
ZYDIS_ISA_EXT_PAUSE,
|
||||
ZYDIS_ISA_EXT_PCLMULQDQ,
|
||||
ZYDIS_ISA_EXT_PCONFIG,
|
||||
ZYDIS_ISA_EXT_PKU,
|
||||
ZYDIS_ISA_EXT_PREFETCHWT1,
|
||||
ZYDIS_ISA_EXT_PT,
|
||||
ZYDIS_ISA_EXT_RDPID,
|
||||
ZYDIS_ISA_EXT_RDPRU,
|
||||
ZYDIS_ISA_EXT_RDRAND,
|
||||
ZYDIS_ISA_EXT_RDSEED,
|
||||
ZYDIS_ISA_EXT_RDTSCP,
|
||||
ZYDIS_ISA_EXT_RDWRFSGS,
|
||||
ZYDIS_ISA_EXT_RTM,
|
||||
ZYDIS_ISA_EXT_SERIALIZE,
|
||||
ZYDIS_ISA_EXT_SGX,
|
||||
ZYDIS_ISA_EXT_SGX_ENCLV,
|
||||
ZYDIS_ISA_EXT_SHA,
|
||||
ZYDIS_ISA_EXT_SMAP,
|
||||
ZYDIS_ISA_EXT_SMX,
|
||||
ZYDIS_ISA_EXT_SNP,
|
||||
ZYDIS_ISA_EXT_SSE,
|
||||
ZYDIS_ISA_EXT_SSE2,
|
||||
ZYDIS_ISA_EXT_SSE3,
|
||||
ZYDIS_ISA_EXT_SSE4,
|
||||
ZYDIS_ISA_EXT_SSE4A,
|
||||
ZYDIS_ISA_EXT_SSSE3,
|
||||
ZYDIS_ISA_EXT_SVM,
|
||||
ZYDIS_ISA_EXT_TBM,
|
||||
ZYDIS_ISA_EXT_TSX_LDTRK,
|
||||
ZYDIS_ISA_EXT_VAES,
|
||||
ZYDIS_ISA_EXT_VMFUNC,
|
||||
ZYDIS_ISA_EXT_VPCLMULQDQ,
|
||||
ZYDIS_ISA_EXT_VTX,
|
||||
ZYDIS_ISA_EXT_WAITPKG,
|
||||
ZYDIS_ISA_EXT_X87,
|
||||
ZYDIS_ISA_EXT_XOP,
|
||||
ZYDIS_ISA_EXT_XSAVE,
|
||||
ZYDIS_ISA_EXT_XSAVEC,
|
||||
ZYDIS_ISA_EXT_XSAVEOPT,
|
||||
ZYDIS_ISA_EXT_XSAVES,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_ISA_EXT_MAX_VALUE = ZYDIS_ISA_EXT_XSAVES,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_ISA_EXT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_EXT_MAX_VALUE)
|
||||
} ZydisISAExt;
|
@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Defines the `ZydisISASet` enum.
|
||||
*/
|
||||
typedef enum ZydisISASet_
|
||||
{
|
||||
ZYDIS_ISA_SET_INVALID,
|
||||
ZYDIS_ISA_SET_ADOX_ADCX,
|
||||
ZYDIS_ISA_SET_AES,
|
||||
ZYDIS_ISA_SET_AMD,
|
||||
ZYDIS_ISA_SET_AMD3DNOW,
|
||||
ZYDIS_ISA_SET_AMX_BF16,
|
||||
ZYDIS_ISA_SET_AMX_INT8,
|
||||
ZYDIS_ISA_SET_AMX_TILE,
|
||||
ZYDIS_ISA_SET_AVX,
|
||||
ZYDIS_ISA_SET_AVX2,
|
||||
ZYDIS_ISA_SET_AVX2GATHER,
|
||||
ZYDIS_ISA_SET_AVX512BW_128,
|
||||
ZYDIS_ISA_SET_AVX512BW_128N,
|
||||
ZYDIS_ISA_SET_AVX512BW_256,
|
||||
ZYDIS_ISA_SET_AVX512BW_512,
|
||||
ZYDIS_ISA_SET_AVX512BW_KOP,
|
||||
ZYDIS_ISA_SET_AVX512CD_128,
|
||||
ZYDIS_ISA_SET_AVX512CD_256,
|
||||
ZYDIS_ISA_SET_AVX512CD_512,
|
||||
ZYDIS_ISA_SET_AVX512DQ_128,
|
||||
ZYDIS_ISA_SET_AVX512DQ_128N,
|
||||
ZYDIS_ISA_SET_AVX512DQ_256,
|
||||
ZYDIS_ISA_SET_AVX512DQ_512,
|
||||
ZYDIS_ISA_SET_AVX512DQ_KOP,
|
||||
ZYDIS_ISA_SET_AVX512DQ_SCALAR,
|
||||
ZYDIS_ISA_SET_AVX512ER_512,
|
||||
ZYDIS_ISA_SET_AVX512ER_SCALAR,
|
||||
ZYDIS_ISA_SET_AVX512F_128,
|
||||
ZYDIS_ISA_SET_AVX512F_128N,
|
||||
ZYDIS_ISA_SET_AVX512F_256,
|
||||
ZYDIS_ISA_SET_AVX512F_512,
|
||||
ZYDIS_ISA_SET_AVX512F_KOP,
|
||||
ZYDIS_ISA_SET_AVX512F_SCALAR,
|
||||
ZYDIS_ISA_SET_AVX512PF_512,
|
||||
ZYDIS_ISA_SET_AVX512_4FMAPS_512,
|
||||
ZYDIS_ISA_SET_AVX512_4FMAPS_SCALAR,
|
||||
ZYDIS_ISA_SET_AVX512_4VNNIW_512,
|
||||
ZYDIS_ISA_SET_AVX512_BF16_128,
|
||||
ZYDIS_ISA_SET_AVX512_BF16_256,
|
||||
ZYDIS_ISA_SET_AVX512_BF16_512,
|
||||
ZYDIS_ISA_SET_AVX512_BITALG_128,
|
||||
ZYDIS_ISA_SET_AVX512_BITALG_256,
|
||||
ZYDIS_ISA_SET_AVX512_BITALG_512,
|
||||
ZYDIS_ISA_SET_AVX512_GFNI_128,
|
||||
ZYDIS_ISA_SET_AVX512_GFNI_256,
|
||||
ZYDIS_ISA_SET_AVX512_GFNI_512,
|
||||
ZYDIS_ISA_SET_AVX512_IFMA_128,
|
||||
ZYDIS_ISA_SET_AVX512_IFMA_256,
|
||||
ZYDIS_ISA_SET_AVX512_IFMA_512,
|
||||
ZYDIS_ISA_SET_AVX512_VAES_128,
|
||||
ZYDIS_ISA_SET_AVX512_VAES_256,
|
||||
ZYDIS_ISA_SET_AVX512_VAES_512,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI2_128,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI2_256,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI2_512,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI_128,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI_256,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI_512,
|
||||
ZYDIS_ISA_SET_AVX512_VNNI_128,
|
||||
ZYDIS_ISA_SET_AVX512_VNNI_256,
|
||||
ZYDIS_ISA_SET_AVX512_VNNI_512,
|
||||
ZYDIS_ISA_SET_AVX512_VP2INTERSECT_128,
|
||||
ZYDIS_ISA_SET_AVX512_VP2INTERSECT_256,
|
||||
ZYDIS_ISA_SET_AVX512_VP2INTERSECT_512,
|
||||
ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_128,
|
||||
ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_256,
|
||||
ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_512,
|
||||
ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_128,
|
||||
ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_256,
|
||||
ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_512,
|
||||
ZYDIS_ISA_SET_AVXAES,
|
||||
ZYDIS_ISA_SET_AVX_GFNI,
|
||||
ZYDIS_ISA_SET_BMI1,
|
||||
ZYDIS_ISA_SET_BMI2,
|
||||
ZYDIS_ISA_SET_CET,
|
||||
ZYDIS_ISA_SET_CLDEMOTE,
|
||||
ZYDIS_ISA_SET_CLFLUSHOPT,
|
||||
ZYDIS_ISA_SET_CLFSH,
|
||||
ZYDIS_ISA_SET_CLWB,
|
||||
ZYDIS_ISA_SET_CLZERO,
|
||||
ZYDIS_ISA_SET_CMOV,
|
||||
ZYDIS_ISA_SET_CMPXCHG16B,
|
||||
ZYDIS_ISA_SET_ENQCMD,
|
||||
ZYDIS_ISA_SET_F16C,
|
||||
ZYDIS_ISA_SET_FAT_NOP,
|
||||
ZYDIS_ISA_SET_FCMOV,
|
||||
ZYDIS_ISA_SET_FMA,
|
||||
ZYDIS_ISA_SET_FMA4,
|
||||
ZYDIS_ISA_SET_FXSAVE,
|
||||
ZYDIS_ISA_SET_FXSAVE64,
|
||||
ZYDIS_ISA_SET_GFNI,
|
||||
ZYDIS_ISA_SET_I186,
|
||||
ZYDIS_ISA_SET_I286PROTECTED,
|
||||
ZYDIS_ISA_SET_I286REAL,
|
||||
ZYDIS_ISA_SET_I386,
|
||||
ZYDIS_ISA_SET_I486,
|
||||
ZYDIS_ISA_SET_I486REAL,
|
||||
ZYDIS_ISA_SET_I86,
|
||||
ZYDIS_ISA_SET_INVPCID,
|
||||
ZYDIS_ISA_SET_KNCE,
|
||||
ZYDIS_ISA_SET_KNCJKBR,
|
||||
ZYDIS_ISA_SET_KNCSTREAM,
|
||||
ZYDIS_ISA_SET_KNCV,
|
||||
ZYDIS_ISA_SET_KNC_MISC,
|
||||
ZYDIS_ISA_SET_KNC_PF_HINT,
|
||||
ZYDIS_ISA_SET_LAHF,
|
||||
ZYDIS_ISA_SET_LONGMODE,
|
||||
ZYDIS_ISA_SET_LZCNT,
|
||||
ZYDIS_ISA_SET_MCOMMIT,
|
||||
ZYDIS_ISA_SET_MONITOR,
|
||||
ZYDIS_ISA_SET_MONITORX,
|
||||
ZYDIS_ISA_SET_MOVBE,
|
||||
ZYDIS_ISA_SET_MOVDIR,
|
||||
ZYDIS_ISA_SET_MPX,
|
||||
ZYDIS_ISA_SET_PADLOCK_ACE,
|
||||
ZYDIS_ISA_SET_PADLOCK_PHE,
|
||||
ZYDIS_ISA_SET_PADLOCK_PMM,
|
||||
ZYDIS_ISA_SET_PADLOCK_RNG,
|
||||
ZYDIS_ISA_SET_PAUSE,
|
||||
ZYDIS_ISA_SET_PCLMULQDQ,
|
||||
ZYDIS_ISA_SET_PCONFIG,
|
||||
ZYDIS_ISA_SET_PENTIUMMMX,
|
||||
ZYDIS_ISA_SET_PENTIUMREAL,
|
||||
ZYDIS_ISA_SET_PKU,
|
||||
ZYDIS_ISA_SET_POPCNT,
|
||||
ZYDIS_ISA_SET_PPRO,
|
||||
ZYDIS_ISA_SET_PREFETCHWT1,
|
||||
ZYDIS_ISA_SET_PREFETCH_NOP,
|
||||
ZYDIS_ISA_SET_PT,
|
||||
ZYDIS_ISA_SET_RDPID,
|
||||
ZYDIS_ISA_SET_RDPMC,
|
||||
ZYDIS_ISA_SET_RDPRU,
|
||||
ZYDIS_ISA_SET_RDRAND,
|
||||
ZYDIS_ISA_SET_RDSEED,
|
||||
ZYDIS_ISA_SET_RDTSCP,
|
||||
ZYDIS_ISA_SET_RDWRFSGS,
|
||||
ZYDIS_ISA_SET_RTM,
|
||||
ZYDIS_ISA_SET_SERIALIZE,
|
||||
ZYDIS_ISA_SET_SGX,
|
||||
ZYDIS_ISA_SET_SGX_ENCLV,
|
||||
ZYDIS_ISA_SET_SHA,
|
||||
ZYDIS_ISA_SET_SMAP,
|
||||
ZYDIS_ISA_SET_SMX,
|
||||
ZYDIS_ISA_SET_SSE,
|
||||
ZYDIS_ISA_SET_SSE2,
|
||||
ZYDIS_ISA_SET_SSE2MMX,
|
||||
ZYDIS_ISA_SET_SSE3,
|
||||
ZYDIS_ISA_SET_SSE3X87,
|
||||
ZYDIS_ISA_SET_SSE4,
|
||||
ZYDIS_ISA_SET_SSE42,
|
||||
ZYDIS_ISA_SET_SSE4A,
|
||||
ZYDIS_ISA_SET_SSEMXCSR,
|
||||
ZYDIS_ISA_SET_SSE_PREFETCH,
|
||||
ZYDIS_ISA_SET_SSSE3,
|
||||
ZYDIS_ISA_SET_SSSE3MMX,
|
||||
ZYDIS_ISA_SET_SVM,
|
||||
ZYDIS_ISA_SET_TBM,
|
||||
ZYDIS_ISA_SET_TSX_LDTRK,
|
||||
ZYDIS_ISA_SET_VAES,
|
||||
ZYDIS_ISA_SET_VMFUNC,
|
||||
ZYDIS_ISA_SET_VPCLMULQDQ,
|
||||
ZYDIS_ISA_SET_VTX,
|
||||
ZYDIS_ISA_SET_WAITPKG,
|
||||
ZYDIS_ISA_SET_X87,
|
||||
ZYDIS_ISA_SET_XOP,
|
||||
ZYDIS_ISA_SET_XSAVE,
|
||||
ZYDIS_ISA_SET_XSAVEC,
|
||||
ZYDIS_ISA_SET_XSAVEOPT,
|
||||
ZYDIS_ISA_SET_XSAVES,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_ISA_SET_MAX_VALUE = ZYDIS_ISA_SET_XSAVES,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_ISA_SET_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_SET_MAX_VALUE)
|
||||
} ZydisISASet;
|
@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Defines the `ZydisInstructionCategory` enum.
|
||||
*/
|
||||
typedef enum ZydisInstructionCategory_
|
||||
{
|
||||
ZYDIS_CATEGORY_INVALID,
|
||||
ZYDIS_CATEGORY_ADOX_ADCX,
|
||||
ZYDIS_CATEGORY_AES,
|
||||
ZYDIS_CATEGORY_AMD3DNOW,
|
||||
ZYDIS_CATEGORY_AMX_TILE,
|
||||
ZYDIS_CATEGORY_AVX,
|
||||
ZYDIS_CATEGORY_AVX2,
|
||||
ZYDIS_CATEGORY_AVX2GATHER,
|
||||
ZYDIS_CATEGORY_AVX512,
|
||||
ZYDIS_CATEGORY_AVX512_4FMAPS,
|
||||
ZYDIS_CATEGORY_AVX512_4VNNIW,
|
||||
ZYDIS_CATEGORY_AVX512_BITALG,
|
||||
ZYDIS_CATEGORY_AVX512_VBMI,
|
||||
ZYDIS_CATEGORY_AVX512_VP2INTERSECT,
|
||||
ZYDIS_CATEGORY_BINARY,
|
||||
ZYDIS_CATEGORY_BITBYTE,
|
||||
ZYDIS_CATEGORY_BLEND,
|
||||
ZYDIS_CATEGORY_BMI1,
|
||||
ZYDIS_CATEGORY_BMI2,
|
||||
ZYDIS_CATEGORY_BROADCAST,
|
||||
ZYDIS_CATEGORY_CALL,
|
||||
ZYDIS_CATEGORY_CET,
|
||||
ZYDIS_CATEGORY_CLDEMOTE,
|
||||
ZYDIS_CATEGORY_CLFLUSHOPT,
|
||||
ZYDIS_CATEGORY_CLWB,
|
||||
ZYDIS_CATEGORY_CLZERO,
|
||||
ZYDIS_CATEGORY_CMOV,
|
||||
ZYDIS_CATEGORY_COMPRESS,
|
||||
ZYDIS_CATEGORY_COND_BR,
|
||||
ZYDIS_CATEGORY_CONFLICT,
|
||||
ZYDIS_CATEGORY_CONVERT,
|
||||
ZYDIS_CATEGORY_DATAXFER,
|
||||
ZYDIS_CATEGORY_DECIMAL,
|
||||
ZYDIS_CATEGORY_ENQCMD,
|
||||
ZYDIS_CATEGORY_EXPAND,
|
||||
ZYDIS_CATEGORY_FCMOV,
|
||||
ZYDIS_CATEGORY_FLAGOP,
|
||||
ZYDIS_CATEGORY_FMA4,
|
||||
ZYDIS_CATEGORY_GATHER,
|
||||
ZYDIS_CATEGORY_GFNI,
|
||||
ZYDIS_CATEGORY_IFMA,
|
||||
ZYDIS_CATEGORY_INTERRUPT,
|
||||
ZYDIS_CATEGORY_IO,
|
||||
ZYDIS_CATEGORY_IOSTRINGOP,
|
||||
ZYDIS_CATEGORY_KMASK,
|
||||
ZYDIS_CATEGORY_KNC,
|
||||
ZYDIS_CATEGORY_KNCMASK,
|
||||
ZYDIS_CATEGORY_KNCSCALAR,
|
||||
ZYDIS_CATEGORY_LOGICAL,
|
||||
ZYDIS_CATEGORY_LOGICAL_FP,
|
||||
ZYDIS_CATEGORY_LZCNT,
|
||||
ZYDIS_CATEGORY_MISC,
|
||||
ZYDIS_CATEGORY_MMX,
|
||||
ZYDIS_CATEGORY_MOVDIR,
|
||||
ZYDIS_CATEGORY_MPX,
|
||||
ZYDIS_CATEGORY_NOP,
|
||||
ZYDIS_CATEGORY_PADLOCK,
|
||||
ZYDIS_CATEGORY_PCLMULQDQ,
|
||||
ZYDIS_CATEGORY_PCONFIG,
|
||||
ZYDIS_CATEGORY_PKU,
|
||||
ZYDIS_CATEGORY_POP,
|
||||
ZYDIS_CATEGORY_PREFETCH,
|
||||
ZYDIS_CATEGORY_PREFETCHWT1,
|
||||
ZYDIS_CATEGORY_PT,
|
||||
ZYDIS_CATEGORY_PUSH,
|
||||
ZYDIS_CATEGORY_RDPID,
|
||||
ZYDIS_CATEGORY_RDPRU,
|
||||
ZYDIS_CATEGORY_RDRAND,
|
||||
ZYDIS_CATEGORY_RDSEED,
|
||||
ZYDIS_CATEGORY_RDWRFSGS,
|
||||
ZYDIS_CATEGORY_RET,
|
||||
ZYDIS_CATEGORY_ROTATE,
|
||||
ZYDIS_CATEGORY_SCATTER,
|
||||
ZYDIS_CATEGORY_SEGOP,
|
||||
ZYDIS_CATEGORY_SEMAPHORE,
|
||||
ZYDIS_CATEGORY_SERIALIZE,
|
||||
ZYDIS_CATEGORY_SETCC,
|
||||
ZYDIS_CATEGORY_SGX,
|
||||
ZYDIS_CATEGORY_SHA,
|
||||
ZYDIS_CATEGORY_SHIFT,
|
||||
ZYDIS_CATEGORY_SMAP,
|
||||
ZYDIS_CATEGORY_SSE,
|
||||
ZYDIS_CATEGORY_STRINGOP,
|
||||
ZYDIS_CATEGORY_STTNI,
|
||||
ZYDIS_CATEGORY_SYSCALL,
|
||||
ZYDIS_CATEGORY_SYSRET,
|
||||
ZYDIS_CATEGORY_SYSTEM,
|
||||
ZYDIS_CATEGORY_TBM,
|
||||
ZYDIS_CATEGORY_TSX_LDTRK,
|
||||
ZYDIS_CATEGORY_UFMA,
|
||||
ZYDIS_CATEGORY_UNCOND_BR,
|
||||
ZYDIS_CATEGORY_VAES,
|
||||
ZYDIS_CATEGORY_VBMI2,
|
||||
ZYDIS_CATEGORY_VFMA,
|
||||
ZYDIS_CATEGORY_VPCLMULQDQ,
|
||||
ZYDIS_CATEGORY_VTX,
|
||||
ZYDIS_CATEGORY_WAITPKG,
|
||||
ZYDIS_CATEGORY_WIDENOP,
|
||||
ZYDIS_CATEGORY_X87_ALU,
|
||||
ZYDIS_CATEGORY_XOP,
|
||||
ZYDIS_CATEGORY_XSAVE,
|
||||
ZYDIS_CATEGORY_XSAVEOPT,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_CATEGORY_MAX_VALUE = ZYDIS_CATEGORY_XSAVEOPT,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_CATEGORY_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_CATEGORY_MAX_VALUE)
|
||||
} ZydisInstructionCategory;
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,301 @@
|
||||
/**
|
||||
* Defines the `ZydisRegister` enum.
|
||||
*/
|
||||
typedef enum ZydisRegister_
|
||||
{
|
||||
ZYDIS_REGISTER_NONE,
|
||||
|
||||
// General purpose registers 8-bit
|
||||
ZYDIS_REGISTER_AL,
|
||||
ZYDIS_REGISTER_CL,
|
||||
ZYDIS_REGISTER_DL,
|
||||
ZYDIS_REGISTER_BL,
|
||||
ZYDIS_REGISTER_AH,
|
||||
ZYDIS_REGISTER_CH,
|
||||
ZYDIS_REGISTER_DH,
|
||||
ZYDIS_REGISTER_BH,
|
||||
ZYDIS_REGISTER_SPL,
|
||||
ZYDIS_REGISTER_BPL,
|
||||
ZYDIS_REGISTER_SIL,
|
||||
ZYDIS_REGISTER_DIL,
|
||||
ZYDIS_REGISTER_R8B,
|
||||
ZYDIS_REGISTER_R9B,
|
||||
ZYDIS_REGISTER_R10B,
|
||||
ZYDIS_REGISTER_R11B,
|
||||
ZYDIS_REGISTER_R12B,
|
||||
ZYDIS_REGISTER_R13B,
|
||||
ZYDIS_REGISTER_R14B,
|
||||
ZYDIS_REGISTER_R15B,
|
||||
// General purpose registers 16-bit
|
||||
ZYDIS_REGISTER_AX,
|
||||
ZYDIS_REGISTER_CX,
|
||||
ZYDIS_REGISTER_DX,
|
||||
ZYDIS_REGISTER_BX,
|
||||
ZYDIS_REGISTER_SP,
|
||||
ZYDIS_REGISTER_BP,
|
||||
ZYDIS_REGISTER_SI,
|
||||
ZYDIS_REGISTER_DI,
|
||||
ZYDIS_REGISTER_R8W,
|
||||
ZYDIS_REGISTER_R9W,
|
||||
ZYDIS_REGISTER_R10W,
|
||||
ZYDIS_REGISTER_R11W,
|
||||
ZYDIS_REGISTER_R12W,
|
||||
ZYDIS_REGISTER_R13W,
|
||||
ZYDIS_REGISTER_R14W,
|
||||
ZYDIS_REGISTER_R15W,
|
||||
// General purpose registers 32-bit
|
||||
ZYDIS_REGISTER_EAX,
|
||||
ZYDIS_REGISTER_ECX,
|
||||
ZYDIS_REGISTER_EDX,
|
||||
ZYDIS_REGISTER_EBX,
|
||||
ZYDIS_REGISTER_ESP,
|
||||
ZYDIS_REGISTER_EBP,
|
||||
ZYDIS_REGISTER_ESI,
|
||||
ZYDIS_REGISTER_EDI,
|
||||
ZYDIS_REGISTER_R8D,
|
||||
ZYDIS_REGISTER_R9D,
|
||||
ZYDIS_REGISTER_R10D,
|
||||
ZYDIS_REGISTER_R11D,
|
||||
ZYDIS_REGISTER_R12D,
|
||||
ZYDIS_REGISTER_R13D,
|
||||
ZYDIS_REGISTER_R14D,
|
||||
ZYDIS_REGISTER_R15D,
|
||||
// General purpose registers 64-bit
|
||||
ZYDIS_REGISTER_RAX,
|
||||
ZYDIS_REGISTER_RCX,
|
||||
ZYDIS_REGISTER_RDX,
|
||||
ZYDIS_REGISTER_RBX,
|
||||
ZYDIS_REGISTER_RSP,
|
||||
ZYDIS_REGISTER_RBP,
|
||||
ZYDIS_REGISTER_RSI,
|
||||
ZYDIS_REGISTER_RDI,
|
||||
ZYDIS_REGISTER_R8,
|
||||
ZYDIS_REGISTER_R9,
|
||||
ZYDIS_REGISTER_R10,
|
||||
ZYDIS_REGISTER_R11,
|
||||
ZYDIS_REGISTER_R12,
|
||||
ZYDIS_REGISTER_R13,
|
||||
ZYDIS_REGISTER_R14,
|
||||
ZYDIS_REGISTER_R15,
|
||||
// Floating point legacy registers
|
||||
ZYDIS_REGISTER_ST0,
|
||||
ZYDIS_REGISTER_ST1,
|
||||
ZYDIS_REGISTER_ST2,
|
||||
ZYDIS_REGISTER_ST3,
|
||||
ZYDIS_REGISTER_ST4,
|
||||
ZYDIS_REGISTER_ST5,
|
||||
ZYDIS_REGISTER_ST6,
|
||||
ZYDIS_REGISTER_ST7,
|
||||
ZYDIS_REGISTER_X87CONTROL,
|
||||
ZYDIS_REGISTER_X87STATUS,
|
||||
ZYDIS_REGISTER_X87TAG,
|
||||
// Floating point multimedia registers
|
||||
ZYDIS_REGISTER_MM0,
|
||||
ZYDIS_REGISTER_MM1,
|
||||
ZYDIS_REGISTER_MM2,
|
||||
ZYDIS_REGISTER_MM3,
|
||||
ZYDIS_REGISTER_MM4,
|
||||
ZYDIS_REGISTER_MM5,
|
||||
ZYDIS_REGISTER_MM6,
|
||||
ZYDIS_REGISTER_MM7,
|
||||
// Floating point vector registers 128-bit
|
||||
ZYDIS_REGISTER_XMM0,
|
||||
ZYDIS_REGISTER_XMM1,
|
||||
ZYDIS_REGISTER_XMM2,
|
||||
ZYDIS_REGISTER_XMM3,
|
||||
ZYDIS_REGISTER_XMM4,
|
||||
ZYDIS_REGISTER_XMM5,
|
||||
ZYDIS_REGISTER_XMM6,
|
||||
ZYDIS_REGISTER_XMM7,
|
||||
ZYDIS_REGISTER_XMM8,
|
||||
ZYDIS_REGISTER_XMM9,
|
||||
ZYDIS_REGISTER_XMM10,
|
||||
ZYDIS_REGISTER_XMM11,
|
||||
ZYDIS_REGISTER_XMM12,
|
||||
ZYDIS_REGISTER_XMM13,
|
||||
ZYDIS_REGISTER_XMM14,
|
||||
ZYDIS_REGISTER_XMM15,
|
||||
ZYDIS_REGISTER_XMM16,
|
||||
ZYDIS_REGISTER_XMM17,
|
||||
ZYDIS_REGISTER_XMM18,
|
||||
ZYDIS_REGISTER_XMM19,
|
||||
ZYDIS_REGISTER_XMM20,
|
||||
ZYDIS_REGISTER_XMM21,
|
||||
ZYDIS_REGISTER_XMM22,
|
||||
ZYDIS_REGISTER_XMM23,
|
||||
ZYDIS_REGISTER_XMM24,
|
||||
ZYDIS_REGISTER_XMM25,
|
||||
ZYDIS_REGISTER_XMM26,
|
||||
ZYDIS_REGISTER_XMM27,
|
||||
ZYDIS_REGISTER_XMM28,
|
||||
ZYDIS_REGISTER_XMM29,
|
||||
ZYDIS_REGISTER_XMM30,
|
||||
ZYDIS_REGISTER_XMM31,
|
||||
// Floating point vector registers 256-bit
|
||||
ZYDIS_REGISTER_YMM0,
|
||||
ZYDIS_REGISTER_YMM1,
|
||||
ZYDIS_REGISTER_YMM2,
|
||||
ZYDIS_REGISTER_YMM3,
|
||||
ZYDIS_REGISTER_YMM4,
|
||||
ZYDIS_REGISTER_YMM5,
|
||||
ZYDIS_REGISTER_YMM6,
|
||||
ZYDIS_REGISTER_YMM7,
|
||||
ZYDIS_REGISTER_YMM8,
|
||||
ZYDIS_REGISTER_YMM9,
|
||||
ZYDIS_REGISTER_YMM10,
|
||||
ZYDIS_REGISTER_YMM11,
|
||||
ZYDIS_REGISTER_YMM12,
|
||||
ZYDIS_REGISTER_YMM13,
|
||||
ZYDIS_REGISTER_YMM14,
|
||||
ZYDIS_REGISTER_YMM15,
|
||||
ZYDIS_REGISTER_YMM16,
|
||||
ZYDIS_REGISTER_YMM17,
|
||||
ZYDIS_REGISTER_YMM18,
|
||||
ZYDIS_REGISTER_YMM19,
|
||||
ZYDIS_REGISTER_YMM20,
|
||||
ZYDIS_REGISTER_YMM21,
|
||||
ZYDIS_REGISTER_YMM22,
|
||||
ZYDIS_REGISTER_YMM23,
|
||||
ZYDIS_REGISTER_YMM24,
|
||||
ZYDIS_REGISTER_YMM25,
|
||||
ZYDIS_REGISTER_YMM26,
|
||||
ZYDIS_REGISTER_YMM27,
|
||||
ZYDIS_REGISTER_YMM28,
|
||||
ZYDIS_REGISTER_YMM29,
|
||||
ZYDIS_REGISTER_YMM30,
|
||||
ZYDIS_REGISTER_YMM31,
|
||||
// Floating point vector registers 512-bit
|
||||
ZYDIS_REGISTER_ZMM0,
|
||||
ZYDIS_REGISTER_ZMM1,
|
||||
ZYDIS_REGISTER_ZMM2,
|
||||
ZYDIS_REGISTER_ZMM3,
|
||||
ZYDIS_REGISTER_ZMM4,
|
||||
ZYDIS_REGISTER_ZMM5,
|
||||
ZYDIS_REGISTER_ZMM6,
|
||||
ZYDIS_REGISTER_ZMM7,
|
||||
ZYDIS_REGISTER_ZMM8,
|
||||
ZYDIS_REGISTER_ZMM9,
|
||||
ZYDIS_REGISTER_ZMM10,
|
||||
ZYDIS_REGISTER_ZMM11,
|
||||
ZYDIS_REGISTER_ZMM12,
|
||||
ZYDIS_REGISTER_ZMM13,
|
||||
ZYDIS_REGISTER_ZMM14,
|
||||
ZYDIS_REGISTER_ZMM15,
|
||||
ZYDIS_REGISTER_ZMM16,
|
||||
ZYDIS_REGISTER_ZMM17,
|
||||
ZYDIS_REGISTER_ZMM18,
|
||||
ZYDIS_REGISTER_ZMM19,
|
||||
ZYDIS_REGISTER_ZMM20,
|
||||
ZYDIS_REGISTER_ZMM21,
|
||||
ZYDIS_REGISTER_ZMM22,
|
||||
ZYDIS_REGISTER_ZMM23,
|
||||
ZYDIS_REGISTER_ZMM24,
|
||||
ZYDIS_REGISTER_ZMM25,
|
||||
ZYDIS_REGISTER_ZMM26,
|
||||
ZYDIS_REGISTER_ZMM27,
|
||||
ZYDIS_REGISTER_ZMM28,
|
||||
ZYDIS_REGISTER_ZMM29,
|
||||
ZYDIS_REGISTER_ZMM30,
|
||||
ZYDIS_REGISTER_ZMM31,
|
||||
// Matrix registers
|
||||
ZYDIS_REGISTER_TMM0,
|
||||
ZYDIS_REGISTER_TMM1,
|
||||
ZYDIS_REGISTER_TMM2,
|
||||
ZYDIS_REGISTER_TMM3,
|
||||
ZYDIS_REGISTER_TMM4,
|
||||
ZYDIS_REGISTER_TMM5,
|
||||
ZYDIS_REGISTER_TMM6,
|
||||
ZYDIS_REGISTER_TMM7,
|
||||
// Flags registers
|
||||
ZYDIS_REGISTER_FLAGS,
|
||||
ZYDIS_REGISTER_EFLAGS,
|
||||
ZYDIS_REGISTER_RFLAGS,
|
||||
// Instruction-pointer registers
|
||||
ZYDIS_REGISTER_IP,
|
||||
ZYDIS_REGISTER_EIP,
|
||||
ZYDIS_REGISTER_RIP,
|
||||
// Segment registers
|
||||
ZYDIS_REGISTER_ES,
|
||||
ZYDIS_REGISTER_CS,
|
||||
ZYDIS_REGISTER_SS,
|
||||
ZYDIS_REGISTER_DS,
|
||||
ZYDIS_REGISTER_FS,
|
||||
ZYDIS_REGISTER_GS,
|
||||
// Table registers
|
||||
ZYDIS_REGISTER_GDTR,
|
||||
ZYDIS_REGISTER_LDTR,
|
||||
ZYDIS_REGISTER_IDTR,
|
||||
ZYDIS_REGISTER_TR,
|
||||
// Test registers
|
||||
ZYDIS_REGISTER_TR0,
|
||||
ZYDIS_REGISTER_TR1,
|
||||
ZYDIS_REGISTER_TR2,
|
||||
ZYDIS_REGISTER_TR3,
|
||||
ZYDIS_REGISTER_TR4,
|
||||
ZYDIS_REGISTER_TR5,
|
||||
ZYDIS_REGISTER_TR6,
|
||||
ZYDIS_REGISTER_TR7,
|
||||
// Control registers
|
||||
ZYDIS_REGISTER_CR0,
|
||||
ZYDIS_REGISTER_CR1,
|
||||
ZYDIS_REGISTER_CR2,
|
||||
ZYDIS_REGISTER_CR3,
|
||||
ZYDIS_REGISTER_CR4,
|
||||
ZYDIS_REGISTER_CR5,
|
||||
ZYDIS_REGISTER_CR6,
|
||||
ZYDIS_REGISTER_CR7,
|
||||
ZYDIS_REGISTER_CR8,
|
||||
ZYDIS_REGISTER_CR9,
|
||||
ZYDIS_REGISTER_CR10,
|
||||
ZYDIS_REGISTER_CR11,
|
||||
ZYDIS_REGISTER_CR12,
|
||||
ZYDIS_REGISTER_CR13,
|
||||
ZYDIS_REGISTER_CR14,
|
||||
ZYDIS_REGISTER_CR15,
|
||||
// Debug registers
|
||||
ZYDIS_REGISTER_DR0,
|
||||
ZYDIS_REGISTER_DR1,
|
||||
ZYDIS_REGISTER_DR2,
|
||||
ZYDIS_REGISTER_DR3,
|
||||
ZYDIS_REGISTER_DR4,
|
||||
ZYDIS_REGISTER_DR5,
|
||||
ZYDIS_REGISTER_DR6,
|
||||
ZYDIS_REGISTER_DR7,
|
||||
ZYDIS_REGISTER_DR8,
|
||||
ZYDIS_REGISTER_DR9,
|
||||
ZYDIS_REGISTER_DR10,
|
||||
ZYDIS_REGISTER_DR11,
|
||||
ZYDIS_REGISTER_DR12,
|
||||
ZYDIS_REGISTER_DR13,
|
||||
ZYDIS_REGISTER_DR14,
|
||||
ZYDIS_REGISTER_DR15,
|
||||
// Mask registers
|
||||
ZYDIS_REGISTER_K0,
|
||||
ZYDIS_REGISTER_K1,
|
||||
ZYDIS_REGISTER_K2,
|
||||
ZYDIS_REGISTER_K3,
|
||||
ZYDIS_REGISTER_K4,
|
||||
ZYDIS_REGISTER_K5,
|
||||
ZYDIS_REGISTER_K6,
|
||||
ZYDIS_REGISTER_K7,
|
||||
// Bound registers
|
||||
ZYDIS_REGISTER_BND0,
|
||||
ZYDIS_REGISTER_BND1,
|
||||
ZYDIS_REGISTER_BND2,
|
||||
ZYDIS_REGISTER_BND3,
|
||||
ZYDIS_REGISTER_BNDCFG,
|
||||
ZYDIS_REGISTER_BNDSTATUS,
|
||||
// Uncategorized
|
||||
ZYDIS_REGISTER_MXCSR,
|
||||
ZYDIS_REGISTER_PKRU,
|
||||
ZYDIS_REGISTER_XCR0,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_REGISTER_MAX_VALUE = ZYDIS_REGISTER_XCR0,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_REGISTER_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGISTER_MAX_VALUE)
|
||||
} ZydisRegister;
|
@ -0,0 +1,331 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#ifndef ZYDIS_INTERNAL_DECODERDATA_H
|
||||
#define ZYDIS_INTERNAL_DECODERDATA_H
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zydis/DecoderTypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
// MSVC does not like types other than (un-)signed int for bit-fields
|
||||
#ifdef ZYAN_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4214)
|
||||
#endif
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Decoder tree */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisDecoderTreeNodeType` data-type.
|
||||
*/
|
||||
typedef ZyanU8 ZydisDecoderTreeNodeType;
|
||||
|
||||
/**
|
||||
* Values that represent zydis decoder tree node types.
|
||||
*/
|
||||
enum ZydisDecoderTreeNodeTypes
|
||||
{
|
||||
ZYDIS_NODETYPE_INVALID = 0x00,
|
||||
/**
|
||||
* Reference to an instruction-definition.
|
||||
*/
|
||||
ZYDIS_NODETYPE_DEFINITION_MASK = 0x80,
|
||||
/**
|
||||
* Reference to an XOP-map filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_XOP = 0x01,
|
||||
/**
|
||||
* Reference to an VEX-map filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_VEX = 0x02,
|
||||
/**
|
||||
* Reference to an EVEX/MVEX-map filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_EMVEX = 0x03,
|
||||
/**
|
||||
* Reference to an opcode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_OPCODE = 0x04,
|
||||
/**
|
||||
* Reference to an instruction-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE = 0x05,
|
||||
/**
|
||||
* Reference to an compacted instruction-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_COMPACT = 0x06,
|
||||
/**
|
||||
* Reference to a ModRM.mod filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODRM_MOD = 0x07,
|
||||
/**
|
||||
* Reference to a compacted ModRM.mod filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT = 0x08,
|
||||
/**
|
||||
* Reference to a ModRM.reg filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODRM_REG = 0x09,
|
||||
/**
|
||||
* Reference to a ModRM.rm filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODRM_RM = 0x0A,
|
||||
/**
|
||||
* Reference to a PrefixGroup1 filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_PREFIX_GROUP1 = 0x0B,
|
||||
/**
|
||||
* Reference to a mandatory-prefix filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX = 0x0C,
|
||||
/**
|
||||
* Reference to an operand-size filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_OPERAND_SIZE = 0x0D,
|
||||
/**
|
||||
* Reference to an address-size filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_ADDRESS_SIZE = 0x0E,
|
||||
/**
|
||||
* Reference to a vector-length filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_VECTOR_LENGTH = 0x0F,
|
||||
/**
|
||||
* Reference to an REX/VEX/EVEX.W filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_REX_W = 0x10,
|
||||
/**
|
||||
* Reference to an REX/VEX/EVEX.B filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_REX_B = 0x11,
|
||||
/**
|
||||
* Reference to an EVEX.b filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_EVEX_B = 0x12,
|
||||
/**
|
||||
* Reference to an MVEX.E filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MVEX_E = 0x13,
|
||||
/**
|
||||
* Reference to a AMD-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_AMD = 0x14,
|
||||
/**
|
||||
* Reference to a KNC-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_KNC = 0x15,
|
||||
/**
|
||||
* Reference to a MPX-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_MPX = 0x16,
|
||||
/**
|
||||
* Reference to a CET-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_CET = 0x17,
|
||||
/**
|
||||
* Reference to a LZCNT-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_LZCNT = 0x18,
|
||||
/**
|
||||
* Reference to a TZCNT-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_TZCNT = 0x19,
|
||||
/**
|
||||
* Reference to a WBNOINVD-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_WBNOINVD = 0x1A,
|
||||
/**
|
||||
* Reference to a CLDEMOTE-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_CLDEMOTE = 0x1B
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisDecoderTreeNodeValue` data-type.
|
||||
*/
|
||||
typedef ZyanU16 ZydisDecoderTreeNodeValue;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisDecoderTreeNode` struct.
|
||||
*/
|
||||
typedef struct ZydisDecoderTreeNode_
|
||||
{
|
||||
ZydisDecoderTreeNodeType type;
|
||||
ZydisDecoderTreeNodeValue value;
|
||||
} ZydisDecoderTreeNode;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef ZYAN_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Physical instruction encoding info */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionEncodingFlags` data-type.
|
||||
*/
|
||||
typedef ZyanU8 ZydisInstructionEncodingFlags;
|
||||
|
||||
/**
|
||||
* The instruction has an optional modrm byte.
|
||||
*/
|
||||
#define ZYDIS_INSTR_ENC_FLAG_HAS_MODRM 0x01
|
||||
|
||||
/**
|
||||
* The instruction has an optional displacement value.
|
||||
*/
|
||||
#define ZYDIS_INSTR_ENC_FLAG_HAS_DISP 0x02
|
||||
|
||||
/**
|
||||
* The instruction has an optional immediate value.
|
||||
*/
|
||||
#define ZYDIS_INSTR_ENC_FLAG_HAS_IMM0 0x04
|
||||
|
||||
/**
|
||||
* The instruction has a second optional immediate value.
|
||||
*/
|
||||
#define ZYDIS_INSTR_ENC_FLAG_HAS_IMM1 0x08
|
||||
|
||||
/**
|
||||
* The instruction ignores the value of `modrm.mod` and always assumes `modrm.mod == 3`
|
||||
* ("reg, reg" - form).
|
||||
*
|
||||
* Instructions with this flag can't have a SIB byte or a displacement value.
|
||||
*/
|
||||
#define ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM 0x10
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionEncodingInfo` struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionEncodingInfo_
|
||||
{
|
||||
/**
|
||||
* Contains flags with information about the physical instruction-encoding.
|
||||
*/
|
||||
ZydisInstructionEncodingFlags flags;
|
||||
/**
|
||||
* Displacement info.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* The size of the displacement value.
|
||||
*/
|
||||
ZyanU8 size[3];
|
||||
} disp;
|
||||
/**
|
||||
* Immediate info.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* The size of the immediate value.
|
||||
*/
|
||||
ZyanU8 size[3];
|
||||
/**
|
||||
* Signals, if the value is signed.
|
||||
*/
|
||||
ZyanBool is_signed;
|
||||
/**
|
||||
* Signals, if the value is a relative offset.
|
||||
*/
|
||||
ZyanBool is_relative;
|
||||
} imm[2];
|
||||
} ZydisInstructionEncodingInfo;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Decoder tree */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
extern const ZydisDecoderTreeNode zydis_decoder_tree_root;
|
||||
|
||||
/**
|
||||
* Returns the root node of the instruction tree.
|
||||
*
|
||||
* @return The root node of the instruction tree.
|
||||
*/
|
||||
ZYAN_INLINE const ZydisDecoderTreeNode* ZydisDecoderTreeGetRootNode(void)
|
||||
{
|
||||
return &zydis_decoder_tree_root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the child node of `parent` specified by `index`.
|
||||
*
|
||||
* @param parent The parent node.
|
||||
* @param index The index of the child node to retrieve.
|
||||
*
|
||||
* @return The specified child node.
|
||||
*/
|
||||
ZYDIS_NO_EXPORT const ZydisDecoderTreeNode* ZydisDecoderTreeGetChildNode(
|
||||
const ZydisDecoderTreeNode* parent, ZyanU16 index);
|
||||
|
||||
/**
|
||||
* Returns information about optional instruction parts (like modrm, displacement or
|
||||
* immediates) for the instruction that is linked to the given `node`.
|
||||
*
|
||||
* @param node The instruction definition node.
|
||||
* @param info A pointer to the `ZydisInstructionParts` struct.
|
||||
*/
|
||||
ZYDIS_NO_EXPORT void ZydisGetInstructionEncodingInfo(const ZydisDecoderTreeNode* node,
|
||||
const ZydisInstructionEncodingInfo** info);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_INTERNAL_DECODERDATA_H */
|
@ -0,0 +1,178 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements the `AT&T` style instruction-formatter.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_FORMATTER_ATT_H
|
||||
#define ZYDIS_FORMATTER_ATT_H
|
||||
|
||||
#include <Zydis/Formatter.h>
|
||||
#include <Zydis/Internal/FormatterBase.h>
|
||||
#include <Zydis/Internal/String.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Formatter functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Instruction */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Operands */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZydisFormatterATTFormatOperandMEM(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Elemental tokens */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZydisFormatterATTPrintMnemonic(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterATTPrintRegister(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg);
|
||||
|
||||
ZyanStatus ZydisFormatterATTPrintDISP(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterATTPrintIMM(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Fomatter presets */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* AT&T */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The default formatter configuration for `AT&T` style disassembly.
|
||||
*/
|
||||
static const ZydisFormatter FORMATTER_ATT =
|
||||
{
|
||||
/* style */ ZYDIS_FORMATTER_STYLE_ATT,
|
||||
/* force_memory_size */ ZYAN_FALSE,
|
||||
/* force_memory_seg */ ZYAN_FALSE,
|
||||
/* force_relative_branches */ ZYAN_FALSE,
|
||||
/* force_relative_riprel */ ZYAN_FALSE,
|
||||
/* print_branch_size */ ZYAN_FALSE,
|
||||
/* detailed_prefixes */ ZYAN_FALSE,
|
||||
/* addr_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||
/* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||
/* addr_padding_absolute */ ZYDIS_PADDING_AUTO,
|
||||
/* addr_padding_relative */ 2,
|
||||
/* disp_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||
/* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||
/* disp_padding */ 2,
|
||||
/* imm_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||
/* imm_signedness */ ZYDIS_SIGNEDNESS_AUTO,
|
||||
/* imm_padding */ 2,
|
||||
/* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_registers */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* hex_uppercase */ ZYAN_TRUE,
|
||||
/* number_format */
|
||||
{
|
||||
// ZYDIS_NUMERIC_BASE_DEC
|
||||
{
|
||||
// Prefix
|
||||
{
|
||||
/* string */ ZYAN_NULL,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
},
|
||||
// Suffix
|
||||
{
|
||||
/* string */ ZYAN_NULL,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
}
|
||||
},
|
||||
// ZYDIS_NUMERIC_BASE_HEX
|
||||
{
|
||||
// Prefix
|
||||
{
|
||||
/* string */ &FORMATTER_ATT.number_format[
|
||||
ZYDIS_NUMERIC_BASE_HEX][0].string_data,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW("0x"),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
},
|
||||
// Suffix
|
||||
{
|
||||
/* string */ ZYAN_NULL,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
}
|
||||
}
|
||||
},
|
||||
/* func_pre_instruction */ ZYAN_NULL,
|
||||
/* func_post_instruction */ ZYAN_NULL,
|
||||
/* func_format_instruction */ &ZydisFormatterATTFormatInstruction,
|
||||
/* func_pre_operand */ ZYAN_NULL,
|
||||
/* func_post_operand */ ZYAN_NULL,
|
||||
/* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG,
|
||||
/* func_format_operand_mem */ &ZydisFormatterATTFormatOperandMEM,
|
||||
/* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR,
|
||||
/* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM,
|
||||
/* func_print_mnemonic */ &ZydisFormatterATTPrintMnemonic,
|
||||
/* func_print_register */ &ZydisFormatterATTPrintRegister,
|
||||
/* func_print_address_abs */ &ZydisFormatterBasePrintAddressABS,
|
||||
/* func_print_address_rel */ &ZydisFormatterBasePrintAddressREL,
|
||||
/* func_print_disp */ &ZydisFormatterATTPrintDISP,
|
||||
/* func_print_imm */ &ZydisFormatterATTPrintIMM,
|
||||
/* func_print_typecast */ ZYAN_NULL,
|
||||
/* func_print_segment */ &ZydisFormatterBasePrintSegment,
|
||||
/* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes,
|
||||
/* func_print_decorator */ &ZydisFormatterBasePrintDecorator
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ZYDIS_FORMATTER_ATT_H
|
@ -0,0 +1,318 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides formatter functions that are shared between the different formatters.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_FORMATTER_BASE_H
|
||||
#define ZYDIS_FORMATTER_BASE_H
|
||||
|
||||
#include <Zydis/Formatter.h>
|
||||
#include <Zydis/Internal/String.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* String */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Appends an unsigned numeric value to the given string.
|
||||
*
|
||||
* @param formatter A pointer to the `ZydisFormatter` instance.
|
||||
* @param base The numeric base.
|
||||
* @param str The destination string.
|
||||
* @param value The value.
|
||||
* @param padding_length The padding length.
|
||||
*/
|
||||
#define ZYDIS_STRING_APPEND_NUM_U(formatter, base, str, value, padding_length) \
|
||||
switch (base) \
|
||||
{ \
|
||||
case ZYDIS_NUMERIC_BASE_DEC: \
|
||||
ZYAN_CHECK(ZydisStringAppendDecU(str, value, padding_length, \
|
||||
(formatter)->number_format[base][0].string, \
|
||||
(formatter)->number_format[base][1].string)); \
|
||||
break; \
|
||||
case ZYDIS_NUMERIC_BASE_HEX: \
|
||||
ZYAN_CHECK(ZydisStringAppendHexU(str, value, padding_length, \
|
||||
(formatter)->hex_uppercase, \
|
||||
(formatter)->number_format[base][0].string, \
|
||||
(formatter)->number_format[base][1].string)); \
|
||||
break; \
|
||||
default: \
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a signed numeric value to the given string.
|
||||
*
|
||||
* @param formatter A pointer to the `ZydisFormatter` instance.
|
||||
* @param base The numeric base.
|
||||
* @param str The destination string.
|
||||
* @param value The value.
|
||||
* @param padding_length The padding length.
|
||||
* @param force_sign Forces printing of the '+' sign for positive numbers.
|
||||
*/
|
||||
#define ZYDIS_STRING_APPEND_NUM_S(formatter, base, str, value, padding_length, force_sign) \
|
||||
switch (base) \
|
||||
{ \
|
||||
case ZYDIS_NUMERIC_BASE_DEC: \
|
||||
ZYAN_CHECK(ZydisStringAppendDecS(str, value, padding_length, force_sign, \
|
||||
(formatter)->number_format[base][0].string, \
|
||||
(formatter)->number_format[base][1].string)); \
|
||||
break; \
|
||||
case ZYDIS_NUMERIC_BASE_HEX: \
|
||||
ZYAN_CHECK(ZydisStringAppendHexS(str, value, padding_length, \
|
||||
(formatter)->hex_uppercase, force_sign, \
|
||||
(formatter)->number_format[base][0].string, \
|
||||
(formatter)->number_format[base][1].string)); \
|
||||
break; \
|
||||
default: \
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT; \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Buffer */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Invokes the `ZydisFormatterBufferAppend` routine, if tokenization is enabled for the
|
||||
* current pass.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param type The token type.
|
||||
*
|
||||
* Using this macro instead of direct calls to `ZydisFormatterBufferAppend` greatly improves the
|
||||
* performance for non-tokenizing passes.
|
||||
*/
|
||||
#define ZYDIS_BUFFER_APPEND_TOKEN(buffer, type) \
|
||||
if ((buffer)->is_token_list) \
|
||||
{ \
|
||||
ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, type)); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a snapshot of the buffer-state.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param state Receives a snapshot of the buffer-state.
|
||||
*
|
||||
* Using this macro instead of direct calls to `ZydisFormatterBufferRemember` improves the
|
||||
* performance for non-tokenizing passes.
|
||||
*/
|
||||
#define ZYDIS_BUFFER_REMEMBER(buffer, state) \
|
||||
if ((buffer)->is_token_list) \
|
||||
{ \
|
||||
(state) = (ZyanUPointer)(buffer)->string.vector.data; \
|
||||
} else \
|
||||
{ \
|
||||
(state) = (ZyanUPointer)(buffer)->string.vector.size; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a string (`STR_`-prefix) or a predefined token-list (`TOK_`-prefix).
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param name The base name (without prefix) of the string- or token.
|
||||
*/
|
||||
#define ZYDIS_BUFFER_APPEND(buffer, name) \
|
||||
if ((buffer)->is_token_list) \
|
||||
{ \
|
||||
ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \
|
||||
} else \
|
||||
{ \
|
||||
ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_ ## name)); \
|
||||
}
|
||||
|
||||
// TODO: Implement `letter_case` for predefined tokens
|
||||
|
||||
/**
|
||||
* Appends a string (`STR_`-prefix) or a predefined token-list (`TOK_`-prefix).
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param name The base name (without prefix) of the string- or token.
|
||||
* @param letter-case The desired letter-case.
|
||||
*/
|
||||
#define ZYDIS_BUFFER_APPEND_CASE(buffer, name, letter_case) \
|
||||
if ((buffer)->is_token_list) \
|
||||
{ \
|
||||
ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \
|
||||
} else \
|
||||
{ \
|
||||
ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_ ## name, letter_case)); \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Helper functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Buffer */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
// MSVC does not like the C99 flexible-array extension
|
||||
#ifdef ZYAN_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4200)
|
||||
#endif
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct ZydisPredefinedToken_
|
||||
{
|
||||
ZyanU8 size;
|
||||
ZyanU8 next;
|
||||
ZyanU8 data[];
|
||||
} ZydisPredefinedToken;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef ZYAN_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Appends a predefined token-list to the `buffer`.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param data A pointer to the `ZydisPredefinedToken` struct.
|
||||
*
|
||||
* @return A zycore status code.
|
||||
*
|
||||
* This function is internally used to improve performance while adding static strings or multiple
|
||||
* tokens at once.
|
||||
*/
|
||||
ZYAN_INLINE ZyanStatus ZydisFormatterBufferAppendPredefined(ZydisFormatterBuffer* buffer,
|
||||
const ZydisPredefinedToken* data)
|
||||
{
|
||||
ZYAN_ASSERT(buffer);
|
||||
ZYAN_ASSERT(data);
|
||||
|
||||
const ZyanUSize len = buffer->string.vector.size;
|
||||
ZYAN_ASSERT((len > 0) && (len < 256));
|
||||
if (buffer->capacity <= len + data->size)
|
||||
{
|
||||
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
ZydisFormatterToken* const last = (ZydisFormatterToken*)buffer->string.vector.data - 1;
|
||||
last->next = (ZyanU8)len;
|
||||
|
||||
ZYAN_MEMCPY((ZyanU8*)buffer->string.vector.data + len, &data->data[0], data->size);
|
||||
|
||||
const ZyanUSize delta = len + data->next;
|
||||
buffer->capacity -= delta;
|
||||
buffer->string.vector.data = (ZyanU8*)buffer->string.vector.data + delta;
|
||||
buffer->string.vector.size = data->size - data->next;
|
||||
buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the size to be used as explicit size suffix (`AT&T`) or explicit typecast
|
||||
* (`INTEL`), if required.
|
||||
*
|
||||
* @param formatter A pointer to the `ZydisFormatter` instance.
|
||||
* @param context A pointer to the `ZydisFormatterContext` struct.
|
||||
* @param memop_id The operand-id of the instructions first memory operand.
|
||||
*
|
||||
* @return Returns the explicit size, if required, or `0`, if not needed.
|
||||
*
|
||||
* This function always returns a size different to `0`, if the `ZYDIS_FORMATTER_PROP_FORCE_SIZE`
|
||||
* is set to `ZYAN_TRUE`.
|
||||
*/
|
||||
ZyanU32 ZydisFormatterHelperGetExplicitSize(const ZydisFormatter* formatter,
|
||||
ZydisFormatterContext* context, ZyanU8 memop_id);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Formatter functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Operands */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZydisFormatterBaseFormatOperandREG(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterBaseFormatOperandPTR(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterBaseFormatOperandIMM(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Elemental tokens */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZydisFormatterBasePrintAddressABS(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterBasePrintAddressREL(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterBasePrintIMM(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Optional tokens */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZydisFormatterBasePrintSegment(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterBasePrintPrefixes(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterBasePrintDecorator(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ZYDIS_FORMATTER_BASE_H
|
@ -0,0 +1,267 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements the `INTEL` style instruction-formatter.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_FORMATTER_INTEL_H
|
||||
#define ZYDIS_FORMATTER_INTEL_H
|
||||
|
||||
#include <Zydis/Formatter.h>
|
||||
#include <Zydis/Internal/FormatterBase.h>
|
||||
#include <Zydis/Internal/String.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Formatter functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Intel */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterIntelPrintMnemonic(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterIntelPrintRegister(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg);
|
||||
|
||||
ZyanStatus ZydisFormatterIntelPrintDISP(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterIntelPrintTypecast(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* MASM */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Fomatter presets */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* INTEL */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The default formatter configuration for `INTEL` style disassembly.
|
||||
*/
|
||||
static const ZydisFormatter FORMATTER_INTEL =
|
||||
{
|
||||
/* style */ ZYDIS_FORMATTER_STYLE_INTEL,
|
||||
/* force_memory_size */ ZYAN_FALSE,
|
||||
/* force_memory_seg */ ZYAN_FALSE,
|
||||
/* force_relative_branches */ ZYAN_FALSE,
|
||||
/* force_relative_riprel */ ZYAN_FALSE,
|
||||
/* print_branch_size */ ZYAN_FALSE,
|
||||
/* detailed_prefixes */ ZYAN_FALSE,
|
||||
/* addr_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||
/* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||
/* addr_padding_absolute */ ZYDIS_PADDING_AUTO,
|
||||
/* addr_padding_relative */ 2,
|
||||
/* disp_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||
/* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||
/* disp_padding */ 2,
|
||||
/* imm_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||
/* imm_signedness */ ZYDIS_SIGNEDNESS_UNSIGNED,
|
||||
/* imm_padding */ 2,
|
||||
/* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_registers */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* hex_uppercase */ ZYAN_TRUE,
|
||||
/* number_format */
|
||||
{
|
||||
// ZYDIS_NUMERIC_BASE_DEC
|
||||
{
|
||||
// Prefix
|
||||
{
|
||||
/* string */ ZYAN_NULL,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
},
|
||||
// Suffix
|
||||
{
|
||||
/* string */ ZYAN_NULL,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
}
|
||||
},
|
||||
// ZYDIS_NUMERIC_BASE_HEX
|
||||
{
|
||||
// Prefix
|
||||
{
|
||||
/* string */ &FORMATTER_INTEL.number_format[
|
||||
ZYDIS_NUMERIC_BASE_HEX][0].string_data,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW("0x"),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
},
|
||||
// Suffix
|
||||
{
|
||||
/* string */ ZYAN_NULL,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
}
|
||||
}
|
||||
},
|
||||
/* func_pre_instruction */ ZYAN_NULL,
|
||||
/* func_post_instruction */ ZYAN_NULL,
|
||||
/* func_format_instruction */ &ZydisFormatterIntelFormatInstruction,
|
||||
/* func_pre_operand */ ZYAN_NULL,
|
||||
/* func_post_operand */ ZYAN_NULL,
|
||||
/* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG,
|
||||
/* func_format_operand_mem */ &ZydisFormatterIntelFormatOperandMEM,
|
||||
/* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR,
|
||||
/* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM,
|
||||
/* func_print_mnemonic */ &ZydisFormatterIntelPrintMnemonic,
|
||||
/* func_print_register */ &ZydisFormatterIntelPrintRegister,
|
||||
/* func_print_address_abs */ &ZydisFormatterBasePrintAddressABS,
|
||||
/* func_print_address_rel */ &ZydisFormatterBasePrintAddressREL,
|
||||
/* func_print_disp */ &ZydisFormatterIntelPrintDISP,
|
||||
/* func_print_imm */ &ZydisFormatterBasePrintIMM,
|
||||
/* func_print_typecast */ &ZydisFormatterIntelPrintTypecast,
|
||||
/* func_print_segment */ &ZydisFormatterBasePrintSegment,
|
||||
/* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes,
|
||||
/* func_print_decorator */ &ZydisFormatterBasePrintDecorator
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* MASM */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The default formatter configuration for `MASM` style disassembly.
|
||||
*/
|
||||
static const ZydisFormatter FORMATTER_INTEL_MASM =
|
||||
{
|
||||
/* style */ ZYDIS_FORMATTER_STYLE_INTEL_MASM,
|
||||
/* force_memory_size */ ZYAN_TRUE,
|
||||
/* force_memory_seg */ ZYAN_FALSE,
|
||||
/* force_relative_branches */ ZYAN_FALSE,
|
||||
/* force_relative_riprel */ ZYAN_FALSE,
|
||||
/* print_branch_size */ ZYAN_FALSE,
|
||||
/* detailed_prefixes */ ZYAN_FALSE,
|
||||
/* addr_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||
/* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||
/* addr_padding_absolute */ ZYDIS_PADDING_DISABLED,
|
||||
/* addr_padding_relative */ ZYDIS_PADDING_DISABLED,
|
||||
/* disp_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||
/* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||
/* disp_padding */ ZYDIS_PADDING_DISABLED,
|
||||
/* imm_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||
/* imm_signedness */ ZYDIS_SIGNEDNESS_AUTO,
|
||||
/* imm_padding */ ZYDIS_PADDING_DISABLED,
|
||||
/* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_registers */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/* hex_uppercase */ ZYAN_TRUE,
|
||||
/* number_format */
|
||||
{
|
||||
// ZYDIS_NUMERIC_BASE_DEC
|
||||
{
|
||||
// Prefix
|
||||
{
|
||||
/* string */ ZYAN_NULL,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
},
|
||||
// Suffix
|
||||
{
|
||||
/* string */ ZYAN_NULL,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
}
|
||||
},
|
||||
// ZYDIS_NUMERIC_BASE_HEX
|
||||
{
|
||||
// Prefix
|
||||
{
|
||||
/* string */ ZYAN_NULL,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
},
|
||||
// Suffix
|
||||
{
|
||||
/* string */ &FORMATTER_INTEL_MASM.number_format[
|
||||
ZYDIS_NUMERIC_BASE_HEX][1].string_data,
|
||||
/* string_data */ ZYAN_DEFINE_STRING_VIEW("h"),
|
||||
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
}
|
||||
}
|
||||
},
|
||||
/* func_pre_instruction */ ZYAN_NULL,
|
||||
/* func_post_instruction */ ZYAN_NULL,
|
||||
/* func_format_instruction */ &ZydisFormatterIntelFormatInstructionMASM,
|
||||
/* func_pre_operand */ ZYAN_NULL,
|
||||
/* func_post_operand */ ZYAN_NULL,
|
||||
/* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG,
|
||||
/* func_format_operand_mem */ &ZydisFormatterIntelFormatOperandMEM,
|
||||
/* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR,
|
||||
/* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM,
|
||||
/* func_print_mnemonic */ &ZydisFormatterIntelPrintMnemonic,
|
||||
/* func_print_register */ &ZydisFormatterIntelPrintRegister,
|
||||
/* func_print_address_abs */ &ZydisFormatterIntelPrintAddressMASM,
|
||||
/* func_print_address_rel */ &ZydisFormatterIntelPrintAddressMASM,
|
||||
/* func_print_disp */ &ZydisFormatterIntelPrintDISP,
|
||||
/* func_print_imm */ &ZydisFormatterBasePrintIMM,
|
||||
/* func_print_typecast */ &ZydisFormatterIntelPrintTypecast,
|
||||
/* func_print_segment */ &ZydisFormatterBasePrintSegment,
|
||||
/* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes,
|
||||
/* func_print_decorator */ &ZydisFormatterBasePrintDecorator
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ZYDIS_FORMATTER_INTEL_H
|
@ -0,0 +1,974 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#ifndef ZYDIS_INTERNAL_SHAREDDATA_H
|
||||
#define ZYDIS_INTERNAL_SHAREDDATA_H
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zydis/Mnemonic.h>
|
||||
#include <Zydis/Register.h>
|
||||
#include <Zydis/SharedTypes.h>
|
||||
#include <Zydis/DecoderTypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
// MSVC does not like types other than (un-)signed int for bit-fields
|
||||
#ifdef ZYAN_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4214)
|
||||
#endif
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Operand definition */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisSemanticOperandType` enum.
|
||||
*/
|
||||
typedef enum ZydisSemanticOperandType_
|
||||
{
|
||||
ZYDIS_SEMANTIC_OPTYPE_UNUSED,
|
||||
ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG,
|
||||
ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM,
|
||||
ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1,
|
||||
ZYDIS_SEMANTIC_OPTYPE_GPR8,
|
||||
ZYDIS_SEMANTIC_OPTYPE_GPR16,
|
||||
ZYDIS_SEMANTIC_OPTYPE_GPR32,
|
||||
ZYDIS_SEMANTIC_OPTYPE_GPR64,
|
||||
ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64,
|
||||
ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64,
|
||||
ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32,
|
||||
ZYDIS_SEMANTIC_OPTYPE_GPR_ASZ,
|
||||
ZYDIS_SEMANTIC_OPTYPE_FPR,
|
||||
ZYDIS_SEMANTIC_OPTYPE_MMX,
|
||||
ZYDIS_SEMANTIC_OPTYPE_XMM,
|
||||
ZYDIS_SEMANTIC_OPTYPE_YMM,
|
||||
ZYDIS_SEMANTIC_OPTYPE_ZMM,
|
||||
ZYDIS_SEMANTIC_OPTYPE_TMM,
|
||||
ZYDIS_SEMANTIC_OPTYPE_BND,
|
||||
ZYDIS_SEMANTIC_OPTYPE_SREG,
|
||||
ZYDIS_SEMANTIC_OPTYPE_CR,
|
||||
ZYDIS_SEMANTIC_OPTYPE_DR,
|
||||
ZYDIS_SEMANTIC_OPTYPE_MASK,
|
||||
ZYDIS_SEMANTIC_OPTYPE_MEM,
|
||||
ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX,
|
||||
ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY,
|
||||
ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ,
|
||||
ZYDIS_SEMANTIC_OPTYPE_IMM,
|
||||
ZYDIS_SEMANTIC_OPTYPE_REL,
|
||||
ZYDIS_SEMANTIC_OPTYPE_PTR,
|
||||
ZYDIS_SEMANTIC_OPTYPE_AGEN,
|
||||
ZYDIS_SEMANTIC_OPTYPE_MOFFS,
|
||||
ZYDIS_SEMANTIC_OPTYPE_MIB,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_SEMANTIC_OPTYPE_MAX_VALUE = ZYDIS_SEMANTIC_OPTYPE_MIB,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_SEMANTIC_OPTYPE_MAX_VALUE)
|
||||
} ZydisSemanticOperandType;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInternalElementType` enum.
|
||||
*/
|
||||
typedef enum ZydisInternalElementType_
|
||||
{
|
||||
ZYDIS_IELEMENT_TYPE_INVALID,
|
||||
ZYDIS_IELEMENT_TYPE_VARIABLE,
|
||||
ZYDIS_IELEMENT_TYPE_STRUCT,
|
||||
ZYDIS_IELEMENT_TYPE_INT,
|
||||
ZYDIS_IELEMENT_TYPE_UINT,
|
||||
ZYDIS_IELEMENT_TYPE_INT1,
|
||||
ZYDIS_IELEMENT_TYPE_INT8,
|
||||
ZYDIS_IELEMENT_TYPE_INT16,
|
||||
ZYDIS_IELEMENT_TYPE_INT32,
|
||||
ZYDIS_IELEMENT_TYPE_INT64,
|
||||
ZYDIS_IELEMENT_TYPE_UINT8,
|
||||
ZYDIS_IELEMENT_TYPE_UINT16,
|
||||
ZYDIS_IELEMENT_TYPE_UINT32,
|
||||
ZYDIS_IELEMENT_TYPE_UINT64,
|
||||
ZYDIS_IELEMENT_TYPE_UINT128,
|
||||
ZYDIS_IELEMENT_TYPE_UINT256,
|
||||
ZYDIS_IELEMENT_TYPE_FLOAT16,
|
||||
ZYDIS_IELEMENT_TYPE_FLOAT32,
|
||||
ZYDIS_IELEMENT_TYPE_FLOAT64,
|
||||
ZYDIS_IELEMENT_TYPE_FLOAT80,
|
||||
ZYDIS_IELEMENT_TYPE_BCD80,
|
||||
ZYDIS_IELEMENT_TYPE_CC3,
|
||||
ZYDIS_IELEMENT_TYPE_CC5,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_IELEMENT_TYPE_MAX_VALUE = ZYDIS_IELEMENT_TYPE_CC5,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_IELEMENT_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IELEMENT_TYPE_MAX_VALUE)
|
||||
} ZydisInternalElementType;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisImplicitRegisterType` enum.
|
||||
*/
|
||||
typedef enum ZydisImplicitRegisterType_
|
||||
{
|
||||
ZYDIS_IMPLREG_TYPE_STATIC,
|
||||
ZYDIS_IMPLREG_TYPE_GPR_OSZ,
|
||||
ZYDIS_IMPLREG_TYPE_GPR_ASZ,
|
||||
ZYDIS_IMPLREG_TYPE_GPR_SSZ,
|
||||
ZYDIS_IMPLREG_TYPE_IP_ASZ,
|
||||
ZYDIS_IMPLREG_TYPE_IP_SSZ,
|
||||
ZYDIS_IMPLREG_TYPE_FLAGS_SSZ,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_IMPLREG_TYPE_MAX_VALUE = ZYDIS_IMPLREG_TYPE_FLAGS_SSZ,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_IMPLREG_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IMPLREG_TYPE_MAX_VALUE)
|
||||
} ZydisImplicitRegisterType;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisImplicitMemBase` enum.
|
||||
*/
|
||||
typedef enum ZydisImplicitMemBase_
|
||||
{
|
||||
ZYDIS_IMPLMEM_BASE_AGPR_REG,
|
||||
ZYDIS_IMPLMEM_BASE_AGPR_RM,
|
||||
ZYDIS_IMPLMEM_BASE_AAX,
|
||||
ZYDIS_IMPLMEM_BASE_ADX,
|
||||
ZYDIS_IMPLMEM_BASE_ABX,
|
||||
ZYDIS_IMPLMEM_BASE_ASP,
|
||||
ZYDIS_IMPLMEM_BASE_ABP,
|
||||
ZYDIS_IMPLMEM_BASE_ASI,
|
||||
ZYDIS_IMPLMEM_BASE_ADI,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_IMPLMEM_BASE_MAX_VALUE = ZYDIS_IMPLMEM_BASE_ADI,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_IMPLMEM_BASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IMPLMEM_BASE_MAX_VALUE)
|
||||
} ZydisImplicitMemBase;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct
|
||||
// enum types
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_ACTION_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_IELEMENT_TYPE_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_ENCODING_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_IMPLREG_TYPE_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_REGISTER_REQUIRED_BITS <= 16);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_IMPLMEM_BASE_REQUIRED_BITS <= 8);
|
||||
|
||||
/**
|
||||
* Defines the `ZydisOperandDefinition` struct.
|
||||
*/
|
||||
typedef struct ZydisOperandDefinition_
|
||||
{
|
||||
ZyanU8 type ZYAN_BITFIELD(ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS);
|
||||
ZyanU8 visibility ZYAN_BITFIELD(ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS);
|
||||
ZyanU8 actions ZYAN_BITFIELD(ZYDIS_OPERAND_ACTION_REQUIRED_BITS);
|
||||
ZyanU16 size[3];
|
||||
ZyanU8 element_type ZYAN_BITFIELD(ZYDIS_IELEMENT_TYPE_REQUIRED_BITS);
|
||||
union
|
||||
{
|
||||
ZyanU8 encoding ZYAN_BITFIELD(ZYDIS_OPERAND_ENCODING_REQUIRED_BITS);
|
||||
struct
|
||||
{
|
||||
ZyanU8 type ZYAN_BITFIELD(ZYDIS_IMPLREG_TYPE_REQUIRED_BITS);
|
||||
union
|
||||
{
|
||||
ZyanU16 reg ZYAN_BITFIELD(ZYDIS_REGISTER_REQUIRED_BITS);
|
||||
ZyanU8 id ZYAN_BITFIELD(6);
|
||||
} reg;
|
||||
} reg;
|
||||
struct
|
||||
{
|
||||
ZyanU8 seg ZYAN_BITFIELD(3);
|
||||
ZyanU8 base ZYAN_BITFIELD(ZYDIS_IMPLMEM_BASE_REQUIRED_BITS);
|
||||
} mem;
|
||||
} op;
|
||||
} ZydisOperandDefinition;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Instruction definition */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisReadWriteAction` enum.
|
||||
*/
|
||||
typedef enum ZydisReadWriteAction_
|
||||
{
|
||||
ZYDIS_RW_ACTION_NONE,
|
||||
ZYDIS_RW_ACTION_READ,
|
||||
ZYDIS_RW_ACTION_WRITE,
|
||||
ZYDIS_RW_ACTION_READWRITE,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_RW_ACTION_MAX_VALUE = ZYDIS_RW_ACTION_READWRITE,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_RW_ACTION_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_RW_ACTION_MAX_VALUE)
|
||||
} ZydisReadWriteAction;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisRegisterConstraint` enum.
|
||||
*/
|
||||
typedef enum ZydisRegisterConstraint_
|
||||
{
|
||||
ZYDIS_REG_CONSTRAINTS_UNUSED,
|
||||
ZYDIS_REG_CONSTRAINTS_NONE,
|
||||
ZYDIS_REG_CONSTRAINTS_GPR,
|
||||
ZYDIS_REG_CONSTRAINTS_SR_DEST,
|
||||
ZYDIS_REG_CONSTRAINTS_SR,
|
||||
ZYDIS_REG_CONSTRAINTS_CR,
|
||||
ZYDIS_REG_CONSTRAINTS_DR,
|
||||
ZYDIS_REG_CONSTRAINTS_MASK,
|
||||
ZYDIS_REG_CONSTRAINTS_BND,
|
||||
ZYDIS_REG_CONSTRAINTS_VSIB,
|
||||
ZYDIS_REG_CONSTRAINTS_NO_REL,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_REG_CONSTRAINTS_MAX_VALUE = ZYDIS_REG_CONSTRAINTS_NO_REL,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REG_CONSTRAINTS_MAX_VALUE)
|
||||
} ZydisRegisterConstraint;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInternalVectorLength` enum.
|
||||
*/
|
||||
typedef enum ZydisInternalVectorLength_
|
||||
{
|
||||
ZYDIS_IVECTOR_LENGTH_DEFAULT,
|
||||
ZYDIS_IVECTOR_LENGTH_FIXED_128,
|
||||
ZYDIS_IVECTOR_LENGTH_FIXED_256,
|
||||
ZYDIS_IVECTOR_LENGTH_FIXED_512,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_IVECTOR_LENGTH_MAX_VALUE = ZYDIS_IVECTOR_LENGTH_FIXED_512,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IVECTOR_LENGTH_MAX_VALUE)
|
||||
} ZydisInternalVectorLength;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInternalElementSize` enum.
|
||||
*/
|
||||
typedef enum ZydisInternalElementSize_
|
||||
{
|
||||
ZYDIS_IELEMENT_SIZE_INVALID,
|
||||
ZYDIS_IELEMENT_SIZE_8,
|
||||
ZYDIS_IELEMENT_SIZE_16,
|
||||
ZYDIS_IELEMENT_SIZE_32,
|
||||
ZYDIS_IELEMENT_SIZE_64,
|
||||
ZYDIS_IELEMENT_SIZE_128,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_IELEMENT_SIZE_MAX_VALUE = ZYDIS_IELEMENT_SIZE_128,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_IELEMENT_SIZE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IELEMENT_SIZE_MAX_VALUE)
|
||||
} ZydisInternalElementSize;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisEVEXFunctionality` enum.
|
||||
*/
|
||||
typedef enum ZydisEVEXFunctionality_
|
||||
{
|
||||
ZYDIS_EVEX_FUNC_INVALID,
|
||||
/**
|
||||
* `EVEX.b` enables broadcast functionality.
|
||||
*/
|
||||
ZYDIS_EVEX_FUNC_BC,
|
||||
/**
|
||||
* `EVEX.b` enables embedded-rounding functionality.
|
||||
*/
|
||||
ZYDIS_EVEX_FUNC_RC,
|
||||
/**
|
||||
* `EVEX.b` enables sae functionality.
|
||||
*/
|
||||
ZYDIS_EVEX_FUNC_SAE,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_EVEX_FUNC_MAX_VALUE = ZYDIS_EVEX_FUNC_SAE,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_EVEX_FUNC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_EVEX_FUNC_MAX_VALUE)
|
||||
} ZydisEVEXFunctionality;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisEVEXTupleType` enum.
|
||||
*/
|
||||
typedef enum ZydisEVEXTupleType_
|
||||
{
|
||||
ZYDIS_TUPLETYPE_INVALID,
|
||||
/**
|
||||
* Full Vector
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_FV,
|
||||
/**
|
||||
* Half Vector
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_HV,
|
||||
/**
|
||||
* Full Vector Mem
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_FVM,
|
||||
/**
|
||||
* Tuple1 Scalar
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_T1S,
|
||||
/**
|
||||
* Tuple1 Fixed
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_T1F,
|
||||
/**
|
||||
* Tuple1 4x32
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_T1_4X,
|
||||
/**
|
||||
* Gather / Scatter
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_GSCAT,
|
||||
/**
|
||||
* Tuple2
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_T2,
|
||||
/**
|
||||
* Tuple4
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_T4,
|
||||
/**
|
||||
* Tuple8
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_T8,
|
||||
/**
|
||||
* Half Mem
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_HVM,
|
||||
/**
|
||||
* QuarterMem
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_QVM,
|
||||
/**
|
||||
* OctMem
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_OVM,
|
||||
/**
|
||||
* Mem128
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_M128,
|
||||
/**
|
||||
* MOVDDUP
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_DUP,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_MAX_VALUE = ZYDIS_TUPLETYPE_DUP,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_TUPLETYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_TUPLETYPE_MAX_VALUE)
|
||||
} ZydisEVEXTupleType;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisMVEXFunctionality` enum.
|
||||
*/
|
||||
typedef enum ZydisMVEXFunctionality_
|
||||
{
|
||||
/**
|
||||
* The `MVEX.SSS` value is ignored.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_IGNORED,
|
||||
/**
|
||||
* `MVEX.SSS` must be `000b`.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_INVALID,
|
||||
/**
|
||||
* `MVEX.SSS` controls embedded-rounding functionality.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_RC,
|
||||
/**
|
||||
* `MVEX.SSS` controls sae functionality.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_SAE,
|
||||
/**
|
||||
* No special operation (32bit float elements).
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_F_32,
|
||||
/**
|
||||
* No special operation (32bit uint elements).
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_I_32,
|
||||
/**
|
||||
* No special operation (64bit float elements).
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_F_64,
|
||||
/**
|
||||
* No special operation (64bit uint elements).
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_I_64,
|
||||
/**
|
||||
* Sf32(reg) or Si32(reg).
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_SWIZZLE_32,
|
||||
/**
|
||||
* Sf64(reg) or Si64(reg).
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_SWIZZLE_64,
|
||||
/**
|
||||
* Sf32(mem).
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_SF_32,
|
||||
/**
|
||||
* Sf32(mem) broadcast only.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_SF_32_BCST,
|
||||
/**
|
||||
* Sf32(mem) broadcast 4to16 only.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16,
|
||||
/**
|
||||
* Sf64(mem).
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_SF_64,
|
||||
/**
|
||||
* Si32(mem).
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_SI_32,
|
||||
/**
|
||||
* Si32(mem) broadcast only.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_SI_32_BCST,
|
||||
/**
|
||||
* Si32(mem) broadcast 4to16 only.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16,
|
||||
/**
|
||||
* Si64(mem).
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_SI_64,
|
||||
/**
|
||||
* Uf32.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_UF_32,
|
||||
/**
|
||||
* Uf64.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_UF_64,
|
||||
/**
|
||||
* Ui32.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_UI_32,
|
||||
/**
|
||||
* Ui64.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_UI_64,
|
||||
/**
|
||||
* Df32.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_DF_32,
|
||||
/**
|
||||
* Df64.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_DF_64,
|
||||
/**
|
||||
* Di32.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_DI_32,
|
||||
/**
|
||||
* Di64.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_DI_64,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_MAX_VALUE = ZYDIS_MVEX_FUNC_DI_64,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_MVEX_FUNC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MVEX_FUNC_MAX_VALUE)
|
||||
} ZydisMVEXFunctionality;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisVEXStaticBroadcast` enum.
|
||||
*/
|
||||
typedef enum ZydisVEXStaticBroadcast
|
||||
{
|
||||
ZYDIS_VEX_STATIC_BROADCAST_NONE,
|
||||
ZYDIS_VEX_STATIC_BROADCAST_1_TO_2,
|
||||
ZYDIS_VEX_STATIC_BROADCAST_1_TO_4,
|
||||
ZYDIS_VEX_STATIC_BROADCAST_1_TO_8,
|
||||
ZYDIS_VEX_STATIC_BROADCAST_1_TO_16,
|
||||
ZYDIS_VEX_STATIC_BROADCAST_1_TO_32,
|
||||
ZYDIS_VEX_STATIC_BROADCAST_2_TO_4,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_VEX_STATIC_BROADCAST_2_TO_4,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS =
|
||||
ZYAN_BITS_TO_REPRESENT(ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE)
|
||||
} ZydisVEXStaticBroadcast;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisEVEXStaticBroadcast` enum.
|
||||
*/
|
||||
typedef enum ZydisEVEXStaticBroadcast_
|
||||
{
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_NONE,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_2,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_4,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_8,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_16,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_32,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_64,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_2_TO_4,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_2_TO_8,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_2_TO_16,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_4_TO_8,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_4_TO_16,
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS =
|
||||
ZYAN_BITS_TO_REPRESENT(ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE)
|
||||
} ZydisEVEXStaticBroadcast;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisMVEXStaticBroadcast` enum.
|
||||
*/
|
||||
typedef enum ZydisMVEXStaticBroadcast_
|
||||
{
|
||||
ZYDIS_MVEX_STATIC_BROADCAST_NONE,
|
||||
ZYDIS_MVEX_STATIC_BROADCAST_1_TO_8,
|
||||
ZYDIS_MVEX_STATIC_BROADCAST_1_TO_16,
|
||||
ZYDIS_MVEX_STATIC_BROADCAST_4_TO_8,
|
||||
ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_MVEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS =
|
||||
ZYAN_BITS_TO_REPRESENT(ZYDIS_MVEX_STATIC_BROADCAST_MAX_VALUE)
|
||||
} ZydisMVEXStaticBroadcast;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisMaskPolicy` enum.
|
||||
*/
|
||||
typedef enum ZydisMaskPolicy_
|
||||
{
|
||||
ZYDIS_MASK_POLICY_INVALID,
|
||||
/**
|
||||
* The instruction accepts mask-registers other than the default-mask (K0), but
|
||||
* does not require them.
|
||||
*/
|
||||
ZYDIS_MASK_POLICY_ALLOWED,
|
||||
/**
|
||||
* The instruction requires a mask-register other than the default-mask (K0).
|
||||
*/
|
||||
ZYDIS_MASK_POLICY_REQUIRED,
|
||||
/**
|
||||
* The instruction does not allow a mask-register other than the default-mask (K0).
|
||||
*/
|
||||
ZYDIS_MASK_POLICY_FORBIDDEN,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_MASK_POLICY_MAX_VALUE = ZYDIS_MASK_POLICY_FORBIDDEN,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_MASK_POLICY_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MASK_POLICY_MAX_VALUE)
|
||||
} ZydisMaskPolicy;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisMaskOverride` enum.
|
||||
*/
|
||||
typedef enum ZydisMaskOverride_
|
||||
{
|
||||
ZYDIS_MASK_OVERRIDE_DEFAULT,
|
||||
ZYDIS_MASK_OVERRIDE_ZEROING,
|
||||
ZYDIS_MASK_OVERRIDE_CONTROL,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_MASK_OVERRIDE_MAX_VALUE = ZYDIS_MASK_OVERRIDE_CONTROL,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_MASK_OVERRIDE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MASK_OVERRIDE_MAX_VALUE)
|
||||
} ZydisMaskOverride;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct
|
||||
// enum types
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_MNEMONIC_REQUIRED_BITS <= 16);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_CATEGORY_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_ISA_SET_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_ISA_EXT_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_BRANCH_TYPE_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_EXCEPTION_CLASS_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_RW_ACTION_REQUIRED_BITS <= 8);
|
||||
|
||||
#ifndef ZYDIS_MINIMAL_MODE
|
||||
# define ZYDIS_INSTRUCTION_DEFINITION_BASE \
|
||||
ZyanU16 mnemonic ZYAN_BITFIELD(ZYDIS_MNEMONIC_REQUIRED_BITS); \
|
||||
ZyanU8 operand_count ZYAN_BITFIELD( 4); \
|
||||
ZyanU16 operand_reference ZYAN_BITFIELD(15); \
|
||||
ZyanU8 operand_size_map ZYAN_BITFIELD( 3); \
|
||||
ZyanU8 address_size_map ZYAN_BITFIELD( 2); \
|
||||
ZyanU8 flags_reference ZYAN_BITFIELD( 7); \
|
||||
ZyanBool requires_protected_mode ZYAN_BITFIELD( 1); \
|
||||
ZyanU8 category ZYAN_BITFIELD(ZYDIS_CATEGORY_REQUIRED_BITS); \
|
||||
ZyanU8 isa_set ZYAN_BITFIELD(ZYDIS_ISA_SET_REQUIRED_BITS); \
|
||||
ZyanU8 isa_ext ZYAN_BITFIELD(ZYDIS_ISA_EXT_REQUIRED_BITS); \
|
||||
ZyanU8 branch_type ZYAN_BITFIELD(ZYDIS_BRANCH_TYPE_REQUIRED_BITS); \
|
||||
ZyanU8 exception_class ZYAN_BITFIELD(ZYDIS_EXCEPTION_CLASS_REQUIRED_BITS); \
|
||||
ZyanU8 constr_REG ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \
|
||||
ZyanU8 constr_RM ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \
|
||||
ZyanU8 cpu_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS); \
|
||||
ZyanU8 fpu_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS); \
|
||||
ZyanU8 xmm_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS)
|
||||
#else
|
||||
# define ZYDIS_INSTRUCTION_DEFINITION_BASE \
|
||||
ZyanU16 mnemonic ZYAN_BITFIELD(ZYDIS_MNEMONIC_REQUIRED_BITS); \
|
||||
ZyanU8 operand_size_map ZYAN_BITFIELD( 3); \
|
||||
ZyanU8 address_size_map ZYAN_BITFIELD( 2); \
|
||||
ZyanBool requires_protected_mode ZYAN_BITFIELD( 1); \
|
||||
ZyanU8 constr_REG ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \
|
||||
ZyanU8 constr_RM ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS)
|
||||
#endif
|
||||
|
||||
#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR \
|
||||
ZYDIS_INSTRUCTION_DEFINITION_BASE; \
|
||||
ZyanU8 constr_NDSNDD ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS)
|
||||
|
||||
#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL \
|
||||
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; \
|
||||
ZyanBool is_gather ZYAN_BITFIELD( 1)
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionDefinition` struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionDefinition_
|
||||
{
|
||||
ZYDIS_INSTRUCTION_DEFINITION_BASE;
|
||||
} ZydisInstructionDefinition;
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionDefinitionLEGACY` struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionDefinitionLEGACY_
|
||||
{
|
||||
ZYDIS_INSTRUCTION_DEFINITION_BASE;
|
||||
#ifndef ZYDIS_MINIMAL_MODE
|
||||
ZyanBool is_privileged ZYAN_BITFIELD( 1);
|
||||
#endif
|
||||
ZyanBool accepts_LOCK ZYAN_BITFIELD( 1);
|
||||
#ifndef ZYDIS_MINIMAL_MODE
|
||||
ZyanBool accepts_REP ZYAN_BITFIELD( 1);
|
||||
ZyanBool accepts_REPEREPZ ZYAN_BITFIELD( 1);
|
||||
ZyanBool accepts_REPNEREPNZ ZYAN_BITFIELD( 1);
|
||||
ZyanBool accepts_BOUND ZYAN_BITFIELD( 1);
|
||||
ZyanBool accepts_XACQUIRE ZYAN_BITFIELD( 1);
|
||||
ZyanBool accepts_XRELEASE ZYAN_BITFIELD( 1);
|
||||
ZyanBool accepts_hle_without_lock ZYAN_BITFIELD( 1);
|
||||
ZyanBool accepts_branch_hints ZYAN_BITFIELD( 1);
|
||||
ZyanBool accepts_segment ZYAN_BITFIELD( 1);
|
||||
#endif
|
||||
} ZydisInstructionDefinitionLEGACY;
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionDefinition3DNOW` struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionDefinition3DNOW_
|
||||
{
|
||||
ZYDIS_INSTRUCTION_DEFINITION_BASE;
|
||||
} ZydisInstructionDefinition3DNOW;
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionDefinitionXOP` struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionDefinitionXOP_
|
||||
{
|
||||
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR;
|
||||
} ZydisInstructionDefinitionXOP;
|
||||
|
||||
// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct
|
||||
// enum types
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS <= 8);
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionDefinitionVEX` struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionDefinitionVEX_
|
||||
{
|
||||
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL;
|
||||
#ifndef ZYDIS_MINIMAL_MODE
|
||||
ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS);
|
||||
#endif
|
||||
} ZydisInstructionDefinitionVEX;
|
||||
|
||||
#ifndef ZYDIS_DISABLE_AVX512
|
||||
|
||||
// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct
|
||||
// enum types
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_TUPLETYPE_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_IELEMENT_SIZE_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_EVEX_FUNC_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_MASK_POLICY_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_MASK_OVERRIDE_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS <= 8);
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionDefinitionEVEX` struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionDefinitionEVEX_
|
||||
{
|
||||
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL;
|
||||
#ifndef ZYDIS_MINIMAL_MODE
|
||||
ZyanU8 vector_length ZYAN_BITFIELD(ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS);
|
||||
ZyanU8 tuple_type ZYAN_BITFIELD(ZYDIS_TUPLETYPE_REQUIRED_BITS);
|
||||
ZyanU8 element_size ZYAN_BITFIELD(ZYDIS_IELEMENT_SIZE_REQUIRED_BITS);
|
||||
ZyanU8 functionality ZYAN_BITFIELD(ZYDIS_EVEX_FUNC_REQUIRED_BITS);
|
||||
#endif
|
||||
ZyanU8 mask_policy ZYAN_BITFIELD(ZYDIS_MASK_POLICY_REQUIRED_BITS);
|
||||
ZyanBool accepts_zero_mask ZYAN_BITFIELD( 1);
|
||||
#ifndef ZYDIS_MINIMAL_MODE
|
||||
ZyanU8 mask_override ZYAN_BITFIELD(ZYDIS_MASK_OVERRIDE_REQUIRED_BITS);
|
||||
ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS);
|
||||
#endif
|
||||
} ZydisInstructionDefinitionEVEX;
|
||||
#endif
|
||||
|
||||
#ifndef ZYDIS_DISABLE_KNC
|
||||
|
||||
// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct
|
||||
// enum types
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_MVEX_FUNC_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_MASK_POLICY_REQUIRED_BITS <= 8);
|
||||
ZYAN_STATIC_ASSERT(ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS <= 8);
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionDefinitionMVEX` struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionDefinitionMVEX_
|
||||
{
|
||||
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL;
|
||||
ZyanU8 functionality ZYAN_BITFIELD(ZYDIS_MVEX_FUNC_REQUIRED_BITS);
|
||||
ZyanU8 mask_policy ZYAN_BITFIELD(ZYDIS_MASK_POLICY_REQUIRED_BITS);
|
||||
#ifndef ZYDIS_MINIMAL_MODE
|
||||
ZyanBool has_element_granularity ZYAN_BITFIELD( 1);
|
||||
ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS);
|
||||
#endif
|
||||
} ZydisInstructionDefinitionMVEX;
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Accessed CPU flags */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
typedef struct ZydisAccessedFlags_
|
||||
{
|
||||
ZydisCPUFlagAction action[ZYDIS_CPUFLAG_MAX_VALUE + 1];
|
||||
ZyanU32 cpu_flags_read ZYAN_BITFIELD(22);
|
||||
ZyanU32 cpu_flags_written ZYAN_BITFIELD(22);
|
||||
ZyanU8 fpu_flags_read ZYAN_BITFIELD( 4);
|
||||
ZyanU8 fpu_flags_written ZYAN_BITFIELD( 4);
|
||||
} ZydisAccessedFlags;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef ZYAN_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Instruction definition */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the instruction-definition with the given `encoding` and `id`.
|
||||
*
|
||||
* @param encoding The instruction-encoding.
|
||||
* @param id The definition-id.
|
||||
* @param definition A pointer to the variable that receives a pointer to the instruction-
|
||||
* definition.
|
||||
*/
|
||||
ZYDIS_NO_EXPORT void ZydisGetInstructionDefinition(ZydisInstructionEncoding encoding,
|
||||
ZyanU16 id, const ZydisInstructionDefinition** definition);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Operand definition */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYDIS_MINIMAL_MODE
|
||||
/**
|
||||
* Returns the the operand-definitions for the given instruction-`definition`.
|
||||
*
|
||||
* @param definition A pointer to the instruction-definition.
|
||||
* @param operand A pointer to the variable that receives a pointer to the first operand-
|
||||
* definition of the instruction.
|
||||
*
|
||||
* @return The number of operands for the given instruction-definition.
|
||||
*/
|
||||
ZYDIS_NO_EXPORT ZyanU8 ZydisGetOperandDefinitions(const ZydisInstructionDefinition* definition,
|
||||
const ZydisOperandDefinition** operand);
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Element info */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYDIS_MINIMAL_MODE
|
||||
/**
|
||||
* Returns the actual type and size of an internal element-type.
|
||||
*
|
||||
* @param element The internal element type.
|
||||
* @param type The actual element type.
|
||||
* @param size The element size.
|
||||
*/
|
||||
ZYDIS_NO_EXPORT void ZydisGetElementInfo(ZydisInternalElementType element, ZydisElementType* type,
|
||||
ZydisElementSize* size);
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Accessed CPU flags */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYDIS_MINIMAL_MODE
|
||||
/**
|
||||
* Returns the the operand-definitions for the given instruction-`definition`.
|
||||
*
|
||||
* @param definition A pointer to the instruction-definition.
|
||||
* @param flags A pointer to the variable that receives the `ZydisAccessedFlags` struct.
|
||||
*
|
||||
* @return `ZYAN_TRUE`, if the instruction accesses any flags, or `ZYAN_FALSE`, if not.
|
||||
*/
|
||||
ZYDIS_NO_EXPORT ZyanBool ZydisGetAccessedFlags(const ZydisInstructionDefinition* definition,
|
||||
const ZydisAccessedFlags** flags);
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_INTERNAL_SHAREDDATA_H */
|
@ -0,0 +1,464 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides some internal, more performant, but unsafe helper functions for the `ZyanString`
|
||||
* data-type.
|
||||
*
|
||||
* Most of these functions are very similar to the ones in `Zycore/String.h`, but inlined and
|
||||
* without optional overhead like parameter-validation checks, etc ...
|
||||
*
|
||||
* The `ZyanString` data-type is able to dynamically allocate memory on the heap, but as `Zydis` is
|
||||
* designed to be a non-'malloc'ing library, all functions in this file assume that the instances
|
||||
* they are operating on are created with a user-defined static-buffer.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_INTERNAL_STRING_H
|
||||
#define ZYDIS_INTERNAL_STRING_H
|
||||
|
||||
#include <Zycore/LibC.h>
|
||||
#include <Zycore/String.h>
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zycore/Format.h>
|
||||
#include <Zydis/ShortString.h>
|
||||
#include <Zydis/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Letter Case */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisLetterCase` enum.
|
||||
*/
|
||||
typedef enum ZydisLetterCase_
|
||||
{
|
||||
/**
|
||||
* Uses the given text "as is".
|
||||
*/
|
||||
ZYDIS_LETTER_CASE_DEFAULT,
|
||||
/**
|
||||
* Converts the given text to lowercase letters.
|
||||
*/
|
||||
ZYDIS_LETTER_CASE_LOWER,
|
||||
/**
|
||||
* Converts the given text to uppercase letters.
|
||||
*/
|
||||
ZYDIS_LETTER_CASE_UPPER,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_LETTER_CASE_MAX_VALUE = ZYDIS_LETTER_CASE_UPPER,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_LETTER_CASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_LETTER_CASE_MAX_VALUE)
|
||||
} ZydisLetterCase;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Internal macros */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Checks for a terminating '\0' character at the end of the string data.
|
||||
*/
|
||||
#define ZYDIS_STRING_ASSERT_NULLTERMINATION(string) \
|
||||
ZYAN_ASSERT(*(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) == '\0');
|
||||
|
||||
/**
|
||||
* Writes a terminating '\0' character at the end of the string data.
|
||||
*/
|
||||
#define ZYDIS_STRING_NULLTERMINATE(string) \
|
||||
*(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) = '\0';
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal Functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Appending */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Appends the content of the source string to the end of the destination string.
|
||||
*
|
||||
* @param destination The destination string.
|
||||
* @param source The source string.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYAN_INLINE ZyanStatus ZydisStringAppend(ZyanString* destination, const ZyanStringView* source)
|
||||
{
|
||||
ZYAN_ASSERT(destination && source);
|
||||
ZYAN_ASSERT(!destination->vector.allocator);
|
||||
ZYAN_ASSERT(destination->vector.size && source->string.vector.size);
|
||||
|
||||
if (destination->vector.size + source->string.vector.size - 1 > destination->vector.capacity)
|
||||
{
|
||||
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1,
|
||||
source->string.vector.data, source->string.vector.size - 1);
|
||||
|
||||
destination->vector.size += source->string.vector.size - 1;
|
||||
ZYDIS_STRING_NULLTERMINATE(destination);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the content of the source string to the end of the destination
|
||||
* string, converting the characters to the specified letter-case.
|
||||
*
|
||||
* @param destination The destination string.
|
||||
* @param source The source string.
|
||||
* @param letter_case The desired letter-case.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYAN_INLINE ZyanStatus ZydisStringAppendCase(ZyanString* destination, const ZyanStringView* source,
|
||||
ZydisLetterCase letter_case)
|
||||
{
|
||||
ZYAN_ASSERT(destination && source);
|
||||
ZYAN_ASSERT(!destination->vector.allocator);
|
||||
ZYAN_ASSERT(destination->vector.size && source->string.vector.size);
|
||||
|
||||
if (destination->vector.size + source->string.vector.size - 1 > destination->vector.capacity)
|
||||
{
|
||||
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1,
|
||||
source->string.vector.data, source->string.vector.size - 1);
|
||||
|
||||
switch (letter_case)
|
||||
{
|
||||
case ZYDIS_LETTER_CASE_DEFAULT:
|
||||
break;
|
||||
case ZYDIS_LETTER_CASE_LOWER:
|
||||
{
|
||||
const ZyanUSize index = destination->vector.size - 1;
|
||||
const ZyanUSize count = source->string.vector.size - 1;
|
||||
char* s = (char*)destination->vector.data + index;
|
||||
for (ZyanUSize i = index; i < index + count; ++i)
|
||||
{
|
||||
const char c = *s;
|
||||
if ((c >= 'A') && (c <= 'Z'))
|
||||
{
|
||||
*s = c | 32;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZYDIS_LETTER_CASE_UPPER:
|
||||
{
|
||||
const ZyanUSize index = destination->vector.size - 1;
|
||||
const ZyanUSize count = source->string.vector.size - 1;
|
||||
char* s = (char*)destination->vector.data + index;
|
||||
for (ZyanUSize i = index; i < index + count; ++i)
|
||||
{
|
||||
const char c = *s;
|
||||
if ((c >= 'a') && (c <= 'z'))
|
||||
{
|
||||
*s = c & ~32;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ZYAN_UNREACHABLE;
|
||||
}
|
||||
|
||||
destination->vector.size += source->string.vector.size - 1;
|
||||
ZYDIS_STRING_NULLTERMINATE(destination);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the content of the source short-string to the end of the destination string.
|
||||
*
|
||||
* @param destination The destination string.
|
||||
* @param source The source string.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYAN_INLINE ZyanStatus ZydisStringAppendShort(ZyanString* destination,
|
||||
const ZydisShortString* source)
|
||||
{
|
||||
ZYAN_ASSERT(destination && source);
|
||||
ZYAN_ASSERT(!destination->vector.allocator);
|
||||
ZYAN_ASSERT(destination->vector.size && source->size);
|
||||
|
||||
if (destination->vector.size + source->size > destination->vector.capacity)
|
||||
{
|
||||
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, source->data,
|
||||
(ZyanUSize)source->size + 1);
|
||||
|
||||
destination->vector.size += source->size;
|
||||
ZYDIS_STRING_ASSERT_NULLTERMINATION(destination);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the content of the source short-string to the end of the destination string,
|
||||
* converting the characters to the specified letter-case.
|
||||
*
|
||||
* @param destination The destination string.
|
||||
* @param source The source string.
|
||||
* @param letter_case The desired letter-case.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYAN_INLINE ZyanStatus ZydisStringAppendShortCase(ZyanString* destination,
|
||||
const ZydisShortString* source, ZydisLetterCase letter_case)
|
||||
{
|
||||
ZYAN_ASSERT(destination && source);
|
||||
ZYAN_ASSERT(!destination->vector.allocator);
|
||||
ZYAN_ASSERT(destination->vector.size && source->size);
|
||||
|
||||
if (destination->vector.size + source->size > destination->vector.capacity)
|
||||
{
|
||||
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, source->data,
|
||||
(ZyanUSize)source->size + 1);
|
||||
|
||||
switch (letter_case)
|
||||
{
|
||||
case ZYDIS_LETTER_CASE_DEFAULT:
|
||||
break;
|
||||
case ZYDIS_LETTER_CASE_LOWER:
|
||||
{
|
||||
const ZyanUSize index = destination->vector.size - 1;
|
||||
const ZyanUSize count = source->size;
|
||||
char* s = (char*)destination->vector.data + index;
|
||||
for (ZyanUSize i = index; i < index + count; ++i)
|
||||
{
|
||||
const char c = *s;
|
||||
if ((c >= 'A') && (c <= 'Z'))
|
||||
{
|
||||
*s = c | 32;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZYDIS_LETTER_CASE_UPPER:
|
||||
{
|
||||
const ZyanUSize index = destination->vector.size - 1;
|
||||
const ZyanUSize count = source->size;
|
||||
char* s = (char*)destination->vector.data + index;
|
||||
for (ZyanUSize i = index; i < index + count; ++i)
|
||||
{
|
||||
const char c = *s;
|
||||
if ((c >= 'a') && (c <= 'z'))
|
||||
{
|
||||
*s = c & ~32;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ZYAN_UNREACHABLE;
|
||||
}
|
||||
|
||||
destination->vector.size += source->size;
|
||||
ZYDIS_STRING_ASSERT_NULLTERMINATION(destination);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Formatting */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Formats the given unsigned ordinal `value` to its decimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||
* @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZyanStatus ZydisStringAppendDecU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
|
||||
const ZyanStringView* prefix, const ZyanStringView* suffix);
|
||||
|
||||
/**
|
||||
* Formats the given signed ordinal `value` to its decimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||
* @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYAN_INLINE ZyanStatus ZydisStringAppendDecS(ZyanString* string, ZyanI64 value,
|
||||
ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView* prefix,
|
||||
const ZyanStringView* suffix)
|
||||
{
|
||||
static const ZydisShortString str_add = ZYDIS_MAKE_SHORTSTRING("+");
|
||||
static const ZydisShortString str_sub = ZYDIS_MAKE_SHORTSTRING("-");
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
ZYAN_CHECK(ZydisStringAppendShort(string, &str_sub));
|
||||
if (prefix)
|
||||
{
|
||||
ZYAN_CHECK(ZydisStringAppend(string, prefix));
|
||||
}
|
||||
return ZydisStringAppendDecU(string, ZyanAbsI64(value), padding_length,
|
||||
(const ZyanStringView*)ZYAN_NULL, suffix);
|
||||
}
|
||||
|
||||
if (force_sign)
|
||||
{
|
||||
ZYAN_ASSERT(value >= 0);
|
||||
ZYAN_CHECK(ZydisStringAppendShort(string, &str_add));
|
||||
}
|
||||
return ZydisStringAppendDecU(string, value, padding_length, prefix, suffix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the given unsigned ordinal `value` to its hexadecimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||
* ones ('a'-'f').
|
||||
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||
* @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZyanStatus ZydisStringAppendHexU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
|
||||
ZyanBool uppercase, const ZyanStringView* prefix, const ZyanStringView* suffix);
|
||||
|
||||
/**
|
||||
* Formats the given signed ordinal `value` to its hexadecimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the string.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length` (the sign char is ignored).
|
||||
* @param uppercase Set `ZYAN_TRUE` to print the hexadecimal value in uppercase letters
|
||||
* instead of lowercase ones.
|
||||
* @param force_sign Set to `ZYAN_TRUE`, to force printing of the `+` sign for positive
|
||||
* numbers.
|
||||
* @param prefix The string to use as prefix or `NULL`, if not needed.
|
||||
* @param suffix The string to use as suffix or `NULL`, if not needed.
|
||||
*
|
||||
* @return `ZYAN_STATUS_SUCCESS`, if the function succeeded, or
|
||||
* `ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE`, if the size of the buffer was not
|
||||
* sufficient to append the given `value`.
|
||||
*
|
||||
* The string-buffer pointer is increased by the number of chars written, if the call was
|
||||
* successful.
|
||||
*/
|
||||
ZYAN_INLINE ZyanStatus ZydisStringAppendHexS(ZyanString* string, ZyanI64 value,
|
||||
ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix,
|
||||
const ZyanStringView* suffix)
|
||||
{
|
||||
static const ZydisShortString str_add = ZYDIS_MAKE_SHORTSTRING("+");
|
||||
static const ZydisShortString str_sub = ZYDIS_MAKE_SHORTSTRING("-");
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
ZYAN_CHECK(ZydisStringAppendShort(string, &str_sub));
|
||||
if (prefix)
|
||||
{
|
||||
ZYAN_CHECK(ZydisStringAppend(string, prefix));
|
||||
}
|
||||
return ZydisStringAppendHexU(string, ZyanAbsI64(value), padding_length, uppercase,
|
||||
(const ZyanStringView*)ZYAN_NULL, suffix);
|
||||
}
|
||||
|
||||
if (force_sign)
|
||||
{
|
||||
ZYAN_ASSERT(value >= 0);
|
||||
ZYAN_CHECK(ZydisStringAppendShort(string, &str_add));
|
||||
}
|
||||
return ZydisStringAppendHexU(string, value, padding_length, uppercase, prefix, suffix);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ZYDIS_INTERNAL_STRING_H
|
@ -0,0 +1,88 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_METAINFO_H
|
||||
#define ZYDIS_METAINFO_H
|
||||
|
||||
#include <ZydisExportConfig.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#include <Zydis/Generated/EnumInstructionCategory.h>
|
||||
#include <Zydis/Generated/EnumISASet.h>
|
||||
#include <Zydis/Generated/EnumISAExt.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Returns the specified instruction category string.
|
||||
*
|
||||
* @param category The instruction category.
|
||||
*
|
||||
* @return The instruction category string or `ZYAN_NULL`, if an invalid category was passed.
|
||||
*/
|
||||
ZYDIS_EXPORT const char* ZydisCategoryGetString(ZydisInstructionCategory category);
|
||||
|
||||
/**
|
||||
* Returns the specified isa-set string.
|
||||
*
|
||||
* @param isa_set The isa-set.
|
||||
*
|
||||
* @return The isa-set string or `ZYAN_NULL`, if an invalid isa-set was passed.
|
||||
*/
|
||||
ZYDIS_EXPORT const char* ZydisISASetGetString(ZydisISASet isa_set);
|
||||
|
||||
/**
|
||||
* Returns the specified isa-extension string.
|
||||
*
|
||||
* @param isa_ext The isa-extension.
|
||||
*
|
||||
* @return The isa-extension string or `ZYAN_NULL`, if an invalid isa-extension was passed.
|
||||
*/
|
||||
ZYDIS_EXPORT const char* ZydisISAExtGetString(ZydisISAExt isa_ext);
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_METAINFO_H */
|
@ -0,0 +1,88 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Mnemonic constant definitions and helper functions.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_MNEMONIC_H
|
||||
#define ZYDIS_MNEMONIC_H
|
||||
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zydis/ShortString.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#include <Zydis/Generated/EnumMnemonic.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* @addtogroup mnemonic Mnemonic
|
||||
* Functions for retrieving mnemonic names.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the specified instruction mnemonic string.
|
||||
*
|
||||
* @param mnemonic The mnemonic.
|
||||
*
|
||||
* @return The instruction mnemonic string or `ZYAN_NULL`, if an invalid mnemonic was passed.
|
||||
*/
|
||||
ZYDIS_EXPORT const char* ZydisMnemonicGetString(ZydisMnemonic mnemonic);
|
||||
|
||||
/**
|
||||
* Returns the specified instruction mnemonic as `ZydisShortString`.
|
||||
*
|
||||
* @param mnemonic The mnemonic.
|
||||
*
|
||||
* @return The instruction mnemonic string or `ZYAN_NULL`, if an invalid mnemonic was passed.
|
||||
*
|
||||
* The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case.
|
||||
*/
|
||||
ZYDIS_EXPORT const ZydisShortString* ZydisMnemonicGetStringWrapped(ZydisMnemonic mnemonic);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_MNEMONIC_H */
|
@ -0,0 +1,293 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Utility functions and constants for registers.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_REGISTER_H
|
||||
#define ZYDIS_REGISTER_H
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zydis/SharedTypes.h>
|
||||
#include <Zydis/ShortString.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Registers */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#include <Zydis/Generated/EnumRegister.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Register classes */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisRegisterClass` enum.
|
||||
*
|
||||
* Please note that this enum does not contain a matching entry for all values of the
|
||||
* `ZydisRegister` enum, but only for those registers where it makes sense to logically group them
|
||||
* for decoding/encoding purposes.
|
||||
*
|
||||
* These are mainly the registers that can be identified by an id within their corresponding
|
||||
* register-class. The `IP` and `FLAGS` values are exceptions to this rule.
|
||||
*/
|
||||
typedef enum ZydisRegisterClass_
|
||||
{
|
||||
ZYDIS_REGCLASS_INVALID,
|
||||
/**
|
||||
* 8-bit general-purpose registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_GPR8,
|
||||
/**
|
||||
* 16-bit general-purpose registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_GPR16,
|
||||
/**
|
||||
* 32-bit general-purpose registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_GPR32,
|
||||
/**
|
||||
* 64-bit general-purpose registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_GPR64,
|
||||
/**
|
||||
* Floating point legacy registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_X87,
|
||||
/**
|
||||
* Floating point multimedia registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_MMX,
|
||||
/**
|
||||
* 128-bit vector registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_XMM,
|
||||
/**
|
||||
* 256-bit vector registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_YMM,
|
||||
/**
|
||||
* 512-bit vector registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_ZMM,
|
||||
/**
|
||||
* Matrix registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_TMM,
|
||||
/*
|
||||
* Flags registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_FLAGS,
|
||||
/**
|
||||
* Instruction-pointer registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_IP,
|
||||
/**
|
||||
* Segment registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_SEGMENT,
|
||||
/**
|
||||
* Test registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_TEST,
|
||||
/**
|
||||
* Control registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_CONTROL,
|
||||
/**
|
||||
* Debug registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_DEBUG,
|
||||
/**
|
||||
* Mask registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_MASK,
|
||||
/**
|
||||
* Bound registers.
|
||||
*/
|
||||
ZYDIS_REGCLASS_BOUND,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_REGCLASS_MAX_VALUE = ZYDIS_REGCLASS_BOUND,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_REGCLASS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGCLASS_MAX_VALUE)
|
||||
} ZydisRegisterClass;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Register width */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisRegisterWidth` data-type.
|
||||
*/
|
||||
typedef ZyanU16 ZydisRegisterWidth;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Register context */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisRegisterContext` struct.
|
||||
*/
|
||||
typedef struct ZydisRegisterContext_
|
||||
{
|
||||
/**
|
||||
* The values stored in the register context.
|
||||
*/
|
||||
ZyanU64 values[ZYDIS_REGISTER_MAX_VALUE + 1];
|
||||
} ZydisRegisterContext;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* @addtogroup register Register
|
||||
* Functions allowing retrieval of information about registers.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Register */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the register specified by the `register_class` and `id` tuple.
|
||||
*
|
||||
* @param register_class The register class.
|
||||
* @param id The register id.
|
||||
*
|
||||
* @return The register specified by the `register_class` and `id` tuple or `ZYDIS_REGISTER_NONE`,
|
||||
* if an invalid parameter was passed.
|
||||
*/
|
||||
ZYDIS_EXPORT ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class, ZyanU8 id);
|
||||
|
||||
/**
|
||||
* Returns the id of the specified register.
|
||||
*
|
||||
* @param reg The register.
|
||||
*
|
||||
* @return The id of the specified register, or -1 if an invalid parameter was passed.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanI8 ZydisRegisterGetId(ZydisRegister reg);
|
||||
|
||||
/**
|
||||
* Returns the register-class of the specified register.
|
||||
*
|
||||
* @param reg The register.
|
||||
*
|
||||
* @return The register-class of the specified register.
|
||||
*/
|
||||
ZYDIS_EXPORT ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg);
|
||||
|
||||
/**
|
||||
* Returns the width of the specified register.
|
||||
*
|
||||
* @param mode The active machine mode.
|
||||
* @param reg The register.
|
||||
*
|
||||
* @return The width of the specified register, or `ZYDIS_REGISTER_NONE` if the register is
|
||||
* invalid for the active machine-mode.
|
||||
*/
|
||||
ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, ZydisRegister reg);
|
||||
|
||||
/**
|
||||
* Returns the largest enclosing register of the given register.
|
||||
*
|
||||
* @param mode The active machine mode.
|
||||
* @param reg The register.
|
||||
*
|
||||
* @return The largest enclosing register of the given register, or `ZYDIS_REGISTER_NONE` if the
|
||||
* register is invalid for the active machine-mode or does not have an enclosing-register.
|
||||
*/
|
||||
ZYDIS_EXPORT ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode,
|
||||
ZydisRegister reg);
|
||||
|
||||
/**
|
||||
* Returns the specified register string.
|
||||
*
|
||||
* @param reg The register.
|
||||
*
|
||||
* @return The register string or `ZYAN_NULL`, if an invalid register was passed.
|
||||
*/
|
||||
ZYDIS_EXPORT const char* ZydisRegisterGetString(ZydisRegister reg);
|
||||
|
||||
/**
|
||||
* Returns the specified register string as `ZydisShortString`.
|
||||
*
|
||||
* @param reg The register.
|
||||
*
|
||||
* @return The register string or `ZYAN_NULL`, if an invalid register was passed.
|
||||
*
|
||||
* The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case.
|
||||
*/
|
||||
ZYDIS_EXPORT const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Register class */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the width of the specified register-class.
|
||||
*
|
||||
* @param mode The active machine mode.
|
||||
* @param register_class The register class.
|
||||
*
|
||||
* @return The width of the specified register.
|
||||
*/
|
||||
ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode,
|
||||
ZydisRegisterClass register_class);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_REGISTER_H */
|
@ -0,0 +1,480 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines decoder/encoder-shared macros and types.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_SHAREDTYPES_H
|
||||
#define ZYDIS_SHAREDTYPES_H
|
||||
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constants */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYDIS_MAX_INSTRUCTION_LENGTH 15
|
||||
#define ZYDIS_MAX_OPERAND_COUNT 10
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Machine mode */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisMachineMode` enum.
|
||||
*/
|
||||
typedef enum ZydisMachineMode_
|
||||
{
|
||||
/**
|
||||
* 64 bit mode.
|
||||
*/
|
||||
ZYDIS_MACHINE_MODE_LONG_64,
|
||||
/**
|
||||
* 32 bit protected mode.
|
||||
*/
|
||||
ZYDIS_MACHINE_MODE_LONG_COMPAT_32,
|
||||
/**
|
||||
* 16 bit protected mode.
|
||||
*/
|
||||
ZYDIS_MACHINE_MODE_LONG_COMPAT_16,
|
||||
/**
|
||||
* 32 bit protected mode.
|
||||
*/
|
||||
ZYDIS_MACHINE_MODE_LEGACY_32,
|
||||
/**
|
||||
* 16 bit protected mode.
|
||||
*/
|
||||
ZYDIS_MACHINE_MODE_LEGACY_16,
|
||||
/**
|
||||
* 16 bit real mode.
|
||||
*/
|
||||
ZYDIS_MACHINE_MODE_REAL_16,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_MACHINE_MODE_MAX_VALUE = ZYDIS_MACHINE_MODE_REAL_16,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_MACHINE_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MACHINE_MODE_MAX_VALUE)
|
||||
} ZydisMachineMode;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Address width */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisAddressWidth` enum.
|
||||
*/
|
||||
typedef enum ZydisAddressWidth_
|
||||
{
|
||||
ZYDIS_ADDRESS_WIDTH_16,
|
||||
ZYDIS_ADDRESS_WIDTH_32,
|
||||
ZYDIS_ADDRESS_WIDTH_64,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_ADDRESS_WIDTH_MAX_VALUE = ZYDIS_ADDRESS_WIDTH_64,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_ADDRESS_WIDTH_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ADDRESS_WIDTH_MAX_VALUE)
|
||||
} ZydisAddressWidth;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Element type */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisElementType` enum.
|
||||
*/
|
||||
typedef enum ZydisElementType_
|
||||
{
|
||||
ZYDIS_ELEMENT_TYPE_INVALID,
|
||||
/**
|
||||
* A struct type.
|
||||
*/
|
||||
ZYDIS_ELEMENT_TYPE_STRUCT,
|
||||
/**
|
||||
* Unsigned integer value.
|
||||
*/
|
||||
ZYDIS_ELEMENT_TYPE_UINT,
|
||||
/**
|
||||
* Signed integer value.
|
||||
*/
|
||||
ZYDIS_ELEMENT_TYPE_INT,
|
||||
/**
|
||||
* 16-bit floating point value (`half`).
|
||||
*/
|
||||
ZYDIS_ELEMENT_TYPE_FLOAT16,
|
||||
/**
|
||||
* 32-bit floating point value (`single`).
|
||||
*/
|
||||
ZYDIS_ELEMENT_TYPE_FLOAT32,
|
||||
/**
|
||||
* 64-bit floating point value (`double`).
|
||||
*/
|
||||
ZYDIS_ELEMENT_TYPE_FLOAT64,
|
||||
/**
|
||||
* 80-bit floating point value (`extended`).
|
||||
*/
|
||||
ZYDIS_ELEMENT_TYPE_FLOAT80,
|
||||
/**
|
||||
* Binary coded decimal value.
|
||||
*/
|
||||
ZYDIS_ELEMENT_TYPE_LONGBCD,
|
||||
/**
|
||||
* A condition code (e.g. used by `CMPPD`, `VCMPPD`, ...).
|
||||
*/
|
||||
ZYDIS_ELEMENT_TYPE_CC,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_ELEMENT_TYPE_MAX_VALUE = ZYDIS_ELEMENT_TYPE_CC,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_ELEMENT_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ELEMENT_TYPE_MAX_VALUE)
|
||||
} ZydisElementType;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Element size */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisElementSize` datatype.
|
||||
*/
|
||||
typedef ZyanU16 ZydisElementSize;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Operand type */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisOperandType` enum.
|
||||
*/
|
||||
typedef enum ZydisOperandType_
|
||||
{
|
||||
/**
|
||||
* The operand is not used.
|
||||
*/
|
||||
ZYDIS_OPERAND_TYPE_UNUSED,
|
||||
/**
|
||||
* The operand is a register operand.
|
||||
*/
|
||||
ZYDIS_OPERAND_TYPE_REGISTER,
|
||||
/**
|
||||
* The operand is a memory operand.
|
||||
*/
|
||||
ZYDIS_OPERAND_TYPE_MEMORY,
|
||||
/**
|
||||
* The operand is a pointer operand with a segment:offset lvalue.
|
||||
*/
|
||||
ZYDIS_OPERAND_TYPE_POINTER,
|
||||
/**
|
||||
* The operand is an immediate operand.
|
||||
*/
|
||||
ZYDIS_OPERAND_TYPE_IMMEDIATE,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_OPERAND_TYPE_MAX_VALUE = ZYDIS_OPERAND_TYPE_IMMEDIATE,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_OPERAND_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_TYPE_MAX_VALUE)
|
||||
} ZydisOperandType;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Operand encoding */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisOperandEncoding` enum.
|
||||
*/
|
||||
typedef enum ZydisOperandEncoding_
|
||||
{
|
||||
ZYDIS_OPERAND_ENCODING_NONE,
|
||||
ZYDIS_OPERAND_ENCODING_MODRM_REG,
|
||||
ZYDIS_OPERAND_ENCODING_MODRM_RM,
|
||||
ZYDIS_OPERAND_ENCODING_OPCODE,
|
||||
ZYDIS_OPERAND_ENCODING_NDSNDD,
|
||||
ZYDIS_OPERAND_ENCODING_IS4,
|
||||
ZYDIS_OPERAND_ENCODING_MASK,
|
||||
ZYDIS_OPERAND_ENCODING_DISP8,
|
||||
ZYDIS_OPERAND_ENCODING_DISP16,
|
||||
ZYDIS_OPERAND_ENCODING_DISP32,
|
||||
ZYDIS_OPERAND_ENCODING_DISP64,
|
||||
ZYDIS_OPERAND_ENCODING_DISP16_32_64,
|
||||
ZYDIS_OPERAND_ENCODING_DISP32_32_64,
|
||||
ZYDIS_OPERAND_ENCODING_DISP16_32_32,
|
||||
ZYDIS_OPERAND_ENCODING_UIMM8,
|
||||
ZYDIS_OPERAND_ENCODING_UIMM16,
|
||||
ZYDIS_OPERAND_ENCODING_UIMM32,
|
||||
ZYDIS_OPERAND_ENCODING_UIMM64,
|
||||
ZYDIS_OPERAND_ENCODING_UIMM16_32_64,
|
||||
ZYDIS_OPERAND_ENCODING_UIMM32_32_64,
|
||||
ZYDIS_OPERAND_ENCODING_UIMM16_32_32,
|
||||
ZYDIS_OPERAND_ENCODING_SIMM8,
|
||||
ZYDIS_OPERAND_ENCODING_SIMM16,
|
||||
ZYDIS_OPERAND_ENCODING_SIMM32,
|
||||
ZYDIS_OPERAND_ENCODING_SIMM64,
|
||||
ZYDIS_OPERAND_ENCODING_SIMM16_32_64,
|
||||
ZYDIS_OPERAND_ENCODING_SIMM32_32_64,
|
||||
ZYDIS_OPERAND_ENCODING_SIMM16_32_32,
|
||||
ZYDIS_OPERAND_ENCODING_JIMM8,
|
||||
ZYDIS_OPERAND_ENCODING_JIMM16,
|
||||
ZYDIS_OPERAND_ENCODING_JIMM32,
|
||||
ZYDIS_OPERAND_ENCODING_JIMM64,
|
||||
ZYDIS_OPERAND_ENCODING_JIMM16_32_64,
|
||||
ZYDIS_OPERAND_ENCODING_JIMM32_32_64,
|
||||
ZYDIS_OPERAND_ENCODING_JIMM16_32_32,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_OPERAND_ENCODING_MAX_VALUE = ZYDIS_OPERAND_ENCODING_JIMM16_32_32,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_OPERAND_ENCODING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_ENCODING_MAX_VALUE)
|
||||
} ZydisOperandEncoding;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Operand visibility */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisOperandVisibility` enum.
|
||||
*/
|
||||
typedef enum ZydisOperandVisibility_
|
||||
{
|
||||
ZYDIS_OPERAND_VISIBILITY_INVALID,
|
||||
/**
|
||||
* The operand is explicitly encoded in the instruction.
|
||||
*/
|
||||
ZYDIS_OPERAND_VISIBILITY_EXPLICIT,
|
||||
/**
|
||||
* The operand is part of the opcode, but listed as an operand.
|
||||
*/
|
||||
ZYDIS_OPERAND_VISIBILITY_IMPLICIT,
|
||||
/**
|
||||
* The operand is part of the opcode, and not typically listed as an operand.
|
||||
*/
|
||||
ZYDIS_OPERAND_VISIBILITY_HIDDEN,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_OPERAND_VISIBILITY_MAX_VALUE = ZYDIS_OPERAND_VISIBILITY_HIDDEN,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS =
|
||||
ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_VISIBILITY_MAX_VALUE)
|
||||
} ZydisOperandVisibility;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Operand action */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisOperandAction` enum.
|
||||
*/
|
||||
typedef enum ZydisOperandAction_
|
||||
{
|
||||
/* ------------------------------------------------------------------------------------------ */
|
||||
/* Elemental actions */
|
||||
/* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* The operand is read by the instruction.
|
||||
*/
|
||||
ZYDIS_OPERAND_ACTION_READ = 0x01,
|
||||
/**
|
||||
* The operand is written by the instruction (must write).
|
||||
*/
|
||||
ZYDIS_OPERAND_ACTION_WRITE = 0x02,
|
||||
/**
|
||||
* The operand is conditionally read by the instruction.
|
||||
*/
|
||||
ZYDIS_OPERAND_ACTION_CONDREAD = 0x04,
|
||||
/**
|
||||
* The operand is conditionally written by the instruction (may write).
|
||||
*/
|
||||
ZYDIS_OPERAND_ACTION_CONDWRITE = 0x08,
|
||||
|
||||
/* ------------------------------------------------------------------------------------------ */
|
||||
/* Combined actions */
|
||||
/* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* The operand is read (must read) and written by the instruction (must write).
|
||||
*/
|
||||
ZYDIS_OPERAND_ACTION_READWRITE = ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_WRITE,
|
||||
/**
|
||||
* The operand is conditionally read (may read) and conditionally written by
|
||||
* the instruction (may write).
|
||||
*/
|
||||
ZYDIS_OPERAND_ACTION_CONDREAD_CONDWRITE =
|
||||
ZYDIS_OPERAND_ACTION_CONDREAD | ZYDIS_OPERAND_ACTION_CONDWRITE,
|
||||
/**
|
||||
* The operand is read (must read) and conditionally written by the
|
||||
* instruction (may write).
|
||||
*/
|
||||
ZYDIS_OPERAND_ACTION_READ_CONDWRITE =
|
||||
ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_CONDWRITE,
|
||||
/**
|
||||
* The operand is written (must write) and conditionally read by the
|
||||
* instruction (may read).
|
||||
*/
|
||||
ZYDIS_OPERAND_ACTION_CONDREAD_WRITE =
|
||||
ZYDIS_OPERAND_ACTION_CONDREAD | ZYDIS_OPERAND_ACTION_WRITE,
|
||||
|
||||
/**
|
||||
* Mask combining all reading access flags.
|
||||
*/
|
||||
ZYDIS_OPERAND_ACTION_MASK_READ = ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_CONDREAD,
|
||||
/**
|
||||
* Mask combining all writing access flags.
|
||||
*/
|
||||
ZYDIS_OPERAND_ACTION_MASK_WRITE = ZYDIS_OPERAND_ACTION_WRITE | ZYDIS_OPERAND_ACTION_CONDWRITE,
|
||||
|
||||
/* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this bitset.
|
||||
*/
|
||||
ZYDIS_OPERAND_ACTION_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_ACTION_CONDWRITE)
|
||||
} ZydisOperandAction;
|
||||
|
||||
/**
|
||||
* Defines the `ZydisOperandActions` data-type.
|
||||
*/
|
||||
typedef ZyanU8 ZydisOperandActions;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Instruction encoding */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionEncoding` enum.
|
||||
*/
|
||||
typedef enum ZydisInstructionEncoding_
|
||||
{
|
||||
/**
|
||||
* The instruction uses the legacy encoding.
|
||||
*/
|
||||
ZYDIS_INSTRUCTION_ENCODING_LEGACY,
|
||||
/**
|
||||
* The instruction uses the AMD 3DNow-encoding.
|
||||
*/
|
||||
ZYDIS_INSTRUCTION_ENCODING_3DNOW,
|
||||
/**
|
||||
* The instruction uses the AMD XOP-encoding.
|
||||
*/
|
||||
ZYDIS_INSTRUCTION_ENCODING_XOP,
|
||||
/**
|
||||
* The instruction uses the VEX-encoding.
|
||||
*/
|
||||
ZYDIS_INSTRUCTION_ENCODING_VEX,
|
||||
/**
|
||||
* The instruction uses the EVEX-encoding.
|
||||
*/
|
||||
ZYDIS_INSTRUCTION_ENCODING_EVEX,
|
||||
/**
|
||||
* The instruction uses the MVEX-encoding.
|
||||
*/
|
||||
ZYDIS_INSTRUCTION_ENCODING_MVEX,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_INSTRUCTION_ENCODING_MAX_VALUE = ZYDIS_INSTRUCTION_ENCODING_MVEX,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_INSTRUCTION_ENCODING_REQUIRED_BITS =
|
||||
ZYAN_BITS_TO_REPRESENT(ZYDIS_INSTRUCTION_ENCODING_MAX_VALUE)
|
||||
} ZydisInstructionEncoding;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Opcode map */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisOpcodeMap` enum.
|
||||
*/
|
||||
typedef enum ZydisOpcodeMap_
|
||||
{
|
||||
ZYDIS_OPCODE_MAP_DEFAULT,
|
||||
ZYDIS_OPCODE_MAP_0F,
|
||||
ZYDIS_OPCODE_MAP_0F38,
|
||||
ZYDIS_OPCODE_MAP_0F3A,
|
||||
ZYDIS_OPCODE_MAP_0F0F,
|
||||
ZYDIS_OPCODE_MAP_XOP8,
|
||||
ZYDIS_OPCODE_MAP_XOP9,
|
||||
ZYDIS_OPCODE_MAP_XOPA,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_OPCODE_MAP_MAX_VALUE = ZYDIS_OPCODE_MAP_XOPA,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_OPCODE_MAP_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPCODE_MAP_MAX_VALUE)
|
||||
} ZydisOpcodeMap;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_SHAREDTYPES_H */
|
@ -0,0 +1,90 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines the immutable and storage-efficient `ZydisShortString` struct, which
|
||||
* is used to store strings in the generated tables.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_SHORTSTRING_H
|
||||
#define ZYDIS_SHORTSTRING_H
|
||||
|
||||
#include <ZydisExportConfig.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/**
|
||||
* Defines the `ZydisShortString` struct.
|
||||
*
|
||||
* This compact struct is mainly used for internal string-tables to save up some bytes.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZydisShortString_
|
||||
{
|
||||
/**
|
||||
* The buffer that contains the actual (null-terminated) string.
|
||||
*/
|
||||
const char* data;
|
||||
/**
|
||||
* The length (number of characters) of the string (without 0-termination).
|
||||
*/
|
||||
ZyanU8 size;
|
||||
} ZydisShortString;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Declares a `ZydisShortString` from a static C-style string.
|
||||
*
|
||||
* @param string The C-string constant.
|
||||
*/
|
||||
#define ZYDIS_MAKE_SHORTSTRING(string) \
|
||||
{ string, sizeof(string) - 1 }
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_SHORTSTRING_H */
|
@ -0,0 +1,159 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Status code definitions and check macros.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_STATUS_H
|
||||
#define ZYDIS_STATUS_H
|
||||
|
||||
#include <Zycore/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Status codes */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Module IDs */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The zydis module id.
|
||||
*/
|
||||
#define ZYAN_MODULE_ZYDIS 0x002u
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Status codes */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Decoder */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* An attempt was made to read data from an input data-source that has no more
|
||||
* data available.
|
||||
*/
|
||||
#define ZYDIS_STATUS_NO_MORE_DATA \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x00u)
|
||||
|
||||
/**
|
||||
* An general error occured while decoding the current instruction. The
|
||||
* instruction might be undefined.
|
||||
*/
|
||||
#define ZYDIS_STATUS_DECODING_ERROR \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x01u)
|
||||
|
||||
/**
|
||||
* The instruction exceeded the maximum length of 15 bytes.
|
||||
*/
|
||||
#define ZYDIS_STATUS_INSTRUCTION_TOO_LONG \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x02u)
|
||||
|
||||
/**
|
||||
* The instruction encoded an invalid register.
|
||||
*/
|
||||
#define ZYDIS_STATUS_BAD_REGISTER \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x03u)
|
||||
|
||||
/**
|
||||
* A lock-prefix (F0) was found while decoding an instruction that does not
|
||||
* support locking.
|
||||
*/
|
||||
#define ZYDIS_STATUS_ILLEGAL_LOCK \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x04u)
|
||||
|
||||
/**
|
||||
* A legacy-prefix (F2, F3, 66) was found while decoding a XOP/VEX/EVEX/MVEX
|
||||
* instruction.
|
||||
*/
|
||||
#define ZYDIS_STATUS_ILLEGAL_LEGACY_PFX \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x05u)
|
||||
|
||||
/**
|
||||
* A rex-prefix was found while decoding a XOP/VEX/EVEX/MVEX instruction.
|
||||
*/
|
||||
#define ZYDIS_STATUS_ILLEGAL_REX \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x06u)
|
||||
|
||||
/**
|
||||
* An invalid opcode-map value was found while decoding a XOP/VEX/EVEX/MVEX-prefix.
|
||||
*/
|
||||
#define ZYDIS_STATUS_INVALID_MAP \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x07u)
|
||||
|
||||
/**
|
||||
* An error occured while decoding the EVEX-prefix.
|
||||
*/
|
||||
#define ZYDIS_STATUS_MALFORMED_EVEX \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x08u)
|
||||
|
||||
/**
|
||||
* An error occured while decoding the MVEX-prefix.
|
||||
*/
|
||||
#define ZYDIS_STATUS_MALFORMED_MVEX \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x09u)
|
||||
|
||||
/**
|
||||
* An invalid write-mask was specified for an EVEX/MVEX instruction.
|
||||
*/
|
||||
#define ZYDIS_STATUS_INVALID_MASK \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x0Au)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Formatter */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returning this status code in some specified formatter callbacks will cause
|
||||
* the formatter to omit the corresponding token.
|
||||
*
|
||||
* Valid callbacks:
|
||||
* - `ZYDIS_FORMATTER_FUNC_PRE_OPERAND`
|
||||
* - `ZYDIS_FORMATTER_FUNC_POST_OPERAND`
|
||||
* - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG`
|
||||
* - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM`
|
||||
* - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR`
|
||||
* - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM`
|
||||
*/
|
||||
#define ZYDIS_STATUS_SKIP_TOKEN \
|
||||
ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYDIS, 0x0Bu)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_STATUS_H */
|
@ -0,0 +1,275 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Other utility functions.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_UTILS_H
|
||||
#define ZYDIS_UTILS_H
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zydis/DecoderTypes.h>
|
||||
#include <Zydis/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constants */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYDIS_MAX_INSTRUCTION_SEGMENT_COUNT 9
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionSegment` struct.
|
||||
*/
|
||||
typedef enum ZydisInstructionSegment_
|
||||
{
|
||||
ZYDIS_INSTR_SEGMENT_NONE,
|
||||
/**
|
||||
* The legacy prefixes (including ignored `REX` prefixes).
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_PREFIXES,
|
||||
/**
|
||||
* The effective `REX` prefix byte.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_REX,
|
||||
/**
|
||||
* The `XOP` prefix bytes.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_XOP,
|
||||
/**
|
||||
* The `VEX` prefix bytes.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_VEX,
|
||||
/**
|
||||
* The `EVEX` prefix bytes.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_EVEX,
|
||||
/**
|
||||
* The `MVEX` prefix bytes.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_MVEX,
|
||||
/**
|
||||
* The opcode bytes.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_OPCODE,
|
||||
/**
|
||||
* The `ModRM` byte.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_MODRM,
|
||||
/**
|
||||
* The `SIB` byte.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_SIB,
|
||||
/**
|
||||
* The displacement bytes.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_DISPLACEMENT,
|
||||
/**
|
||||
* The immediate bytes.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_IMMEDIATE,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_MAX_VALUE = ZYDIS_INSTR_SEGMENT_IMMEDIATE,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_INSTR_SEGMENT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_INSTR_SEGMENT_MAX_VALUE)
|
||||
} ZydisInstructionSegment;
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionSegments` struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionSegments_
|
||||
{
|
||||
/**
|
||||
* The number of logical instruction segments.
|
||||
*/
|
||||
ZyanU8 count;
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* The type of the segment.
|
||||
*/
|
||||
ZydisInstructionSegment type;
|
||||
/**
|
||||
* The offset of the segment relative to the start of the instruction (in bytes).
|
||||
*/
|
||||
ZyanU8 offset;
|
||||
/**
|
||||
* The size of the segment, in bytes.
|
||||
*/
|
||||
ZyanU8 size;
|
||||
} segments[ZYDIS_MAX_INSTRUCTION_SEGMENT_COUNT];
|
||||
} ZydisInstructionSegments;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* @addtogroup utils Utils
|
||||
* Miscellaneous utility functions. Address translation and other helpers.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Address calculation */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
// TODO: Provide a function that works in minimal-mode and does not require a operand parameter
|
||||
|
||||
/**
|
||||
* Calculates the absolute address value for the given instruction operand.
|
||||
*
|
||||
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||
* @param operand A pointer to the `ZydisDecodedOperand` struct.
|
||||
* @param runtime_address The runtime address of the instruction.
|
||||
* @param result_address A pointer to the memory that receives the absolute address.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* You should use this function in the following cases:
|
||||
* - `IMM` operands with relative address (e.g. `JMP`, `CALL`, ...)
|
||||
* - `MEM` operands with `RIP`/`EIP`-relative address (e.g. `MOV RAX, [RIP+0x12345678]`)
|
||||
* - `MEM` operands with absolute address (e.g. `MOV RAX, [0x12345678]`)
|
||||
* - The displacement needs to get truncated and zero extended
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddress(const ZydisDecodedInstruction* instruction,
|
||||
const ZydisDecodedOperand* operand, ZyanU64 runtime_address, ZyanU64* result_address);
|
||||
|
||||
/**
|
||||
* Calculates the absolute address value for the given instruction operand.
|
||||
*
|
||||
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||
* @param operand A pointer to the `ZydisDecodedOperand` struct.
|
||||
* @param runtime_address The runtime address of the instruction.
|
||||
* @param register_context A pointer to the `ZydisRegisterContext` struct.
|
||||
* @param result_address A pointer to the memory that receives the absolute target-address.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function behaves like `ZydisCalcAbsoluteAddress` but takes an additional register-context
|
||||
* argument to allow calculation of addresses depending on runtime register values.
|
||||
*
|
||||
* Note that `IP/EIP/RIP` from the register-context will be ignored in favor of the passed
|
||||
* runtime-address.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddressEx(const ZydisDecodedInstruction* instruction,
|
||||
const ZydisDecodedOperand* operand, ZyanU64 runtime_address,
|
||||
const ZydisRegisterContext* register_context, ZyanU64* result_address);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Accessed CPU flags */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns a mask of accessed CPU-flags matching the given `action`.
|
||||
*
|
||||
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||
* @param action The CPU-flag action.
|
||||
* @param flags Receives the flag mask.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisGetAccessedFlagsByAction(const ZydisDecodedInstruction* instruction,
|
||||
ZydisCPUFlagAction action, ZydisCPUFlags* flags);
|
||||
|
||||
/**
|
||||
* Returns a mask of accessed CPU-flags that are read (tested) by the current instruction.
|
||||
*
|
||||
* DEPRECATED. This function will be removed in the next major release. Please refer to the
|
||||
* `cpu_flags_read` or `fpu_flags_read` fields of the `ZydisDecodedInstruction` instead.
|
||||
*
|
||||
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||
* @param flags Receives the flag mask.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsRead(
|
||||
const ZydisDecodedInstruction* instruction, ZydisCPUFlags* flags);
|
||||
|
||||
/**
|
||||
* Returns a mask of accessed CPU-flags that are written (modified, undefined) by the current
|
||||
* instruction.
|
||||
*
|
||||
* DEPRECATED. This function will be removed in the next major release. Please refer to the
|
||||
* `cpu_flags_written` or `fpu_flags_written` fields of the `ZydisDecodedInstruction` instead.
|
||||
*
|
||||
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||
* @param flags Receives the flag mask.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsWritten(
|
||||
const ZydisDecodedInstruction* instruction, ZydisCPUFlags* flags);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Instruction segments */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns offsets and sizes of all logical instruction segments (e.g. `OPCODE`,
|
||||
* `MODRM`, ...).
|
||||
*
|
||||
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||
* @param segments Receives the instruction segments information.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisGetInstructionSegments(const ZydisDecodedInstruction* instruction,
|
||||
ZydisInstructionSegments* segments);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_UTILS_H */
|
@ -0,0 +1,169 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Master include file, including everything else.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_H
|
||||
#define ZYDIS_H
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifndef ZYDIS_DISABLE_DECODER
|
||||
# include <Zydis/Decoder.h>
|
||||
# include <Zydis/DecoderTypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef ZYDIS_DISABLE_FORMATTER
|
||||
# include <Zydis/Formatter.h>
|
||||
#endif
|
||||
|
||||
#include <Zydis/MetaInfo.h>
|
||||
#include <Zydis/Mnemonic.h>
|
||||
#include <Zydis/Register.h>
|
||||
#include <Zydis/SharedTypes.h>
|
||||
#include <Zydis/Status.h>
|
||||
#include <Zydis/Utils.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constants */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* A macro that defines the zydis version.
|
||||
*/
|
||||
#define ZYDIS_VERSION (ZyanU64)0x0003000100000000
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helper macros */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Extracts the major-part of the zydis version.
|
||||
*
|
||||
* @param version The zydis version value
|
||||
*/
|
||||
#define ZYDIS_VERSION_MAJOR(version) (ZyanU16)(((version) & 0xFFFF000000000000) >> 48)
|
||||
|
||||
/**
|
||||
* Extracts the minor-part of the zydis version.
|
||||
*
|
||||
* @param version The zydis version value
|
||||
*/
|
||||
#define ZYDIS_VERSION_MINOR(version) (ZyanU16)(((version) & 0x0000FFFF00000000) >> 32)
|
||||
|
||||
/**
|
||||
* Extracts the patch-part of the zydis version.
|
||||
*
|
||||
* @param version The zydis version value
|
||||
*/
|
||||
#define ZYDIS_VERSION_PATCH(version) (ZyanU16)(((version) & 0x00000000FFFF0000) >> 16)
|
||||
|
||||
/**
|
||||
* Extracts the build-part of the zydis version.
|
||||
*
|
||||
* @param version The zydis version value
|
||||
*/
|
||||
#define ZYDIS_VERSION_BUILD(version) (ZyanU16)((version) & 0x000000000000FFFF)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisFeature` enum.
|
||||
*/
|
||||
typedef enum ZydisFeature_
|
||||
{
|
||||
ZYDIS_FEATURE_DECODER,
|
||||
ZYDIS_FEATURE_FORMATTER,
|
||||
ZYDIS_FEATURE_AVX512,
|
||||
ZYDIS_FEATURE_KNC,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_FEATURE_MAX_VALUE = ZYDIS_FEATURE_KNC,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_FEATURE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FEATURE_MAX_VALUE)
|
||||
} ZydisFeature;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* @addtogroup version Version
|
||||
* Functions for checking the library version and build options.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the zydis version.
|
||||
*
|
||||
* @return The zydis version.
|
||||
*
|
||||
* Use the macros provided in this file to extract the major, minor, patch and build part from the
|
||||
* returned version value.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanU64 ZydisGetVersion(void);
|
||||
|
||||
/**
|
||||
* Checks, if the specified feature is enabled in the current zydis library instance.
|
||||
*
|
||||
* @param feature The feature.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE` if the feature is enabled, `ZYAN_STATUS_FALSE` if not. Another
|
||||
* zyan status code, if an error occured.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisIsFeatureEnabled(ZydisFeature feature);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_H */
|
@ -0,0 +1,42 @@
|
||||
|
||||
#ifndef ZYDIS_EXPORT_H
|
||||
#define ZYDIS_EXPORT_H
|
||||
|
||||
#ifdef ZYDIS_STATIC_DEFINE
|
||||
# define ZYDIS_EXPORT
|
||||
# define ZYDIS_NO_EXPORT
|
||||
#else
|
||||
# ifndef ZYDIS_EXPORT
|
||||
# ifdef Zydis_EXPORTS
|
||||
/* We are building this library */
|
||||
# define ZYDIS_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
/* We are using this library */
|
||||
# define ZYDIS_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef ZYDIS_NO_EXPORT
|
||||
# define ZYDIS_NO_EXPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZYDIS_DEPRECATED
|
||||
# define ZYDIS_DEPRECATED __declspec(deprecated)
|
||||
#endif
|
||||
|
||||
#ifndef ZYDIS_DEPRECATED_EXPORT
|
||||
# define ZYDIS_DEPRECATED_EXPORT ZYDIS_EXPORT ZYDIS_DEPRECATED
|
||||
#endif
|
||||
|
||||
#ifndef ZYDIS_DEPRECATED_NO_EXPORT
|
||||
# define ZYDIS_DEPRECATED_NO_EXPORT ZYDIS_NO_EXPORT ZYDIS_DEPRECATED
|
||||
#endif
|
||||
|
||||
#if 0 /* DEFINE_NO_DEPRECATED */
|
||||
# ifndef ZYDIS_NO_DEPRECATED
|
||||
# define ZYDIS_NO_DEPRECATED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_EXPORT_H */
|
@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- asmjit visualizer for Visual Studio (natvis) -->
|
||||
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
<Type Name="asmjit::String">
|
||||
<Intrinsic Name="isSmall" Expression="(_type < 0x1F)"/>
|
||||
<DisplayString Condition="isSmall()">{_small.data, s8}</DisplayString>
|
||||
<DisplayString Condition="!isSmall()">{_large.data, s8}</DisplayString>
|
||||
<Expand HideRawView="true">
|
||||
<Synthetic Name="_type">
|
||||
<DisplayString Condition="(_type < 0x1F)">Small</DisplayString>
|
||||
<DisplayString Condition="(_type == 0x1F)">Large</DisplayString>
|
||||
<DisplayString Condition="(_type > 0x1F)">External</DisplayString>
|
||||
</Synthetic>
|
||||
<Item Name="_size" Condition="isSmall()" ExcludeView="simple">(int)_small.type, d</Item>
|
||||
<Item Name="_size" Condition="!isSmall()" ExcludeView="simple">_large.size, d</Item>
|
||||
<Item Name="_capacity" Condition="isSmall()" ExcludeView="simple">asmjit::String::kSSOCapacity, d</Item>
|
||||
<Item Name="_capacity" Condition="!isSmall()" ExcludeView="simple">_large.capacity, d</Item>
|
||||
<Item Name="_data" Condition="isSmall()" ExcludeView="simple">_small.data, s8</Item>
|
||||
<Item Name="_data" Condition="!isSmall()" ExcludeView="simple">_large.data, s8</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="asmjit::ZoneVector<*>">
|
||||
<DisplayString>{{ [size={_size, d} capacity={_capacity, d}] }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="_size" ExcludeView="simple">_size, d</Item>
|
||||
<Item Name="_capacity" ExcludeView="simple">_capacity, d</Item>
|
||||
<ArrayItems>
|
||||
<Size>_size</Size>
|
||||
<ValuePointer>(($T1*)_data)</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="asmjit::Operand_">
|
||||
<Intrinsic Name="opType" Expression="(unsigned int)(_signature & 0x7)" />
|
||||
<Intrinsic Name="opSize" Expression="(_signature >> 24) & 0xFF" />
|
||||
|
||||
<Intrinsic Name="regType" Expression="(_signature >> 3) & 0x1F" />
|
||||
<Intrinsic Name="regGroup" Expression="(_signature >> 8) & 0xF" />
|
||||
|
||||
<Intrinsic Name="memBaseType" Expression="(_signature >> 3) & 0x1F" />
|
||||
<Intrinsic Name="memIndexType" Expression="(_signature >> 8) & 0x1F" />
|
||||
<Intrinsic Name="memAddrType" Expression="(_signature >> 13) & 0x3" />
|
||||
<Intrinsic Name="memRegHome" Expression="(_signature >> 15) & 0x1" />
|
||||
|
||||
<Intrinsic Name="memBaseId" Expression="_baseId" />
|
||||
<Intrinsic Name="memIndexId" Expression="_data[0]" />
|
||||
|
||||
<Intrinsic Name="memOffset32b" Expression="(__int64)int(_data[1])" />
|
||||
<Intrinsic Name="memOffset64b" Expression="(__int64) ((unsigned __int64)_baseId << 32) | ((unsigned __int64)_data[1])" />
|
||||
<Intrinsic Name="memOffset" Expression="memBaseType() != 0 ? memOffset32b() : memOffset64b()" />
|
||||
|
||||
<Intrinsic Name="immValue" Expression="((__int64)_data[1] << 32) | (__int64)_data[0]" />
|
||||
|
||||
<DisplayString Condition="opType() == 0">[None]</DisplayString>
|
||||
<DisplayString Condition="opType() == 1">[Reg] {{ id={_baseId, d} group={regGroup(), d} type={regType(), d} size={opSize(), d} }}</DisplayString>
|
||||
<DisplayString Condition="opType() == 2">[Mem] {{ baseId={memBaseId(), d} indexId={memIndexId(), d} offset={(__int64)memOffset(), d} }}</DisplayString>
|
||||
<DisplayString Condition="opType() == 3">[Imm] {{ val={immValue(), d} hex={immValue(), X} }}</DisplayString>
|
||||
<DisplayString Condition="opType() == 4">[Label] {{ id={_baseId} }}</DisplayString>
|
||||
<DisplayString Condition="opType() > 4">[Unknown]</DisplayString>
|
||||
<Expand HideRawView="true">
|
||||
<Item Name="_signature">_signature, X</Item>
|
||||
<Item Name="_signature.any.type">(asmjit::Operand_::OpType)opType()</Item>
|
||||
<Item Name="_signature.any.size">opSize(), d</Item>
|
||||
<Item Name="_signature.reg.type" Condition="opType() == 1">(asmjit::BaseReg::RegType)regType()</Item>
|
||||
<Item Name="_signature.reg.group" Condition="opType() == 1">(asmjit::BaseReg::RegGroup)regGroup()</Item>
|
||||
<Item Name="_signature.mem.baseType" Condition="opType() == 2">(asmjit::BaseReg::RegType)memBaseType()</Item>
|
||||
<Item Name="_signature.mem.indexType" Condition="opType() == 2">(asmjit::BaseReg::RegType)memIndexType()</Item>
|
||||
<Item Name="_signature.mem.addrType" Condition="opType() == 2">(asmjit::BaseMem::AddrType)memAddrType()</Item>
|
||||
<Item Name="_signature.mem.regHome" Condition="opType() == 2">(bool)memRegHome()</Item>
|
||||
<Item Name="_baseId">_baseId</Item>
|
||||
<Item Name="_data[0]" Condition="opType() != 2 && opType() != 3">_data[0]</Item>
|
||||
<Item Name="_data[1]" Condition="opType() != 2 && opType() != 3">_data[1]</Item>
|
||||
<Item Name="_data[IndexId]" Condition="opType() == 2">_data[0]</Item>
|
||||
<Item Name="_data[OffsetLo]" Condition="opType() == 2">_data[1]</Item>
|
||||
<Item Name="_data[ImmHi]" Condition="opType() == 3">_data[0]</Item>
|
||||
<Item Name="_data[ImmLo]" Condition="opType() == 3">_data[1]</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="asmjit::FuncValue">
|
||||
<Intrinsic Name="isReg" Expression="(_data & asmjit::FuncValue::kFlagIsReg) != 0" />
|
||||
<Intrinsic Name="isStack" Expression="(_data & asmjit::FuncValue::kFlagIsStack) != 0" />
|
||||
<Intrinsic Name="isIndirect" Expression="(_data & asmjit::FuncValue::kFlagIsIndirect) != 0" />
|
||||
<Intrinsic Name="isDone" Expression="(_data & asmjit::FuncValue::kFlagIsDone) != 0" />
|
||||
|
||||
<Intrinsic Name="typeId" Expression="((_data & asmjit::FuncValue::kTypeIdMask) >> asmjit::FuncValue::kTypeIdShift)" />
|
||||
<Intrinsic Name="regId" Expression="((_data & asmjit::FuncValue::kRegIdMask) >> asmjit::FuncValue::kRegIdShift)" />
|
||||
<Intrinsic Name="regType" Expression="((_data & asmjit::FuncValue::kRegTypeMask) >> asmjit::FuncValue::kRegTypeShift)" />
|
||||
<Intrinsic Name="stackOffset" Expression="((_data & asmjit::FuncValue::kStackOffsetMask) >> asmjit::FuncValue::kStackOffsetShift)" />
|
||||
|
||||
<DisplayString Condition="isReg()">[RegValue {{ regType={regType()} indirect={isIndirect()} done={isDone()} }}]</DisplayString>
|
||||
<DisplayString Condition="isStack()">[StackValue {{ indirect={isIndirect()} done={isDone()} }}]</DisplayString>
|
||||
<DisplayString Condition="!isReg() && !isStack()">[Unknown]</DisplayString>
|
||||
|
||||
<Expand HideRawView="true">
|
||||
<Item Name="data">_data</Item>
|
||||
<Item Name="typeId">(asmjit::Type::Id)(typeId())</Item>
|
||||
<Item Name="regType" Condition="isReg()">(asmjit::BaseReg::RegType)regType()</Item>
|
||||
<Item Name="regId" Condition="isReg()">regId()</Item>
|
||||
<Item Name="stackOffset" Condition="isStack()">stackOffset()</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="asmjit::BaseNode">
|
||||
<Intrinsic Name="nodeType" Expression="_any._nodeType" />
|
||||
|
||||
<Intrinsic Name="isInst" Expression="nodeType() == asmjit::BaseNode::kNodeInst"></Intrinsic>
|
||||
<Intrinsic Name="isSection" Expression="nodeType() == asmjit::BaseNode::kNodeSection"></Intrinsic>
|
||||
<Intrinsic Name="isLabel" Expression="nodeType() == asmjit::BaseNode::kNodeLabel"></Intrinsic>
|
||||
<Intrinsic Name="isAlign" Expression="nodeType() == asmjit::BaseNode::kNodeAlign"></Intrinsic>
|
||||
<Intrinsic Name="isEmbedData" Expression="nodeType() == asmjit::BaseNode::kNodeEmbedData"></Intrinsic>
|
||||
<Intrinsic Name="isEmbedLabel" Expression="nodeType() == asmjit::BaseNode::kNodeEmbedLabel"></Intrinsic>
|
||||
<Intrinsic Name="isEmbedLabelDelta" Expression="nodeType() == asmjit::BaseNode::kNodeEmbedLabelDelta"></Intrinsic>
|
||||
<Intrinsic Name="isConstPool" Expression="nodeType() == asmjit::BaseNode::kNodeConstPool"></Intrinsic>
|
||||
<Intrinsic Name="isComment" Expression="nodeType() == asmjit::BaseNode::kNodeComment"></Intrinsic>
|
||||
<Intrinsic Name="isSentinel" Expression="nodeType() == asmjit::BaseNode::kNodeSentinel"></Intrinsic>
|
||||
<Intrinsic Name="isJump" Expression="nodeType() == asmjit::BaseNode::kNodeJump"></Intrinsic>
|
||||
<Intrinsic Name="isFunc" Expression="nodeType() == asmjit::BaseNode::kNodeFunc"></Intrinsic>
|
||||
<Intrinsic Name="isFuncRet" Expression="nodeType() == asmjit::BaseNode::kNodeFuncRet"></Intrinsic>
|
||||
<Intrinsic Name="isInvoke" Expression="nodeType() == asmjit::BaseNode::kNodeInvoke"></Intrinsic>
|
||||
|
||||
<Intrinsic Name="actsAsInst" Expression="isInst() || isJump() || isFunc() || isFuncRet() || isInvoke()" />
|
||||
<Intrinsic Name="actsAsLabel" Expression="isLabel() || isFunc()" />
|
||||
|
||||
<DisplayString Condition="isInst()">[InstNode]</DisplayString>
|
||||
<DisplayString Condition="isSentinel()">[SectionNode]</DisplayString>
|
||||
<DisplayString Condition="isLabel()">[LabelNode]</DisplayString>
|
||||
<DisplayString Condition="isAlign()">[AlignNode]</DisplayString>
|
||||
<DisplayString Condition="isEmbedData()">[EmbedDataNode]</DisplayString>
|
||||
<DisplayString Condition="isEmbedLabel()">[EmbedLabelNode]</DisplayString>
|
||||
<DisplayString Condition="isEmbedLabelDelta()">[EmbedLabelDeltaNode]</DisplayString>
|
||||
<DisplayString Condition="isConstPool()">[ConstPoolNode]</DisplayString>
|
||||
<DisplayString Condition="isComment()">[CommentNode]</DisplayString>
|
||||
<DisplayString Condition="isSentinel()">[SentinelNode]</DisplayString>
|
||||
<DisplayString Condition="isJump()">[JumpNode]</DisplayString>
|
||||
<DisplayString Condition="isFunc()">[FuncNode]</DisplayString>
|
||||
<DisplayString Condition="isFuncRet()">[FuncRetNode]</DisplayString>
|
||||
<DisplayString Condition="isInvoke()">[InvokeNode]</DisplayString>
|
||||
<DisplayString Condition="nodeType() == 0 || nodeType() > 18">[UnknownNode {nodeType(), d}]</DisplayString>
|
||||
|
||||
<Expand HideRawView="true">
|
||||
<Item Name="prev">_prev</Item>
|
||||
<Item Name="next">_next</Item>
|
||||
|
||||
<Item Name="nodeType">(asmjit::BaseNode::NodeType)_any._nodeType</Item>
|
||||
<Item Name="nodeFlags">(asmjit::BaseNode::Flags)_any._nodeFlags</Item>
|
||||
|
||||
<Item Name="position">_position</Item>
|
||||
<Item Name="userData.u64">_userDataU64</Item>
|
||||
<Item Name="userData.ptr">_userDataPtr</Item>
|
||||
<Item Name="passData">_passData</Item>
|
||||
<Item Name="inlineComment">_inlineComment, s8</Item>
|
||||
|
||||
<Item Name="baseInst" Condition="actsAsInst()">((asmjit::InstNode*)this)->_baseInst</Item>
|
||||
<Item Name="opCount" Condition="actsAsInst()">_inst._opCount</Item>
|
||||
<Item Name="opCapacity" Condition="actsAsInst()">_inst._opCapacity</Item>
|
||||
<Item Name="opArray" Condition="actsAsInst()">((asmjit::InstNode*)this)->_opArray, [_inst._opCount]</Item>
|
||||
|
||||
<Item Name="sectionId" Condition="isSection()">((asmjit::SectionNode*)this)->_id</Item>
|
||||
<Item Name="nextSection" Condition="isSection()">((asmjit::SectionNode*)this)->_nextSection</Item>
|
||||
|
||||
<Item Name="labelId" Condition="isLabel()">((asmjit::LabelNode*)this)->_id</Item>
|
||||
|
||||
<Item Name="alignMode" Condition="isAlign()">((asmjit::AlignNode*)this)->_alignMode</Item>
|
||||
<Item Name="alignment" Condition="isAlign()">((asmjit::AlignNode*)this)->_alignment</Item>
|
||||
|
||||
<Item Name="typeId" Condition="isEmbedData()">_embed._typeId, d</Item>
|
||||
<Item Name="typeSize" Condition="isEmbedData()">_embed._typeSize, d</Item>
|
||||
<Item Name="itemCount" Condition="isEmbedData()">((asmjit::EmbedDataNode*)this)->_itemCount</Item>
|
||||
<Item Name="repeatCount" Condition="isEmbedData()">((asmjit::EmbedDataNode*)this)->_repeatCount</Item>
|
||||
<Item Name="inlineData" Condition="isEmbedData()">((asmjit::EmbedDataNode*)this)->_inlineData</Item>
|
||||
<Item Name="externalData" Condition="isEmbedData()">((asmjit::EmbedDataNode*)this)->_externalData</Item>
|
||||
|
||||
<Item Name="labelId" Condition="isEmbedLabel()">((asmjit::EmbedLabelNode*)this)->_id</Item>
|
||||
|
||||
<Item Name="labelId" Condition="isEmbedLabelDelta()">((asmjit::EmbedLabelDeltaNode*)this)->_id</Item>
|
||||
<Item Name="baseId" Condition="isEmbedLabelDelta()">((asmjit::EmbedLabelDeltaNode*)this)->_baseId</Item>
|
||||
<Item Name="dataSize" Condition="isEmbedLabelDelta()">((asmjit::EmbedLabelDeltaNode*)this)->_dataSize</Item>
|
||||
|
||||
<Item Name="constPool" Condition="isConstPool()">((asmjit::ConstPoolNode*)this)->_constPool</Item>
|
||||
|
||||
<Item Name="sentinel.sentinelType" Condition="isSentinel()">(asmjit::SentinelNode::SentinelType)_sentinel._sentinelType</Item>
|
||||
|
||||
<Item Name="annotation" Condition="isJump()">((asmjit::JumpNode*)this)->_annotation</Item>
|
||||
|
||||
<Item Name="funcDetail" Condition="isFunc()">((asmjit::FuncNode*)this)->_funcDetail</Item>
|
||||
<Item Name="frame" Condition="isFunc()">((asmjit::FuncNode*)this)->_frame</Item>
|
||||
<Item Name="exitNode" Condition="isFunc()">((asmjit::FuncNode*)this)->_exitNode</Item>
|
||||
<Item Name="end" Condition="isFunc()">((asmjit::FuncNode*)this)->_end</Item>
|
||||
<Item Name="args" Condition="isFunc()">((asmjit::FuncNode*)this)->_args, [((asmjit::FuncNode*)this)->_funcDetail._argCount]</Item>
|
||||
|
||||
<Item Name="funcDetail" Condition="isInvoke()">((asmjit::InvokeNode*)this)->_funcDetail</Item>
|
||||
<Item Name="rets" Condition="isInvoke()">((asmjit::InvokeNode*)this)->_rets, [((asmjit::InvokeNode*)this)->_funcDetail._retCount]</Item>
|
||||
<Item Name="args" Condition="isInvoke()">((asmjit::InvokeNode*)this)->_args, [((asmjit::InvokeNode*)this)->_funcDetail._argCount]</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
</AutoVisualizer>
|
@ -0,0 +1,35 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma push_macro("min")
|
||||
#pragma push_macro("max")
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,27 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma pop_macro("min")
|
||||
#pragma pop_macro("max")
|
||||
#endif
|
@ -0,0 +1,37 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_ASMJIT_H_INCLUDED
|
||||
#define ASMJIT_ASMJIT_H_INCLUDED
|
||||
|
||||
#include "./core.h"
|
||||
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
#include "./x86.h"
|
||||
#endif
|
||||
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
#include "./arm.h"
|
||||
#endif
|
||||
|
||||
#endif // ASMJIT_ASMJIT_H_INCLUDED
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,77 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_API_BUILD_P_H_INCLUDED
|
||||
#define ASMJIT_CORE_API_BUILD_P_H_INCLUDED
|
||||
|
||||
#define ASMJIT_EXPORTS
|
||||
|
||||
// Only turn-off these warnings when building asmjit itself.
|
||||
#ifdef _MSC_VER
|
||||
#ifndef _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Dependencies only required for asmjit build, but never exposed through public headers.
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Build - Globals - Build-Only]
|
||||
// ============================================================================
|
||||
|
||||
#include "./api-config.h"
|
||||
|
||||
#if !defined(ASMJIT_BUILD_DEBUG) && defined(__GNUC__) && !defined(__clang__)
|
||||
#define ASMJIT_FAVOR_SIZE __attribute__((__optimize__("Os")))
|
||||
#define ASMJIT_FAVOR_SPEED __attribute__((__optimize__("O3")))
|
||||
#elif ASMJIT_CXX_HAS_ATTRIBUTE(__minsize__, 0)
|
||||
#define ASMJIT_FAVOR_SIZE __attribute__((__minsize__))
|
||||
#define ASMJIT_FAVOR_SPEED
|
||||
#else
|
||||
#define ASMJIT_FAVOR_SIZE
|
||||
#define ASMJIT_FAVOR_SPEED
|
||||
#endif
|
||||
|
||||
// Make sure '#ifdef'ed unit tests are properly highlighted in IDE.
|
||||
#if !defined(ASMJIT_TEST) && defined(__INTELLISENSE__)
|
||||
#define ASMJIT_TEST
|
||||
#endif
|
||||
|
||||
// Include a unit testing package if this is a `asmjit_test_unit` build.
|
||||
#if defined(ASMJIT_TEST)
|
||||
#include "../../../test/broken.h"
|
||||
#endif
|
||||
|
||||
#endif // ASMJIT_CORE_API_BUILD_P_H_INCLUDED
|
@ -0,0 +1,552 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_API_CONFIG_H_INCLUDED
|
||||
#define ASMJIT_CORE_API_CONFIG_H_INCLUDED
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Version]
|
||||
// ============================================================================
|
||||
|
||||
//! \addtogroup asmjit_core
|
||||
//! \{
|
||||
|
||||
//! AsmJit library version in `(Major << 16) | (Minor << 8) | (Patch)` format.
|
||||
#define ASMJIT_LIBRARY_VERSION 0x010400 /* 1.4.0 */
|
||||
|
||||
//! \}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Build - Documentation]
|
||||
// ============================================================================
|
||||
|
||||
// NOTE: Doxygen cannot document macros that are not defined, that's why we have
|
||||
// to define them and then undefine them, so it won't use the macros with its
|
||||
// own preprocessor.
|
||||
#ifdef _DOXYGEN
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_build
|
||||
//! \{
|
||||
|
||||
//! Asmjit is embedded, implies \ref ASMJIT_STATIC.
|
||||
#define ASMJIT_EMBED
|
||||
|
||||
//! Enables static-library build.
|
||||
#define ASMJIT_STATIC
|
||||
|
||||
//! Defined when AsmJit's build configuration is 'Debug'.
|
||||
//!
|
||||
//! \note Can be defined explicitly to bypass autodetection.
|
||||
#define ASMJIT_BUILD_DEBUG
|
||||
|
||||
//! Defined when AsmJit's build configuration is 'Release'.
|
||||
//!
|
||||
//! \note Can be defined explicitly to bypass autodetection.
|
||||
#define ASMJIT_BUILD_RELEASE
|
||||
|
||||
//! Defined to build X86/X64 backend.
|
||||
#define ASMJIT_BUILD_X86
|
||||
|
||||
//! Defined to build host backend autodetected at compile-time.
|
||||
#define ASMJIT_BUILD_HOST
|
||||
|
||||
//! Disables deprecated API at compile time.
|
||||
#define ASMJIT_NO_DEPRECATED
|
||||
|
||||
//! Disable non-host architectures entirely.
|
||||
#define ASMJIT_NO_FOREIGN
|
||||
|
||||
//! Disables \ref asmjit_builder functionality completely.
|
||||
#define ASMJIT_NO_BUILDER
|
||||
|
||||
//! Disables \ref asmjit_compiler functionality completely.
|
||||
#define ASMJIT_NO_COMPILER
|
||||
|
||||
//! Disables JIT memory management and \ref JitRuntime.
|
||||
#define ASMJIT_NO_JIT
|
||||
|
||||
//! Disables \ref Logger and \ref Formatter.
|
||||
#define ASMJIT_NO_LOGGING
|
||||
|
||||
//! Disables everything that contains text.
|
||||
#define ASMJIT_NO_TEXT
|
||||
|
||||
//! Disables instruction validation API.
|
||||
#define ASMJIT_NO_VALIDATION
|
||||
|
||||
//! Disables instruction introspection API.
|
||||
#define ASMJIT_NO_INTROSPECTION
|
||||
|
||||
// Avoid doxygen preprocessor using feature-selection definitions.
|
||||
#undef ASMJIT_NO_BUILDER
|
||||
#undef ASMJIT_NO_COMPILER
|
||||
#undef ASMJIT_NO_JIT
|
||||
#undef ASMJIT_NO_LOGGING
|
||||
#undef ASMJIT_NO_TEXT
|
||||
#undef ASMJIT_NO_VALIDATION
|
||||
#undef ASMJIT_NO_INTROSPECTION
|
||||
|
||||
//! \}
|
||||
|
||||
} // {asmjit}
|
||||
#endif // _DOXYGEN
|
||||
|
||||
// Enable all features at IDE level, so it's properly highlighted and indexed.
|
||||
#ifdef __INTELLISENSE__
|
||||
#ifndef ASMJIT_BUILD_X86
|
||||
#define ASMJIT_BUILD_X86
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Dependencies]
|
||||
// ============================================================================
|
||||
|
||||
// We really want std-types as globals.
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Options]
|
||||
// ============================================================================
|
||||
|
||||
// ASMJIT_NO_BUILDER implies ASMJIT_NO_COMPILER.
|
||||
#if defined(ASMJIT_NO_BUILDER) && !defined(ASMJIT_NO_COMPILER)
|
||||
#define ASMJIT_NO_COMPILER
|
||||
#endif
|
||||
|
||||
// Prevent compile-time errors caused by misconfiguration.
|
||||
#if defined(ASMJIT_NO_TEXT) && !defined(ASMJIT_NO_LOGGING)
|
||||
#pragma "ASMJIT_NO_TEXT can only be defined when ASMJIT_NO_LOGGING is defined."
|
||||
#undef ASMJIT_NO_TEXT
|
||||
#endif
|
||||
|
||||
#if defined(ASMJIT_NO_INTROSPECTION) && !defined(ASMJIT_NO_COMPILER)
|
||||
#pragma message("ASMJIT_NO_INTROSPECTION can only be defined when ASMJIT_NO_COMPILER is defined")
|
||||
#undef ASMJIT_NO_INTROSPECTION
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Build - Globals - Deprecated]
|
||||
// ============================================================================
|
||||
|
||||
#ifndef ASMJIT_NO_DEPRECATED
|
||||
#if defined(ASMJIT_BUILD_EMBED) || defined(ASMJIT_BUILD_STATIC)
|
||||
#if defined(ASMJIT_BUILD_EMBED)
|
||||
#pragma message("'ASMJIT_BUILD_EMBED' is deprecated, use 'ASMJIT_STATIC'")
|
||||
#endif
|
||||
#if defined(ASMJIT_BUILD_STATIC)
|
||||
#pragma message("'ASMJIT_BUILD_STATIC' is deprecated, use 'ASMJIT_STATIC'")
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_STATIC)
|
||||
#define ASMJIT_STATIC
|
||||
#endif
|
||||
#endif
|
||||
#endif // !ASMJIT_NO_DEPRECATED
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Build - Globals - Build Mode]
|
||||
// ============================================================================
|
||||
|
||||
// Detect ASMJIT_BUILD_DEBUG and ASMJIT_BUILD_RELEASE if not defined.
|
||||
#if !defined(ASMJIT_BUILD_DEBUG) && !defined(ASMJIT_BUILD_RELEASE)
|
||||
#if !defined(NDEBUG)
|
||||
#define ASMJIT_BUILD_DEBUG
|
||||
#else
|
||||
#define ASMJIT_BUILD_RELEASE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Build - Globals - Target Architecture Information]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define ASMJIT_ARCH_X86 64
|
||||
#elif defined(_M_IX86) || defined(__X86__) || defined(__i386__)
|
||||
#define ASMJIT_ARCH_X86 32
|
||||
#else
|
||||
#define ASMJIT_ARCH_X86 0
|
||||
#endif
|
||||
|
||||
#if defined(__arm64__) || defined(__aarch64__)
|
||||
# define ASMJIT_ARCH_ARM 64
|
||||
#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__) || defined(__thumb2__)
|
||||
#define ASMJIT_ARCH_ARM 32
|
||||
#else
|
||||
#define ASMJIT_ARCH_ARM 0
|
||||
#endif
|
||||
|
||||
#if defined(_MIPS_ARCH_MIPS64) || defined(__mips64)
|
||||
#define ASMJIT_ARCH_MIPS 64
|
||||
#elif defined(_MIPS_ARCH_MIPS32) || defined(_M_MRX000) || defined(__mips__)
|
||||
#define ASMJIT_ARCH_MIPS 32
|
||||
#else
|
||||
#define ASMJIT_ARCH_MIPS 0
|
||||
#endif
|
||||
|
||||
#define ASMJIT_ARCH_BITS (ASMJIT_ARCH_X86 | ASMJIT_ARCH_ARM | ASMJIT_ARCH_MIPS)
|
||||
#if ASMJIT_ARCH_BITS == 0
|
||||
#undef ASMJIT_ARCH_BITS
|
||||
#if defined (__LP64__) || defined(_LP64)
|
||||
#define ASMJIT_ARCH_BITS 64
|
||||
#else
|
||||
#define ASMJIT_ARCH_BITS 32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(__ARMEB__)) || \
|
||||
(defined(__MIPSEB__)) || \
|
||||
(defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
#define ASMJIT_ARCH_LE 0
|
||||
#define ASMJIT_ARCH_BE 1
|
||||
#else
|
||||
#define ASMJIT_ARCH_LE 1
|
||||
#define ASMJIT_ARCH_BE 0
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Build - Globals - Build Architectures Definitions]
|
||||
// ============================================================================
|
||||
|
||||
#if !defined(ASMJIT_NO_FOREIGN)
|
||||
// If 'ASMJIT_NO_FOREIGN' is not defined then all architectures will be built.
|
||||
#if !defined(ASMJIT_BUILD_X86)
|
||||
#define ASMJIT_BUILD_X86
|
||||
#endif
|
||||
#else
|
||||
// Detect architectures to build if building only for the host architecture.
|
||||
#if ASMJIT_ARCH_X86 && !defined(ASMJIT_BUILD_X86)
|
||||
#define ASMJIT_BUILD_X86
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Define 'ASMJIT_BUILD_HOST' if we know that host architecture will be built.
|
||||
#if !defined(ASMJIT_BUILD_HOST) && ASMJIT_ARCH_X86 && defined(ASMJIT_BUILD_X86)
|
||||
#define ASMJIT_BUILD_HOST
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Build - Globals - C++ Compiler and Features Detection]
|
||||
// ============================================================================
|
||||
|
||||
#define ASMJIT_CXX_GNU 0
|
||||
#define ASMJIT_CXX_MAKE_VER(MAJOR, MINOR) ((MAJOR) * 1000 + (MINOR))
|
||||
|
||||
// Intel Compiler [pretends to be GNU or MSC, so it must be checked first]:
|
||||
// - https://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler
|
||||
// - https://software.intel.com/en-us/articles/c14-features-supported-by-intel-c-compiler
|
||||
// - https://software.intel.com/en-us/articles/c17-features-supported-by-intel-c-compiler
|
||||
#if defined(__INTEL_COMPILER)
|
||||
|
||||
// MSC Compiler:
|
||||
// - https://msdn.microsoft.com/en-us/library/hh567368.aspx
|
||||
//
|
||||
// Version List:
|
||||
// - 16.00.0 == VS2010
|
||||
// - 17.00.0 == VS2012
|
||||
// - 18.00.0 == VS2013
|
||||
// - 19.00.0 == VS2015
|
||||
// - 19.10.0 == VS2017
|
||||
#elif defined(_MSC_VER) && defined(_MSC_FULL_VER)
|
||||
|
||||
// Clang Compiler [Pretends to be GNU, so it must be checked before]:
|
||||
// - https://clang.llvm.org/cxx_status.html
|
||||
#elif defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
|
||||
|
||||
// GNU Compiler:
|
||||
// - https://gcc.gnu.org/projects/cxx-status.html
|
||||
#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
|
||||
|
||||
#undef ASMJIT_CXX_GNU
|
||||
#define ASMJIT_CXX_GNU ASMJIT_CXX_MAKE_VER(__GNUC__, __GNUC_MINOR__)
|
||||
|
||||
#endif
|
||||
|
||||
// Compiler features detection macros.
|
||||
#if defined(__clang__) && defined(__has_attribute)
|
||||
#define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (__has_attribute(NAME))
|
||||
#else
|
||||
#define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (!(!(CHECK)))
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Build - Globals - API Decorators & Language Extensions]
|
||||
// ============================================================================
|
||||
|
||||
// API (Export / Import).
|
||||
#if !defined(ASMJIT_STATIC)
|
||||
#if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__))
|
||||
#ifdef ASMJIT_EXPORTS
|
||||
#define ASMJIT_API __declspec(dllexport)
|
||||
#else
|
||||
#define ASMJIT_API __declspec(dllimport)
|
||||
#endif
|
||||
#elif defined(_WIN32) && defined(__GNUC__)
|
||||
#ifdef ASMJIT_EXPORTS
|
||||
#define ASMJIT_API __attribute__((__dllexport__))
|
||||
#else
|
||||
#define ASMJIT_API __attribute__((__dllimport__))
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#define ASMJIT_API __attribute__((__visibility__("default")))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_API)
|
||||
#define ASMJIT_API
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_VARAPI)
|
||||
#define ASMJIT_VARAPI extern ASMJIT_API
|
||||
#endif
|
||||
|
||||
// This is basically a workaround. When using MSVC and marking class as DLL
|
||||
// export everything gets exported, which is unwanted in most projects. MSVC
|
||||
// automatically exports typeinfo and vtable if at least one symbol of the
|
||||
// class is exported. However, GCC has some strange behavior that even if
|
||||
// one or more symbol is exported it doesn't export typeinfo unless the
|
||||
// class itself is decorated with "visibility(default)" (i.e. ASMJIT_API).
|
||||
#if !defined(_WIN32) && defined(__GNUC__)
|
||||
#define ASMJIT_VIRTAPI ASMJIT_API
|
||||
#else
|
||||
#define ASMJIT_VIRTAPI
|
||||
#endif
|
||||
|
||||
// Function attributes.
|
||||
#if !defined(ASMJIT_BUILD_DEBUG) && defined(__GNUC__)
|
||||
#define ASMJIT_INLINE inline __attribute__((__always_inline__))
|
||||
#elif !defined(ASMJIT_BUILD_DEBUG) && defined(_MSC_VER)
|
||||
#define ASMJIT_INLINE __forceinline
|
||||
#else
|
||||
#define ASMJIT_INLINE inline
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define ASMJIT_NOINLINE __attribute__((__noinline__))
|
||||
#define ASMJIT_NORETURN __attribute__((__noreturn__))
|
||||
#elif defined(_MSC_VER)
|
||||
#define ASMJIT_NOINLINE __declspec(noinline)
|
||||
#define ASMJIT_NORETURN __declspec(noreturn)
|
||||
#else
|
||||
#define ASMJIT_NOINLINE
|
||||
#define ASMJIT_NORETURN
|
||||
#endif
|
||||
|
||||
// Calling conventions.
|
||||
#if ASMJIT_ARCH_X86 == 32 && defined(__GNUC__)
|
||||
#define ASMJIT_CDECL __attribute__((__cdecl__))
|
||||
#define ASMJIT_STDCALL __attribute__((__stdcall__))
|
||||
#define ASMJIT_FASTCALL __attribute__((__fastcall__))
|
||||
#define ASMJIT_REGPARM(N) __attribute__((__regparm__(N)))
|
||||
#elif ASMJIT_ARCH_X86 == 32 && defined(_MSC_VER)
|
||||
#define ASMJIT_CDECL __cdecl
|
||||
#define ASMJIT_STDCALL __stdcall
|
||||
#define ASMJIT_FASTCALL __fastcall
|
||||
#define ASMJIT_REGPARM(N)
|
||||
#else
|
||||
#define ASMJIT_CDECL
|
||||
#define ASMJIT_STDCALL
|
||||
#define ASMJIT_FASTCALL
|
||||
#define ASMJIT_REGPARM(N)
|
||||
#endif
|
||||
|
||||
#if ASMJIT_ARCH_X86 && defined(_WIN32) && defined(_MSC_VER)
|
||||
#define ASMJIT_VECTORCALL __vectorcall
|
||||
#elif ASMJIT_ARCH_X86 && defined(_WIN32)
|
||||
#define ASMJIT_VECTORCALL __attribute__((__vectorcall__))
|
||||
#else
|
||||
#define ASMJIT_VECTORCALL
|
||||
#endif
|
||||
|
||||
|
||||
// Type alignment (not allowed by C++11 'alignas' keyword).
|
||||
#if defined(__GNUC__)
|
||||
#define ASMJIT_ALIGN_TYPE(TYPE, N) __attribute__((__aligned__(N))) TYPE
|
||||
#elif defined(_MSC_VER)
|
||||
#define ASMJIT_ALIGN_TYPE(TYPE, N) __declspec(align(N)) TYPE
|
||||
#else
|
||||
#define ASMJIT_ALIGN_TYPE(TYPE, N) TYPE
|
||||
#endif
|
||||
|
||||
//! \def ASMJIT_MAY_ALIAS
|
||||
//!
|
||||
//! Expands to `__attribute__((__may_alias__))` if supported.
|
||||
#if defined(__GNUC__)
|
||||
#define ASMJIT_MAY_ALIAS __attribute__((__may_alias__))
|
||||
#else
|
||||
#define ASMJIT_MAY_ALIAS
|
||||
#endif
|
||||
|
||||
//! \def ASMJIT_LIKELY(...)
|
||||
//!
|
||||
//! Condition is likely to be taken (mostly error handling and edge cases).
|
||||
|
||||
//! \def ASMJIT_UNLIKELY(...)
|
||||
//!
|
||||
//! Condition is unlikely to be taken (mostly error handling and edge cases).
|
||||
#if defined(__GNUC__)
|
||||
#define ASMJIT_LIKELY(...) __builtin_expect(!!(__VA_ARGS__), 1)
|
||||
#define ASMJIT_UNLIKELY(...) __builtin_expect(!!(__VA_ARGS__), 0)
|
||||
#else
|
||||
#define ASMJIT_LIKELY(...) (__VA_ARGS__)
|
||||
#define ASMJIT_UNLIKELY(...) (__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
//! \def ASMJIT_FALLTHROUGH
|
||||
//!
|
||||
//! Portable [[fallthrough]] attribute.
|
||||
#if defined(__clang__) && __cplusplus >= 201103L
|
||||
#define ASMJIT_FALLTHROUGH [[clang::fallthrough]]
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 7
|
||||
#define ASMJIT_FALLTHROUGH __attribute__((__fallthrough__))
|
||||
#else
|
||||
#define ASMJIT_FALLTHROUGH ((void)0) /* fallthrough */
|
||||
#endif
|
||||
|
||||
//! \def ASMJIT_DEPRECATED
|
||||
//!
|
||||
//! Marks function, class, struct, enum, or anything else as deprecated.
|
||||
#if defined(__GNUC__)
|
||||
#define ASMJIT_DEPRECATED(MESSAGE) __attribute__((__deprecated__(MESSAGE)))
|
||||
#if defined(__clang__)
|
||||
#define ASMJIT_DEPRECATED_STRUCT(MESSAGE) __attribute__((__deprecated__(MESSAGE)))
|
||||
#else
|
||||
#define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#define ASMJIT_DEPRECATED(MESSAGE) __declspec(deprecated(MESSAGE))
|
||||
#define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */
|
||||
#else
|
||||
#define ASMJIT_DEPRECATED(MESSAGE)
|
||||
#define ASMJIT_DEPRECATED_STRUCT(MESSAGE)
|
||||
#endif
|
||||
|
||||
// Utilities.
|
||||
#define ASMJIT_OFFSET_OF(STRUCT, MEMBER) ((int)(intptr_t)((const char*)&((const STRUCT*)0x100)->MEMBER) - 0x100)
|
||||
#define ASMJIT_ARRAY_SIZE(X) uint32_t(sizeof(X) / sizeof(X[0]))
|
||||
|
||||
#if ASMJIT_CXX_HAS_ATTRIBUTE(no_sanitize, 0)
|
||||
#define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize__("undefined")))
|
||||
#elif ASMJIT_CXX_GNU >= ASMJIT_CXX_MAKE_VER(4, 9)
|
||||
#define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize_undefined__))
|
||||
#else
|
||||
#define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Build - Globals - Begin-Namespace / End-Namespace]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(__clang__)
|
||||
#define ASMJIT_BEGIN_NAMESPACE \
|
||||
namespace asmjit { \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wconstant-logical-operand\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wunnamed-type-template-args\"")
|
||||
#define ASMJIT_END_NAMESPACE \
|
||||
_Pragma("clang diagnostic pop") \
|
||||
}
|
||||
#elif defined(__GNUC__) && __GNUC__ == 4
|
||||
#define ASMJIT_BEGIN_NAMESPACE \
|
||||
namespace asmjit { \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
|
||||
#define ASMJIT_END_NAMESPACE \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
}
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 8
|
||||
#define ASMJIT_BEGIN_NAMESPACE \
|
||||
namespace asmjit { \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"")
|
||||
#define ASMJIT_END_NAMESPACE \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
}
|
||||
#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER)
|
||||
#define ASMJIT_BEGIN_NAMESPACE \
|
||||
namespace asmjit { \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable: 4127)) /* conditional expression is const */ \
|
||||
__pragma(warning(disable: 4201)) /* nameless struct/union */
|
||||
#define ASMJIT_END_NAMESPACE \
|
||||
__pragma(warning(pop)) \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_BEGIN_NAMESPACE) && !defined(ASMJIT_END_NAMESPACE)
|
||||
#define ASMJIT_BEGIN_NAMESPACE namespace asmjit {
|
||||
#define ASMJIT_END_NAMESPACE }
|
||||
#endif
|
||||
|
||||
#define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) \
|
||||
ASMJIT_BEGIN_NAMESPACE \
|
||||
namespace NAMESPACE {
|
||||
|
||||
#define ASMJIT_END_SUB_NAMESPACE \
|
||||
} \
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Build - Globals - Utilities]
|
||||
// ============================================================================
|
||||
|
||||
#define ASMJIT_NONCOPYABLE(...) \
|
||||
private: \
|
||||
__VA_ARGS__(const __VA_ARGS__& other) = delete; \
|
||||
__VA_ARGS__& operator=(const __VA_ARGS__& other) = delete; \
|
||||
public:
|
||||
|
||||
#define ASMJIT_NONCONSTRUCTIBLE(...) \
|
||||
private: \
|
||||
__VA_ARGS__() = delete; \
|
||||
__VA_ARGS__(const __VA_ARGS__& other) = delete; \
|
||||
__VA_ARGS__& operator=(const __VA_ARGS__& other) = delete; \
|
||||
public:
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Build - Globals - Cleanup]
|
||||
// ============================================================================
|
||||
|
||||
// Cleanup definitions that are only used within this header file.
|
||||
#undef ASMJIT_CXX_GNU
|
||||
#undef ASMJIT_CXX_MAKE_VER
|
||||
|
||||
#endif // ASMJIT_CORE_API_CONFIG_H_INCLUDED
|
@ -0,0 +1,164 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED
|
||||
#define ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED
|
||||
|
||||
// This file provides architecture-specific classes that are required in the
|
||||
// core library. For example Imm operand allows to be created from arm::Shift
|
||||
// in a const-expr way, so the arm::Shift must be provided. So this header
|
||||
// file provides everything architecture-specific that is used by the Core API.
|
||||
|
||||
#include "../core/globals.h"
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::arm]
|
||||
// ============================================================================
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(arm)
|
||||
|
||||
//! \addtogroup asmjit_arm
|
||||
//! \{
|
||||
|
||||
//! Represents ARM immediate shift operation type and value.
|
||||
class Shift {
|
||||
public:
|
||||
//! Operation predicate (ARM) describes either SHIFT or EXTEND operation.
|
||||
//!
|
||||
//! \note The constants are AsmJit specific. The first 5 values describe real
|
||||
//! constants on ARM32 and AArch64 hardware, however, the addition constants
|
||||
//! that describe extend modes are specific to AsmJit and would be translated
|
||||
//! to the AArch64 specific constants by the assembler.
|
||||
enum Op : uint32_t {
|
||||
//! Shift left logical operation (default).
|
||||
//!
|
||||
//! Available to all ARM architectures.
|
||||
kOpLSL = 0x00u,
|
||||
|
||||
//! Shift right logical operation.
|
||||
//!
|
||||
//! Available to all ARM architectures.
|
||||
kOpLSR = 0x01u,
|
||||
|
||||
//! Shift right arithmetic operation.
|
||||
//!
|
||||
//! Available to all ARM architectures.
|
||||
kOpASR = 0x02u,
|
||||
|
||||
//! Rotate right operation.
|
||||
//!
|
||||
//! \note Not available in AArch64 mode.
|
||||
kOpROR = 0x03u,
|
||||
|
||||
//! Rotate right with carry operation (encoded as `kShiftROR` with zero).
|
||||
//!
|
||||
//! \note Not available in AArch64 mode.
|
||||
kOpRRX = 0x04u,
|
||||
|
||||
//! Shift left by filling low order bits with ones.
|
||||
kOpMSL = 0x05u,
|
||||
|
||||
//! UXTN extend register operation (AArch64 only).
|
||||
kOpUXTB = 0x06u,
|
||||
//! UXTH extend register operation (AArch64 only).
|
||||
kOpUXTH = 0x07u,
|
||||
//! UXTW extend register operation (AArch64 only).
|
||||
kOpUXTW = 0x08u,
|
||||
//! UXTX extend register operation (AArch64 only).
|
||||
kOpUXTX = 0x09u,
|
||||
|
||||
//! SXTB extend register operation (AArch64 only).
|
||||
kOpSXTB = 0x0Au,
|
||||
//! SXTH extend register operation (AArch64 only).
|
||||
kOpSXTH = 0x0Bu,
|
||||
//! SXTW extend register operation (AArch64 only).
|
||||
kOpSXTW = 0x0Cu,
|
||||
//! SXTX extend register operation (AArch64 only).
|
||||
kOpSXTX = 0x0Du
|
||||
|
||||
// NOTE: 0xE and 0xF are used by memory operand to specify POST|PRE offset mode.
|
||||
};
|
||||
|
||||
//! Shift operation.
|
||||
uint32_t _op;
|
||||
//! Shift Value.
|
||||
uint32_t _value;
|
||||
|
||||
//! Default constructed Shift is not initialized.
|
||||
inline Shift() noexcept = default;
|
||||
|
||||
//! Copy constructor (default)
|
||||
constexpr Shift(const Shift& other) noexcept = default;
|
||||
|
||||
//! Constructs Shift from operation `op` and shift `value`.
|
||||
constexpr Shift(uint32_t op, uint32_t value) noexcept
|
||||
: _op(op),
|
||||
_value(value) {}
|
||||
|
||||
//! Returns the shift operation.
|
||||
constexpr uint32_t op() const noexcept { return _op; }
|
||||
//! Returns the shift smount.
|
||||
constexpr uint32_t value() const noexcept { return _value; }
|
||||
|
||||
//! Sets shift operation to `op`.
|
||||
inline void setOp(uint32_t op) noexcept { _op = op; }
|
||||
//! Sets shift amount to `value`.
|
||||
inline void setValue(uint32_t value) noexcept { _value = value; }
|
||||
};
|
||||
|
||||
//! Constructs a `LSL #value` shift (logical shift left).
|
||||
static constexpr Shift lsl(uint32_t value) noexcept { return Shift(Shift::kOpLSL, value); }
|
||||
//! Constructs a `LSR #value` shift (logical shift right).
|
||||
static constexpr Shift lsr(uint32_t value) noexcept { return Shift(Shift::kOpLSR, value); }
|
||||
//! Constructs a `ASR #value` shift (arithmetic shift right).
|
||||
static constexpr Shift asr(uint32_t value) noexcept { return Shift(Shift::kOpASR, value); }
|
||||
//! Constructs a `ROR #value` shift (rotate right).
|
||||
static constexpr Shift ror(uint32_t value) noexcept { return Shift(Shift::kOpROR, value); }
|
||||
//! Constructs a `RRX` shift (rotate with carry by 1).
|
||||
static constexpr Shift rrx() noexcept { return Shift(Shift::kOpRRX, 0); }
|
||||
//! Constructs a `MSL #value` shift (logical shift left filling ones).
|
||||
static constexpr Shift msl(uint32_t value) noexcept { return Shift(Shift::kOpMSL, value); }
|
||||
|
||||
//! Constructs a `UXTB #value` extend and shift (unsigned byte extend).
|
||||
static constexpr Shift uxtb(uint32_t value) noexcept { return Shift(Shift::kOpUXTB, value); }
|
||||
//! Constructs a `UXTH #value` extend and shift (unsigned hword extend).
|
||||
static constexpr Shift uxth(uint32_t value) noexcept { return Shift(Shift::kOpUXTH, value); }
|
||||
//! Constructs a `UXTW #value` extend and shift (unsigned word extend).
|
||||
static constexpr Shift uxtw(uint32_t value) noexcept { return Shift(Shift::kOpUXTW, value); }
|
||||
//! Constructs a `UXTX #value` extend and shift (unsigned dword extend).
|
||||
static constexpr Shift uxtx(uint32_t value) noexcept { return Shift(Shift::kOpUXTX, value); }
|
||||
|
||||
//! Constructs a `SXTB #value` extend and shift (signed byte extend).
|
||||
static constexpr Shift sxtb(uint32_t value) noexcept { return Shift(Shift::kOpSXTB, value); }
|
||||
//! Constructs a `SXTH #value` extend and shift (signed hword extend).
|
||||
static constexpr Shift sxth(uint32_t value) noexcept { return Shift(Shift::kOpSXTH, value); }
|
||||
//! Constructs a `SXTW #value` extend and shift (signed word extend).
|
||||
static constexpr Shift sxtw(uint32_t value) noexcept { return Shift(Shift::kOpSXTW, value); }
|
||||
//! Constructs a `SXTX #value` extend and shift (signed dword extend).
|
||||
static constexpr Shift sxtx(uint32_t value) noexcept { return Shift(Shift::kOpSXTX, value); }
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED
|
@ -0,0 +1,155 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#include "../core/archtraits.h"
|
||||
#include "../core/misc_p.h"
|
||||
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
#include "../x86/x86archtraits_p.h"
|
||||
#endif
|
||||
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
#include "../arm/armarchtraits_p.h"
|
||||
#endif
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ArchTraits]
|
||||
// ============================================================================
|
||||
|
||||
static const constexpr ArchTraits noArchTraits = {
|
||||
0xFF, // SP.
|
||||
0xFF, // FP.
|
||||
0xFF, // LR.
|
||||
0xFF, // PC.
|
||||
{ 0, 0, 0 }, // Reserved.
|
||||
0, // HW stack alignment.
|
||||
0, // Min stack offset.
|
||||
0, // Max stack offset.
|
||||
{ 0, 0, 0, 0}, // ISA features [Gp, Vec, Other0, Other1].
|
||||
{ { 0 } }, // RegTypeToSignature.
|
||||
{ 0 }, // RegTypeToTypeId.
|
||||
{ 0 } // TypeIdToRegType.
|
||||
};
|
||||
|
||||
ASMJIT_VARAPI const ArchTraits _archTraits[Environment::kArchCount] = {
|
||||
// No architecture.
|
||||
noArchTraits,
|
||||
|
||||
// X86/X86 architectures.
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
x86::x86ArchTraits,
|
||||
x86::x64ArchTraits,
|
||||
#else
|
||||
noArchTraits,
|
||||
noArchTraits,
|
||||
#endif
|
||||
|
||||
// RISCV32/RISCV64 architectures.
|
||||
noArchTraits,
|
||||
noArchTraits,
|
||||
|
||||
// ARM architecture
|
||||
noArchTraits,
|
||||
|
||||
// AArch64 architecture.
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
arm::a64ArchTraits,
|
||||
#else
|
||||
noArchTraits,
|
||||
#endif
|
||||
|
||||
// ARM/Thumb architecture.
|
||||
noArchTraits,
|
||||
|
||||
// Reserved.
|
||||
noArchTraits,
|
||||
|
||||
// MIPS32/MIPS64
|
||||
noArchTraits,
|
||||
noArchTraits
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ArchUtils]
|
||||
// ============================================================================
|
||||
|
||||
ASMJIT_FAVOR_SIZE Error ArchUtils::typeIdToRegInfo(uint32_t arch, uint32_t typeId, uint32_t* typeIdOut, RegInfo* regInfoOut) noexcept {
|
||||
const ArchTraits& archTraits = ArchTraits::byArch(arch);
|
||||
|
||||
// Passed RegType instead of TypeId?
|
||||
if (typeId <= BaseReg::kTypeMax)
|
||||
typeId = archTraits.regTypeToTypeId(typeId);
|
||||
|
||||
if (ASMJIT_UNLIKELY(!Type::isValid(typeId)))
|
||||
return DebugUtils::errored(kErrorInvalidTypeId);
|
||||
|
||||
// First normalize architecture dependent types.
|
||||
if (Type::isAbstract(typeId)) {
|
||||
bool is32Bit = Environment::is32Bit(arch);
|
||||
if (typeId == Type::kIdIntPtr)
|
||||
typeId = is32Bit ? Type::kIdI32 : Type::kIdI64;
|
||||
else
|
||||
typeId = is32Bit ? Type::kIdU32 : Type::kIdU64;
|
||||
}
|
||||
|
||||
// Type size helps to construct all groups of registers.
|
||||
// TypeId is invalid if the size is zero.
|
||||
uint32_t size = Type::sizeOf(typeId);
|
||||
if (ASMJIT_UNLIKELY(!size))
|
||||
return DebugUtils::errored(kErrorInvalidTypeId);
|
||||
|
||||
if (ASMJIT_UNLIKELY(typeId == Type::kIdF80))
|
||||
return DebugUtils::errored(kErrorInvalidUseOfF80);
|
||||
|
||||
uint32_t regType = 0;
|
||||
if (typeId >= Type::_kIdBaseStart && typeId < Type::_kIdVec32Start) {
|
||||
regType = archTraits._typeIdToRegType[typeId - Type::_kIdBaseStart];
|
||||
if (!regType) {
|
||||
if (typeId == Type::kIdI64 || typeId == Type::kIdU64)
|
||||
return DebugUtils::errored(kErrorInvalidUseOfGpq);
|
||||
else
|
||||
return DebugUtils::errored(kErrorInvalidTypeId);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (size <= 8 && archTraits._regInfo[BaseReg::kTypeVec64].isValid())
|
||||
regType = BaseReg::kTypeVec64;
|
||||
else if (size <= 16 && archTraits._regInfo[BaseReg::kTypeVec128].isValid())
|
||||
regType = BaseReg::kTypeVec128;
|
||||
else if (size == 32 && archTraits._regInfo[BaseReg::kTypeVec256].isValid())
|
||||
regType = BaseReg::kTypeVec256;
|
||||
else if (archTraits._regInfo[BaseReg::kTypeVec512].isValid())
|
||||
regType = BaseReg::kTypeVec512;
|
||||
else
|
||||
return DebugUtils::errored(kErrorInvalidTypeId);
|
||||
}
|
||||
|
||||
*typeIdOut = typeId;
|
||||
regInfoOut->reset(archTraits.regTypeToSignature(regType));
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
@ -0,0 +1,174 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_ARCHTRAITS_H_INCLUDED
|
||||
#define ASMJIT_CORE_ARCHTRAITS_H_INCLUDED
|
||||
|
||||
#include "../core/environment.h"
|
||||
#include "../core/operand.h"
|
||||
#include "../core/type.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
//! \addtogroup asmjit_core
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ArchTraits]
|
||||
// ============================================================================
|
||||
|
||||
//! Architecture traits used by Function API and Compiler's register allocator.
|
||||
struct ArchTraits {
|
||||
//! ISA features for each register group.
|
||||
enum IsaFeatures : uint32_t {
|
||||
//! ISA features a register swap by using a single instruction.
|
||||
kIsaFeatureSwap = 0x01u,
|
||||
//! ISA features a push/pop like instruction for this register group.
|
||||
kIsaFeaturePushPop = 0x02u,
|
||||
};
|
||||
|
||||
//! Stack pointer register id.
|
||||
uint8_t _spRegId;
|
||||
//! Frame pointer register id.
|
||||
uint8_t _fpRegId;
|
||||
//! Link register id.
|
||||
uint8_t _linkRegId;
|
||||
//! Instruction pointer (or program counter) register id, if accessible.
|
||||
uint8_t _ipRegId;
|
||||
|
||||
// Reserved.
|
||||
uint8_t _reserved[3];
|
||||
//! Hardware stack alignment requirement.
|
||||
uint8_t _hwStackAlignment;
|
||||
//! Minimum addressable offset on stack guaranteed for all instructions.
|
||||
uint32_t _minStackOffset;
|
||||
//! Maximum addressable offset on stack depending on specific instruction.
|
||||
uint32_t _maxStackOffset;
|
||||
|
||||
//! Flags for each virtual register group (always covers GP and Vec groups).
|
||||
uint8_t _isaFlags[BaseReg::kGroupVirt];
|
||||
|
||||
//! Maps register type into a signature, that provides group, size and can
|
||||
//! be used to construct register operands.
|
||||
RegInfo _regInfo[BaseReg::kTypeMax + 1];
|
||||
//! Maps a register to type-id, see \ref Type::Id.
|
||||
uint8_t _regTypeToTypeId[BaseReg::kTypeMax + 1];
|
||||
//! Maps base TypeId values (from TypeId::_kIdBaseStart) to register types, see \ref Type::Id.
|
||||
uint8_t _typeIdToRegType[32];
|
||||
|
||||
//! Resets all members to zeros.
|
||||
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
//! Returns stack pointer register id.
|
||||
inline constexpr uint32_t spRegId() const noexcept { return _spRegId; }
|
||||
//! Returns stack frame register id.
|
||||
inline constexpr uint32_t fpRegId() const noexcept { return _fpRegId; }
|
||||
//! Returns link register id, if the architecture provides it.
|
||||
inline constexpr uint32_t linkRegId() const noexcept { return _linkRegId; }
|
||||
//! Returns instruction pointer register id, if the architecture provides it.
|
||||
inline constexpr uint32_t ipRegId() const noexcept { return _ipRegId; }
|
||||
|
||||
//! Returns a hardware stack alignment requirement.
|
||||
//!
|
||||
//! \note This is a hardware constraint. Architectures that don't constrain
|
||||
//! it would return the lowest alignment (1), however, some architectures may
|
||||
//! constrain the alignment, for example AArch64 requires 16-byte alignment.
|
||||
inline constexpr uint32_t hwStackAlignment() const noexcept { return _hwStackAlignment; }
|
||||
|
||||
//! Tests whether the architecture provides link register, which is used across
|
||||
//! function calls. If the link register is not provided then a function call
|
||||
//! pushes the return address on stack (X86/X64).
|
||||
inline constexpr bool hasLinkReg() const noexcept { return _linkRegId != BaseReg::kIdBad; }
|
||||
|
||||
//! Returns minimum addressable offset on stack guaranteed for all instructions.
|
||||
inline constexpr uint32_t minStackOffset() const noexcept { return _minStackOffset; }
|
||||
//! Returns maximum addressable offset on stack depending on specific instruction.
|
||||
inline constexpr uint32_t maxStackOffset() const noexcept { return _maxStackOffset; }
|
||||
|
||||
//! Returns ISA flags of the given register `group`.
|
||||
inline constexpr uint32_t isaFlags(uint32_t group) const noexcept { return _isaFlags[group]; }
|
||||
//! Tests whether the given register `group` has the given `flag` set.
|
||||
inline constexpr bool hasIsaFlag(uint32_t group, uint32_t flag) const noexcept { return (_isaFlags[group] & flag) != 0; }
|
||||
//! Tests whether the ISA provides register swap instruction for the given register `group`.
|
||||
inline constexpr bool hasSwap(uint32_t group) const noexcept { return hasIsaFlag(group, kIsaFeatureSwap); }
|
||||
//! Tests whether the ISA provides push/pop instructions for the given register `group`.
|
||||
inline constexpr bool hasPushPop(uint32_t group) const noexcept { return hasIsaFlag(group, kIsaFeaturePushPop); }
|
||||
|
||||
inline uint32_t hasRegType(uint32_t rType) const noexcept {
|
||||
return rType <= BaseReg::kTypeMax && _regInfo[rType].signature() != 0;
|
||||
}
|
||||
|
||||
inline uint32_t regTypeToSignature(uint32_t rType) const noexcept {
|
||||
ASMJIT_ASSERT(rType <= BaseReg::kTypeMax);
|
||||
return _regInfo[rType].signature();
|
||||
}
|
||||
|
||||
inline uint32_t regTypeToGroup(uint32_t rType) const noexcept {
|
||||
ASMJIT_ASSERT(rType <= BaseReg::kTypeMax);
|
||||
return _regInfo[rType].group();
|
||||
}
|
||||
|
||||
inline uint32_t regTypeToSize(uint32_t rType) const noexcept {
|
||||
ASMJIT_ASSERT(rType <= BaseReg::kTypeMax);
|
||||
return _regInfo[rType].size();
|
||||
}
|
||||
|
||||
inline uint32_t regTypeToTypeId(uint32_t rType) const noexcept {
|
||||
ASMJIT_ASSERT(rType <= BaseReg::kTypeMax);
|
||||
return _regTypeToTypeId[rType];
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Statics
|
||||
//! \{
|
||||
|
||||
//! Returns a const reference to `ArchTraits` for the given architecture `arch`.
|
||||
static inline const ArchTraits& byArch(uint32_t arch) noexcept;
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
ASMJIT_VARAPI const ArchTraits _archTraits[Environment::kArchCount];
|
||||
|
||||
inline const ArchTraits& ArchTraits::byArch(uint32_t arch) noexcept { return _archTraits[arch & ~Environment::kArchBigEndianMask]; }
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ArchUtils]
|
||||
// ============================================================================
|
||||
|
||||
//! Architecture utilities.
|
||||
namespace ArchUtils {
|
||||
|
||||
ASMJIT_API Error typeIdToRegInfo(uint32_t arch, uint32_t typeId, uint32_t* typeIdOut, RegInfo* regInfo) noexcept;
|
||||
|
||||
} // {ArchUtils}
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_ARCHTRAITS_H_INCLUDED
|
@ -0,0 +1,409 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#include "../core/assembler.h"
|
||||
#include "../core/codewriter_p.h"
|
||||
#include "../core/constpool.h"
|
||||
#include "../core/emitterutils_p.h"
|
||||
#include "../core/formatter.h"
|
||||
#include "../core/logger.h"
|
||||
#include "../core/support.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseAssembler - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
BaseAssembler::BaseAssembler() noexcept
|
||||
: BaseEmitter(kTypeAssembler) {}
|
||||
|
||||
BaseAssembler::~BaseAssembler() noexcept {}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseAssembler - Buffer Management]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseAssembler::setOffset(size_t offset) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
|
||||
size_t size = Support::max<size_t>(_section->bufferSize(), this->offset());
|
||||
if (ASMJIT_UNLIKELY(offset > size))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidArgument));
|
||||
|
||||
_bufferPtr = _bufferData + offset;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseAssembler - Section Management]
|
||||
// ============================================================================
|
||||
|
||||
static void BaseAssembler_initSection(BaseAssembler* self, Section* section) noexcept {
|
||||
uint8_t* p = section->_buffer._data;
|
||||
|
||||
self->_section = section;
|
||||
self->_bufferData = p;
|
||||
self->_bufferPtr = p + section->_buffer._size;
|
||||
self->_bufferEnd = p + section->_buffer._capacity;
|
||||
}
|
||||
|
||||
Error BaseAssembler::section(Section* section) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
|
||||
if (!_code->isSectionValid(section->id()) || _code->_sections[section->id()] != section)
|
||||
return reportError(DebugUtils::errored(kErrorInvalidSection));
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger)
|
||||
_logger->logf(".section %s {#%u}\n", section->name(), section->id());
|
||||
#endif
|
||||
|
||||
BaseAssembler_initSection(this, section);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseAssembler - Label Management]
|
||||
// ============================================================================
|
||||
|
||||
Label BaseAssembler::newLabel() {
|
||||
uint32_t labelId = Globals::kInvalidId;
|
||||
if (ASMJIT_LIKELY(_code)) {
|
||||
LabelEntry* le;
|
||||
Error err = _code->newLabelEntry(&le);
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
reportError(err);
|
||||
else
|
||||
labelId = le->id();
|
||||
}
|
||||
return Label(labelId);
|
||||
}
|
||||
|
||||
Label BaseAssembler::newNamedLabel(const char* name, size_t nameSize, uint32_t type, uint32_t parentId) {
|
||||
uint32_t labelId = Globals::kInvalidId;
|
||||
if (ASMJIT_LIKELY(_code)) {
|
||||
LabelEntry* le;
|
||||
Error err = _code->newNamedLabelEntry(&le, name, nameSize, type, parentId);
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
reportError(err);
|
||||
else
|
||||
labelId = le->id();
|
||||
}
|
||||
return Label(labelId);
|
||||
}
|
||||
|
||||
Error BaseAssembler::bind(const Label& label) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
|
||||
Error err = _code->bindLabel(label, _section->id(), offset());
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger)
|
||||
EmitterUtils::logLabelBound(this, label);
|
||||
#endif
|
||||
|
||||
resetInlineComment();
|
||||
if (err)
|
||||
return reportError(err);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseAssembler - Embed]
|
||||
// ============================================================================
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
struct DataSizeByPower {
|
||||
char str[4];
|
||||
};
|
||||
|
||||
static const DataSizeByPower dataSizeByPowerTable[] = {
|
||||
{ "db" },
|
||||
{ "dw" },
|
||||
{ "dd" },
|
||||
{ "dq" }
|
||||
};
|
||||
#endif
|
||||
|
||||
Error BaseAssembler::embed(const void* data, size_t dataSize) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
|
||||
if (dataSize == 0)
|
||||
return kErrorOk;
|
||||
|
||||
CodeWriter writer(this);
|
||||
ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
|
||||
|
||||
writer.emitData(data, dataSize);
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger)
|
||||
_logger->logBinary(data, dataSize);
|
||||
#endif
|
||||
|
||||
writer.done(this);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseAssembler::embedDataArray(uint32_t typeId, const void* data, size_t itemCcount, size_t repeatCount) {
|
||||
uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize());
|
||||
uint32_t finalTypeId = Type::deabstract(typeId, deabstractDelta);
|
||||
|
||||
if (ASMJIT_UNLIKELY(!Type::isValid(finalTypeId)))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidArgument));
|
||||
|
||||
if (itemCcount == 0 || repeatCount == 0)
|
||||
return kErrorOk;
|
||||
|
||||
uint32_t typeSize = Type::sizeOf(finalTypeId);
|
||||
Support::FastUInt8 of = 0;
|
||||
|
||||
size_t dataSize = Support::mulOverflow(itemCcount, size_t(typeSize), &of);
|
||||
size_t totalSize = Support::mulOverflow(dataSize, repeatCount, &of);
|
||||
|
||||
if (ASMJIT_UNLIKELY(of))
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
|
||||
CodeWriter writer(this);
|
||||
ASMJIT_PROPAGATE(writer.ensureSpace(this, totalSize));
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
const uint8_t* start = writer.cursor();
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < repeatCount; i++) {
|
||||
writer.emitData(data, dataSize);
|
||||
}
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger)
|
||||
_logger->logBinary(start, totalSize);
|
||||
#endif
|
||||
|
||||
writer.done(this);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseAssembler::embedConstPool(const Label& label, const ConstPool& pool) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
|
||||
if (ASMJIT_UNLIKELY(!isLabelValid(label)))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidLabel));
|
||||
|
||||
ASMJIT_PROPAGATE(align(kAlignData, uint32_t(pool.alignment())));
|
||||
ASMJIT_PROPAGATE(bind(label));
|
||||
|
||||
size_t size = pool.size();
|
||||
CodeWriter writer(this);
|
||||
ASMJIT_PROPAGATE(writer.ensureSpace(this, size));
|
||||
|
||||
pool.fill(writer.cursor());
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger)
|
||||
_logger->logBinary(writer.cursor(), size);
|
||||
#endif
|
||||
|
||||
writer.advance(size);
|
||||
writer.done(this);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseAssembler::embedLabel(const Label& label, size_t dataSize) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
|
||||
ASMJIT_ASSERT(_code != nullptr);
|
||||
RelocEntry* re;
|
||||
LabelEntry* le = _code->labelEntry(label);
|
||||
|
||||
if (ASMJIT_UNLIKELY(!le))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidLabel));
|
||||
|
||||
if (dataSize == 0)
|
||||
dataSize = registerSize();
|
||||
|
||||
if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidOperandSize));
|
||||
|
||||
CodeWriter writer(this);
|
||||
ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger) {
|
||||
StringTmp<256> sb;
|
||||
sb.appendFormat("%s ", dataSizeByPowerTable[Support::ctz(dataSize)].str);
|
||||
Formatter::formatLabel(sb, 0, this, label.id());
|
||||
sb.append('\n');
|
||||
_logger->log(sb);
|
||||
}
|
||||
#endif
|
||||
|
||||
Error err = _code->newRelocEntry(&re, RelocEntry::kTypeRelToAbs);
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
return reportError(err);
|
||||
|
||||
re->_sourceSectionId = _section->id();
|
||||
re->_sourceOffset = offset();
|
||||
re->_format.resetToDataValue(uint32_t(dataSize));
|
||||
|
||||
if (le->isBound()) {
|
||||
re->_targetSectionId = le->section()->id();
|
||||
re->_payload = le->offset();
|
||||
}
|
||||
else {
|
||||
OffsetFormat of;
|
||||
of.resetToDataValue(uint32_t(dataSize));
|
||||
|
||||
LabelLink* link = _code->newLabelLink(le, _section->id(), offset(), 0, of);
|
||||
if (ASMJIT_UNLIKELY(!link))
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
|
||||
link->relocId = re->id();
|
||||
}
|
||||
|
||||
// Emit dummy DWORD/QWORD depending on the data size.
|
||||
writer.emitZeros(dataSize);
|
||||
writer.done(this);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
|
||||
LabelEntry* labelEntry = _code->labelEntry(label);
|
||||
LabelEntry* baseEntry = _code->labelEntry(base);
|
||||
|
||||
if (ASMJIT_UNLIKELY(!labelEntry || !baseEntry))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidLabel));
|
||||
|
||||
if (dataSize == 0)
|
||||
dataSize = registerSize();
|
||||
|
||||
if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidOperandSize));
|
||||
|
||||
CodeWriter writer(this);
|
||||
ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger) {
|
||||
StringTmp<256> sb;
|
||||
sb.appendFormat(".%s (", dataSizeByPowerTable[Support::ctz(dataSize)].str);
|
||||
Formatter::formatLabel(sb, 0, this, label.id());
|
||||
sb.append(" - ");
|
||||
Formatter::formatLabel(sb, 0, this, base.id());
|
||||
sb.append(")\n");
|
||||
_logger->log(sb);
|
||||
}
|
||||
#endif
|
||||
|
||||
// If both labels are bound within the same section it means the delta can be calculated now.
|
||||
if (labelEntry->isBound() && baseEntry->isBound() && labelEntry->section() == baseEntry->section()) {
|
||||
uint64_t delta = labelEntry->offset() - baseEntry->offset();
|
||||
writer.emitValueLE(delta, dataSize);
|
||||
}
|
||||
else {
|
||||
RelocEntry* re;
|
||||
Error err = _code->newRelocEntry(&re, RelocEntry::kTypeExpression);
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
return reportError(err);
|
||||
|
||||
Expression* exp = _code->_zone.newT<Expression>();
|
||||
if (ASMJIT_UNLIKELY(!exp))
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
|
||||
exp->reset();
|
||||
exp->opType = Expression::kOpSub;
|
||||
exp->setValueAsLabel(0, labelEntry);
|
||||
exp->setValueAsLabel(1, baseEntry);
|
||||
|
||||
re->_format.resetToDataValue(dataSize);
|
||||
re->_sourceSectionId = _section->id();
|
||||
re->_sourceOffset = offset();
|
||||
re->_payload = (uint64_t)(uintptr_t)exp;
|
||||
|
||||
writer.emitZeros(dataSize);
|
||||
}
|
||||
|
||||
writer.done(this);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseAssembler - Comment]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseAssembler::comment(const char* data, size_t size) {
|
||||
if (!hasEmitterFlag(kFlagLogComments)) {
|
||||
if (!hasEmitterFlag(kFlagAttached))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
// Logger cannot be NULL if `kFlagLogComments` is set.
|
||||
ASMJIT_ASSERT(_logger != nullptr);
|
||||
|
||||
_logger->log(data, size);
|
||||
_logger->log("\n", 1);
|
||||
return kErrorOk;
|
||||
#else
|
||||
DebugUtils::unused(data, size);
|
||||
return kErrorOk;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseAssembler - Events]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseAssembler::onAttach(CodeHolder* code) noexcept {
|
||||
ASMJIT_PROPAGATE(Base::onAttach(code));
|
||||
|
||||
// Attach to the end of the .text section.
|
||||
BaseAssembler_initSection(this, code->_sections[0]);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseAssembler::onDetach(CodeHolder* code) noexcept {
|
||||
_section = nullptr;
|
||||
_bufferData = nullptr;
|
||||
_bufferEnd = nullptr;
|
||||
_bufferPtr = nullptr;
|
||||
return Base::onDetach(code);
|
||||
}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
@ -0,0 +1,152 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_ASSEMBLER_H_INCLUDED
|
||||
#define ASMJIT_CORE_ASSEMBLER_H_INCLUDED
|
||||
|
||||
#include "../core/codeholder.h"
|
||||
#include "../core/datatypes.h"
|
||||
#include "../core/emitter.h"
|
||||
#include "../core/operand.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
//! \addtogroup asmjit_assembler
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseAssembler]
|
||||
// ============================================================================
|
||||
|
||||
//! Base assembler.
|
||||
//!
|
||||
//! This is a base class that provides interface used by architecture specific
|
||||
//! assembler implementations. Assembler doesn't hold any data, instead it's
|
||||
//! attached to \ref CodeHolder, which provides all the data that Assembler
|
||||
//! needs and which can be altered by it.
|
||||
//!
|
||||
//! Check out architecture specific assemblers for more details and examples:
|
||||
//!
|
||||
//! - \ref x86::Assembler - X86/X64 assembler implementation.
|
||||
class ASMJIT_VIRTAPI BaseAssembler : public BaseEmitter {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(BaseAssembler)
|
||||
typedef BaseEmitter Base;
|
||||
|
||||
//! Current section where the assembling happens.
|
||||
Section* _section = nullptr;
|
||||
//! Start of the CodeBuffer of the current section.
|
||||
uint8_t* _bufferData = nullptr;
|
||||
//! End (first invalid byte) of the current section.
|
||||
uint8_t* _bufferEnd = nullptr;
|
||||
//! Pointer in the CodeBuffer of the current section.
|
||||
uint8_t* _bufferPtr = nullptr;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
//! Creates a new `BaseAssembler` instance.
|
||||
ASMJIT_API BaseAssembler() noexcept;
|
||||
//! Destroys the `BaseAssembler` instance.
|
||||
ASMJIT_API virtual ~BaseAssembler() noexcept;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Code-Buffer Management
|
||||
//! \{
|
||||
|
||||
//! Returns the capacity of the current CodeBuffer.
|
||||
inline size_t bufferCapacity() const noexcept { return (size_t)(_bufferEnd - _bufferData); }
|
||||
//! Returns the number of remaining bytes in the current CodeBuffer.
|
||||
inline size_t remainingSpace() const noexcept { return (size_t)(_bufferEnd - _bufferPtr); }
|
||||
|
||||
//! Returns the current position in the CodeBuffer.
|
||||
inline size_t offset() const noexcept { return (size_t)(_bufferPtr - _bufferData); }
|
||||
|
||||
//! Sets the current position in the CodeBuffer to `offset`.
|
||||
//!
|
||||
//! \note The `offset` cannot be greater than buffer size even if it's
|
||||
//! within the buffer's capacity.
|
||||
ASMJIT_API Error setOffset(size_t offset);
|
||||
|
||||
//! Returns the start of the CodeBuffer in the current section.
|
||||
inline uint8_t* bufferData() const noexcept { return _bufferData; }
|
||||
//! Returns the end (first invalid byte) in the current section.
|
||||
inline uint8_t* bufferEnd() const noexcept { return _bufferEnd; }
|
||||
//! Returns the current pointer in the CodeBuffer in the current section.
|
||||
inline uint8_t* bufferPtr() const noexcept { return _bufferPtr; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Section Management
|
||||
//! \{
|
||||
|
||||
//! Returns the current section.
|
||||
inline Section* currentSection() const noexcept { return _section; }
|
||||
|
||||
ASMJIT_API Error section(Section* section) override;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Label Management
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Label newLabel() override;
|
||||
ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, uint32_t type = Label::kTypeGlobal, uint32_t parentId = Globals::kInvalidId) override;
|
||||
ASMJIT_API Error bind(const Label& label) override;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Embed
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error embed(const void* data, size_t dataSize) override;
|
||||
ASMJIT_API Error embedDataArray(uint32_t typeId, const void* data, size_t itemCcount, size_t repeatCount = 1) override;
|
||||
ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override;
|
||||
|
||||
ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override;
|
||||
ASMJIT_API Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) override;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Comment
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error comment(const char* data, size_t size = SIZE_MAX) override;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Events
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error onAttach(CodeHolder* code) noexcept override;
|
||||
ASMJIT_API Error onDetach(CodeHolder* code) noexcept override;
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_ASSEMBLER_H_INCLUDED
|
@ -0,0 +1,920 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#ifndef ASMJIT_NO_BUILDER
|
||||
|
||||
#include "../core/builder.h"
|
||||
#include "../core/emitterutils_p.h"
|
||||
#include "../core/errorhandler.h"
|
||||
#include "../core/formatter.h"
|
||||
#include "../core/logger.h"
|
||||
#include "../core/support.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::PostponedErrorHandler (Internal)]
|
||||
// ============================================================================
|
||||
|
||||
//! Postponed error handler that never throws. Used as a temporal error handler
|
||||
//! to run passes. If error occurs, the caller is notified and will call the
|
||||
//! real error handler, that can throw.
|
||||
class PostponedErrorHandler : public ErrorHandler {
|
||||
public:
|
||||
void handleError(Error err, const char* message, BaseEmitter* origin) override {
|
||||
DebugUtils::unused(err, origin);
|
||||
_message.assign(message);
|
||||
}
|
||||
|
||||
StringTmp<128> _message;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Utilities]
|
||||
// ============================================================================
|
||||
|
||||
static void BaseBuilder_deletePasses(BaseBuilder* self) noexcept {
|
||||
for (Pass* pass : self->_passes)
|
||||
pass->~Pass();
|
||||
self->_passes.reset();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
BaseBuilder::BaseBuilder() noexcept
|
||||
: BaseEmitter(kTypeBuilder),
|
||||
_codeZone(32768 - Zone::kBlockOverhead),
|
||||
_dataZone(16384 - Zone::kBlockOverhead),
|
||||
_passZone(65536 - Zone::kBlockOverhead),
|
||||
_allocator(&_codeZone) {}
|
||||
|
||||
BaseBuilder::~BaseBuilder() noexcept {
|
||||
BaseBuilder_deletePasses(this);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Node Management]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseBuilder::_newInstNode(InstNode** out, uint32_t instId, uint32_t instOptions, uint32_t opCount) {
|
||||
uint32_t opCapacity = InstNode::capacityOfOpCount(opCount);
|
||||
ASMJIT_ASSERT(opCapacity >= InstNode::kBaseOpCapacity);
|
||||
|
||||
InstNode* node = _allocator.allocT<InstNode>(InstNode::nodeSizeOfOpCapacity(opCapacity));
|
||||
if (ASMJIT_UNLIKELY(!node))
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
|
||||
*out = new(node) InstNode(this, instId, instOptions, opCount, opCapacity);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
|
||||
Error BaseBuilder::_newLabelNode(LabelNode** out) {
|
||||
*out = nullptr;
|
||||
|
||||
ASMJIT_PROPAGATE(_newNodeT<LabelNode>(out));
|
||||
return registerLabelNode(*out);
|
||||
}
|
||||
|
||||
Error BaseBuilder::_newAlignNode(AlignNode** out, uint32_t alignMode, uint32_t alignment) {
|
||||
*out = nullptr;
|
||||
return _newNodeT<AlignNode>(out, alignMode, alignment);
|
||||
}
|
||||
|
||||
Error BaseBuilder::_newEmbedDataNode(EmbedDataNode** out, uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount) {
|
||||
*out = nullptr;
|
||||
|
||||
uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize());
|
||||
uint32_t finalTypeId = Type::deabstract(typeId, deabstractDelta);
|
||||
|
||||
if (ASMJIT_UNLIKELY(!Type::isValid(finalTypeId)))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidArgument));
|
||||
|
||||
uint32_t typeSize = Type::sizeOf(finalTypeId);
|
||||
Support::FastUInt8 of = 0;
|
||||
|
||||
size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of);
|
||||
if (ASMJIT_UNLIKELY(of))
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
|
||||
EmbedDataNode* node;
|
||||
ASMJIT_PROPAGATE(_newNodeT<EmbedDataNode>(&node));
|
||||
|
||||
node->_embed._typeId = uint8_t(typeId);
|
||||
node->_embed._typeSize = uint8_t(typeSize);
|
||||
node->_itemCount = itemCount;
|
||||
node->_repeatCount = repeatCount;
|
||||
|
||||
uint8_t* dstData = node->_inlineData;
|
||||
if (dataSize > EmbedDataNode::kInlineBufferSize) {
|
||||
dstData = static_cast<uint8_t*>(_dataZone.alloc(dataSize, 8));
|
||||
if (ASMJIT_UNLIKELY(!dstData))
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
node->_externalData = dstData;
|
||||
}
|
||||
|
||||
if (data)
|
||||
memcpy(dstData, data, dataSize);
|
||||
|
||||
*out = node;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseBuilder::_newConstPoolNode(ConstPoolNode** out) {
|
||||
*out = nullptr;
|
||||
|
||||
ASMJIT_PROPAGATE(_newNodeT<ConstPoolNode>(out));
|
||||
return registerLabelNode(*out);
|
||||
}
|
||||
|
||||
Error BaseBuilder::_newCommentNode(CommentNode** out, const char* data, size_t size) {
|
||||
*out = nullptr;
|
||||
|
||||
if (data) {
|
||||
if (size == SIZE_MAX)
|
||||
size = strlen(data);
|
||||
|
||||
if (size > 0) {
|
||||
data = static_cast<char*>(_dataZone.dup(data, size, true));
|
||||
if (ASMJIT_UNLIKELY(!data))
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
}
|
||||
}
|
||||
|
||||
return _newNodeT<CommentNode>(out, data);
|
||||
}
|
||||
|
||||
BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept {
|
||||
ASMJIT_ASSERT(node);
|
||||
ASMJIT_ASSERT(!node->_prev);
|
||||
ASMJIT_ASSERT(!node->_next);
|
||||
ASMJIT_ASSERT(!node->isActive());
|
||||
|
||||
if (!_cursor) {
|
||||
if (!_firstNode) {
|
||||
_firstNode = node;
|
||||
_lastNode = node;
|
||||
}
|
||||
else {
|
||||
node->_next = _firstNode;
|
||||
_firstNode->_prev = node;
|
||||
_firstNode = node;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BaseNode* prev = _cursor;
|
||||
BaseNode* next = _cursor->next();
|
||||
|
||||
node->_prev = prev;
|
||||
node->_next = next;
|
||||
|
||||
prev->_next = node;
|
||||
if (next)
|
||||
next->_prev = node;
|
||||
else
|
||||
_lastNode = node;
|
||||
}
|
||||
|
||||
node->addFlags(BaseNode::kFlagIsActive);
|
||||
if (node->isSection())
|
||||
_dirtySectionLinks = true;
|
||||
|
||||
_cursor = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
BaseNode* BaseBuilder::addAfter(BaseNode* node, BaseNode* ref) noexcept {
|
||||
ASMJIT_ASSERT(node);
|
||||
ASMJIT_ASSERT(ref);
|
||||
|
||||
ASMJIT_ASSERT(!node->_prev);
|
||||
ASMJIT_ASSERT(!node->_next);
|
||||
|
||||
BaseNode* prev = ref;
|
||||
BaseNode* next = ref->next();
|
||||
|
||||
node->_prev = prev;
|
||||
node->_next = next;
|
||||
|
||||
node->addFlags(BaseNode::kFlagIsActive);
|
||||
if (node->isSection())
|
||||
_dirtySectionLinks = true;
|
||||
|
||||
prev->_next = node;
|
||||
if (next)
|
||||
next->_prev = node;
|
||||
else
|
||||
_lastNode = node;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
BaseNode* BaseBuilder::addBefore(BaseNode* node, BaseNode* ref) noexcept {
|
||||
ASMJIT_ASSERT(node != nullptr);
|
||||
ASMJIT_ASSERT(!node->_prev);
|
||||
ASMJIT_ASSERT(!node->_next);
|
||||
ASMJIT_ASSERT(!node->isActive());
|
||||
ASMJIT_ASSERT(ref != nullptr);
|
||||
ASMJIT_ASSERT(ref->isActive());
|
||||
|
||||
BaseNode* prev = ref->prev();
|
||||
BaseNode* next = ref;
|
||||
|
||||
node->_prev = prev;
|
||||
node->_next = next;
|
||||
|
||||
node->addFlags(BaseNode::kFlagIsActive);
|
||||
if (node->isSection())
|
||||
_dirtySectionLinks = true;
|
||||
|
||||
next->_prev = node;
|
||||
if (prev)
|
||||
prev->_next = node;
|
||||
else
|
||||
_firstNode = node;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
BaseNode* BaseBuilder::removeNode(BaseNode* node) noexcept {
|
||||
if (!node->isActive())
|
||||
return node;
|
||||
|
||||
BaseNode* prev = node->prev();
|
||||
BaseNode* next = node->next();
|
||||
|
||||
if (_firstNode == node)
|
||||
_firstNode = next;
|
||||
else
|
||||
prev->_next = next;
|
||||
|
||||
if (_lastNode == node)
|
||||
_lastNode = prev;
|
||||
else
|
||||
next->_prev = prev;
|
||||
|
||||
node->_prev = nullptr;
|
||||
node->_next = nullptr;
|
||||
node->clearFlags(BaseNode::kFlagIsActive);
|
||||
if (node->isSection())
|
||||
_dirtySectionLinks = true;
|
||||
|
||||
if (_cursor == node)
|
||||
_cursor = prev;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void BaseBuilder::removeNodes(BaseNode* first, BaseNode* last) noexcept {
|
||||
if (first == last) {
|
||||
removeNode(first);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!first->isActive())
|
||||
return;
|
||||
|
||||
BaseNode* prev = first->prev();
|
||||
BaseNode* next = last->next();
|
||||
|
||||
if (_firstNode == first)
|
||||
_firstNode = next;
|
||||
else
|
||||
prev->_next = next;
|
||||
|
||||
if (_lastNode == last)
|
||||
_lastNode = prev;
|
||||
else
|
||||
next->_prev = prev;
|
||||
|
||||
BaseNode* node = first;
|
||||
uint32_t didRemoveSection = false;
|
||||
|
||||
for (;;) {
|
||||
next = node->next();
|
||||
ASMJIT_ASSERT(next != nullptr);
|
||||
|
||||
node->_prev = nullptr;
|
||||
node->_next = nullptr;
|
||||
node->clearFlags(BaseNode::kFlagIsActive);
|
||||
didRemoveSection |= uint32_t(node->isSection());
|
||||
|
||||
if (_cursor == node)
|
||||
_cursor = prev;
|
||||
|
||||
if (node == last)
|
||||
break;
|
||||
node = next;
|
||||
}
|
||||
|
||||
if (didRemoveSection)
|
||||
_dirtySectionLinks = true;
|
||||
}
|
||||
|
||||
BaseNode* BaseBuilder::setCursor(BaseNode* node) noexcept {
|
||||
BaseNode* old = _cursor;
|
||||
_cursor = node;
|
||||
return old;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Section]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseBuilder::sectionNodeOf(SectionNode** out, uint32_t sectionId) {
|
||||
*out = nullptr;
|
||||
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
if (ASMJIT_UNLIKELY(!_code->isSectionValid(sectionId)))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidSection));
|
||||
|
||||
if (sectionId >= _sectionNodes.size()) {
|
||||
Error err = _sectionNodes.reserve(&_allocator, sectionId + 1);
|
||||
if (ASMJIT_UNLIKELY(err != kErrorOk))
|
||||
return reportError(err);
|
||||
}
|
||||
|
||||
SectionNode* node = nullptr;
|
||||
if (sectionId < _sectionNodes.size())
|
||||
node = _sectionNodes[sectionId];
|
||||
|
||||
if (!node) {
|
||||
ASMJIT_PROPAGATE(_newNodeT<SectionNode>(&node, sectionId));
|
||||
|
||||
// We have already reserved enough space, this cannot fail now.
|
||||
if (sectionId >= _sectionNodes.size())
|
||||
_sectionNodes.resize(&_allocator, sectionId + 1);
|
||||
|
||||
_sectionNodes[sectionId] = node;
|
||||
}
|
||||
|
||||
*out = node;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseBuilder::section(Section* section) {
|
||||
SectionNode* node;
|
||||
ASMJIT_PROPAGATE(sectionNodeOf(&node, section->id()));
|
||||
|
||||
if (!node->isActive()) {
|
||||
// Insert the section at the end if it was not part of the code.
|
||||
addAfter(node, lastNode());
|
||||
_cursor = node;
|
||||
}
|
||||
else {
|
||||
// This is a bit tricky. We cache section links to make sure that
|
||||
// switching sections doesn't involve traversal in linked-list unless
|
||||
// the position of the section has changed.
|
||||
if (hasDirtySectionLinks())
|
||||
updateSectionLinks();
|
||||
|
||||
if (node->_nextSection)
|
||||
_cursor = node->_nextSection->_prev;
|
||||
else
|
||||
_cursor = _lastNode;
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
void BaseBuilder::updateSectionLinks() noexcept {
|
||||
if (!_dirtySectionLinks)
|
||||
return;
|
||||
|
||||
BaseNode* node_ = _firstNode;
|
||||
SectionNode* currentSection = nullptr;
|
||||
|
||||
while (node_) {
|
||||
if (node_->isSection()) {
|
||||
if (currentSection)
|
||||
currentSection->_nextSection = node_->as<SectionNode>();
|
||||
currentSection = node_->as<SectionNode>();
|
||||
}
|
||||
node_ = node_->next();
|
||||
}
|
||||
|
||||
if (currentSection)
|
||||
currentSection->_nextSection = nullptr;
|
||||
|
||||
_dirtySectionLinks = false;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Labels]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseBuilder::labelNodeOf(LabelNode** out, uint32_t labelId) {
|
||||
*out = nullptr;
|
||||
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
uint32_t index = labelId;
|
||||
if (ASMJIT_UNLIKELY(index >= _code->labelCount()))
|
||||
return DebugUtils::errored(kErrorInvalidLabel);
|
||||
|
||||
if (index >= _labelNodes.size())
|
||||
ASMJIT_PROPAGATE(_labelNodes.resize(&_allocator, index + 1));
|
||||
|
||||
LabelNode* node = _labelNodes[index];
|
||||
if (!node) {
|
||||
ASMJIT_PROPAGATE(_newNodeT<LabelNode>(&node, labelId));
|
||||
_labelNodes[index] = node;
|
||||
}
|
||||
|
||||
*out = node;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseBuilder::registerLabelNode(LabelNode* node) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
LabelEntry* le;
|
||||
ASMJIT_PROPAGATE(_code->newLabelEntry(&le));
|
||||
uint32_t labelId = le->id();
|
||||
|
||||
// We just added one label so it must be true.
|
||||
ASMJIT_ASSERT(_labelNodes.size() < labelId + 1);
|
||||
ASMJIT_PROPAGATE(_labelNodes.resize(&_allocator, labelId + 1));
|
||||
|
||||
_labelNodes[labelId] = node;
|
||||
node->_labelId = labelId;
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
static Error BaseBuilder_newLabelInternal(BaseBuilder* self, uint32_t labelId) {
|
||||
ASMJIT_ASSERT(self->_labelNodes.size() < labelId + 1);
|
||||
|
||||
uint32_t growBy = labelId - self->_labelNodes.size();
|
||||
Error err = self->_labelNodes.willGrow(&self->_allocator, growBy);
|
||||
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
return self->reportError(err);
|
||||
|
||||
LabelNode* node;
|
||||
ASMJIT_PROPAGATE(self->_newNodeT<LabelNode>(&node, labelId));
|
||||
|
||||
self->_labelNodes.resize(&self->_allocator, labelId + 1);
|
||||
self->_labelNodes[labelId] = node;
|
||||
node->_labelId = labelId;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Label BaseBuilder::newLabel() {
|
||||
uint32_t labelId = Globals::kInvalidId;
|
||||
LabelEntry* le;
|
||||
|
||||
if (_code &&
|
||||
_code->newLabelEntry(&le) == kErrorOk &&
|
||||
BaseBuilder_newLabelInternal(this, le->id()) == kErrorOk) {
|
||||
labelId = le->id();
|
||||
}
|
||||
|
||||
return Label(labelId);
|
||||
}
|
||||
|
||||
Label BaseBuilder::newNamedLabel(const char* name, size_t nameSize, uint32_t type, uint32_t parentId) {
|
||||
uint32_t labelId = Globals::kInvalidId;
|
||||
LabelEntry* le;
|
||||
|
||||
if (_code &&
|
||||
_code->newNamedLabelEntry(&le, name, nameSize, type, parentId) == kErrorOk &&
|
||||
BaseBuilder_newLabelInternal(this, le->id()) == kErrorOk) {
|
||||
labelId = le->id();
|
||||
}
|
||||
|
||||
return Label(labelId);
|
||||
}
|
||||
|
||||
Error BaseBuilder::bind(const Label& label) {
|
||||
LabelNode* node;
|
||||
ASMJIT_PROPAGATE(labelNodeOf(&node, label));
|
||||
|
||||
addNode(node);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Passes]
|
||||
// ============================================================================
|
||||
|
||||
ASMJIT_FAVOR_SIZE Pass* BaseBuilder::passByName(const char* name) const noexcept {
|
||||
for (Pass* pass : _passes)
|
||||
if (strcmp(pass->name(), name) == 0)
|
||||
return pass;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ASMJIT_FAVOR_SIZE Error BaseBuilder::addPass(Pass* pass) noexcept {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
if (ASMJIT_UNLIKELY(pass == nullptr)) {
|
||||
// Since this is directly called by `addPassT()` we treat `null` argument
|
||||
// as out-of-memory condition. Otherwise it would be API misuse.
|
||||
return DebugUtils::errored(kErrorOutOfMemory);
|
||||
}
|
||||
else if (ASMJIT_UNLIKELY(pass->_cb)) {
|
||||
// Kinda weird, but okay...
|
||||
if (pass->_cb == this)
|
||||
return kErrorOk;
|
||||
return DebugUtils::errored(kErrorInvalidState);
|
||||
}
|
||||
|
||||
ASMJIT_PROPAGATE(_passes.append(&_allocator, pass));
|
||||
pass->_cb = this;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
ASMJIT_FAVOR_SIZE Error BaseBuilder::deletePass(Pass* pass) noexcept {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
if (ASMJIT_UNLIKELY(pass == nullptr))
|
||||
return DebugUtils::errored(kErrorInvalidArgument);
|
||||
|
||||
if (pass->_cb != nullptr) {
|
||||
if (pass->_cb != this)
|
||||
return DebugUtils::errored(kErrorInvalidState);
|
||||
|
||||
uint32_t index = _passes.indexOf(pass);
|
||||
ASMJIT_ASSERT(index != Globals::kNotFound);
|
||||
|
||||
pass->_cb = nullptr;
|
||||
_passes.removeAt(index);
|
||||
}
|
||||
|
||||
pass->~Pass();
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseBuilder::runPasses() {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
if (_passes.empty())
|
||||
return kErrorOk;
|
||||
|
||||
ErrorHandler* prev = errorHandler();
|
||||
PostponedErrorHandler postponed;
|
||||
|
||||
Error err = kErrorOk;
|
||||
setErrorHandler(&postponed);
|
||||
|
||||
for (Pass* pass : _passes) {
|
||||
_passZone.reset();
|
||||
err = pass->run(&_passZone, _logger);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
_passZone.reset();
|
||||
setErrorHandler(prev);
|
||||
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
return reportError(err, !postponed._message.empty() ? postponed._message.data() : nullptr);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Emit]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseBuilder::_emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) {
|
||||
uint32_t opCount = EmitterUtils::opCountFromEmitArgs(o0, o1, o2, opExt);
|
||||
uint32_t options = instOptions() | forcedInstOptions();
|
||||
|
||||
if (options & BaseInst::kOptionReserved) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
#ifndef ASMJIT_NO_VALIDATION
|
||||
// Strict validation.
|
||||
if (hasValidationOption(kValidationOptionIntermediate)) {
|
||||
Operand_ opArray[Globals::kMaxOpCount];
|
||||
EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt);
|
||||
|
||||
Error err = InstAPI::validate(arch(), BaseInst(instId, options, _extraReg), opArray, opCount);
|
||||
if (ASMJIT_UNLIKELY(err)) {
|
||||
resetInstOptions();
|
||||
resetExtraReg();
|
||||
resetInlineComment();
|
||||
return reportError(err);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Clear options that should never be part of `InstNode`.
|
||||
options &= ~BaseInst::kOptionReserved;
|
||||
}
|
||||
|
||||
uint32_t opCapacity = InstNode::capacityOfOpCount(opCount);
|
||||
ASMJIT_ASSERT(opCapacity >= InstNode::kBaseOpCapacity);
|
||||
|
||||
InstNode* node = _allocator.allocT<InstNode>(InstNode::nodeSizeOfOpCapacity(opCapacity));
|
||||
const char* comment = inlineComment();
|
||||
|
||||
resetInstOptions();
|
||||
resetInlineComment();
|
||||
|
||||
if (ASMJIT_UNLIKELY(!node)) {
|
||||
resetExtraReg();
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
}
|
||||
|
||||
node = new(node) InstNode(this, instId, options, opCount, opCapacity);
|
||||
node->setExtraReg(extraReg());
|
||||
node->setOp(0, o0);
|
||||
node->setOp(1, o1);
|
||||
node->setOp(2, o2);
|
||||
for (uint32_t i = 3; i < opCount; i++)
|
||||
node->setOp(i, opExt[i - 3]);
|
||||
node->resetOpRange(opCount, opCapacity);
|
||||
|
||||
if (comment)
|
||||
node->setInlineComment(static_cast<char*>(_dataZone.dup(comment, strlen(comment), true)));
|
||||
|
||||
addNode(node);
|
||||
resetExtraReg();
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Align]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseBuilder::align(uint32_t alignMode, uint32_t alignment) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
AlignNode* node;
|
||||
ASMJIT_PROPAGATE(_newAlignNode(&node, alignMode, alignment));
|
||||
|
||||
addNode(node);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Embed]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseBuilder::embed(const void* data, size_t dataSize) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
EmbedDataNode* node;
|
||||
ASMJIT_PROPAGATE(_newEmbedDataNode(&node, Type::kIdU8, data, dataSize));
|
||||
|
||||
addNode(node);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseBuilder::embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t itemRepeat) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
EmbedDataNode* node;
|
||||
ASMJIT_PROPAGATE(_newEmbedDataNode(&node, typeId, data, itemCount, itemRepeat));
|
||||
|
||||
addNode(node);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseBuilder::embedConstPool(const Label& label, const ConstPool& pool) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
if (!isLabelValid(label))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidLabel));
|
||||
|
||||
ASMJIT_PROPAGATE(align(kAlignData, uint32_t(pool.alignment())));
|
||||
ASMJIT_PROPAGATE(bind(label));
|
||||
|
||||
EmbedDataNode* node;
|
||||
ASMJIT_PROPAGATE(_newEmbedDataNode(&node, Type::kIdU8, nullptr, pool.size()));
|
||||
|
||||
pool.fill(node->data());
|
||||
addNode(node);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// EmbedLabel / EmbedLabelDelta
|
||||
// ----------------------------
|
||||
//
|
||||
// If dataSize is zero it means that the size is the same as target register
|
||||
// width, however, if it's provided we really want to validate whether it's
|
||||
// within the possible range.
|
||||
|
||||
static inline bool BaseBuilder_checkDataSize(size_t dataSize) noexcept {
|
||||
return !dataSize || (Support::isPowerOf2(dataSize) && dataSize <= 8);
|
||||
}
|
||||
|
||||
Error BaseBuilder::embedLabel(const Label& label, size_t dataSize) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
if (!BaseBuilder_checkDataSize(dataSize))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidArgument));
|
||||
|
||||
EmbedLabelNode* node;
|
||||
ASMJIT_PROPAGATE(_newNodeT<EmbedLabelNode>(&node, label.id(), uint32_t(dataSize)));
|
||||
|
||||
addNode(node);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseBuilder::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
if (!BaseBuilder_checkDataSize(dataSize))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidArgument));
|
||||
|
||||
EmbedLabelDeltaNode* node;
|
||||
ASMJIT_PROPAGATE(_newNodeT<EmbedLabelDeltaNode>(&node, label.id(), base.id(), uint32_t(dataSize)));
|
||||
|
||||
addNode(node);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Comment]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseBuilder::comment(const char* data, size_t size) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
CommentNode* node;
|
||||
ASMJIT_PROPAGATE(_newCommentNode(&node, data, size));
|
||||
|
||||
addNode(node);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Serialize]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseBuilder::serializeTo(BaseEmitter* dst) {
|
||||
Error err = kErrorOk;
|
||||
BaseNode* node_ = _firstNode;
|
||||
|
||||
Operand_ opArray[Globals::kMaxOpCount];
|
||||
|
||||
do {
|
||||
dst->setInlineComment(node_->inlineComment());
|
||||
|
||||
if (node_->isInst()) {
|
||||
InstNode* node = node_->as<InstNode>();
|
||||
|
||||
// NOTE: Inlined to remove one additional call per instruction.
|
||||
dst->setInstOptions(node->instOptions());
|
||||
dst->setExtraReg(node->extraReg());
|
||||
|
||||
const Operand_* op = node->operands();
|
||||
const Operand_* opExt = EmitterUtils::noExt;
|
||||
|
||||
uint32_t opCount = node->opCount();
|
||||
if (opCount > 3) {
|
||||
uint32_t i = 4;
|
||||
opArray[3] = op[3];
|
||||
|
||||
while (i < opCount) {
|
||||
opArray[i].copyFrom(op[i]);
|
||||
i++;
|
||||
}
|
||||
while (i < Globals::kMaxOpCount) {
|
||||
opArray[i].reset();
|
||||
i++;
|
||||
}
|
||||
opExt = opArray + 3;
|
||||
}
|
||||
|
||||
err = dst->_emit(node->id(), op[0], op[1], op[2], opExt);
|
||||
}
|
||||
else if (node_->isLabel()) {
|
||||
if (node_->isConstPool()) {
|
||||
ConstPoolNode* node = node_->as<ConstPoolNode>();
|
||||
err = dst->embedConstPool(node->label(), node->constPool());
|
||||
}
|
||||
else {
|
||||
LabelNode* node = node_->as<LabelNode>();
|
||||
err = dst->bind(node->label());
|
||||
}
|
||||
}
|
||||
else if (node_->isAlign()) {
|
||||
AlignNode* node = node_->as<AlignNode>();
|
||||
err = dst->align(node->alignMode(), node->alignment());
|
||||
}
|
||||
else if (node_->isEmbedData()) {
|
||||
EmbedDataNode* node = node_->as<EmbedDataNode>();
|
||||
err = dst->embedDataArray(node->typeId(), node->data(), node->itemCount(), node->repeatCount());
|
||||
}
|
||||
else if (node_->isEmbedLabel()) {
|
||||
EmbedLabelNode* node = node_->as<EmbedLabelNode>();
|
||||
err = dst->embedLabel(node->label(), node->dataSize());
|
||||
}
|
||||
else if (node_->isEmbedLabelDelta()) {
|
||||
EmbedLabelDeltaNode* node = node_->as<EmbedLabelDeltaNode>();
|
||||
err = dst->embedLabelDelta(node->label(), node->baseLabel(), node->dataSize());
|
||||
}
|
||||
else if (node_->isSection()) {
|
||||
SectionNode* node = node_->as<SectionNode>();
|
||||
err = dst->section(_code->sectionById(node->id()));
|
||||
}
|
||||
else if (node_->isComment()) {
|
||||
CommentNode* node = node_->as<CommentNode>();
|
||||
err = dst->comment(node->inlineComment());
|
||||
}
|
||||
|
||||
if (err) break;
|
||||
node_ = node_->next();
|
||||
} while (node_);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseBuilder - Events]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseBuilder::onAttach(CodeHolder* code) noexcept {
|
||||
ASMJIT_PROPAGATE(Base::onAttach(code));
|
||||
|
||||
SectionNode* initialSection;
|
||||
Error err = sectionNodeOf(&initialSection, 0);
|
||||
|
||||
if (!err)
|
||||
err = _passes.willGrow(&_allocator, 8);
|
||||
|
||||
if (ASMJIT_UNLIKELY(err)) {
|
||||
onDetach(code);
|
||||
return err;
|
||||
}
|
||||
|
||||
_cursor = initialSection;
|
||||
_firstNode = initialSection;
|
||||
_lastNode = initialSection;
|
||||
initialSection->setFlags(BaseNode::kFlagIsActive);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseBuilder::onDetach(CodeHolder* code) noexcept {
|
||||
BaseBuilder_deletePasses(this);
|
||||
_sectionNodes.reset();
|
||||
_labelNodes.reset();
|
||||
|
||||
_allocator.reset(&_codeZone);
|
||||
_codeZone.reset();
|
||||
_dataZone.reset();
|
||||
_passZone.reset();
|
||||
|
||||
_nodeFlags = 0;
|
||||
|
||||
_cursor = nullptr;
|
||||
_firstNode = nullptr;
|
||||
_lastNode = nullptr;
|
||||
|
||||
return Base::onDetach(code);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Pass - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
Pass::Pass(const char* name) noexcept
|
||||
: _name(name) {}
|
||||
Pass::~Pass() noexcept {}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // !ASMJIT_NO_BUILDER
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,126 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_CODEBUFFER_H_INCLUDED
|
||||
#define ASMJIT_CORE_CODEBUFFER_H_INCLUDED
|
||||
|
||||
#include "../core/globals.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
//! \addtogroup asmjit_core
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::CodeBuffer]
|
||||
// ============================================================================
|
||||
|
||||
//! Code or data buffer.
|
||||
struct CodeBuffer {
|
||||
//! The content of the buffer (data).
|
||||
uint8_t* _data;
|
||||
//! Number of bytes of `data` used.
|
||||
size_t _size;
|
||||
//! Buffer capacity (in bytes).
|
||||
size_t _capacity;
|
||||
//! Buffer flags.
|
||||
uint32_t _flags;
|
||||
|
||||
//! Code buffer flags.
|
||||
enum Flags : uint32_t {
|
||||
//! Buffer is external (not allocated by asmjit).
|
||||
kFlagIsExternal = 0x00000001u,
|
||||
//! Buffer is fixed (cannot be reallocated).
|
||||
kFlagIsFixed = 0x00000002u
|
||||
};
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
//! Returns a referebce to the byte at the given `index`.
|
||||
inline uint8_t& operator[](size_t index) noexcept {
|
||||
ASMJIT_ASSERT(index < _size);
|
||||
return _data[index];
|
||||
}
|
||||
//! \overload
|
||||
inline const uint8_t& operator[](size_t index) const noexcept {
|
||||
ASMJIT_ASSERT(index < _size);
|
||||
return _data[index];
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
//! Returns code buffer flags, see \ref Flags.
|
||||
inline uint32_t flags() const noexcept { return _flags; }
|
||||
//! Tests whether the code buffer has the given `flag` set.
|
||||
inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; }
|
||||
|
||||
//! Tests whether this code buffer has a fixed size.
|
||||
//!
|
||||
//! Fixed size means that the code buffer is fixed and cannot grow.
|
||||
inline bool isFixed() const noexcept { return hasFlag(kFlagIsFixed); }
|
||||
|
||||
//! Tests whether the data in this code buffer is external.
|
||||
//!
|
||||
//! External data can only be provided by users, it's never used by AsmJit.
|
||||
inline bool isExternal() const noexcept { return hasFlag(kFlagIsExternal); }
|
||||
|
||||
//! Tests whether the data in this code buffer is allocated (non-null).
|
||||
inline bool isAllocated() const noexcept { return _data != nullptr; }
|
||||
|
||||
//! Tests whether the code buffer is empty.
|
||||
inline bool empty() const noexcept { return !_size; }
|
||||
|
||||
//! Returns the size of the data.
|
||||
inline size_t size() const noexcept { return _size; }
|
||||
//! Returns the capacity of the data.
|
||||
inline size_t capacity() const noexcept { return _capacity; }
|
||||
|
||||
//! Returns the pointer to the data the buffer references.
|
||||
inline uint8_t* data() noexcept { return _data; }
|
||||
//! \overload
|
||||
inline const uint8_t* data() const noexcept { return _data; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Iterators
|
||||
//! \{
|
||||
|
||||
inline uint8_t* begin() noexcept { return _data; }
|
||||
inline const uint8_t* begin() const noexcept { return _data; }
|
||||
|
||||
inline uint8_t* end() noexcept { return _data + _size; }
|
||||
inline const uint8_t* end() const noexcept { return _data + _size; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_CODEBUFFER_H_INCLUDED
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,151 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#include "../core/codeholder.h"
|
||||
#include "../core/codewriter_p.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
bool CodeWriterUtils::encodeOffset32(uint32_t* dst, int64_t offset64, const OffsetFormat& format) noexcept {
|
||||
uint32_t bitCount = format.immBitCount();
|
||||
uint32_t bitShift = format.immBitShift();
|
||||
uint32_t discardLsb = format.immDiscardLsb();
|
||||
|
||||
if (!bitCount || bitCount > format.valueSize() * 8u)
|
||||
return false;
|
||||
|
||||
if (discardLsb) {
|
||||
ASMJIT_ASSERT(discardLsb <= 32);
|
||||
if ((offset64 & Support::lsbMask<uint32_t>(discardLsb)) != 0)
|
||||
return false;
|
||||
offset64 >>= discardLsb;
|
||||
}
|
||||
|
||||
if (!Support::isInt32(offset64))
|
||||
return false;
|
||||
|
||||
int32_t offset32 = int32_t(offset64);
|
||||
if (!Support::isEncodableOffset32(offset32, bitCount))
|
||||
return false;
|
||||
|
||||
switch (format.type()) {
|
||||
case OffsetFormat::kTypeCommon: {
|
||||
*dst = (uint32_t(offset32) & Support::lsbMask<uint32_t>(bitCount)) << bitShift;
|
||||
return true;
|
||||
}
|
||||
|
||||
case OffsetFormat::kTypeAArch64_ADR:
|
||||
case OffsetFormat::kTypeAArch64_ADRP: {
|
||||
// Sanity checks.
|
||||
if (format.valueSize() != 4 || bitCount != 21 || bitShift != 5)
|
||||
return false;
|
||||
|
||||
uint32_t immLo = uint32_t(offset32) & 0x3u;
|
||||
uint32_t immHi = uint32_t(offset32 >> 2) & Support::lsbMask<uint32_t>(19);
|
||||
|
||||
*dst = (immLo << 29) | (immHi << 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CodeWriterUtils::encodeOffset64(uint64_t* dst, int64_t offset64, const OffsetFormat& format) noexcept {
|
||||
uint32_t bitCount = format.immBitCount();
|
||||
uint32_t discardLsb = format.immDiscardLsb();
|
||||
|
||||
if (!bitCount || bitCount > format.valueSize() * 8u)
|
||||
return false;
|
||||
|
||||
if (discardLsb) {
|
||||
ASMJIT_ASSERT(discardLsb <= 32);
|
||||
if ((offset64 & Support::lsbMask<uint32_t>(discardLsb)) != 0)
|
||||
return false;
|
||||
offset64 >>= discardLsb;
|
||||
}
|
||||
|
||||
if (!Support::isEncodableOffset64(offset64, bitCount))
|
||||
return false;
|
||||
|
||||
switch (format.type()) {
|
||||
case OffsetFormat::kTypeCommon: {
|
||||
*dst = (uint64_t(offset64) & Support::lsbMask<uint64_t>(bitCount)) << format.immBitShift();
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CodeWriterUtils::writeOffset(void* dst, int64_t offset64, const OffsetFormat& format) noexcept {
|
||||
// Offset the destination by ValueOffset so the `dst` points to the
|
||||
// patched word instead of the beginning of the patched region.
|
||||
dst = static_cast<char*>(dst) + format.valueOffset();
|
||||
|
||||
switch (format.valueSize()) {
|
||||
case 1: {
|
||||
uint32_t mask;
|
||||
if (!encodeOffset32(&mask, offset64, format))
|
||||
return false;
|
||||
|
||||
Support::writeU8(dst, Support::readU8(dst) | mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
uint32_t mask;
|
||||
if (!encodeOffset32(&mask, offset64, format))
|
||||
return false;
|
||||
|
||||
Support::writeU16uLE(dst, Support::readU16uLE(dst) | mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
case 4: {
|
||||
uint32_t mask;
|
||||
if (!encodeOffset32(&mask, offset64, format))
|
||||
return false;
|
||||
|
||||
Support::writeU32uLE(dst, Support::readU32uLE(dst) | mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
case 8: {
|
||||
uint64_t mask;
|
||||
if (!encodeOffset64(&mask, offset64, format))
|
||||
return false;
|
||||
|
||||
Support::writeU64uLE(dst, Support::readU64uLE(dst) | mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
@ -0,0 +1,208 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_CODEBUFFERWRITER_P_H_INCLUDED
|
||||
#define ASMJIT_CORE_CODEBUFFERWRITER_P_H_INCLUDED
|
||||
|
||||
#include "../core/assembler.h"
|
||||
#include "../core/codebuffer.h"
|
||||
#include "../core/support.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
//! \cond INTERNAL
|
||||
//! \addtogroup asmjit_assembler
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [Forward Declarations]
|
||||
// ============================================================================
|
||||
|
||||
struct OffsetFormat;
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::CodeWriter]
|
||||
// ============================================================================
|
||||
|
||||
//! Helper that is used to write into a \ref CodeBuffer held by \ref BaseAssembler.
|
||||
class CodeWriter {
|
||||
public:
|
||||
uint8_t* _cursor;
|
||||
|
||||
ASMJIT_INLINE explicit CodeWriter(BaseAssembler* a) noexcept
|
||||
: _cursor(a->_bufferPtr) {}
|
||||
|
||||
ASMJIT_INLINE Error ensureSpace(BaseAssembler* a, size_t n) noexcept {
|
||||
size_t remainingSpace = (size_t)(a->_bufferEnd - _cursor);
|
||||
if (ASMJIT_UNLIKELY(remainingSpace < n)) {
|
||||
CodeBuffer& buffer = a->_section->_buffer;
|
||||
Error err = a->_code->growBuffer(&buffer, n);
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
return a->reportError(err);
|
||||
_cursor = a->_bufferPtr;
|
||||
}
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE uint8_t* cursor() const noexcept { return _cursor; }
|
||||
ASMJIT_INLINE void setCursor(uint8_t* cursor) noexcept { _cursor = cursor; }
|
||||
ASMJIT_INLINE void advance(size_t n) noexcept { _cursor += n; }
|
||||
|
||||
ASMJIT_INLINE size_t offsetFrom(uint8_t* from) const noexcept {
|
||||
ASMJIT_ASSERT(_cursor >= from);
|
||||
return (size_t)(_cursor - from);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ASMJIT_INLINE void emit8(T val) noexcept {
|
||||
typedef typename std::make_unsigned<T>::type U;
|
||||
_cursor[0] = uint8_t(U(val) & U(0xFF));
|
||||
_cursor++;
|
||||
}
|
||||
|
||||
template<typename T, typename Y>
|
||||
ASMJIT_INLINE void emit8If(T val, Y cond) noexcept {
|
||||
typedef typename std::make_unsigned<T>::type U;
|
||||
ASMJIT_ASSERT(size_t(cond) <= 1u);
|
||||
|
||||
_cursor[0] = uint8_t(U(val) & U(0xFF));
|
||||
_cursor += size_t(cond);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ASMJIT_INLINE void emit16uLE(T val) noexcept {
|
||||
typedef typename std::make_unsigned<T>::type U;
|
||||
Support::writeU16uLE(_cursor, uint32_t(U(val) & 0xFFFFu));
|
||||
_cursor += 2;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ASMJIT_INLINE void emit16uBE(T val) noexcept {
|
||||
typedef typename std::make_unsigned<T>::type U;
|
||||
Support::writeU16uBE(_cursor, uint32_t(U(val) & 0xFFFFu));
|
||||
_cursor += 2;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ASMJIT_INLINE void emit32uLE(T val) noexcept {
|
||||
typedef typename std::make_unsigned<T>::type U;
|
||||
Support::writeU32uLE(_cursor, uint32_t(U(val) & 0xFFFFFFFFu));
|
||||
_cursor += 4;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ASMJIT_INLINE void emit32uBE(T val) noexcept {
|
||||
typedef typename std::make_unsigned<T>::type U;
|
||||
Support::writeU32uBE(_cursor, uint32_t(U(val) & 0xFFFFFFFFu));
|
||||
_cursor += 4;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE void emitData(const void* data, size_t size) noexcept {
|
||||
ASMJIT_ASSERT(size != 0);
|
||||
memcpy(_cursor, data, size);
|
||||
_cursor += size;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ASMJIT_INLINE void emitValueLE(const T& value, size_t size) noexcept {
|
||||
typedef typename std::make_unsigned<T>::type U;
|
||||
ASMJIT_ASSERT(size <= sizeof(T));
|
||||
|
||||
U v = U(value);
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
_cursor[i] = uint8_t(v & 0xFFu);
|
||||
v >>= 8;
|
||||
}
|
||||
_cursor += size;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ASMJIT_INLINE void emitValueBE(const T& value, size_t size) noexcept {
|
||||
typedef typename std::make_unsigned<T>::type U;
|
||||
ASMJIT_ASSERT(size <= sizeof(T));
|
||||
|
||||
U v = U(value);
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
_cursor[i] = uint8_t(v >> (sizeof(T) - 8));
|
||||
v <<= 8;
|
||||
}
|
||||
_cursor += size;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE void emitZeros(size_t size) noexcept {
|
||||
ASMJIT_ASSERT(size != 0);
|
||||
memset(_cursor, 0, size);
|
||||
_cursor += size;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE void remove8(uint8_t* where) noexcept {
|
||||
ASMJIT_ASSERT(where < _cursor);
|
||||
|
||||
uint8_t* p = where;
|
||||
while (++p != _cursor)
|
||||
p[-1] = p[0];
|
||||
_cursor--;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ASMJIT_INLINE void insert8(uint8_t* where, T val) noexcept {
|
||||
uint8_t* p = _cursor;
|
||||
|
||||
while (p != where) {
|
||||
p[0] = p[-1];
|
||||
p--;
|
||||
}
|
||||
|
||||
*p = uint8_t(val & 0xFF);
|
||||
_cursor++;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE void done(BaseAssembler* a) noexcept {
|
||||
CodeBuffer& buffer = a->_section->_buffer;
|
||||
size_t newSize = (size_t)(_cursor - a->_bufferData);
|
||||
ASMJIT_ASSERT(newSize <= buffer.capacity());
|
||||
|
||||
a->_bufferPtr = _cursor;
|
||||
buffer._size = Support::max(buffer._size, newSize);
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::CodeWriterUtils]
|
||||
// ============================================================================
|
||||
|
||||
namespace CodeWriterUtils {
|
||||
|
||||
bool encodeOffset32(uint32_t* dst, int64_t offset64, const OffsetFormat& format) noexcept;
|
||||
bool encodeOffset64(uint64_t* dst, int64_t offset64, const OffsetFormat& format) noexcept;
|
||||
|
||||
bool writeOffset(void* dst, int64_t offset64, const OffsetFormat& format) noexcept;
|
||||
|
||||
} // {CodeWriterUtils}
|
||||
|
||||
//! \}
|
||||
//! \endcond
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_CODEBUFFERWRITER_P_H_INCLUDED
|
@ -0,0 +1,628 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#ifndef ASMJIT_NO_COMPILER
|
||||
|
||||
#include "../core/assembler.h"
|
||||
#include "../core/compiler.h"
|
||||
#include "../core/cpuinfo.h"
|
||||
#include "../core/logger.h"
|
||||
#include "../core/rapass_p.h"
|
||||
#include "../core/rastack_p.h"
|
||||
#include "../core/support.h"
|
||||
#include "../core/type.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::GlobalConstPoolPass]
|
||||
// ============================================================================
|
||||
|
||||
class GlobalConstPoolPass : public Pass {
|
||||
typedef Pass Base;
|
||||
ASMJIT_NONCOPYABLE(GlobalConstPoolPass)
|
||||
|
||||
GlobalConstPoolPass() noexcept : Pass("GlobalConstPoolPass") {}
|
||||
|
||||
Error run(Zone* zone, Logger* logger) override {
|
||||
DebugUtils::unused(zone, logger);
|
||||
|
||||
// Flush the global constant pool.
|
||||
BaseCompiler* compiler = static_cast<BaseCompiler*>(_cb);
|
||||
if (compiler->_globalConstPool) {
|
||||
compiler->addAfter(compiler->_globalConstPool, compiler->lastNode());
|
||||
compiler->_globalConstPool = nullptr;
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseCompiler - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
BaseCompiler::BaseCompiler() noexcept
|
||||
: BaseBuilder(),
|
||||
_func(nullptr),
|
||||
_vRegZone(4096 - Zone::kBlockOverhead),
|
||||
_vRegArray(),
|
||||
_localConstPool(nullptr),
|
||||
_globalConstPool(nullptr) {
|
||||
|
||||
_emitterType = uint8_t(kTypeCompiler);
|
||||
_validationFlags = uint8_t(InstAPI::kValidationFlagVirtRegs);
|
||||
}
|
||||
BaseCompiler::~BaseCompiler() noexcept {}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseCompiler - Function Management]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseCompiler::_newFuncNode(FuncNode** out, const FuncSignature& signature) {
|
||||
*out = nullptr;
|
||||
|
||||
// Create FuncNode together with all the required surrounding nodes.
|
||||
FuncNode* funcNode;
|
||||
ASMJIT_PROPAGATE(_newNodeT<FuncNode>(&funcNode));
|
||||
ASMJIT_PROPAGATE(_newLabelNode(&funcNode->_exitNode));
|
||||
ASMJIT_PROPAGATE(_newNodeT<SentinelNode>(&funcNode->_end, SentinelNode::kSentinelFuncEnd));
|
||||
|
||||
// Initialize the function's detail info.
|
||||
Error err = funcNode->detail().init(signature, environment());
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
return reportError(err);
|
||||
|
||||
// If the Target guarantees greater stack alignment than required by the
|
||||
// calling convention then override it as we can prevent having to perform
|
||||
// dynamic stack alignment
|
||||
uint32_t environmentStackAlignment = _environment.stackAlignment();
|
||||
|
||||
if (funcNode->_funcDetail._callConv.naturalStackAlignment() < environmentStackAlignment)
|
||||
funcNode->_funcDetail._callConv.setNaturalStackAlignment(environmentStackAlignment);
|
||||
|
||||
// Initialize the function frame.
|
||||
err = funcNode->_frame.init(funcNode->_funcDetail);
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
return reportError(err);
|
||||
|
||||
// Allocate space for function arguments.
|
||||
funcNode->_args = nullptr;
|
||||
if (funcNode->argCount() != 0) {
|
||||
funcNode->_args = _allocator.allocT<FuncNode::ArgPack>(funcNode->argCount() * sizeof(FuncNode::ArgPack));
|
||||
if (ASMJIT_UNLIKELY(!funcNode->_args))
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
memset(funcNode->_args, 0, funcNode->argCount() * sizeof(FuncNode::ArgPack));
|
||||
}
|
||||
|
||||
ASMJIT_PROPAGATE(registerLabelNode(funcNode));
|
||||
|
||||
*out = funcNode;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::_addFuncNode(FuncNode** out, const FuncSignature& signature) {
|
||||
ASMJIT_PROPAGATE(_newFuncNode(out, signature));
|
||||
addFunc(*out);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::_newRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) {
|
||||
uint32_t opCount = !o1.isNone() ? 2u : !o0.isNone() ? 1u : 0u;
|
||||
FuncRetNode* node;
|
||||
|
||||
ASMJIT_PROPAGATE(_newNodeT<FuncRetNode>(&node));
|
||||
node->setOpCount(opCount);
|
||||
node->setOp(0, o0);
|
||||
node->setOp(1, o1);
|
||||
node->resetOpRange(2, node->opCapacity());
|
||||
|
||||
*out = node;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::_addRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) {
|
||||
ASMJIT_PROPAGATE(_newRetNode(out, o0, o1));
|
||||
addNode(*out);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
FuncNode* BaseCompiler::addFunc(FuncNode* func) {
|
||||
ASMJIT_ASSERT(_func == nullptr);
|
||||
_func = func;
|
||||
|
||||
addNode(func); // Function node.
|
||||
BaseNode* prev = cursor(); // {CURSOR}.
|
||||
addNode(func->exitNode()); // Function exit label.
|
||||
addNode(func->endNode()); // Function end sentinel.
|
||||
|
||||
_setCursor(prev);
|
||||
return func;
|
||||
}
|
||||
|
||||
Error BaseCompiler::endFunc() {
|
||||
FuncNode* func = _func;
|
||||
|
||||
if (ASMJIT_UNLIKELY(!func))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidState));
|
||||
|
||||
// Add the local constant pool at the end of the function (if exists).
|
||||
if (_localConstPool) {
|
||||
setCursor(func->endNode()->prev());
|
||||
addNode(_localConstPool);
|
||||
_localConstPool = nullptr;
|
||||
}
|
||||
|
||||
// Mark as finished.
|
||||
_func = nullptr;
|
||||
|
||||
SentinelNode* end = func->endNode();
|
||||
setCursor(end);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::_setArg(size_t argIndex, size_t valueIndex, const BaseReg& r) {
|
||||
FuncNode* func = _func;
|
||||
|
||||
if (ASMJIT_UNLIKELY(!func))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidState));
|
||||
|
||||
if (ASMJIT_UNLIKELY(!isVirtRegValid(r)))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidVirtId));
|
||||
|
||||
VirtReg* vReg = virtRegByReg(r);
|
||||
func->setArg(argIndex, valueIndex, vReg);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseCompiler - Function Invocation]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseCompiler::_newInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature) {
|
||||
InvokeNode* node;
|
||||
ASMJIT_PROPAGATE(_newNodeT<InvokeNode>(&node, instId, 0u));
|
||||
|
||||
node->setOpCount(1);
|
||||
node->setOp(0, o0);
|
||||
node->resetOpRange(1, node->opCapacity());
|
||||
|
||||
Error err = node->detail().init(signature, environment());
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
return reportError(err);
|
||||
|
||||
// Skip the allocation if there are no arguments.
|
||||
uint32_t argCount = signature.argCount();
|
||||
if (argCount) {
|
||||
node->_args = static_cast<InvokeNode::OperandPack*>(_allocator.alloc(argCount * sizeof(InvokeNode::OperandPack)));
|
||||
if (!node->_args)
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
memset(node->_args, 0, argCount * sizeof(InvokeNode::OperandPack));
|
||||
}
|
||||
|
||||
*out = node;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::_addInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature) {
|
||||
ASMJIT_PROPAGATE(_newInvokeNode(out, instId, o0, signature));
|
||||
addNode(*out);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseCompiler - Virtual Registers]
|
||||
// ============================================================================
|
||||
|
||||
static void BaseCompiler_assignGenericName(BaseCompiler* self, VirtReg* vReg) {
|
||||
uint32_t index = unsigned(Operand::virtIdToIndex(vReg->_id));
|
||||
|
||||
char buf[64];
|
||||
int size = snprintf(buf, ASMJIT_ARRAY_SIZE(buf), "%%%u", unsigned(index));
|
||||
|
||||
ASMJIT_ASSERT(size > 0 && size < int(ASMJIT_ARRAY_SIZE(buf)));
|
||||
vReg->_name.setData(&self->_dataZone, buf, unsigned(size));
|
||||
}
|
||||
|
||||
Error BaseCompiler::newVirtReg(VirtReg** out, uint32_t typeId, uint32_t signature, const char* name) {
|
||||
*out = nullptr;
|
||||
uint32_t index = _vRegArray.size();
|
||||
|
||||
if (ASMJIT_UNLIKELY(index >= uint32_t(Operand::kVirtIdCount)))
|
||||
return reportError(DebugUtils::errored(kErrorTooManyVirtRegs));
|
||||
|
||||
if (ASMJIT_UNLIKELY(_vRegArray.willGrow(&_allocator) != kErrorOk))
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
|
||||
VirtReg* vReg = _vRegZone.allocZeroedT<VirtReg>();
|
||||
if (ASMJIT_UNLIKELY(!vReg))
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
|
||||
uint32_t size = Type::sizeOf(typeId);
|
||||
uint32_t alignment = Support::min<uint32_t>(size, 64);
|
||||
|
||||
vReg = new(vReg) VirtReg(Operand::indexToVirtId(index), signature, size, alignment, typeId);
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (name && name[0] != '\0')
|
||||
vReg->_name.setData(&_dataZone, name, SIZE_MAX);
|
||||
else
|
||||
BaseCompiler_assignGenericName(this, vReg);
|
||||
#else
|
||||
DebugUtils::unused(name);
|
||||
#endif
|
||||
|
||||
_vRegArray.appendUnsafe(vReg);
|
||||
*out = vReg;
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::_newReg(BaseReg* out, uint32_t typeId, const char* name) {
|
||||
RegInfo regInfo;
|
||||
out->reset();
|
||||
|
||||
Error err = ArchUtils::typeIdToRegInfo(arch(), typeId, &typeId, ®Info);
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
return reportError(err);
|
||||
|
||||
VirtReg* vReg;
|
||||
ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regInfo.signature(), name));
|
||||
|
||||
out->_initReg(regInfo.signature(), vReg->id());
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::_newRegFmt(BaseReg* out, uint32_t typeId, const char* fmt, ...) {
|
||||
va_list ap;
|
||||
StringTmp<256> sb;
|
||||
|
||||
va_start(ap, fmt);
|
||||
sb.appendVFormat(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return _newReg(out, typeId, sb.data());
|
||||
}
|
||||
|
||||
Error BaseCompiler::_newReg(BaseReg* out, const BaseReg& ref, const char* name) {
|
||||
out->reset();
|
||||
|
||||
RegInfo regInfo;
|
||||
uint32_t typeId;
|
||||
|
||||
if (isVirtRegValid(ref)) {
|
||||
VirtReg* vRef = virtRegByReg(ref);
|
||||
typeId = vRef->typeId();
|
||||
|
||||
// NOTE: It's possible to cast one register type to another if it's the
|
||||
// same register group. However, VirtReg always contains the TypeId that
|
||||
// was used to create the register. This means that in some cases we may
|
||||
// end up having different size of `ref` and `vRef`. In such case we
|
||||
// adjust the TypeId to match the `ref` register type instead of the
|
||||
// original register type, which should be the expected behavior.
|
||||
uint32_t typeSize = Type::sizeOf(typeId);
|
||||
uint32_t refSize = ref.size();
|
||||
|
||||
if (typeSize != refSize) {
|
||||
if (Type::isInt(typeId)) {
|
||||
// GP register - change TypeId to match `ref`, but keep sign of `vRef`.
|
||||
switch (refSize) {
|
||||
case 1: typeId = Type::kIdI8 | (typeId & 1); break;
|
||||
case 2: typeId = Type::kIdI16 | (typeId & 1); break;
|
||||
case 4: typeId = Type::kIdI32 | (typeId & 1); break;
|
||||
case 8: typeId = Type::kIdI64 | (typeId & 1); break;
|
||||
default: typeId = Type::kIdVoid; break;
|
||||
}
|
||||
}
|
||||
else if (Type::isMmx(typeId)) {
|
||||
// MMX register - always use 64-bit.
|
||||
typeId = Type::kIdMmx64;
|
||||
}
|
||||
else if (Type::isMask(typeId)) {
|
||||
// Mask register - change TypeId to match `ref` size.
|
||||
switch (refSize) {
|
||||
case 1: typeId = Type::kIdMask8; break;
|
||||
case 2: typeId = Type::kIdMask16; break;
|
||||
case 4: typeId = Type::kIdMask32; break;
|
||||
case 8: typeId = Type::kIdMask64; break;
|
||||
default: typeId = Type::kIdVoid; break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// VEC register - change TypeId to match `ref` size, keep vector metadata.
|
||||
uint32_t elementTypeId = Type::baseOf(typeId);
|
||||
|
||||
switch (refSize) {
|
||||
case 16: typeId = Type::_kIdVec128Start + (elementTypeId - Type::kIdI8); break;
|
||||
case 32: typeId = Type::_kIdVec256Start + (elementTypeId - Type::kIdI8); break;
|
||||
case 64: typeId = Type::_kIdVec512Start + (elementTypeId - Type::kIdI8); break;
|
||||
default: typeId = Type::kIdVoid; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeId == Type::kIdVoid)
|
||||
return reportError(DebugUtils::errored(kErrorInvalidState));
|
||||
}
|
||||
}
|
||||
else {
|
||||
typeId = ref.type();
|
||||
}
|
||||
|
||||
Error err = ArchUtils::typeIdToRegInfo(arch(), typeId, &typeId, ®Info);
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
return reportError(err);
|
||||
|
||||
VirtReg* vReg;
|
||||
ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regInfo.signature(), name));
|
||||
|
||||
out->_initReg(regInfo.signature(), vReg->id());
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::_newRegFmt(BaseReg* out, const BaseReg& ref, const char* fmt, ...) {
|
||||
va_list ap;
|
||||
StringTmp<256> sb;
|
||||
|
||||
va_start(ap, fmt);
|
||||
sb.appendVFormat(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return _newReg(out, ref, sb.data());
|
||||
}
|
||||
|
||||
Error BaseCompiler::_newStack(BaseMem* out, uint32_t size, uint32_t alignment, const char* name) {
|
||||
out->reset();
|
||||
|
||||
if (size == 0)
|
||||
return reportError(DebugUtils::errored(kErrorInvalidArgument));
|
||||
|
||||
if (alignment == 0)
|
||||
alignment = 1;
|
||||
|
||||
if (!Support::isPowerOf2(alignment))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidArgument));
|
||||
|
||||
if (alignment > 64)
|
||||
alignment = 64;
|
||||
|
||||
VirtReg* vReg;
|
||||
ASMJIT_PROPAGATE(newVirtReg(&vReg, 0, 0, name));
|
||||
|
||||
vReg->_virtSize = size;
|
||||
vReg->_isStack = true;
|
||||
vReg->_alignment = uint8_t(alignment);
|
||||
|
||||
// Set the memory operand to GPD/GPQ and its id to VirtReg.
|
||||
*out = BaseMem(BaseMem::Decomposed { _gpRegInfo.type(), vReg->id(), BaseReg::kTypeNone, 0, 0, 0, BaseMem::kSignatureMemRegHomeFlag });
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::setStackSize(uint32_t virtId, uint32_t newSize, uint32_t newAlignment) {
|
||||
if (!isVirtIdValid(virtId))
|
||||
return DebugUtils::errored(kErrorInvalidVirtId);
|
||||
|
||||
if (newAlignment && !Support::isPowerOf2(newAlignment))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidArgument));
|
||||
|
||||
if (newAlignment > 64)
|
||||
newAlignment = 64;
|
||||
|
||||
VirtReg* vReg = virtRegById(virtId);
|
||||
if (newSize)
|
||||
vReg->_virtSize = newSize;
|
||||
|
||||
if (newAlignment)
|
||||
vReg->_alignment = uint8_t(newAlignment);
|
||||
|
||||
// This is required if the RAPass is already running. There is a chance that
|
||||
// a stack-slot has been already allocated and in that case it has to be
|
||||
// updated as well, otherwise we would allocate wrong amount of memory.
|
||||
RAWorkReg* workReg = vReg->_workReg;
|
||||
if (workReg && workReg->_stackSlot) {
|
||||
workReg->_stackSlot->_size = vReg->_virtSize;
|
||||
workReg->_stackSlot->_alignment = vReg->_alignment;
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::_newConst(BaseMem* out, uint32_t scope, const void* data, size_t size) {
|
||||
out->reset();
|
||||
ConstPoolNode** pPool;
|
||||
|
||||
if (scope == ConstPool::kScopeLocal)
|
||||
pPool = &_localConstPool;
|
||||
else if (scope == ConstPool::kScopeGlobal)
|
||||
pPool = &_globalConstPool;
|
||||
else
|
||||
return reportError(DebugUtils::errored(kErrorInvalidArgument));
|
||||
|
||||
if (!*pPool)
|
||||
ASMJIT_PROPAGATE(_newConstPoolNode(pPool));
|
||||
|
||||
ConstPoolNode* pool = *pPool;
|
||||
size_t off;
|
||||
Error err = pool->add(data, size, off);
|
||||
|
||||
if (ASMJIT_UNLIKELY(err))
|
||||
return reportError(err);
|
||||
|
||||
*out = BaseMem(BaseMem::Decomposed {
|
||||
Label::kLabelTag, // Base type.
|
||||
pool->labelId(), // Base id.
|
||||
0, // Index type.
|
||||
0, // Index id.
|
||||
int32_t(off), // Offset.
|
||||
uint32_t(size), // Size.
|
||||
0 // Flags.
|
||||
});
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
void BaseCompiler::rename(const BaseReg& reg, const char* fmt, ...) {
|
||||
if (!reg.isVirtReg()) return;
|
||||
|
||||
VirtReg* vReg = virtRegById(reg.id());
|
||||
if (!vReg) return;
|
||||
|
||||
if (fmt && fmt[0] != '\0') {
|
||||
char buf[128];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
vReg->_name.setData(&_dataZone, buf, SIZE_MAX);
|
||||
}
|
||||
else {
|
||||
BaseCompiler_assignGenericName(this, vReg);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseCompiler - Jump Annotations]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseCompiler::newJumpNode(JumpNode** out, uint32_t instId, uint32_t instOptions, const Operand_& o0, JumpAnnotation* annotation) {
|
||||
JumpNode* node = _allocator.allocT<JumpNode>();
|
||||
uint32_t opCount = 1;
|
||||
|
||||
*out = node;
|
||||
if (ASMJIT_UNLIKELY(!node))
|
||||
return reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
|
||||
node = new(node) JumpNode(this, instId, instOptions, opCount, annotation);
|
||||
node->setOp(0, o0);
|
||||
node->resetOpRange(opCount, JumpNode::kBaseOpCapacity);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::emitAnnotatedJump(uint32_t instId, const Operand_& o0, JumpAnnotation* annotation) {
|
||||
uint32_t options = instOptions() | forcedInstOptions();
|
||||
RegOnly extra = extraReg();
|
||||
const char* comment = inlineComment();
|
||||
|
||||
resetInstOptions();
|
||||
resetInlineComment();
|
||||
resetExtraReg();
|
||||
|
||||
JumpNode* node;
|
||||
ASMJIT_PROPAGATE(newJumpNode(&node, instId, options, o0, annotation));
|
||||
|
||||
node->setExtraReg(extra);
|
||||
if (comment)
|
||||
node->setInlineComment(static_cast<char*>(_dataZone.dup(comment, strlen(comment), true)));
|
||||
|
||||
addNode(node);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
JumpAnnotation* BaseCompiler::newJumpAnnotation() {
|
||||
if (_jumpAnnotations.grow(&_allocator, 1) != kErrorOk) {
|
||||
reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t id = _jumpAnnotations.size();
|
||||
JumpAnnotation* jumpAnnotation = _allocator.newT<JumpAnnotation>(this, id);
|
||||
|
||||
if (!jumpAnnotation) {
|
||||
reportError(DebugUtils::errored(kErrorOutOfMemory));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
_jumpAnnotations.appendUnsafe(jumpAnnotation);
|
||||
return jumpAnnotation;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseCompiler - Events]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseCompiler::onAttach(CodeHolder* code) noexcept {
|
||||
ASMJIT_PROPAGATE(Base::onAttach(code));
|
||||
|
||||
const ArchTraits& archTraits = ArchTraits::byArch(code->arch());
|
||||
uint32_t nativeRegType = Environment::is32Bit(code->arch()) ? BaseReg::kTypeGp32 : BaseReg::kTypeGp64;
|
||||
_gpRegInfo.setSignature(archTraits.regTypeToSignature(nativeRegType));
|
||||
|
||||
Error err = addPassT<GlobalConstPoolPass>();
|
||||
if (ASMJIT_UNLIKELY(err)) {
|
||||
onDetach(code);
|
||||
return err;
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseCompiler::onDetach(CodeHolder* code) noexcept {
|
||||
_func = nullptr;
|
||||
_localConstPool = nullptr;
|
||||
_globalConstPool = nullptr;
|
||||
|
||||
_vRegArray.reset();
|
||||
_vRegZone.reset();
|
||||
|
||||
return Base::onDetach(code);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::FuncPass - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
FuncPass::FuncPass(const char* name) noexcept
|
||||
: Pass(name) {}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::FuncPass - Run]
|
||||
// ============================================================================
|
||||
|
||||
Error FuncPass::run(Zone* zone, Logger* logger) {
|
||||
BaseNode* node = cb()->firstNode();
|
||||
if (!node) return kErrorOk;
|
||||
|
||||
do {
|
||||
if (node->type() == BaseNode::kNodeFunc) {
|
||||
FuncNode* func = node->as<FuncNode>();
|
||||
node = func->endNode();
|
||||
ASMJIT_PROPAGATE(runOnFunction(zone, logger, func));
|
||||
}
|
||||
|
||||
// Find a function by skipping all nodes that are not `kNodeFunc`.
|
||||
do {
|
||||
node = node->next();
|
||||
} while (node && node->type() != BaseNode::kNodeFunc);
|
||||
} while (node);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // !ASMJIT_NO_COMPILER
|
@ -0,0 +1,763 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_COMPILER_H_INCLUDED
|
||||
#define ASMJIT_CORE_COMPILER_H_INCLUDED
|
||||
|
||||
#include "../core/api-config.h"
|
||||
#ifndef ASMJIT_NO_COMPILER
|
||||
|
||||
#include "../core/assembler.h"
|
||||
#include "../core/builder.h"
|
||||
#include "../core/constpool.h"
|
||||
#include "../core/compilerdefs.h"
|
||||
#include "../core/func.h"
|
||||
#include "../core/inst.h"
|
||||
#include "../core/operand.h"
|
||||
#include "../core/support.h"
|
||||
#include "../core/zone.h"
|
||||
#include "../core/zonevector.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [Forward Declarations]
|
||||
// ============================================================================
|
||||
|
||||
class JumpAnnotation;
|
||||
class JumpNode;
|
||||
class FuncNode;
|
||||
class FuncRetNode;
|
||||
class InvokeNode;
|
||||
|
||||
//! \addtogroup asmjit_compiler
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseCompiler]
|
||||
// ============================================================================
|
||||
|
||||
//! Code emitter that uses virtual registers and performs register allocation.
|
||||
//!
|
||||
//! Compiler is a high-level code-generation tool that provides register
|
||||
//! allocation and automatic handling of function calling conventions. It was
|
||||
//! primarily designed for merging multiple parts of code into a function
|
||||
//! without worrying about registers and function calling conventions.
|
||||
//!
|
||||
//! BaseCompiler can be used, with a minimum effort, to handle 32-bit and
|
||||
//! 64-bit code generation within a single code base.
|
||||
//!
|
||||
//! BaseCompiler is based on BaseBuilder and contains all the features it
|
||||
//! provides. It means that the code it stores can be modified (removed, added,
|
||||
//! injected) and analyzed. When the code is finalized the compiler can emit
|
||||
//! the code into an Assembler to translate the abstract representation into a
|
||||
//! machine code.
|
||||
//!
|
||||
//! Check out architecture specific compilers for more details and examples:
|
||||
//!
|
||||
//! - \ref x86::Compiler - X86/X64 compiler implementation.
|
||||
class ASMJIT_VIRTAPI BaseCompiler : public BaseBuilder {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(BaseCompiler)
|
||||
typedef BaseBuilder Base;
|
||||
|
||||
//! Current function.
|
||||
FuncNode* _func;
|
||||
//! Allocates `VirtReg` objects.
|
||||
Zone _vRegZone;
|
||||
//! Stores array of `VirtReg` pointers.
|
||||
ZoneVector<VirtReg*> _vRegArray;
|
||||
//! Stores jump annotations.
|
||||
ZoneVector<JumpAnnotation*> _jumpAnnotations;
|
||||
|
||||
//! Local constant pool, flushed at the end of each function.
|
||||
ConstPoolNode* _localConstPool;
|
||||
//! Global constant pool, flushed by `finalize()`.
|
||||
ConstPoolNode* _globalConstPool;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
//! Creates a new `BaseCompiler` instance.
|
||||
ASMJIT_API BaseCompiler() noexcept;
|
||||
//! Destroys the `BaseCompiler` instance.
|
||||
ASMJIT_API virtual ~BaseCompiler() noexcept;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Function Management
|
||||
//! \{
|
||||
|
||||
//! Returns the current function.
|
||||
inline FuncNode* func() const noexcept { return _func; }
|
||||
|
||||
//! Creates a new \ref FuncNode.
|
||||
ASMJIT_API Error _newFuncNode(FuncNode** out, const FuncSignature& signature);
|
||||
//! Creates a new \ref FuncNode adds it to the compiler.
|
||||
ASMJIT_API Error _addFuncNode(FuncNode** out, const FuncSignature& signature);
|
||||
|
||||
//! Creates a new \ref FuncRetNode.
|
||||
ASMJIT_API Error _newRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1);
|
||||
//! Creates a new \ref FuncRetNode and adds it to the compiler.
|
||||
ASMJIT_API Error _addRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1);
|
||||
|
||||
//! Creates a new \ref FuncNode with the given `signature` and returns it.
|
||||
inline FuncNode* newFunc(const FuncSignature& signature) {
|
||||
FuncNode* node;
|
||||
_newFuncNode(&node, signature);
|
||||
return node;
|
||||
}
|
||||
|
||||
//! Creates a new \ref FuncNode with the given `signature`, adds it to the
|
||||
//! compiler by using the \ref addFunc(FuncNode*) overload, and returns it.
|
||||
inline FuncNode* addFunc(const FuncSignature& signature) {
|
||||
FuncNode* node;
|
||||
_addFuncNode(&node, signature);
|
||||
return node;
|
||||
}
|
||||
|
||||
//! Adds a function `node` to the instruction stream.
|
||||
ASMJIT_API FuncNode* addFunc(FuncNode* func);
|
||||
//! Emits a sentinel that marks the end of the current function.
|
||||
ASMJIT_API Error endFunc();
|
||||
|
||||
ASMJIT_API Error _setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg);
|
||||
|
||||
//! Sets a function argument at `argIndex` to `reg`.
|
||||
inline Error setArg(size_t argIndex, const BaseReg& reg) { return _setArg(argIndex, 0, reg); }
|
||||
//! Sets a function argument at `argIndex` at `valueIndex` to `reg`.
|
||||
inline Error setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) { return _setArg(argIndex, valueIndex, reg); }
|
||||
|
||||
inline FuncRetNode* newRet(const Operand_& o0, const Operand_& o1) {
|
||||
FuncRetNode* node;
|
||||
_newRetNode(&node, o0, o1);
|
||||
return node;
|
||||
}
|
||||
|
||||
inline FuncRetNode* addRet(const Operand_& o0, const Operand_& o1) {
|
||||
FuncRetNode* node;
|
||||
_addRetNode(&node, o0, o1);
|
||||
return node;
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Function Invocation
|
||||
//! \{
|
||||
|
||||
//! Creates a new \ref InvokeNode.
|
||||
ASMJIT_API Error _newInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature);
|
||||
//! Creates a new \ref InvokeNode and adds it to Compiler.
|
||||
ASMJIT_API Error _addInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature);
|
||||
|
||||
//! Creates a new `InvokeNode`.
|
||||
inline InvokeNode* newCall(uint32_t instId, const Operand_& o0, const FuncSignature& signature) {
|
||||
InvokeNode* node;
|
||||
_newInvokeNode(&node, instId, o0, signature);
|
||||
return node;
|
||||
}
|
||||
|
||||
//! Adds a new `InvokeNode`.
|
||||
inline InvokeNode* addCall(uint32_t instId, const Operand_& o0, const FuncSignature& signature) {
|
||||
InvokeNode* node;
|
||||
_addInvokeNode(&node, instId, o0, signature);
|
||||
return node;
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Virtual Registers
|
||||
//! \{
|
||||
|
||||
//! Creates a new virtual register representing the given `typeId` and `signature`.
|
||||
//!
|
||||
//! \note This function is public, but it's not generally recommended to be used
|
||||
//! by AsmJit users, use architecture-specific `newReg()` functionality instead
|
||||
//! or functions like \ref _newReg() and \ref _newRegFmt().
|
||||
ASMJIT_API Error newVirtReg(VirtReg** out, uint32_t typeId, uint32_t signature, const char* name);
|
||||
|
||||
//! Creates a new virtual register of the given `typeId` and stores it to `out` operand.
|
||||
ASMJIT_API Error _newReg(BaseReg* out, uint32_t typeId, const char* name = nullptr);
|
||||
|
||||
//! Creates a new virtual register of the given `typeId` and stores it to `out` operand.
|
||||
//!
|
||||
//! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments.
|
||||
ASMJIT_API Error _newRegFmt(BaseReg* out, uint32_t typeId, const char* fmt, ...);
|
||||
|
||||
//! Creates a new virtual register compatible with the provided reference register `ref`.
|
||||
ASMJIT_API Error _newReg(BaseReg* out, const BaseReg& ref, const char* name = nullptr);
|
||||
|
||||
//! Creates a new virtual register compatible with the provided reference register `ref`.
|
||||
//!
|
||||
//! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments.
|
||||
ASMJIT_API Error _newRegFmt(BaseReg* out, const BaseReg& ref, const char* fmt, ...);
|
||||
|
||||
//! Tests whether the given `id` is a valid virtual register id.
|
||||
inline bool isVirtIdValid(uint32_t id) const noexcept {
|
||||
uint32_t index = Operand::virtIdToIndex(id);
|
||||
return index < _vRegArray.size();
|
||||
}
|
||||
//! Tests whether the given `reg` is a virtual register having a valid id.
|
||||
inline bool isVirtRegValid(const BaseReg& reg) const noexcept {
|
||||
return isVirtIdValid(reg.id());
|
||||
}
|
||||
|
||||
//! Returns \ref VirtReg associated with the given `id`.
|
||||
inline VirtReg* virtRegById(uint32_t id) const noexcept {
|
||||
ASMJIT_ASSERT(isVirtIdValid(id));
|
||||
return _vRegArray[Operand::virtIdToIndex(id)];
|
||||
}
|
||||
|
||||
//! Returns \ref VirtReg associated with the given `reg`.
|
||||
inline VirtReg* virtRegByReg(const BaseReg& reg) const noexcept { return virtRegById(reg.id()); }
|
||||
|
||||
//! Returns \ref VirtReg associated with the given virtual register `index`.
|
||||
//!
|
||||
//! \note This is not the same as virtual register id. The conversion between
|
||||
//! id and its index is implemented by \ref Operand_::virtIdToIndex() and \ref
|
||||
//! Operand_::indexToVirtId() functions.
|
||||
inline VirtReg* virtRegByIndex(uint32_t index) const noexcept { return _vRegArray[index]; }
|
||||
|
||||
//! Returns an array of all virtual registers managed by the Compiler.
|
||||
inline const ZoneVector<VirtReg*>& virtRegs() const noexcept { return _vRegArray; }
|
||||
|
||||
//! \name Stack
|
||||
//! \{
|
||||
|
||||
//! Creates a new stack of the given `size` and `alignment` and stores it to `out`.
|
||||
//!
|
||||
//! \note `name` can be used to give the stack a name, for debugging purposes.
|
||||
ASMJIT_API Error _newStack(BaseMem* out, uint32_t size, uint32_t alignment, const char* name = nullptr);
|
||||
|
||||
//! Updates the stack size of a stack created by `_newStack()` by its `virtId`.
|
||||
ASMJIT_API Error setStackSize(uint32_t virtId, uint32_t newSize, uint32_t newAlignment = 0);
|
||||
|
||||
//! Updates the stack size of a stack created by `_newStack()`.
|
||||
inline Error setStackSize(const BaseMem& mem, uint32_t newSize, uint32_t newAlignment = 0) {
|
||||
return setStackSize(mem.id(), newSize, newAlignment);
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Constants
|
||||
//! \{
|
||||
|
||||
//! Creates a new constant of the given `scope` (see \ref ConstPool::Scope).
|
||||
//!
|
||||
//! This function adds a constant of the given `size` to the built-in \ref
|
||||
//! ConstPool and stores the reference to that constant to the `out` operand.
|
||||
ASMJIT_API Error _newConst(BaseMem* out, uint32_t scope, const void* data, size_t size);
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Miscellaneous
|
||||
//! \{
|
||||
|
||||
//! Rename the given virtual register `reg` to a formatted string `fmt`.
|
||||
ASMJIT_API void rename(const BaseReg& reg, const char* fmt, ...);
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Jump Annotations
|
||||
//! \{
|
||||
|
||||
inline const ZoneVector<JumpAnnotation*>& jumpAnnotations() const noexcept {
|
||||
return _jumpAnnotations;
|
||||
}
|
||||
|
||||
ASMJIT_API Error newJumpNode(JumpNode** out, uint32_t instId, uint32_t instOptions, const Operand_& o0, JumpAnnotation* annotation);
|
||||
ASMJIT_API Error emitAnnotatedJump(uint32_t instId, const Operand_& o0, JumpAnnotation* annotation);
|
||||
|
||||
//! Returns a new `JumpAnnotation` instance, which can be used to aggregate
|
||||
//! possible targets of a jump where the target is not a label, for example
|
||||
//! to implement jump tables.
|
||||
ASMJIT_API JumpAnnotation* newJumpAnnotation();
|
||||
|
||||
//! \}
|
||||
|
||||
#ifndef ASMJIT_NO_DEPRECATED
|
||||
ASMJIT_DEPRECATED("alloc() has no effect, it will be removed in the future")
|
||||
inline void alloc(BaseReg&) {}
|
||||
ASMJIT_DEPRECATED("spill() has no effect, it will be removed in the future")
|
||||
inline void spill(BaseReg&) {}
|
||||
#endif // !ASMJIT_NO_DEPRECATED
|
||||
|
||||
//! \name Events
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error onAttach(CodeHolder* code) noexcept override;
|
||||
ASMJIT_API Error onDetach(CodeHolder* code) noexcept override;
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::JumpAnnotation]
|
||||
// ============================================================================
|
||||
|
||||
//! Jump annotation used to annotate jumps.
|
||||
//!
|
||||
//! \ref BaseCompiler allows to emit jumps where the target is either register
|
||||
//! or memory operand. Such jumps cannot be trivially inspected, so instead of
|
||||
//! doing heuristics AsmJit allows to annotate such jumps with possible targets.
|
||||
//! Register allocator then use the annotation to construct control-flow, which
|
||||
//! is then used by liveness analysis and other tools to prepare ground for
|
||||
//! register allocation.
|
||||
class JumpAnnotation {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(JumpAnnotation)
|
||||
|
||||
//! Compiler that owns this JumpAnnotation.
|
||||
BaseCompiler* _compiler;
|
||||
//! Annotation identifier.
|
||||
uint32_t _annotationId;
|
||||
//! Vector of label identifiers, see \ref labelIds().
|
||||
ZoneVector<uint32_t> _labelIds;
|
||||
|
||||
inline JumpAnnotation(BaseCompiler* compiler, uint32_t annotationId) noexcept
|
||||
: _compiler(compiler),
|
||||
_annotationId(annotationId) {}
|
||||
|
||||
//! Returns the compiler that owns this JumpAnnotation.
|
||||
inline BaseCompiler* compiler() const noexcept { return _compiler; }
|
||||
//! Returns the annotation id.
|
||||
inline uint32_t annotationId() const noexcept { return _annotationId; }
|
||||
//! Returns a vector of label identifiers that lists all targets of the jump.
|
||||
const ZoneVector<uint32_t>& labelIds() const noexcept { return _labelIds; }
|
||||
|
||||
//! Tests whether the given `label` is a target of this JumpAnnotation.
|
||||
inline bool hasLabel(const Label& label) const noexcept { return hasLabelId(label.id()); }
|
||||
//! Tests whether the given `labelId` is a target of this JumpAnnotation.
|
||||
inline bool hasLabelId(uint32_t labelId) const noexcept { return _labelIds.contains(labelId); }
|
||||
|
||||
//! Adds the `label` to the list of targets of this JumpAnnotation.
|
||||
inline Error addLabel(const Label& label) noexcept { return addLabelId(label.id()); }
|
||||
//! Adds the `labelId` to the list of targets of this JumpAnnotation.
|
||||
inline Error addLabelId(uint32_t labelId) noexcept { return _labelIds.append(&_compiler->_allocator, labelId); }
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::JumpNode]
|
||||
// ============================================================================
|
||||
|
||||
//! Jump instruction with \ref JumpAnnotation.
|
||||
//!
|
||||
//! \note This node should be only used to represent jump where the jump target
|
||||
//! cannot be deduced by examining instruction operands. For example if the jump
|
||||
//! target is register or memory location. This pattern is often used to perform
|
||||
//! indirect jumps that use jump table, e.g. to implement `switch{}` statement.
|
||||
class JumpNode : public InstNode {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(JumpNode)
|
||||
|
||||
JumpAnnotation* _annotation;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
ASMJIT_INLINE JumpNode(BaseCompiler* cc, uint32_t instId, uint32_t options, uint32_t opCount, JumpAnnotation* annotation) noexcept
|
||||
: InstNode(cc, instId, options, opCount, kBaseOpCapacity),
|
||||
_annotation(annotation) {
|
||||
setType(kNodeJump);
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
//! Tests whether this JumpNode has associated a \ref JumpAnnotation.
|
||||
inline bool hasAnnotation() const noexcept { return _annotation != nullptr; }
|
||||
//! Returns the \ref JumpAnnotation associated with this jump, or `nullptr`.
|
||||
inline JumpAnnotation* annotation() const noexcept { return _annotation; }
|
||||
//! Sets the \ref JumpAnnotation associated with this jump to `annotation`.
|
||||
inline void setAnnotation(JumpAnnotation* annotation) noexcept { _annotation = annotation; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::FuncNode]
|
||||
// ============================================================================
|
||||
|
||||
//! Function node represents a function used by \ref BaseCompiler.
|
||||
//!
|
||||
//! A function is composed of the following:
|
||||
//!
|
||||
//! - Function entry, \ref FuncNode acts as a label, so the entry is implicit.
|
||||
//! To get the entry, simply use \ref FuncNode::label(), which is the same
|
||||
//! as \ref LabelNode::label().
|
||||
//!
|
||||
//! - Function exit, which is represented by \ref FuncNode::exitNode(). A
|
||||
//! helper function \ref FuncNode::exitLabel() exists and returns an exit
|
||||
//! label instead of node.
|
||||
//!
|
||||
//! - Function \ref FuncNode::endNode() sentinel. This node marks the end of
|
||||
//! a function - there should be no code that belongs to the function after
|
||||
//! this node, but the Compiler doesn't enforce that at the moment.
|
||||
//!
|
||||
//! - Function detail, see \ref FuncNode::detail().
|
||||
//!
|
||||
//! - Function frame, see \ref FuncNode::frame().
|
||||
//!
|
||||
//! - Function arguments mapped to virtual registers, see \ref FuncNode::args().
|
||||
//!
|
||||
//! In a node list, the function and its body looks like the following:
|
||||
//!
|
||||
//! \code{.unparsed}
|
||||
//! [...] - Anything before the function.
|
||||
//!
|
||||
//! [FuncNode] - Entry point of the function, acts as a label as well.
|
||||
//! <Prolog> - Prolog inserted by the register allocator.
|
||||
//! {...} - Function body - user code basically.
|
||||
//! [ExitLabel] - Exit label
|
||||
//! <Epilog> - Epilog inserted by the register allocator.
|
||||
//! <Return> - Return inserted by the register allocator.
|
||||
//! {...} - Can contain data or user code (error handling, special cases, ...).
|
||||
//! [FuncEnd] - End sentinel
|
||||
//!
|
||||
//! [...] - Anything after the function.
|
||||
//! \endcode
|
||||
//!
|
||||
//! When a function is added to the compiler by \ref BaseCompiler::addFunc() it
|
||||
//! actually inserts 3 nodes (FuncNode, ExitLabel, and FuncEnd) and sets the
|
||||
//! current cursor to be FuncNode. When \ref BaseCompiler::endFunc() is called
|
||||
//! the cursor is set to FuncEnd. This guarantees that user can use ExitLabel
|
||||
//! as a marker after additional code or data can be placed, and it's a common
|
||||
//! practice.
|
||||
class FuncNode : public LabelNode {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(FuncNode)
|
||||
|
||||
//! Arguments pack.
|
||||
struct ArgPack {
|
||||
VirtReg* _data[Globals::kMaxValuePack];
|
||||
|
||||
inline void reset() noexcept {
|
||||
for (size_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++)
|
||||
_data[valueIndex] = nullptr;
|
||||
}
|
||||
|
||||
inline VirtReg*& operator[](size_t valueIndex) noexcept { return _data[valueIndex]; }
|
||||
inline VirtReg* const& operator[](size_t valueIndex) const noexcept { return _data[valueIndex]; }
|
||||
};
|
||||
|
||||
//! Function detail.
|
||||
FuncDetail _funcDetail;
|
||||
//! Function frame.
|
||||
FuncFrame _frame;
|
||||
//! Function exit label.
|
||||
LabelNode* _exitNode;
|
||||
//! Function end (sentinel).
|
||||
SentinelNode* _end;
|
||||
|
||||
//! Argument packs.
|
||||
ArgPack* _args;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
//! Creates a new `FuncNode` instance.
|
||||
//!
|
||||
//! Always use `BaseCompiler::addFunc()` to create `FuncNode`.
|
||||
ASMJIT_INLINE FuncNode(BaseBuilder* cb) noexcept
|
||||
: LabelNode(cb),
|
||||
_funcDetail(),
|
||||
_frame(),
|
||||
_exitNode(nullptr),
|
||||
_end(nullptr),
|
||||
_args(nullptr) {
|
||||
setType(kNodeFunc);
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \{
|
||||
//! \name Accessors
|
||||
|
||||
//! Returns function exit `LabelNode`.
|
||||
inline LabelNode* exitNode() const noexcept { return _exitNode; }
|
||||
//! Returns function exit label.
|
||||
inline Label exitLabel() const noexcept { return _exitNode->label(); }
|
||||
|
||||
//! Returns "End of Func" sentinel.
|
||||
inline SentinelNode* endNode() const noexcept { return _end; }
|
||||
|
||||
//! Returns function declaration.
|
||||
inline FuncDetail& detail() noexcept { return _funcDetail; }
|
||||
//! Returns function declaration.
|
||||
inline const FuncDetail& detail() const noexcept { return _funcDetail; }
|
||||
|
||||
//! Returns function frame.
|
||||
inline FuncFrame& frame() noexcept { return _frame; }
|
||||
//! Returns function frame.
|
||||
inline const FuncFrame& frame() const noexcept { return _frame; }
|
||||
|
||||
//! Tests whether the function has a return value.
|
||||
inline bool hasRet() const noexcept { return _funcDetail.hasRet(); }
|
||||
//! Returns arguments count.
|
||||
inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); }
|
||||
|
||||
//! Returns argument packs.
|
||||
inline ArgPack* argPacks() const noexcept { return _args; }
|
||||
|
||||
//! Returns argument pack at `argIndex`.
|
||||
inline ArgPack& argPack(size_t argIndex) const noexcept {
|
||||
ASMJIT_ASSERT(argIndex < argCount());
|
||||
return _args[argIndex];
|
||||
}
|
||||
|
||||
//! Sets argument at `argIndex`.
|
||||
inline void setArg(size_t argIndex, VirtReg* vReg) noexcept {
|
||||
ASMJIT_ASSERT(argIndex < argCount());
|
||||
_args[argIndex][0] = vReg;
|
||||
}
|
||||
|
||||
//! Sets argument at `argIndex` and `valueIndex`.
|
||||
inline void setArg(size_t argIndex, size_t valueIndex, VirtReg* vReg) noexcept {
|
||||
ASMJIT_ASSERT(argIndex < argCount());
|
||||
_args[argIndex][valueIndex] = vReg;
|
||||
}
|
||||
|
||||
//! Resets argument pack at `argIndex`.
|
||||
inline void resetArg(size_t argIndex) noexcept {
|
||||
ASMJIT_ASSERT(argIndex < argCount());
|
||||
_args[argIndex].reset();
|
||||
}
|
||||
|
||||
//! Resets argument pack at `argIndex`.
|
||||
inline void resetArg(size_t argIndex, size_t valueIndex) noexcept {
|
||||
ASMJIT_ASSERT(argIndex < argCount());
|
||||
_args[argIndex][valueIndex] = nullptr;
|
||||
}
|
||||
|
||||
//! Returns function attributes.
|
||||
inline uint32_t attributes() const noexcept { return _frame.attributes(); }
|
||||
//! Adds `attrs` to the function attributes.
|
||||
inline void addAttributes(uint32_t attrs) noexcept { _frame.addAttributes(attrs); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::FuncRetNode]
|
||||
// ============================================================================
|
||||
|
||||
//! Function return, used by \ref BaseCompiler.
|
||||
class FuncRetNode : public InstNode {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(FuncRetNode)
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
//! Creates a new `FuncRetNode` instance.
|
||||
inline FuncRetNode(BaseBuilder* cb) noexcept : InstNode(cb, BaseInst::kIdAbstract, 0, 0) {
|
||||
_any._nodeType = kNodeFuncRet;
|
||||
}
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::InvokeNode]
|
||||
// ============================================================================
|
||||
|
||||
//! Function invocation, used by \ref BaseCompiler.
|
||||
class InvokeNode : public InstNode {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(InvokeNode)
|
||||
|
||||
//! Operand pack provides multiple operands that can be associated with a
|
||||
//! single return value of function argument. Sometims this is necessary to
|
||||
//! express an argument or return value that requires multiple registers, for
|
||||
//! example 64-bit value in 32-bit mode or passing / returning homogenous data
|
||||
//! structures.
|
||||
struct OperandPack {
|
||||
//! Operands.
|
||||
Operand_ _data[Globals::kMaxValuePack];
|
||||
|
||||
//! Reset the pack by resetting all operands in the pack.
|
||||
inline void reset() noexcept {
|
||||
for (size_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++)
|
||||
_data[valueIndex].reset();
|
||||
}
|
||||
|
||||
//! Returns an operand at the given `valueIndex`.
|
||||
inline Operand& operator[](size_t valueIndex) noexcept {
|
||||
ASMJIT_ASSERT(valueIndex < Globals::kMaxValuePack);
|
||||
return _data[valueIndex].as<Operand>();
|
||||
}
|
||||
|
||||
//! Returns an operand at the given `valueIndex` (const).
|
||||
const inline Operand& operator[](size_t valueIndex) const noexcept {
|
||||
ASMJIT_ASSERT(valueIndex < Globals::kMaxValuePack);
|
||||
return _data[valueIndex].as<Operand>();
|
||||
}
|
||||
};
|
||||
|
||||
//! Function detail.
|
||||
FuncDetail _funcDetail;
|
||||
//! Function return value(s).
|
||||
OperandPack _rets;
|
||||
//! Function arguments.
|
||||
OperandPack* _args;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
//! Creates a new `InvokeNode` instance.
|
||||
inline InvokeNode(BaseBuilder* cb, uint32_t instId, uint32_t options) noexcept
|
||||
: InstNode(cb, instId, options, kBaseOpCapacity),
|
||||
_funcDetail(),
|
||||
_args(nullptr) {
|
||||
setType(kNodeInvoke);
|
||||
_resetOps();
|
||||
_rets.reset();
|
||||
addFlags(kFlagIsRemovable);
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
//! Sets the function signature.
|
||||
inline Error init(const FuncSignature& signature, const Environment& environment) noexcept {
|
||||
return _funcDetail.init(signature, environment);
|
||||
}
|
||||
|
||||
//! Returns the function detail.
|
||||
inline FuncDetail& detail() noexcept { return _funcDetail; }
|
||||
//! Returns the function detail.
|
||||
inline const FuncDetail& detail() const noexcept { return _funcDetail; }
|
||||
|
||||
//! Returns the target operand.
|
||||
inline Operand& target() noexcept { return _opArray[0].as<Operand>(); }
|
||||
//! \overload
|
||||
inline const Operand& target() const noexcept { return _opArray[0].as<Operand>(); }
|
||||
|
||||
//! Returns the number of function return values.
|
||||
inline bool hasRet() const noexcept { return _funcDetail.hasRet(); }
|
||||
//! Returns the number of function arguments.
|
||||
inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); }
|
||||
|
||||
//! Returns operand pack representing function return value(s).
|
||||
inline OperandPack& retPack() noexcept { return _rets; }
|
||||
//! Returns operand pack representing function return value(s).
|
||||
inline const OperandPack& retPack() const noexcept { return _rets; }
|
||||
|
||||
//! Returns the return value at the given `valueIndex`.
|
||||
inline Operand& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; }
|
||||
//! \overload
|
||||
inline const Operand& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; }
|
||||
|
||||
//! Returns operand pack representing function return value(s).
|
||||
inline OperandPack& argPack(size_t argIndex) noexcept {
|
||||
ASMJIT_ASSERT(argIndex < argCount());
|
||||
return _args[argIndex];
|
||||
}
|
||||
//! \overload
|
||||
inline const OperandPack& argPack(size_t argIndex) const noexcept {
|
||||
ASMJIT_ASSERT(argIndex < argCount());
|
||||
return _args[argIndex];
|
||||
}
|
||||
|
||||
//! Returns a function argument at the given `argIndex`.
|
||||
inline Operand& arg(size_t argIndex, size_t valueIndex) noexcept {
|
||||
ASMJIT_ASSERT(argIndex < argCount());
|
||||
return _args[argIndex][valueIndex];
|
||||
}
|
||||
//! \overload
|
||||
inline const Operand& arg(size_t argIndex, size_t valueIndex) const noexcept {
|
||||
ASMJIT_ASSERT(argIndex < argCount());
|
||||
return _args[argIndex][valueIndex];
|
||||
}
|
||||
|
||||
//! Sets the function return value at `i` to `op`.
|
||||
inline void _setRet(size_t valueIndex, const Operand_& op) noexcept { _rets[valueIndex] = op; }
|
||||
//! Sets the function argument at `i` to `op`.
|
||||
inline void _setArg(size_t argIndex, size_t valueIndex, const Operand_& op) noexcept {
|
||||
ASMJIT_ASSERT(argIndex < argCount());
|
||||
_args[argIndex][valueIndex] = op;
|
||||
}
|
||||
|
||||
//! Sets the function return value at `valueIndex` to `reg`.
|
||||
inline void setRet(size_t valueIndex, const BaseReg& reg) noexcept { _setRet(valueIndex, reg); }
|
||||
|
||||
//! Sets the first function argument in a value-pack at `argIndex` to `reg`.
|
||||
inline void setArg(size_t argIndex, const BaseReg& reg) noexcept { _setArg(argIndex, 0, reg); }
|
||||
//! Sets the first function argument in a value-pack at `argIndex` to `imm`.
|
||||
inline void setArg(size_t argIndex, const Imm& imm) noexcept { _setArg(argIndex, 0, imm); }
|
||||
|
||||
//! Sets the function argument at `argIndex` and `valueIndex` to `reg`.
|
||||
inline void setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) noexcept { _setArg(argIndex, valueIndex, reg); }
|
||||
//! Sets the function argument at `argIndex` and `valueIndex` to `imm`.
|
||||
inline void setArg(size_t argIndex, size_t valueIndex, const Imm& imm) noexcept { _setArg(argIndex, valueIndex, imm); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::FuncPass]
|
||||
// ============================================================================
|
||||
|
||||
//! Function pass extends \ref Pass with \ref FuncPass::runOnFunction().
|
||||
class ASMJIT_VIRTAPI FuncPass : public Pass {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(FuncPass)
|
||||
typedef Pass Base;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
ASMJIT_API FuncPass(const char* name) noexcept;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
//! Returns the associated `BaseCompiler`.
|
||||
inline BaseCompiler* cc() const noexcept { return static_cast<BaseCompiler*>(_cb); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Run
|
||||
//! \{
|
||||
|
||||
//! Calls `runOnFunction()` on each `FuncNode` node found.
|
||||
ASMJIT_API Error run(Zone* zone, Logger* logger) override;
|
||||
|
||||
//! Called once per `FuncNode`.
|
||||
virtual Error runOnFunction(Zone* zone, Logger* logger, FuncNode* func) = 0;
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // !ASMJIT_NO_COMPILER
|
||||
#endif // ASMJIT_CORE_COMPILER_H_INCLUDED
|
@ -0,0 +1,170 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_COMPILERDEFS_H_INCLUDED
|
||||
#define ASMJIT_CORE_COMPILERDEFS_H_INCLUDED
|
||||
|
||||
#include "../core/api-config.h"
|
||||
#include "../core/operand.h"
|
||||
#include "../core/zonestring.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [Forward Declarations]
|
||||
// ============================================================================
|
||||
|
||||
class RAWorkReg;
|
||||
|
||||
//! \addtogroup asmjit_compiler
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::VirtReg]
|
||||
// ============================================================================
|
||||
|
||||
//! Virtual register data, managed by \ref BaseCompiler.
|
||||
class VirtReg {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(VirtReg)
|
||||
|
||||
//! Virtual register id.
|
||||
uint32_t _id = 0;
|
||||
//! Virtual register info (signature).
|
||||
RegInfo _info = {};
|
||||
//! Virtual register size (can be smaller than `regInfo._size`).
|
||||
uint32_t _virtSize = 0;
|
||||
//! Virtual register alignment (for spilling).
|
||||
uint8_t _alignment = 0;
|
||||
//! Type-id.
|
||||
uint8_t _typeId = 0;
|
||||
//! Virtual register weight for alloc/spill decisions.
|
||||
uint8_t _weight = 1;
|
||||
//! True if this is a fixed register, never reallocated.
|
||||
uint8_t _isFixed : 1;
|
||||
//! True if the virtual register is only used as a stack (never accessed as register).
|
||||
uint8_t _isStack : 1;
|
||||
uint8_t _reserved : 6;
|
||||
|
||||
//! Virtual register name (user provided or automatically generated).
|
||||
ZoneString<16> _name {};
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// The following members are used exclusively by RAPass. They are initialized
|
||||
// when the VirtReg is created to NULL pointers and then changed during RAPass
|
||||
// execution. RAPass sets them back to NULL before it returns.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
//! Reference to `RAWorkReg`, used during register allocation.
|
||||
RAWorkReg* _workReg = nullptr;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline VirtReg(uint32_t id, uint32_t signature, uint32_t virtSize, uint32_t alignment, uint32_t typeId) noexcept
|
||||
: _id(id),
|
||||
_info { signature },
|
||||
_virtSize(virtSize),
|
||||
_alignment(uint8_t(alignment)),
|
||||
_typeId(uint8_t(typeId)),
|
||||
_isFixed(false),
|
||||
_isStack(false),
|
||||
_reserved(0) {}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
//! Returns the virtual register id.
|
||||
inline uint32_t id() const noexcept { return _id; }
|
||||
|
||||
//! Returns the virtual register name.
|
||||
inline const char* name() const noexcept { return _name.data(); }
|
||||
//! Returns the size of the virtual register name.
|
||||
inline uint32_t nameSize() const noexcept { return _name.size(); }
|
||||
|
||||
//! Returns a register information that wraps the register signature.
|
||||
inline const RegInfo& info() const noexcept { return _info; }
|
||||
//! Returns a virtual register type (maps to the physical register type as well).
|
||||
inline uint32_t type() const noexcept { return _info.type(); }
|
||||
//! Returns a virtual register group (maps to the physical register group as well).
|
||||
inline uint32_t group() const noexcept { return _info.group(); }
|
||||
|
||||
//! Returns a real size of the register this virtual register maps to.
|
||||
//!
|
||||
//! For example if this is a 128-bit SIMD register used for a scalar single
|
||||
//! precision floating point value then its virtSize would be 4, however, the
|
||||
//! `regSize` would still say 16 (128-bits), because it's the smallest size
|
||||
//! of that register type.
|
||||
inline uint32_t regSize() const noexcept { return _info.size(); }
|
||||
|
||||
//! Returns a register signature of this virtual register.
|
||||
inline uint32_t signature() const noexcept { return _info.signature(); }
|
||||
|
||||
//! Returns the virtual register size.
|
||||
//!
|
||||
//! The virtual register size describes how many bytes the virtual register
|
||||
//! needs to store its content. It can be smaller than the physical register
|
||||
//! size, see `regSize()`.
|
||||
inline uint32_t virtSize() const noexcept { return _virtSize; }
|
||||
|
||||
//! Returns the virtual register alignment.
|
||||
inline uint32_t alignment() const noexcept { return _alignment; }
|
||||
|
||||
//! Returns the virtual register type id, see `Type::Id`.
|
||||
inline uint32_t typeId() const noexcept { return _typeId; }
|
||||
|
||||
//! Returns the virtual register weight - the register allocator can use it
|
||||
//! as explicit hint for alloc/spill decisions.
|
||||
inline uint32_t weight() const noexcept { return _weight; }
|
||||
//! Sets the virtual register weight (0 to 255) - the register allocator can
|
||||
//! use it as explicit hint for alloc/spill decisions and initial bin-packing.
|
||||
inline void setWeight(uint32_t weight) noexcept { _weight = uint8_t(weight); }
|
||||
|
||||
//! Returns whether the virtual register is always allocated to a fixed
|
||||
//! physical register (and never reallocated).
|
||||
//!
|
||||
//! \note This is only used for special purposes and it's mostly internal.
|
||||
inline bool isFixed() const noexcept { return bool(_isFixed); }
|
||||
|
||||
//! Returns whether the virtual register is indeed a stack that only uses
|
||||
//! the virtual register id for making it accessible.
|
||||
//!
|
||||
//! \note It's an error if a stack is accessed as a register.
|
||||
inline bool isStack() const noexcept { return bool(_isStack); }
|
||||
|
||||
inline bool hasWorkReg() const noexcept { return _workReg != nullptr; }
|
||||
inline RAWorkReg* workReg() const noexcept { return _workReg; }
|
||||
inline void setWorkReg(RAWorkReg* workReg) noexcept { _workReg = workReg; }
|
||||
inline void resetWorkReg() noexcept { _workReg = nullptr; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_COMPILERDEFS_H_INCLUDED
|
||||
|
@ -0,0 +1,375 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#include "../core/constpool.h"
|
||||
#include "../core/support.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPool - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
ConstPool::ConstPool(Zone* zone) noexcept { reset(zone); }
|
||||
ConstPool::~ConstPool() noexcept {}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPool - Reset]
|
||||
// ============================================================================
|
||||
|
||||
void ConstPool::reset(Zone* zone) noexcept {
|
||||
_zone = zone;
|
||||
|
||||
size_t dataSize = 1;
|
||||
for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_tree); i++) {
|
||||
_tree[i].reset();
|
||||
_tree[i].setDataSize(dataSize);
|
||||
_gaps[i] = nullptr;
|
||||
dataSize <<= 1;
|
||||
}
|
||||
|
||||
_gapPool = nullptr;
|
||||
_size = 0;
|
||||
_alignment = 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPool - Ops]
|
||||
// ============================================================================
|
||||
|
||||
static ASMJIT_INLINE ConstPool::Gap* ConstPool_allocGap(ConstPool* self) noexcept {
|
||||
ConstPool::Gap* gap = self->_gapPool;
|
||||
if (!gap)
|
||||
return self->_zone->allocT<ConstPool::Gap>();
|
||||
|
||||
self->_gapPool = gap->_next;
|
||||
return gap;
|
||||
}
|
||||
|
||||
static ASMJIT_INLINE void ConstPool_freeGap(ConstPool* self, ConstPool::Gap* gap) noexcept {
|
||||
gap->_next = self->_gapPool;
|
||||
self->_gapPool = gap;
|
||||
}
|
||||
|
||||
static void ConstPool_addGap(ConstPool* self, size_t offset, size_t size) noexcept {
|
||||
ASMJIT_ASSERT(size > 0);
|
||||
|
||||
while (size > 0) {
|
||||
size_t gapIndex;
|
||||
size_t gapSize;
|
||||
|
||||
if (size >= 16 && Support::isAligned<size_t>(offset, 16)) {
|
||||
gapIndex = ConstPool::kIndex16;
|
||||
gapSize = 16;
|
||||
}
|
||||
else if (size >= 8 && Support::isAligned<size_t>(offset, 8)) {
|
||||
gapIndex = ConstPool::kIndex8;
|
||||
gapSize = 8;
|
||||
}
|
||||
else if (size >= 4 && Support::isAligned<size_t>(offset, 4)) {
|
||||
gapIndex = ConstPool::kIndex4;
|
||||
gapSize = 4;
|
||||
}
|
||||
else if (size >= 2 && Support::isAligned<size_t>(offset, 2)) {
|
||||
gapIndex = ConstPool::kIndex2;
|
||||
gapSize = 2;
|
||||
}
|
||||
else {
|
||||
gapIndex = ConstPool::kIndex1;
|
||||
gapSize = 1;
|
||||
}
|
||||
|
||||
// We don't have to check for errors here, if this failed nothing really
|
||||
// happened (just the gap won't be visible) and it will fail again at
|
||||
// place where the same check would generate `kErrorOutOfMemory` error.
|
||||
ConstPool::Gap* gap = ConstPool_allocGap(self);
|
||||
if (!gap)
|
||||
return;
|
||||
|
||||
gap->_next = self->_gaps[gapIndex];
|
||||
self->_gaps[gapIndex] = gap;
|
||||
|
||||
gap->_offset = offset;
|
||||
gap->_size = gapSize;
|
||||
|
||||
offset += gapSize;
|
||||
size -= gapSize;
|
||||
}
|
||||
}
|
||||
|
||||
Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept {
|
||||
size_t treeIndex;
|
||||
|
||||
if (size == 32)
|
||||
treeIndex = kIndex32;
|
||||
else if (size == 16)
|
||||
treeIndex = kIndex16;
|
||||
else if (size == 8)
|
||||
treeIndex = kIndex8;
|
||||
else if (size == 4)
|
||||
treeIndex = kIndex4;
|
||||
else if (size == 2)
|
||||
treeIndex = kIndex2;
|
||||
else if (size == 1)
|
||||
treeIndex = kIndex1;
|
||||
else
|
||||
return DebugUtils::errored(kErrorInvalidArgument);
|
||||
|
||||
ConstPool::Node* node = _tree[treeIndex].get(data);
|
||||
if (node) {
|
||||
dstOffset = node->_offset;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// Before incrementing the current offset try if there is a gap that can
|
||||
// be used for the requested data.
|
||||
size_t offset = ~size_t(0);
|
||||
size_t gapIndex = treeIndex;
|
||||
|
||||
while (gapIndex != kIndexCount - 1) {
|
||||
ConstPool::Gap* gap = _gaps[treeIndex];
|
||||
|
||||
// Check if there is a gap.
|
||||
if (gap) {
|
||||
size_t gapOffset = gap->_offset;
|
||||
size_t gapSize = gap->_size;
|
||||
|
||||
// Destroy the gap for now.
|
||||
_gaps[treeIndex] = gap->_next;
|
||||
ConstPool_freeGap(this, gap);
|
||||
|
||||
offset = gapOffset;
|
||||
ASMJIT_ASSERT(Support::isAligned<size_t>(offset, size));
|
||||
|
||||
gapSize -= size;
|
||||
if (gapSize > 0)
|
||||
ConstPool_addGap(this, gapOffset, gapSize);
|
||||
}
|
||||
|
||||
gapIndex++;
|
||||
}
|
||||
|
||||
if (offset == ~size_t(0)) {
|
||||
// Get how many bytes have to be skipped so the address is aligned accordingly
|
||||
// to the 'size'.
|
||||
size_t diff = Support::alignUpDiff<size_t>(_size, size);
|
||||
|
||||
if (diff != 0) {
|
||||
ConstPool_addGap(this, _size, diff);
|
||||
_size += diff;
|
||||
}
|
||||
|
||||
offset = _size;
|
||||
_size += size;
|
||||
}
|
||||
|
||||
// Add the initial node to the right index.
|
||||
node = ConstPool::Tree::_newNode(_zone, data, size, offset, false);
|
||||
if (!node) return DebugUtils::errored(kErrorOutOfMemory);
|
||||
|
||||
_tree[treeIndex].insert(node);
|
||||
_alignment = Support::max<size_t>(_alignment, size);
|
||||
|
||||
dstOffset = offset;
|
||||
|
||||
// Now create a bunch of shared constants that are based on the data pattern.
|
||||
// We stop at size 4, it probably doesn't make sense to split constants down
|
||||
// to 1 byte.
|
||||
size_t pCount = 1;
|
||||
while (size > 4) {
|
||||
size >>= 1;
|
||||
pCount <<= 1;
|
||||
|
||||
ASMJIT_ASSERT(treeIndex != 0);
|
||||
treeIndex--;
|
||||
|
||||
const uint8_t* pData = static_cast<const uint8_t*>(data);
|
||||
for (size_t i = 0; i < pCount; i++, pData += size) {
|
||||
node = _tree[treeIndex].get(pData);
|
||||
if (node) continue;
|
||||
|
||||
node = ConstPool::Tree::_newNode(_zone, pData, size, offset + (i * size), true);
|
||||
_tree[treeIndex].insert(node);
|
||||
}
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPool - Reset]
|
||||
// ============================================================================
|
||||
|
||||
struct ConstPoolFill {
|
||||
inline ConstPoolFill(uint8_t* dst, size_t dataSize) noexcept :
|
||||
_dst(dst),
|
||||
_dataSize(dataSize) {}
|
||||
|
||||
inline void operator()(const ConstPool::Node* node) noexcept {
|
||||
if (!node->_shared)
|
||||
memcpy(_dst + node->_offset, node->data(), _dataSize);
|
||||
}
|
||||
|
||||
uint8_t* _dst;
|
||||
size_t _dataSize;
|
||||
};
|
||||
|
||||
void ConstPool::fill(void* dst) const noexcept {
|
||||
// Clears possible gaps, asmjit should never emit garbage to the output.
|
||||
memset(dst, 0, _size);
|
||||
|
||||
ConstPoolFill filler(static_cast<uint8_t*>(dst), 1);
|
||||
for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_tree); i++) {
|
||||
_tree[i].forEach(filler);
|
||||
filler._dataSize <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPool - Unit]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_TEST)
|
||||
UNIT(const_pool) {
|
||||
Zone zone(32384 - Zone::kBlockOverhead);
|
||||
ConstPool pool(&zone);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t kCount = BrokenAPI::hasArg("--quick") ? 1000 : 1000000;
|
||||
|
||||
INFO("Adding %u constants to the pool", kCount);
|
||||
{
|
||||
size_t prevOffset;
|
||||
size_t curOffset;
|
||||
uint64_t c = 0x0101010101010101u;
|
||||
|
||||
EXPECT(pool.add(&c, 8, prevOffset) == kErrorOk);
|
||||
EXPECT(prevOffset == 0);
|
||||
|
||||
for (i = 1; i < kCount; i++) {
|
||||
c++;
|
||||
EXPECT(pool.add(&c, 8, curOffset) == kErrorOk);
|
||||
EXPECT(prevOffset + 8 == curOffset);
|
||||
EXPECT(pool.size() == (i + 1) * 8);
|
||||
prevOffset = curOffset;
|
||||
}
|
||||
|
||||
EXPECT(pool.alignment() == 8);
|
||||
}
|
||||
|
||||
INFO("Retrieving %u constants from the pool", kCount);
|
||||
{
|
||||
uint64_t c = 0x0101010101010101u;
|
||||
|
||||
for (i = 0; i < kCount; i++) {
|
||||
size_t offset;
|
||||
EXPECT(pool.add(&c, 8, offset) == kErrorOk);
|
||||
EXPECT(offset == i * 8);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
INFO("Checking if the constants were split into 4-byte patterns");
|
||||
{
|
||||
uint32_t c = 0x01010101;
|
||||
for (i = 0; i < kCount; i++) {
|
||||
size_t offset;
|
||||
EXPECT(pool.add(&c, 4, offset) == kErrorOk);
|
||||
EXPECT(offset == i * 8);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
INFO("Adding 2 byte constant to misalign the current offset");
|
||||
{
|
||||
uint16_t c = 0xFFFF;
|
||||
size_t offset;
|
||||
|
||||
EXPECT(pool.add(&c, 2, offset) == kErrorOk);
|
||||
EXPECT(offset == kCount * 8);
|
||||
EXPECT(pool.alignment() == 8);
|
||||
}
|
||||
|
||||
INFO("Adding 8 byte constant to check if pool gets aligned again");
|
||||
{
|
||||
uint64_t c = 0xFFFFFFFFFFFFFFFFu;
|
||||
size_t offset;
|
||||
|
||||
EXPECT(pool.add(&c, 8, offset) == kErrorOk);
|
||||
EXPECT(offset == kCount * 8 + 8);
|
||||
}
|
||||
|
||||
INFO("Adding 2 byte constant to verify the gap is filled");
|
||||
{
|
||||
uint16_t c = 0xFFFE;
|
||||
size_t offset;
|
||||
|
||||
EXPECT(pool.add(&c, 2, offset) == kErrorOk);
|
||||
EXPECT(offset == kCount * 8 + 2);
|
||||
EXPECT(pool.alignment() == 8);
|
||||
}
|
||||
|
||||
INFO("Checking reset functionality");
|
||||
{
|
||||
pool.reset(&zone);
|
||||
zone.reset();
|
||||
|
||||
EXPECT(pool.size() == 0);
|
||||
EXPECT(pool.alignment() == 0);
|
||||
}
|
||||
|
||||
INFO("Checking pool alignment when combined constants are added");
|
||||
{
|
||||
uint8_t bytes[32] = { 0 };
|
||||
size_t offset;
|
||||
|
||||
pool.add(bytes, 1, offset);
|
||||
EXPECT(pool.size() == 1);
|
||||
EXPECT(pool.alignment() == 1);
|
||||
EXPECT(offset == 0);
|
||||
|
||||
pool.add(bytes, 2, offset);
|
||||
EXPECT(pool.size() == 4);
|
||||
EXPECT(pool.alignment() == 2);
|
||||
EXPECT(offset == 2);
|
||||
|
||||
pool.add(bytes, 4, offset);
|
||||
EXPECT(pool.size() == 8);
|
||||
EXPECT(pool.alignment() == 4);
|
||||
EXPECT(offset == 4);
|
||||
|
||||
pool.add(bytes, 4, offset);
|
||||
EXPECT(pool.size() == 8);
|
||||
EXPECT(pool.alignment() == 4);
|
||||
EXPECT(offset == 4);
|
||||
|
||||
pool.add(bytes, 32, offset);
|
||||
EXPECT(pool.size() == 64);
|
||||
EXPECT(pool.alignment() == 32);
|
||||
EXPECT(offset == 32);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
@ -0,0 +1,262 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_CONSTPOOL_H_INCLUDED
|
||||
#define ASMJIT_CORE_CONSTPOOL_H_INCLUDED
|
||||
|
||||
#include "../core/support.h"
|
||||
#include "../core/zone.h"
|
||||
#include "../core/zonetree.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
//! \addtogroup asmjit_utilities
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPool]
|
||||
// ============================================================================
|
||||
|
||||
//! Constant pool.
|
||||
class ConstPool {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(ConstPool)
|
||||
|
||||
//! Constant pool scope.
|
||||
enum Scope : uint32_t {
|
||||
//! Local constant, always embedded right after the current function.
|
||||
kScopeLocal = 0,
|
||||
//! Global constant, embedded at the end of the currently compiled code.
|
||||
kScopeGlobal = 1
|
||||
};
|
||||
|
||||
//! \cond INTERNAL
|
||||
|
||||
//! Index of a given size in const-pool table.
|
||||
enum Index : uint32_t {
|
||||
kIndex1 = 0,
|
||||
kIndex2 = 1,
|
||||
kIndex4 = 2,
|
||||
kIndex8 = 3,
|
||||
kIndex16 = 4,
|
||||
kIndex32 = 5,
|
||||
kIndexCount = 6
|
||||
};
|
||||
|
||||
//! Zone-allocated const-pool gap created by two differently aligned constants.
|
||||
struct Gap {
|
||||
//! Pointer to the next gap
|
||||
Gap* _next;
|
||||
//! Offset of the gap.
|
||||
size_t _offset;
|
||||
//! Remaining bytes of the gap (basically a gap size).
|
||||
size_t _size;
|
||||
};
|
||||
|
||||
//! Zone-allocated const-pool node.
|
||||
class Node : public ZoneTreeNodeT<Node> {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(Node)
|
||||
|
||||
//! If this constant is shared with another.
|
||||
uint32_t _shared : 1;
|
||||
//! Data offset from the beginning of the pool.
|
||||
uint32_t _offset;
|
||||
|
||||
inline Node(size_t offset, bool shared) noexcept
|
||||
: ZoneTreeNodeT<Node>(),
|
||||
_shared(shared),
|
||||
_offset(uint32_t(offset)) {}
|
||||
|
||||
inline void* data() const noexcept {
|
||||
return static_cast<void*>(const_cast<ConstPool::Node*>(this) + 1);
|
||||
}
|
||||
};
|
||||
|
||||
//! Data comparer used internally.
|
||||
class Compare {
|
||||
public:
|
||||
size_t _dataSize;
|
||||
|
||||
inline Compare(size_t dataSize) noexcept
|
||||
: _dataSize(dataSize) {}
|
||||
|
||||
inline int operator()(const Node& a, const Node& b) const noexcept {
|
||||
return ::memcmp(a.data(), b.data(), _dataSize);
|
||||
}
|
||||
|
||||
inline int operator()(const Node& a, const void* data) const noexcept {
|
||||
return ::memcmp(a.data(), data, _dataSize);
|
||||
}
|
||||
};
|
||||
|
||||
//! Zone-allocated const-pool tree.
|
||||
struct Tree {
|
||||
//! RB tree.
|
||||
ZoneTree<Node> _tree;
|
||||
//! Size of the tree (number of nodes).
|
||||
size_t _size;
|
||||
//! Size of the data.
|
||||
size_t _dataSize;
|
||||
|
||||
inline explicit Tree(size_t dataSize = 0) noexcept
|
||||
: _tree(),
|
||||
_size(0),
|
||||
_dataSize(dataSize) {}
|
||||
|
||||
inline void reset() noexcept {
|
||||
_tree.reset();
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
inline bool empty() const noexcept { return _size == 0; }
|
||||
inline size_t size() const noexcept { return _size; }
|
||||
|
||||
inline void setDataSize(size_t dataSize) noexcept {
|
||||
ASMJIT_ASSERT(empty());
|
||||
_dataSize = dataSize;
|
||||
}
|
||||
|
||||
inline Node* get(const void* data) noexcept {
|
||||
Compare cmp(_dataSize);
|
||||
return _tree.get(data, cmp);
|
||||
}
|
||||
|
||||
inline void insert(Node* node) noexcept {
|
||||
Compare cmp(_dataSize);
|
||||
_tree.insert(node, cmp);
|
||||
_size++;
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
inline void forEach(Visitor& visitor) const noexcept {
|
||||
Node* node = _tree.root();
|
||||
if (!node) return;
|
||||
|
||||
Node* stack[Globals::kMaxTreeHeight];
|
||||
size_t top = 0;
|
||||
|
||||
for (;;) {
|
||||
Node* left = node->left();
|
||||
if (left != nullptr) {
|
||||
ASMJIT_ASSERT(top != Globals::kMaxTreeHeight);
|
||||
stack[top++] = node;
|
||||
|
||||
node = left;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
visitor(node);
|
||||
node = node->right();
|
||||
|
||||
if (node != nullptr)
|
||||
break;
|
||||
|
||||
if (top == 0)
|
||||
return;
|
||||
|
||||
node = stack[--top];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline Node* _newNode(Zone* zone, const void* data, size_t size, size_t offset, bool shared) noexcept {
|
||||
Node* node = zone->allocT<Node>(sizeof(Node) + size);
|
||||
if (ASMJIT_UNLIKELY(!node)) return nullptr;
|
||||
|
||||
node = new(node) Node(offset, shared);
|
||||
memcpy(node->data(), data, size);
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
//! \endcond
|
||||
|
||||
//! Zone allocator.
|
||||
Zone* _zone;
|
||||
//! Tree per size.
|
||||
Tree _tree[kIndexCount];
|
||||
//! Gaps per size.
|
||||
Gap* _gaps[kIndexCount];
|
||||
//! Gaps pool
|
||||
Gap* _gapPool;
|
||||
|
||||
//! Size of the pool (in bytes).
|
||||
size_t _size;
|
||||
//! Required pool alignment.
|
||||
size_t _alignment;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
ASMJIT_API ConstPool(Zone* zone) noexcept;
|
||||
ASMJIT_API ~ConstPool() noexcept;
|
||||
|
||||
ASMJIT_API void reset(Zone* zone) noexcept;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
//! Tests whether the constant-pool is empty.
|
||||
inline bool empty() const noexcept { return _size == 0; }
|
||||
//! Returns the size of the constant-pool in bytes.
|
||||
inline size_t size() const noexcept { return _size; }
|
||||
//! Returns minimum alignment.
|
||||
inline size_t alignment() const noexcept { return _alignment; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Utilities
|
||||
//! \{
|
||||
|
||||
//! Adds a constant to the constant pool.
|
||||
//!
|
||||
//! The constant must have known size, which is 1, 2, 4, 8, 16 or 32 bytes.
|
||||
//! The constant is added to the pool only if it doesn't not exist, otherwise
|
||||
//! cached value is returned.
|
||||
//!
|
||||
//! AsmJit is able to subdivide added constants, so for example if you add
|
||||
//! 8-byte constant 0x1122334455667788 it will create the following slots:
|
||||
//!
|
||||
//! 8-byte: 0x1122334455667788
|
||||
//! 4-byte: 0x11223344, 0x55667788
|
||||
//!
|
||||
//! The reason is that when combining MMX/SSE/AVX code some patterns are used
|
||||
//! frequently. However, AsmJit is not able to reallocate a constant that has
|
||||
//! been already added. For example if you try to add 4-byte constant and then
|
||||
//! 8-byte constant having the same 4-byte pattern as the previous one, two
|
||||
//! independent slots will be generated by the pool.
|
||||
ASMJIT_API Error add(const void* data, size_t size, size_t& dstOffset) noexcept;
|
||||
|
||||
//! Fills the destination with the content of this constant pool.
|
||||
ASMJIT_API void fill(void* dst) const noexcept;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_CONSTPOOL_H_INCLUDED
|
@ -0,0 +1,97 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#include "../core/cpuinfo.h"
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <errno.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::CpuInfo - Detect - CPU NumThreads]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(_WIN32)
|
||||
static inline uint32_t detectHWThreadCount() noexcept {
|
||||
SYSTEM_INFO info;
|
||||
::GetSystemInfo(&info);
|
||||
return info.dwNumberOfProcessors;
|
||||
}
|
||||
#elif defined(_SC_NPROCESSORS_ONLN)
|
||||
static inline uint32_t detectHWThreadCount() noexcept {
|
||||
long res = ::sysconf(_SC_NPROCESSORS_ONLN);
|
||||
return res <= 0 ? uint32_t(1) : uint32_t(res);
|
||||
}
|
||||
#else
|
||||
static inline uint32_t detectHWThreadCount() noexcept {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::CpuInfo - Detect - CPU Features]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_BUILD_X86) && ASMJIT_ARCH_X86
|
||||
namespace x86 { void detectCpu(CpuInfo& cpu) noexcept; }
|
||||
#endif
|
||||
|
||||
#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM
|
||||
namespace arm { void detectCpu(CpuInfo& cpu) noexcept; }
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::CpuInfo - Detect - Static Initializer]
|
||||
// ============================================================================
|
||||
|
||||
static uint32_t cpuInfoInitialized;
|
||||
static CpuInfo cpuInfoGlobal(Globals::NoInit);
|
||||
|
||||
const CpuInfo& CpuInfo::host() noexcept {
|
||||
// This should never cause a problem as the resulting information should
|
||||
// always be the same.
|
||||
if (!cpuInfoInitialized) {
|
||||
CpuInfo cpuInfoLocal;
|
||||
|
||||
#if defined(ASMJIT_BUILD_X86) && ASMJIT_ARCH_X86
|
||||
x86::detectCpu(cpuInfoLocal);
|
||||
#endif
|
||||
|
||||
#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM
|
||||
arm::detectCpu(cpuInfoLocal);
|
||||
#endif
|
||||
|
||||
cpuInfoLocal._hwThreadCount = detectHWThreadCount();
|
||||
cpuInfoGlobal = cpuInfoLocal;
|
||||
cpuInfoInitialized = 1;
|
||||
}
|
||||
|
||||
return cpuInfoGlobal;
|
||||
}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
@ -0,0 +1,154 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_CPUINFO_H_INCLUDED
|
||||
#define ASMJIT_CORE_CPUINFO_H_INCLUDED
|
||||
|
||||
#include "../core/archtraits.h"
|
||||
#include "../core/features.h"
|
||||
#include "../core/globals.h"
|
||||
#include "../core/string.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
//! \addtogroup asmjit_core
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::CpuInfo]
|
||||
// ============================================================================
|
||||
|
||||
//! CPU information.
|
||||
class CpuInfo {
|
||||
public:
|
||||
//! Architecture.
|
||||
uint8_t _arch;
|
||||
//! Sub-architecture.
|
||||
uint8_t _subArch;
|
||||
//! Reserved for future use.
|
||||
uint16_t _reserved;
|
||||
//! CPU family ID.
|
||||
uint32_t _familyId;
|
||||
//! CPU model ID.
|
||||
uint32_t _modelId;
|
||||
//! CPU brand ID.
|
||||
uint32_t _brandId;
|
||||
//! CPU stepping.
|
||||
uint32_t _stepping;
|
||||
//! Processor type.
|
||||
uint32_t _processorType;
|
||||
//! Maximum number of addressable IDs for logical processors.
|
||||
uint32_t _maxLogicalProcessors;
|
||||
//! Cache line size (in bytes).
|
||||
uint32_t _cacheLineSize;
|
||||
//! Number of hardware threads.
|
||||
uint32_t _hwThreadCount;
|
||||
|
||||
//! CPU vendor string.
|
||||
FixedString<16> _vendor;
|
||||
//! CPU brand string.
|
||||
FixedString<64> _brand;
|
||||
//! CPU features.
|
||||
BaseFeatures _features;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline CpuInfo() noexcept { reset(); }
|
||||
inline CpuInfo(const CpuInfo& other) noexcept = default;
|
||||
|
||||
inline explicit CpuInfo(Globals::NoInit_) noexcept
|
||||
: _features(Globals::NoInit) {};
|
||||
|
||||
//! Returns the host CPU information.
|
||||
ASMJIT_API static const CpuInfo& host() noexcept;
|
||||
|
||||
//! Initializes CpuInfo to the given architecture, see \ref Environment.
|
||||
inline void initArch(uint32_t arch, uint32_t subArch = 0u) noexcept {
|
||||
_arch = uint8_t(arch);
|
||||
_subArch = uint8_t(subArch);
|
||||
}
|
||||
|
||||
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline CpuInfo& operator=(const CpuInfo& other) noexcept = default;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
//! Returns the CPU architecture id, see \ref Environment::Arch.
|
||||
inline uint32_t arch() const noexcept { return _arch; }
|
||||
//! Returns the CPU architecture sub-id, see \ref Environment::SubArch.
|
||||
inline uint32_t subArch() const noexcept { return _subArch; }
|
||||
|
||||
//! Returns the CPU family ID.
|
||||
inline uint32_t familyId() const noexcept { return _familyId; }
|
||||
//! Returns the CPU model ID.
|
||||
inline uint32_t modelId() const noexcept { return _modelId; }
|
||||
//! Returns the CPU brand id.
|
||||
inline uint32_t brandId() const noexcept { return _brandId; }
|
||||
//! Returns the CPU stepping.
|
||||
inline uint32_t stepping() const noexcept { return _stepping; }
|
||||
//! Returns the processor type.
|
||||
inline uint32_t processorType() const noexcept { return _processorType; }
|
||||
//! Returns the number of maximum logical processors.
|
||||
inline uint32_t maxLogicalProcessors() const noexcept { return _maxLogicalProcessors; }
|
||||
|
||||
//! Returns the size of a cache line flush.
|
||||
inline uint32_t cacheLineSize() const noexcept { return _cacheLineSize; }
|
||||
//! Returns number of hardware threads available.
|
||||
inline uint32_t hwThreadCount() const noexcept { return _hwThreadCount; }
|
||||
|
||||
//! Returns the CPU vendor.
|
||||
inline const char* vendor() const noexcept { return _vendor.str; }
|
||||
//! Tests whether the CPU vendor is equal to `s`.
|
||||
inline bool isVendor(const char* s) const noexcept { return _vendor.eq(s); }
|
||||
|
||||
//! Returns the CPU brand string.
|
||||
inline const char* brand() const noexcept { return _brand.str; }
|
||||
|
||||
//! Returns all CPU features as `BaseFeatures`, cast to your arch-specific class
|
||||
//! if needed.
|
||||
template<typename T = BaseFeatures>
|
||||
inline const T& features() const noexcept { return _features.as<T>(); }
|
||||
|
||||
//! Tests whether the CPU has the given `feature`.
|
||||
inline bool hasFeature(uint32_t featureId) const noexcept { return _features.has(featureId); }
|
||||
//! Adds the given CPU `feature` to the list of this CpuInfo features.
|
||||
inline CpuInfo& addFeature(uint32_t featureId) noexcept { _features.add(featureId); return *this; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_CPUINFO_H_INCLUDED
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,351 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#include "../core/archtraits.h"
|
||||
#include "../core/emithelper_p.h"
|
||||
#include "../core/formatter.h"
|
||||
#include "../core/funcargscontext_p.h"
|
||||
#include "../core/radefs_p.h"
|
||||
|
||||
// Can be used for debugging...
|
||||
// #define ASMJIT_DUMP_ARGS_ASSIGNMENT
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitHelper - Formatting]
|
||||
// ============================================================================
|
||||
|
||||
#ifdef ASMJIT_DUMP_ARGS_ASSIGNMENT
|
||||
static void dumpFuncValue(String& sb, uint32_t arch, const FuncValue& value) noexcept {
|
||||
Formatter::formatTypeId(sb, value.typeId());
|
||||
sb.append('@');
|
||||
|
||||
if (value.isIndirect())
|
||||
sb.append('[');
|
||||
|
||||
if (value.isReg())
|
||||
Formatter::formatRegister(sb, 0, nullptr, arch, value.regType(), value.regId());
|
||||
else if (value.isStack())
|
||||
sb.appendFormat("[%d]", value.stackOffset());
|
||||
else
|
||||
sb.append("<none>");
|
||||
|
||||
if (value.isIndirect())
|
||||
sb.append(']');
|
||||
}
|
||||
|
||||
static void dumpAssignment(String& sb, const FuncArgsContext& ctx) noexcept {
|
||||
typedef FuncArgsContext::Var Var;
|
||||
|
||||
uint32_t arch = ctx.arch();
|
||||
uint32_t varCount = ctx.varCount();
|
||||
|
||||
for (uint32_t i = 0; i < varCount; i++) {
|
||||
const Var& var = ctx.var(i);
|
||||
const FuncValue& dst = var.out;
|
||||
const FuncValue& cur = var.cur;
|
||||
|
||||
sb.appendFormat("Var%u: ", i);
|
||||
dumpFuncValue(sb, arch, dst);
|
||||
sb.append(" <- ");
|
||||
dumpFuncValue(sb, arch, cur);
|
||||
|
||||
if (var.isDone())
|
||||
sb.append(" {Done}");
|
||||
|
||||
sb.append('\n');
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitHelper - EmitArgsAssignment]
|
||||
// ============================================================================
|
||||
|
||||
ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) {
|
||||
typedef FuncArgsContext::Var Var;
|
||||
typedef FuncArgsContext::WorkData WorkData;
|
||||
|
||||
enum WorkFlags : uint32_t {
|
||||
kWorkNone = 0x00,
|
||||
kWorkDidSome = 0x01,
|
||||
kWorkPending = 0x02,
|
||||
kWorkPostponed = 0x04
|
||||
};
|
||||
|
||||
uint32_t arch = frame.arch();
|
||||
const ArchTraits& archTraits = ArchTraits::byArch(arch);
|
||||
|
||||
RAConstraints constraints;
|
||||
FuncArgsContext ctx;
|
||||
|
||||
ASMJIT_PROPAGATE(constraints.init(arch));
|
||||
ASMJIT_PROPAGATE(ctx.initWorkData(frame, args, &constraints));
|
||||
|
||||
#ifdef ASMJIT_DUMP_ARGS_ASSIGNMENT
|
||||
{
|
||||
String sb;
|
||||
dumpAssignment(sb, ctx);
|
||||
printf("%s\n", sb.data());
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t varCount = ctx._varCount;
|
||||
WorkData* workData = ctx._workData;
|
||||
|
||||
uint32_t saVarId = ctx._saVarId;
|
||||
BaseReg sp = BaseReg::fromSignatureAndId(_emitter->_gpRegInfo.signature(), archTraits.spRegId());
|
||||
BaseReg sa = sp;
|
||||
|
||||
if (frame.hasDynamicAlignment()) {
|
||||
if (frame.hasPreservedFP())
|
||||
sa.setId(archTraits.fpRegId());
|
||||
else
|
||||
sa.setId(saVarId < varCount ? ctx._vars[saVarId].cur.regId() : frame.saRegId());
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Register to stack and stack to stack moves must be first as now we have
|
||||
// the biggest chance of having as many as possible unassigned registers.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
if (ctx._stackDstMask) {
|
||||
// Base address of all arguments passed by stack.
|
||||
BaseMem baseArgPtr(sa, int32_t(frame.saOffset(sa.id())));
|
||||
BaseMem baseStackPtr(sp, 0);
|
||||
|
||||
for (uint32_t varId = 0; varId < varCount; varId++) {
|
||||
Var& var = ctx._vars[varId];
|
||||
|
||||
if (!var.out.isStack())
|
||||
continue;
|
||||
|
||||
FuncValue& cur = var.cur;
|
||||
FuncValue& out = var.out;
|
||||
|
||||
ASMJIT_ASSERT(cur.isReg() || cur.isStack());
|
||||
BaseReg reg;
|
||||
|
||||
BaseMem dstStackPtr = baseStackPtr.cloneAdjusted(out.stackOffset());
|
||||
BaseMem srcStackPtr = baseArgPtr.cloneAdjusted(cur.stackOffset());
|
||||
|
||||
if (cur.isIndirect()) {
|
||||
if (cur.isStack()) {
|
||||
// TODO: Indirect stack.
|
||||
return DebugUtils::errored(kErrorInvalidAssignment);
|
||||
}
|
||||
else {
|
||||
srcStackPtr.setBaseId(cur.regId());
|
||||
}
|
||||
}
|
||||
|
||||
if (cur.isReg() && !cur.isIndirect()) {
|
||||
WorkData& wd = workData[archTraits.regTypeToGroup(cur.regType())];
|
||||
uint32_t rId = cur.regId();
|
||||
|
||||
reg.setSignatureAndId(archTraits.regTypeToSignature(cur.regType()), rId);
|
||||
wd.unassign(varId, rId);
|
||||
}
|
||||
else {
|
||||
// Stack to reg move - tricky since we move stack to stack we can decide which
|
||||
// register to use. In general we follow the rule that IntToInt moves will use
|
||||
// GP regs with possibility to signature or zero extend, and all other moves will
|
||||
// either use GP or VEC regs depending on the size of the move.
|
||||
RegInfo rInfo = getSuitableRegForMemToMemMove(arch, out.typeId(), cur.typeId());
|
||||
if (ASMJIT_UNLIKELY(!rInfo.isValid()))
|
||||
return DebugUtils::errored(kErrorInvalidState);
|
||||
|
||||
WorkData& wd = workData[rInfo.group()];
|
||||
uint32_t availableRegs = wd.availableRegs();
|
||||
if (ASMJIT_UNLIKELY(!availableRegs))
|
||||
return DebugUtils::errored(kErrorInvalidState);
|
||||
|
||||
uint32_t rId = Support::ctz(availableRegs);
|
||||
reg.setSignatureAndId(rInfo.signature(), rId);
|
||||
|
||||
ASMJIT_PROPAGATE(emitArgMove(reg, out.typeId(), srcStackPtr, cur.typeId()));
|
||||
}
|
||||
|
||||
if (cur.isIndirect() && cur.isReg())
|
||||
workData[BaseReg::kGroupGp].unassign(varId, cur.regId());
|
||||
|
||||
// Register to stack move.
|
||||
ASMJIT_PROPAGATE(emitRegMove(dstStackPtr, reg, cur.typeId()));
|
||||
var.markDone();
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Shuffle all registers that are currently assigned accordingly to target
|
||||
// assignment.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
uint32_t workFlags = kWorkNone;
|
||||
for (;;) {
|
||||
for (uint32_t varId = 0; varId < varCount; varId++) {
|
||||
Var& var = ctx._vars[varId];
|
||||
if (var.isDone() || !var.cur.isReg())
|
||||
continue;
|
||||
|
||||
FuncValue& cur = var.cur;
|
||||
FuncValue& out = var.out;
|
||||
|
||||
uint32_t curGroup = archTraits.regTypeToGroup(cur.regType());
|
||||
uint32_t outGroup = archTraits.regTypeToGroup(out.regType());
|
||||
|
||||
uint32_t curId = cur.regId();
|
||||
uint32_t outId = out.regId();
|
||||
|
||||
if (curGroup != outGroup) {
|
||||
// TODO: Conversion is not supported.
|
||||
return DebugUtils::errored(kErrorInvalidAssignment);
|
||||
}
|
||||
else {
|
||||
WorkData& wd = workData[outGroup];
|
||||
if (!wd.isAssigned(outId)) {
|
||||
EmitMove:
|
||||
ASMJIT_PROPAGATE(
|
||||
emitArgMove(
|
||||
BaseReg::fromSignatureAndId(archTraits.regTypeToSignature(out.regType()), outId), out.typeId(),
|
||||
BaseReg::fromSignatureAndId(archTraits.regTypeToSignature(cur.regType()), curId), cur.typeId()));
|
||||
|
||||
wd.reassign(varId, outId, curId);
|
||||
cur.initReg(out.regType(), outId, out.typeId());
|
||||
|
||||
if (outId == out.regId())
|
||||
var.markDone();
|
||||
workFlags |= kWorkDidSome | kWorkPending;
|
||||
}
|
||||
else {
|
||||
uint32_t altId = wd._physToVarId[outId];
|
||||
Var& altVar = ctx._vars[altId];
|
||||
|
||||
if (!altVar.out.isInitialized() || (altVar.out.isReg() && altVar.out.regId() == curId)) {
|
||||
// Only few architectures provide swap operations, and only for few register groups.
|
||||
if (archTraits.hasSwap(curGroup)) {
|
||||
uint32_t highestType = Support::max(cur.regType(), altVar.cur.regType());
|
||||
if (Support::isBetween<uint32_t>(highestType, BaseReg::kTypeGp8Lo, BaseReg::kTypeGp16))
|
||||
highestType = BaseReg::kTypeGp32;
|
||||
|
||||
uint32_t signature = archTraits.regTypeToSignature(highestType);
|
||||
ASMJIT_PROPAGATE(
|
||||
emitRegSwap(BaseReg::fromSignatureAndId(signature, outId),
|
||||
BaseReg::fromSignatureAndId(signature, curId)));
|
||||
wd.swap(varId, curId, altId, outId);
|
||||
cur.setRegId(outId);
|
||||
var.markDone();
|
||||
altVar.cur.setRegId(curId);
|
||||
|
||||
if (altVar.out.isInitialized())
|
||||
altVar.markDone();
|
||||
workFlags |= kWorkDidSome;
|
||||
}
|
||||
else {
|
||||
// If there is a scratch register it can be used to perform the swap.
|
||||
uint32_t availableRegs = wd.availableRegs();
|
||||
if (availableRegs) {
|
||||
uint32_t inOutRegs = wd.dstRegs();
|
||||
if (availableRegs & ~inOutRegs)
|
||||
availableRegs &= ~inOutRegs;
|
||||
outId = Support::ctz(availableRegs);
|
||||
goto EmitMove;
|
||||
}
|
||||
else {
|
||||
workFlags |= kWorkPending;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
workFlags |= kWorkPending;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(workFlags & kWorkPending))
|
||||
break;
|
||||
|
||||
// If we did nothing twice it means that something is really broken.
|
||||
if ((workFlags & (kWorkDidSome | kWorkPostponed)) == kWorkPostponed)
|
||||
return DebugUtils::errored(kErrorInvalidState);
|
||||
|
||||
workFlags = (workFlags & kWorkDidSome) ? kWorkNone : kWorkPostponed;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Load arguments passed by stack into registers. This is pretty simple and
|
||||
// it never requires multiple iterations like the previous phase.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
if (ctx._hasStackSrc) {
|
||||
uint32_t iterCount = 1;
|
||||
if (frame.hasDynamicAlignment() && !frame.hasPreservedFP())
|
||||
sa.setId(saVarId < varCount ? ctx._vars[saVarId].cur.regId() : frame.saRegId());
|
||||
|
||||
// Base address of all arguments passed by stack.
|
||||
BaseMem baseArgPtr(sa, int32_t(frame.saOffset(sa.id())));
|
||||
|
||||
for (uint32_t iter = 0; iter < iterCount; iter++) {
|
||||
for (uint32_t varId = 0; varId < varCount; varId++) {
|
||||
Var& var = ctx._vars[varId];
|
||||
if (var.isDone())
|
||||
continue;
|
||||
|
||||
if (var.cur.isStack()) {
|
||||
ASMJIT_ASSERT(var.out.isReg());
|
||||
|
||||
uint32_t outId = var.out.regId();
|
||||
uint32_t outType = var.out.regType();
|
||||
|
||||
uint32_t group = archTraits.regTypeToGroup(outType);
|
||||
WorkData& wd = ctx._workData[group];
|
||||
|
||||
if (outId == sa.id() && group == BaseReg::kGroupGp) {
|
||||
// This register will be processed last as we still need `saRegId`.
|
||||
if (iterCount == 1) {
|
||||
iterCount++;
|
||||
continue;
|
||||
}
|
||||
wd.unassign(wd._physToVarId[outId], outId);
|
||||
}
|
||||
|
||||
BaseReg dstReg = BaseReg::fromSignatureAndId(archTraits.regTypeToSignature(outType), outId);
|
||||
BaseMem srcMem = baseArgPtr.cloneAdjusted(var.cur.stackOffset());
|
||||
|
||||
ASMJIT_PROPAGATE(emitArgMove(
|
||||
dstReg, var.out.typeId(),
|
||||
srcMem, var.cur.typeId()));
|
||||
|
||||
wd.assign(varId, outId);
|
||||
var.cur.initReg(outType, outId, var.cur.typeId(), FuncValue::kFlagIsDone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
@ -0,0 +1,83 @@
|
||||
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_EMITHELPER_P_H_INCLUDED
|
||||
#define ASMJIT_CORE_EMITHELPER_P_H_INCLUDED
|
||||
|
||||
#include "../core/emitter.h"
|
||||
#include "../core/operand.h"
|
||||
#include "../core/type.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
//! \cond INTERNAL
|
||||
//! \addtogroup asmjit_core
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitHelper]
|
||||
// ============================================================================
|
||||
|
||||
//! Helper class that provides utilities for each supported architecture.
|
||||
class BaseEmitHelper {
|
||||
public:
|
||||
BaseEmitter* _emitter;
|
||||
|
||||
inline explicit BaseEmitHelper(BaseEmitter* emitter = nullptr) noexcept
|
||||
: _emitter(emitter) {}
|
||||
|
||||
inline BaseEmitter* emitter() const noexcept { return _emitter; }
|
||||
inline void setEmitter(BaseEmitter* emitter) noexcept { _emitter = emitter; }
|
||||
|
||||
//! Emits a pure move operation between two registers or the same type or
|
||||
//! between a register and its home slot. This function does not handle
|
||||
//! register conversion.
|
||||
virtual Error emitRegMove(
|
||||
const Operand_& dst_,
|
||||
const Operand_& src_, uint32_t typeId, const char* comment = nullptr) = 0;
|
||||
|
||||
//! Emits swap between two registers.
|
||||
virtual Error emitRegSwap(
|
||||
const BaseReg& a,
|
||||
const BaseReg& b, const char* comment = nullptr) = 0;
|
||||
|
||||
//! Emits move from a function argument (either register or stack) to a register.
|
||||
//!
|
||||
//! This function can handle the necessary conversion from one argument to
|
||||
//! another, and from one register type to another, if it's possible. Any
|
||||
//! attempt of conversion that requires third register of a different group
|
||||
//! (for example conversion from K to MMX on X86/X64) will fail.
|
||||
virtual Error emitArgMove(
|
||||
const BaseReg& dst_, uint32_t dstTypeId,
|
||||
const Operand_& src_, uint32_t srcTypeId, const char* comment = nullptr) = 0;
|
||||
|
||||
Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args);
|
||||
};
|
||||
|
||||
//! \}
|
||||
//! \endcond
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_EMITHELPER_P_H_INCLUDED
|
@ -0,0 +1,416 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#include "../core/emitterutils_p.h"
|
||||
#include "../core/errorhandler.h"
|
||||
#include "../core/logger.h"
|
||||
#include "../core/support.h"
|
||||
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
#include "../x86/x86emithelper_p.h"
|
||||
#include "../x86/x86instdb_p.h"
|
||||
#endif // ASMJIT_BUILD_X86
|
||||
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
#include "../arm/a64emithelper_p.h"
|
||||
#include "../arm/a64instdb.h"
|
||||
#endif // ASMJIT_BUILD_ARM
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
BaseEmitter::BaseEmitter(uint32_t emitterType) noexcept
|
||||
: _emitterType(uint8_t(emitterType)) {}
|
||||
|
||||
BaseEmitter::~BaseEmitter() noexcept {
|
||||
if (_code) {
|
||||
_addEmitterFlags(kFlagDestroyed);
|
||||
_code->detach(this);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter - Finalize]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseEmitter::finalize() {
|
||||
// Does nothing by default, overridden by `BaseBuilder` and `BaseCompiler`.
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter - Internals]
|
||||
// ============================================================================
|
||||
|
||||
static constexpr uint32_t kEmitterPreservedFlags = BaseEmitter::kFlagOwnLogger | BaseEmitter::kFlagOwnErrorHandler;
|
||||
|
||||
static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept {
|
||||
bool emitComments = false;
|
||||
bool hasValidationOptions = false;
|
||||
|
||||
if (self->emitterType() == BaseEmitter::kTypeAssembler) {
|
||||
// Assembler: Don't emit comments if logger is not attached.
|
||||
emitComments = self->_code != nullptr && self->_logger != nullptr;
|
||||
hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionAssembler);
|
||||
}
|
||||
else {
|
||||
// Builder/Compiler: Always emit comments, we cannot assume they won't be used.
|
||||
emitComments = self->_code != nullptr;
|
||||
hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionIntermediate);
|
||||
}
|
||||
|
||||
if (emitComments)
|
||||
self->_addEmitterFlags(BaseEmitter::kFlagLogComments);
|
||||
else
|
||||
self->_clearEmitterFlags(BaseEmitter::kFlagLogComments);
|
||||
|
||||
// The reserved option tells emitter (Assembler/Builder/Compiler) that there
|
||||
// may be either a border case (CodeHolder not attached, for example) or that
|
||||
// logging or validation is required.
|
||||
if (self->_code == nullptr || self->_logger || hasValidationOptions)
|
||||
self->_forcedInstOptions |= BaseInst::kOptionReserved;
|
||||
else
|
||||
self->_forcedInstOptions &= ~BaseInst::kOptionReserved;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter - Validation Options]
|
||||
// ============================================================================
|
||||
|
||||
void BaseEmitter::addValidationOptions(uint32_t options) noexcept {
|
||||
_validationOptions = uint8_t(_validationOptions | options);
|
||||
BaseEmitter_updateForcedOptions(this);
|
||||
}
|
||||
|
||||
void BaseEmitter::clearValidationOptions(uint32_t options) noexcept {
|
||||
_validationOptions = uint8_t(_validationOptions | options);
|
||||
BaseEmitter_updateForcedOptions(this);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter - Logging]
|
||||
// ============================================================================
|
||||
|
||||
void BaseEmitter::setLogger(Logger* logger) noexcept {
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (logger) {
|
||||
_logger = logger;
|
||||
_addEmitterFlags(kFlagOwnLogger);
|
||||
}
|
||||
else {
|
||||
_logger = nullptr;
|
||||
_clearEmitterFlags(kFlagOwnLogger);
|
||||
if (_code)
|
||||
_logger = _code->logger();
|
||||
}
|
||||
BaseEmitter_updateForcedOptions(this);
|
||||
#else
|
||||
DebugUtils::unused(logger);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter - Error Handling]
|
||||
// ============================================================================
|
||||
|
||||
void BaseEmitter::setErrorHandler(ErrorHandler* errorHandler) noexcept {
|
||||
if (errorHandler) {
|
||||
_errorHandler = errorHandler;
|
||||
_addEmitterFlags(kFlagOwnErrorHandler);
|
||||
}
|
||||
else {
|
||||
_errorHandler = nullptr;
|
||||
_clearEmitterFlags(kFlagOwnErrorHandler);
|
||||
if (_code)
|
||||
_errorHandler = _code->errorHandler();
|
||||
}
|
||||
}
|
||||
|
||||
Error BaseEmitter::reportError(Error err, const char* message) {
|
||||
ErrorHandler* eh = _errorHandler;
|
||||
if (eh) {
|
||||
if (!message)
|
||||
message = DebugUtils::errorAsString(err);
|
||||
eh->handleError(err, message, this);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter - Labels]
|
||||
// ============================================================================
|
||||
|
||||
Label BaseEmitter::labelByName(const char* name, size_t nameSize, uint32_t parentId) noexcept {
|
||||
return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : uint32_t(Globals::kInvalidId));
|
||||
}
|
||||
|
||||
bool BaseEmitter::isLabelValid(uint32_t labelId) const noexcept {
|
||||
return _code && labelId < _code->labelCount();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter - Emit (Low-Level)]
|
||||
// ============================================================================
|
||||
|
||||
using EmitterUtils::noExt;
|
||||
|
||||
Error BaseEmitter::_emitI(uint32_t instId) {
|
||||
return _emit(instId, noExt[0], noExt[1], noExt[2], noExt);
|
||||
}
|
||||
|
||||
Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0) {
|
||||
return _emit(instId, o0, noExt[1], noExt[2], noExt);
|
||||
}
|
||||
|
||||
Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1) {
|
||||
return _emit(instId, o0, o1, noExt[2], noExt);
|
||||
}
|
||||
|
||||
Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2) {
|
||||
return _emit(instId, o0, o1, o2, noExt);
|
||||
}
|
||||
|
||||
Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) {
|
||||
Operand_ opExt[3] = { o3 };
|
||||
return _emit(instId, o0, o1, o2, opExt);
|
||||
}
|
||||
|
||||
Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4) {
|
||||
Operand_ opExt[3] = { o3, o4 };
|
||||
return _emit(instId, o0, o1, o2, opExt);
|
||||
}
|
||||
|
||||
Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) {
|
||||
Operand_ opExt[3] = { o3, o4, o5 };
|
||||
return _emit(instId, o0, o1, o2, opExt);
|
||||
}
|
||||
|
||||
Error BaseEmitter::_emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount) {
|
||||
const Operand_* op = operands;
|
||||
|
||||
Operand_ opExt[3];
|
||||
|
||||
switch (opCount) {
|
||||
case 0:
|
||||
return _emit(instId, noExt[0], noExt[1], noExt[2], noExt);
|
||||
|
||||
case 1:
|
||||
return _emit(instId, op[0], noExt[1], noExt[2], noExt);
|
||||
|
||||
case 2:
|
||||
return _emit(instId, op[0], op[1], noExt[2], noExt);
|
||||
|
||||
case 3:
|
||||
return _emit(instId, op[0], op[1], op[2], noExt);
|
||||
|
||||
case 4:
|
||||
opExt[0] = op[3];
|
||||
opExt[1].reset();
|
||||
opExt[2].reset();
|
||||
return _emit(instId, op[0], op[1], op[2], opExt);
|
||||
|
||||
case 5:
|
||||
opExt[0] = op[3];
|
||||
opExt[1] = op[4];
|
||||
opExt[2].reset();
|
||||
return _emit(instId, op[0], op[1], op[2], opExt);
|
||||
|
||||
case 6:
|
||||
return _emit(instId, op[0], op[1], op[2], op + 3);
|
||||
|
||||
default:
|
||||
return DebugUtils::errored(kErrorInvalidArgument);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter - Emit (High-Level)]
|
||||
// ============================================================================
|
||||
|
||||
ASMJIT_FAVOR_SIZE Error BaseEmitter::emitProlog(const FuncFrame& frame) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
if (environment().isFamilyX86()) {
|
||||
x86::EmitHelper emitHelper(this, frame.isAvxEnabled());
|
||||
return emitHelper.emitProlog(frame);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
if (environment().isArchAArch64()) {
|
||||
a64::EmitHelper emitHelper(this);
|
||||
return emitHelper.emitProlog(frame);
|
||||
}
|
||||
#endif
|
||||
|
||||
return DebugUtils::errored(kErrorInvalidArch);
|
||||
}
|
||||
|
||||
ASMJIT_FAVOR_SIZE Error BaseEmitter::emitEpilog(const FuncFrame& frame) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
if (environment().isFamilyX86()) {
|
||||
x86::EmitHelper emitHelper(this, frame.isAvxEnabled());
|
||||
return emitHelper.emitEpilog(frame);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
if (environment().isArchAArch64()) {
|
||||
a64::EmitHelper emitHelper(this);
|
||||
return emitHelper.emitEpilog(frame);
|
||||
}
|
||||
#endif
|
||||
|
||||
return DebugUtils::errored(kErrorInvalidArch);
|
||||
}
|
||||
|
||||
ASMJIT_FAVOR_SIZE Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return DebugUtils::errored(kErrorNotInitialized);
|
||||
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
if (environment().isFamilyX86()) {
|
||||
x86::EmitHelper emitHelper(this, frame.isAvxEnabled());
|
||||
return emitHelper.emitArgsAssignment(frame, args);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
if (environment().isArchAArch64()) {
|
||||
a64::EmitHelper emitHelper(this);
|
||||
return emitHelper.emitArgsAssignment(frame, args);
|
||||
}
|
||||
#endif
|
||||
|
||||
return DebugUtils::errored(kErrorInvalidArch);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter - Comment]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseEmitter::commentf(const char* fmt, ...) {
|
||||
if (!hasEmitterFlag(kFlagLogComments)) {
|
||||
if (!hasEmitterFlag(kFlagAttached))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
StringTmp<1024> sb;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
Error err = sb.appendVFormat(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
ASMJIT_PROPAGATE(err);
|
||||
return comment(sb.data(), sb.size());
|
||||
#else
|
||||
DebugUtils::unused(fmt);
|
||||
return kErrorOk;
|
||||
#endif
|
||||
}
|
||||
|
||||
Error BaseEmitter::commentv(const char* fmt, va_list ap) {
|
||||
if (!hasEmitterFlag(kFlagLogComments)) {
|
||||
if (!hasEmitterFlag(kFlagAttached))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
StringTmp<1024> sb;
|
||||
Error err = sb.appendVFormat(fmt, ap);
|
||||
|
||||
ASMJIT_PROPAGATE(err);
|
||||
return comment(sb.data(), sb.size());
|
||||
#else
|
||||
DebugUtils::unused(fmt, ap);
|
||||
return kErrorOk;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter - Events]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseEmitter::onAttach(CodeHolder* code) noexcept {
|
||||
_code = code;
|
||||
_environment = code->environment();
|
||||
_addEmitterFlags(kFlagAttached);
|
||||
|
||||
const ArchTraits& archTraits = ArchTraits::byArch(code->arch());
|
||||
uint32_t nativeRegType = Environment::is32Bit(code->arch()) ? BaseReg::kTypeGp32 : BaseReg::kTypeGp64;
|
||||
_gpRegInfo.setSignature(archTraits._regInfo[nativeRegType].signature());
|
||||
|
||||
onSettingsUpdated();
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseEmitter::onDetach(CodeHolder* code) noexcept {
|
||||
DebugUtils::unused(code);
|
||||
|
||||
if (!hasOwnLogger())
|
||||
_logger = nullptr;
|
||||
|
||||
if (!hasOwnErrorHandler())
|
||||
_errorHandler = nullptr;
|
||||
|
||||
_clearEmitterFlags(~kEmitterPreservedFlags);
|
||||
_forcedInstOptions = BaseInst::kOptionReserved;
|
||||
_privateData = 0;
|
||||
|
||||
_environment.reset();
|
||||
_gpRegInfo.reset();
|
||||
|
||||
_instOptions = 0;
|
||||
_extraReg.reset();
|
||||
_inlineComment = nullptr;
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
void BaseEmitter::onSettingsUpdated() noexcept {
|
||||
// Only called when attached to CodeHolder by CodeHolder.
|
||||
ASMJIT_ASSERT(_code != nullptr);
|
||||
|
||||
if (!hasOwnLogger())
|
||||
_logger = _code->logger();
|
||||
|
||||
if (!hasOwnErrorHandler())
|
||||
_errorHandler = _code->errorHandler();
|
||||
|
||||
BaseEmitter_updateForcedOptions(this);
|
||||
}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
@ -0,0 +1,723 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_EMITTER_H_INCLUDED
|
||||
#define ASMJIT_CORE_EMITTER_H_INCLUDED
|
||||
|
||||
#include "../core/archtraits.h"
|
||||
#include "../core/codeholder.h"
|
||||
#include "../core/inst.h"
|
||||
#include "../core/operand.h"
|
||||
#include "../core/type.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
//! \addtogroup asmjit_core
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [Forward Declarations]
|
||||
// ============================================================================
|
||||
|
||||
class ConstPool;
|
||||
class FuncFrame;
|
||||
class FuncArgsAssignment;
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseEmitter]
|
||||
// ============================================================================
|
||||
|
||||
//! Provides a base foundation to emit code - specialized by `Assembler` and
|
||||
//! `BaseBuilder`.
|
||||
class ASMJIT_VIRTAPI BaseEmitter {
|
||||
public:
|
||||
ASMJIT_BASE_CLASS(BaseEmitter)
|
||||
|
||||
//! See \ref EmitterType.
|
||||
uint8_t _emitterType = 0;
|
||||
//! See \ref BaseEmitter::EmitterFlags.
|
||||
uint8_t _emitterFlags = 0;
|
||||
//! Validation flags in case validation is used, see \ref InstAPI::ValidationFlags.
|
||||
//!
|
||||
//! \note Validation flags are specific to the emitter and they are setup at
|
||||
//! construction time and then never changed.
|
||||
uint8_t _validationFlags = 0;
|
||||
//! Validation options, see \ref ValidationOptions.
|
||||
uint8_t _validationOptions = 0;
|
||||
|
||||
//! Encoding options, see \ref EncodingOptions.
|
||||
uint32_t _encodingOptions = 0;
|
||||
|
||||
//! Forced instruction options, combined with \ref _instOptions by \ref emit().
|
||||
uint32_t _forcedInstOptions = BaseInst::kOptionReserved;
|
||||
//! Internal private data used freely by any emitter.
|
||||
uint32_t _privateData = 0;
|
||||
|
||||
//! CodeHolder the emitter is attached to.
|
||||
CodeHolder* _code = nullptr;
|
||||
//! Attached \ref Logger.
|
||||
Logger* _logger = nullptr;
|
||||
//! Attached \ref ErrorHandler.
|
||||
ErrorHandler* _errorHandler = nullptr;
|
||||
|
||||
//! Describes the target environment, matches \ref CodeHolder::environment().
|
||||
Environment _environment {};
|
||||
//! Native GP register signature and signature related information.
|
||||
RegInfo _gpRegInfo {};
|
||||
|
||||
//! Next instruction options (affects the next instruction).
|
||||
uint32_t _instOptions = 0;
|
||||
//! Extra register (op-mask {k} on AVX-512) (affects the next instruction).
|
||||
RegOnly _extraReg {};
|
||||
//! Inline comment of the next instruction (affects the next instruction).
|
||||
const char* _inlineComment = nullptr;
|
||||
|
||||
//! Emitter type.
|
||||
enum EmitterType : uint32_t {
|
||||
//! Unknown or uninitialized.
|
||||
kTypeNone = 0,
|
||||
//! Emitter inherits from \ref BaseAssembler.
|
||||
kTypeAssembler = 1,
|
||||
//! Emitter inherits from \ref BaseBuilder.
|
||||
kTypeBuilder = 2,
|
||||
//! Emitter inherits from \ref BaseCompiler.
|
||||
kTypeCompiler = 3,
|
||||
|
||||
//! Count of emitter types.
|
||||
kTypeCount = 4
|
||||
};
|
||||
|
||||
//! Emitter flags.
|
||||
enum EmitterFlags : uint32_t {
|
||||
//! Emitter is attached to CodeHolder.
|
||||
kFlagAttached = 0x01u,
|
||||
//! The emitter must emit comments.
|
||||
kFlagLogComments = 0x08u,
|
||||
//! The emitter has its own \ref Logger (not propagated from \ref CodeHolder).
|
||||
kFlagOwnLogger = 0x10u,
|
||||
//! The emitter has its own \ref ErrorHandler (not propagated from \ref CodeHolder).
|
||||
kFlagOwnErrorHandler = 0x20u,
|
||||
//! The emitter was finalized.
|
||||
kFlagFinalized = 0x40u,
|
||||
//! The emitter was destroyed.
|
||||
kFlagDestroyed = 0x80u
|
||||
};
|
||||
|
||||
//! Encoding options.
|
||||
enum EncodingOptions : uint32_t {
|
||||
//! Emit instructions that are optimized for size, if possible.
|
||||
//!
|
||||
//! Default: false.
|
||||
//!
|
||||
//! X86 Specific
|
||||
//! ------------
|
||||
//!
|
||||
//! When this option is set it the assembler will try to fix instructions
|
||||
//! if possible into operation equivalent instructions that take less bytes
|
||||
//! by taking advantage of implicit zero extension. For example instruction
|
||||
//! like `mov r64, imm` and `and r64, imm` can be translated to `mov r32, imm`
|
||||
//! and `and r32, imm` when the immediate constant is lesser than `2^31`.
|
||||
kEncodingOptionOptimizeForSize = 0x00000001u,
|
||||
|
||||
//! Emit optimized code-alignment sequences.
|
||||
//!
|
||||
//! Default: false.
|
||||
//!
|
||||
//! X86 Specific
|
||||
//! ------------
|
||||
//!
|
||||
//! Default align sequence used by X86 architecture is one-byte (0x90)
|
||||
//! opcode that is often shown by disassemblers as NOP. However there are
|
||||
//! more optimized align sequences for 2-11 bytes that may execute faster
|
||||
//! on certain CPUs. If this feature is enabled AsmJit will generate
|
||||
//! specialized sequences for alignment between 2 to 11 bytes.
|
||||
kEncodingOptionOptimizedAlign = 0x00000002u,
|
||||
|
||||
//! Emit jump-prediction hints.
|
||||
//!
|
||||
//! Default: false.
|
||||
//!
|
||||
//! X86 Specific
|
||||
//! ------------
|
||||
//!
|
||||
//! Jump prediction is usually based on the direction of the jump. If the
|
||||
//! jump is backward it is usually predicted as taken; and if the jump is
|
||||
//! forward it is usually predicted as not-taken. The reason is that loops
|
||||
//! generally use backward jumps and conditions usually use forward jumps.
|
||||
//! However this behavior can be overridden by using instruction prefixes.
|
||||
//! If this option is enabled these hints will be emitted.
|
||||
//!
|
||||
//! This feature is disabled by default, because the only processor that
|
||||
//! used to take into consideration prediction hints was P4. Newer processors
|
||||
//! implement heuristics for branch prediction and ignore static hints. This
|
||||
//! means that this feature can be only used for annotation purposes.
|
||||
kEncodingOptionPredictedJumps = 0x00000010u
|
||||
};
|
||||
|
||||
#ifndef ASMJIT_NO_DEPRECATED
|
||||
enum EmitterOptions : uint32_t {
|
||||
kOptionOptimizedForSize = kEncodingOptionOptimizeForSize,
|
||||
kOptionOptimizedAlign = kEncodingOptionOptimizedAlign,
|
||||
kOptionPredictedJumps = kEncodingOptionPredictedJumps
|
||||
};
|
||||
#endif
|
||||
|
||||
//! Validation options are used to tell emitters to perform strict validation
|
||||
//! of instructions passed to \ref emit().
|
||||
//!
|
||||
//! \ref BaseAssembler implementation perform by default only basic checks
|
||||
//! that are necessary to identify all variations of an instruction so the
|
||||
//! correct encoding can be selected. This is fine for production-ready code
|
||||
//! as the assembler doesn't have to perform checks that would slow it down.
|
||||
//! However, sometimes these checks are beneficial especially when the project
|
||||
//! that uses AsmJit is in a development phase, in which mistakes happen often.
|
||||
//! To make the experience of using AsmJit seamless it offers validation
|
||||
//! features that can be controlled by `ValidationOptions`.
|
||||
enum ValidationOptions : uint32_t {
|
||||
//! Perform strict validation in \ref BaseAssembler::emit() implementations.
|
||||
//!
|
||||
//! This flag ensures that each instruction is checked before it's encoded
|
||||
//! into a binary representation. This flag is only relevant for \ref
|
||||
//! BaseAssembler implementations, but can be set in any other emitter type,
|
||||
//! in that case if that emitter needs to create an assembler on its own,
|
||||
//! for the purpose of \ref finalize() it would propagate this flag to such
|
||||
//! assembler so all instructions passed to it are explicitly validated.
|
||||
//!
|
||||
//! Default: false.
|
||||
kValidationOptionAssembler = 0x00000001u,
|
||||
|
||||
//! Perform strict validation in \ref BaseBuilder::emit() and \ref
|
||||
//! BaseCompiler::emit() implementations.
|
||||
//!
|
||||
//! This flag ensures that each instruction is checked before an \ref
|
||||
//! InstNode representing the instruction is created by Builder or Compiler.
|
||||
//!
|
||||
//! Default: false.
|
||||
kValidationOptionIntermediate = 0x00000002u
|
||||
};
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
ASMJIT_API explicit BaseEmitter(uint32_t emitterType) noexcept;
|
||||
ASMJIT_API virtual ~BaseEmitter() noexcept;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Cast
|
||||
//! \{
|
||||
|
||||
template<typename T>
|
||||
inline T* as() noexcept { return reinterpret_cast<T*>(this); }
|
||||
|
||||
template<typename T>
|
||||
inline const T* as() const noexcept { return reinterpret_cast<const T*>(this); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Emitter Type & Flags
|
||||
//! \{
|
||||
|
||||
//! Returns the type of this emitter, see `EmitterType`.
|
||||
inline uint32_t emitterType() const noexcept { return _emitterType; }
|
||||
//! Returns emitter flags , see `Flags`.
|
||||
inline uint32_t emitterFlags() const noexcept { return _emitterFlags; }
|
||||
|
||||
//! Tests whether the emitter inherits from `BaseAssembler`.
|
||||
inline bool isAssembler() const noexcept { return _emitterType == kTypeAssembler; }
|
||||
//! Tests whether the emitter inherits from `BaseBuilder`.
|
||||
//!
|
||||
//! \note Both Builder and Compiler emitters would return `true`.
|
||||
inline bool isBuilder() const noexcept { return _emitterType >= kTypeBuilder; }
|
||||
//! Tests whether the emitter inherits from `BaseCompiler`.
|
||||
inline bool isCompiler() const noexcept { return _emitterType == kTypeCompiler; }
|
||||
|
||||
//! Tests whether the emitter has the given `flag` enabled.
|
||||
inline bool hasEmitterFlag(uint32_t flag) const noexcept { return (_emitterFlags & flag) != 0; }
|
||||
//! Tests whether the emitter is finalized.
|
||||
inline bool isFinalized() const noexcept { return hasEmitterFlag(kFlagFinalized); }
|
||||
//! Tests whether the emitter is destroyed (only used during destruction).
|
||||
inline bool isDestroyed() const noexcept { return hasEmitterFlag(kFlagDestroyed); }
|
||||
|
||||
inline void _addEmitterFlags(uint32_t flags) noexcept { _emitterFlags = uint8_t(_emitterFlags | flags); }
|
||||
inline void _clearEmitterFlags(uint32_t flags) noexcept { _emitterFlags = uint8_t(_emitterFlags & ~flags); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Target Information
|
||||
//! \{
|
||||
|
||||
//! Returns the CodeHolder this emitter is attached to.
|
||||
inline CodeHolder* code() const noexcept { return _code; }
|
||||
|
||||
//! Returns the target environment, see \ref Environment.
|
||||
//!
|
||||
//! The returned \ref Environment reference matches \ref CodeHolder::environment().
|
||||
inline const Environment& environment() const noexcept { return _environment; }
|
||||
|
||||
//! Tests whether the target architecture is 32-bit.
|
||||
inline bool is32Bit() const noexcept { return environment().is32Bit(); }
|
||||
//! Tests whether the target architecture is 64-bit.
|
||||
inline bool is64Bit() const noexcept { return environment().is64Bit(); }
|
||||
|
||||
//! Returns the target architecture type.
|
||||
inline uint32_t arch() const noexcept { return environment().arch(); }
|
||||
//! Returns the target architecture sub-type.
|
||||
inline uint32_t subArch() const noexcept { return environment().subArch(); }
|
||||
|
||||
//! Returns the target architecture's GP register size (4 or 8 bytes).
|
||||
inline uint32_t registerSize() const noexcept { return environment().registerSize(); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Initialization & Finalization
|
||||
//! \{
|
||||
|
||||
//! Tests whether the emitter is initialized (i.e. attached to \ref CodeHolder).
|
||||
inline bool isInitialized() const noexcept { return _code != nullptr; }
|
||||
|
||||
//! Finalizes this emitter.
|
||||
//!
|
||||
//! Materializes the content of the emitter by serializing it to the attached
|
||||
//! \ref CodeHolder through an architecture specific \ref BaseAssembler. This
|
||||
//! function won't do anything if the emitter inherits from \ref BaseAssembler
|
||||
//! as assemblers emit directly to a \ref CodeBuffer held by \ref CodeHolder.
|
||||
//! However, if this is an emitter that inherits from \ref BaseBuilder or \ref
|
||||
//! BaseCompiler then these emitters need the materialization phase as they
|
||||
//! store their content in a representation not visible to \ref CodeHolder.
|
||||
ASMJIT_API virtual Error finalize();
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Logging
|
||||
//! \{
|
||||
|
||||
//! Tests whether the emitter has a logger.
|
||||
inline bool hasLogger() const noexcept { return _logger != nullptr; }
|
||||
|
||||
//! Tests whether the emitter has its own logger.
|
||||
//!
|
||||
//! Own logger means that it overrides the possible logger that may be used
|
||||
//! by \ref CodeHolder this emitter is attached to.
|
||||
inline bool hasOwnLogger() const noexcept { return hasEmitterFlag(kFlagOwnLogger); }
|
||||
|
||||
//! Returns the logger this emitter uses.
|
||||
//!
|
||||
//! The returned logger is either the emitter's own logger or it's logger
|
||||
//! used by \ref CodeHolder this emitter is attached to.
|
||||
inline Logger* logger() const noexcept { return _logger; }
|
||||
|
||||
//! Sets or resets the logger of the emitter.
|
||||
//!
|
||||
//! If the `logger` argument is non-null then the logger will be considered
|
||||
//! emitter's own logger, see \ref hasOwnLogger() for more details. If the
|
||||
//! given `logger` is null then the emitter will automatically use logger
|
||||
//! that is attached to the \ref CodeHolder this emitter is attached to.
|
||||
ASMJIT_API void setLogger(Logger* logger) noexcept;
|
||||
|
||||
//! Resets the logger of this emitter.
|
||||
//!
|
||||
//! The emitter will bail to using a logger attached to \ref CodeHolder this
|
||||
//! emitter is attached to, or no logger at all if \ref CodeHolder doesn't
|
||||
//! have one.
|
||||
inline void resetLogger() noexcept { return setLogger(nullptr); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Error Handling
|
||||
//! \{
|
||||
|
||||
//! Tests whether the emitter has an error handler attached.
|
||||
inline bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; }
|
||||
|
||||
//! Tests whether the emitter has its own error handler.
|
||||
//!
|
||||
//! Own error handler means that it overrides the possible error handler that
|
||||
//! may be used by \ref CodeHolder this emitter is attached to.
|
||||
inline bool hasOwnErrorHandler() const noexcept { return hasEmitterFlag(kFlagOwnErrorHandler); }
|
||||
|
||||
//! Returns the error handler this emitter uses.
|
||||
//!
|
||||
//! The returned error handler is either the emitter's own error handler or
|
||||
//! it's error handler used by \ref CodeHolder this emitter is attached to.
|
||||
inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; }
|
||||
|
||||
//! Sets or resets the error handler of the emitter.
|
||||
ASMJIT_API void setErrorHandler(ErrorHandler* errorHandler) noexcept;
|
||||
|
||||
//! Resets the error handler.
|
||||
inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); }
|
||||
|
||||
//! Handles the given error in the following way:
|
||||
//! 1. If the emitter has \ref ErrorHandler attached, it calls its
|
||||
//! \ref ErrorHandler::handleError() member function first, and
|
||||
//! then returns the error. The `handleError()` function may throw.
|
||||
//! 2. if the emitter doesn't have \ref ErrorHandler, the error is
|
||||
//! simply returned.
|
||||
ASMJIT_API Error reportError(Error err, const char* message = nullptr);
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Encoding Options
|
||||
//! \{
|
||||
|
||||
//! Returns encoding options, see \ref EncodingOptions.
|
||||
inline uint32_t encodingOptions() const noexcept { return _encodingOptions; }
|
||||
//! Tests whether the encoding `option` is set.
|
||||
inline bool hasEncodingOption(uint32_t option) const noexcept { return (_encodingOptions & option) != 0; }
|
||||
|
||||
//! Enables the given encoding `options`, see \ref EncodingOptions.
|
||||
inline void addEncodingOptions(uint32_t options) noexcept { _encodingOptions |= options; }
|
||||
//! Disables the given encoding `options`, see \ref EncodingOptions.
|
||||
inline void clearEncodingOptions(uint32_t options) noexcept { _encodingOptions &= ~options; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Validation Options
|
||||
//! \{
|
||||
|
||||
//! Returns the emitter's validation options, see \ref ValidationOptions.
|
||||
inline uint32_t validationOptions() const noexcept {
|
||||
return _validationOptions;
|
||||
}
|
||||
|
||||
//! Tests whether the given `option` is present in validation options.
|
||||
inline bool hasValidationOption(uint32_t option) const noexcept {
|
||||
return (_validationOptions & option) != 0;
|
||||
}
|
||||
|
||||
//! Activates the given validation `options`, see \ref ValidationOptions.
|
||||
//!
|
||||
//! This function is used to activate explicit validation options that will
|
||||
//! be then used by all emitter implementations. There are in general two
|
||||
//! possibilities:
|
||||
//!
|
||||
//! - Architecture specific assembler is used. In this case a
|
||||
//! \ref kValidationOptionAssembler can be used to turn on explicit
|
||||
//! validation that will be used before an instruction is emitted.
|
||||
//! This means that internally an extra step will be performed to
|
||||
//! make sure that the instruction is correct. This is needed, because
|
||||
//! by default assemblers prefer speed over strictness.
|
||||
//!
|
||||
//! This option should be used in debug builds as it's pretty expensive.
|
||||
//!
|
||||
//! - Architecture specific builder or compiler is used. In this case
|
||||
//! the user can turn on \ref kValidationOptionIntermediate option
|
||||
//! that adds explicit validation step before the Builder or Compiler
|
||||
//! creates an \ref InstNode to represent an emitted instruction. Error
|
||||
//! will be returned if the instruction is ill-formed. In addition,
|
||||
//! also \ref kValidationOptionAssembler can be used, which would not be
|
||||
//! consumed by Builder / Compiler directly, but it would be propagated
|
||||
//! to an architecture specific \ref BaseAssembler implementation it
|
||||
//! creates during \ref BaseEmitter::finalize().
|
||||
ASMJIT_API void addValidationOptions(uint32_t options) noexcept;
|
||||
|
||||
//! Deactivates the given validation `options`.
|
||||
//!
|
||||
//! See \ref addValidationOptions() and \ref ValidationOptions for more details.
|
||||
ASMJIT_API void clearValidationOptions(uint32_t options) noexcept;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Instruction Options
|
||||
//! \{
|
||||
|
||||
//! Returns forced instruction options.
|
||||
//!
|
||||
//! Forced instruction options are merged with next instruction options before
|
||||
//! the instruction is encoded. These options have some bits reserved that are
|
||||
//! used by error handling, logging, and instruction validation purposes. Other
|
||||
//! options are globals that affect each instruction.
|
||||
inline uint32_t forcedInstOptions() const noexcept { return _forcedInstOptions; }
|
||||
|
||||
//! Returns options of the next instruction.
|
||||
inline uint32_t instOptions() const noexcept { return _instOptions; }
|
||||
//! Returns options of the next instruction.
|
||||
inline void setInstOptions(uint32_t options) noexcept { _instOptions = options; }
|
||||
//! Adds options of the next instruction.
|
||||
inline void addInstOptions(uint32_t options) noexcept { _instOptions |= options; }
|
||||
//! Resets options of the next instruction.
|
||||
inline void resetInstOptions() noexcept { _instOptions = 0; }
|
||||
|
||||
//! Tests whether the extra register operand is valid.
|
||||
inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); }
|
||||
//! Returns an extra operand that will be used by the next instruction (architecture specific).
|
||||
inline const RegOnly& extraReg() const noexcept { return _extraReg; }
|
||||
//! Sets an extra operand that will be used by the next instruction (architecture specific).
|
||||
inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); }
|
||||
//! Sets an extra operand that will be used by the next instruction (architecture specific).
|
||||
inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); }
|
||||
//! Resets an extra operand that will be used by the next instruction (architecture specific).
|
||||
inline void resetExtraReg() noexcept { _extraReg.reset(); }
|
||||
|
||||
//! Returns comment/annotation of the next instruction.
|
||||
inline const char* inlineComment() const noexcept { return _inlineComment; }
|
||||
//! Sets comment/annotation of the next instruction.
|
||||
//!
|
||||
//! \note This string is set back to null by `_emit()`, but until that it has
|
||||
//! to remain valid as the Emitter is not required to make a copy of it (and
|
||||
//! it would be slow to do that for each instruction).
|
||||
inline void setInlineComment(const char* s) noexcept { _inlineComment = s; }
|
||||
//! Resets the comment/annotation to nullptr.
|
||||
inline void resetInlineComment() noexcept { _inlineComment = nullptr; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Sections
|
||||
//! \{
|
||||
|
||||
virtual Error section(Section* section) = 0;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Labels
|
||||
//! \{
|
||||
|
||||
//! Creates a new label.
|
||||
virtual Label newLabel() = 0;
|
||||
//! Creates a new named label.
|
||||
virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, uint32_t type = Label::kTypeGlobal, uint32_t parentId = Globals::kInvalidId) = 0;
|
||||
|
||||
//! Creates a new external label.
|
||||
inline Label newExternalLabel(const char* name, size_t nameSize = SIZE_MAX) {
|
||||
return newNamedLabel(name, nameSize, Label::kTypeExternal);
|
||||
}
|
||||
|
||||
//! Returns `Label` by `name`.
|
||||
//!
|
||||
//! Returns invalid Label in case that the name is invalid or label was not found.
|
||||
//!
|
||||
//! \note This function doesn't trigger ErrorHandler in case the name is invalid
|
||||
//! or no such label exist. You must always check the validity of the `Label` returned.
|
||||
ASMJIT_API Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept;
|
||||
|
||||
//! Binds the `label` to the current position of the current section.
|
||||
//!
|
||||
//! \note Attempt to bind the same label multiple times will return an error.
|
||||
virtual Error bind(const Label& label) = 0;
|
||||
|
||||
//! Tests whether the label `id` is valid (i.e. registered).
|
||||
ASMJIT_API bool isLabelValid(uint32_t labelId) const noexcept;
|
||||
//! Tests whether the `label` is valid (i.e. registered).
|
||||
inline bool isLabelValid(const Label& label) const noexcept { return isLabelValid(label.id()); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Emit
|
||||
//! \{
|
||||
|
||||
// NOTE: These `emit()` helpers are designed to address a code-bloat generated
|
||||
// by C++ compilers to call a function having many arguments. Each parameter to
|
||||
// `_emit()` requires some code to pass it, which means that if we default to
|
||||
// 5 arguments in `_emit()` and instId the C++ compiler would have to generate
|
||||
// a virtual function call having 5 parameters and additional `this` argument,
|
||||
// which is quite a lot. Since by default most instructions have 2 to 3 operands
|
||||
// it's better to introduce helpers that pass from 0 to 6 operands that help to
|
||||
// reduce the size of emit(...) function call.
|
||||
|
||||
//! Emits an instruction (internal).
|
||||
ASMJIT_API Error _emitI(uint32_t instId);
|
||||
//! \overload
|
||||
ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0);
|
||||
//! \overload
|
||||
ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1);
|
||||
//! \overload
|
||||
ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2);
|
||||
//! \overload
|
||||
ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3);
|
||||
//! \overload
|
||||
ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4);
|
||||
//! \overload
|
||||
ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5);
|
||||
|
||||
//! Emits an instruction `instId` with the given `operands`.
|
||||
template<typename... Args>
|
||||
ASMJIT_INLINE Error emit(uint32_t instId, Args&&... operands) {
|
||||
return _emitI(instId, Support::ForwardOp<Args>::forward(operands)...);
|
||||
}
|
||||
|
||||
inline Error emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount) {
|
||||
return _emitOpArray(instId, operands, opCount);
|
||||
}
|
||||
|
||||
inline Error emitInst(const BaseInst& inst, const Operand_* operands, size_t opCount) {
|
||||
setInstOptions(inst.options());
|
||||
setExtraReg(inst.extraReg());
|
||||
return _emitOpArray(inst.id(), operands, opCount);
|
||||
}
|
||||
|
||||
//! \cond INTERNAL
|
||||
//! Emits an instruction - all 6 operands must be defined.
|
||||
virtual Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt) = 0;
|
||||
//! Emits instruction having operands stored in array.
|
||||
ASMJIT_API virtual Error _emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount);
|
||||
//! \endcond
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Emit Utilities
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error emitProlog(const FuncFrame& frame);
|
||||
ASMJIT_API Error emitEpilog(const FuncFrame& frame);
|
||||
ASMJIT_API Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args);
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Align
|
||||
//! \{
|
||||
|
||||
//! Aligns the current CodeBuffer position to the `alignment` specified.
|
||||
//!
|
||||
//! The sequence that is used to fill the gap between the aligned location
|
||||
//! and the current location depends on the align `mode`, see \ref AlignMode.
|
||||
virtual Error align(uint32_t alignMode, uint32_t alignment) = 0;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Embed
|
||||
//! \{
|
||||
|
||||
//! Embeds raw data into the \ref CodeBuffer.
|
||||
virtual Error embed(const void* data, size_t dataSize) = 0;
|
||||
|
||||
//! Embeds a typed data array.
|
||||
//!
|
||||
//! This is the most flexible function for embedding data as it allows to:
|
||||
//! - Assign a `typeId` to the data, so the emitter knows the type of
|
||||
//! items stored in `data`. Binary data should use \ref Type::kIdU8.
|
||||
//! - Repeat the given data `repeatCount` times, so the data can be used
|
||||
//! as a fill pattern for example, or as a pattern used by SIMD instructions.
|
||||
virtual Error embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1) = 0;
|
||||
|
||||
//! Embeds int8_t `value` repeated by `repeatCount`.
|
||||
inline Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI8, &value, 1, repeatCount); }
|
||||
//! Embeds uint8_t `value` repeated by `repeatCount`.
|
||||
inline Error embedUInt8(uint8_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU8, &value, 1, repeatCount); }
|
||||
//! Embeds int16_t `value` repeated by `repeatCount`.
|
||||
inline Error embedInt16(int16_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI16, &value, 1, repeatCount); }
|
||||
//! Embeds uint16_t `value` repeated by `repeatCount`.
|
||||
inline Error embedUInt16(uint16_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU16, &value, 1, repeatCount); }
|
||||
//! Embeds int32_t `value` repeated by `repeatCount`.
|
||||
inline Error embedInt32(int32_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI32, &value, 1, repeatCount); }
|
||||
//! Embeds uint32_t `value` repeated by `repeatCount`.
|
||||
inline Error embedUInt32(uint32_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU32, &value, 1, repeatCount); }
|
||||
//! Embeds int64_t `value` repeated by `repeatCount`.
|
||||
inline Error embedInt64(int64_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI64, &value, 1, repeatCount); }
|
||||
//! Embeds uint64_t `value` repeated by `repeatCount`.
|
||||
inline Error embedUInt64(uint64_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU64, &value, 1, repeatCount); }
|
||||
//! Embeds a floating point `value` repeated by `repeatCount`.
|
||||
inline Error embedFloat(float value, size_t repeatCount = 1) { return embedDataArray(Type::kIdF32, &value, 1, repeatCount); }
|
||||
//! Embeds a floating point `value` repeated by `repeatCount`.
|
||||
inline Error embedDouble(double value, size_t repeatCount = 1) { return embedDataArray(Type::IdOfT<double>::kTypeId, &value, 1, repeatCount); }
|
||||
|
||||
//! Embeds a constant pool at the current offset by performing the following:
|
||||
//! 1. Aligns by using kAlignData to the minimum `pool` alignment.
|
||||
//! 2. Binds the ConstPool label so it's bound to an aligned location.
|
||||
//! 3. Emits ConstPool content.
|
||||
virtual Error embedConstPool(const Label& label, const ConstPool& pool) = 0;
|
||||
|
||||
//! Embeds an absolute `label` address as data.
|
||||
//!
|
||||
//! The `dataSize` is an optional argument that can be used to specify the
|
||||
//! size of the address data. If it's zero (default) the address size is
|
||||
//! deduced from the target architecture (either 4 or 8 bytes).
|
||||
virtual Error embedLabel(const Label& label, size_t dataSize = 0) = 0;
|
||||
|
||||
//! Embeds a delta (distance) between the `label` and `base` calculating it
|
||||
//! as `label - base`. This function was designed to make it easier to embed
|
||||
//! lookup tables where each index is a relative distance of two labels.
|
||||
virtual Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) = 0;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Comment
|
||||
//! \{
|
||||
|
||||
//! Emits a comment stored in `data` with an optional `size` parameter.
|
||||
virtual Error comment(const char* data, size_t size = SIZE_MAX) = 0;
|
||||
|
||||
//! Emits a formatted comment specified by `fmt` and variable number of arguments.
|
||||
ASMJIT_API Error commentf(const char* fmt, ...);
|
||||
//! Emits a formatted comment specified by `fmt` and `ap`.
|
||||
ASMJIT_API Error commentv(const char* fmt, va_list ap);
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Events
|
||||
//! \{
|
||||
|
||||
//! Called after the emitter was attached to `CodeHolder`.
|
||||
virtual Error onAttach(CodeHolder* code) noexcept = 0;
|
||||
//! Called after the emitter was detached from `CodeHolder`.
|
||||
virtual Error onDetach(CodeHolder* code) noexcept = 0;
|
||||
|
||||
//! Called when \ref CodeHolder has updated an important setting, which
|
||||
//! involves the following:
|
||||
//!
|
||||
//! - \ref Logger has been changed (\ref CodeHolder::setLogger() has been
|
||||
//! called).
|
||||
//! - \ref ErrorHandler has been changed (\ref CodeHolder::setErrorHandler()
|
||||
//! has been called).
|
||||
//!
|
||||
//! This function ensures that the settings are properly propagated from
|
||||
//! \ref CodeHolder to the emitter.
|
||||
//!
|
||||
//! \note This function is virtual and can be overridden, however, if you
|
||||
//! do so, always call \ref BaseEmitter::onSettingsUpdated() within your
|
||||
//! own implementation to ensure that the emitter is in a consisten state.
|
||||
ASMJIT_API virtual void onSettingsUpdated() noexcept;
|
||||
|
||||
//! \}
|
||||
|
||||
#ifndef ASMJIT_NO_DEPRECATED
|
||||
ASMJIT_DEPRECATED("Use environment() instead")
|
||||
inline CodeInfo codeInfo() const noexcept {
|
||||
return CodeInfo(_environment, _code ? _code->baseAddress() : Globals::kNoBaseAddress);
|
||||
}
|
||||
|
||||
ASMJIT_DEPRECATED("Use arch() instead")
|
||||
inline uint32_t archId() const noexcept { return arch(); }
|
||||
|
||||
ASMJIT_DEPRECATED("Use registerSize() instead")
|
||||
inline uint32_t gpSize() const noexcept { return registerSize(); }
|
||||
|
||||
ASMJIT_DEPRECATED("Use encodingOptions() instead")
|
||||
inline uint32_t emitterOptions() const noexcept { return encodingOptions(); }
|
||||
|
||||
ASMJIT_DEPRECATED("Use addEncodingOptions() instead")
|
||||
inline void addEmitterOptions(uint32_t options) noexcept { addEncodingOptions(options); }
|
||||
|
||||
ASMJIT_DEPRECATED("Use clearEncodingOptions() instead")
|
||||
inline void clearEmitterOptions(uint32_t options) noexcept { clearEncodingOptions(options); }
|
||||
|
||||
ASMJIT_DEPRECATED("Use forcedInstOptions() instead")
|
||||
inline uint32_t globalInstOptions() const noexcept { return forcedInstOptions(); }
|
||||
#endif // !ASMJIT_NO_DEPRECATED
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_EMITTER_H_INCLUDED
|
@ -0,0 +1,150 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#include "../core/assembler.h"
|
||||
#include "../core/emitterutils_p.h"
|
||||
#include "../core/formatter.h"
|
||||
#include "../core/logger.h"
|
||||
#include "../core/support.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::EmitterUtils]
|
||||
// ============================================================================
|
||||
|
||||
namespace EmitterUtils {
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
|
||||
Error formatLine(String& sb, const uint8_t* binData, size_t binSize, size_t dispSize, size_t immSize, const char* comment) noexcept {
|
||||
size_t currentSize = sb.size();
|
||||
size_t commentSize = comment ? Support::strLen(comment, Globals::kMaxCommentSize) : 0;
|
||||
|
||||
ASMJIT_ASSERT(binSize >= dispSize);
|
||||
const size_t kNoBinSize = SIZE_MAX;
|
||||
|
||||
if ((binSize != 0 && binSize != kNoBinSize) || commentSize) {
|
||||
size_t align = kMaxInstLineSize;
|
||||
char sep = ';';
|
||||
|
||||
for (size_t i = (binSize == kNoBinSize); i < 2; i++) {
|
||||
size_t begin = sb.size();
|
||||
ASMJIT_PROPAGATE(sb.padEnd(align));
|
||||
|
||||
if (sep) {
|
||||
ASMJIT_PROPAGATE(sb.append(sep));
|
||||
ASMJIT_PROPAGATE(sb.append(' '));
|
||||
}
|
||||
|
||||
// Append binary data or comment.
|
||||
if (i == 0) {
|
||||
ASMJIT_PROPAGATE(sb.appendHex(binData, binSize - dispSize - immSize));
|
||||
ASMJIT_PROPAGATE(sb.appendChars('.', dispSize * 2));
|
||||
ASMJIT_PROPAGATE(sb.appendHex(binData + binSize - immSize, immSize));
|
||||
if (commentSize == 0) break;
|
||||
}
|
||||
else {
|
||||
ASMJIT_PROPAGATE(sb.append(comment, commentSize));
|
||||
}
|
||||
|
||||
currentSize += sb.size() - begin;
|
||||
align += kMaxBinarySize;
|
||||
sep = '|';
|
||||
}
|
||||
}
|
||||
|
||||
return sb.append('\n');
|
||||
}
|
||||
|
||||
void logLabelBound(BaseAssembler* self, const Label& label) noexcept {
|
||||
Logger* logger = self->logger();
|
||||
|
||||
StringTmp<512> sb;
|
||||
size_t binSize = logger->hasFlag(FormatOptions::kFlagMachineCode) ? size_t(0) : SIZE_MAX;
|
||||
|
||||
sb.appendChars(' ', logger->indentation(FormatOptions::kIndentationLabel));
|
||||
Formatter::formatLabel(sb, logger->flags(), self, label.id());
|
||||
sb.append(':');
|
||||
EmitterUtils::formatLine(sb, nullptr, binSize, 0, 0, self->_inlineComment);
|
||||
logger->log(sb.data(), sb.size());
|
||||
}
|
||||
|
||||
void logInstructionEmitted(
|
||||
BaseAssembler* self,
|
||||
uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt,
|
||||
uint32_t relSize, uint32_t immSize, uint8_t* afterCursor) {
|
||||
|
||||
Logger* logger = self->logger();
|
||||
ASMJIT_ASSERT(logger != nullptr);
|
||||
|
||||
StringTmp<256> sb;
|
||||
uint32_t flags = logger->flags();
|
||||
|
||||
uint8_t* beforeCursor = self->bufferPtr();
|
||||
intptr_t emittedSize = (intptr_t)(afterCursor - beforeCursor);
|
||||
|
||||
Operand_ opArray[Globals::kMaxOpCount];
|
||||
EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt);
|
||||
|
||||
sb.appendChars(' ', logger->indentation(FormatOptions::kIndentationCode));
|
||||
Formatter::formatInstruction(sb, flags, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount);
|
||||
|
||||
if ((flags & FormatOptions::kFlagMachineCode) != 0)
|
||||
EmitterUtils::formatLine(sb, self->bufferPtr(), size_t(emittedSize), relSize, immSize, self->inlineComment());
|
||||
else
|
||||
EmitterUtils::formatLine(sb, nullptr, SIZE_MAX, 0, 0, self->inlineComment());
|
||||
logger->log(sb);
|
||||
}
|
||||
|
||||
Error logInstructionFailed(
|
||||
BaseAssembler* self,
|
||||
Error err,
|
||||
uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) {
|
||||
|
||||
StringTmp<256> sb;
|
||||
sb.append(DebugUtils::errorAsString(err));
|
||||
sb.append(": ");
|
||||
|
||||
Operand_ opArray[Globals::kMaxOpCount];
|
||||
EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt);
|
||||
|
||||
Formatter::formatInstruction(sb, 0, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount);
|
||||
|
||||
if (self->inlineComment()) {
|
||||
sb.append(" ; ");
|
||||
sb.append(self->inlineComment());
|
||||
}
|
||||
|
||||
self->resetInstOptions();
|
||||
self->resetExtraReg();
|
||||
self->resetInlineComment();
|
||||
return self->reportError(err, sb.data());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // {EmitterUtils}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
@ -0,0 +1,109 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_EMITTERUTILS_P_H_INCLUDED
|
||||
#define ASMJIT_CORE_EMITTERUTILS_P_H_INCLUDED
|
||||
|
||||
#include "../core/emitter.h"
|
||||
#include "../core/operand.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
class BaseAssembler;
|
||||
|
||||
//! \cond INTERNAL
|
||||
//! \addtogroup asmjit_core
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::EmitterUtils]
|
||||
// ============================================================================
|
||||
|
||||
namespace EmitterUtils {
|
||||
|
||||
static const Operand_ noExt[3] {};
|
||||
|
||||
enum kOpIndex {
|
||||
kOp3 = 0,
|
||||
kOp4 = 1,
|
||||
kOp5 = 2
|
||||
};
|
||||
|
||||
static ASMJIT_INLINE uint32_t opCountFromEmitArgs(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) noexcept {
|
||||
uint32_t opCount = 0;
|
||||
|
||||
if (opExt[kOp3].isNone()) {
|
||||
if (!o0.isNone()) opCount = 1;
|
||||
if (!o1.isNone()) opCount = 2;
|
||||
if (!o2.isNone()) opCount = 3;
|
||||
}
|
||||
else {
|
||||
opCount = 4;
|
||||
if (!opExt[kOp4].isNone()) {
|
||||
opCount = 5 + uint32_t(!opExt[kOp5].isNone());
|
||||
}
|
||||
}
|
||||
|
||||
return opCount;
|
||||
}
|
||||
|
||||
static ASMJIT_INLINE void opArrayFromEmitArgs(Operand_ dst[Globals::kMaxOpCount], const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) noexcept {
|
||||
dst[0].copyFrom(o0);
|
||||
dst[1].copyFrom(o1);
|
||||
dst[2].copyFrom(o2);
|
||||
dst[3].copyFrom(opExt[kOp3]);
|
||||
dst[4].copyFrom(opExt[kOp4]);
|
||||
dst[5].copyFrom(opExt[kOp5]);
|
||||
}
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
enum : uint32_t {
|
||||
// Has to be big to be able to hold all metadata compiler can assign to a
|
||||
// single instruction.
|
||||
kMaxInstLineSize = 44,
|
||||
kMaxBinarySize = 26
|
||||
};
|
||||
|
||||
Error formatLine(String& sb, const uint8_t* binData, size_t binSize, size_t dispSize, size_t immSize, const char* comment) noexcept;
|
||||
|
||||
void logLabelBound(BaseAssembler* self, const Label& label) noexcept;
|
||||
|
||||
void logInstructionEmitted(
|
||||
BaseAssembler* self,
|
||||
uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt,
|
||||
uint32_t relSize, uint32_t immSize, uint8_t* afterCursor);
|
||||
|
||||
Error logInstructionFailed(
|
||||
BaseAssembler* self,
|
||||
Error err, uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//! \}
|
||||
//! \endcond
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_EMITTERUTILS_P_H_INCLUDED
|
||||
|
@ -0,0 +1,64 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#include "../core/environment.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// X86 Target
|
||||
// ----------
|
||||
//
|
||||
// - 32-bit - Linux, OSX, BSD, and apparently also Haiku guarantee 16-byte
|
||||
// stack alignment. Other operating systems are assumed to have
|
||||
// 4-byte alignment by default for safety reasons.
|
||||
// - 64-bit - stack must be aligned to 16 bytes.
|
||||
//
|
||||
// ARM Target
|
||||
// ----------
|
||||
//
|
||||
// - 32-bit - Stack must be aligned to 8 bytes.
|
||||
// - 64-bit - Stack must be aligned to 16 bytes (hardware requirement).
|
||||
uint32_t Environment::stackAlignment() const noexcept {
|
||||
if (is64Bit()) {
|
||||
// Assume 16-byte alignment on any 64-bit target.
|
||||
return 16;
|
||||
}
|
||||
else {
|
||||
// The following platforms use 16-byte alignment in 32-bit mode.
|
||||
if (isPlatformLinux() ||
|
||||
isPlatformBSD() ||
|
||||
isPlatformApple() ||
|
||||
isPlatformHaiku()) {
|
||||
return 16u;
|
||||
}
|
||||
|
||||
if (isFamilyARM())
|
||||
return 8;
|
||||
|
||||
// Bail to 4-byte alignment if we don't know.
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
@ -0,0 +1,612 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_ENVIRONMENT_H_INCLUDED
|
||||
#define ASMJIT_CORE_ENVIRONMENT_H_INCLUDED
|
||||
|
||||
#include "../core/globals.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
//! \addtogroup asmjit_core
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Environment]
|
||||
// ============================================================================
|
||||
|
||||
//! Represents an environment, which is usually related to a \ref Target.
|
||||
//!
|
||||
//! Environment has usually an 'arch-subarch-vendor-os-abi' format, which is
|
||||
//! sometimes called "Triple" (historically it used to be 3 only parts) or
|
||||
//! "Tuple", which is a convention used by Debian Linux.
|
||||
//!
|
||||
//! AsmJit doesn't support all possible combinations or architectures and ABIs,
|
||||
//! however, it models the environment similarly to other compilers for future
|
||||
//! extensibility.
|
||||
class Environment {
|
||||
public:
|
||||
//! Architecture type, see \ref Arch.
|
||||
uint8_t _arch;
|
||||
//! Sub-architecture type, see \ref SubArch.
|
||||
uint8_t _subArch;
|
||||
//! Vendor type, see \ref Vendor.
|
||||
uint8_t _vendor;
|
||||
//! Platform type, see \ref Platform.
|
||||
uint8_t _platform;
|
||||
//! ABI type, see \ref Abi.
|
||||
uint8_t _abi;
|
||||
//! Object format, see \ref Format.
|
||||
uint8_t _format;
|
||||
//! Reserved for future use, must be zero.
|
||||
uint16_t _reserved;
|
||||
|
||||
//! Architecture.
|
||||
enum Arch : uint32_t {
|
||||
//! Unknown or uninitialized architecture.
|
||||
kArchUnknown = 0,
|
||||
|
||||
//! Mask used by 32-bit architectures (odd are 32-bit, even are 64-bit).
|
||||
kArch32BitMask = 0x01,
|
||||
//! Mask used by big-endian architectures.
|
||||
kArchBigEndianMask = 0x80u,
|
||||
|
||||
//! 32-bit X86 architecture.
|
||||
kArchX86 = 1,
|
||||
//! 64-bit X86 architecture also known as X86_64 and AMD64.
|
||||
kArchX64 = 2,
|
||||
|
||||
//! 32-bit RISC-V architecture.
|
||||
kArchRISCV32 = 3,
|
||||
//! 64-bit RISC-V architecture.
|
||||
kArchRISCV64 = 4,
|
||||
|
||||
//! 32-bit ARM architecture (little endian).
|
||||
kArchARM = 5,
|
||||
//! 32-bit ARM architecture (big endian).
|
||||
kArchARM_BE = kArchARM | kArchBigEndianMask,
|
||||
//! 64-bit ARM architecture in (little endian).
|
||||
kArchAArch64 = 6,
|
||||
//! 64-bit ARM architecture in (big endian).
|
||||
kArchAArch64_BE = kArchAArch64 | kArchBigEndianMask,
|
||||
//! 32-bit ARM in Thumb mode (little endian).
|
||||
kArchThumb = 7,
|
||||
//! 32-bit ARM in Thumb mode (big endian).
|
||||
kArchThumb_BE = kArchThumb | kArchBigEndianMask,
|
||||
|
||||
// 8 is not used, even numbers are 64-bit architectures.
|
||||
|
||||
//! 32-bit MIPS architecture in (little endian).
|
||||
kArchMIPS32_LE = 9,
|
||||
//! 32-bit MIPS architecture in (big endian).
|
||||
kArchMIPS32_BE = kArchMIPS32_LE | kArchBigEndianMask,
|
||||
//! 64-bit MIPS architecture in (little endian).
|
||||
kArchMIPS64_LE = 10,
|
||||
//! 64-bit MIPS architecture in (big endian).
|
||||
kArchMIPS64_BE = kArchMIPS64_LE | kArchBigEndianMask,
|
||||
|
||||
//! Count of architectures.
|
||||
kArchCount = 11
|
||||
};
|
||||
|
||||
//! Sub-architecture.
|
||||
enum SubArch : uint32_t {
|
||||
//! Unknown or uninitialized architecture sub-type.
|
||||
kSubArchUnknown = 0,
|
||||
|
||||
//! Count of sub-architectures.
|
||||
kSubArchCount
|
||||
};
|
||||
|
||||
//! Vendor.
|
||||
//!
|
||||
//! \note AsmJit doesn't use vendor information at the moment. It's provided
|
||||
//! for future use, if required.
|
||||
enum Vendor : uint32_t {
|
||||
//! Unknown or uninitialized vendor.
|
||||
kVendorUnknown = 0,
|
||||
|
||||
//! Count of vendor identifiers.
|
||||
kVendorCount
|
||||
};
|
||||
|
||||
//! Platform / OS.
|
||||
enum Platform : uint32_t {
|
||||
//! Unknown or uninitialized platform.
|
||||
kPlatformUnknown = 0,
|
||||
|
||||
//! Windows OS.
|
||||
kPlatformWindows,
|
||||
|
||||
//! Other platform, most likely POSIX based.
|
||||
kPlatformOther,
|
||||
|
||||
//! Linux OS.
|
||||
kPlatformLinux,
|
||||
//! GNU/Hurd OS.
|
||||
kPlatformHurd,
|
||||
|
||||
//! FreeBSD OS.
|
||||
kPlatformFreeBSD,
|
||||
//! OpenBSD OS.
|
||||
kPlatformOpenBSD,
|
||||
//! NetBSD OS.
|
||||
kPlatformNetBSD,
|
||||
//! DragonFly BSD OS.
|
||||
kPlatformDragonFlyBSD,
|
||||
|
||||
//! Haiku OS.
|
||||
kPlatformHaiku,
|
||||
|
||||
//! Apple OSX.
|
||||
kPlatformOSX,
|
||||
//! Apple iOS.
|
||||
kPlatformIOS,
|
||||
//! Apple TVOS.
|
||||
kPlatformTVOS,
|
||||
//! Apple WatchOS.
|
||||
kPlatformWatchOS,
|
||||
|
||||
//! Emscripten platform.
|
||||
kPlatformEmscripten,
|
||||
|
||||
//! Count of platform identifiers.
|
||||
kPlatformCount
|
||||
};
|
||||
|
||||
//! ABI.
|
||||
enum Abi : uint32_t {
|
||||
//! Unknown or uninitialied environment.
|
||||
kAbiUnknown = 0,
|
||||
//! Microsoft ABI.
|
||||
kAbiMSVC,
|
||||
//! GNU ABI.
|
||||
kAbiGNU,
|
||||
//! Android Environment / ABI.
|
||||
kAbiAndroid,
|
||||
//! Cygwin ABI.
|
||||
kAbiCygwin,
|
||||
|
||||
//! Count of known ABI types.
|
||||
kAbiCount
|
||||
};
|
||||
|
||||
//! Object format.
|
||||
//!
|
||||
//! \note AsmJit doesn't really use anything except \ref kFormatUnknown and
|
||||
//! \ref kFormatJIT at the moment. Object file formats are provided for
|
||||
//! future extensibility and a possibility to generate object files at some
|
||||
//! point.
|
||||
enum Format : uint32_t {
|
||||
//! Unknown or uninitialized object format.
|
||||
kFormatUnknown = 0,
|
||||
|
||||
//! JIT code generation object, most likely \ref JitRuntime or a custom
|
||||
//! \ref Target implementation.
|
||||
kFormatJIT,
|
||||
|
||||
//! Executable and linkable format (ELF).
|
||||
kFormatELF,
|
||||
//! Common object file format.
|
||||
kFormatCOFF,
|
||||
//! Extended COFF object format.
|
||||
kFormatXCOFF,
|
||||
//! Mach object file format.
|
||||
kFormatMachO,
|
||||
|
||||
//! Count of object format types.
|
||||
kFormatCount
|
||||
};
|
||||
|
||||
//! \name Environment Detection
|
||||
//! \{
|
||||
|
||||
#ifdef _DOXYGEN
|
||||
//! Architecture detected at compile-time (architecture of the host).
|
||||
static constexpr Arch kArchHost = DETECTED_AT_COMPILE_TIME;
|
||||
//! Sub-architecture detected at compile-time (sub-architecture of the host).
|
||||
static constexpr SubArch kSubArchHost = DETECTED_AT_COMPILE_TIME;
|
||||
//! Vendor detected at compile-time (vendor of the host).
|
||||
static constexpr Vendor kVendorHost = DETECTED_AT_COMPILE_TIME;
|
||||
//! Platform detected at compile-time (platform of the host).
|
||||
static constexpr Platform kPlatformHost = DETECTED_AT_COMPILE_TIME;
|
||||
//! ABI detected at compile-time (ABI of the host).
|
||||
static constexpr Abi kAbiHost = DETECTED_AT_COMPILE_TIME;
|
||||
#else
|
||||
static constexpr Arch kArchHost =
|
||||
ASMJIT_ARCH_X86 == 32 ? kArchX86 :
|
||||
ASMJIT_ARCH_X86 == 64 ? kArchX64 :
|
||||
|
||||
ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_LE ? kArchARM :
|
||||
ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_BE ? kArchARM_BE :
|
||||
ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_LE ? kArchAArch64 :
|
||||
ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_BE ? kArchAArch64_BE :
|
||||
|
||||
ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_LE ? kArchMIPS32_LE :
|
||||
ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_BE ? kArchMIPS32_BE :
|
||||
ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_LE ? kArchMIPS64_LE :
|
||||
ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_BE ? kArchMIPS64_BE :
|
||||
|
||||
kArchUnknown;
|
||||
|
||||
static constexpr SubArch kSubArchHost =
|
||||
kSubArchUnknown;
|
||||
|
||||
static constexpr Vendor kVendorHost =
|
||||
kVendorUnknown;
|
||||
|
||||
static constexpr Platform kPlatformHost =
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
kPlatformEmscripten
|
||||
#elif defined(_WIN32)
|
||||
kPlatformWindows
|
||||
#elif defined(__linux__)
|
||||
kPlatformLinux
|
||||
#elif defined(__gnu_hurd__)
|
||||
kPlatformHurd
|
||||
#elif defined(__FreeBSD__)
|
||||
kPlatformFreeBSD
|
||||
#elif defined(__OpenBSD__)
|
||||
kPlatformOpenBSD
|
||||
#elif defined(__NetBSD__)
|
||||
kPlatformNetBSD
|
||||
#elif defined(__DragonFly__)
|
||||
kPlatformDragonFlyBSD
|
||||
#elif defined(__HAIKU__)
|
||||
kPlatformHaiku
|
||||
#elif defined(__APPLE__) && TARGET_OS_OSX
|
||||
kPlatformOSX
|
||||
#elif defined(__APPLE__) && TARGET_OS_TV
|
||||
kPlatformTVOS
|
||||
#elif defined(__APPLE__) && TARGET_OS_WATCH
|
||||
kPlatformWatchOS
|
||||
#elif defined(__APPLE__) && TARGET_OS_IPHONE
|
||||
kPlatformIOS
|
||||
#else
|
||||
kPlatformOther
|
||||
#endif
|
||||
;
|
||||
|
||||
static constexpr Abi kAbiHost =
|
||||
#if defined(_MSC_VER)
|
||||
kAbiMSVC
|
||||
#elif defined(__CYGWIN__)
|
||||
kAbiCygwin
|
||||
#elif defined(__MINGW32__) || defined(__GLIBC__)
|
||||
kAbiGNU
|
||||
#elif defined(__ANDROID__)
|
||||
kAbiAndroid
|
||||
#else
|
||||
kAbiUnknown
|
||||
#endif
|
||||
;
|
||||
|
||||
#endif
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Construction / Destruction
|
||||
//! \{
|
||||
|
||||
inline Environment() noexcept :
|
||||
_arch(uint8_t(kArchUnknown)),
|
||||
_subArch(uint8_t(kSubArchUnknown)),
|
||||
_vendor(uint8_t(kVendorUnknown)),
|
||||
_platform(uint8_t(kPlatformUnknown)),
|
||||
_abi(uint8_t(kAbiUnknown)),
|
||||
_format(uint8_t(kFormatUnknown)),
|
||||
_reserved(0) {}
|
||||
|
||||
inline Environment(const Environment& other) noexcept = default;
|
||||
|
||||
inline explicit Environment(uint32_t arch,
|
||||
uint32_t subArch = kSubArchUnknown,
|
||||
uint32_t vendor = kVendorUnknown,
|
||||
uint32_t platform = kPlatformUnknown,
|
||||
uint32_t abi = kAbiUnknown,
|
||||
uint32_t format = kFormatUnknown) noexcept {
|
||||
init(arch, subArch, vendor, platform, abi, format);
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline Environment& operator=(const Environment& other) noexcept = default;
|
||||
|
||||
inline bool operator==(const Environment& other) const noexcept { return equals(other); }
|
||||
inline bool operator!=(const Environment& other) const noexcept { return !equals(other); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
//! Tests whether the environment is not set up.
|
||||
//!
|
||||
//! Returns true if all members are zero, and thus unknown.
|
||||
inline bool empty() const noexcept {
|
||||
// Unfortunately compilers won't optimize fields are checked one by one...
|
||||
return _packed() == 0;
|
||||
}
|
||||
|
||||
//! Tests whether the environment is intialized, which means it must have
|
||||
//! a valid architecture.
|
||||
inline bool isInitialized() const noexcept {
|
||||
return _arch != kArchUnknown;
|
||||
}
|
||||
|
||||
inline uint64_t _packed() const noexcept {
|
||||
uint64_t x;
|
||||
memcpy(&x, this, 8);
|
||||
return x;
|
||||
}
|
||||
|
||||
//! Resets all members of the environment to zero / unknown.
|
||||
inline void reset() noexcept {
|
||||
_arch = uint8_t(kArchUnknown);
|
||||
_subArch = uint8_t(kSubArchUnknown);
|
||||
_vendor = uint8_t(kVendorUnknown);
|
||||
_platform = uint8_t(kPlatformUnknown);
|
||||
_abi = uint8_t(kAbiUnknown);
|
||||
_format = uint8_t(kFormatUnknown);
|
||||
_reserved = 0;
|
||||
}
|
||||
|
||||
inline bool equals(const Environment& other) const noexcept {
|
||||
return _packed() == other._packed();
|
||||
}
|
||||
|
||||
//! Returns the architecture, see \ref Arch.
|
||||
inline uint32_t arch() const noexcept { return _arch; }
|
||||
//! Returns the sub-architecture, see \ref SubArch.
|
||||
inline uint32_t subArch() const noexcept { return _subArch; }
|
||||
//! Returns vendor, see \ref Vendor.
|
||||
inline uint32_t vendor() const noexcept { return _vendor; }
|
||||
//! Returns target's platform or operating system, see \ref Platform.
|
||||
inline uint32_t platform() const noexcept { return _platform; }
|
||||
//! Returns target's ABI, see \ref Abi.
|
||||
inline uint32_t abi() const noexcept { return _abi; }
|
||||
//! Returns target's object format, see \ref Format.
|
||||
inline uint32_t format() const noexcept { return _format; }
|
||||
|
||||
inline void init(uint32_t arch,
|
||||
uint32_t subArch = kSubArchUnknown,
|
||||
uint32_t vendor = kVendorUnknown,
|
||||
uint32_t platform = kPlatformUnknown,
|
||||
uint32_t abi = kAbiUnknown,
|
||||
uint32_t format = kFormatUnknown) noexcept {
|
||||
_arch = uint8_t(arch);
|
||||
_subArch = uint8_t(subArch);
|
||||
_vendor = uint8_t(vendor);
|
||||
_platform = uint8_t(platform);
|
||||
_abi = uint8_t(abi);
|
||||
_format = uint8_t(format);
|
||||
_reserved = 0;
|
||||
}
|
||||
|
||||
inline bool isArchX86() const noexcept { return _arch == kArchX86; }
|
||||
inline bool isArchX64() const noexcept { return _arch == kArchX64; }
|
||||
inline bool isArchRISCV32() const noexcept { return _arch == kArchRISCV32; }
|
||||
inline bool isArchRISCV64() const noexcept { return _arch == kArchRISCV64; }
|
||||
inline bool isArchARM() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchARM; }
|
||||
inline bool isArchThumb() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchThumb; }
|
||||
inline bool isArchAArch64() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchAArch64; }
|
||||
inline bool isArchMIPS32() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchMIPS32_LE; }
|
||||
inline bool isArchMIPS64() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchMIPS64_LE; }
|
||||
|
||||
//! Tests whether the architecture is 32-bit.
|
||||
inline bool is32Bit() const noexcept { return is32Bit(_arch); }
|
||||
//! Tests whether the architecture is 64-bit.
|
||||
inline bool is64Bit() const noexcept { return is64Bit(_arch); }
|
||||
|
||||
//! Tests whether the architecture is little endian.
|
||||
inline bool isLittleEndian() const noexcept { return isLittleEndian(_arch); }
|
||||
//! Tests whether the architecture is big endian.
|
||||
inline bool isBigEndian() const noexcept { return isBigEndian(_arch); }
|
||||
|
||||
//! Tests whether this architecture is of X86 family.
|
||||
inline bool isFamilyX86() const noexcept { return isFamilyX86(_arch); }
|
||||
//! Tests whether this architecture family is RISC-V (both 32-bit and 64-bit).
|
||||
inline bool isFamilyRISCV() const noexcept { return isFamilyRISCV(_arch); }
|
||||
//! Tests whether this architecture family is ARM, Thumb, or AArch64.
|
||||
inline bool isFamilyARM() const noexcept { return isFamilyARM(_arch); }
|
||||
//! Tests whether this architecture family is MISP or MIPS64.
|
||||
inline bool isFamilyMIPS() const noexcept { return isFamilyMIPS(_arch); }
|
||||
|
||||
//! Tests whether the environment platform is Windows.
|
||||
inline bool isPlatformWindows() const noexcept { return _platform == kPlatformWindows; }
|
||||
|
||||
//! Tests whether the environment platform is Linux.
|
||||
inline bool isPlatformLinux() const noexcept { return _platform == kPlatformLinux; }
|
||||
|
||||
//! Tests whether the environment platform is Hurd.
|
||||
inline bool isPlatformHurd() const noexcept { return _platform == kPlatformHurd; }
|
||||
|
||||
//! Tests whether the environment platform is Haiku.
|
||||
inline bool isPlatformHaiku() const noexcept { return _platform == kPlatformHaiku; }
|
||||
|
||||
//! Tests whether the environment platform is any BSD.
|
||||
inline bool isPlatformBSD() const noexcept {
|
||||
return _platform == kPlatformFreeBSD ||
|
||||
_platform == kPlatformOpenBSD ||
|
||||
_platform == kPlatformNetBSD ||
|
||||
_platform == kPlatformDragonFlyBSD;
|
||||
}
|
||||
|
||||
//! Tests whether the environment platform is any Apple platform (OSX, iOS, TVOS, WatchOS).
|
||||
inline bool isPlatformApple() const noexcept {
|
||||
return _platform == kPlatformOSX ||
|
||||
_platform == kPlatformIOS ||
|
||||
_platform == kPlatformTVOS ||
|
||||
_platform == kPlatformWatchOS;
|
||||
}
|
||||
|
||||
//! Tests whether the ABI is MSVC.
|
||||
inline bool isAbiMSVC() const noexcept { return _abi == kAbiMSVC; }
|
||||
//! Tests whether the ABI is GNU.
|
||||
inline bool isAbiGNU() const noexcept { return _abi == kAbiGNU; }
|
||||
|
||||
//! Returns a calculated stack alignment for this environment.
|
||||
ASMJIT_API uint32_t stackAlignment() const noexcept;
|
||||
|
||||
//! Returns a native register size of this architecture.
|
||||
uint32_t registerSize() const noexcept { return registerSizeFromArch(_arch); }
|
||||
|
||||
//! Sets the architecture to `arch`.
|
||||
inline void setArch(uint32_t arch) noexcept { _arch = uint8_t(arch); }
|
||||
//! Sets the sub-architecture to `subArch`.
|
||||
inline void setSubArch(uint32_t subArch) noexcept { _subArch = uint8_t(subArch); }
|
||||
//! Sets the vendor to `vendor`.
|
||||
inline void setVendor(uint32_t vendor) noexcept { _vendor = uint8_t(vendor); }
|
||||
//! Sets the platform to `platform`.
|
||||
inline void setPlatform(uint32_t platform) noexcept { _platform = uint8_t(platform); }
|
||||
//! Sets the ABI to `abi`.
|
||||
inline void setAbi(uint32_t abi) noexcept { _abi = uint8_t(abi); }
|
||||
//! Sets the object format to `format`.
|
||||
inline void setFormat(uint32_t format) noexcept { _format = uint8_t(format); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Static Utilities
|
||||
//! \{
|
||||
|
||||
static inline bool isValidArch(uint32_t arch) noexcept {
|
||||
return (arch & ~kArchBigEndianMask) != 0 &&
|
||||
(arch & ~kArchBigEndianMask) < kArchCount;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture `arch` is 32-bit.
|
||||
static inline bool is32Bit(uint32_t arch) noexcept {
|
||||
return (arch & kArch32BitMask) == kArch32BitMask;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture `arch` is 64-bit.
|
||||
static inline bool is64Bit(uint32_t arch) noexcept {
|
||||
return (arch & kArch32BitMask) == 0;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture `arch` is little endian.
|
||||
static inline bool isLittleEndian(uint32_t arch) noexcept {
|
||||
return (arch & kArchBigEndianMask) == 0;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture `arch` is big endian.
|
||||
static inline bool isBigEndian(uint32_t arch) noexcept {
|
||||
return (arch & kArchBigEndianMask) == kArchBigEndianMask;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture is AArch64.
|
||||
static inline bool isArchAArch64(uint32_t arch) noexcept {
|
||||
arch &= ~kArchBigEndianMask;
|
||||
return arch == kArchAArch64;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture family is X86 or X64.
|
||||
static inline bool isFamilyX86(uint32_t arch) noexcept {
|
||||
return arch == kArchX86 ||
|
||||
arch == kArchX64;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture family is RISC-V (both 32-bit and 64-bit).
|
||||
static inline bool isFamilyRISCV(uint32_t arch) noexcept {
|
||||
return arch == kArchRISCV32 ||
|
||||
arch == kArchRISCV64;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture family is ARM, Thumb, or AArch64.
|
||||
static inline bool isFamilyARM(uint32_t arch) noexcept {
|
||||
arch &= ~kArchBigEndianMask;
|
||||
return arch == kArchARM ||
|
||||
arch == kArchAArch64 ||
|
||||
arch == kArchThumb;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture family is MISP or MIPS64.
|
||||
static inline bool isFamilyMIPS(uint32_t arch) noexcept {
|
||||
arch &= ~kArchBigEndianMask;
|
||||
return arch == kArchMIPS32_LE ||
|
||||
arch == kArchMIPS64_LE;
|
||||
}
|
||||
|
||||
//! Returns a native general purpose register size from the given architecture.
|
||||
static uint32_t registerSizeFromArch(uint32_t arch) noexcept {
|
||||
return is32Bit(arch) ? 4u : 8u;
|
||||
}
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! Returns the host environment constructed from preprocessor macros defined
|
||||
//! by the compiler.
|
||||
//!
|
||||
//! The returned environment should precisely match the target host architecture,
|
||||
//! sub-architecture, platform, and ABI.
|
||||
static ASMJIT_INLINE Environment hostEnvironment() noexcept {
|
||||
return Environment(Environment::kArchHost,
|
||||
Environment::kSubArchHost,
|
||||
Environment::kVendorHost,
|
||||
Environment::kPlatformHost,
|
||||
Environment::kAbiHost,
|
||||
Environment::kFormatUnknown);
|
||||
}
|
||||
|
||||
static_assert(sizeof(Environment) == 8,
|
||||
"Environment must occupy exactly 8 bytes.");
|
||||
|
||||
//! \}
|
||||
|
||||
#ifndef ASMJIT_NO_DEPRECATED
|
||||
class ASMJIT_DEPRECATED_STRUCT("Use Environment instead") ArchInfo : public Environment {
|
||||
public:
|
||||
inline ArchInfo() noexcept : Environment() {}
|
||||
|
||||
inline ArchInfo(const Environment& other) noexcept : Environment(other) {}
|
||||
inline explicit ArchInfo(uint32_t arch, uint32_t subArch = kSubArchUnknown) noexcept
|
||||
: Environment(arch, subArch) {}
|
||||
|
||||
enum Id : uint32_t {
|
||||
kIdNone = Environment::kArchUnknown,
|
||||
kIdX86 = Environment::kArchX86,
|
||||
kIdX64 = Environment::kArchX64,
|
||||
kIdA32 = Environment::kArchARM,
|
||||
kIdA64 = Environment::kArchAArch64,
|
||||
kIdHost = Environment::kArchHost
|
||||
};
|
||||
|
||||
enum SubType : uint32_t {
|
||||
kSubIdNone = Environment::kSubArchUnknown
|
||||
};
|
||||
|
||||
static inline ArchInfo host() noexcept { return ArchInfo(hostEnvironment()); }
|
||||
};
|
||||
#endif // !ASMJIT_NO_DEPRECATED
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_ENVIRONMENT_H_INCLUDED
|
@ -0,0 +1,37 @@
|
||||
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#include "../core/errorhandler.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ErrorHandler]
|
||||
// ============================================================================
|
||||
|
||||
ErrorHandler::ErrorHandler() noexcept {}
|
||||
ErrorHandler::~ErrorHandler() noexcept {}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
@ -0,0 +1,267 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_ERRORHANDLER_H_INCLUDED
|
||||
#define ASMJIT_CORE_ERRORHANDLER_H_INCLUDED
|
||||
|
||||
#include "../core/globals.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
//! \addtogroup asmjit_error_handling
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [Forward Declarations]
|
||||
// ============================================================================
|
||||
|
||||
class BaseEmitter;
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ErrorHandler]
|
||||
// ============================================================================
|
||||
|
||||
//! Error handler can be used to override the default behavior of error handling.
|
||||
//!
|
||||
//! It's available to all classes that inherit `BaseEmitter`. Override
|
||||
//! \ref ErrorHandler::handleError() to implement your own error handler.
|
||||
//!
|
||||
//! The following use-cases are supported:
|
||||
//!
|
||||
//! - Record the error and continue code generation. This is the simplest
|
||||
//! approach that can be used to at least log possible errors.
|
||||
//! - Throw an exception. AsmJit doesn't use exceptions and is completely
|
||||
//! exception-safe, but it's perfectly legal to throw an exception from
|
||||
//! the error handler.
|
||||
//! - Use plain old C's `setjmp()` and `longjmp()`. Asmjit always puts Assembler,
|
||||
//! Builder and Compiler to a consistent state before calling \ref handleError(),
|
||||
//! so `longjmp()` can be used without issues to cancel the code-generation if
|
||||
//! an error occurred. This method can be used if exception handling in your
|
||||
//! project is turned off and you still want some comfort. In most cases it
|
||||
//! should be safe as AsmJit uses \ref Zone memory and the ownership of memory
|
||||
//! it allocates always ends with the instance that allocated it. If using this
|
||||
//! approach please never jump outside the life-time of \ref CodeHolder and
|
||||
//! \ref BaseEmitter.
|
||||
//!
|
||||
//! \ref ErrorHandler can be attached to \ref CodeHolder or \ref BaseEmitter,
|
||||
//! which has a priority. The example below uses error handler that just prints
|
||||
//! the error, but lets AsmJit continue:
|
||||
//!
|
||||
//! ```
|
||||
//! // Error Handling #1 - Logging and returing Error.
|
||||
//! #include <asmjit/x86.h>
|
||||
//! #include <stdio.h>
|
||||
//!
|
||||
//! using namespace asmjit;
|
||||
//!
|
||||
//! // Error handler that just prints the error and lets AsmJit ignore it.
|
||||
//! class SimpleErrorHandler : public ErrorHandler {
|
||||
//! public:
|
||||
//! Error err;
|
||||
//!
|
||||
//! inline SimpleErrorHandler() : err(kErrorOk) {}
|
||||
//!
|
||||
//! void handleError(Error err, const char* message, BaseEmitter* origin) override {
|
||||
//! this->err = err;
|
||||
//! fprintf(stderr, "ERROR: %s\n", message);
|
||||
//! }
|
||||
//! };
|
||||
//!
|
||||
//! int main() {
|
||||
//! JitRuntime rt;
|
||||
//! SimpleErrorHandler eh;
|
||||
//!
|
||||
//! CodeHolder code;
|
||||
//! code.init(rt.environment());
|
||||
//! code.setErrorHandler(&eh);
|
||||
//!
|
||||
//! // Try to emit instruction that doesn't exist.
|
||||
//! x86::Assembler a(&code);
|
||||
//! a.emit(x86::Inst::kIdMov, x86::xmm0, x86::xmm1);
|
||||
//!
|
||||
//! if (eh.err) {
|
||||
//! // Assembler failed!
|
||||
//! return 1;
|
||||
//! }
|
||||
//!
|
||||
//! return 0;
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! If error happens during instruction emitting / encoding the assembler behaves
|
||||
//! transactionally - the output buffer won't advance if encoding failed, thus
|
||||
//! either a fully encoded instruction or nothing is emitted. The error handling
|
||||
//! shown above is useful, but it's still not the best way of dealing with errors
|
||||
//! in AsmJit. The following example shows how to use exception handling to handle
|
||||
//! errors in a more C++ way:
|
||||
//!
|
||||
//! ```
|
||||
//! // Error Handling #2 - Throwing an exception.
|
||||
//! #include <asmjit/x86.h>
|
||||
//! #include <exception>
|
||||
//! #include <string>
|
||||
//! #include <stdio.h>
|
||||
//!
|
||||
//! using namespace asmjit;
|
||||
//!
|
||||
//! // Error handler that throws a user-defined `AsmJitException`.
|
||||
//! class AsmJitException : public std::exception {
|
||||
//! public:
|
||||
//! Error err;
|
||||
//! std::string message;
|
||||
//!
|
||||
//! AsmJitException(Error err, const char* message) noexcept
|
||||
//! : err(err),
|
||||
//! message(message) {}
|
||||
//!
|
||||
//! const char* what() const noexcept override { return message.c_str(); }
|
||||
//! };
|
||||
//!
|
||||
//! class ThrowableErrorHandler : public ErrorHandler {
|
||||
//! public:
|
||||
//! // Throw is possible, functions that use ErrorHandler are never 'noexcept'.
|
||||
//! void handleError(Error err, const char* message, BaseEmitter* origin) override {
|
||||
//! throw AsmJitException(err, message);
|
||||
//! }
|
||||
//! };
|
||||
//!
|
||||
//! int main() {
|
||||
//! JitRuntime rt;
|
||||
//! ThrowableErrorHandler eh;
|
||||
//!
|
||||
//! CodeHolder code;
|
||||
//! code.init(rt.environment());
|
||||
//! code.setErrorHandler(&eh);
|
||||
//!
|
||||
//! x86::Assembler a(&code);
|
||||
//!
|
||||
//! // Try to emit instruction that doesn't exist.
|
||||
//! try {
|
||||
//! a.emit(x86::Inst::kIdMov, x86::xmm0, x86::xmm1);
|
||||
//! }
|
||||
//! catch (const AsmJitException& ex) {
|
||||
//! printf("EXCEPTION THROWN: %s\n", ex.what());
|
||||
//! return 1;
|
||||
//! }
|
||||
//!
|
||||
//! return 0;
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! If C++ exceptions are not what you like or your project turns off them
|
||||
//! completely there is still a way of reducing the error handling to a minimum
|
||||
//! by using a standard setjmp/longjmp approach. AsmJit is exception-safe and
|
||||
//! cleans up everything before calling the ErrorHandler, so any approach is
|
||||
//! safe. You can simply jump from the error handler without causing any
|
||||
//! side-effects or memory leaks. The following example demonstrates how it
|
||||
//! could be done:
|
||||
//!
|
||||
//! ```
|
||||
//! // Error Handling #3 - Using setjmp/longjmp if exceptions are not allowed.
|
||||
//! #include <asmjit/x86.h>
|
||||
//! #include <setjmp.h>
|
||||
//! #include <stdio.h>
|
||||
//!
|
||||
//! class LongJmpErrorHandler : public asmjit::ErrorHandler {
|
||||
//! public:
|
||||
//! inline LongJmpErrorHandler() : err(asmjit::kErrorOk) {}
|
||||
//!
|
||||
//! void handleError(asmjit::Error err, const char* message, asmjit::BaseEmitter* origin) override {
|
||||
//! this->err = err;
|
||||
//! longjmp(state, 1);
|
||||
//! }
|
||||
//!
|
||||
//! jmp_buf state;
|
||||
//! asmjit::Error err;
|
||||
//! };
|
||||
//!
|
||||
//! int main(int argc, char* argv[]) {
|
||||
//! using namespace asmjit;
|
||||
//!
|
||||
//! JitRuntime rt;
|
||||
//! LongJmpErrorHandler eh;
|
||||
//!
|
||||
//! CodeHolder code;
|
||||
//! code.init(rt.rt.environment());
|
||||
//! code.setErrorHandler(&eh);
|
||||
//!
|
||||
//! x86::Assembler a(&code);
|
||||
//!
|
||||
//! if (!setjmp(eh.state)) {
|
||||
//! // Try to emit instruction that doesn't exist.
|
||||
//! a.emit(x86::Inst::kIdMov, x86::xmm0, x86::xmm1);
|
||||
//! }
|
||||
//! else {
|
||||
//! Error err = eh.err;
|
||||
//! printf("ASMJIT ERROR: 0x%08X [%s]\n", err, DebugUtils::errorAsString(err));
|
||||
//! }
|
||||
//!
|
||||
//! return 0;
|
||||
//! }
|
||||
//! ```
|
||||
class ASMJIT_VIRTAPI ErrorHandler {
|
||||
public:
|
||||
ASMJIT_BASE_CLASS(ErrorHandler)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Creates a new `ErrorHandler` instance.
|
||||
ASMJIT_API ErrorHandler() noexcept;
|
||||
//! Destroys the `ErrorHandler` instance.
|
||||
ASMJIT_API virtual ~ErrorHandler() noexcept;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Handle Error]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Error handler (must be reimplemented).
|
||||
//!
|
||||
//! Error handler is called after an error happened and before it's propagated
|
||||
//! to the caller. There are multiple ways how the error handler can be used:
|
||||
//!
|
||||
//! 1. User-based error handling without throwing exception or using C's
|
||||
//! `longjmp()`. This is for users that don't use exceptions and want
|
||||
//! customized error handling.
|
||||
//!
|
||||
//! 2. Throwing an exception. AsmJit doesn't use exceptions and is completely
|
||||
//! exception-safe, but you can throw exception from your error handler if
|
||||
//! this way is the preferred way of handling errors in your project.
|
||||
//!
|
||||
//! 3. Using plain old C's `setjmp()` and `longjmp()`. Asmjit always puts
|
||||
//! `BaseEmitter` to a consistent state before calling `handleError()`
|
||||
//! so `longjmp()` can be used without any issues to cancel the code
|
||||
//! generation if an error occurred. There is no difference between
|
||||
//! exceptions and `longjmp()` from AsmJit's perspective, however,
|
||||
//! never jump outside of `CodeHolder` and `BaseEmitter` scope as you
|
||||
//! would leak memory.
|
||||
virtual void handleError(Error err, const char* message, BaseEmitter* origin) = 0;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_ERRORHANDLER_H_INCLUDED
|
||||
|
@ -0,0 +1,186 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef ASMJIT_CORE_FEATURES_H_INCLUDED
|
||||
#define ASMJIT_CORE_FEATURES_H_INCLUDED
|
||||
|
||||
#include "../core/globals.h"
|
||||
#include "../core/support.h"
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
//! \addtogroup asmjit_core
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseFeatures]
|
||||
// ============================================================================
|
||||
|
||||
//! Base class that provides information about CPU features.
|
||||
//!
|
||||
//! Internally each feature is represented by a single bit in an embedded
|
||||
//! bit-array, however, feature bits are defined by an architecture specific
|
||||
//! implementations, like \ref x86::Features.
|
||||
class BaseFeatures {
|
||||
public:
|
||||
typedef Support::BitWord BitWord;
|
||||
typedef Support::BitVectorIterator<BitWord> Iterator;
|
||||
|
||||
enum : uint32_t {
|
||||
kMaxFeatures = 256,
|
||||
kNumBitWords = kMaxFeatures / Support::kBitWordSizeInBits
|
||||
};
|
||||
|
||||
BitWord _bits[kNumBitWords];
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline BaseFeatures() noexcept { reset(); }
|
||||
inline BaseFeatures(const BaseFeatures& other) noexcept = default;
|
||||
inline explicit BaseFeatures(Globals::NoInit_) noexcept {}
|
||||
|
||||
inline void reset() noexcept {
|
||||
for (size_t i = 0; i < kNumBitWords; i++)
|
||||
_bits[i] = 0;
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline BaseFeatures& operator=(const BaseFeatures& other) noexcept = default;
|
||||
|
||||
inline bool operator==(const BaseFeatures& other) noexcept { return eq(other); }
|
||||
inline bool operator!=(const BaseFeatures& other) noexcept { return !eq(other); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Cast
|
||||
//! \{
|
||||
|
||||
//! Casts this base class into a derived type `T`.
|
||||
template<typename T>
|
||||
inline T& as() noexcept { return static_cast<T&>(*this); }
|
||||
|
||||
//! Casts this base class into a derived type `T` (const).
|
||||
template<typename T>
|
||||
inline const T& as() const noexcept { return static_cast<const T&>(*this); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline bool empty() const noexcept {
|
||||
for (uint32_t i = 0; i < kNumBitWords; i++)
|
||||
if (_bits[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Returns all features as array of bitwords (see \ref Support::BitWord).
|
||||
inline BitWord* bits() noexcept { return _bits; }
|
||||
//! Returns all features as array of bitwords (const).
|
||||
inline const BitWord* bits() const noexcept { return _bits; }
|
||||
|
||||
//! Returns the number of BitWords returned by \ref bits().
|
||||
inline size_t bitWordCount() const noexcept { return kNumBitWords; }
|
||||
|
||||
//! Returns \ref Support::BitVectorIterator, that can be used to iterate
|
||||
//! all features efficiently
|
||||
inline Iterator iterator() const noexcept {
|
||||
return Iterator(_bits, kNumBitWords);
|
||||
}
|
||||
|
||||
//! Tests whether the feature `featureId` is present.
|
||||
inline bool has(uint32_t featureId) const noexcept {
|
||||
ASMJIT_ASSERT(featureId < kMaxFeatures);
|
||||
|
||||
uint32_t idx = featureId / Support::kBitWordSizeInBits;
|
||||
uint32_t bit = featureId % Support::kBitWordSizeInBits;
|
||||
|
||||
return bool((_bits[idx] >> bit) & 0x1);
|
||||
}
|
||||
|
||||
//! Tests whether all features as defined by `other` are present.
|
||||
inline bool hasAll(const BaseFeatures& other) const noexcept {
|
||||
for (uint32_t i = 0; i < kNumBitWords; i++)
|
||||
if ((_bits[i] & other._bits[i]) != other._bits[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Utilities
|
||||
//! \{
|
||||
|
||||
//! Adds the given CPU `featureId` to the list of features.
|
||||
inline void add(uint32_t featureId) noexcept {
|
||||
ASMJIT_ASSERT(featureId < kMaxFeatures);
|
||||
|
||||
uint32_t idx = featureId / Support::kBitWordSizeInBits;
|
||||
uint32_t bit = featureId % Support::kBitWordSizeInBits;
|
||||
|
||||
_bits[idx] |= BitWord(1) << bit;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void add(uint32_t featureId, Args... otherIds) noexcept {
|
||||
add(featureId);
|
||||
add(otherIds...);
|
||||
}
|
||||
|
||||
//! Removes the given CPU `featureId` from the list of features.
|
||||
inline void remove(uint32_t featureId) noexcept {
|
||||
ASMJIT_ASSERT(featureId < kMaxFeatures);
|
||||
|
||||
uint32_t idx = featureId / Support::kBitWordSizeInBits;
|
||||
uint32_t bit = featureId % Support::kBitWordSizeInBits;
|
||||
|
||||
_bits[idx] &= ~(BitWord(1) << bit);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void remove(uint32_t featureId, Args... otherIds) noexcept {
|
||||
remove(featureId);
|
||||
remove(otherIds...);
|
||||
}
|
||||
|
||||
inline bool eq(const BaseFeatures& other) const noexcept {
|
||||
for (size_t i = 0; i < kNumBitWords; i++)
|
||||
if (_bits[i] != other._bits[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_CORE_FEATURES_H_INCLUDED
|
@ -0,0 +1,481 @@
|
||||
// AsmJit - Machine code generation for C++
|
||||
//
|
||||
// * Official AsmJit Home Page: https://asmjit.com
|
||||
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||||
//
|
||||
// Copyright (c) 2008-2020 The AsmJit Authors
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "../core/api-build_p.h"
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
|
||||
#include "../core/builder.h"
|
||||
#include "../core/codeholder.h"
|
||||
#include "../core/compiler.h"
|
||||
#include "../core/emitter.h"
|
||||
#include "../core/formatter.h"
|
||||
#include "../core/string.h"
|
||||
#include "../core/support.h"
|
||||
#include "../core/type.h"
|
||||
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
#include "../x86/x86formatter_p.h"
|
||||
#endif
|
||||
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
#include "../arm/armformatter_p.h"
|
||||
#endif
|
||||
|
||||
ASMJIT_BEGIN_NAMESPACE
|
||||
|
||||
#if defined(ASMJIT_NO_COMPILER)
|
||||
class VirtReg;
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Formatter]
|
||||
// ============================================================================
|
||||
|
||||
namespace Formatter {
|
||||
|
||||
Error formatTypeId(String& sb, uint32_t typeId) noexcept {
|
||||
if (typeId == Type::kIdVoid)
|
||||
return sb.append("void");
|
||||
|
||||
if (!Type::isValid(typeId))
|
||||
return sb.append("unknown");
|
||||
|
||||
const char* typeName = "unknown";
|
||||
uint32_t typeSize = Type::sizeOf(typeId);
|
||||
|
||||
uint32_t baseId = Type::baseOf(typeId);
|
||||
switch (baseId) {
|
||||
case Type::kIdIntPtr : typeName = "iptr" ; break;
|
||||
case Type::kIdUIntPtr: typeName = "uptr" ; break;
|
||||
case Type::kIdI8 : typeName = "i8" ; break;
|
||||
case Type::kIdU8 : typeName = "u8" ; break;
|
||||
case Type::kIdI16 : typeName = "i16" ; break;
|
||||
case Type::kIdU16 : typeName = "u16" ; break;
|
||||
case Type::kIdI32 : typeName = "i32" ; break;
|
||||
case Type::kIdU32 : typeName = "u32" ; break;
|
||||
case Type::kIdI64 : typeName = "i64" ; break;
|
||||
case Type::kIdU64 : typeName = "u64" ; break;
|
||||
case Type::kIdF32 : typeName = "f32" ; break;
|
||||
case Type::kIdF64 : typeName = "f64" ; break;
|
||||
case Type::kIdF80 : typeName = "f80" ; break;
|
||||
case Type::kIdMask8 : typeName = "mask8" ; break;
|
||||
case Type::kIdMask16 : typeName = "mask16"; break;
|
||||
case Type::kIdMask32 : typeName = "mask32"; break;
|
||||
case Type::kIdMask64 : typeName = "mask64"; break;
|
||||
case Type::kIdMmx32 : typeName = "mmx32" ; break;
|
||||
case Type::kIdMmx64 : typeName = "mmx64" ; break;
|
||||
}
|
||||
|
||||
uint32_t baseSize = Type::sizeOf(baseId);
|
||||
if (typeSize > baseSize) {
|
||||
uint32_t count = typeSize / baseSize;
|
||||
return sb.appendFormat("%sx%u", typeName, unsigned(count));
|
||||
}
|
||||
else {
|
||||
return sb.append(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
Error formatFeature(
|
||||
String& sb,
|
||||
uint32_t arch,
|
||||
uint32_t featureId) noexcept {
|
||||
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
if (Environment::isFamilyX86(arch))
|
||||
return x86::FormatterInternal::formatFeature(sb, featureId);
|
||||
#endif
|
||||
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
if (Environment::isFamilyARM(arch))
|
||||
return arm::FormatterInternal::formatFeature(sb, featureId);
|
||||
#endif
|
||||
|
||||
return kErrorInvalidArch;
|
||||
}
|
||||
|
||||
Error formatLabel(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
const BaseEmitter* emitter,
|
||||
uint32_t labelId) noexcept {
|
||||
|
||||
DebugUtils::unused(formatFlags);
|
||||
|
||||
const LabelEntry* le = emitter->code()->labelEntry(labelId);
|
||||
if (ASMJIT_UNLIKELY(!le))
|
||||
return sb.appendFormat("<InvalidLabel:%u>", labelId);
|
||||
|
||||
if (le->hasName()) {
|
||||
if (le->hasParent()) {
|
||||
uint32_t parentId = le->parentId();
|
||||
const LabelEntry* pe = emitter->code()->labelEntry(parentId);
|
||||
|
||||
if (ASMJIT_UNLIKELY(!pe))
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("<InvalidLabel:%u>", labelId));
|
||||
else if (ASMJIT_UNLIKELY(!pe->hasName()))
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("L%u", parentId));
|
||||
else
|
||||
ASMJIT_PROPAGATE(sb.append(pe->name()));
|
||||
|
||||
ASMJIT_PROPAGATE(sb.append('.'));
|
||||
}
|
||||
return sb.append(le->name());
|
||||
}
|
||||
else {
|
||||
return sb.appendFormat("L%u", labelId);
|
||||
}
|
||||
}
|
||||
|
||||
Error formatRegister(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
const BaseEmitter* emitter,
|
||||
uint32_t arch,
|
||||
uint32_t regType,
|
||||
uint32_t regId) noexcept {
|
||||
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
if (Environment::isFamilyX86(arch))
|
||||
return x86::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId);
|
||||
#endif
|
||||
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
if (Environment::isFamilyARM(arch))
|
||||
return arm::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId);
|
||||
#endif
|
||||
|
||||
return kErrorInvalidArch;
|
||||
}
|
||||
|
||||
Error formatOperand(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
const BaseEmitter* emitter,
|
||||
uint32_t arch,
|
||||
const Operand_& op) noexcept {
|
||||
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
if (Environment::isFamilyX86(arch))
|
||||
return x86::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op);
|
||||
#endif
|
||||
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
if (Environment::isFamilyARM(arch))
|
||||
return arm::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op);
|
||||
#endif
|
||||
|
||||
return kErrorInvalidArch;
|
||||
}
|
||||
|
||||
Error formatInstruction(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
const BaseEmitter* emitter,
|
||||
uint32_t arch,
|
||||
const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept {
|
||||
|
||||
#ifdef ASMJIT_BUILD_X86
|
||||
if (Environment::isFamilyX86(arch))
|
||||
return x86::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount);
|
||||
#endif
|
||||
|
||||
#ifdef ASMJIT_BUILD_ARM
|
||||
if (Environment::isFamilyARM(arch))
|
||||
return arm::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount);
|
||||
#endif
|
||||
|
||||
return kErrorInvalidArch;
|
||||
}
|
||||
|
||||
#ifndef ASMJIT_NO_BUILDER
|
||||
|
||||
#ifndef ASMJIT_NO_COMPILER
|
||||
static Error formatFuncValue(String& sb, uint32_t formatFlags, const BaseEmitter* emitter, FuncValue value) noexcept {
|
||||
uint32_t typeId = value.typeId();
|
||||
ASMJIT_PROPAGATE(formatTypeId(sb, typeId));
|
||||
|
||||
if (value.isAssigned()) {
|
||||
ASMJIT_PROPAGATE(sb.append('@'));
|
||||
|
||||
if (value.isIndirect())
|
||||
ASMJIT_PROPAGATE(sb.append('['));
|
||||
|
||||
// NOTE: It should be either reg or stack, but never both. We
|
||||
// use two IFs on purpose so if the FuncValue is both it would
|
||||
// show in logs.
|
||||
if (value.isReg()) {
|
||||
ASMJIT_PROPAGATE(formatRegister(sb, formatFlags, emitter, emitter->arch(), value.regType(), value.regId()));
|
||||
}
|
||||
|
||||
if (value.isStack()) {
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("[%d]", int(value.stackOffset())));
|
||||
}
|
||||
|
||||
if (value.isIndirect())
|
||||
ASMJIT_PROPAGATE(sb.append(']'));
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
static Error formatFuncValuePack(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
const BaseEmitter* emitter,
|
||||
const FuncValuePack& pack,
|
||||
VirtReg* const* vRegs) noexcept {
|
||||
|
||||
size_t count = pack.count();
|
||||
if (!count)
|
||||
return sb.append("void");
|
||||
|
||||
if (count > 1)
|
||||
sb.append('[');
|
||||
|
||||
for (uint32_t valueIndex = 0; valueIndex < count; valueIndex++) {
|
||||
const FuncValue& value = pack[valueIndex];
|
||||
if (!value)
|
||||
break;
|
||||
|
||||
if (valueIndex)
|
||||
ASMJIT_PROPAGATE(sb.append(", "));
|
||||
|
||||
ASMJIT_PROPAGATE(formatFuncValue(sb, formatFlags, emitter, value));
|
||||
|
||||
if (vRegs) {
|
||||
static const char nullRet[] = "<none>";
|
||||
ASMJIT_PROPAGATE(sb.appendFormat(" %s", vRegs[valueIndex] ? vRegs[valueIndex]->name() : nullRet));
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 1)
|
||||
sb.append(']');
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
static Error formatFuncRets(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
const BaseEmitter* emitter,
|
||||
const FuncDetail& fd) noexcept {
|
||||
|
||||
return formatFuncValuePack(sb, formatFlags, emitter, fd.retPack(), nullptr);
|
||||
}
|
||||
|
||||
static Error formatFuncArgs(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
const BaseEmitter* emitter,
|
||||
const FuncDetail& fd,
|
||||
const FuncNode::ArgPack* argPacks) noexcept {
|
||||
|
||||
uint32_t argCount = fd.argCount();
|
||||
if (!argCount)
|
||||
return sb.append("void");
|
||||
|
||||
for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) {
|
||||
if (argIndex)
|
||||
ASMJIT_PROPAGATE(sb.append(", "));
|
||||
|
||||
ASMJIT_PROPAGATE(formatFuncValuePack(sb, formatFlags, emitter, fd.argPack(argIndex), argPacks[argIndex]._data));
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
#endif
|
||||
|
||||
Error formatNode(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
const BaseBuilder* builder,
|
||||
const BaseNode* node) noexcept {
|
||||
|
||||
if (node->hasPosition() && (formatFlags & FormatOptions::kFlagPositions) != 0)
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("<%05u> ", node->position()));
|
||||
|
||||
switch (node->type()) {
|
||||
case BaseNode::kNodeInst:
|
||||
case BaseNode::kNodeJump: {
|
||||
const InstNode* instNode = node->as<InstNode>();
|
||||
ASMJIT_PROPAGATE(
|
||||
formatInstruction(sb, formatFlags, builder,
|
||||
builder->arch(),
|
||||
instNode->baseInst(), instNode->operands(), instNode->opCount()));
|
||||
break;
|
||||
}
|
||||
|
||||
case BaseNode::kNodeSection: {
|
||||
const SectionNode* sectionNode = node->as<SectionNode>();
|
||||
if (builder->_code->isSectionValid(sectionNode->id())) {
|
||||
const Section* section = builder->_code->sectionById(sectionNode->id());
|
||||
ASMJIT_PROPAGATE(sb.appendFormat(".section %s", section->name()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BaseNode::kNodeLabel: {
|
||||
const LabelNode* labelNode = node->as<LabelNode>();
|
||||
ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, labelNode->labelId()));
|
||||
ASMJIT_PROPAGATE(sb.append(":"));
|
||||
break;
|
||||
}
|
||||
|
||||
case BaseNode::kNodeAlign: {
|
||||
const AlignNode* alignNode = node->as<AlignNode>();
|
||||
ASMJIT_PROPAGATE(
|
||||
sb.appendFormat("align %u (%s)",
|
||||
alignNode->alignment(),
|
||||
alignNode->alignMode() == kAlignCode ? "code" : "data"));
|
||||
break;
|
||||
}
|
||||
|
||||
case BaseNode::kNodeEmbedData: {
|
||||
const EmbedDataNode* embedNode = node->as<EmbedDataNode>();
|
||||
ASMJIT_PROPAGATE(sb.append("embed "));
|
||||
if (embedNode->repeatCount() != 1)
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("[repeat=%zu] ", size_t(embedNode->repeatCount())));
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("%u bytes", embedNode->dataSize()));
|
||||
break;
|
||||
}
|
||||
|
||||
case BaseNode::kNodeEmbedLabel: {
|
||||
const EmbedLabelNode* embedNode = node->as<EmbedLabelNode>();
|
||||
ASMJIT_PROPAGATE(sb.append(".label "));
|
||||
ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->labelId()));
|
||||
break;
|
||||
}
|
||||
|
||||
case BaseNode::kNodeEmbedLabelDelta: {
|
||||
const EmbedLabelDeltaNode* embedNode = node->as<EmbedLabelDeltaNode>();
|
||||
ASMJIT_PROPAGATE(sb.append(".label ("));
|
||||
ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->labelId()));
|
||||
ASMJIT_PROPAGATE(sb.append(" - "));
|
||||
ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->baseLabelId()));
|
||||
ASMJIT_PROPAGATE(sb.append(")"));
|
||||
break;
|
||||
}
|
||||
|
||||
case BaseNode::kNodeComment: {
|
||||
const CommentNode* commentNode = node->as<CommentNode>();
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("; %s", commentNode->inlineComment()));
|
||||
break;
|
||||
}
|
||||
|
||||
case BaseNode::kNodeSentinel: {
|
||||
const SentinelNode* sentinelNode = node->as<SentinelNode>();
|
||||
const char* sentinelName = nullptr;
|
||||
|
||||
switch (sentinelNode->sentinelType()) {
|
||||
case SentinelNode::kSentinelFuncEnd:
|
||||
sentinelName = "[FuncEnd]";
|
||||
break;
|
||||
|
||||
default:
|
||||
sentinelName = "[Sentinel]";
|
||||
break;
|
||||
}
|
||||
|
||||
ASMJIT_PROPAGATE(sb.append(sentinelName));
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef ASMJIT_NO_COMPILER
|
||||
case BaseNode::kNodeFunc: {
|
||||
const FuncNode* funcNode = node->as<FuncNode>();
|
||||
|
||||
ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, funcNode->labelId()));
|
||||
ASMJIT_PROPAGATE(sb.append(": "));
|
||||
|
||||
ASMJIT_PROPAGATE(formatFuncRets(sb, formatFlags, builder, funcNode->detail()));
|
||||
ASMJIT_PROPAGATE(sb.append(" Func("));
|
||||
ASMJIT_PROPAGATE(formatFuncArgs(sb, formatFlags, builder, funcNode->detail(), funcNode->argPacks()));
|
||||
ASMJIT_PROPAGATE(sb.append(")"));
|
||||
break;
|
||||
}
|
||||
|
||||
case BaseNode::kNodeFuncRet: {
|
||||
const FuncRetNode* retNode = node->as<FuncRetNode>();
|
||||
ASMJIT_PROPAGATE(sb.append("[FuncRet]"));
|
||||
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
const Operand_& op = retNode->_opArray[i];
|
||||
if (!op.isNone()) {
|
||||
ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", "));
|
||||
ASMJIT_PROPAGATE(formatOperand(sb, formatFlags, builder, builder->arch(), op));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BaseNode::kNodeInvoke: {
|
||||
const InvokeNode* invokeNode = node->as<InvokeNode>();
|
||||
ASMJIT_PROPAGATE(
|
||||
formatInstruction(sb, formatFlags, builder,
|
||||
builder->arch(),
|
||||
invokeNode->baseInst(), invokeNode->operands(), invokeNode->opCount()));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default: {
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("[UserNode:%u]", node->type()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
|
||||
Error formatNodeList(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
const BaseBuilder* builder) noexcept {
|
||||
|
||||
return formatNodeList(sb, formatFlags, builder, builder->firstNode(), nullptr);
|
||||
}
|
||||
|
||||
Error formatNodeList(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
const BaseBuilder* builder,
|
||||
const BaseNode* begin,
|
||||
const BaseNode* end) noexcept {
|
||||
|
||||
const BaseNode* node = begin;
|
||||
while (node != end) {
|
||||
ASMJIT_PROPAGATE(formatNode(sb, formatFlags, builder, node));
|
||||
ASMJIT_PROPAGATE(sb.append('\n'));
|
||||
node = node->next();
|
||||
}
|
||||
return kErrorOk;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // {Formatter}
|
||||
|
||||
ASMJIT_END_NAMESPACE
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue