// File: /workspace/github_c_makefile_star2_O3/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, %r15
movq %rdi, %rbx
leaq 0x24a9(%rip), %rdi      # 0x613f
movq %rdx, %rsi
xorl %eax, %eax
callq 0x30d0
cmpb $0x0, 0x8491(%rip)      # 0xc138
jne 0x3d4b
cmpb $0x0, 0x8485(%rip)      # 0xc139
jne 0x3d4b
testq %r14, %r14
js 0x3cc6
cvtsi2ss %r14, %xmm0
jmp 0x3cde
movq %r14, %rax
shrq %rax
movl %r14d, %ecx
andl $0x1, %ecx
orq %rax, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
callq 0x3180
cvttss2si %xmm0, %r13d
testb %r12b, %r12b
je 0x3d2c
movzbl %r13b, %eax
movzbl 0x8448(%rip), %ecx      # 0xc140
decl %ecx
cmpl %eax, %ecx
jle 0x3d20
incb %r13b
movl $0x2d, %edi
callq 0x3040
movzbl %r13b, %eax
movzbl 0x842a(%rip), %ecx      # 0xc140
decl %ecx
leal 0x1(%rax), %r13d
cmpl %eax, %ecx
jg 0x3d01
movl $0x3e, %edi
callq 0x3040
jmp 0x3d4b
cmpb %r13b, 0x840d(%rip)     # 0xc140
jbe 0x3d4b
movl $0x20, %edi
callq 0x3040
incb %r13b
cmpb 0x83f7(%rip), %r13b     # 0xc140
jb 0x3d35
testb %bpl, %bpl
jne 0x3dfb
movq (%rbx), %rsi
leaq 0x2aee(%rip), %rdi      # 0x684c
xorl %r13d, %r13d
xorl %eax, %eax
callq 0x30d0
leaq 0x23d7(%rip), %rdi      # 0x6146
xorl %eax, %eax
callq 0x30d0
cmpq $0x0, 0x8(%rbx)
je 0x3dd7
movq %r15, 0x10(%rsp)
movl %ebp, 0xc(%rsp)
movb $0x1, %r15b
leaq 0x23ba(%rip), %r12      # 0x614a
xorl %ebp, %ebp
movb 0x10(%rbx,%rbp), %al
cmpb $0xf, %al
ja 0x3da8
movl $0x30, %edi
callq 0x3040
movb 0x10(%rbx,%rbp), %al
movzbl %al, %esi
movq %r12, %rdi
xorl %eax, %eax
callq 0x30d0
movzbl %r15b, %ebp
movq 0x8(%rbx), %r13
movl %ebp, %r15d
incb %r15b
cmpq %rbp, %r13
ja 0x3d92
cmpq $0x7, %r13
movl 0xc(%rsp), %ebp
movq 0x10(%rsp), %r15
ja 0x3df1
addb $-0x8, %r13b
leaq 0x236c(%rip), %r12      # 0x614e
movq %r12, %rdi
xorl %eax, %eax
callq 0x30d0
incb %r13b
jne 0x3de2
movl $0x9, %edi
callq 0x3040
cmpq $0x2, 0x8(%rbx)
jne 0x3e2a
cmpb $0xf, 0x10(%rbx)
jne 0x3e2a
cmpb $0x5, 0x11(%rbx)
jne 0x3e2a
movq %r15, %rdi
callq 0x4e13
incq %r14
cmpq %rax, %r14
jbe 0x3f02
xorl %r14d, %r14d
jmp 0x3f20
movl $0xa, %edi
callq 0x3040
cmpb $0x1, 0x82fd(%rip)      # 0xc138
jne 0x3ed4
cmpq $0x0, 0x20(%rbx)
je 0x3ed4
leaq 0x28(%rbx), %r15
movl $0x1, %ebp
leaq 0x82ec(%rip), %r13      # 0xc148
leaq 0x2324(%rip), %r14      # 0x6187
xorl %r12d, %r12d
movl $0x9, %edi
callq 0x3040
shlq $0x5, %r12
cmpl $0x0, 0x14(%r15,%r12)
leaq 0x22e9(%rip), %rdi      # 0x616a
leaq 0x22f1(%rip), %rax      # 0x6179
cmoveq %rax, %rdi
xorl %eax, %eax
callq 0x30d0
cmpl $0x0, 0x14(%r15,%r12)
movl 0x10(%r15,%r12), %esi
movq %r13, %rax
leaq 0x82a8(%rip), %rcx      # 0xc150
cmoveq %rcx, %rax
addq %rsi, (%rax)
movq (%r15,%r12), %rdx
movq %r14, %rdi
xorl %eax, %eax
callq 0x30d0
cmpl $0x2, 0x14(%r15,%r12)
jae 0x3f5d
movl %ebp, %r12d
incl %ebp
cmpq %r12, 0x20(%rbx)
ja 0x3e66
cmpb $0x1, 0x825e(%rip)      # 0xc139
jne 0x3ef3
movq %rbx, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x56cf
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
movq %r15, %rsi
callq 0x551a
movq 0x130(%rax), %rcx
movq 0x38(%rcx), %r14
movq %rax, %rdi
callq 0x570e
movq 0x130(%rbx), %rdi
movzbl %bpl, %edx
movq %r14, %rsi
callq 0x49d0
testl %eax, %eax
je 0x3f45
leaq 0x2214(%rip), %rdi      # 0x6152
xorl %eax, %eax
callq 0x30d0
movl $0xa, %edi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3040
callq 0x335b