// File: /workspace/github_cpp_makefile_star2_O1/helchr[P]reMap/main.cpp
// Function: setupMeasure(int, unsigned int, unsigned int, unsigned int, bool)
int setupMeasure(int cpuid, unsigned int channel,unsigned int rank, unsigned int bank, bool bankGroup=false)
{
    struct perf_event_attr pe;
    int fd;

    memset(&pe, 0, sizeof(struct perf_event_attr));

    auto imcs = SysInfo::getImcs();
    if(imcs.size() == 0)
    {
        std::cout << "No memory controller PMU found" << std::endl;
        exit(EXIT_FAILURE);
    }
    auto imc = imcs[channel];
    pe.type = SysInfo::getTypeOfImc(imc);
    pe.size = sizeof(struct perf_event_attr);
    //pe.config = (0b11 << 8) | 0x04; // CAS_COUNT_READ
    //pe.config = (0b00001100 << 8) | 0x04; // CAS_COUNT_WR
    //unsigned int bankBits = 0b00010000;//all banks
    unsigned int bankBits = 0;
    if(bankGroup==true)
    {
        bankBits = 0b00010001 + bank;
    }
    else
    {
        bankBits = bank;
    }
    bankBits = bankBits << 8;
    auto rankBits = 0xb0 + rank;
    auto bits = bankBits | rankBits;
    pe.config = bits ; //umask first followed by event id
    // exact config is in cat /sys/devices/cpu/format/event
    pe.disabled = 1;
    pe.sample_type=PERF_SAMPLE_IDENTIFIER;
    pe.inherit=0;
    pe.exclude_guest=1;

    //how to get per-socket numbers? choose the cpu id in syscall
    //pid = -1 cpu >= 0 -> global measurement
    fd = perf_event_open(&pe, -1, cpuid, -1, 0);
    if (fd == -1) {
        std::cout << "Setup of performance counters failed" << std::endl;
        exit(EXIT_FAILURE);
    }

    return fd;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movl %r8d, %ebp
movl %ecx, %r15d
movl %edx, %r14d
movl %esi, %r12d
movl %edi, %ebx
xorps %xmm0, %xmm0
movaps %xmm0, 0xb0(%rsp)
movaps %xmm0, 0xa0(%rsp)
movaps %xmm0, 0x90(%rsp)
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x70(%rsp)
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
leaq 0x28(%rsp), %r13
movq %r13, %rdi
callq 0xdf24
movq (%r13), %rax
cmpq %rax, 0x8(%r13)
je 0x8043
movl %r12d, %ecx
shlq $0x5, %rcx
leaq 0x18(%rsp), %r12
movq %r12, -0x10(%r12)
movq (%rax,%rcx), %rsi
movq 0x8(%rax,%rcx), %rdx
addq %rsi, %rdx
leaq 0x8(%rsp), %rdi
callq 0xb118
leaq 0x8(%rsp), %rdi
callq 0xe37e
leaq 0x40(%rsp), %rsi
movl %eax, (%rsi)
movl $0x80, 0x4(%rsi)
shll $0x8, %r15d
leal 0x1100(%r15), %eax
testb %bpl, %bpl
cmovel %r15d, %eax
addl $0xb0, %r14d
orl %eax, %r14d
movq %r14, 0x8(%rsi)
movq 0x28(%rsi), %rax
orq $0x1, %rax
movq $0x10000, 0x18(%rsi)    # imm = 0x10000
andq $-0x100003, %rax        # imm = 0xFFEFFFFD
orq $0x100000, %rax         # imm = 0x100000
movq %rax, 0x28(%rsi)
movl $0x12a, %edi            # imm = 0x12A
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl %ebx, %ecx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
xorl %r9d, %r9d
xorl %eax, %eax
callq 0x5080
movq %rax, %rbx
cmpl $-0x1, %ebx
je 0x8069
movq 0x8(%rsp), %rdi
cmpq %r12, %rdi
je 0x8025
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x5470
leaq 0x28(%rsp), %rdi
callq 0xa550
movl %ebx, %eax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x23f66(%rip), %rdi     # 0x2bfb0
leaq 0x1a0dc(%rip), %rsi     # 0x2212d
movl $0x1e, %edx
callq 0x54c0
movq 0x23f4e(%rip), %rdi     # 0x2bfb0
callq 0x5230
jmp 0x808d
movq 0x23f40(%rip), %rdi     # 0x2bfb0
leaq 0x1a0d5(%rip), %rsi     # 0x2214c
movl $0x24, %edx
callq 0x54c0
movq 0x23f28(%rip), %rdi     # 0x2bfb0
callq 0x5230
movl $0x1, %edi
callq 0x5510
jmp 0x809b
jmp 0x80b7
movq %rax, %rbx
movq 0x8(%rsp), %rdi
cmpq %r12, %rdi
je 0x80ba
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x5470
jmp 0x80ba
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0xa550
movq %rbx, %rdi
callq 0x5790