// File: /workspace/github_cpp_makefile_star2_O2/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 0x4706(%rip), %rdi      # 0x65f0
callq 0x1120
leaq 0x182ea(%rip), %r12     # 0x1a1e0
movq %r12, %rdi
callq 0x5b26
movl %eax, %ebx
movq %r12, %rdi
callq 0x5b26
movq %r12, %rdi
callq 0x5b26
movq %r12, %rdi
callq 0x5b26
movl %eax, %r14d
shrl $0x16, %r14d
andl $0x3, %r14d
movq %r12, %rdi
callq 0x5b26
movl %eax, %ebp
movq %r12, %rdi
callq 0x5b26
movl %eax, %r13d
shrl $0x18, %r13d
andl $0x1f, %r13d
movq %r12, %rdi
callq 0x5b26
movl %eax, %r15d
shrl $0x5, %r15d
andl $0x1f, %r15d
movq %r12, %rdi
callq 0x5b26
cmpl $0xb, %r13d
je 0x1fff
cmpl $0x11, %r13d
jne 0x22c0
shrl $0xa, %ebp
andl $0xfff, %ebp            # imm = 0xFFF
leaq 0x46a7(%rip), %rdi      # 0x6626
callq 0x1120
movl %ebp, %r12d
shll $0xc, %r12d
cmpl $0x1, %r14d
cmovnel %ebp, %r12d
btl $0x1f, %ebx
movl %r15d, %eax
leaq 0x813f(%rip), %rcx      # 0xa0e0
leaq (%rcx,%rax,8), %rdi
jb 0x20ee
callq 0x5b26
movl %eax, %ebx
cmpb $0x1, 0x8119(%rip)      # 0xa0d2
jne 0x1fc7
leaq 0x468e(%rip), %rdi      # 0x6650
callq 0x1120
cmpl %r12d, %ebx
setl %bpl
setl 0x80ff(%rip)            # 0xa0d4
jge 0x213c
leaq 0x46a0(%rip), %rdi      # 0x6682
callq 0x1120
movb %bpl, 0x80e5(%rip)      # 0xa0d3
leaq 0x477a(%rip), %rdi      # 0x676f
callq 0x1120
jmp 0x2143
leaq 0x4602(%rip), %rdi      # 0x6608
callq 0x1120
leaq 0x181ce(%rip), %rdi     # 0x1a1e0
callq 0x5b26
btl $0x15, %eax
jae 0x22c0
leaq 0x181b8(%rip), %r13     # 0x1a1e0
movq %r13, %rdi
callq 0x5b26
movl %eax, %r12d
shrl $0x10, %r12d
andl $0x1f, %r12d
movq %r13, %rdi
callq 0x5b26
movl %eax, %ebp
shrl $0xa, %ebp
andl $0x3f, %ebp
btl $0x1f, %ebx
jb 0x215a
cmpl $0x3, %r14d
je 0x22c0
movl %r15d, %eax
testl %r14d, %r14d
jne 0x219c
leaq 0x806e(%rip), %r14      # 0xa0e0
leaq (%r14,%rax,8), %rdi
callq 0x5b26
movl %eax, %ebx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5b26
movl %ebp, %ecx
shll %cl, %eax
cmpl %eax, %ebx
setb 0x803e(%rip)            # 0xa0d4
setb 0x8036(%rip)            # 0xa0d3
sete 0x802d(%rip)            # 0xa0d1
jae 0x20c7
leaq 0x46c2(%rip), %rdi      # 0x676f
callq 0x1120
testb $0x1, 0x801b(%rip)      # 0xa0d4
je 0x20c7
leaq 0x45c0(%rip), %rdi      # 0x6682
callq 0x1120
cmpb $0x1, 0x8003(%rip)      # 0xa0d1
jne 0x20dc
leaq 0x4682(%rip), %rdi      # 0x6759
callq 0x1120
cmpb $0x0, 0x7fef(%rip)      # 0xa0d2
jne 0x221a
jmp 0x22c0
callq 0x5b22
movq %rax, %rbx
cmpb $0x1, 0x7fd5(%rip)      # 0xa0d2
jne 0x210b
leaq 0x454a(%rip), %rdi      # 0x6650
callq 0x1120
cmpq %r12, %rbx
setb %bpl
setb 0x7fbb(%rip)            # 0xa0d4
jae 0x214b
leaq 0x4560(%rip), %rdi      # 0x6682
callq 0x1120
movb %bpl, 0x7fa5(%rip)      # 0xa0d3
leaq 0x463a(%rip), %rdi      # 0x676f
callq 0x1120
jmp 0x2152
movb %bpl, 0x7f90(%rip)      # 0xa0d3
cmpl %r12d, %ebx
jmp 0x229d
movb %bpl, 0x7f81(%rip)      # 0xa0d3
cmpq %r12, %rbx
jmp 0x229d
cmpl $0x3, %r14d
je 0x22c0
movl %r15d, %eax
testl %r14d, %r14d
jne 0x2226
leaq 0x7f69(%rip), %r14      # 0xa0e0
leaq (%r14,%rax,8), %rdi
callq 0x5b22
movq %rax, %rbx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5b22
movq %rax, %r14
movl %ebp, %ecx
shlq %cl, %r14
jmp 0x224d
leaq 0x7f3d(%rip), %r14      # 0xa0e0
leaq (%r14,%rax,8), %rdi
callq 0x5b26
movl %eax, %ebx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5b26
movl %ebp, %ecx
shrl %cl, %eax
cmpl %eax, %ebx
setb 0x7f0d(%rip)            # 0xa0d4
setb 0x7f05(%rip)            # 0xa0d3
sete 0x7efc(%rip)            # 0xa0d1
jae 0x21f8
leaq 0x44a4(%rip), %rdi      # 0x6682
callq 0x1120
testb $0x1, 0x7ee9(%rip)      # 0xa0d3
je 0x21f8
leaq 0x457c(%rip), %rdi      # 0x676f
callq 0x1120
cmpb $0x1, 0x7ed2(%rip)      # 0xa0d1
jne 0x220d
leaq 0x4551(%rip), %rdi      # 0x6759
callq 0x1120
cmpb $0x1, 0x7ebe(%rip)      # 0xa0d2
jne 0x22c0
leaq 0x442f(%rip), %rdi      # 0x6650
jmp 0x22ad
leaq 0x7eb3(%rip), %r14      # 0xa0e0
leaq (%r14,%rax,8), %rdi
callq 0x5b22
movq %rax, %rbx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5b22
movq %rax, %r14
movl %ebp, %ecx
shrq %cl, %r14
cmpb $0x1, 0x7e7e(%rip)      # 0xa0d2
jne 0x2262
leaq 0x43f3(%rip), %rdi      # 0x6650
callq 0x1120
cmpq %r14, %rbx
setb %bpl
setb 0x7e64(%rip)            # 0xa0d4
jae 0x2293
leaq 0x4409(%rip), %rdi      # 0x6682
callq 0x1120
movb %bpl, 0x7e4e(%rip)      # 0xa0d3
leaq 0x44e3(%rip), %rdi      # 0x676f
callq 0x1120
jmp 0x229a
movb %bpl, 0x7e39(%rip)      # 0xa0d3
cmpq %r14, %rbx
sete 0x7e2d(%rip)            # 0xa0d1
jne 0x22c0
leaq 0x44ac(%rip), %rdi      # 0x6759
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1120
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq