#!/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 '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 ', 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:
            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)

        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:
            if not '[]' in line2:
                print_line('    set_mem_access(MI, true);')

        if ']' 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 'unsigned I = 0;' in line and in_printAliasInstr:
        print_line("""
  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;
    }

    do {
      if (AsmString[I] == '$') {
        ++I;
        if (AsmString[I] == (char)0xff) {
          ++I;
          OpIdx = AsmString[I++] - 1;
          PrintMethodIdx = AsmString[I++] - 1;
          printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, OS);
        } else
            printOperand(MI, (unsigned)(AsmString[I++]) - 1, OS);
      } else {
          SStream_concat1(OS, AsmString[I++]);
      }
    } while (AsmString[I] != '\\0');
  }

  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()
