// File: /workspace/github_cpp_makefile_star2_O3/akshayrajput[P]ARMV8_Simulator/./CMP.cpp
// Function: CMP()
void CMP()
{
    printf("[log] - CMP instruction\n");
    int sf = IR.getLowerData() & 0x80000000;
    int op = IR.getLowerData() & 0x40000000;
    int S = IR.getLowerData() & 0x20000000;
    int shift = (IR.getLowerData()  & 0x00c00000) >> 22;
    int imm12 = (IR.getLowerData()  & 0x003ffc00) >> 10;
    int mod = (IR.getLowerData()  & 0x1f000000) >> 24;
    int rn = (IR.getLowerData()  & 0x000003e0) >> 5;
    int rd = IR.getLowerData()  & 0x0000001f;

    if(mod == 17)   //immediate
    {
	printf("[log] - CMP instruction immediate\n");
        uint64_t imm = imm12;
        if(shift == 1)
        {
            imm = imm12 << 12;
        }
        
        if(sf)
        {
            uint64_t dat = R[rn].getData();
            if((dat > 0 && imm < 0 && (dat-imm) < 0) || (dat < 0 && imm > 0 && (dat - imm) > 0))
                OFLAG = true;
            if(OFLAG)
		    printf("Overflow flag set\n");
            CFLAG = (dat <imm);
            if(CFLAG)
		    printf("Carry flag set\n");
            NFLAG = (dat < imm);
            if(NFLAG)
		    printf("Negative flag set\n");
            ZFLAG = (dat == imm);
            if(ZFLAG)
		    printf("Zero flag set\n");
        }
        
        else
        {
            int imm32 = (int)imm;
            int dat = R[rn].getLowerData();
            if((dat > 0 && imm32 < 0 && (dat-imm32) < 0) || (dat < 0 && imm32 > 0 && (dat - imm32) > 0))
                OFLAG = true;
            if(OFLAG)
		    printf("Overflow flag set\n");
            CFLAG = (dat < imm32);
            if(CFLAG)
		    	printf("Carry flag set\n");
		    	
            NFLAG = (dat < imm32);
            
            if(NFLAG)
		    	printf("Negative flag set\n");
		    	
            ZFLAG = (dat == imm32);
            if(ZFLAG)
		    	printf("Zero flag set\n");
        }
    }
    else if(mod == 11)  //extended or register
    {
	printf("[log] - CMP extended/register\n");
        int inst_t = IR.getLowerData() & 0x00200000;
        if(inst_t) //register
        {
            int rm = (IR.getLowerData() & 0x001f0000) >> 16;
            int imm6 = (IR.getLowerData() & 0x0000fc00) >> 10;
            if(sf)  //64 bit registers
            {
                if(shift == 0) //LSL
                {
                    uint64_t rn_data = R[rn].getData();
                    uint64_t rm_data = R[rm].getData();
                    rm_data = rm_data << imm6;
                    
                    if((rn_data > 0 && rm_data < 0 && (rn_data-rm_data) < 0) || (rn_data < 0 && rm_data > 0 && (rn_data - rm_data) > 0))
                OFLAG = true;
        if(OFLAG)
		    printf("Overflow flag set\n");
		    
            CFLAG = (rn_data < rm_data);
	    if(CFLAG)
		    printf("Carry flag set\n");
		    
            NFLAG = (rn_data < rm_data);
	    if(NFLAG)
		    printf("Negative flag set\n");
		    
            ZFLAG = (rn_data == rm_data);
        if(ZFLAG)
		    printf("Zero flag set\n");
        
                }
                
                else if(shift == 1 or shift == 2) // LSR or ASR(in c both are same)
                {
                    uint64_t rn_data = R[rn].getData();
                    uint64_t rm_data = R[rm].getData();
                    rm_data = rm_data >> imm6;
                    
                    if((rn_data > 0 && rm_data < 0 && (rn_data-rm_data) < 0) || (rn_data < 0 && rm_data > 0 && (rn_data - rm_data) > 0))
                OFLAG = true;
            if(OFLAG)
		    printf("Overflow flag set\n");
            CFLAG = (rn_data < rm_data);
		if(CFLAG)
		    printf("Carry flag set\n");

            NFLAG = (rn_data < rm_data);
		if(NFLAG)
		    printf("Negative flag set\n");

            ZFLAG = (rn_data == rm_data);
		if(ZFLAG)
		    printf("Zero flag set\n");

                }
            }
            
            else    //32 bit registers
            {
                if(shift == 0) //LSL
                {
                    uint32_t rn_data = R[rn].getLowerData();
                    uint32_t rm_data = R[rm].getLowerData();
                    rm_data = rm_data << imm6;
                    
                    if((rn_data > 0 && rm_data < 0 && (rn_data-rm_data) < 0) || (rn_data < 0 && rm_data > 0 && (rn_data - rm_data) > 0))
                OFLAG = true;
            
            CFLAG = (rn_data < rm_data);
            NFLAG = (rn_data < rm_data);
            ZFLAG = (rn_data == rm_data);
            if(NFLAG)
		    printf("Negative flag set\n");
		    if(CFLAG)
		    printf("Carry flag set\n");
		    if(ZFLAG)
		    printf("Zero flag set\n");
		    if(OFLAG)
		    printf("Overflow flag set\n");
                }
                
                else if(shift == 1 or shift == 2) // LSR or ASR(in c both are same)
                {
                    uint32_t rn_data = R[rn].getLowerData();
                    uint32_t rm_data = R[rm].getLowerData();
                    rm_data = rm_data >> imm6;
                    
                    if((rn_data > 0 && rm_data < 0 && (rn_data-rm_data) < 0) || (rn_data < 0 && rm_data > 0 && (rn_data - rm_data) > 0))
                OFLAG = true;
            
            CFLAG = (rn_data < rm_data);
            NFLAG = (rn_data < rm_data);
            ZFLAG = (rn_data == rm_data);
            
            if(CFLAG)
		    printf("Carry flag set\n");
		    if(NFLAG)
		    printf("Negative flag set\n");
		    if(ZFLAG)
		    printf("Zero flag set\n");
		    if(OFLAG)
		    printf("Overflow flag set\n");
                }
            }
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
leaq 0x4665(%rip), %rdi      # 0x65f0
callq 0x1140
leaq 0x18259(%rip), %r12     # 0x1a1f0
movq %r12, %rdi
callq 0x5cb2
movl %eax, %ebx
movq %r12, %rdi
callq 0x5cb2
movq %r12, %rdi
callq 0x5cb2
movq %r12, %rdi
callq 0x5cb2
movl %eax, %r14d
shrl $0x16, %r14d
andl $0x3, %r14d
movq %r12, %rdi
callq 0x5cb2
movl %eax, %ebp
movq %r12, %rdi
callq 0x5cb2
movl %eax, %r13d
shrl $0x18, %r13d
andl $0x1f, %r13d
movq %r12, %rdi
callq 0x5cb2
movl %eax, %r15d
shrl $0x5, %r15d
andl $0x1f, %r15d
movq %r12, %rdi
callq 0x5cb2
cmpl $0xb, %r13d
je 0x20a0
cmpl $0x11, %r13d
jne 0x2361
shrl $0xa, %ebp
andl $0xfff, %ebp            # imm = 0xFFF
leaq 0x4606(%rip), %rdi      # 0x6626
callq 0x1140
movl %ebp, %r12d
shll $0xc, %r12d
cmpl $0x1, %r14d
cmovnel %ebp, %r12d
btl $0x1f, %ebx
movl %r15d, %eax
leaq 0x80ae(%rip), %rcx      # 0xa0f0
leaq (%rcx,%rax,8), %rdi
jb 0x218f
callq 0x5cb2
movl %eax, %ebx
cmpb $0x1, 0x8088(%rip)      # 0xa0e2
jne 0x2068
leaq 0x45ed(%rip), %rdi      # 0x6650
callq 0x1140
cmpl %r12d, %ebx
setl %bpl
setl 0x806e(%rip)            # 0xa0e4
jge 0x21dd
leaq 0x45ff(%rip), %rdi      # 0x6682
callq 0x1140
movb %bpl, 0x8054(%rip)      # 0xa0e3
leaq 0x46d9(%rip), %rdi      # 0x676f
callq 0x1140
jmp 0x21e4
leaq 0x4561(%rip), %rdi      # 0x6608
callq 0x1140
leaq 0x1813d(%rip), %rdi     # 0x1a1f0
callq 0x5cb2
btl $0x15, %eax
jae 0x2361
leaq 0x18127(%rip), %r13     # 0x1a1f0
movq %r13, %rdi
callq 0x5cb2
movl %eax, %r12d
shrl $0x10, %r12d
andl $0x1f, %r12d
movq %r13, %rdi
callq 0x5cb2
movl %eax, %ebp
shrl $0xa, %ebp
andl $0x3f, %ebp
btl $0x1f, %ebx
jb 0x21fb
cmpl $0x3, %r14d
je 0x2361
movl %r15d, %eax
testl %r14d, %r14d
jne 0x223d
leaq 0x7fdd(%rip), %r14      # 0xa0f0
leaq (%r14,%rax,8), %rdi
callq 0x5cb2
movl %eax, %ebx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5cb2
movl %ebp, %ecx
shll %cl, %eax
cmpl %eax, %ebx
setb 0x7fad(%rip)            # 0xa0e4
setb 0x7fa5(%rip)            # 0xa0e3
sete 0x7f9c(%rip)            # 0xa0e1
jae 0x2168
leaq 0x4621(%rip), %rdi      # 0x676f
callq 0x1140
testb $0x1, 0x7f8a(%rip)      # 0xa0e4
je 0x2168
leaq 0x451f(%rip), %rdi      # 0x6682
callq 0x1140
cmpb $0x1, 0x7f72(%rip)      # 0xa0e1
jne 0x217d
leaq 0x45e1(%rip), %rdi      # 0x6759
callq 0x1140
cmpb $0x0, 0x7f5e(%rip)      # 0xa0e2
jne 0x22bb
jmp 0x2361
callq 0x5cae
movq %rax, %rbx
cmpb $0x1, 0x7f44(%rip)      # 0xa0e2
jne 0x21ac
leaq 0x44a9(%rip), %rdi      # 0x6650
callq 0x1140
cmpq %r12, %rbx
setb %bpl
setb 0x7f2a(%rip)            # 0xa0e4
jae 0x21ec
leaq 0x44bf(%rip), %rdi      # 0x6682
callq 0x1140
movb %bpl, 0x7f14(%rip)      # 0xa0e3
leaq 0x4599(%rip), %rdi      # 0x676f
callq 0x1140
jmp 0x21f3
movb %bpl, 0x7eff(%rip)      # 0xa0e3
cmpl %r12d, %ebx
jmp 0x233e
movb %bpl, 0x7ef0(%rip)      # 0xa0e3
cmpq %r12, %rbx
jmp 0x233e
cmpl $0x3, %r14d
je 0x2361
movl %r15d, %eax
testl %r14d, %r14d
jne 0x22c7
leaq 0x7ed8(%rip), %r14      # 0xa0f0
leaq (%r14,%rax,8), %rdi
callq 0x5cae
movq %rax, %rbx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5cae
movq %rax, %r14
movl %ebp, %ecx
shlq %cl, %r14
jmp 0x22ee
leaq 0x7eac(%rip), %r14      # 0xa0f0
leaq (%r14,%rax,8), %rdi
callq 0x5cb2
movl %eax, %ebx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5cb2
movl %ebp, %ecx
shrl %cl, %eax
cmpl %eax, %ebx
setb 0x7e7c(%rip)            # 0xa0e4
setb 0x7e74(%rip)            # 0xa0e3
sete 0x7e6b(%rip)            # 0xa0e1
jae 0x2299
leaq 0x4403(%rip), %rdi      # 0x6682
callq 0x1140
testb $0x1, 0x7e58(%rip)      # 0xa0e3
je 0x2299
leaq 0x44db(%rip), %rdi      # 0x676f
callq 0x1140
cmpb $0x1, 0x7e41(%rip)      # 0xa0e1
jne 0x22ae
leaq 0x44b0(%rip), %rdi      # 0x6759
callq 0x1140
cmpb $0x1, 0x7e2d(%rip)      # 0xa0e2
jne 0x2361
leaq 0x438e(%rip), %rdi      # 0x6650
jmp 0x234e
leaq 0x7e22(%rip), %r14      # 0xa0f0
leaq (%r14,%rax,8), %rdi
callq 0x5cae
movq %rax, %rbx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5cae
movq %rax, %r14
movl %ebp, %ecx
shrq %cl, %r14
cmpb $0x1, 0x7ded(%rip)      # 0xa0e2
jne 0x2303
leaq 0x4352(%rip), %rdi      # 0x6650
callq 0x1140
cmpq %r14, %rbx
setb %bpl
setb 0x7dd3(%rip)            # 0xa0e4
jae 0x2334
leaq 0x4368(%rip), %rdi      # 0x6682
callq 0x1140
movb %bpl, 0x7dbd(%rip)      # 0xa0e3
leaq 0x4442(%rip), %rdi      # 0x676f
callq 0x1140
jmp 0x233b
movb %bpl, 0x7da8(%rip)      # 0xa0e3
cmpq %r14, %rbx
sete 0x7d9c(%rip)            # 0xa0e1
jne 0x2361
leaq 0x440b(%rip), %rdi      # 0x6759
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1140
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq