Initial Commit

This commit is contained in:
Sajid
2024-09-07 18:00:09 +06:00
commit 0f9a53f75a
3352 changed files with 1563708 additions and 0 deletions

5
thirdparty/capstone/contrib/README vendored Normal file
View File

@@ -0,0 +1,5 @@
This directory contains contributions that do not belong to the core engine.
Code here might be helpful for those who want to integrate Capstone into
their own projects.
The license of these code was defined by their authors.

View File

@@ -0,0 +1,5 @@
This directory contains a sample project for using Capstone from a Windows
driver. Open cs_driver.sln with Visual Studio 2013 or newer and see cs_driver.c
for details.
For prerequisites to compile Capstone for drivers, see COMPILE_MSVC.TXT.

View File

@@ -0,0 +1,49 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cs_driver", "cs_driver\cs_driver.vcxproj", "{F29A9424-0ECD-4FFE-9CB7-C844756373BB}"
ProjectSection(ProjectDependencies) = postProject
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B} = {FE197816-EF84-4E8D-B29D-E0A6BA2B144B}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "capstone_static_winkernel", "..\..\msvc\capstone_static_winkernel\capstone_static_winkernel.vcxproj", "{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Debug|Win32.ActiveCfg = Debug|Win32
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Debug|Win32.Build.0 = Debug|Win32
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Debug|Win32.Deploy.0 = Debug|Win32
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Debug|x64.ActiveCfg = Debug|x64
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Debug|x64.Build.0 = Debug|x64
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Debug|x64.Deploy.0 = Debug|x64
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Release|Win32.ActiveCfg = Release|Win32
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Release|Win32.Build.0 = Release|Win32
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Release|Win32.Deploy.0 = Release|Win32
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Release|x64.ActiveCfg = Release|x64
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Release|x64.Build.0 = Release|x64
{F29A9424-0ECD-4FFE-9CB7-C844756373BB}.Release|x64.Deploy.0 = Release|x64
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Debug|Win32.ActiveCfg = Debug|Win32
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Debug|Win32.Build.0 = Debug|Win32
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Debug|Win32.Deploy.0 = Debug|Win32
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Debug|x64.ActiveCfg = Debug|x64
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Debug|x64.Build.0 = Debug|x64
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Debug|x64.Deploy.0 = Debug|x64
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Release|Win32.ActiveCfg = Release|Win32
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Release|Win32.Build.0 = Release|Win32
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Release|Win32.Deploy.0 = Release|Win32
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Release|x64.ActiveCfg = Release|x64
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Release|x64.Build.0 = Release|x64
{FE197816-EF84-4E8D-B29D-E0A6BA2B144B}.Release|x64.Deploy.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,99 @@
/* Capstone Driver */
/* By Satoshi Tanda <tanda.sat@gmail.com>, 2016 */
// Firstly, compile capstone_static_winkernel and
// generate capstone_static_winkernel.lib. It can be done by adding the
// capstone_static_winkernel project to your solution and compiling it first.
//
// Then, configure your driver project (cs_driver in this example) to locate to
// capstone.h and capstone_static_winkernel.lib. To do it, open project
// properties of the project and set Configuration to "All Configurations" and
// Platform to "All Platforms". Then, add the following entries:
// - C/C++ > General > Additional Include Directories
// - $(SolutionDir)capstone\include
// - Linker > Input > Additional Dependencies
// - $(OutDir)capstone_static_winkernel.lib
// - ntstrsafe.lib
//
// Note that ntstrsafe.lib is required to resolve __fltused indirectly used in
// Capstone.
#include <ntddk.h>
#include <capstone/capstone.h>
// 'conversion' : from function pointer 'type1' to data pointer 'type2'
#pragma warning(disable : 4054)
DRIVER_INITIALIZE DriverEntry;
static NTSTATUS cs_driver_hello();
// Driver entry point
EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath) {
printf("Entering DriverEntry()\n");
cs_driver_hello();
printf("Leaving DriverEntry()\n");
return STATUS_CANCELLED;
}
// Hello, Capstone!
static NTSTATUS cs_driver_hello() {
csh handle;
cs_insn *insn;
size_t count;
KFLOATING_SAVE float_save;
NTSTATUS status = STATUS_UNSUCCESSFUL;
// Any of Capstone APIs cannot be called at IRQL higher than DISPATCH_LEVEL
// since our malloc implementation based on ExAllocatePoolWithTag() is not able
// to allocate memory at higher IRQL than the DISPATCH_LEVEL level.
NT_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
// On a 32bit driver, KeSaveFloatingPointState() is required before using any
// Capstone function because Capstone can access to the MMX/x87 registers and
// 32bit Windows requires drivers to use KeSaveFloatingPointState() before and
// KeRestoreFloatingPointState() after accessing them. See "Using Floating
// Point or MMX in a WDM Driver" on MSDN for more details.
status = KeSaveFloatingPointState(&float_save);
if (!NT_SUCCESS(status)) {
return status;
}
// Do stuff just like user-mode. All functionalities are supported.
if (cs_open(CS_ARCH_X86, (sizeof(void *) == 4) ? CS_MODE_32 : CS_MODE_64,
&handle) != CS_ERR_OK) {
goto exit;
}
count = cs_disasm(handle, (uint8_t *)&cs_driver_hello, 0x80,
(uint64_t)&cs_driver_hello, 0, &insn);
if (count > 0) {
printf("cs_driver!cs_driver_hello:\n");
for (size_t j = 0; j < count; j++) {
printf("0x%p\t%s\t\t%s\n", (void *)(uintptr_t)insn[j].address,
insn[j].mnemonic, insn[j].op_str);
}
cs_free(insn, count);
}
cs_close(&handle);
exit:;
// Restores the nonvolatile floating-point context.
KeRestoreFloatingPointState(&float_save);
return status;
}
// printf()
_Use_decl_annotations_ int __cdecl printf(const char *_Format, ...) {
NTSTATUS status;
va_list args;
va_start(args, _Format);
status = vDbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, _Format, args);
va_end(args);
return NT_SUCCESS(status);
}

