// File: /workspace/github_c_makefile_star2_O2/melynx[P]peekaboo/read_trace.c
// Function: print_peekaboo_insn
void print_peekaboo_insn(peekaboo_insn_t *insn, 
                         peekaboo_trace_t *peekaboo_trace_ptr, 
                         const size_t insn_idx,
                         const bool target,
                         const bool print_syscall_info)
{
    // Print instruction index
    printf("[%lu] ", insn_idx);

    if (!print_memory && !print_register)
        if (target) 
        {
            for (uint8_t idx = (uint8_t)log10f(insn_idx); idx < digits - 1; idx++) printf("-");
            printf(">");
        }
        else
            for (uint8_t idx = (uint8_t)log10f(insn_idx); idx < digits; idx++) printf(" ");

    if (!print_syscall_info)
    {
        // Print instruction ea
        printf("0x%"PRIx64"", insn->addr);
            
        // Print Rawbytes
        printf(":\t ");

        for (uint8_t rawbyte_idx = 0; rawbyte_idx < insn->size; rawbyte_idx++)
        {
            if (insn->rawbytes[rawbyte_idx] < 16) printf("0");
            printf("%"PRIx8" ", insn->rawbytes[rawbyte_idx]);
        }
        
        // Pretty print 
        for (uint8_t idx = insn->size; idx < 8; idx++) printf("   ");
        printf("\t");
    }


    // Is this syscall?
    if (insn->size == 2 && insn->rawbytes[0]=='\x0f' && insn->rawbytes[1]=='\x05')
    {
        // Yes, syscall. Print it!
        size_t trace_length = get_num_insn(peekaboo_trace_ptr);
        size_t next_insn_idx = insn_idx + 1;
        const regfile_amd64_t *regfile_ptr = (regfile_amd64_t *) insn->regfile;
        uint64_t rvalue;
        if (next_insn_idx > trace_length)
            rvalue = 0;
        else
        {
            peekaboo_insn_t *next_insn = get_peekaboo_insn(next_insn_idx, peekaboo_trace_ptr);
            regfile_ptr = (regfile_amd64_t *) next_insn->regfile;
            rvalue = regfile_ptr->gpr.reg_rax;
            free_peekaboo_insn(next_insn);
        }
        if (0!=amd64_syscall_pp(insn->regfile, rvalue, print_syscall_info))
        {
            // Syscall analysis failed.
            printf("Syscall analysis failed");
        }
        printf("\n");
        return;
    }

    // Print disassemble for instructions using libopcodes
    #ifdef ASM
    {
        // Disasmble the instruction
        int rvalue = disassemble_raw((enum ARCH)peekaboo_trace_ptr->internal->arch, false, insn->rawbytes, insn->size);
        if(rvalue != 0) PEEKABOO_DIE("Libopcodes disasm error!\n");
    }
    #else 
    #ifdef ASM_CAPSTONE
    {
        cs_insn *capstone_insn;
        size_t count = cs_disasm(capstone_handler, insn->rawbytes, insn->size, insn->addr, 0, &capstone_insn);
        if (count == 0)
        {
            printf("Capstone Error");
        }
        else
        {
            printf("%s\t%s", capstone_insn[0].mnemonic, capstone_insn[0].op_str);
            cs_free(capstone_insn, count);
        }
    }
    #endif //ASM_CAPSTONE
    #endif // ASM
    printf("\n");

    // Print memory ops
    if (print_memory && (insn->num_mem > 0))
    {
        for (uint32_t mem_idx = 0; mem_idx < insn->num_mem; mem_idx++)
        {
            printf("\t");
            printf(insn->mem[mem_idx].status ? "Memory Write: " : "Memory Read: ");
            if (insn->mem[mem_idx].status) 
                write_bytes+=insn->mem[mem_idx].size; 
            else
                read_bytes+=insn->mem[mem_idx].size; 
            printf("%d bytes @ 0x%lx\n", insn->mem[mem_idx].size, insn->mem[mem_idx].addr);

            // Memory trace broken checker
            if (!(insn->mem[mem_idx].status==0 || insn->mem[mem_idx].status==1)) 
                PEEKABOO_DIE("Abort! Broken memrefs_offsets. Remove memrefs_offsets in trace folder and try again.");
        }
    }

    // Print GPR
    if (print_register) regfile_pp(insn);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %r8d, %ebp
movl %ecx, %r12d
movq %rdx, %r14
movq %rsi, %r13
movq %rdi, %rbx
leaq 0x2aad(%rip), %rdi      # 0x613f
movq %rdx, %rsi
xorl %eax, %eax
callq 0x30d0
cmpb $0x0, 0x7a95(%rip)      # 0xb138
jne 0x3729
cmpb $0x0, 0x7a89(%rip)      # 0xb139
jne 0x3729
testq %r14, %r14
js 0x36be
cvtsi2ss %r14, %xmm0
jmp 0x36d6
movq %r14, %rax
shrq %rax
movl %r14d, %ecx
andl $0x1, %ecx
orq %rax, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
callq 0x3180
cvttss2si %xmm0, %r15d
testb %r12b, %r12b
je 0x3707
pushq $0x2d
popq %r12
movzbl %r15b, %eax
movzbl 0x7a4c(%rip), %ecx      # 0xb140
decl %ecx
cmpl %eax, %ecx
jle 0x3721
movl %r12d, %edi
callq 0x3040
incb %r15b
jmp 0x36e9
pushq $0x20
popq %r12
cmpb 0x7a2e(%rip), %r15b     # 0xb140
jae 0x3729
movl %r12d, %edi
callq 0x3040
incb %r15b
jmp 0x370b
pushq $0x3e
popq %rdi
callq 0x3040
testb %bpl, %bpl
jne 0x37ca
movq %r13, 0x10(%rsp)
movl %ebp, 0xc(%rsp)
movq (%rbx), %rsi
leaq 0x3107(%rip), %rdi      # 0x684c
xorl %r15d, %r15d
xorl %eax, %eax
callq 0x30d0
leaq 0x29f0(%rip), %rdi      # 0x6146
xorl %eax, %eax
callq 0x30d0
pushq $0x30
popq %r12
leaq 0x29e2(%rip), %r13      # 0x614a
movzbl %r15b, %r15d
movq 0x8(%rbx), %rbp
cmpq %r15, %rbp
jbe 0x379d
movb 0x10(%rbx,%r15), %al
cmpb $0xf, %al
ja 0x378b
movl %r12d, %edi
callq 0x3040
movb 0x10(%rbx,%r15), %al
movzbl %al, %esi
movq %r13, %rdi
xorl %eax, %eax
callq 0x30d0
incb %r15b
jmp 0x3768
leaq 0x29aa(%rip), %r12      # 0x614e
movq 0x10(%rsp), %r13
cmpb $0x8, %bpl
jae 0x37be
movq %r12, %rdi
xorl %eax, %eax
callq 0x30d0
incb %bpl
jmp 0x37a9
pushq $0x9
popq %rdi
callq 0x3040
movl 0xc(%rsp), %ebp
cmpq $0x2, 0x8(%rbx)
jne 0x37f9
cmpb $0xf, 0x10(%rbx)
jne 0x37f9
cmpb $0x5, 0x11(%rbx)
jne 0x37f9
movq %r13, %rdi
callq 0x48bc
incq %r14
cmpq %rax, %r14
jbe 0x38ec
xorl %r14d, %r14d
jmp 0x390a
pushq $0xa
popq %rdi
callq 0x3040
cmpb $0x1, 0x7930(%rip)      # 0xb138
jne 0x38be
cmpq $0x0, 0x20(%rbx)
je 0x38be
leaq 0x28(%rbx), %r15
xorl %r12d, %r12d
leaq 0x7929(%rip), %rbp      # 0xb150
leaq 0x2959(%rip), %r14      # 0x6187
movl %r12d, %r12d
cmpq %r12, 0x20(%rbx)
jbe 0x38be
pushq $0x9
popq %rdi
callq 0x3040
movq %r12, %r13
shlq $0x5, %r13
cmpl $0x0, 0x14(%r15,%r13)
leaq 0x2922(%rip), %rdi      # 0x6179
je 0x3860
leaq 0x290a(%rip), %rdi      # 0x616a
xorl %eax, %eax
callq 0x30d0
cmpl $0x0, 0x14(%r15,%r13)
movl 0x10(%r15,%r13), %esi
movq %rbp, %rax
je 0x387e
leaq 0x78ca(%rip), %rax      # 0xb148
addq %rsi, (%rax)
movq (%r15,%r13), %rdx
movq %r14, %rdi
xorl %eax, %eax
callq 0x30d0
incl %r12d
cmpl $0x2, 0x14(%r15,%r13)
jb 0x382e
movq 0x7757(%rip), %rax      # 0xaff8
movq (%rax), %rcx
leaq 0x28ee(%rip), %rdi      # 0x6199
pushq $0x54
popq %rsi
pushq $0x1
popq %rdx
callq 0x3230
pushq $0x1
popq %rdi
callq 0x3220
cmpb $0x1, 0x7874(%rip)      # 0xb139
jne 0x38dd
movq %rbx, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x524d
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
movq %r13, %rsi
callq 0x5074
movq 0x130(%rax), %rcx
movq 0x38(%rcx), %r14
movq %rax, %rdi
callq 0x52ab
movq 0x130(%rbx), %rdi
movzbl %bpl, %edx
movq %r14, %rsi
callq 0x4450
testl %eax, %eax
je 0x392f
leaq 0x282a(%rip), %rdi      # 0x6152
xorl %eax, %eax
callq 0x30d0
pushq $0xa
popq %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3040