#!/usr/bin/python
# convert LLVM GenAsmWriter.inc for Capstone disassembler.
# by Nguyen Anh Quynh, 2019

import sys

if len(sys.argv) == 1:
    print("Syntax: %s <GenAsmWriter.inc> <Output-GenAsmWriter.inc> <Output-GenRegisterName.inc> <arch>" %sys.argv[0])
    sys.exit(1)

arch = sys.argv[4] 
f = open(sys.argv[1])
lines = f.readlines()
f.close()

f1 = open(sys.argv[2], 'w+')

f2 = open(sys.argv[3], 'w+')

f1.write("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n")
f1.write("/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */\n")
f1.write("\n")

f2.write("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n")
f2.write("/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */\n")
f2.write("\n")

need_endif = False
in_getRegisterName = False
in_printAliasInstr = False
fragment_no = None
skip_printing = False

skip_line = 0
skip_count = 0

def replace_getOp(line):
    line2 = line
    if 'MI->getOperand(0)' in line:
        line2 = line.replace('MI->getOperand(0)', 'MCInst_getOperand(MI, 0)')
    elif 'MI->getOperand(1)' in line:
        line2 = line.replace('MI->getOperand(1)', 'MCInst_getOperand(MI, 1)')
    elif 'MI->getOperand(2)' in line:
        line2 = line.replace('MI->getOperand(2)', 'MCInst_getOperand(MI, 2)')
    elif 'MI->getOperand(3)' in line:
        line2 = line.replace('MI->getOperand(3)', 'MCInst_getOperand(MI, 3)')
    elif 'MI->getOperand(4)' in line:
        line2 = line.replace('MI->getOperand(4)', 'MCInst_getOperand(MI, 4)')
    elif 'MI->getOperand(5)' in line:
        line2 = line.replace('MI->getOperand(5)', 'MCInst_getOperand(MI, 5)')
    elif 'MI->getOperand(6)' in line:
        line2 = line.replace('MI->getOperand(6)', 'MCInst_getOperand(MI, 6)')
    elif 'MI->getOperand(7)' in line:
        line2 = line.replace('MI->getOperand(7)', 'MCInst_getOperand(MI, 7)')
    elif 'MI->getOperand(8)' in line:
        line2 = line.replace('MI->getOperand(8)', 'MCInst_getOperand(MI, 8)')
    return line2

def replace_getReg(line):
    line2 = line
    if 'MI->getOperand(0).getReg()' in line:
        line2 = line.replace('MI->getOperand(0).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 0))')
    elif 'MI->getOperand(1).getReg()' in line:
        line2 = line.replace('MI->getOperand(1).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 1))')
    elif 'MI->getOperand(2).getReg()' in line:
        line2 = line.replace('MI->getOperand(2).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 2))')
    elif 'MI->getOperand(3).getReg()' in line:
        line2 = line.replace('MI->getOperand(3).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 3))')
    elif 'MI->getOperand(4).getReg()' in line:
        line2 = line.replace('MI->getOperand(4).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 4))')
    elif 'MI->getOperand(5).getReg()' in line:
        line2 = line.replace('MI->getOperand(5).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 5))')
    elif 'MI->getOperand(6).getReg()' in line:
        line2 = line.replace('MI->getOperand(6).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 6))')
    elif 'MI->getOperand(7).getReg()' in line:
        line2 = line.replace('MI->getOperand(7).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 7))')
    elif 'MI->getOperand(8).getReg()' in line:
        line2 = line.replace('MI->getOperand(8).getReg()', 'MCOperand_getReg(MCInst_getOperand(MI, 8))')
    return line2

# extract param between text()
# MRI.getRegClass(AArch64::GPR32spRegClassID).contains(MI->getOperand(1).getReg()))
def extract_paren(line, text):
    i = line.index(text)
    return line[line.index('(', i)+1 : line.index(')', i)]


# extract text between <>
# printSVERegOp<'q'>
def extract_brackets(line):
    if '<' in line:
        return line[line.index('<')+1 : line.index('>')]
    else:
        return ''

# delete text between <>, including <>
# printSVERegOp<'q'>
def del_brackets(line):
    if '<' in line:
        return line[:line.index('<')] + line[line.index('>') + 1:]
    else:
        return line


def print_line(line):
    line = line.replace('::', '_')
    line = line.replace('nullptr', 'NULL')
    if not skip_printing:
        if in_getRegisterName:
            f2.write(line + "\n")
        else:
            f1.write(line + "\n")


for line in lines:
    line = line.rstrip()
    #print("@", line)

    # skip Alias
    if arch.upper() == 'X86':
        if 'PRINT_ALIAS_INSTR' in line:
            # done
            break

    if skip_line:
        skip_count += 1
        if skip_count <= skip_line:
            # skip this line
            continue
        else:
            # skip enough number of lines, reset counters
            skip_line = 0
            skip_count = 0

    if "::printInstruction" in line:
        if arch.upper() in ('AARCH64', 'ARM64'):
            #print_line("static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI)\n{")
            print_line("static void printInstruction(MCInst *MI, SStream *O)\n{")
        else:
            print_line("static void printInstruction(MCInst *MI, SStream *O)\n{")
    elif 'LLVM_NO_PROFILE_INSTRUMENT_FUNCTION' in line:
        continue
    elif 'AArch64InstPrinter::getMnemonic' in line:
        print_line("static uint64_t getMnemonic(MCInst *MI, SStream *O, unsigned int opcode) {")
    elif 'return {AsmStrs+(Bits' in line:
        tmp = line.split(',')
        prntStr = tmp[0].split('{')[1]
        print_line("\tSStream_concat0(O, " + prntStr + ");")
        print_line("\treturn Bits;")
    elif 'MnemonicInfo = getMnemonic(' in line:
        continue
    elif 'O << MnemonicInfo' in line:
        continue
    elif 'uint64_t Bits = MnemonicInfo' in line:
        print_line("\tuint64_t Bits = getMnemonic(MI, O, opcode);")
    elif 'const char *AArch64InstPrinter::' in line:
        continue
    elif 'getRegisterName(' in line:
        if 'unsigned AltIdx' in line:
            print_line("static const char *getRegisterName(unsigned RegNo, unsigned AltIdx)\n{")
        else:
            print_line("static const char *getRegisterName(unsigned RegNo)\n{")
    elif 'getRegisterName' in line:
        in_getRegisterName = True
        print_line(line)
    elif '::printAliasInstr' in line:
        if arch.upper() in ('AARCH64', 'PPC'):
            print_line("static char *printAliasInstr(MCInst *MI, SStream *OS, MCRegisterInfo *MRI)\n{")
            print_line('  #define GETREGCLASS_CONTAIN(_class, _reg) MCRegisterClass_contains(MCRegisterInfo_getRegClass(MRI, _class), MCOperand_getReg(MCInst_getOperand(MI, _reg)))')
        else:
            print_line("static bool printAliasInstr(MCInst *MI, SStream *OS)\n{")
        print_line("  unsigned int I = 0, OpIdx, PrintMethodIdx;")
        print_line("  char *tmpString;")
        in_printAliasInstr = True
    elif 'STI.getFeatureBits()[' in line:
        if arch.upper() == 'ARM':
            line2 = line.replace('STI.getFeatureBits()[', 'ARM_getFeatureBits(MI->csh->mode, ')
        elif arch.upper() == 'AARCH64':
            line2 = line.replace('STI.getFeatureBits()[', 'AArch64_getFeatureBits(')
        line2 = line2.replace(']', ')')
        print_line(line2)
    elif 'lookupBTIByEncoding' in line:
        line = line.replace('AArch64BTIHint::', '')
        line = line.replace('MCOp.getImm()', 'MCOperand_getImm(MCOp)')
        print_line(line)
    elif 'lookupPSBByEncoding' in line:
        line = line.replace('AArch64PSBHint::', '')
        line = line.replace('MCOp.getImm()', 'MCOperand_getImm(MCOp)')
        print_line(line)
    elif ', STI, ' in line:
        line2 = line.replace(', STI, ', ', ')

        if 'printSVELogicalImm<' in line:
            if 'int16' in line:
                line2 = line2.replace('printSVELogicalImm', 'printSVELogicalImm16')
                line2 = line2.replace('<int16_t>', '')
            elif 'int32' in line: 
                line2 = line2.replace('printSVELogicalImm', 'printSVELogicalImm32')
                line2 = line2.replace('<int32_t>', '')
            else:
                line2 = line2.replace('printSVELogicalImm', 'printSVELogicalImm64')
                line2 = line2.replace('<int64_t>', '')

        if 'MI->getOperand(' in line:
            line2 = replace_getOp(line2)

        # C++ template
        if 'printPrefetchOp' in line2:
            param = extract_brackets(line2)
            if param == '':
                param = 'false'
            line2 = del_brackets(line2)
            line2 = line2.replace(', O);', ', O, %s);' %param)
            line2 = line2.replace(', OS);', ', OS, %s);' %param)
        elif '<false>' in line2:
            line2 = line2.replace('<false>', '')
            line2 = line2.replace(', O);', ', O, false);')
            line2 = line2.replace('STI, ', '')
        elif '<true>' in line:
            line2 = line2.replace('<true>', '')
            line2 = line2.replace(', O);', ', O, true);')
            line2 = line2.replace('STI, ', '')
        elif 'printAdrLabelOperand' in line:
            # C++ template
            if '<0>' in line:
                line2 = line2.replace('<0>', '')
                line2 = line2.replace(', O);', ', O, 0);')
            elif '<1>' in line:
                line2 = line2.replace('<1>', '')
                line2 = line2.replace(', O);', ', O, 1);')
            elif '<2>' in line:
                line2 = line2.replace('<2>', '')
                line2 = line2.replace(', O);', ', O, 2);')
        elif 'printImm8OptLsl' in line2:
            param = extract_brackets(line2)
            line2 = del_brackets(line2)
            if '8' in param or '16' in param or '32' in param:
                line2 = line2.replace('printImm8OptLsl', 'printImm8OptLsl32')
            elif '64' in param:
                line2 = line2.replace('printImm8OptLsl', 'printImm8OptLsl64')
        elif 'printLogicalImm' in line2:
            param = extract_brackets(line2)
            line2 = del_brackets(line2)
            if '8' in param or '16' in param or '32' in param:
                line2 = line2.replace('printLogicalImm', 'printLogicalImm32')
            elif '64' in param:
                line2 = line2.replace('printLogicalImm', 'printLogicalImm64')
        elif 'printSVERegOp' in line2 or 'printGPRSeqPairsClassOperand' in line2 or 'printTypedVectorList' in line2 or 'printPostIncOperand' in line2 or 'printImmScale' in line2 or 'printRegWithShiftExtend' in line2 or 'printUImm12Offset' in line2 or 'printExactFPImm' in line2 or 'printMemExtend' in line2 or 'printZPRasFPR' in line2 or 'printMatrixTileVector' in line2 or 'printMatrix<' in line2 or 'printSImm' in line2:
            param = extract_brackets(line2)
            if param == '':
                param = '0'
            line2 = del_brackets(line2)
            line2 = line2.replace(', O);', ', O, %s);' %param)
            line2 = line2.replace(', OS);', ', OS, %s);' %param)
        elif 'printComplexRotationOp' in line:
            # printComplexRotationOp<90, 0>(MI, 5, STI, O);
            bracket_content = line2[line2.index('<') + 1 : line2.index('>')]
            line2 = line2.replace('<' + bracket_content + '>', '')
            line2 = line2.replace(' O);', ' O, %s);' %bracket_content)
        elif 'printAlignedLabel' in line2 or 'printAdrpLabel' in line2:
            line2 = line2.replace('Address, ', '')

        print_line(line2)
    elif "static const char AsmStrs[]" in line:
        print_line("#ifndef CAPSTONE_DIET")
        print_line("  static const char AsmStrs[] = {")
        need_endif = True
    elif "static const char AsmStrsNoRegAltName[]" in line:
        print_line("#ifndef CAPSTONE_DIET")
        print_line("  static const char AsmStrsNoRegAltName[] = {")
        need_endif = True
    elif line == '  O << "\\t";':
        print_line("  unsigned int opcode = MCInst_getOpcode(MI);")
        print_line('  // printf("opcode = %u\\n", opcode);');
    elif 'MI->getOpcode()' in line:
        if 'switch' in line:
            line2 = line.replace('MI->getOpcode()', 'MCInst_getOpcode(MI)')
        else:
            line2 = line.replace('MI->getOpcode()', 'opcode')
        print_line(line2)

    elif 'O << ' in line:
        if '"' in line:
            line2 = line.lower()
            line2 = line2.replace('o << ', 'SStream_concat0(O, ');
        else:
            line2 = line.replace('O << ', 'SStream_concat0(O, ');
        line2 = line2.replace("'", '"')
        line2 = line2.replace(';', ');')
        if '" : "' in line2:    # "segment : offset" in X86
            line2 = line2.replace('" : "', '":"')

        # ARM
        print_line(line2)

        if '", #0"' in line2:
            print_line('    op_addImm(MI, 0);')

        if '", #1"' in line2:
            print_line('    op_addImm(MI, 1);')

        # PowerPC
        if '", 268"' in line2:
            print_line('    op_addImm(MI, 268);')

        elif '", 256"' in line2:
            print_line('    op_addImm(MI, 256);')

        elif '", 0, "' in line2 or '", 0"' in line2:
            print_line('    op_addImm(MI, 0);')

        elif '", -1"' in line2:
            print_line('    op_addImm(MI, -1);')
        

        if '], [' in line2 or ']!, [' in line2:
            print_line('    set_mem_access(MI, false);')
            print_line('    set_mem_access(MI, true);')
        
        elif "\"[\"" in line2:
            # Check for SME_Index specific string of only "["
            print_line('    set_sme_index(MI, true);')

        elif '[' in line2:
            if not '[]' in line2:
                print_line('    set_mem_access(MI, true);')

        elif ']' in line2:
            if not '[]' in line2:
                print_line('    set_mem_access(MI, false);')

        if '".f64\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F64);')
        elif '".f32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F32);')
        elif '".f16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F16);')
        elif '".s64\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_S64);')
        elif '".s32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_S32);')
        elif '".s16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_S16);')
        elif '".s8\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_S8);')
        elif '".u64\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_U64);')
        elif '".u32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_U32);')
        elif '".u16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_U16);')
        elif '".u8\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_U8);')
        elif '".i64\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_I64);')
        elif '".i32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_I32);')
        elif '".i16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_I16);')
        elif '".i8\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_I8);')
        elif '".f16.f64\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F16F64);')
        elif '".f64.f16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F64F16);')
        elif '".f16.f32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F16F32);')
        elif '".f32.f16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F32F16);')
        elif '".f64.f32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F64F32);')
        elif '".f32.f64\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F32F64);')
        elif '".s32.f32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_S32F32);')
        elif '".f32.s32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F32S32);')
        elif '".u32.f32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_U32F32);')
        elif '".f32.u32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F32U32);')
        elif '".p8\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_P8);')
        elif '".f64.s16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F64S16);')
        elif '".s16.f64\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_S16F64);')
        elif '".f32.s16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F32S16);')
        elif '".s16.f32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_S16F32);')
        elif '".f64.s32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F64S32);')
        elif '".s32.f64\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_S32F64);')
        elif '".f64.u16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F64U16);')
        elif '".u16.f64\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_U16F64);')
        elif '".f32.u16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F32U16);')
        elif '".u16.f32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_U16F32);')
        elif '".f64.u32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F64U32);')
        elif '".u32.f64\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_U32F64);')
        elif '".f16.u32\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F16U32);')
        elif '".u32.f16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_U32F16);')
        elif '".f16.u16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_F16U16);')
        elif '".u16.f16\\t"' in line2:
            print_line('    ARM_addVectorDataType(MI, ARM_VECTORDATA_U16F16);')
        elif '"\\tlr"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_LR);')
        elif '"\\tapsr_nzcv, fpscr"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_APSR_NZCV);')
            print_line('    ARM_addReg(MI, ARM_REG_FPSCR);')
        elif '"\\tpc, lr"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_PC);')
            print_line('    ARM_addReg(MI, ARM_REG_LR);')
        elif '"\\tfpscr, "' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_FPSCR);')
        elif '"\\tfpexc, "' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_FPEXC);')
        elif '"\\tfpinst, "' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_FPINST);')
        elif '"\\tfpinst2, "' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_FPINST2);')
        elif '"\\tfpsid, "' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_FPSID);')
        elif '"\\tsp, "' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_SP);')
        elif '"\\tsp!, "' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_SP);')
        elif '", apsr"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_APSR);')
        elif '", spsr"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_SPSR);')
        elif '", fpscr"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_FPSCR);')
        elif '", fpscr"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_FPSCR);')
        elif '", fpexc"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_FPEXC);')
        elif '", fpinst"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_FPINST);')
        elif '", fpinst2"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_FPINST2);')
        elif '", fpsid"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_FPSID);')
        elif '", mvfr0"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_MVFR0);')
        elif '", mvfr1"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_MVFR1);')
        elif '", mvfr2"' in line2:
            print_line('    ARM_addReg(MI, ARM_REG_MVFR2);')
        elif '.8\\t' in line2:
            print_line('    ARM_addVectorDataSize(MI, 8);')
        elif '.16\\t' in line2:
            print_line('    ARM_addVectorDataSize(MI, 16);')
        elif '.32\\t' in line2:
            print_line('    ARM_addVectorDataSize(MI, 32);')
        elif '.64\\t' in line2:
            print_line('    ARM_addVectorDataSize(MI, 64);')
        elif '" ^"' in line2:
            print_line('    ARM_addUserMode(MI);')

        if '.16b' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_16B);')
        elif '.8b' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_8B);')
        elif '.4b' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_4B);')
        elif '.b' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1B);')
        elif '.8h' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_8H);')
        elif '.4h' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_4H);')
        elif '.2h' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_2H);')
        elif '.h' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1H);')
        elif '.4s' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_4S);')
        elif '.2s' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_2S);')
        elif '.s' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1S);')
        elif '.2d' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_2D);')
        elif '.1d' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1D);')
        elif '.1q' in line2:
            print_line('    arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1Q);')

        if '#0.0' in line2:
            print_line('    arm64_op_addFP(MI, 0);')
        elif '#0' in line2:
            print_line('    arm64_op_addImm(MI, 0);')
        elif '#8' in line2:
            print_line('    arm64_op_addImm(MI, 8);')
        elif '#16' in line2:
            print_line('    arm64_op_addImm(MI, 16);')
        elif '#32' in line2:
            print_line('    arm64_op_addImm(MI, 32);')

        # X86
        if '", %rax"' in line2 or '", rax"' in line2:
            print_line('    op_addReg(MI, X86_REG_RAX);')
        elif '", %eax"' in line2 or '", eax"' in line2:
            print_line('    op_addReg(MI, X86_REG_EAX);')
        elif '", %ax"' in line2 or '", ax"' in line2:
            print_line('    op_addReg(MI, X86_REG_AX);')
        elif '", %al"' in line2 or '", al"' in line2:
            print_line('    op_addReg(MI, X86_REG_AL);')
        elif '", %dx"' in line2 or '", dx"' in line2:
            print_line('    op_addReg(MI, X86_REG_DX);')
        elif '", %st(0)"' in line2 or '", st(0)"' in line2:
            print_line('    op_addReg(MI, X86_REG_ST0);')
        elif '", 1"' in line2:
            print_line('    op_addImm(MI, 1);')
        elif '", cl"' in line2:
            print_line('    op_addReg(MI, X86_REG_CL);')
        elif '"{1to2}, "' in line2:
            print_line('    op_addAvxBroadcast(MI, X86_AVX_BCAST_2);')
        elif '"{1to4}, "' in line2:
            print_line('    op_addAvxBroadcast(MI, X86_AVX_BCAST_4);')
        elif '"{1to8}, "' in line2:
            print_line('    op_addAvxBroadcast(MI, X86_AVX_BCAST_8);')
        elif '"{1to16}, "' in line2:
            print_line('    op_addAvxBroadcast(MI, X86_AVX_BCAST_16);')
        elif '{z}{sae}' in line2:
            print_line('    op_addAvxSae(MI);')
            print_line('    op_addAvxZeroOpmask(MI);')
        elif ('{z}' in line2):
            print_line('    op_addAvxZeroOpmask(MI);')
        elif '{sae}' in line2:
            print_line('    op_addAvxSae(MI);')
    elif 'llvm_unreachable("Invalid command number.");' in line:
        line2 = line.replace('llvm_unreachable("Invalid command number.");', '// unreachable')
        print_line(line2)
    elif ('assert(' in line) or ('assert (' in line):
        pass
    elif 'Invalid alt name index' in line:
        pass
    elif '::' in line and 'case ' in line:
        #print_line(line2)
        print_line(line)
    elif 'MI->getNumOperands()' in line:
        line2 = line.replace('MI->getNumOperands()', 'MCInst_getNumOperands(MI)')
        print_line(line2)
    elif 'const MCOperand &MCOp' in line:
        line2 = line.replace('const MCOperand &MCOp', 'MCOperand *MCOp')
        print_line(line2)
    elif 'MI->getOperand(0).isImm()' in line:
        line2 = line.replace('MI->getOperand(0).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 0))')
        print_line(line2)
    elif 'MI->getOperand(1).isImm()' in line:
        line2 = line.replace('MI->getOperand(1).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 1))')
        print_line(line2)
    elif 'MI->getOperand(2).isImm()' in line:
        line2 = line.replace('MI->getOperand(2).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 2))')
        print_line(line2)
    elif 'MI->getOperand(3).isImm()' in line:
        line2 = line.replace('MI->getOperand(3).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 3))')
        print_line(line2)
    elif 'MI->getOperand(4).isImm()' in line:
        line2 = line.replace('MI->getOperand(4).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 4))')
        print_line(line2)
    elif 'MI->getOperand(5).isImm()' in line:
        line2 = line.replace('MI->getOperand(5).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 5))')
        print_line(line2)
    elif 'MI->getOperand(6).isImm()' in line:
        line2 = line.replace('MI->getOperand(6).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 6))')
        print_line(line2)
    elif 'MI->getOperand(7).isImm()' in line:
        line2 = line.replace('MI->getOperand(7).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 7))')
        print_line(line2)
    elif 'MI->getOperand(8).isImm()' in line:
        line2 = line.replace('MI->getOperand(8).isImm()', 'MCOperand_isImm(MCInst_getOperand(MI, 8))')
        print_line(line2)
    elif 'MI->getOperand(0).getImm()' in line:
        line2 = line.replace('MI->getOperand(0).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 0))')
        print_line(line2)
    elif 'MI->getOperand(1).getImm()' in line:
        line2 = line.replace('MI->getOperand(1).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 1))')
        print_line(line2)
    elif 'MI->getOperand(2).getImm()' in line:
        line2 = line.replace('MI->getOperand(2).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 2))')
        print_line(line2)
    elif 'MI->getOperand(3).getImm()' in line:
        line2 = line.replace('MI->getOperand(3).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 3))')
        print_line(line2)
    elif 'MI->getOperand(4).getImm()' in line:
        line2 = line.replace('MI->getOperand(4).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 4))')
        print_line(line2)
    elif 'MI->getOperand(5).getImm()' in line:
        line2 = line.replace('MI->getOperand(5).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 5))')
        print_line(line2)
    elif 'MI->getOperand(6).getImm()' in line:
        line2 = line.replace('MI->getOperand(6).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 6))')
        print_line(line2)
    elif 'MI->getOperand(7).getImm()' in line:
        line2 = line.replace('MI->getOperand(7).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 7))')
        print_line(line2)
    elif 'MI->getOperand(8).getImm()' in line:
        line2 = line.replace('MI->getOperand(8).getImm()', 'MCOperand_getImm(MCInst_getOperand(MI, 8))')
        print_line(line2)
    elif 'MRI.getRegClass(' in line:
        classid = extract_paren(line, 'getRegClass(')
        operand = extract_paren(line, 'getOperand')
        line2 = line.replace('MI->getNumOperands()', 'MCInst_getNumOperands(MI)')
        line2 = '        GETREGCLASS_CONTAIN(%s, %s)' %(classid, operand)
        if line.endswith('())) {'):
            line2 += ') {'
        elif line.endswith(' {'):
            line2 += ' {'
        elif line.endswith(' &&'):
            line2 += ' &&'
        print_line(line2)
    elif 'MI->getOperand(' in line and 'isReg' in line:
        operand = extract_paren(line, 'getOperand')
        line2 = '        MCOperand_isReg(MCInst_getOperand(MI, %s))' %(operand)
        # MI->getOperand(1).isReg() &&
        if line.endswith(' {'):
            line2 += ' {'
        elif line.endswith(' &&'):
            line2 += ' &&'
        print_line(line2)
    elif 'MI->getOperand(' in line and 'getReg' in line:
        line2 = replace_getReg(line)
        # one more time
        line2 = replace_getReg(line2)
        print_line(line2)
    elif '    return false;' in line and in_printAliasInstr:
        print_line('    return NULL;')
    elif 'MCOp.isImm()' in line:
        line2 = line.replace('MCOp.isImm()', 'MCOperand_isImm(MCOp)')
        print_line(line2)
    elif 'MCOp.getImm()' in line:
        line2 = line.replace('MCOp.getImm()', 'MCOperand_getImm(MCOp)')
        if 'int64_t Val =' in line:
            line2 = line2.replace('int64_t Val =', 'Val =')
        print_line(line2)
    elif 'isSVEMaskOfIdenticalElements<' in line:
        if 'int8' in line:
            line2 = line.replace('isSVEMaskOfIdenticalElements', 'isSVEMaskOfIdenticalElements8')
            line2 = line2.replace('<int8_t>', '')
        elif 'int16' in line:
            line2 = line.replace('isSVEMaskOfIdenticalElements', 'isSVEMaskOfIdenticalElements16')
            line2 = line2.replace('<int16_t>', '')
        elif 'int32' in line: 
            line2 = line.replace('isSVEMaskOfIdenticalElements', 'isSVEMaskOfIdenticalElements32')
            line2 = line2.replace('<int32_t>', '')
        else:
            line2 = line.replace('isSVEMaskOfIdenticalElements', 'isSVEMaskOfIdenticalElements64')
            line2 = line2.replace('<int64_t>', '')
        print_line(line2)
    elif 'switch (PredicateIndex) {' in line:
        print_line('  int64_t Val;')
        print_line(line)
    elif 'uint32_t(' in line and in_printAliasInstr:
        line = line.replace('uint32_t(', '')
        line = line.replace(')', '')
        print_line(line)
    elif '#ifndef NDEBUG' in line and in_printAliasInstr:
        print_line("""
  char *AsmString;
  const size_t OpToSize = sizeof(OpToPatterns) / sizeof(PatternsForOpcode);

  const unsigned opcode = MCInst_getOpcode(MI);

  // Check for alias
  int OpToIndex = 0;
  for(int i = 0; i < OpToSize; i++){
    if(OpToPatterns[i].Opcode == opcode){
      OpToIndex = i;
      break;
    }
  }
  // Check for match
  if(opcode != OpToPatterns[OpToIndex].Opcode)
    return NULL;

  const PatternsForOpcode opToPat = OpToPatterns[OpToIndex];

  // Try all patterns for this opcode
  uint32_t AsmStrOffset = ~0U;
  int patIdx = opToPat.PatternStart;
  while(patIdx < (opToPat.PatternStart + opToPat.NumPatterns)){
    // Check operand count first
    if(MCInst_getNumOperands(MI) != Patterns[patIdx].NumOperands)
      return NULL;
    
    // Test all conditions for this pattern
    int condIdx = Patterns[patIdx].AliasCondStart;
    int opIdx = 0;
    bool allPass = true;
    while(condIdx < (Patterns[patIdx].AliasCondStart + Patterns[patIdx].NumConds)){
      MCOperand *opnd = MCInst_getOperand(MI, opIdx);
      opIdx++;
      // Not concerned with any Feature related conditions as STI is disregarded
      switch (Conds[condIdx].Kind)
      {
      case AliasPatternCond_K_Ignore :
        // Operand can be anything.
        break;
      case AliasPatternCond_K_Reg :
        // Operand must be a specific register.
        allPass = allPass && (MCOperand_isReg(opnd) && MCOperand_getReg(opnd) == Conds[condIdx].Value);
        break;
      case AliasPatternCond_K_TiedReg :
        // Operand must match the register of another operand.
        allPass = allPass && (MCOperand_isReg(opnd) && MCOperand_getReg(opnd) == 
                  MCOperand_getReg(MCInst_getOperand(MI, Conds[condIdx].Value)));
        break;
      case AliasPatternCond_K_Imm :
        // Operand must be a specific immediate.
        allPass = allPass && (MCOperand_isImm(opnd) && MCOperand_getImm(opnd) == Conds[condIdx].Value);
        break;
      case AliasPatternCond_K_RegClass :
        // Operand must be a register in this class. Value is a register class id.
        allPass = allPass && (MCOperand_isReg(opnd) && GETREGCLASS_CONTAIN(Conds[condIdx].Value, (opIdx-1)));
        break;
      case AliasPatternCond_K_Custom :
        // Operand must match some custom criteria.
        allPass = allPass && AArch64InstPrinterValidateMCOperand(opnd, Conds[condIdx].Value);
        break;
      case AliasPatternCond_K_Feature :
      case AliasPatternCond_K_NegFeature :
      case AliasPatternCond_K_OrFeature :
      case AliasPatternCond_K_OrNegFeature :
      case AliasPatternCond_K_EndOrFeatures :
      default :
        break;
      }
      condIdx++;
    }
    if(allPass){
      AsmStrOffset = Patterns[patIdx].AsmStrOffset;
      break;
    }
    patIdx++;
  }

  // If no alias matched, don't print an alias.
  if (AsmStrOffset == ~0U)
    return NULL;

  AsmString = cs_strdup(&AsmStrings[AsmStrOffset]);

  tmpString = cs_strdup(AsmString);

  while (AsmString[I] != ' ' && AsmString[I] != '\\t' &&
        AsmString[I] != '$' && AsmString[I] != '\\0')
    ++I;

  tmpString[I] = 0;
  SStream_concat0(OS, tmpString);

  if (AsmString[I] != '\\0') {
    if (AsmString[I] == ' ' || AsmString[I] == '\\t') {
      SStream_concat0(OS, " ");
      ++I;
    }

    bool isSME = false;
    do {
      if (AsmString[I] == '$') {
        ++I;
        if (AsmString[I] == (char)0xff) {
          ++I;
          OpIdx = AsmString[I++] - 1;
          PrintMethodIdx = AsmString[I++] - 1;
          printCustomAliasOperand(MI, 0, OpIdx, PrintMethodIdx, OS);
        } else
          printOperand(MI, (unsigned)(AsmString[I++]) - 1, OS);
      } else {
        if (AsmString[I] == '[') {
          if (AsmString[I-1] != ' ') {
            set_sme_index(MI, true);
            isSME = true;
          } else {
            set_mem_access(MI, true);
          }
        } else if (AsmString[I] == ']') {
          if (isSME) {
            set_sme_index(MI, false);
            isSME = false;
          } else {
            set_mem_access(MI, false);
          }
        }
        SStream_concat1(OS, AsmString[I++]);
      }
    } while (AsmString[I] != '\\0');
  }
  cs_mem_free(AsmString);
  return tmpString;
}
        """)
        in_printAliasInstr = False
        # skip next few lines
        skip_printing = True
    elif '::printCustomAliasOperand' in line:
        # print again
        skip_printing = False
        print_line('static void printCustomAliasOperand(')
    elif 'const MCSubtargetInfo &STI' in line:
        pass
    elif 'const MCInst *MI' in line:
        line2 = line.replace('const MCInst *MI', 'MCInst *MI')
        print_line(line2)
    elif 'llvm_unreachable("' in line:
        if 'default: ' in line:
            print_line('  default:')
        elif 'llvm_unreachable("Unknown MCOperandPredicate kind")' in line:
            print_line('    return false; // never reach')
        else:
            pass
    elif 'raw_ostream &' in line:
        line2 = line.replace('raw_ostream &', 'SStream *')
        if line2.endswith(' {'):
            line2 = line2.replace(' {', '\n{')
        print_line(line2)
    elif 'printPredicateOperand(' in line and 'STI, ' in line:
        line2 = line.replace('STI, ', '')
        print_line(line2)
    elif '// Fragment ' in line:
        # // Fragment 0 encoded into 6 bits for 51 unique commands.
        tmp = line.strip().split(' ')
        fragment_no = tmp[2]
        print_line(line)
    elif ('switch ((' in line or 'if ((' in line) and 'Bits' in line:
        # switch ((Bits >> 14) & 63) {
        bits = line.strip()
        bits = bits.replace('switch ', '')
        bits = bits.replace('if ', '')
        bits = bits.replace('{', '')
        bits = bits.strip()
        print_line('  // printf("Fragment %s: %%"PRIu64"\\n", %s);' %(fragment_no, bits))
        print_line(line)
    elif not skip_printing:
        print_line(line)

    if line == '  };':
        if need_endif and not in_getRegisterName:
            # endif only for AsmStrs when we are not inside getRegisterName()
            print_line("#endif")
            need_endif = False
    elif 'return AsmStrs+RegAsmOffset[RegNo-1];' in line:
        if in_getRegisterName:
            # return NULL for register name on Diet mode
            print_line("#else")
            print_line("  return NULL;")
            print_line("#endif")
            print_line("}")
            need_endif = False
            in_getRegisterName = False
            # skip 1 line
            skip_line = 1
    elif line == '  }':
        # ARM64
        if in_getRegisterName:
            # return NULL for register name on Diet mode
            print_line("#else")
            print_line("  return NULL;")
            print_line("#endif")
            print_line("}")
            need_endif = False
            in_getRegisterName = False
            # skip 1 line
            skip_line = 1
    elif 'default:' in line:
        # ARM64
        if in_getRegisterName:
            # get the size of RegAsmOffsetvreg[]
            print_line("    return (const char *)(sizeof(RegAsmOffsetvreg)/sizeof(RegAsmOffsetvreg[0]));")


f1.close()
f2.close()