View File

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{F29A9424-0ECD-4FFE-9CB7-C844756373BB}</ProjectGuid>
<TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
<Configuration>Win8.1 Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>cs_driver</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WppScanConfigurationData Condition="'%(ClCompile. ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>$(OutDir)capstone_static_winkernel.lib;ntstrsafe.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WppScanConfigurationData Condition="'%(ClCompile. ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>$(OutDir)capstone_static_winkernel.lib;ntstrsafe.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WppScanConfigurationData Condition="'%(ClCompile. ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>$(OutDir)capstone_static_winkernel.lib;ntstrsafe.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WppScanConfigurationData Condition="'%(ClCompile. ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>$(OutDir)capstone_static_winkernel.lib;ntstrsafe.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
<FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="cs_driver.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,26 @@
<?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>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Driver Files">
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
<Extensions>inf;inv;inx;mof;mc;</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="cs_driver.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,468 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
/* This code is used to build the static lookup table used inside the M68KDisassembler.c code
* To run this use the Makefile in the same directory
*/
typedef struct {
const char *name; /* handler function name */
uint16_t mask; /* mask on opcode */
uint16_t match; /* what to match after masking */
uint16_t ea_mask; /* what ea modes are allowed */
uint16_t mask2; /* mask the 2nd word */
uint16_t match2; /* what to match after masking */
} opcode_struct;
/* ======================================================================== */
/* ======================= INSTRUCTION TABLE BUILDER ====================== */
/* ======================================================================== */
/* EA Masks:
800 = data register direct
400 = address register direct
200 = address register indirect
100 = ARI postincrement
80 = ARI pre-decrement
40 = ARI displacement
20 = ARI index
10 = absolute short
8 = absolute long
4 = immediate / sr
2 = pc displacement
1 = pc idx
*/
static opcode_struct g_opcode_info[] = {
/* opcode handler mask match ea_mask mask2 match2*/
{"d68000_1010" , 0xf000, 0xa000, 0x000},
{"d68000_1111" , 0xf000, 0xf000, 0x000},
{"d68000_abcd_rr" , 0xf1f8, 0xc100, 0x000},
{"d68000_abcd_mm" , 0xf1f8, 0xc108, 0x000},
{"d68000_add_er_8" , 0xf1c0, 0xd000, 0xbff},
{"d68000_add_er_16" , 0xf1c0, 0xd040, 0xfff},
{"d68000_add_er_32" , 0xf1c0, 0xd080, 0xfff},
{"d68000_add_re_8" , 0xf1c0, 0xd100, 0x3f8},
{"d68000_add_re_16" , 0xf1c0, 0xd140, 0x3f8},
{"d68000_add_re_32" , 0xf1c0, 0xd180, 0x3f8},
{"d68000_adda_16" , 0xf1c0, 0xd0c0, 0xfff},
{"d68000_adda_32" , 0xf1c0, 0xd1c0, 0xfff},
{"d68000_addi_8" , 0xffc0, 0x0600, 0xbf8},
{"d68000_addi_16" , 0xffc0, 0x0640, 0xbf8},
{"d68000_addi_32" , 0xffc0, 0x0680, 0xbf8},
{"d68000_addq_8" , 0xf1c0, 0x5000, 0xbf8},
{"d68000_addq_16" , 0xf1c0, 0x5040, 0xff8},
{"d68000_addq_32" , 0xf1c0, 0x5080, 0xff8},
{"d68000_addx_rr_8" , 0xf1f8, 0xd100, 0x000},
{"d68000_addx_rr_16" , 0xf1f8, 0xd140, 0x000},
{"d68000_addx_rr_32" , 0xf1f8, 0xd180, 0x000},
{"d68000_addx_mm_8" , 0xf1f8, 0xd108, 0x000},
{"d68000_addx_mm_16" , 0xf1f8, 0xd148, 0x000},
{"d68000_addx_mm_32" , 0xf1f8, 0xd188, 0x000},
{"d68000_and_er_8" , 0xf1c0, 0xc000, 0xbff},
{"d68000_and_er_16" , 0xf1c0, 0xc040, 0xbff},
{"d68000_and_er_32" , 0xf1c0, 0xc080, 0xbff},
{"d68000_and_re_8" , 0xf1c0, 0xc100, 0x3f8},
{"d68000_and_re_16" , 0xf1c0, 0xc140, 0x3f8},
{"d68000_and_re_32" , 0xf1c0, 0xc180, 0x3f8},
{"d68000_andi_to_ccr" , 0xffff, 0x023c, 0x000, 0xff00, 0x0000},
{"d68000_andi_to_sr" , 0xffff, 0x027c, 0x000},
{"d68000_andi_8" , 0xffc0, 0x0200, 0xbf8},
{"d68000_andi_16" , 0xffc0, 0x0240, 0xbf8},
{"d68000_andi_32" , 0xffc0, 0x0280, 0xbf8},
{"d68000_asr_s_8" , 0xf1f8, 0xe000, 0x000},
{"d68000_asr_s_16" , 0xf1f8, 0xe040, 0x000},
{"d68000_asr_s_32" , 0xf1f8, 0xe080, 0x000},
{"d68000_asr_r_8" , 0xf1f8, 0xe020, 0x000},
{"d68000_asr_r_16" , 0xf1f8, 0xe060, 0x000},
{"d68000_asr_r_32" , 0xf1f8, 0xe0a0, 0x000},
{"d68000_asr_ea" , 0xffc0, 0xe0c0, 0x3f8},
{"d68000_asl_s_8" , 0xf1f8, 0xe100, 0x000},
{"d68000_asl_s_16" , 0xf1f8, 0xe140, 0x000},
{"d68000_asl_s_32" , 0xf1f8, 0xe180, 0x000},
{"d68000_asl_r_8" , 0xf1f8, 0xe120, 0x000},
{"d68000_asl_r_16" , 0xf1f8, 0xe160, 0x000},
{"d68000_asl_r_32" , 0xf1f8, 0xe1a0, 0x000},
{"d68000_asl_ea" , 0xffc0, 0xe1c0, 0x3f8},
{"d68000_bcc_8" , 0xf000, 0x6000, 0x000},
{"d68000_bcc_16" , 0xf0ff, 0x6000, 0x000},
{"d68020_bcc_32" , 0xf0ff, 0x60ff, 0x000},
{"d68000_bchg_r" , 0xf1c0, 0x0140, 0xbf8},
{"d68000_bchg_s" , 0xffc0, 0x0840, 0xbf8, 0xff00, 0x0000},
{"d68000_bclr_r" , 0xf1c0, 0x0180, 0xbf8},
{"d68000_bclr_s" , 0xffc0, 0x0880, 0xbf8, 0xff00, 0x0000},
{"d68020_bfchg" , 0xffc0, 0xeac0, 0xa78, 0xf000, 0x0000},
{"d68020_bfclr" , 0xffc0, 0xecc0, 0xa78, 0xf000, 0x0000},
{"d68020_bfexts" , 0xffc0, 0xebc0, 0xa7b, 0x8000, 0x0000},
{"d68020_bfextu" , 0xffc0, 0xe9c0, 0xa7b, 0x8000, 0x0000},
{"d68020_bfffo" , 0xffc0, 0xedc0, 0xa7b, 0x8000, 0x0000},
{"d68020_bfins" , 0xffc0, 0xefc0, 0xa78, 0x8000, 0x0000},
{"d68020_bfset" , 0xffc0, 0xeec0, 0xa78, 0xf000, 0x0000},
{"d68020_bftst" , 0xffc0, 0xe8c0, 0xa7b, 0xf000, 0x0000},
{"d68010_bkpt" , 0xfff8, 0x4848, 0x000},
{"d68000_bra_8" , 0xff00, 0x6000, 0x000},
{"d68000_bra_16" , 0xffff, 0x6000, 0x000},
{"d68020_bra_32" , 0xffff, 0x60ff, 0x000},
{"d68000_bset_r" , 0xf1c0, 0x01c0, 0xbf8},
{"d68000_bset_s" , 0xffc0, 0x08c0, 0xbf8, 0xfe00, 0x0000 },
{"d68000_bsr_8" , 0xff00, 0x6100, 0x000},
{"d68000_bsr_16" , 0xffff, 0x6100, 0x000},
{"d68020_bsr_32" , 0xffff, 0x61ff, 0x000},
{"d68000_btst_r" , 0xf1c0, 0x0100, 0xbff},
{"d68000_btst_s" , 0xffc0, 0x0800, 0xbfb, 0xff00, 0x0000},
{"d68020_callm" , 0xffc0, 0x06c0, 0x27b, 0xff00, 0x0000},
{"d68020_cas_8" , 0xffc0, 0x0ac0, 0x3f8, 0xfe38, 0x0000},
{"d68020_cas_16" , 0xffc0, 0x0cc0, 0x3f8, 0xfe38, 0x0000},
{"d68020_cas_32" , 0xffc0, 0x0ec0, 0x3f8, 0xfe38, 0x0000},
{"d68020_cas2_16" , 0xffff, 0x0cfc, 0x000, 0x0e38, 0x0000/*, 0x0e38, 0x0000 */},
{"d68020_cas2_32" , 0xffff, 0x0efc, 0x000, 0x0e38, 0x0000/*, 0x0e38, 0x0000 */},
{"d68000_chk_16" , 0xf1c0, 0x4180, 0xbff},
{"d68020_chk_32" , 0xf1c0, 0x4100, 0xbff},
{"d68020_chk2_cmp2_8" , 0xffc0, 0x00c0, 0x27b, 0x07ff, 0x0000},
{"d68020_chk2_cmp2_16" , 0xffc0, 0x02c0, 0x27b, 0x07ff, 0x0000},
{"d68020_chk2_cmp2_32" , 0xffc0, 0x04c0, 0x27b, 0x07ff, 0x0000},
{"d68040_cinv" , 0xff20, 0xf400, 0x000},
{"d68000_clr_8" , 0xffc0, 0x4200, 0xbf8},
{"d68000_clr_16" , 0xffc0, 0x4240, 0xbf8},
{"d68000_clr_32" , 0xffc0, 0x4280, 0xbf8},
{"d68000_cmp_8" , 0xf1c0, 0xb000, 0xbff},
{"d68000_cmp_16" , 0xf1c0, 0xb040, 0xfff},
{"d68000_cmp_32" , 0xf1c0, 0xb080, 0xfff},
{"d68000_cmpa_16" , 0xf1c0, 0xb0c0, 0xfff},
{"d68000_cmpa_32" , 0xf1c0, 0xb1c0, 0xfff},
{"d68000_cmpi_8" , 0xffc0, 0x0c00, 0xbf8},
{"d68020_cmpi_pcdi_8" , 0xffff, 0x0c3a, 0x000},
{"d68020_cmpi_pcix_8" , 0xffff, 0x0c3b, 0x000},
{"d68000_cmpi_16" , 0xffc0, 0x0c40, 0xbf8},
{"d68020_cmpi_pcdi_16" , 0xffff, 0x0c7a, 0x000},
{"d68020_cmpi_pcix_16" , 0xffff, 0x0c7b, 0x000},
{"d68000_cmpi_32" , 0xffc0, 0x0c80, 0xbf8},
{"d68020_cmpi_pcdi_32" , 0xffff, 0x0cba, 0x000},
{"d68020_cmpi_pcix_32" , 0xffff, 0x0cbb, 0x000},
{"d68000_cmpm_8" , 0xf1f8, 0xb108, 0x000},
{"d68000_cmpm_16" , 0xf1f8, 0xb148, 0x000},
{"d68000_cmpm_32" , 0xf1f8, 0xb188, 0x000},
{"d68020_cpbcc_16" , 0xf1c0, 0xf080, 0x000},
{"d68020_cpbcc_32" , 0xf1c0, 0xf0c0, 0x000},
{"d68020_cpdbcc" , 0xf1f8, 0xf048, 0x000},
{"d68020_cpgen" , 0xf1c0, 0xf000, 0x000},
{"d68020_cprestore" , 0xf1c0, 0xf140, 0x37f},
{"d68020_cpsave" , 0xf1c0, 0xf100, 0x2f8},
{"d68020_cpscc" , 0xf1c0, 0xf040, 0xbf8},
{"d68020_cptrapcc_0" , 0xf1ff, 0xf07c, 0x000},
{"d68020_cptrapcc_16" , 0xf1ff, 0xf07a, 0x000},
{"d68020_cptrapcc_32" , 0xf1ff, 0xf07b, 0x000},
{"d68040_cpush" , 0xff20, 0xf420, 0x000},
{"d68000_dbcc" , 0xf0f8, 0x50c8, 0x000},
{"d68000_dbra" , 0xfff8, 0x51c8, 0x000},
{"d68000_divs" , 0xf1c0, 0x81c0, 0xbff},
{"d68000_divu" , 0xf1c0, 0x80c0, 0xbff},
{"d68020_divl" , 0xff80, 0x4c00, 0xbff, 0x83f8, 0x0000},
{"d68000_eor_8" , 0xf1c0, 0xb100, 0xbf8},
{"d68000_eor_16" , 0xf1c0, 0xb140, 0xbf8},
{"d68000_eor_32" , 0xf1c0, 0xb180, 0xbf8},
{"d68000_eori_to_ccr" , 0xffff, 0x0a3c, 0x000, 0xff00, 0x0000},
{"d68000_eori_to_sr" , 0xffff, 0x0a7c, 0x000},
{"d68000_eori_8" , 0xffc0, 0x0a00, 0xbf8},
{"d68000_eori_16" , 0xffc0, 0x0a40, 0xbf8},
{"d68000_eori_32" , 0xffc0, 0x0a80, 0xbf8},
{"d68000_exg_dd" , 0xf1f8, 0xc140, 0x000},
{"d68000_exg_aa" , 0xf1f8, 0xc148, 0x000},
{"d68000_exg_da" , 0xf1f8, 0xc188, 0x000},
{"d68020_extb_32" , 0xfff8, 0x49c0, 0x000},
{"d68000_ext_16" , 0xfff8, 0x4880, 0x000},
{"d68000_ext_32" , 0xfff8, 0x48c0, 0x000},
{"d68000_illegal" , 0xffff, 0x4afc, 0x000},
{"d68000_jmp" , 0xffc0, 0x4ec0, 0x27b},
{"d68000_jsr" , 0xffc0, 0x4e80, 0x27b},
{"d68000_lea" , 0xf1c0, 0x41c0, 0x27b},
{"d68000_link_16" , 0xfff8, 0x4e50, 0x000},
{"d68020_link_32" , 0xfff8, 0x4808, 0x000},
{"d68000_lsr_s_8" , 0xf1f8, 0xe008, 0x000},
{"d68000_lsr_s_16" , 0xf1f8, 0xe048, 0x000},
{"d68000_lsr_s_32" , 0xf1f8, 0xe088, 0x000},
{"d68000_lsr_r_8" , 0xf1f8, 0xe028, 0x000},
{"d68000_lsr_r_16" , 0xf1f8, 0xe068, 0x000},
{"d68000_lsr_r_32" , 0xf1f8, 0xe0a8, 0x000},
{"d68000_lsr_ea" , 0xffc0, 0xe2c0, 0x3f8},
{"d68000_lsl_s_8" , 0xf1f8, 0xe108, 0x000},
{"d68000_lsl_s_16" , 0xf1f8, 0xe148, 0x000},
{"d68000_lsl_s_32" , 0xf1f8, 0xe188, 0x000},
{"d68000_lsl_r_8" , 0xf1f8, 0xe128, 0x000},
{"d68000_lsl_r_16" , 0xf1f8, 0xe168, 0x000},
{"d68000_lsl_r_32" , 0xf1f8, 0xe1a8, 0x000},
{"d68000_lsl_ea" , 0xffc0, 0xe3c0, 0x3f8},
{"d68000_move_8" , 0xf000, 0x1000, 0xbff},
{"d68000_move_16" , 0xf000, 0x3000, 0xfff},
{"d68000_move_32" , 0xf000, 0x2000, 0xfff},
{"d68000_movea_16" , 0xf1c0, 0x3040, 0xfff},
{"d68000_movea_32" , 0xf1c0, 0x2040, 0xfff},
{"d68000_move_to_ccr" , 0xffc0, 0x44c0, 0xbff},
{"d68010_move_fr_ccr" , 0xffc0, 0x42c0, 0xbf8},
{"d68000_move_to_sr" , 0xffc0, 0x46c0, 0xbff},
{"d68000_move_fr_sr" , 0xffc0, 0x40c0, 0xbf8},
{"d68000_move_to_usp" , 0xfff8, 0x4e60, 0x000},
{"d68000_move_fr_usp" , 0xfff8, 0x4e68, 0x000},
{"d68010_movec" , 0xfffe, 0x4e7a, 0x000},
{"d68000_movem_pd_16" , 0xfff8, 0x48a0, 0x000},
{"d68000_movem_pd_32" , 0xfff8, 0x48e0, 0x000},
{"d68000_movem_re_16" , 0xffc0, 0x4880, 0x2f8},
{"d68000_movem_re_32" , 0xffc0, 0x48c0, 0x2f8},
{"d68000_movem_er_16" , 0xffc0, 0x4c80, 0x37b},
{"d68000_movem_er_32" , 0xffc0, 0x4cc0, 0x37b},
{"d68000_movep_er_16" , 0xf1f8, 0x0108, 0x000},
{"d68000_movep_er_32" , 0xf1f8, 0x0148, 0x000},
{"d68000_movep_re_16" , 0xf1f8, 0x0188, 0x000},
{"d68000_movep_re_32" , 0xf1f8, 0x01c8, 0x000},
{"d68010_moves_8" , 0xffc0, 0x0e00, 0x3f8, 0x07ff, 0x0000},
{"d68010_moves_16" , 0xffc0, 0x0e40, 0x3f8, 0x07ff, 0x0000},
{"d68010_moves_32" , 0xffc0, 0x0e80, 0x3f8, 0x07ff, 0x0000},
{"d68000_moveq" , 0xf100, 0x7000, 0x000},
{"d68040_move16_pi_pi" , 0xfff8, 0xf620, 0x000, 0x8fff, 0x8000},
{"d68040_move16_pi_al" , 0xfff8, 0xf600, 0x000},
{"d68040_move16_al_pi" , 0xfff8, 0xf608, 0x000},
{"d68040_move16_ai_al" , 0xfff8, 0xf610, 0x000},
{"d68040_move16_al_ai" , 0xfff8, 0xf618, 0x000},
{"d68000_muls" , 0xf1c0, 0xc1c0, 0xbff},
{"d68000_mulu" , 0xf1c0, 0xc0c0, 0xbff},
{"d68020_mull" , 0xffc0, 0x4c00, 0xbff, 0x83f8, 0x0000},
{"d68000_nbcd" , 0xffc0, 0x4800, 0xbf8},
{"d68000_neg_8" , 0xffc0, 0x4400, 0xbf8},
{"d68000_neg_16" , 0xffc0, 0x4440, 0xbf8},
{"d68000_neg_32" , 0xffc0, 0x4480, 0xbf8},
{"d68000_negx_8" , 0xffc0, 0x4000, 0xbf8},
{"d68000_negx_16" , 0xffc0, 0x4040, 0xbf8},
{"d68000_negx_32" , 0xffc0, 0x4080, 0xbf8},
{"d68000_nop" , 0xffff, 0x4e71, 0x000},
{"d68000_not_8" , 0xffc0, 0x4600, 0xbf8},
{"d68000_not_16" , 0xffc0, 0x4640, 0xbf8},
{"d68000_not_32" , 0xffc0, 0x4680, 0xbf8},
{"d68000_or_er_8" , 0xf1c0, 0x8000, 0xbff},
{"d68000_or_er_16" , 0xf1c0, 0x8040, 0xbff},
{"d68000_or_er_32" , 0xf1c0, 0x8080, 0xbff},
{"d68000_or_re_8" , 0xf1c0, 0x8100, 0x3f8},
{"d68000_or_re_16" , 0xf1c0, 0x8140, 0x3f8},
{"d68000_or_re_32" , 0xf1c0, 0x8180, 0x3f8},
{"d68000_ori_to_ccr" , 0xffff, 0x003c, 0x000, 0xff00, 0x0000},
{"d68000_ori_to_sr" , 0xffff, 0x007c, 0x000},
{"d68000_ori_8" , 0xffc0, 0x0000, 0xbf8},
{"d68000_ori_16" , 0xffc0, 0x0040, 0xbf8},
{"d68000_ori_32" , 0xffc0, 0x0080, 0xbf8},
{"d68020_pack_rr" , 0xf1f8, 0x8140, 0x000},
{"d68020_pack_mm" , 0xf1f8, 0x8148, 0x000},
{"d68000_pea" , 0xffc0, 0x4840, 0x27b},
{"d68000_reset" , 0xffff, 0x4e70, 0x000},
{"d68000_ror_s_8" , 0xf1f8, 0xe018, 0x000},
{"d68000_ror_s_16" , 0xf1f8, 0xe058, 0x000},
{"d68000_ror_s_32" , 0xf1f8, 0xe098, 0x000},
{"d68000_ror_r_8" , 0xf1f8, 0xe038, 0x000},
{"d68000_ror_r_16" , 0xf1f8, 0xe078, 0x000},
{"d68000_ror_r_32" , 0xf1f8, 0xe0b8, 0x000},
{"d68000_ror_ea" , 0xffc0, 0xe6c0, 0x3f8},
{"d68000_rol_s_8" , 0xf1f8, 0xe118, 0x000},
{"d68000_rol_s_16" , 0xf1f8, 0xe158, 0x000},
{"d68000_rol_s_32" , 0xf1f8, 0xe198, 0x000},
{"d68000_rol_r_8" , 0xf1f8, 0xe138, 0x000},
{"d68000_rol_r_16" , 0xf1f8, 0xe178, 0x000},
{"d68000_rol_r_32" , 0xf1f8, 0xe1b8, 0x000},
{"d68000_rol_ea" , 0xffc0, 0xe7c0, 0x3f8},
{"d68000_roxr_s_8" , 0xf1f8, 0xe010, 0x000},
{"d68000_roxr_s_16" , 0xf1f8, 0xe050, 0x000},
{"d68000_roxr_s_32" , 0xf1f8, 0xe090, 0x000},
{"d68000_roxr_r_8" , 0xf1f8, 0xe030, 0x000},
{"d68000_roxr_r_16" , 0xf1f8, 0xe070, 0x000},
{"d68000_roxr_r_32" , 0xf1f8, 0xe0b0, 0x000},
{"d68000_roxr_ea" , 0xffc0, 0xe4c0, 0x3f8},
{"d68000_roxl_s_8" , 0xf1f8, 0xe110, 0x000},
{"d68000_roxl_s_16" , 0xf1f8, 0xe150, 0x000},
{"d68000_roxl_s_32" , 0xf1f8, 0xe190, 0x000},
{"d68000_roxl_r_8" , 0xf1f8, 0xe130, 0x000},
{"d68000_roxl_r_16" , 0xf1f8, 0xe170, 0x000},
{"d68000_roxl_r_32" , 0xf1f8, 0xe1b0, 0x000},
{"d68000_roxl_ea" , 0xffc0, 0xe5c0, 0x3f8},
{"d68010_rtd" , 0xffff, 0x4e74, 0x000},
{"d68000_rte" , 0xffff, 0x4e73, 0x000},
{"d68020_rtm" , 0xfff0, 0x06c0, 0x000},
{"d68000_rtr" , 0xffff, 0x4e77, 0x000},
{"d68000_rts" , 0xffff, 0x4e75, 0x000},
{"d68000_sbcd_rr" , 0xf1f8, 0x8100, 0x000},
{"d68000_sbcd_mm" , 0xf1f8, 0x8108, 0x000},
{"d68000_scc" , 0xf0c0, 0x50c0, 0xbf8},
{"d68000_stop" , 0xffff, 0x4e72, 0x000},
{"d68000_sub_er_8" , 0xf1c0, 0x9000, 0xbff},
{"d68000_sub_er_16" , 0xf1c0, 0x9040, 0xfff},
{"d68000_sub_er_32" , 0xf1c0, 0x9080, 0xfff},
{"d68000_sub_re_8" , 0xf1c0, 0x9100, 0x3f8},
{"d68000_sub_re_16" , 0xf1c0, 0x9140, 0x3f8},
{"d68000_sub_re_32" , 0xf1c0, 0x9180, 0x3f8},
{"d68000_suba_16" , 0xf1c0, 0x90c0, 0xfff},
{"d68000_suba_32" , 0xf1c0, 0x91c0, 0xfff},
{"d68000_subi_8" , 0xffc0, 0x0400, 0xbf8},
{"d68000_subi_16" , 0xffc0, 0x0440, 0xbf8},
{"d68000_subi_32" , 0xffc0, 0x0480, 0xbf8},
{"d68000_subq_8" , 0xf1c0, 0x5100, 0xbf8},
{"d68000_subq_16" , 0xf1c0, 0x5140, 0xff8},
{"d68000_subq_32" , 0xf1c0, 0x5180, 0xff8},
{"d68000_subx_rr_8" , 0xf1f8, 0x9100, 0x000},
{"d68000_subx_rr_16" , 0xf1f8, 0x9140, 0x000},
{"d68000_subx_rr_32" , 0xf1f8, 0x9180, 0x000},
{"d68000_subx_mm_8" , 0xf1f8, 0x9108, 0x000},
{"d68000_subx_mm_16" , 0xf1f8, 0x9148, 0x000},
{"d68000_subx_mm_32" , 0xf1f8, 0x9188, 0x000},
{"d68000_swap" , 0xfff8, 0x4840, 0x000},
{"d68000_tas" , 0xffc0, 0x4ac0, 0xbf8},
{"d68000_trap" , 0xfff0, 0x4e40, 0x000},
{"d68020_trapcc_0" , 0xf0ff, 0x50fc, 0x000},
{"d68020_trapcc_16" , 0xf0ff, 0x50fa, 0x000},
{"d68020_trapcc_32" , 0xf0ff, 0x50fb, 0x000},
{"d68000_trapv" , 0xffff, 0x4e76, 0x000},
{"d68000_tst_8" , 0xffc0, 0x4a00, 0xbf8},
{"d68020_tst_pcdi_8" , 0xffff, 0x4a3a, 0x000},
{"d68020_tst_pcix_8" , 0xffff, 0x4a3b, 0x000},
{"d68020_tst_i_8" , 0xffff, 0x4a3c, 0x000},
{"d68000_tst_16" , 0xffc0, 0x4a40, 0xbf8},
{"d68020_tst_a_16" , 0xfff8, 0x4a48, 0x000},
{"d68020_tst_pcdi_16" , 0xffff, 0x4a7a, 0x000},
{"d68020_tst_pcix_16" , 0xffff, 0x4a7b, 0x000},
{"d68020_tst_i_16" , 0xffff, 0x4a7c, 0x000},
{"d68000_tst_32" , 0xffc0, 0x4a80, 0xbf8},
{"d68020_tst_a_32" , 0xfff8, 0x4a88, 0x000},
{"d68020_tst_pcdi_32" , 0xffff, 0x4aba, 0x000},
{"d68020_tst_pcix_32" , 0xffff, 0x4abb, 0x000},
{"d68020_tst_i_32" , 0xffff, 0x4abc, 0x000},
{"d68000_unlk" , 0xfff8, 0x4e58, 0x000},
{"d68020_unpk_rr" , 0xf1f8, 0x8180, 0x000},
{"d68020_unpk_mm" , 0xf1f8, 0x8188, 0x000},
{0, 0, 0, 0}
};
/* Check if opcode is using a valid ea mode */
static int valid_ea(unsigned int opcode, unsigned int mask)
{
if (mask == 0)
return 1;
switch(opcode & 0x3f) {
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x04: case 0x05: case 0x06: case 0x07:
return (mask & 0x800) != 0;
case 0x08: case 0x09: case 0x0a: case 0x0b:
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
return (mask & 0x400) != 0;
case 0x10: case 0x11: case 0x12: case 0x13:
case 0x14: case 0x15: case 0x16: case 0x17:
return (mask & 0x200) != 0;
case 0x18: case 0x19: case 0x1a: case 0x1b:
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
return (mask & 0x100) != 0;
case 0x20: case 0x21: case 0x22: case 0x23:
case 0x24: case 0x25: case 0x26: case 0x27:
return (mask & 0x080) != 0;
case 0x28: case 0x29: case 0x2a: case 0x2b:
case 0x2c: case 0x2d: case 0x2e: case 0x2f:
return (mask & 0x040) != 0;
case 0x30: case 0x31: case 0x32: case 0x33:
case 0x34: case 0x35: case 0x36: case 0x37:
return (mask & 0x020) != 0;
case 0x38:
return (mask & 0x010) != 0;
case 0x39:
return (mask & 0x008) != 0;
case 0x3a:
return (mask & 0x002) != 0;
case 0x3b:
return (mask & 0x001) != 0;
case 0x3c:
return (mask & 0x004) != 0;
}
return 0;
}
#ifndef DECL_SPEC
#ifdef _MSC_VER
#define DECL_SPEC __cdecl
#else
#define DECL_SPEC
#endif // _MSC_VER
#endif // DECL_SPEC
/* Used by qsort */
static int DECL_SPEC compare_nof_true_bits(const void *aptr, const void *bptr)
{
unsigned int a = ((const opcode_struct*)aptr)->mask;
unsigned int b = ((const opcode_struct*)bptr)->mask;
a = ((a & 0xAAAA) >> 1) + (a & 0x5555);
a = ((a & 0xCCCC) >> 2) + (a & 0x3333);
a = ((a & 0xF0F0) >> 4) + (a & 0x0F0F);
a = ((a & 0xFF00) >> 8) + (a & 0x00FF);
b = ((b & 0xAAAA) >> 1) + (b & 0x5555);
b = ((b & 0xCCCC) >> 2) + (b & 0x3333);
b = ((b & 0xF0F0) >> 4) + (b & 0x0F0F);
b = ((b & 0xFF00) >> 8) + (b & 0x00FF);
return b - a; /* reversed to get greatest to least sorting */
}
/* build the opcode handler jump table */
static void build_opcode_table(void)
{
unsigned int i;
unsigned int opcode;
opcode_struct* ostruct;
unsigned int opcode_info_length = 0;
const unsigned int total_count = 0x10000;
for(ostruct = g_opcode_info;ostruct->name != 0;ostruct++)
opcode_info_length++;
qsort((void *)g_opcode_info, opcode_info_length, sizeof(g_opcode_info[0]), compare_nof_true_bits);
printf("/* This table is auto-generated. DO NOT MANUALLY EDIT! Look in M68KInstructionTblGen.c for more info */\n");
printf("static const instruction_struct g_instruction_table[] = {\n");
for(i=0;i<0x10000;i++) {
const char *name = "d68000_invalid";
uint16_t word2_mask = 0;
uint16_t word2_match = 0;
opcode = i;
/* search through opcode info for a match */
for(ostruct = g_opcode_info;ostruct->name != 0;ostruct++) {
/* match opcode mask and allowed ea modes */
if ((opcode & ostruct->mask) == ostruct->match) {
/* Handle destination ea for move instructions */
if ((!strcmp(ostruct->name, "d68000_move_8") ||
!strcmp(ostruct->name, "d68000_move_16") ||
!strcmp(ostruct->name, "d68000_move_32")) &&
!valid_ea(((opcode>>9)&7) | ((opcode>>3)&0x38), 0xbf8))
continue;
if (valid_ea(opcode, ostruct->ea_mask)) {
name = ostruct->name;
word2_mask = ostruct->mask2;
word2_match = ostruct->match2;
break;
}
}
}
// Handle so the last entry won't have a , at the end
if (i != total_count - 1) {
printf("\t{ %s, 0x%x, 0x%x },\n", name, word2_mask, word2_match);
} else {
printf("\t{ %s, 0x%x, 0x%x }\n", name, word2_mask, word2_match);
}
}
printf("};\n\n");
}
int main() {
build_opcode_table();
return 0;
}

View File

@@ -0,0 +1,15 @@
CC=gcc
ODIR=obj
TBL_GEN=tbl_gen
INC_FILE=../../arch/M68K/M68KInstructionTable.inc
gen_inc: $(TBL_GEN)
./$(TBL_GEN) > $(INC_FILE)
tbl_gen: M68KInstructionTblGen.c
$(CC) -O3 M68KInstructionTblGen.c -o $(TBL_GEN)
.PHONY: clean
clean:
rm $(TBL_GEN)

View File

@@ -0,0 +1,425 @@
#!/usr/bin/env python3
import sys
import bitstring
from capstone import *
from capstone.m68k import *
#
# Objdump with the same output as his binary cousin
#
TODO = """
TODO :
o need more testing on M68K_AM_*_DISP
o cleanup, etc ...
"""
objdump_cmd_example = 'm68k-atari-mint-objdump -b binary -D -mm68k --adjust-vma 0x30664 u/m68k.bin'
objdump_dumpheader_fmt = """
%s: file format binary
Disassembly of section .data:
%08x <.data>:"""
M68000_CODE = b"\x04\x40\x00\x40"
all_tests = (
(CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_060, M68000_CODE, "M68060-32 (Big-endian)"),
)
def dump_bytes(b, len):
str = ''
i = 0
while i < len:
str += format("%02x%02x " % (b[i], b[i+1]))
i += 2
return str[:-1]
def dump_op_reg(insn, op_reg):
if op_reg == M68K_REG_A7:
return "%sp"
if op_reg == M68K_REG_A6:
return "%fp"
return '%' + insn.reg_name(op_reg)
def s8(value):
return bitstring.Bits(uint=value, length=8).unpack('int')[0]
def s16(value):
return bitstring.Bits(uint=value, length=16).unpack('int')[0]
def extsign8(value):
if value & 0x80:
return 0xffffffffffffff00 + value
return value
def extsign1616(value):
if value & 0x8000:
return 0xffff0000 + value
return value
def extsign1632(value):
if value & 0x8000:
return 0xffffffffffff0000 + value
return value
def printRegbitsRange(buffer, data, prefix):
str = ''
first = 0
run_length = 0
i = 0
while i < 8:
if (data & (1 << i)):
first = i
run_length = 0
while (i < 7 and (data & (1 << (i + 1)))):
i += 1
run_length += 1
if len(buffer) or len(str):
str += "/"
str += format("%%%s%d" % (prefix, first))
if run_length > 0:
str += format("-%%%s%d" % (prefix, first + run_length))
i += 1
return str
def registerBits(op):
str = ''
data = op.register_bits
str += printRegbitsRange(str, data & 0xff, "d")
str += printRegbitsRange(str, (data >> 8) & 0xff, "a")
str += printRegbitsRange(str, (data >> 16) & 0xff, "fp")
return str
def dump_op_ea(insn, op):
s_spacing = " "
map_index_size_str = { 0: 'w', 1 : 'l' }
str = ''
if op.address_mode == M68K_AM_NONE:
if op.type == M68K_OP_REG_BITS:
return registerBits(op)
if op.type == M68K_OP_REG_PAIR:
return registerPair(op)
if op.type == M68K_OP_REG:
return dump_op_reg(insn, op.reg)
if op.address_mode == M68K_AM_REG_DIRECT_DATA:
return dump_op_reg(insn, op.reg)
if op.address_mode == M68K_AM_REG_DIRECT_ADDR:
return dump_op_reg(insn, op.reg) + "@"
if op.address_mode == M68K_AM_REGI_ADDR:
return dump_op_reg(insn, op.reg) + "@"
if op.address_mode == M68K_AM_REGI_ADDR_POST_INC:
return dump_op_reg(insn, op.reg) + "@+"
if op.address_mode == M68K_AM_REGI_ADDR_PRE_DEC:
return dump_op_reg(insn, op.reg) + "@-"
if op.address_mode == M68K_AM_REGI_ADDR_DISP:
# str = dump_op_reg(insn, op.mem.base_reg - M68K_REG_A0 + 1) #double check and fixme '+1' : 02af 899f 2622
str = dump_op_reg(insn, op.mem.base_reg)
if op.mem.disp:
str += format("@(%d)" % s16(op.mem.disp))
return str
if op.address_mode == M68K_AM_PCI_DISP:
return format("%%pc@(0x%x)" % ( extsign1616(op.mem.disp + 2)))
if op.address_mode == M68K_AM_ABSOLUTE_DATA_SHORT:
return format("0x%x" % (extsign1616(op.imm & 0xffff)))
if op.address_mode == M68K_AM_ABSOLUTE_DATA_LONG:
return format("0x%x" % (op.imm & 0xffffffff))
if op.address_mode == M68K_AM_IMMEDIATE:
if insn.op_size.type == M68K_SIZE_TYPE_FPU:
map_fpu_size_str = { M68K_FPU_SIZE_SINGLE : op.simm, M68K_FPU_SIZE_DOUBLE : op.dimm }
return format("#%f" % (insn.op_size.fpu_size[map_fpu_size_str]))
return format("#$%x" % (op.imm))
if op.address_mode in [ M68K_AM_PCI_INDEX_8_BIT_DISP, M68K_AM_AREGI_INDEX_8_BIT_DISP ]:
disp = op.mem.disp
if op.register_bits == 2:
disp = extsign8(op.mem.disp)
if op.register_bits == 4:
disp = extsign1632(op.mem.disp)
str = dump_op_reg(insn, op.mem.base_reg) + "@(" + "{0:016x}".format(disp) + "," + dump_op_reg(insn, op.mem.index_reg) + ":" + map_index_size_str[op.mem.index_size]
if op.register_bits:
str += format(":%u" % (op.register_bits))
return str + ")"
if op.address_mode in [ M68K_AM_PCI_INDEX_BASE_DISP, M68K_AM_AREGI_INDEX_BASE_DISP ]:
str += format("%s" % ( dump_op_reg(insn, op.mem.base_reg) ))
str += format("@(%016x)@(%016x" % (extsign1632(op.mem.in_disp), extsign1632(op.mem.out_disp)))
if op.mem.index_reg:
str += "," + dump_op_reg(insn, op.mem.index_reg) + ":" + map_index_size_str[op.mem.index_size]
if op.register_bits:
str += format(":%u" % (op.register_bits))
str += ")"
return str
if op.mem.in_disp > 0:
str += format("$%x" % ( op.mem.in_disp))
str += format("(")
if op.address_mode == M68K_AM_PCI_INDEX_BASE_DISP:
str_size = ''
if op.mem.index_size:
str_size = "l"
else:
str_size = "w"
str += format("pc,%s%s.%s" % ( dump_op_reg(insn, op.mem.index_reg)), s_spacing, str_size)
else:
if op.mem.base_reg != M68K_REG_INVALID:
str += format("a%d,%s" % ( op.mem.base_reg - M68K_REG_A0, s_spacing))
str_size = ''
if op.mem.index_size:
str_size = "l"
else:
str_size = "w"
str += format("%s.%s" % ( dump_op_reg(insn, op.mem.index_reg), str_size))
if op.mem.scale > 0:
str += format("%s*%s%d)" % ( s_spacing, s_spacing, op.mem.scale))
else:
str += ")"
return str
# It's ok to just use PCMI here as is as we set base_reg to PC in the disassembler.
# While this is not strictly correct it makes the code
# easier and that is what actually happens when the code is executed anyway.
if op.address_mode in [ M68K_AM_PC_MEMI_POST_INDEX, M68K_AM_PC_MEMI_PRE_INDEX, M68K_AM_MEMI_PRE_INDEX, M68K_AM_MEMI_POST_INDEX]:
if op.mem.base_reg:
str += format("%s" % ( dump_op_reg(insn, op.mem.base_reg) ))
if op.mem.in_disp:
value = op.mem.in_disp
if op.mem.in_disp & 0x8000:
value = 0xffffffffffff0000 + op.mem.in_disp
str += format("@(%016x)@(%016x)" % (value, op.mem.out_disp))
return str
str += format("([")
if op.mem.in_disp > 0:
str += format("$%x" % ( op.mem.in_disp))
if op.mem.base_reg != M68K_REG_INVALID:
if op.mem.in_disp > 0:
str += format(",%s%s" % ( s_spacing, dump_op_reg(insn, op.mem.base_reg)))
else:
str += format("%s" % ( dump_op_reg(insn, op.mem.base_reg)))
if op.address_mode in [ M68K_AM_MEMI_POST_INDEX, M68K_AM_PC_MEMI_POST_INDEX]:
str += format("]")
if op.mem.index_reg != M68K_REG_INVALID:
str_size = ''
if op.mem.index_size:
str_size = "l"
else:
str_size = "w"
str += format(",%s%s.%s" % ( s_spacing, dump_op_reg(insn, op.mem.index_reg), str_size))
if op.mem.scale > 0:
str += format("%s*%s%d" % ( s_spacing, s_spacing, op.mem.scale))
if op.address_mode in [ M68K_AM_MEMI_PRE_INDEX, M68K_AM_PC_MEMI_PRE_INDEX]:
str += format("]")
if op.mem.out_disp > 0:
str += format(",%s$%x" % ( s_spacing, op.mem.out_disp))
str += format(")")
return str
if op.mem.bitfield:
return format("%d:%d" % ( op.mem.offset, op.mem.width))
############# OK
if op.address_mode == M68K_AM_AREGI_INDEX_BASE_DISP:
if op.mem.index_size:
str_size = "l"
else:
str_size = "w"
bits = op.mem.disp
return dump_op_reg(insn, op.mem.base_reg) + "@(" + "{0:016b}".format(bits) + "," + dump_op_reg(insn, op.mem.index_reg) + ":" + str_size + ")"
return ''
# M68K Addressing Modes
map_address_mode_str = {
0 : "M68K_AM_NONE",
1 : "M68K_AM_REG_DIRECT_DATA",
2 : "M68K_AM_REG_DIRECT_ADDR",
3 : "M68K_AM_REGI_ADDR",
4 : "M68K_AM_REGI_ADDR_POST_INC",
5 : "M68K_AM_REGI_ADDR_PRE_DEC",
6 : "M68K_AM_REGI_ADDR_DISP",
7 : "M68K_AM_AREGI_INDEX_8_BIT_DISP",
8 : "M68K_AM_AREGI_INDEX_BASE_DISP",
9 : "M68K_AM_MEMI_POST_INDEX",
10 : "M68K_AM_MEMI_PRE_INDEX",
11 : "M68K_AM_PCI_DISP",
12 : "M68K_AM_PCI_INDEX_8_BIT_DISP",
13 : "M68K_AM_PCI_INDEX_BASE_DISP",
14 : "M68K_AM_PC_MEMI_POST_INDEX",
15 : "M68K_AM_PC_MEMI_PRE_INDEX",
16 : "M68K_AM_ABSOLUTE_DATA_SHORT",
17 : "M68K_AM_ABSOLUTE_DATA_LONG",
18 : "M68K_AM_IMMEDIATE",
}
# Operand type for instruction's operands
map_op_str = {
0 : "M68K_OP_INVALID",
1 : "M68K_OP_REG",
2 : "M68K_OP_IMM",
3 : "M68K_OP_MEM",
4 : "M68K_OP_FP",
5 : "M68K_OP_REG_BITS",
6 : "M68K_OP_REG_PAIR",
}
def debug(insn, op):
if len(sys.argv) > 3:
print("id %d type %s address_mode %s" % (insn.id, map_op_str[op.type], map_address_mode_str[op.address_mode]))
def dump_ops(insn):
str = ''
mnemonic = insn.insn_name()
i = 0
while i < len(insn.operands):
if i > 0:
str += ','
op = insn.operands[i]
debug(insn, op)
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == M68K_INS_INVALID:
return format("0x%04x" % (op.imm))
if op.type == M68K_OP_REG:
str_op_reg = dump_op_ea(insn, op)
if str_op_reg == '' or op.address_mode == M68K_AM_REG_DIRECT_ADDR:
str_op_reg = dump_op_reg(insn, op.reg)
str += str_op_reg
if op.type == M68K_OP_IMM:
str_op_imm = format("#%u" % (op.imm))
if mnemonic in ["bkpt"]:
str_op_imm = format("%u" % (op.imm))
signed_insn = [ "move", "moveq", "cmp", "cmpi", "ori", "bclr", "pack", "unpk", "sub", "add" ]
if mnemonic in signed_insn:
if insn.op_size.size == 1 or mnemonic == "moveq":
str_op_imm = format("#%d" % s8(op.imm))
if insn.op_size.size == 2 or mnemonic == "pack":
str_op_imm = format("#%d" % s16(op.imm))
if insn.op_size.size == 4:
str_op_imm = format("#%d" % (op.imm))
dbxx_insn = [ "dbt", "dbf", "dbhi", "dbls", "dbcc", "dbcs", "dbne", "dbeq", "dbvc", "dbvs", "dbpl", "dbmi", "dbge", "dblt", "dbgt", "dble", "dbra" ]
if is_branch(insn) or mnemonic in dbxx_insn:
str_op_imm = format("0x%x" % (op.imm & 0xffffffff))
str += str_op_imm
if op.type == M68K_OP_MEM:
str_op_mem = dump_op_ea(insn, op)
if str_op_mem == '':
str_op_mem = format("0x%x" % (op.imm))
str += str_op_mem
if op.type in [ M68K_OP_REG_BITS, M68K_OP_REG_PAIR ]:
str += dump_op_ea(insn, op)
# if insn.address == 0x3127c:
# import pdb;pdb.set_trace()
# print("type %u am %u\n" % (op.type, op.address_mode))
i += 1
return str
def is_branch(insn):
mnemonic = insn.insn_name()
branch_insn = [ "bsr", "bra", "bhi", "bls", "bcc", "bcs", "bne", "beq", "bvc", "bvs", "bpl", "bmi", "bge", "blt", "bgt", "ble" ];
return mnemonic in branch_insn
def dump_mnemonic(insn):
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == M68K_INS_INVALID:
return ".short"
mnemonic = insn.insn_name()
ext = { 0: '', 1:'b', 2:'w', 4:'l' }
if is_branch(insn):
ext.update({ 1:'s', 2:'w', 4:'l' })
no_size = [ "pea", "lea", "bset", "bclr", "bchg", "btst", "nbcd", "abcd", "sbcd", "exg", "scc", "sls", "scs", "shi" ]
sxx_insn = [ "st", "sf", "shi", "sls", "scc", "scs", "sne", "seq", "svc", "svs", "spl", "smi", "sge", "slt", "sgt", "sle", "stop" ]
no_size += sxx_insn
no_size += [ "tas" ]
if mnemonic in no_size:
ext.update({ 0:'', 1:'', 2:'', 4:'' })
return mnemonic + ext[insn.op_size.size]
def print_insn_detail_np(insn):
# objdump format hack
if insn.size == 2:
space = ' ' * 11
if insn.size == 4:
space = ' ' * 6
if insn.size >= 6:
space = ' '
space_ops = ''
if len(insn.operands) > 0:
space_ops = ' '
print(" %x:\t%s%s\t%s%s%s" % (insn.address, dump_bytes(insn._raw.bytes, min(insn.size, 6)), space, dump_mnemonic(insn), space_ops, dump_ops(insn)))
if insn.size > 6:
delta = min(insn.size, 6)
print(" %x:\t%s " % (insn.address+delta, dump_bytes(insn._raw.bytes[delta:], min(insn.size-delta, 6))))
def print_objdump_dumpheader(filename='', address=0):
print(objdump_dumpheader_fmt % (filename, address))
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
filename = "/dev/stdin"
address = 0
if len(sys.argv) > 1:
filename = sys.argv[1]
if len(sys.argv) > 2:
address = int(sys.argv[2],16)
if len(sys.argv) > 3:
debug_mode = True
with open(filename, "rb") as f:
code = f.read()
try:
md = Cs(arch, mode)
md.detail = True
print_objdump_dumpheader(filename, address)
for insn in md.disasm(code, address):
print_insn_detail_np(insn)
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,905 @@
From 40ac7444e7f3679fad852564acca4f30f47fb52d Mon Sep 17 00:00:00 2001
From: fanfuqiang <feqin1023@gmail.com>
Date: Thu, 28 Feb 2019 01:37:55 +0800
Subject: [PATCH] update TableGen for generate RISCV port inc for CAPSTONE
---
llvm/lib/Target/RISCV/CMakeLists.txt | 2 +-
llvm/utils/TableGen/AsmWriterEmitter.cpp | 175 ++++++++++++++++--
.../utils/TableGen/FixedLenDecoderEmitter.cpp | 122 ++++++------
llvm/utils/TableGen/InstrInfoEmitter.cpp | 14 +-
llvm/utils/TableGen/RegisterInfoEmitter.cpp | 20 +-
llvm/utils/TableGen/TableGen.cpp | 6 +
6 files changed, 249 insertions(+), 90 deletions(-)
diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index 1821f4b01..603aa3f54 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -6,7 +6,7 @@ tablegen(LLVM RISCVGenCompressInstEmitter.inc -gen-compress-inst-emitter)
tablegen(LLVM RISCVGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM RISCVGenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM RISCVGenInstrInfo.inc -gen-instr-info)
-tablegen(LLVM RISCVGenMappingInsn.inc -gen-mapping-insn)
+tablegen(LLVM RISCVMappingInsn.inc -gen-mapping-insn)
tablegen(LLVM RISCVGenInsnNameMaps.inc -gen-insn-name-maps)
tablegen(LLVM RISCVGenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM RISCVGenMCPseudoLowering.inc -gen-pseudo-lowering)
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index c24dc6052..ac82573fe 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -270,12 +270,13 @@ static void UnescapeString(std::string &Str) {
/// implementation. Destroys all instances of AsmWriterInst information, by
/// clearing the Instructions vector.
void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
+#ifdef CAPSTONE
+ bool PassSubtarget = false;
+#else
Record *AsmWriter = Target.getAsmWriter();
-#ifndef CAPSTONE
StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
-#endif
bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
-
+#endif
O <<
"/// printInstruction - This method is automatically generated by tablegen\n"
"/// from the instruction set description.\n"
@@ -434,7 +435,11 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
}
// Emit the initial tab character.
-#ifndef CAPSTONE
+#ifdef CAPSTONE
+ O << "#ifndef CAPSTONE_DIET\n"
+ << " SStream_concat0(O, \"\\t\");\n"
+ << "#endif\n\n";
+#else
O << " O << \"\\t\";\n\n";
#endif
@@ -493,10 +498,10 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
<< ((1 << NumBits)-1) << ") {\n"
<< " default: "
#ifdef CAPSTONE
- << "assert(0);\n"
-#endif
+ << "assert(0 && \"Invalid command number.\");\n";
+#else
<< "llvm_unreachable(\"Invalid command number.\");\n";
-
+#endif
// Print out all the cases.
for (unsigned j = 0, e = Commands.size(); j != e; ++j) {
O << " case " << j << ":\n";
@@ -576,9 +581,7 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
}
StringTable.layout();
-#ifdef CAPSTONE
- O << "#ifndef CAPSTONE_DIET\n";
-#endif
+
O << " static const char AsmStrs" << AltName << "[] = {\n";
StringTable.emit(O, printChar);
O << " };\n\n";
@@ -625,7 +628,8 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
O << " "
<< "assert(RegNo && RegNo < " << (Registers.size()+1)
<< " && \"Invalid register number!\");\n"
- << "\n";
+ << "\n"
+ << "#ifndef CAPSTONE_DIET\n";
if (hasAltNames) {
for (const Record *R : AltNameIndices)
@@ -636,7 +640,7 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
if (hasAltNames) {
O << " switch(AltIdx) {\n"
#ifdef CAPSTONE
- << " default: assert(0);\n";
+ << " default: assert(0 && \"Invalid register alt name index!\");\n";
#else
<< " default: llvm_unreachable(\"Invalid register alt name index!\");\n";
#endif
@@ -886,7 +890,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
IAPrinter IAP(CGA.Result->getAsString(), FlatAliasAsmString);
+#ifndef CAPSTONE // Silence the compiler waring.
StringRef Namespace = Target.getName();
+#endif
std::vector<Record *> ReqFeatures;
if (PassSubtarget) {
// We only consider ReqFeatures predicates if PassSubtarget
@@ -902,7 +908,11 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
NumMIOps += ResultInstOpnd.MINumOperands;
std::string Cond;
+#ifdef CAPSTONE
+ Cond = std::string("MCInst_getNumOperands(MI) == ") + utostr(NumMIOps);
+#else
Cond = std::string("MI->getNumOperands() == ") + utostr(NumMIOps);
+#endif
IAP.addCond(Cond);
bool CantHandle = false;
@@ -926,9 +936,11 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
}
break;
}
-
+#ifdef CAPSTONE
+ std::string Op = "MCInst_getOperand(MI, " + utostr(MIOpNum) + ")";
+#else
std::string Op = "MI->getOperand(" + utostr(MIOpNum) + ")";
-
+#endif
const CodeGenInstAlias::ResultOperand &RO = CGA.ResultOperands[i];
switch (RO.Kind) {
@@ -954,19 +966,39 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (Rec->isSubClassOf("RegisterOperand"))
Rec = Rec->getValueAsDef("RegClass");
if (Rec->isSubClassOf("RegisterClass")) {
+#ifdef CAPSTONE
+ IAP.addCond("MCOperand_isReg(" + Op + ")");
+#else
IAP.addCond(Op + ".isReg()");
+#endif
if (!IAP.isOpMapped(ROName)) {
IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
Record *R = CGA.ResultOperands[i].getRecord();
if (R->isSubClassOf("RegisterOperand"))
R = R->getValueAsDef("RegClass");
+
+#ifdef CAPSTONE
+ Cond = std::string("MCRegisterClass_contains(") +
+ "MCRegisterInfo_getRegClass(" + "MRI, " +
+ Target.getName().str() + "_" + R->getName().str() + "RegClassID)" +
+ ", " +
+ "MCOperand_getReg(" + Op + "))";
+#else
Cond = std::string("MRI.getRegClass(") + Target.getName().str() +
"::" + R->getName().str() + "RegClassID).contains(" + Op +
".getReg())";
+#endif
+
} else {
+#ifdef CAPSTONE
+ Cond = std::string("MCOperand_getReg(") + Op + ") == " +
+ "MCOperand_getReg(MCInst_getOperand(MI, " +
+ utostr(IAP.getOpIndex(ROName)) + "))";
+#else
Cond = Op + ".getReg() == MI->getOperand(" +
utostr(IAP.getOpIndex(ROName)) + ").getReg()";
+#endif
}
} else {
// Assume all printable operands are desired for now. This can be
@@ -984,8 +1016,12 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
break; // No conditions on this operand at all
}
Cond = (Target.getName() + ClassName + "ValidateMCOperand(" + Op +
+ #ifdef CAPSTONE
+ ", " + utostr(Entry) + ")").str();
+ #else
", STI, " + utostr(Entry) + ")")
.str();
+ #endif
}
// for all subcases of ResultOperand::K_Record:
IAP.addCond(Cond);
@@ -994,9 +1030,15 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
case CodeGenInstAlias::ResultOperand::K_Imm: {
// Just because the alias has an immediate result, doesn't mean the
// MCInst will. An MCExpr could be present, for example.
+#ifdef CAPSTONE
+ IAP.addCond("MCOperand_isImm(" + Op + ")");
+ Cond = "MCOperand_getImm(" + Op + ") == " +
+ itostr(CGA.ResultOperands[i].getImm());
+#else
IAP.addCond(Op + ".isImm()");
-
Cond = Op + ".getImm() == " + itostr(CGA.ResultOperands[i].getImm());
+#endif
+
IAP.addCond(Cond);
break;
}
@@ -1008,8 +1050,14 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
break;
}
+#ifdef CAPSTONE
+ Cond = "MCOperand_getReg(" + Op + ") == " + Target.getName().str() +
+ "_" + CGA.ResultOperands[i].getRegister()->getName().str();
+#else
Cond = Op + ".getReg() == " + Target.getName().str() + "::" +
CGA.ResultOperands[i].getRegister()->getName().str();
+#endif
+
IAP.addCond(Cond);
break;
}
@@ -1019,6 +1067,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (CantHandle) continue;
+#ifndef CAPSTONE
for (auto I = ReqFeatures.cbegin(); I != ReqFeatures.cend(); I++) {
Record *R = *I;
StringRef AsmCondString = R->getValueAsString("AssemblerCondString");
@@ -1040,6 +1089,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
IAP.addCond(Cond);
}
}
+#endif
IAPrinterMap[Aliases.first].push_back(std::move(IAP));
}
@@ -1052,10 +1102,17 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
std::string Header;
raw_string_ostream HeaderO(Header);
+#ifdef CAPSTONE
+ HeaderO << "\nstatic bool printAliasInstr(MCInst *MI, SStream * OS, void *info)"
+ << "\n"
+ << "{\n"
+ << " MCRegisterInfo *MRI = (MCRegisterInfo *) info;\n";
+#else
HeaderO << "bool " << Target.getName() << ClassName
<< "::printAliasInstr(const MCInst"
<< " *MI, " << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
<< "raw_ostream &OS) {\n";
+#endif
std::string Cases;
raw_string_ostream CasesO(Cases);
@@ -1079,7 +1136,16 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (UniqueIAPs.empty()) continue;
+#ifdef CAPSTONE
+ // TODO: tricky.
+ const char* tmpCase = Entry.first.c_str();
+ assert (Entry.first.size() > 7);
+ CasesO.indent(2) << "case "
+ << "RISCV_" << std::string(tmpCase + 7) // strlen("RISCV::) == 7
+ << ":\n";
+#else
CasesO.indent(2) << "case " << Entry.first << ":\n";
+#endif
for (IAPrinter *IAP : UniqueIAPs) {
CasesO.indent(4);
@@ -1100,13 +1166,21 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (!MCOpPredicates.empty())
O << "static bool " << Target.getName() << ClassName
+#ifdef CAPSTONE
+ << "ValidateMCOperand(MCOperand *MCOp,\n"
+#else
<< "ValidateMCOperand(const MCOperand &MCOp,\n"
<< " const MCSubtargetInfo &STI,\n"
+#endif
<< " unsigned PredicateIndex);\n";
O << HeaderO.str();
O.indent(2) << "const char *AsmString;\n";
+#ifdef CAPSTONE
+ O.indent(2) << "switch (MCInst_getOpcode(MI)) {\n";
+#else
O.indent(2) << "switch (MI->getOpcode()) {\n";
+#endif
O.indent(2) << "default: return false;\n";
O << CasesO.str();
O.indent(2) << "}\n\n";
@@ -1114,14 +1188,27 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
// Code that prints the alias, replacing the operands with the ones from the
// MCInst.
O << " unsigned I = 0;\n";
+#ifdef CAPSTONE
+ O << " char *tmpString = cs_strdup(AsmString);\n";
+#endif
O << " while (AsmString[I] != ' ' && AsmString[I] != '\\t' &&\n";
O << " AsmString[I] != '$' && AsmString[I] != '\\0')\n";
O << " ++I;\n";
+#ifdef CAPSTONE
+ O << " tmpString[I] = 0;\n";
+ O << " SStream_concat0(OS, \"\\t\");\n";
+ O << " SStream_concat0(OS, tmpString);\n";
+ O << " SStream_concat0(OS, \"\\n\");\n";
+#else
O << " OS << '\\t' << StringRef(AsmString, I);\n";
-
+#endif
O << " if (AsmString[I] != '\\0') {\n";
O << " if (AsmString[I] == ' ' || AsmString[I] == '\\t') {\n";
+#ifdef CAPSTONE
+ O << " SStream_concat0(OS, \"\\t\");\n";
+#else
O << " OS << '\\t';\n";
+#endif
O << " ++I;\n";
O << " }\n";
O << " do {\n";
@@ -1131,15 +1218,28 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O << " ++I;\n";
O << " int OpIdx = AsmString[I++] - 1;\n";
O << " int PrintMethodIdx = AsmString[I++] - 1;\n";
+#ifdef CAPSTONE
+ O << " printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, OS);\n";
+#else
O << " printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, ";
O << (PassSubtarget ? "STI, " : "");
O << "OS);\n";
+#endif
O << " } else\n";
+
+#ifdef CAPSTONE
+ O << " printOperand(MI, (unsigned)(AsmString[I++]) - 1, OS);\n";
+#else
O << " printOperand(MI, unsigned(AsmString[I++]) - 1, ";
O << (PassSubtarget ? "STI, " : "");
O << "OS);\n";
+#endif
O << " } else {\n";
+#ifdef CAPSTONE
+ O << " SStream_concat0(OS, &AsmString[I++]);\n";
+#else
O << " OS << AsmString[I++];\n";
+#endif
O << " }\n";
O << " } while (AsmString[I] != '\\0');\n";
O << " }\n\n";
@@ -1150,25 +1250,48 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
//////////////////////////////
// Write out the printCustomAliasOperand function
//////////////////////////////
-
+#ifdef CAPSTONE
+ O << "static void "
+#else
O << "void " << Target.getName() << ClassName << "::"
+#endif
<< "printCustomAliasOperand(\n"
+#ifdef CAPSTONE
+ << " MCInst *MI, unsigned OpIdx,\n"
+#else
<< " const MCInst *MI, unsigned OpIdx,\n"
+#endif
<< " unsigned PrintMethodIdx,\n"
+#ifdef CAPSTONE
+ << " SStream *OS) {\n";
+#else
<< (PassSubtarget ? " const MCSubtargetInfo &STI,\n" : "")
<< " raw_ostream &OS) {\n";
+#endif
if (PrintMethods.empty())
+#ifdef CAPSTONE
+ O << " assert(0 && \"Unknown PrintMethod kind\");\n";
+#else
O << " llvm_unreachable(\"Unknown PrintMethod kind\");\n";
+#endif
else {
O << " switch (PrintMethodIdx) {\n"
<< " default:\n"
+#ifdef CAPSTONE
+ << " assert(0 && \"Unknown PrintMethod kind\");\n"
+#else
<< " llvm_unreachable(\"Unknown PrintMethod kind\");\n"
+#endif
<< " break;\n";
for (unsigned i = 0; i < PrintMethods.size(); ++i) {
O << " case " << i << ":\n"
<< " " << PrintMethods[i] << "(MI, OpIdx, "
+#ifdef CAPSTONE
+ << "OS);\n"
+#else
<< (PassSubtarget ? "STI, " : "") << "OS);\n"
+#endif
<< " break;\n";
}
O << " }\n";
@@ -1177,9 +1300,20 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (!MCOpPredicates.empty()) {
O << "static bool " << Target.getName() << ClassName
+#ifdef CAPSTONE
+ << "ValidateMCOperand(MCOperand *MCOp,\n"
+#else
<< "ValidateMCOperand(const MCOperand &MCOp,\n"
<< " const MCSubtargetInfo &STI,\n"
- << " unsigned PredicateIndex) {\n"
+#endif
+ << " unsigned PredicateIndex) {\n"
+#ifdef CAPSTONE
+ << " // TODO: need some constant untils operate the MCOperand,\n"
+ << " // but current CAPSTONE does't have.\n"
+ << " // So, We just return true\n"
+ << " return true;\n\n"
+ << "#if 0\n"
+#endif
<< " switch (PredicateIndex) {\n"
<< " default:\n"
<< " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
@@ -1195,6 +1329,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
llvm_unreachable("Unexpected MCOperandPredicate field!");
}
O << " }\n"
+#ifdef CAPSTONE
+ << "#endif\n"
+#endif
<< "}\n\n";
}
@@ -1228,7 +1365,7 @@ void AsmWriterEmitter::run(raw_ostream &O) {
#endif
EmitPrintInstruction(O);
EmitGetRegisterName(O);
-#ifndef CAPSTONE
+#ifdef CAPSTONE
EmitPrintAliasInstruction(O);
#endif
}
diff --git a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
index 3db428dfa..e1bfaa934 100644
--- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -946,13 +946,6 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
void FixedLenDecoderEmitter::
emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates,
unsigned Indentation) const {
-#ifdef CAPSTONE
- OS.indent(Indentation) << "static bool getbool(uint64_t b)\n";
- OS.indent(Indentation) << "{\n";
- OS.indent(Indentation) << "\treturn b != 0;\n";
- OS.indent(Indentation) << "}\n\n";
-#endif
-
// The predicate function is just a big switch statement based on the
// input predicate index.
OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, "
@@ -966,26 +959,25 @@ emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates,
OS.indent(Indentation) << "switch (Idx) {\n";
OS.indent(Indentation) << "default: "
#ifdef CAPSTONE
- << "assert(0);\n"
-#endif
+ << "assert(0 && \"Invalid index!\");\n";
+#else
<< "llvm_unreachable(\"Invalid index!\");\n";
+#endif
unsigned Index = 0;
for (const auto &Predicate : Predicates) {
OS.indent(Indentation) << "case " << Index++ << ":\n";
OS.indent(Indentation+2) << "return "
-#ifdef CAPSTONE
- << "getbool"
-#endif
- << "(" << Predicate << ");\n";
+ << Predicate << ";\n";
}
OS.indent(Indentation) << "}\n";
} else {
// No case statement to emit
OS.indent(Indentation)
#ifdef CAPSTONE
- << "assert(0);\n"
-#endif
+ << "assert(0 && \"Invalid index!\");\n";
+#else
<< "llvm_unreachable(\"Invalid index!\");\n";
+#endif
}
Indentation -= 2;
OS.indent(Indentation) << "}\n\n";
@@ -998,10 +990,11 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders,
// input decoder index.
#ifdef CAPSTONE
#define EDF_EOL " \\\n"
- OS.indent(Indentation) << "#define DecodeToMCInst(fname,fieldname, InsnType) \\\n";
- OS.indent(Indentation) << "static DecodeStatus fname(DecodeStatus S, unsigned Idx, InsnType insn, MCInst *MI, \\\n";
- OS.indent(Indentation) << " uint64_t Address, const void *Decoder) \\\n";
- OS.indent(Indentation) << "{ \\\n";
+ OS.indent(Indentation) << "#define DecodeToMCInst(fname, fieldname, InsnType) \\\n";
+ OS.indent(Indentation) << "static DecodeStatus fname(DecodeStatus S, unsigned Idx,"
+ << " InsnType insn, MCInst *MI, \\\n";
+ OS.indent(Indentation) << " uint64_t Address, const void *Decoder,\\\n";
+ OS.indent(Indentation) << " bool *DecodeComplete) {\\\n";
#else
#define EDF_EOL "\n"
OS.indent(Indentation) << "template<typename InsnType>\n";
@@ -1011,16 +1004,18 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders,
<< "Address, const void *Decoder, bool &DecodeComplete) {\n";
#endif
Indentation += 2;
-#ifndef CAPSTONE
+#ifdef CAPSTONE
+ OS.indent(Indentation) << "*DecodeComplete = true;\\\n";
+#else
OS.indent(Indentation) << "DecodeComplete = true;\n";
#endif
OS.indent(Indentation) << "InsnType tmp;" EDF_EOL;
OS.indent(Indentation) << "switch (Idx) {" EDF_EOL;
OS.indent(Indentation) << "default:"
-#ifndef CAPSTONE
- << " llvm_unreachable(\"Invalid index!\");\n";
+#ifdef CAPSTONE
+ << " assert(0 && \"Invalid index!\");\\\n";
#else
- << " assert(0);\\\n";
+ << " llvm_unreachable(\"Invalid index!\");\n";
#endif
unsigned Index = 0;
for (const auto &Decoder : Decoders) {
@@ -1174,8 +1169,27 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
if (Decoder != "") {
OpHasCompleteDecoder = OpInfo.HasCompleteDecoder;
+#ifdef CAPSTONE
+ std::string::size_type posOfLeftAngle = 0, posOfRightAngle = 0;
+ posOfLeftAngle = Decoder.find("<");
+ posOfRightAngle = Decoder.find(">");
+ std::string printDecoder = Decoder;
+ if (posOfLeftAngle != std::string::npos &&
+ posOfRightAngle != std::string::npos) {
+ printDecoder = Decoder.substr(0, posOfLeftAngle);
+ o.indent(Indentation) << Emitter->GuardPrefix
+ << printDecoder
+ << "(MI, tmp, Address, Decoder, "
+ << Decoder.substr(posOfLeftAngle+1, posOfRightAngle-posOfLeftAngle-1);
+ } else
+ o.indent(Indentation) << Emitter->GuardPrefix << Decoder
+ << "(MI, tmp, Address, Decoder";
+ // trick.
+ o << ")"
+#else
o.indent(Indentation) << Emitter->GuardPrefix << Decoder
<< "(MI, tmp, Address, Decoder)"
+#endif
<< Emitter->GuardPostfix
#ifdef CAPSTONE
<< " return MCDisassembler_Fail; \\\n";
@@ -1246,7 +1260,7 @@ static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
const std::string &PredicateNamespace) {
if (str[0] == '!')
#ifdef CAPSTONE
- o << "~(Bits & " << PredicateNamespace << "_"
+ o << "!(Bits & " << PredicateNamespace << "_"
<< str.slice(1,str.size()) << ")";
#else
o << "!Bits[" << PredicateNamespace << "::"
@@ -2331,15 +2345,13 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
#endif
#ifdef CAPSTONE
- OS << "static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], "
-
+ OS << "#define DecodeInstruction(fname, fieldname, decoder, InsnType) \\\n"
+ << "static DecodeStatus fname(const uint8_t DecodeTable[], "
"MCInst *MI,\\\n"
- << " InsnType insn, uint64_t "
+ << " InsnType insn, uint64_t "
"Address,\\\n"
- << " const void *DisAsm,\\\n"
- << " int feature) {\\\n"
- << " uint64_t Bits = getFeatureBits(feature); \\\n"
- //<< " const FeatureBitset& Bits = STI.getFeatureBits();\n"
+ << " const void *DisAsm, int feature) {\\\n"
+ << " uint64_t Bits = getFeatureBits(feature);\\\n"
<< "\\\n"
<< " const uint8_t *Ptr = DecodeTable;\\\n"
<< " uint32_t CurFieldValue = 0;\\\n"
@@ -2353,52 +2365,42 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " unsigned Start = *++Ptr;\\\n"
<< " unsigned Len = *++Ptr;\\\n"
<< " ++Ptr;\\\n"
- << " CurFieldValue = fieldFromInstruction(insn, Start, Len);\\\n"
+ << " CurFieldValue = fieldname(insn, Start, Len);\\\n"
<< " break;\\\n"
<< " }\\\n"
<< " case MCD_OPC_FilterValue: {\\\n"
- << " // Decode the field value.\\\n"
<< " unsigned Len;\\\n"
<< " InsnType Val = decodeULEB128(++Ptr, &Len);\\\n"
<< " Ptr += Len;\\\n"
- << " // NumToSkip is a plain 24-bit integer.\\\n"
<< " unsigned NumToSkip = *Ptr++;\\\n"
<< " NumToSkip |= (*Ptr++) << 8;\\\n"
<< " NumToSkip |= (*Ptr++) << 16;\\\n"
<< "\\\n"
- << " // Perform the filter operation.\\\n"
<< " if (Val != CurFieldValue)\\\n"
<< " Ptr += NumToSkip;\\\n"
- << "\\\n"
<< " break;\\\n"
<< " }\\\n"
<< " case MCD_OPC_CheckField: {\\\n"
<< " unsigned Start = *++Ptr;\\\n"
<< " unsigned Len = *++Ptr;\\\n"
- << " InsnType FieldValue = fieldFromInstruction(insn, Start, Len);\\\n"
- << " // Decode the field value.\\\n"
+ << " InsnType FieldValue = fieldname(insn, Start, Len);\\\n"
<< " uint32_t ExpectedValue = decodeULEB128(++Ptr, &Len);\\\n"
<< " Ptr += Len;\\\n"
- << " // NumToSkip is a plain 24-bit integer.\\\n"
<< " unsigned NumToSkip = *Ptr++;\\\n"
<< " NumToSkip |= (*Ptr++) << 8;\\\n"
<< " NumToSkip |= (*Ptr++) << 16;\\\n"
<< "\\\n"
- << " // If the actual and expected values don't match, skip.\\\n"
<< " if (ExpectedValue != FieldValue)\\\n"
<< " Ptr += NumToSkip;\\\n"
<< " break;\\\n"
<< " }\\\n"
<< " case MCD_OPC_CheckPredicate: {\\\n"
<< " unsigned Len;\\\n"
- << " // Decode the Predicate Index value.\\\n"
<< " unsigned PIdx = decodeULEB128(++Ptr, &Len);\\\n"
<< " Ptr += Len;\\\n"
- << " // NumToSkip is a plain 24-bit integer.\\\n"
<< " unsigned NumToSkip = *Ptr++;\\\n"
<< " NumToSkip |= (*Ptr++) << 8;\\\n"
<< " NumToSkip |= (*Ptr++) << 16;\\\n"
- << " // Check the predicate.\\\n"
<< " bool Pred;\\\n"
<< " if (!(Pred = checkDecoderPredicate(PIdx, Bits)))\\\n"
<< " Ptr += NumToSkip;\\\n"
@@ -2407,7 +2409,6 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " }\\\n"
<< " case MCD_OPC_Decode: {\\\n"
<< " unsigned Len;\\\n"
- << " // Decode the Opcode value.\\\n"
<< " unsigned Opc = decodeULEB128(++Ptr, &Len);\\\n"
<< " Ptr += Len;\\\n"
<< " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\\\n"
@@ -2416,47 +2417,39 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " MCInst_clear(MI);\\\n"
<< " MCInst_setOpcode(MI, Opc);\\\n"
<< " bool DecodeComplete;\\\n"
- << " S = decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm, "
- "DecodeComplete);\\\n"
+ << " S = decoder(S, DecodeIdx, insn, MI, Address, DisAsm, "
+ "&DecodeComplete);\\\n"
<< " assert(DecodeComplete);\\\n"
<< "\\\n"
<< " return S;\\\n"
<< " }\\\n"
<< " case MCD_OPC_TryDecode: {\\\n"
<< " unsigned Len;\\\n"
- << " // Decode the Opcode value.\\\n"
<< " unsigned Opc = decodeULEB128(++Ptr, &Len);\\\n"
<< " Ptr += Len;\\\n"
<< " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\\\n"
<< " Ptr += Len;\\\n"
- << " // NumToSkip is a plain 24-bit integer.\\\n"
<< " unsigned NumToSkip = *Ptr++;\\\n"
<< " NumToSkip |= (*Ptr++) << 8;\\\n"
<< " NumToSkip |= (*Ptr++) << 16;\\\n"
<< "\\\n"
- << " // Perform the decode operation.\\\n"
<< " MCInst TmpMI;\\\n"
<< " MCInst_setOpcode(&TmpMI, Opc);\\\n"
- << " bool DecodeComplete;\n"
- << " S = decodeToMCInst(S, DecodeIdx, insn, &TmpMI, Address, DisAsm, "
- "DecodeComplete);\\\n"
+ << " bool DecodeComplete;\\\n"
+ << " S = decoder(S, DecodeIdx, insn, &TmpMI, Address, DisAsm, "
+ "&DecodeComplete);\\\n"
+ << "\\\n"
<< " if (DecodeComplete) {\\\n"
- << " // Decoding complete.\\\n"
- << " MI = &TmpMI;\\\n"
+ << " *MI = TmpMI;\\\n"
<< " return S;\\\n"
<< " } else {\\\n"
<< " assert(S == MCDisassembler_Fail);\\\n"
- << " // If the decoding was incomplete, skip.\\\n"
<< " Ptr += NumToSkip;\\\n"
- << " // Reset decode status. This also drops a SoftFail status "
- "that could be\\\n"
- << " // set before the decode attempt.\\\n"
<< " S = MCDisassembler_Success;\\\n"
<< " }\\\n"
<< " break;\\\n"
<< " }\\\n"
<< " case MCD_OPC_SoftFail: {\\\n"
- << " // Decode the mask values.\\\n"
<< " unsigned Len;\\\n"
<< " InsnType PositiveMask = decodeULEB128(++Ptr, &Len);\\\n"
<< " Ptr += Len;\\\n"
@@ -2472,8 +2465,8 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " }\\\n"
<< " }\\\n"
<< " }\\\n"
- << " assert(0);\\\n"
-
+ << " assert(0 && \"bogosity detected in disassembler state "
+ "machine!\");\\\n"
#else
OS << "template<typename InsnType>\n"
<< "static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], "
@@ -2752,9 +2745,10 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
emitDecodeInstruction(OS);
#ifdef CAPSTONE
- OS << "FieldFromInstruction(fieldFromInstruction, uint64_t)\n";
- OS << "DecodeToMCInst(decodeToMCInst, fieldFromInstruction, uint64_t)\n";
- OS << "DecodeInstruction(decodeInstruction, fieldFromInstruction, decodeToMCInst, uint64_t)\n";
+ OS << "// For RISCV instruction is 32 bits.\n";
+ OS << "FieldFromInstruction(fieldFromInstruction, uint32_t)\n";
+ OS << "DecodeToMCInst(decodeToMCInst, fieldFromInstruction, uint32_t)\n";
+ OS << "DecodeInstruction(decodeInstruction, fieldFromInstruction, decodeToMCInst, uint32_t)\n";
#else
OS << "\n} // End llvm namespace\n";
#endif
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index 01605184f..e59dace24 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -769,6 +769,7 @@ void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {
#ifdef CAPSTONE
std::string GetPublicName(const CodeGenInstruction *Inst) {
std::string Name = Inst->TheDef->getName();
+#if 0
// Apply backward compatibility fixups.
// BRNLE -> BNLER.
if (Name.length() >= 5 && Name.substr(0, 5) == "BRAsm") {
@@ -785,7 +786,7 @@ std::string GetPublicName(const CodeGenInstruction *Inst) {
break;
}
Name = Name.substr(0, pos) + Name.substr(pos + 3);
- }
+ }f 0
// CPSDRxx -> CPSDR.
if (Name.length() >= 2) {
std::string Suffix2 = Name.substr(Name.length() - 2, 2);
@@ -794,7 +795,8 @@ std::string GetPublicName(const CodeGenInstruction *Inst) {
Name = Name.substr(0, Name.length() - 2);
}
}
- return "SYSZ_INS_" + Name;
+#endif
+ return "RISCV_INS_" + Name;
}
std::string GetRegisterName(Record *Reg) {
@@ -802,6 +804,7 @@ std::string GetRegisterName(Record *Reg) {
for (char& c : Name) {
c = toupper(c);
}
+#if 0
// R0L, R0D -> R0.
if (Name.length() >= 3 &&
Name[Name.length() - 3] == 'R' &&
@@ -809,7 +812,8 @@ std::string GetRegisterName(Record *Reg) {
Name[Name.length() - 1] == 'D')) {
Name = Name.substr(0, Name.length() - 3) + Name[Name.length() - 2];
}
- return "SYSZ_REG_" + Name;
+#endif
+ return "RISCV_REG_" + Name;
}
std::string GetGroupName(Record *Pred) {
@@ -817,10 +821,12 @@ std::string GetGroupName(Record *Pred) {
for (char& c : Name) {
c = toupper(c);
}
+#if 0
if (Name.length() >= 7 && Name.substr(0, 7) == "FEATURE") {
Name = Name.substr(7);
}
- return "SYSZ_GRP_" + Name;
+#endif
+ return "RISCV_GRP_" + Name;
}
void EmitMappingInsn(RecordKeeper &RK, raw_ostream &OS) {
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index 0df306680..cf9c352d7 100644
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -180,12 +180,20 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
#endif
}
-#ifndef CAPSTONE
const std::vector<Record*> &RegAltNameIndices = Target.getRegAltNameIndices();
// If the only definition is the default NoRegAltName, we don't need to
// emit anything.
if (RegAltNameIndices.size() > 1) {
OS << "\n// Register alternate name indices\n\n";
+#ifdef CAPSTONE
+ OS << "enum {\n";
+ for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i)
+ OS << " " << NAME_PREFIX RegAltNameIndices[i]->getName()
+ << ",\t// " << i << "\n";
+ OS << " " << NAME_PREFIX "NUM_TARGET_REG_ALT_NAMES = "
+ << RegAltNameIndices.size() << "\n";
+ OS << "};\n";
+#else
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
OS << "enum {\n";
@@ -195,11 +203,19 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "};\n";
if (!Namespace.empty())
OS << "} // end namespace " << Namespace << "\n\n";
+#endif
}
auto &SubRegIndices = Bank.getSubRegIndices();
if (!SubRegIndices.empty()) {
OS << "\n// Subregister indices\n\n";
+#ifdef CAPSTONE
+ OS << "enum {\n" << " " << NAME_PREFIX "NoSubRegister,\n";
+ unsigned i = 0;
+ for (const auto &Idx : SubRegIndices)
+ OS << " " << NAME_PREFIX Idx.getName() << ",\t// " << ++i << "\n";
+ OS << " " << NAME_PREFIX "NUM_TARGET_SUBREGS\n};\n";
+#else
std::string Namespace = SubRegIndices.front().getNamespace();
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
@@ -210,8 +226,8 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << " NUM_TARGET_SUBREGS\n};\n";
if (!Namespace.empty())
OS << "} // end namespace " << Namespace << "\n\n";
- }
#endif
+ }
#ifndef CAPSTONE
OS << "} // end namespace llvm\n\n";
diff --git a/llvm/utils/TableGen/TableGen.cpp b/llvm/utils/TableGen/TableGen.cpp
index 9e2a868be..7ec93c0e0 100644
--- a/llvm/utils/TableGen/TableGen.cpp
+++ b/llvm/utils/TableGen/TableGen.cpp
@@ -27,8 +27,10 @@ enum ActionType {
GenEmitter,
GenRegisterInfo,
GenInstrInfo,
+#ifdef CAPSTONE
GenMappingInsn,
GenInsnNameMaps,
+#endif
GenInstrDocs,
GenAsmWriter,
GenAsmMatcher,
@@ -76,10 +78,12 @@ namespace {
"Generate registers and register classes info"),
clEnumValN(GenInstrInfo, "gen-instr-info",
"Generate instruction descriptions"),
+#ifdef CAPSTONE
clEnumValN(GenMappingInsn, "gen-mapping-insn",
""),
clEnumValN(GenInsnNameMaps, "gen-insn-name-maps",
""),
+#endif
clEnumValN(GenInstrDocs, "gen-instr-docs",
"Generate instruction documentation"),
clEnumValN(GenCallingConv, "gen-callingconv",
@@ -160,12 +164,14 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenInstrInfo:
EmitInstrInfo(Records, OS);
break;
+#ifdef CAPSTONE
case GenMappingInsn:
EmitMappingInsn(Records, OS);
break;
case GenInsnNameMaps:
EmitInsnNameMaps(Records, OS);
break;
+#endif
case GenInstrDocs:
EmitInstrDocs(Records, OS);
break;
--
2.20.1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
From 5adfa13945a8eb1a104db57b29d27ceba0a2d948 Mon Sep 17 00:00:00 2001
From: fanfuqiang <feqin1023@gmail.com>
Date: Sun, 3 Mar 2019 23:16:27 +0800
Subject: [PATCH] fix output TAB for riscv capstone
---
llvm/utils/TableGen/AsmWriterEmitter.cpp | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index ac82573fe..21630f4ce 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -435,14 +435,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
}
// Emit the initial tab character.
-#ifdef CAPSTONE
- O << "#ifndef CAPSTONE_DIET\n"
- << " SStream_concat0(O, \"\\t\");\n"
- << "#endif\n\n";
-#else
- O << " O << \"\\t\";\n\n";
-#endif
-
+ //O << " O << \"\\t\";\n\n";
O << " // Emit the opcode for the instruction.\n";
O << BitsString;
--
2.20.1

View File

@@ -0,0 +1,32 @@
From 9028d6a0ce67296be48a3dae07d954ebe26942e1 Mon Sep 17 00:00:00 2001
From: fanfuqiang <feqin1023@gmail.com>
Date: Thu, 7 Mar 2019 00:08:08 +0800
Subject: [PATCH] fix riscv alias inst output useless newline
---
llvm/utils/TableGen/AsmWriterEmitter.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index 21630f4ce..9db5f7f54 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -1191,14 +1191,13 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O << " tmpString[I] = 0;\n";
O << " SStream_concat0(OS, \"\\t\");\n";
O << " SStream_concat0(OS, tmpString);\n";
- O << " SStream_concat0(OS, \"\\n\");\n";
#else
O << " OS << '\\t' << StringRef(AsmString, I);\n";
#endif
O << " if (AsmString[I] != '\\0') {\n";
O << " if (AsmString[I] == ' ' || AsmString[I] == '\\t') {\n";
#ifdef CAPSTONE
- O << " SStream_concat0(OS, \"\\t\");\n";
+ O << " SStream_concat0(OS, \" \");\n";
#else
O << " OS << '\\t';\n";
#endif
--
2.20.1

View File

@@ -0,0 +1,24 @@
From 6830f128011a19e77e8c131cdfcf2f87fb78e316 Mon Sep 17 00:00:00 2001
From: fanfuqiang <feqin1023@gmail.com>
Date: Thu, 7 Mar 2019 00:31:51 +0800
Subject: [PATCH] fix riscv inst output more formal
---
llvm/utils/TableGen/AsmWriterEmitter.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index 9db5f7f54..fff9f7677 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -1189,7 +1189,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O << " ++I;\n";
#ifdef CAPSTONE
O << " tmpString[I] = 0;\n";
- O << " SStream_concat0(OS, \"\\t\");\n";
O << " SStream_concat0(OS, tmpString);\n";
#else
O << " OS << '\\t' << StringRef(AsmString, I);\n";
--
2.20.1

View File

@@ -0,0 +1,38 @@
From b1a7abb285aaa1436d563a30f65813513a512850 Mon Sep 17 00:00:00 2001
From: fanfuqiang <feqin1023@gmail.com>
Date: Fri, 8 Mar 2019 11:09:54 +0800
Subject: [PATCH] fix riscv asmwriter variable declaration place
---
llvm/utils/TableGen/AsmWriterEmitter.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index fff9f7677..90540000f 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -1170,6 +1170,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O << HeaderO.str();
O.indent(2) << "const char *AsmString;\n";
#ifdef CAPSTONE
+ O << " unsigned I = 0;\n";
+ O << " char *tmpString;\n";
O.indent(2) << "switch (MCInst_getOpcode(MI)) {\n";
#else
O.indent(2) << "switch (MI->getOpcode()) {\n";
@@ -1180,9 +1182,11 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
// Code that prints the alias, replacing the operands with the ones from the
// MCInst.
+#ifndef CAPSTONE
O << " unsigned I = 0;\n";
+#endif
#ifdef CAPSTONE
- O << " char *tmpString = cs_strdup(AsmString);\n";
+ O << " tmpString = cs_strdup(AsmString);\n";
#endif
O << " while (AsmString[I] != ' ' && AsmString[I] != '\\t' &&\n";
O << " AsmString[I] != '$' && AsmString[I] != '\\0')\n";
--
2.20.1

View File

@@ -0,0 +1,24 @@
From 533ce514a7365932e9919be6e63c605d7edf655c Mon Sep 17 00:00:00 2001
From: fanfuqiang <feqin1023@gmail.com>
Date: Wed, 20 Mar 2019 12:26:19 +0800
Subject: [PATCH] fix riscvgenasmwiter.inc memory leak
---
llvm/utils/TableGen/AsmWriterEmitter.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index 90540000f..bc32a494b 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -1194,6 +1194,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
#ifdef CAPSTONE
O << " tmpString[I] = 0;\n";
O << " SStream_concat0(OS, tmpString);\n";
+ O << " cs_mem_free(tmpString);\n";
#else
O << " OS << '\\t' << StringRef(AsmString, I);\n";
#endif
--
2.20.1

View File

@@ -0,0 +1,53 @@
From 93d420c95c3cf1d6a369be1ca7f2333fdf670283 Mon Sep 17 00:00:00 2001
From: fanfuqiang <feqin1023@gmail.com>
Date: Wed, 20 Mar 2019 15:15:01 +0800
Subject: [PATCH] using static array contain temp string for riscv asmwriter
---
llvm/utils/TableGen/AsmWriterEmitter.cpp | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index bc32a494b..8e2bd70c6 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -1171,7 +1171,10 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O.indent(2) << "const char *AsmString;\n";
#ifdef CAPSTONE
O << " unsigned I = 0;\n";
- O << " char *tmpString;\n";
+ O << "#define ASMSTRING_CONTAIN_SIZE 64\n";
+ O << " unsigned AsmStringLen = 0;\n";
+ O << " char tmpString_[ASMSTRING_CONTAIN_SIZE];\n";
+ O << " char *tmpString = tmpString_;\n";
O.indent(2) << "switch (MCInst_getOpcode(MI)) {\n";
#else
O.indent(2) << "switch (MI->getOpcode()) {\n";
@@ -1186,7 +1189,11 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O << " unsigned I = 0;\n";
#endif
#ifdef CAPSTONE
- O << " tmpString = cs_strdup(AsmString);\n";
+ O << " AsmStringLen = strlen(AsmString);\n";
+ O << " if (ASMSTRING_CONTAIN_SIZE - 1 < AsmStringLen)\n";
+ O << " tmpString = cs_strdup(AsmString);\n";
+ O << " else\n";
+ O << " tmpString = memcpy(tmpString, AsmString, 1 + AsmStringLen);\n\n";
#endif
O << " while (AsmString[I] != ' ' && AsmString[I] != '\\t' &&\n";
O << " AsmString[I] != '$' && AsmString[I] != '\\0')\n";
@@ -1194,7 +1201,10 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
#ifdef CAPSTONE
O << " tmpString[I] = 0;\n";
O << " SStream_concat0(OS, tmpString);\n";
- O << " cs_mem_free(tmpString);\n";
+ O << " if (ASMSTRING_CONTAIN_SIZE - 1 < AsmStringLen)\n";
+ O << " /* Free the possible cs_strdup() memory. PR#1424. */\n";
+ O << " cs_mem_free(tmpString);\n";
+ O << "#undef ASMSTRING_CONTAIN_SIZE\n\n";
#else
O << " OS << '\\t' << StringRef(AsmString, I);\n";
#endif
--
2.20.1

View File

@@ -0,0 +1,61 @@
# How to update RISCV tables.
* Checkout LLVM. Patches are tested on commit `b81d715c`.
```
git clone https://github.com/llvm/llvm-project.git
git checkout b81d715c
```
* Apply patches from the current directory.
* Run tablegen.
```
cd $LLVM
mkdir build
cd build
cmake -DCMAKE_CXX_FLAGS=-DCAPSTONE -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="RISCV" ..
make RISCVCommonTableGen
```
* Copy `.inc` files.
```
cp arch/RISCV/RISCVGenInsnNameMaps.inc \
arch/RISCV/RISCVGenInsnNameMaps.inc.old
for inc in $(cd arch/RISCV && ls *.inc); do
cp $LLVM/build/lib/Target/RISCV/$inc arch/RISCV/
done
```
* Fixup `RISCVGenInsnNameMaps.inc`.
```
comm -1 -3 \
<(grep RISCV_INS_ <arch/RISCV/RISCVGenInsnNameMaps.inc.old \
| sort -u) \
<(grep RISCV_INS_ <arch/RISCV/RISCVGenInsnNameMaps.inc \
| sort -u) \
>arch/RISCV/RISCVGenInsnNameMaps.inc.new
cat arch/RISCV/RISCVGenInsnNameMaps.inc.old \
arch/RISCV/RISCVGenInsnNameMaps.inc.new \
>arch/RISCV/RISCVGenInsnNameMaps.inc
```
* Add new groups, insns, registers and formats.
* `include/capstone/RISCV.h`
* `enum RISCV_insn`:
```
comm -1 -3 \
<(perl -ne 'if (/(RISCV_INS_.+),/) { print "\t$1,\n" }' \
<include/capstone/RISCV.h | sort -u) \
<(perl -ne 'if (/(RISCV_INS_.+),/) { print "\t$1,\n" }' \
<arch/RISCV/RISCVMappingInsn.inc | sort -u)
```
* `enum RISCV_insn_group`:
```
perl -ne 'if (/(\{.RISCV_GRP_.*?\}),/) { print "\t$1,\n"; }' < \
arch/RISCV/RISCVMappingInsn.inc | sort -u
```
* `arch/RISCV/RISCVDisassembler.c`
* `arch/RISCV/RISCVInstPrinter.c`
* `arch/RISCV/RISCVMCTargetDesc.c`
* `arch/RISCV/RISCVMCTargetDesc.h`
* `arch/RISCV/RISCVMapping.c`
* `enum group_name_maps`:
```
perl -ne 'if (/(RISCV_GRP_(.*?)),/) { print "\t{ $1, \"" . lc($2) . "\" },\n"; }' \
arch/RISCV/RISCVMappingInsn.inc | sort -u
```

View File

@@ -0,0 +1,338 @@
From 5d631cb16e7ba5dd0380ff1ee9dda192b1cdad18 Mon Sep 17 00:00:00 2001
From: mephi42 <mephi42@gmail.com>
Date: Tue, 7 Aug 2018 17:02:40 +0200
Subject: [PATCH 1/7] capstone: generate *GenRegisterInfo.inc
---
utils/TableGen/RegisterInfoEmitter.cpp | 130 ++++++++++++++++++++++---
1 file changed, 115 insertions(+), 15 deletions(-)
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index 49016cca799..6ebb7148b1b 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -99,6 +99,12 @@ private:
} // end anonymous namespace
+#ifdef CAPSTONE
+#define NAME_PREFIX Target.getName() << "_" <<
+#else
+#define NAME_PREFIX
+#endif
+
// runEnums - Print out enum values for all of the registers.
void RegisterInfoEmitter::runEnums(raw_ostream &OS,
CodeGenTarget &Target, CodeGenRegBank &Bank) {
@@ -107,13 +113,22 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
// Register enums are stored as uint16_t in the tables. Make sure we'll fit.
assert(Registers.size() <= 0xffff && "Too many regs to fit in tables");
+#ifndef CAPSTONE
StringRef Namespace = Registers.front().TheDef->getValueAsString("Namespace");
+#endif
emitSourceFileHeader("Target Register Enum Values", OS);
+#ifdef CAPSTONE
+ OS << "/* Capstone Disassembly Engine */\n"
+ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
+ "\n";
+#endif
+
OS << "\n#ifdef GET_REGINFO_ENUM\n";
OS << "#undef GET_REGINFO_ENUM\n\n";
+#ifndef CAPSTONE
OS << "namespace llvm {\n\n";
OS << "class MCRegisterClass;\n"
@@ -122,16 +137,20 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
- OS << "enum {\n NoRegister,\n";
+#endif
+
+ OS << "enum {\n " << NAME_PREFIX "NoRegister,\n";
for (const auto &Reg : Registers)
- OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n";
+ OS << " " << NAME_PREFIX Reg.getName() << " = " << Reg.EnumValue << ",\n";
assert(Registers.size() == Registers.back().EnumValue &&
"Register enum value mismatch!");
- OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
+ OS << " " << NAME_PREFIX "NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
OS << "};\n";
+#ifndef CAPSTONE
if (!Namespace.empty())
OS << "} // end namespace " << Namespace << "\n";
+#endif
const auto &RegisterClasses = Bank.getRegClasses();
if (!RegisterClasses.empty()) {
@@ -140,18 +159,29 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
assert(RegisterClasses.size() <= 0xffff &&
"Too many register classes to fit in tables");
- OS << "\n// Register classes\n\n";
+ OS << "\n// Register classes\n";
+#ifndef CAPSTONE
+ OS << "\n";
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
+#endif
OS << "enum {\n";
for (const auto &RC : RegisterClasses)
- OS << " " << RC.getName() << "RegClassID"
+ OS << " " << NAME_PREFIX RC.getName() << "RegClassID"
<< " = " << RC.EnumValue << ",\n";
- OS << "\n };\n";
+#ifdef CAPSTONE
+ OS
+#else
+ OS << "\n "
+#endif
+ << "};\n";
+#ifndef CAPSTONE
if (!Namespace.empty())
OS << "} // end namespace " << Namespace << "\n\n";
+#endif
}
+#ifndef CAPSTONE
const std::vector<Record*> &RegAltNameIndices = Target.getRegAltNameIndices();
// If the only definition is the default NoRegAltName, we don't need to
// emit anything.
@@ -182,8 +212,11 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
if (!Namespace.empty())
OS << "} // end namespace " << Namespace << "\n\n";
}
+#endif
+#ifndef CAPSTONE
OS << "} // end namespace llvm\n\n";
+#endif
OS << "#endif // GET_REGINFO_ENUM\n\n";
}
@@ -830,7 +863,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
const auto &Regs = RegBank.getRegisters();
+#ifndef CAPSTONE
auto &SubRegIndices = RegBank.getSubRegIndices();
+#endif
// The lists of sub-registers and super-registers go in the same array. That
// allows us to share suffixes.
typedef std::vector<const CodeGenRegister*> RegVec;
@@ -922,25 +957,40 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
LaneMaskSeqs.layout();
SubRegIdxSeqs.layout();
+#ifndef CAPSTONE
OS << "namespace llvm {\n\n";
+#endif
const std::string &TargetName = Target.getName();
// Emit the shared table of differential lists.
- OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[] = {\n";
+#ifdef CAPSTONE
+ OS << "static"
+#else
+ OS << "extern"
+#endif
+ << " const MCPhysReg " << TargetName << "RegDiffLists[] = {\n";
DiffSeqs.emit(OS, printDiff16);
OS << "};\n\n";
+#ifndef CAPSTONE
// Emit the shared table of regunit lane mask sequences.
OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[] = {\n";
LaneMaskSeqs.emit(OS, printMask, "LaneBitmask::getAll()");
OS << "};\n\n";
+#endif
// Emit the table of sub-register indexes.
- OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n";
+#ifdef CAPSTONE
+ OS << "static"
+#else
+ OS << "extern"
+#endif
+ << " const uint16_t " << TargetName << "SubRegIdxLists[] = {\n";
SubRegIdxSeqs.emit(OS, printSubRegIndex);
OS << "};\n\n";
+#ifndef CAPSTONE
// Emit the table of sub-register index sizes.
OS << "extern const MCRegisterInfo::SubRegCoveredBits "
<< TargetName << "SubRegIdxRanges[] = {\n";
@@ -950,14 +1000,22 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
<< Idx.getName() << "\n";
}
OS << "};\n\n";
+#endif
// Emit the string table.
RegStrings.layout();
+#ifndef CAPSTONE
OS << "extern const char " << TargetName << "RegStrings[] = {\n";
RegStrings.emit(OS, printChar);
OS << "};\n\n";
+#endif
- OS << "extern const MCRegisterDesc " << TargetName
+#ifdef CAPSTONE
+ OS << "static"
+#else
+ OS << "extern"
+#endif
+ << " const MCRegisterDesc " << TargetName
<< "RegDesc[] = { // Descriptors\n";
OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n";
@@ -973,6 +1031,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << "};\n\n"; // End of register descriptors...
+#ifndef CAPSTONE
// Emit the table of register unit roots. Each regunit has one or two root
// registers.
OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n";
@@ -986,11 +1045,14 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << " },\n";
}
OS << "};\n\n";
+#endif
const auto &RegisterClasses = RegBank.getRegClasses();
// Loop over all of the register classes... emitting each one.
+#ifndef CAPSTONE
OS << "namespace { // Register classes...\n";
+#endif
SequenceToOffsetTable<std::string> RegClassStrings;
@@ -1005,15 +1067,28 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
// Emit the register list now.
OS << " // " << Name << " Register Class...\n"
- << " const MCPhysReg " << Name
+ << " "
+#ifdef CAPSTONE
+ << "static "
+#endif
+ << "const MCPhysReg " << Name
<< "[] = {\n ";
for (Record *Reg : Order) {
- OS << getQualifiedName(Reg) << ", ";
+#ifdef CAPSTONE
+ OS << NAME_PREFIX Reg->getName()
+#else
+ OS << getQualifiedName(Reg)
+#endif
+ << ", ";
}
OS << "\n };\n\n";
OS << " // " << Name << " Bit set.\n"
- << " const uint8_t " << Name
+ << " "
+#ifdef CAPSTONE
+ << "static "
+#endif
+ << "const uint8_t " << Name
<< "Bits[] = {\n ";
BitVectorEmitter BVE;
for (Record *Reg : Order) {
@@ -1023,14 +1098,23 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "\n };\n\n";
}
+#ifndef CAPSTONE
OS << "} // end anonymous namespace\n\n";
+#endif
RegClassStrings.layout();
+#ifndef CAPSTONE
OS << "extern const char " << TargetName << "RegClassStrings[] = {\n";
RegClassStrings.emit(OS, printChar);
OS << "};\n\n";
+#endif
- OS << "extern const MCRegisterClass " << TargetName
+#ifdef CAPSTONE
+ OS << "static"
+#else
+ OS << "extern"
+#endif
+ << " const MCRegisterClass " << TargetName
<< "MCRegisterClasses[] = {\n";
for (const auto &RC : RegisterClasses) {
@@ -1041,7 +1125,12 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, "
<< RegClassStrings.get(RC.getName()) << ", "
<< RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), "
- << RC.getQualifiedName() + "RegClassID" << ", "
+#ifdef CAPSTONE
+ << NAME_PREFIX RC.getName()
+#else
+ << RC.getQualifiedName()
+#endif
+ << "RegClassID" << ", "
<< RegSize/8 << ", "
<< RC.CopyCost << ", "
<< ( RC.Allocatable ? "true" : "false" ) << " },\n";
@@ -1049,6 +1138,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "};\n\n";
+#ifndef CAPSTONE
EmitRegMappingTables(OS, Regs, false);
// Emit Reg encoding table
@@ -1067,7 +1157,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << " " << Value << ",\n";
}
OS << "};\n"; // End of HW encoding table
+#endif
+#ifndef CAPSTONE
// MCRegisterInfo initialization routine.
OS << "static inline void Init" << TargetName
<< "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, "
@@ -1088,7 +1180,12 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "}\n\n";
OS << "} // end namespace llvm\n\n";
- OS << "#endif // GET_REGINFO_MC_DESC\n\n";
+#endif
+ OS << "#endif // GET_REGINFO_MC_DESC\n"
+#ifndef CAPSTONE
+ << "\n"
+#endif
+ ;
}
void
@@ -1568,10 +1665,13 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
void RegisterInfoEmitter::run(raw_ostream &OS) {
CodeGenRegBank &RegBank = Target.getRegBank();
+
runEnums(OS, Target, RegBank);
runMCDesc(OS, Target, RegBank);
+#ifndef CAPSTONE
runTargetHeader(OS, Target, RegBank);
runTargetDesc(OS, Target, RegBank);
+#endif
if (RegisterInfoDebug)
debugDump(errs());
--
2.19.1

View File

@@ -0,0 +1,86 @@
From 46ca491e1bbbc9ace2a91fe6a7b112c83b9b88cc Mon Sep 17 00:00:00 2001
From: mephi42 <mephi42@gmail.com>
Date: Tue, 7 Aug 2018 17:42:59 +0200
Subject: [PATCH 2/7] capstone: generate *GenSubtargetInfo.inc
---
utils/TableGen/SubtargetEmitter.cpp | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index c5da8d8142f..98ab3240472 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -147,7 +147,9 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS) {
if (N > MAX_SUBTARGET_FEATURES)
PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
+#ifndef CAPSTONE
OS << "namespace " << Target << " {\n";
+#endif
// Open enumeration.
OS << "enum {\n";
@@ -158,12 +160,22 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS) {
Record *Def = DefList[i];
// Get and emit name
- OS << " " << Def->getName() << " = " << i << ",\n";
+ OS << " "
+#ifdef CAPSTONE
+ << Target << "_"
+#endif
+ << Def->getName() << " = "
+#ifdef CAPSTONE
+ << "1ULL << "
+#endif
+ << i << ",\n";
}
// Close enumeration and namespace
OS << "};\n";
+#ifndef CAPSTONE
OS << "} // end namespace " << Target << "\n";
+#endif
}
//
@@ -1709,14 +1721,27 @@ void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) {
void SubtargetEmitter::run(raw_ostream &OS) {
emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
+#ifdef CAPSTONE
+ OS << "/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n"
+ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
+ "\n";
+#endif
+
OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
OS << "#undef GET_SUBTARGETINFO_ENUM\n\n";
+#ifndef CAPSTONE
OS << "namespace llvm {\n";
+#endif
Enumeration(OS);
+#ifdef CAPSTONE
+ OS << "\n";
+#else
OS << "} // end namespace llvm\n\n";
+#endif
OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
+#ifndef CAPSTONE
OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
OS << "#undef GET_SUBTARGETINFO_MC_DESC\n\n";
@@ -1857,6 +1882,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
+#endif
}
namespace llvm {
--
2.19.1

View File

@@ -0,0 +1,130 @@
From a73fe8ac18d3ca81fa7a8d8c404cd7e0faf92ddc Mon Sep 17 00:00:00 2001
From: mephi42 <mephi42@gmail.com>
Date: Tue, 7 Aug 2018 17:59:43 +0200
Subject: [PATCH 3/7] capstone: generate *GenInstrInfo.inc
---
utils/TableGen/InstrInfoEmitter.cpp | 49 ++++++++++++++++++++++++++---
1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 0aff1aa6f94..2f3a2729262 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -92,6 +92,7 @@ private:
} // end anonymous namespace
+#ifndef CAPSTONE
static void PrintDefList(const std::vector<Record*> &Uses,
unsigned Num, raw_ostream &OS) {
OS << "static const MCPhysReg ImplicitList" << Num << "[] = { ";
@@ -99,6 +100,7 @@ static void PrintDefList(const std::vector<Record*> &Uses,
OS << getQualifiedName(U) << ", ";
OS << "0 };\n";
}
+#endif
//===----------------------------------------------------------------------===//
// Operand Info Emission.
@@ -426,8 +428,17 @@ void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS) {
// run - Emit the main instruction description records for the target...
void InstrInfoEmitter::run(raw_ostream &OS) {
emitSourceFileHeader("Target Instruction Enum Values and Descriptors", OS);
+
+#ifdef CAPSTONE
+ OS << "/* Capstone Disassembly Engine */\n"
+ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
+ "\n"
+ "\n";
+#endif
+
emitEnums(OS);
+#ifndef CAPSTONE
OS << "#ifdef GET_INSTRINFO_MC_DESC\n";
OS << "#undef GET_INSTRINFO_MC_DESC\n";
@@ -545,6 +556,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
emitOperandTypesEnum(OS, Target);
emitMCIIHelperMethods(OS);
+#endif
}
void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
@@ -659,7 +671,9 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
OS << "#ifdef GET_INSTRINFO_ENUM\n";
OS << "#undef GET_INSTRINFO_ENUM\n";
+#ifndef CAPSTONE
OS << "namespace llvm {\n\n";
+#endif
CodeGenTarget Target(Records);
@@ -669,17 +683,39 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
if (Namespace.empty())
PrintFatalError("No instructions defined!");
+#ifndef CAPSTONE
OS << "namespace " << Namespace << " {\n";
- OS << " enum {\n";
+#endif
+#ifdef CAPSTONE
+ OS << "\n"
+#else
+ OS << " "
+#endif
+ << "enum {\n";
unsigned Num = 0;
for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue())
- OS << " " << Inst->TheDef->getName() << "\t= " << Num++ << ",\n";
- OS << " INSTRUCTION_LIST_END = " << Num << "\n";
+ OS << " "
+#ifdef CAPSTONE
+ << Target.getName() << "_"
+#endif
+ << Inst->TheDef->getName() << "\t= " << Num++ << ",\n";
+ OS << " "
+#ifdef CAPSTONE
+ << Target.getName() << "_"
+#endif
+ << "INSTRUCTION_LIST_END = " << Num << "\n";
OS << " };\n\n";
+#ifndef CAPSTONE
OS << "} // end " << Namespace << " namespace\n";
OS << "} // end llvm namespace\n";
- OS << "#endif // GET_INSTRINFO_ENUM\n\n";
-
+#endif
+ OS << "#endif // GET_INSTRINFO_ENUM\n"
+#ifndef CAPSTONE
+ << "\n"
+#endif
+ ;
+
+#ifndef CAPSTONE
OS << "#ifdef GET_INSTRINFO_SCHED_ENUM\n";
OS << "#undef GET_INSTRINFO_SCHED_ENUM\n";
OS << "namespace llvm {\n\n";
@@ -696,13 +732,16 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
OS << "} // end llvm namespace\n";
OS << "#endif // GET_INSTRINFO_SCHED_ENUM\n\n";
+#endif
}
namespace llvm {
void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {
InstrInfoEmitter(RK).run(OS);
+#ifndef CAPSTONE
EmitMapTable(RK, OS);
+#endif
}
} // end llvm namespace
--
2.19.1

View File

@@ -0,0 +1,472 @@
From 29da4c6929679b8ac4019767ab4ebcd83c9894b4 Mon Sep 17 00:00:00 2001
From: mephi42 <mephi42@gmail.com>
Date: Tue, 7 Aug 2018 18:20:17 +0200
Subject: [PATCH 4/7] capstone: generate *GenDisassemblerTables.inc
---
utils/TableGen/DisassemblerEmitter.cpp | 12 +-
utils/TableGen/FixedLenDecoderEmitter.cpp | 248 ++++++++++++++++++++--
2 files changed, 239 insertions(+), 21 deletions(-)
diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp
index b99a0a973a2..2ac6d89645c 100644
--- a/utils/TableGen/DisassemblerEmitter.cpp
+++ b/utils/TableGen/DisassemblerEmitter.cpp
@@ -106,6 +106,11 @@ extern void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
CodeGenTarget Target(Records);
emitSourceFileHeader(" * " + Target.getName().str() + " Disassembler", OS);
+#ifdef CAPSTONE
+ OS << "/* Capstone Disassembly Engine */\n"
+ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
+ "\n";
+#endif
// X86 uses a custom disassembler.
if (Target.getName() == "X86") {
@@ -150,7 +155,12 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
}
EmitFixedLenDecoder(Records, OS, Target.getName(),
- "if (", " == MCDisassembler::Fail)",
+ "if (",
+#ifdef CAPSTONE
+ " == MCDisassembler_Fail)",
+#else
+ " == MCDisassembler::Fail)",
+#endif
"MCDisassembler::Success", "MCDisassembler::Fail", "");
}
diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
index fcecc764d44..36845d960d8 100644
--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -730,7 +730,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
++I;
unsigned Start = *I++;
unsigned Len = *I++;
- OS.indent(Indentation) << "MCD::OPC_ExtractField, " << Start << ", "
+ OS.indent(Indentation)
+#ifdef CAPSTONE
+ << "MCD_OPC_ExtractField"
+#else
+ << "MCD::OPC_ExtractField"
+#endif
+ << ", " << Start << ", "
<< Len << ", // Inst{";
if (Len > 1)
OS << (Start + Len - 1) << "-";
@@ -739,7 +745,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
}
case MCD::OPC_FilterValue: {
++I;
- OS.indent(Indentation) << "MCD::OPC_FilterValue, ";
+ OS.indent(Indentation)
+#ifdef CAPSTONE
+ << "MCD_OPC_FilterValue"
+#else
+ << "MCD::OPC_FilterValue"
+#endif
+ << ", ";
// The filter value is ULEB128 encoded.
while (*I >= 128)
OS << (unsigned)*I++ << ", ";
@@ -759,7 +771,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
++I;
unsigned Start = *I++;
unsigned Len = *I++;
- OS.indent(Indentation) << "MCD::OPC_CheckField, " << Start << ", "
+ OS.indent(Indentation)
+#ifdef CAPSTONE
+ << "MCD_OPC_CheckField"
+#else
+ << "MCD::OPC_CheckField"
+#endif
+ << ", " << Start << ", "
<< Len << ", ";// << Val << ", " << NumToSkip << ",\n";
// ULEB128 encoded field value.
for (; *I >= 128; ++I)
@@ -777,7 +795,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
}
case MCD::OPC_CheckPredicate: {
++I;
- OS.indent(Indentation) << "MCD::OPC_CheckPredicate, ";
+ OS.indent(Indentation)
+#ifdef CAPSTONE
+ << "MCD_OPC_CheckPredicate"
+#else
+ << "MCD::OPC_CheckPredicate"
+#endif
+ << ", ";
for (; *I >= 128; ++I)
OS << (unsigned)*I << ", ";
OS << (unsigned)*I++ << ", ";
@@ -803,7 +827,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
&& "ULEB128 value too large!");
// Decode the Opcode value.
unsigned Opc = decodeULEB128(Buffer);
- OS.indent(Indentation) << "MCD::OPC_" << (IsTry ? "Try" : "")
+ OS.indent(Indentation)
+#ifdef CAPSTONE
+ << "MCD_OPC_"
+#else
+ << "MCD::OPC_"
+#endif
+ << (IsTry ? "Try" : "")
<< "Decode, ";
for (p = Buffer; *p >= 128; ++p)
OS << (unsigned)*p << ", ";
@@ -837,7 +867,12 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
}
case MCD::OPC_SoftFail: {
++I;
- OS.indent(Indentation) << "MCD::OPC_SoftFail";
+ OS.indent(Indentation)
+#ifdef CAPSTONE
+ << "MCD_OPC_SoftFail";
+#else
+ << "MCD::OPC_SoftFail";
+#endif
// Positive mask
uint64_t Value = 0;
unsigned Shift = 0;
@@ -869,7 +904,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
}
case MCD::OPC_Fail: {
++I;
- OS.indent(Indentation) << "MCD::OPC_Fail,\n";
+ OS.indent(Indentation)
+#ifdef CAPSTONE
+ << "MCD_OPC_Fail"
+#else
+ << "MCD::OPC_Fail"
+#endif
+ << ",\n";
break;
}
}
@@ -884,23 +925,46 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
void FixedLenDecoderEmitter::
emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates,
unsigned Indentation) const {
+#ifdef CAPSTONE
+ OS.indent(Indentation) << "static bool getbool(uint64_t b)\n";
+ OS.indent(Indentation) << "{\n";
+ OS.indent(Indentation) << "\treturn b != 0;\n";
+ OS.indent(Indentation) << "}\n\n";
+#endif
+
// The predicate function is just a big switch statement based on the
// input predicate index.
OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, "
+#ifdef CAPSTONE
+ << "uint64_t Bits)\n{\n";
+#else
<< "const FeatureBitset& Bits) {\n";
+#endif
Indentation += 2;
if (!Predicates.empty()) {
OS.indent(Indentation) << "switch (Idx) {\n";
- OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
+ OS.indent(Indentation) << "default: "
+#ifdef CAPSTONE
+ << "// "
+#endif
+ << "llvm_unreachable(\"Invalid index!\");\n";
unsigned Index = 0;
for (const auto &Predicate : Predicates) {
OS.indent(Indentation) << "case " << Index++ << ":\n";
- OS.indent(Indentation+2) << "return (" << Predicate << ");\n";
+ OS.indent(Indentation+2) << "return "
+#ifdef CAPSTONE
+ << "getbool"
+#endif
+ << "(" << Predicate << ");\n";
}
OS.indent(Indentation) << "}\n";
} else {
// No case statement to emit
- OS.indent(Indentation) << "llvm_unreachable(\"Invalid index!\");\n";
+ OS.indent(Indentation)
+#ifdef CAPSTONE
+ << "// "
+#endif
+ << "llvm_unreachable(\"Invalid index!\");\n";
}
Indentation -= 2;
OS.indent(Indentation) << "}\n\n";
@@ -911,23 +975,39 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders,
unsigned Indentation) const {
// The decoder function is just a big switch statement based on the
// input decoder index.
+#ifdef CAPSTONE
+#define EDF_EOL " \\\n"
+ OS.indent(Indentation) << "#define DecodeToMCInst(fname,fieldname, InsnType) \\\n";
+ OS.indent(Indentation) << "static DecodeStatus fname(DecodeStatus S, unsigned Idx, InsnType insn, MCInst *MI, \\\n";
+ OS.indent(Indentation) << " uint64_t Address, const void *Decoder) \\\n";
+ OS.indent(Indentation) << "{ \\\n";
+#else
+#define EDF_EOL "\n"
OS.indent(Indentation) << "template<typename InsnType>\n";
OS.indent(Indentation) << "static DecodeStatus decodeToMCInst(DecodeStatus S,"
<< " unsigned Idx, InsnType insn, MCInst &MI,\n";
OS.indent(Indentation) << " uint64_t "
<< "Address, const void *Decoder, bool &DecodeComplete) {\n";
+#endif
Indentation += 2;
+#ifndef CAPSTONE
OS.indent(Indentation) << "DecodeComplete = true;\n";
- OS.indent(Indentation) << "InsnType tmp;\n";
- OS.indent(Indentation) << "switch (Idx) {\n";
- OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
+#endif
+ OS.indent(Indentation) << "InsnType tmp;" EDF_EOL;
+ OS.indent(Indentation) << "switch (Idx) {" EDF_EOL;
+ OS.indent(Indentation) << "default:"
+#ifndef CAPSTONE
+ << " llvm_unreachable(\"Invalid index!\");\n";
+#else
+ << " \\\n";
+#endif
unsigned Index = 0;
for (const auto &Decoder : Decoders) {
- OS.indent(Indentation) << "case " << Index++ << ":\n";
+ OS.indent(Indentation) << "case " << Index++ << ":" EDF_EOL;
OS << Decoder;
- OS.indent(Indentation+2) << "return S;\n";
+ OS.indent(Indentation+2) << "return S;" EDF_EOL;
}
- OS.indent(Indentation) << "}\n";
+ OS.indent(Indentation) << "}" EDF_EOL;
Indentation -= 2;
OS.indent(Indentation) << "}\n\n";
}
@@ -1054,16 +1134,21 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
const std::string &Decoder = OpInfo.Decoder;
if (OpInfo.numFields() != 1)
- o.indent(Indentation) << "tmp = 0;\n";
+ o.indent(Indentation) << "tmp = 0;" EDF_EOL;
for (const EncodingField &EF : OpInfo) {
o.indent(Indentation) << "tmp ";
if (OpInfo.numFields() != 1) o << '|';
- o << "= fieldFromInstruction"
+ o << "= "
+#ifdef CAPSTONE
+ << "fieldname"
+#else
+ << "fieldFromInstruction"
+#endif
<< "(insn, " << EF.Base << ", " << EF.Width << ')';
if (OpInfo.numFields() != 1 || EF.Offset != 0)
o << " << " << EF.Offset;
- o << ";\n";
+ o << ";" EDF_EOL;
}
if (Decoder != "") {
@@ -1071,8 +1156,12 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
o.indent(Indentation) << Emitter->GuardPrefix << Decoder
<< "(MI, tmp, Address, Decoder)"
<< Emitter->GuardPostfix
+#ifdef CAPSTONE
+ << " return MCDisassembler_Fail; \\\n";
+#else
<< " { " << (OpHasCompleteDecoder ? "" : "DecodeComplete = false; ")
<< "return MCDisassembler::Fail; }\n";
+#endif
} else {
OpHasCompleteDecoder = true;
o.indent(Indentation) << "MI.addOperand(MCOperand::createImm(tmp));\n";
@@ -1091,7 +1180,13 @@ void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation,
<< "(MI, insn, Address, Decoder)"
<< Emitter->GuardPostfix
<< " { " << (HasCompleteDecoder ? "" : "DecodeComplete = false; ")
- << "return MCDisassembler::Fail; }\n";
+ << "return "
+#ifdef CAPSTONE
+ << "MCDisassembler_Fail"
+#else
+ << "MCDisassembler::Fail"
+#endif
+ << "; }\n";
break;
}
@@ -1129,10 +1224,19 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
const std::string &PredicateNamespace) {
if (str[0] == '!')
+#ifdef CAPSTONE
+ o << "~(Bits & " << PredicateNamespace << "_"
+ << str.slice(1,str.size()) << ")";
+#else
o << "!Bits[" << PredicateNamespace << "::"
<< str.slice(1,str.size()) << "]";
+#endif
else
+#ifdef CAPSTONE
+ o << "(Bits & " << PredicateNamespace << "_" << str << ")";
+#else
o << "Bits[" << PredicateNamespace << "::" << str << "]";
+#endif
}
bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
@@ -2047,6 +2151,17 @@ static bool populateInstruction(CodeGenTarget &Target,
// fieldFromInstruction().
static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
OS << "// Helper function for extracting fields from encoded instructions.\n"
+#ifdef CAPSTONE
+ << "#define FieldFromInstruction(fname, InsnType) \\\n"
+ << "static InsnType fname(InsnType insn, unsigned startBit, unsigned numBits) \\\n"
+ << "{ \\\n"
+ << " InsnType fieldMask; \\\n"
+ << " if (numBits == sizeof(InsnType)*8) \\\n"
+ << " fieldMask = (InsnType)(-1LL); \\\n"
+ << " else \\\n"
+ << " fieldMask = (((InsnType)1 << numBits) - 1) << startBit; \\\n"
+ << " return (insn & fieldMask) >> startBit; \\\n"
+#else
<< "template<typename InsnType>\n"
<< "static InsnType fieldFromInstruction(InsnType insn, unsigned startBit,\n"
<< " unsigned numBits) {\n"
@@ -2058,12 +2173,92 @@ static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
<< " else\n"
<< " fieldMask = (((InsnType)1 << numBits) - 1) << startBit;\n"
<< " return (insn & fieldMask) >> startBit;\n"
+#endif
<< "}\n\n";
}
// emitDecodeInstruction - Emit the templated helper function
// decodeInstruction().
static void emitDecodeInstruction(formatted_raw_ostream &OS) {
+#ifdef CAPSTONE
+ OS << "#define DecodeInstruction(fname, fieldname, decoder, InsnType) \\\n"
+ << "static DecodeStatus fname(const uint8_t DecodeTable[], MCInst *MI, \\\n"
+ << " InsnType insn, uint64_t Address, const MCRegisterInfo *MRI, int feature) \\\n"
+ << "{ \\\n"
+ << " uint64_t Bits = getFeatureBits(feature); \\\n"
+ << " const uint8_t *Ptr = DecodeTable; \\\n"
+ << " uint32_t CurFieldValue = 0, ExpectedValue; \\\n"
+ << " DecodeStatus S = MCDisassembler_Success; \\\n"
+ << " unsigned Start, Len, NumToSkip, PIdx, Opc, DecodeIdx; \\\n"
+ << " InsnType Val, FieldValue, PositiveMask, NegativeMask; \\\n"
+ << " bool Pred, Fail; \\\n"
+ << " for (;;) { \\\n"
+ << " switch (*Ptr) { \\\n"
+ << " default: \\\n"
+ << " return MCDisassembler_Fail; \\\n"
+ << " case MCD_OPC_ExtractField: { \\\n"
+ << " Start = *++Ptr; \\\n"
+ << " Len = *++Ptr; \\\n"
+ << " ++Ptr; \\\n"
+ << " CurFieldValue = (uint32_t)fieldname(insn, Start, Len); \\\n"
+ << " break; \\\n"
+ << " } \\\n"
+ << " case MCD_OPC_FilterValue: { \\\n"
+ << " Val = (InsnType)decodeULEB128(++Ptr, &Len); \\\n"
+ << " Ptr += Len; \\\n"
+ << " NumToSkip = *Ptr++; \\\n"
+ << " NumToSkip |= (*Ptr++) << 8; \\\n"
+ << " if (Val != CurFieldValue) \\\n"
+ << " Ptr += NumToSkip; \\\n"
+ << " break; \\\n"
+ << " } \\\n"
+ << " case MCD_OPC_CheckField: { \\\n"
+ << " Start = *++Ptr; \\\n"
+ << " Len = *++Ptr; \\\n"
+ << " FieldValue = fieldname(insn, Start, Len); \\\n"
+ << " ExpectedValue = (uint32_t)decodeULEB128(++Ptr, &Len); \\\n"
+ << " Ptr += Len; \\\n"
+ << " NumToSkip = *Ptr++; \\\n"
+ << " NumToSkip |= (*Ptr++) << 8; \\\n"
+ << " if (ExpectedValue != FieldValue) \\\n"
+ << " Ptr += NumToSkip; \\\n"
+ << " break; \\\n"
+ << " } \\\n"
+ << " case MCD_OPC_CheckPredicate: { \\\n"
+ << " PIdx = (uint32_t)decodeULEB128(++Ptr, &Len); \\\n"
+ << " Ptr += Len; \\\n"
+ << " NumToSkip = *Ptr++; \\\n"
+ << " NumToSkip |= (*Ptr++) << 8; \\\n"
+ << " Pred = checkDecoderPredicate(PIdx, Bits); \\\n"
+ << " if (!Pred) \\\n"
+ << " Ptr += NumToSkip; \\\n"
+ << " (void)Pred; \\\n"
+ << " break; \\\n"
+ << " } \\\n"
+ << " case MCD_OPC_Decode: { \\\n"
+ << " Opc = (unsigned)decodeULEB128(++Ptr, &Len); \\\n"
+ << " Ptr += Len; \\\n"
+ << " DecodeIdx = (unsigned)decodeULEB128(Ptr, &Len); \\\n"
+ << " Ptr += Len; \\\n"
+ << " MCInst_setOpcode(MI, Opc); \\\n"
+ << " return decoder(S, DecodeIdx, insn, MI, Address, MRI); \\\n"
+ << " } \\\n"
+ << " case MCD_OPC_SoftFail: { \\\n"
+ << " PositiveMask = (InsnType)decodeULEB128(++Ptr, &Len); \\\n"
+ << " Ptr += Len; \\\n"
+ << " NegativeMask = (InsnType)decodeULEB128(Ptr, &Len); \\\n"
+ << " Ptr += Len; \\\n"
+ << " Fail = (insn & PositiveMask) || (~insn & NegativeMask); \\\n"
+ << " if (Fail) \\\n"
+ << " S = MCDisassembler_SoftFail; \\\n"
+ << " break; \\\n"
+ << " } \\\n"
+ << " case MCD_OPC_Fail: { \\\n"
+ << " return MCDisassembler_Fail; \\\n"
+ << " } \\\n"
+ << " } \\\n"
+ << " } \\\n"
+#else
OS << "template<typename InsnType>\n"
<< "static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], "
"MCInst &MI,\n"
@@ -2240,12 +2435,18 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " }\n"
<< " llvm_unreachable(\"bogosity detected in disassembler state "
"machine!\");\n"
+#endif
<< "}\n\n";
}
// Emits disassembler code for instruction decoding.
void FixedLenDecoderEmitter::run(raw_ostream &o) {
formatted_raw_ostream OS(o);
+#ifdef CAPSTONE
+ OS << "#include \"../../MCInst.h\"\n";
+ OS << "#include \"../../LEB128.h\"\n";
+ OS << "\n";
+#else
OS << "#include \"llvm/MC/MCInst.h\"\n";
OS << "#include \"llvm/Support/Debug.h\"\n";
OS << "#include \"llvm/Support/DataTypes.h\"\n";
@@ -2254,6 +2455,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
OS << "#include <assert.h>\n";
OS << '\n';
OS << "namespace llvm {\n\n";
+#endif
emitFieldFromInstruction(OS);
@@ -2322,7 +2524,13 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
// Emit the main entry point for the decoder, decodeInstruction().
emitDecodeInstruction(OS);
+#ifdef CAPSTONE
+ OS << "FieldFromInstruction(fieldFromInstruction, uint64_t)\n";
+ OS << "DecodeToMCInst(decodeToMCInst, fieldFromInstruction, uint64_t)\n";
+ OS << "DecodeInstruction(decodeInstruction, fieldFromInstruction, decodeToMCInst, uint64_t)\n";
+#else
OS << "\n} // End llvm namespace\n";
+#endif
}
namespace llvm {
--
2.19.1

View File

@@ -0,0 +1,225 @@
From 5569e48b9cb34a33910e1e850fbfabc999f016a2 Mon Sep 17 00:00:00 2001
From: mephi42 <mephi42@gmail.com>
Date: Tue, 7 Aug 2018 20:00:08 +0200
Subject: [PATCH 5/7] capstone: generate *GenAsmWriter.inc
---
utils/TableGen/AsmWriterEmitter.cpp | 89 +++++++++++++++++++++++++++--
utils/TableGen/AsmWriterInst.cpp | 4 ++
2 files changed, 87 insertions(+), 6 deletions(-)
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index 3c4c9c8e5c6..133800d217c 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -272,16 +272,22 @@ static void UnescapeString(std::string &Str) {
/// clearing the Instructions vector.
void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
Record *AsmWriter = Target.getAsmWriter();
+#ifndef CAPSTONE
StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+#endif
bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
O <<
"/// printInstruction - This method is automatically generated by tablegen\n"
"/// from the instruction set description.\n"
+#ifdef CAPSTONE
+ "static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI)\n{\n";
+#else
"void " << Target.getName() << ClassName
<< "::printInstruction(const MCInst *MI, "
<< (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
<< "raw_ostream &O) {\n";
+#endif
// Build an aggregate string, and build a table of offsets into it.
SequenceToOffsetTable<std::string> StringTable;
@@ -379,9 +385,16 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
}
// Emit the string table itself.
+#ifdef CAPSTONE
+ O << "#ifndef CAPSTONE_DIET\n";
+#endif
O << " static const char AsmStrs[] = {\n";
StringTable.emit(O, printChar);
- O << " };\n\n";
+ O << " };\n"
+#ifdef CAPSTONE
+ << "#endif\n"
+#endif
+ << "\n";
// Emit the lookup tables in pieces to minimize wasted bytes.
unsigned BytesNeeded = ((OpcodeInfoBits - BitsLeft) + 7) / 8;
@@ -409,21 +422,45 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
// If the total bits is more than 32-bits we need to use a 64-bit type.
if (BitsLeft < (OpcodeInfoBits - 32))
BitsOS << "(uint64_t)";
- BitsOS << "OpInfo" << Table << "[MI->getOpcode()] << " << Shift << ";\n";
+ BitsOS << "OpInfo" << Table << "["
+#ifdef CAPSTONE
+ << "MCInst_getOpcode(MI)"
+#else
+ << "MI->getOpcode()"
+#endif
+ << "] << " << Shift << ";\n";
// Prepare the shift for the next iteration and increment the table count.
Shift += TableSize;
++Table;
}
// Emit the initial tab character.
+#ifndef CAPSTONE
O << " O << \"\\t\";\n\n";
+#endif
O << " // Emit the opcode for the instruction.\n";
O << BitsString;
// Emit the starting string.
- O << " assert(Bits != 0 && \"Cannot print this instruction.\");\n"
- << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1;\n\n";
+ O << " "
+#ifdef CAPSTONE
+ << "// "
+#endif
+ << "assert(Bits != 0 && \"Cannot print this instruction.\");\n"
+#ifdef CAPSTONE
+ << "#ifndef CAPSTONE_DIET\n"
+ << " SStream_concat0(O, "
+#else
+ << " O << "
+#endif
+ << "AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1"
+#ifdef CAPSTONE
+ << ");\n"
+ << "#endif\n\n";
+#else
+ << ");\n\n";
+#endif
// Output the table driven operand information.
BitsLeft = OpcodeInfoBits-AsmStrBits;
@@ -455,7 +492,11 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
O << " switch ((Bits >> "
<< (OpcodeInfoBits-BitsLeft) << ") & "
<< ((1 << NumBits)-1) << ") {\n"
- << " default: llvm_unreachable(\"Invalid command number.\");\n";
+ << " default: "
+#ifdef CAPSTONE
+ << "// "
+#endif
+ << "llvm_unreachable(\"Invalid command number.\");\n";
// Print out all the cases.
for (unsigned j = 0, e = Commands.size(); j != e; ++j) {
@@ -536,6 +577,9 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
}
StringTable.layout();
+#ifdef CAPSTONE
+ O << "#ifndef CAPSTONE_DIET\n";
+#endif
O << " static const char AsmStrs" << AltName << "[] = {\n";
StringTable.emit(O, printChar);
O << " };\n\n";
@@ -552,8 +596,10 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
}
void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
+#ifndef CAPSTONE
Record *AsmWriter = Target.getAsmWriter();
StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+#endif
const auto &Registers = Target.getRegBank().getRegisters();
const std::vector<Record*> &AltNameIndices = Target.getRegAltNameIndices();
bool hasAltNames = AltNameIndices.size() > 1;
@@ -563,12 +609,20 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
"\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
"/// from the register set description. This returns the assembler name\n"
"/// for the specified register.\n"
+#ifdef CAPSTONE
+ "static const char *getRegisterName(unsigned RegNo)\n{\n";
+#else
"const char *" << Target.getName() << ClassName << "::";
if (hasAltNames)
O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n";
else
O << "getRegisterName(unsigned RegNo) {\n";
- O << " assert(RegNo && RegNo < " << (Registers.size()+1)
+#endif
+ O << " "
+#ifdef CAPSTONE
+ << "// "
+#endif
+ << "assert(RegNo && RegNo < " << (Registers.size()+1)
<< " && \"Invalid register number!\");\n"
<< "\n";
@@ -595,10 +649,22 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
}
O << " }\n";
} else {
+#ifdef CAPSTONE
+ O << " //int i;\n"
+ << " //for (i = 0; i < sizeof(RegAsmOffset); i++)\n"
+ << " // printf(\"%s = %u\\n\", AsmStrs+RegAsmOffset[i], i + 1);\n"
+ << " //printf(\"*************************\\n\");\n"
+#else
O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
<< " \"Invalid alt name index for register!\");\n"
+#endif
<< " return AsmStrs+RegAsmOffset[RegNo-1];\n";
}
+#ifdef CAPSTONE
+ O << "#else\n"
+ << " return NULL;\n"
+ << "#endif\n";
+#endif
O << "}\n";
}
@@ -1135,9 +1201,20 @@ AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) {
}
void AsmWriterEmitter::run(raw_ostream &O) {
+#ifdef CAPSTONE
+ O << "/* Capstone Disassembly Engine */\n"
+ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
+ "\n"
+ "#include <stdio.h>\t// debug\n"
+ "#include <capstone/platform.h>\n"
+ "\n"
+ "\n";
+#endif
EmitPrintInstruction(O);
EmitGetRegisterName(O);
+#ifndef CAPSTONE
EmitPrintAliasInstruction(O);
+#endif
}
namespace llvm {
diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp
index 2c19e5d663d..6fa751e50df 100644
--- a/utils/TableGen/AsmWriterInst.cpp
+++ b/utils/TableGen/AsmWriterInst.cpp
@@ -28,9 +28,13 @@ static bool isIdentChar(char C) {
std::string AsmWriterOperand::getCode(bool PassSubtarget) const {
if (OperandType == isLiteralTextOperand) {
+#ifdef CAPSTONE
+ return "SStream_concat0(O, \"" + Str + "\");";
+#else
if (Str.size() == 1)
return "O << '" + Str + "';";
return "O << \"" + Str + "\";";
+#endif
}
if (OperandType == isLiteralStatementOperand)
--
2.19.1

View File

@@ -0,0 +1,174 @@
From 7a436110ef15c803dc8524af2fb5612bcacbb126 Mon Sep 17 00:00:00 2001
From: mephi42 <mephi42@gmail.com>
Date: Tue, 7 Aug 2018 20:55:32 +0200
Subject: [PATCH 6/7] capstone: generate *MappingInsn.inc
---
lib/Target/SystemZ/CMakeLists.txt | 1 +
utils/TableGen/InstrInfoEmitter.cpp | 95 +++++++++++++++++++++++++++++
utils/TableGen/TableGen.cpp | 6 ++
utils/TableGen/TableGenBackends.h | 1 +
4 files changed, 103 insertions(+)
diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt
index f83b4242fb4..4b5d9c4a3b2 100644
--- a/lib/Target/SystemZ/CMakeLists.txt
+++ b/lib/Target/SystemZ/CMakeLists.txt
@@ -6,6 +6,7 @@ tablegen(LLVM SystemZGenCallingConv.inc -gen-callingconv)
tablegen(LLVM SystemZGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM SystemZGenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM SystemZGenInstrInfo.inc -gen-instr-info)
+tablegen(LLVM SystemZMappingInsn.inc -mapping-insn)
tablegen(LLVM SystemZGenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM SystemZGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM SystemZGenSubtargetInfo.inc -gen-subtarget)
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 2f3a2729262..14ab1ea8a72 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -744,4 +744,99 @@ void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {
#endif
}
+#ifdef CAPSTONE
+std::string GetPublicName(const CodeGenInstruction *Inst) {
+ std::string Name = Inst->TheDef->getName();
+ // Apply backward compatibility fixups.
+ // BRNLE -> BNLER.
+ if (Name.length() >= 5 && Name.substr(0, 5) == "BRAsm") {
+ Name = "B" + Name.substr(5, Name.length() - 5) + "R";
+ }
+ // SSKEOpt -> SSKE.
+ while (Name.length() >= 3 && Name.substr(Name.length() - 3, 3) == "Opt") {
+ Name = Name.substr(0, Name.length() - 3);
+ }
+ // BRCLAsm -> BRCL.
+ while (true) {
+ size_t pos = Name.find("Asm");
+ if (pos == std::string::npos) {
+ break;
+ }
+ Name = Name.substr(0, pos) + Name.substr(pos + 3);
+ }
+ // CPSDRxx -> CPSDR.
+ if (Name.length() >= 2) {
+ std::string Suffix2 = Name.substr(Name.length() - 2, 2);
+ if (Suffix2 == "dd" || Suffix2 == "ds" ||
+ Suffix2 == "sd" || Suffix2 == "ss") {
+ Name = Name.substr(0, Name.length() - 2);
+ }
+ }
+ return "SYSZ_INS_" + Name;
+}
+
+std::string GetRegisterName(Record *Reg) {
+ std::string Name = Reg->getName();
+ for (char& c : Name) {
+ c = toupper(c);
+ }
+ // R0L, R0D -> R0.
+ if (Name.length() >= 3 &&
+ Name[Name.length() - 3] == 'R' &&
+ (Name[Name.length() - 1] == 'L' ||
+ Name[Name.length() - 1] == 'D')) {
+ Name = Name.substr(0, Name.length() - 3) + Name[Name.length() - 2];
+ }
+ return "SYSZ_REG_" + Name;
+}
+
+std::string GetGroupName(Record *Pred) {
+ std::string Name = Pred->getName();
+ for (char& c : Name) {
+ c = toupper(c);
+ }
+ if (Name.length() >= 7 && Name.substr(0, 7) == "FEATURE") {
+ Name = Name.substr(7);
+ }
+ return "SYSZ_GRP_" + Name;
+}
+
+void EmitMappingInsn(RecordKeeper &RK, raw_ostream &OS) {
+ OS << "// This is auto-gen data for Capstone engine (www.capstone-engine.org)\n"
+ "// By Nguyen Anh Quynh <aquynh@gmail.com>\n"
+ "\n";
+ CodeGenTarget Target(RK);
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ if (Inst->TheDef->getValueAsBit("isPseudo") ||
+ Inst->TheDef->getValueAsBit("isCodeGenOnly")) {
+ continue;
+ }
+ OS << "{\n"
+ << "\t" << Target.getName() << "_" << Inst->TheDef->getName() << ", "
+ << GetPublicName(Inst) << ",\n"
+ << "#ifndef CAPSTONE_DIET\n"
+ << "\t{ ";
+ for (Record *Use : Inst->TheDef->getValueAsListOfDefs("Uses")) {
+ OS << GetRegisterName(Use) << ", ";
+ }
+ OS << "0 }, { ";
+ for (Record *Def : Inst->TheDef->getValueAsListOfDefs("Defs")) {
+ OS << GetRegisterName(Def) << ", ";
+ }
+ OS << "0 }, { ";
+ ListInit *Predicates = Inst->TheDef->getValueAsListInit("Predicates");
+ for (unsigned i = 0; i < Predicates->size(); ++i) {
+ OS << GetGroupName(Predicates->getElementAsRecord(i)) << ", ";
+ }
+ OS << "0 }, "
+ << Inst->TheDef->getValueAsBit("isBranch")
+ << ", "
+ << Inst->TheDef->getValueAsBit("isIndirectBranch")
+ << "\n"
+ << "#endif\n"
+ << "},\n";
+ }
+}
+#endif
+
} // end llvm namespace
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index cf1404d8769..bbb4e860536 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -27,6 +27,7 @@ enum ActionType {
GenEmitter,
GenRegisterInfo,
GenInstrInfo,
+ MappingInsn,
GenInstrDocs,
GenAsmWriter,
GenAsmMatcher,
@@ -65,6 +66,8 @@ namespace {
"Generate registers and register classes info"),
clEnumValN(GenInstrInfo, "gen-instr-info",
"Generate instruction descriptions"),
+ clEnumValN(MappingInsn, "mapping-insn",
+ ""),
clEnumValN(GenInstrDocs, "gen-instr-docs",
"Generate instruction documentation"),
clEnumValN(GenCallingConv, "gen-callingconv",
@@ -135,6 +138,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenInstrInfo:
EmitInstrInfo(Records, OS);
break;
+ case MappingInsn:
+ EmitMappingInsn(Records, OS);
+ break;
case GenInstrDocs:
EmitInstrDocs(Records, OS);
break;
diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
index 1329a6d833f..a41e46b1db0 100644
--- a/utils/TableGen/TableGenBackends.h
+++ b/utils/TableGen/TableGenBackends.h
@@ -75,6 +75,7 @@ void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS);
void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);
void EmitFastISel(RecordKeeper &RK, raw_ostream &OS);
void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS);
+void EmitMappingInsn(RecordKeeper &RK, raw_ostream &OS);
void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS);
void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS);
void EmitCompressInst(RecordKeeper &RK, raw_ostream &OS);
--
2.19.1

View File

@@ -0,0 +1,110 @@
From b42f9f2014ec49a22077b6610863d9341a74e142 Mon Sep 17 00:00:00 2001
From: mephi42 <mephi42@gmail.com>
Date: Fri, 17 Aug 2018 11:07:39 +0200
Subject: [PATCH 7/7] capstone: generate *GenInsnNameMaps.inc
---
lib/Target/SystemZ/CMakeLists.txt | 1 +
utils/TableGen/InstrInfoEmitter.cpp | 29 +++++++++++++++++++++++++++++
utils/TableGen/TableGen.cpp | 6 ++++++
utils/TableGen/TableGenBackends.h | 1 +
4 files changed, 37 insertions(+)
diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt
index 4b5d9c4a3b2..2c64e0a94b8 100644
--- a/lib/Target/SystemZ/CMakeLists.txt
+++ b/lib/Target/SystemZ/CMakeLists.txt
@@ -7,6 +7,7 @@ tablegen(LLVM SystemZGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM SystemZGenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM SystemZGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM SystemZMappingInsn.inc -mapping-insn)
+tablegen(LLVM SystemZGenInsnNameMaps.inc -gen-insn-name-maps)
tablegen(LLVM SystemZGenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM SystemZGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM SystemZGenSubtargetInfo.inc -gen-subtarget)
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 14ab1ea8a72..ccf8170ca62 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -837,6 +837,35 @@ void EmitMappingInsn(RecordKeeper &RK, raw_ostream &OS) {
<< "},\n";
}
}
+
+std::string GetMnemonic(const CodeGenInstruction *Inst) {
+ std::string Mnemonic = Inst->AsmString;
+
+ for (size_t i = 0; i < Mnemonic.length(); i++) {
+ if (Mnemonic[i] == '\t') {
+ return Mnemonic.substr(0, i);
+ }
+ }
+ return Mnemonic;
+}
+
+void EmitInsnNameMaps(RecordKeeper &RK, raw_ostream &OS) {
+ OS << "// This is auto-gen data for Capstone engine (www.capstone-engine.org)\n"
+ "// By Nguyen Anh Quynh <aquynh@gmail.com>\n"
+ "\n";
+ CodeGenTarget Target(RK);
+ std::map<std::string, std::string> M;
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ if (Inst->TheDef->getValueAsBit("isPseudo") ||
+ Inst->TheDef->getValueAsBit("isCodeGenOnly")) {
+ continue;
+ }
+ M[GetPublicName(Inst)] = GetMnemonic(Inst);
+ }
+ for (auto &P : M) {
+ OS << "\t{ " << P.first << ", \"" << P.second << "\" },\n";
+ }
+}
#endif
} // end llvm namespace
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index bbb4e860536..27c6603de5a 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -28,6 +28,7 @@ enum ActionType {
GenRegisterInfo,
GenInstrInfo,
MappingInsn,
+ GenInsnNameMaps,
GenInstrDocs,
GenAsmWriter,
GenAsmMatcher,
@@ -68,6 +69,8 @@ namespace {
"Generate instruction descriptions"),
clEnumValN(MappingInsn, "mapping-insn",
""),
+ clEnumValN(GenInsnNameMaps, "gen-insn-name-maps",
+ ""),
clEnumValN(GenInstrDocs, "gen-instr-docs",
"Generate instruction documentation"),
clEnumValN(GenCallingConv, "gen-callingconv",
@@ -141,6 +144,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case MappingInsn:
EmitMappingInsn(Records, OS);
break;
+ case GenInsnNameMaps:
+ EmitInsnNameMaps(Records, OS);
+ break;
case GenInstrDocs:
EmitInstrDocs(Records, OS);
break;
diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
index a41e46b1db0..5656e5be849 100644
--- a/utils/TableGen/TableGenBackends.h
+++ b/utils/TableGen/TableGenBackends.h
@@ -76,6 +76,7 @@ void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);
void EmitFastISel(RecordKeeper &RK, raw_ostream &OS);
void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS);
void EmitMappingInsn(RecordKeeper &RK, raw_ostream &OS);
+void EmitInsnNameMaps(RecordKeeper &RK, raw_ostream &OS);
void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS);
void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS);
void EmitCompressInst(RecordKeeper &RK, raw_ostream &OS);
--
2.19.1

View File

@@ -0,0 +1,58 @@
# How to update SystemZ tables.
* Checkout LLVM. Patches are tested on commit `c13d5969^`, because
`c13d5969` changed the decode table format.
* Apply patches from the current directory.
* Run tablegen.
```
cd $LLVM
mkdir build
cd build
cmake -DCMAKE_CXX_FLAGS=-DCAPSTONE ..
make SystemZCommonTableGen -j$(getconf _NPROCESSORS_ONLN)
```
* Copy `.inc` files.
```
cp arch/SystemZ/SystemZGenInsnNameMaps.inc \
arch/SystemZ/SystemZGenInsnNameMaps.inc.old
for inc in $(cd arch/SystemZ && ls *.inc); do
cp $LLVM/build/lib/Target/SystemZ/$inc arch/SystemZ/
done
```
* Fixup `SystemZGenInsnNameMaps.inc`.
```
comm -1 -3 \
<(grep SYSZ_INS_ <arch/SystemZ/SystemZGenInsnNameMaps.inc.old \
| sort -u) \
<(grep SYSZ_INS_ <arch/SystemZ/SystemZGenInsnNameMaps.inc \
| sort -u) \
>arch/SystemZ/SystemZGenInsnNameMaps.inc.new
cat arch/SystemZ/SystemZGenInsnNameMaps.inc.old \
arch/SystemZ/SystemZGenInsnNameMaps.inc.new \
>arch/SystemZ/SystemZGenInsnNameMaps.inc
```
* Add new groups, insns, registers and formats.
* `include/capstone/systemz.h`
* `enum sysz_insn`:
```
comm -1 -3 \
<(perl -ne 'if (/(SYSZ_INS_.+),/) { print "\t$1,\n" }' \
<include/capstone/systemz.h | sort -u) \
<(perl -ne 'if (/(SYSZ_INS_.+),/) { print "\t$1,\n" }' \
<arch/SystemZ/SystemZMappingInsn.inc | sort -u)
```
* `enum sysz_insn_group`:
```
perl -ne 'if (/(SYSZ_GRP_.*?),/) { print "\t$1,\n"; }' < \
arch/SystemZ/SystemZMappingInsn.inc | sort -u
```
* `arch/SystemZ/SystemZDisassembler.c`
* `arch/SystemZ/SystemZInstPrinter.c`
* `arch/SystemZ/SystemZMCTargetDesc.c`
* `arch/SystemZ/SystemZMCTargetDesc.h`
* `arch/SystemZ/SystemZMapping.c`
* `enum group_name_maps`:
```
perl -ne 'if (/(SYSZ_GRP_(.*?)),/) { print "\t{ $1, \"" . lc($2) . "\" },\n"; }' \
arch/SystemZ/SystemZMappingInsn.inc | sort -u
```

