// File: /workspace/github_cpp_makefile_star2_O2/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 0xc7b4
movq (%r13), %rsi
cmpq %rsi, 0x8(%r13)
je 0x7d40
movl %r12d, %eax
shlq $0x5, %rax
addq %rax, %rsi
leaq 0x8(%rsp), %rdi
callq 0x55a0
leaq 0x8(%rsp), %rdi
callq 0xcb6a
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 $0x10000, 0x18(%rsi)    # imm = 0x10000
movq $0x100001, 0x28(%rsi)   # imm = 0x100001
pushq $-0x1
popq %rdx
movl $0x12a, %edi            # imm = 0x12A
movl %ebx, %ecx
movl %edx, %r8d
xorl %r9d, %r9d
xorl %eax, %eax
callq 0x5070
movq %rax, %rbx
cmpl $-0x1, %ebx
je 0x7d5d
leaq 0x8(%rsp), %rdi
callq 0x5888
leaq 0x28(%rsp), %rdi
callq 0x97fe
movl %ebx, %eax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x24269(%rip), %rdi     # 0x2bfb0
leaq 0x19403(%rip), %rsi     # 0x21151
callq 0x5450
movq %rax, %rdi
callq 0x5230
jmp 0x7d78
movq 0x2424c(%rip), %rdi     # 0x2bfb0
leaq 0x19405(%rip), %rsi     # 0x21170
callq 0x5450
movq %rax, %rdi
callq 0x5230
pushq $0x1
popq %rdi
callq 0x54f0
jmp 0x7d84
jmp 0x7d93
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x5888
jmp 0x7d96
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x97fe
movq %rbx, %rdi
callq 0x5790