View File

@@ -0,0 +1,11 @@
For Windows kernel programming, the SDK does not offer some functions
needed by Capstone. The missing functions are:
- Memory allocations: malloc(), calloc(), realloc() & free().
- Format input variables & write out result to char buffer: vsnprintf()
This directory contains some code providing above-mentioned functions, so you can
integrate Capstone with your Windows-kernel drivers using C++.
All the code here is contributed by Peter Hlavaty <zer0mem@yahoo.com>
See the full example with Capstone integration at https://github.com/zer0mem/libc.git

View File

@@ -0,0 +1,143 @@
/**
* @file libc.cpp
* @author created by: Peter Hlavaty
*/
#include "libc.h"
#include <memory>
#include <Ntintsafe.h>
#pragma warning(push)
#pragma warning (disable : 4565)
#ifndef _LIBC_POOL_TAG
#define _LIBC_POOL_TAG 'colM'
#endif
// very nice for debug forensics!
struct MEMBLOCK
{
size_t size;
#pragma warning(push)
#pragma warning (disable : 4200)
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT))
char data[0];
#pragma warning(pop)
};
EXTERN_C
__drv_when(return!=0, __drv_allocatesMem(pBlock))
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
__bcount_opt(size)
void*
__cdecl malloc(
__in size_t size
)
{
/* A specially crafted size value can trigger the overflow.
If the sum in a value that overflows or underflows the capacity of the type,
the function returns nullptr. */
size_t number_of_bytes = 0;
if (!NT_SUCCESS(RtlSizeTAdd(size, sizeof(MEMBLOCK), &number_of_bytes))){
return nullptr;
}
MEMBLOCK *pBlock = static_cast<MEMBLOCK*>(
ExAllocatePoolWithTag(
NonPagedPoolNxCacheAligned,
number_of_bytes,
_LIBC_POOL_TAG));
if (nullptr == pBlock)
return nullptr;
pBlock->size = size;
return pBlock->data;
}
EXTERN_C
__drv_when(return != 0, __drv_allocatesMem(p))
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
__bcount_opt(size * n)
void*
__cdecl calloc(size_t n, size_t size)
{
size_t total = n * size;
void *p = malloc(total);
if (!p) return NULL;
return memset(p, 0, total);
}
EXTERN_C
__drv_when(return!=0, __drv_allocatesMem(inblock))
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
__bcount_opt(size)
void*
__cdecl realloc(
__in_opt void* ptr,
__in size_t size
)
{
if (!ptr)
return malloc(size);
std::unique_ptr<unsigned char> inblock = std::unique_ptr<unsigned char>(static_cast<unsigned char*>(ptr));
// alloc new block
void* mem = malloc(size);
if (!mem)
return nullptr;
// copy from old one, not overflow ..
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data)->size, size));
return mem;
}
EXTERN_C
__drv_maxIRQL(DISPATCH_LEVEL)
void
__cdecl free(
__inout_opt __drv_freesMem(Mem) void* ptr
)
{
if (ptr)
ExFreePoolWithTag(CONTAINING_RECORD(ptr, MEMBLOCK, data), _LIBC_POOL_TAG);
}
#pragma warning(pop)
__drv_when(return!=0, __drv_allocatesMem(ptr))
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
__bcount_opt(size)
void*
__cdecl operator new(
__in size_t size
)
{
return malloc(size);
}
__drv_maxIRQL(DISPATCH_LEVEL)
void
__cdecl operator delete(
__inout void* ptr
)
{
free(ptr);
}
int
__cdecl vsnprintf(
char *buffer,
size_t count,
const char *format,
va_list argptr
)
{
return vsprintf_s(buffer, count, format, argptr);
}

View File

@@ -0,0 +1,40 @@
/**
* @file libc.h
* @author created by: Peter Hlavaty
*/
#pragma once
#include <ntifs.h>
EXTERN_C
__drv_when(return!=0, __drv_allocatesMem(pBlock))
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
__bcount_opt(size)
void* __cdecl malloc(__in size_t size);
EXTERN_C
__drv_when(return != 0, __drv_allocatesMem(p))
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
__bcount_opt(size * n)
void* __cdecl calloc(size_t n, size_t size);
EXTERN_C
__drv_when(return!=0, __drv_allocatesMem(inblock))
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
__bcount_opt(size)
void* __cdecl realloc(__in_opt void* ptr, __in size_t size);
EXTERN_C
__drv_maxIRQL(DISPATCH_LEVEL)
void __cdecl free(__inout_opt __drv_freesMem(Mem) void* ptr);
int __cdecl vsnprintf(char *buffer, size_t count,
const char *format, va_list argptr);