// File: akshayrajput[P]ARMV8_Simulator/./SUBS.cpp
// Function: SUBS()
void SUBS()
{
    int sf = IR.getLowerData() & 0x80000000;
    int op = IR.getLowerData() & 0x40000000;
    int S =  IR.getLowerData() & 0x20000000;
    int mod = (IR.getLowerData() & 0x1f000000) >> 24;
    int shift = (IR.getLowerData() & 0x00c00000) >> 22;
    int imm12 = (IR.getLowerData() & 0x003ffc00) >>10;
    int imm6 = (IR.getLowerData() & 0x0000fc00) >>10;
    int rm = (IR.getLowerData() & 0x001f0000) >> 16;
    int rn = (IR.getLowerData() & 0x000003e0) >> 5;
    int rd = (IR.getLowerData() & 0x0000001f);
    bool sub_op = false;
    uint64_t imm;
    int amount =1;

    if(rd == 31)
    {
	    CMP();
	    return;
    }	
    if(op)  sub_op = true;

    printf("[log] - SUBS instruction\n");

    if(shift == 0)
    {
        if (sf)
        {
             imm = (uint64_t)imm12;
        }
        else
        {
             imm = imm12;
        }
    }
    
    else if(shift == 1)
    {
        if(sf)
        {
            imm = (uint64_t)imm12;
            imm = imm << 12;
        }
        else
        {
            imm = imm12;
            imm = imm << 12;
        }
    }
    bool setFlag = false;
    if(S == 1) setFlag = true;
    if(mod == 17) // SUBS immediate
    {
	printf("[log]- SUBS immediate\n");
        if(sf)  //64 bit
        {
            int carry = 0;
            if(sub_op)
            {
                imm = ~imm;
                carry = 1;   
            }
            uint64_t rn_data = R[rn].getData();
            uint64_t dat = rn_data + imm + carry;
            
            
                if(rn_data > 0 && imm < 0 && dat < 0)
                    OFLAG = true;
                
                if(rn_data < 0 && imm > 0 && dat > 0)
                    OFLAG = true;
                
                ZFLAG = (dat == 0);
                NFLAG = (dat < 0);
                
                CFLAG = rn_data > (0xffffffffffffffff - (imm + carry));
                
            if(rd == 31 && !S)
                R[31].setData(dat);
            else
                R[rd].setData(dat);
        }
        
        else//32 bit
        {
            int carry = 0;
            if(sub_op)
            {
                imm = ~imm;
                carry = 1;   
            }
            
            int rn_data = R[rn].getLowerData();
            int dat = rn_data + imm + carry;
            
            
            if(rn_data > 0 && imm < 0 && dat < 0)
                OFLAG = true;
            
            if(rn_data < 0 && imm > 0 && dat > 0)
                OFLAG = true;
             
            
            if(dat == 0)
                ZFLAG = true;
            
            if(dat < 0)
                NFLAG = true;
            
            CFLAG = rn_data > (0xffffffff - (imm + carry));
            
            if(rd == 31 && !S)
                R[31].setLowerData(dat);
            else
                R[rd].setLowerData(dat);
        }
    }
    
    if(mod == 11)   //shifted register
    {
	printf("[log]- SUBS register\n");
        if(sf)      //64 bit registers
        {
            uint64_t op1 = R[rn].getData();
            
            uint64_t op2 = R[rm].getData();
            if(shift == 0)
                op2 = op2 << amount;
            else if(shift == 1 && shift == 2)
                op2 = op2 >> amount;
            uint64_t carry = 0;
            if(sub_op)
            {
                op2 = ~op2;
                carry = 1;
            }
            
            uint64_t dat = op1 + op2 + carry;
            if(rd == 31 && !S)
                R[31].setData(dat);
            else
                R[rd].setData(dat);
           
            if(op1 > 0 && op2 < 0 && dat < 0)
	    {
                OFLAG = true;
		printf("[log] -Carry flag set \n");

            }
            if(op1 < 0 && op2 > 0 && dat > 0)
	    {
                OFLAG = true;
		printf("[log] -Overflow flag set \n");

            }

            if(dat == 0)
	    {
                ZFLAG = true;
		printf("[log] -Zero flag set \n");
	    }
            
            if(dat < 0)
	    {
                NFLAG = true;
		printf("[log] -Negative flag set \n");
	    }
                
            CFLAG = op1 > (0xffffffffffffffff - (op2 + carry));
	    if(CFLAG)
		    printf("[log] -Carry flag set \n");

        }
       
        else     //32 bit registers
        {
            int op1 = R[rn].getLowerData();
            
            int op2 = R[rm].getLowerData();
            if(shift == 0)
                op2 = op2 << amount;
            else if(shift == 1 && shift == 2)
                op2 = op2 >> amount;
            int carry = 0;
            if(sub_op)
            {
                op2 = ~op2;
                carry = 1;
            }
            
            int dat = op1 + op2 + carry;
            if(rd == 31 && !S)
                R[31].setLowerData(dat);
            else
                R[rd].setLowerData(dat);
           
            if(op1 > 0 && op2 < 0 && dat < 0)
	    {
                OFLAG = true;
		printf("[log] -Carry flag set \n");

            }
            if(op1 < 0 && op2 > 0 && dat > 0 )
	    {
                OFLAG = true;
		printf("[log] - Overflow flag set \n");

            }
            ZFLAG = (dat == 0);
	    if(ZFLAG)
		    printf("[log] - Zero flag set\n");
            NFLAG = (dat < 0); 
	    if(NFLAG)
                printf("[log] - Negative flag set\n");
 
            CFLAG = op1 > (0xffffffff - (op2 + carry));
            if(CFLAG)
		    printf("[log] - Carry flag set \n");
        }
       
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
leaq 0x1a94e(%rip), %rdi     # 0x1e1e0
callq 0xa6e0
andl $0x80000000, %eax       # imm = 0x80000000
movl %eax, -0x4(%rbp)
leaq 0x1a93a(%rip), %rdi     # 0x1e1e0
callq 0xa6e0
andl $0x40000000, %eax       # imm = 0x40000000
movl %eax, -0x8(%rbp)
leaq 0x1a926(%rip), %rdi     # 0x1e1e0
callq 0xa6e0
andl $0x20000000, %eax       # imm = 0x20000000
movl %eax, -0xc(%rbp)
leaq 0x1a912(%rip), %rdi     # 0x1e1e0
callq 0xa6e0
andl $0x1f000000, %eax       # imm = 0x1F000000
shrl $0x18, %eax
movl %eax, -0x10(%rbp)
leaq 0x1a8fb(%rip), %rdi     # 0x1e1e0
callq 0xa6e0
andl $0xc00000, %eax         # imm = 0xC00000
shrl $0x16, %eax
movl %eax, -0x14(%rbp)
leaq 0x1a8e4(%rip), %rdi     # 0x1e1e0
callq 0xa6e0
andl $0x3ffc00, %eax         # imm = 0x3FFC00
shrl $0xa, %eax
movl %eax, -0x18(%rbp)
leaq 0x1a8cd(%rip), %rdi     # 0x1e1e0
callq 0xa6e0
andl $0xfc00, %eax           # imm = 0xFC00
shrl $0xa, %eax
movl %eax, -0x1c(%rbp)
leaq 0x1a8b6(%rip), %rdi     # 0x1e1e0
callq 0xa6e0
andl $0x1f0000, %eax         # imm = 0x1F0000
shrl $0x10, %eax
movl %eax, -0x20(%rbp)
leaq 0x1a89f(%rip), %rdi     # 0x1e1e0
callq 0xa6e0
andl $0x3e0, %eax            # imm = 0x3E0
shrl $0x5, %eax
movl %eax, -0x24(%rbp)
leaq 0x1a888(%rip), %rdi     # 0x1e1e0
callq 0xa6e0
andl $0x1f, %eax
movl %eax, -0x28(%rbp)
movb $0x0, -0x29(%rbp)
movl $0x1, -0x3c(%rbp)
cmpl $0x1f, -0x28(%rbp)
jne 0x397e
callq 0x2830
jmp 0x3ffa
cmpl $0x0, -0x8(%rbp)
je 0x3988
movb $0x1, -0x29(%rbp)
leaq 0x7c54(%rip), %rdi      # 0xb5e3
movb $0x0, %al
callq 0x1030
cmpl $0x0, -0x14(%rbp)
jne 0x39b6
cmpl $0x0, -0x4(%rbp)
je 0x39ac
movslq -0x18(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0x39b4
movslq -0x18(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0x39f0
cmpl $0x1, -0x14(%rbp)
jne 0x39ee
cmpl $0x0, -0x4(%rbp)
je 0x39d8
movslq -0x18(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
shlq $0xc, %rax
movq %rax, -0x38(%rbp)
jmp 0x39ec
movslq -0x18(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
shlq $0xc, %rax
movq %rax, -0x38(%rbp)
jmp 0x39ee
jmp 0x39f0
movb $0x0, -0x3d(%rbp)
cmpl $0x1, -0xc(%rbp)
jne 0x39fe
movb $0x1, -0x3d(%rbp)
cmpl $0x11, -0x10(%rbp)
jne 0x3c33
leaq 0x7bee(%rip), %rdi      # 0xb5fd
movb $0x0, %al
callq 0x1030
cmpl $0x0, -0x4(%rbp)
je 0x3b32
movl $0x0, -0x44(%rbp)
testb $0x1, -0x29(%rbp)
je 0x3a40
movq -0x38(%rbp), %rax
xorq $-0x1, %rax
movq %rax, -0x38(%rbp)
movl $0x1, -0x44(%rbp)
movslq -0x24(%rbp), %rax
leaq 0xa695(%rip), %rdi      # 0xe0e0
shlq $0x3, %rax
addq %rax, %rdi
callq 0xa6c0
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
addq -0x38(%rbp), %rax
movslq -0x44(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x50(%rbp)
jbe 0x3a8a
cmpq $0x0, -0x38(%rbp)
jae 0x3a8a
cmpq $0x0, -0x58(%rbp)
jae 0x3a8a
movb $0x1, 0xa648(%rip)      # 0xe0d2
cmpq $0x0, -0x50(%rbp)
jae 0x3aa6
cmpq $0x0, -0x38(%rbp)
jbe 0x3aa6
cmpq $0x0, -0x58(%rbp)
jbe 0x3aa6
movb $0x1, 0xa62c(%rip)      # 0xe0d2
cmpq $0x0, -0x58(%rbp)
sete %al
andb $0x1, %al
movb %al, 0xa61b(%rip)       # 0xe0d1
cmpq $0x0, -0x58(%rbp)
setb %al
andb $0x1, %al
movb %al, 0xa60d(%rip)       # 0xe0d3
movq -0x50(%rbp), %rax
movq -0x38(%rbp), %rdx
movslq -0x44(%rbp), %rcx
addq %rcx, %rdx
movq $-0x1, %rcx
subq %rdx, %rcx
cmpq %rcx, %rax
seta %al
andb $0x1, %al
movb %al, 0xa5e7(%rip)       # 0xe0d4
cmpl $0x1f, -0x28(%rbp)
jne 0x3b12
cmpl $0x0, -0xc(%rbp)
jne 0x3b12
movq -0x58(%rbp), %rsi
leaq 0xa5dc(%rip), %rdi      # 0xe0e0
addq $0xf8, %rdi
callq 0xa710
jmp 0x3b2d
movslq -0x28(%rbp), %rax
leaq 0xa5c3(%rip), %rdi      # 0xe0e0
shlq $0x3, %rax
addq %rax, %rdi
movq -0x58(%rbp), %rsi
callq 0xa710
jmp 0x3c31
movl $0x0, -0x5c(%rbp)
testb $0x1, -0x29(%rbp)
je 0x3b52
movq -0x38(%rbp), %rax
xorq $-0x1, %rax
movq %rax, -0x38(%rbp)
movl $0x1, -0x5c(%rbp)
movslq -0x24(%rbp), %rax
leaq 0xa583(%rip), %rdi      # 0xe0e0
shlq $0x3, %rax
addq %rax, %rdi
callq 0xa6e0
movl %eax, -0x60(%rbp)
movslq -0x60(%rbp), %rax
addq -0x38(%rbp), %rax
movslq -0x5c(%rbp), %rcx
addq %rcx, %rax
movl %eax, -0x64(%rbp)
cmpl $0x0, -0x60(%rbp)
jle 0x3b98
cmpq $0x0, -0x38(%rbp)
jae 0x3b98
cmpl $0x0, -0x64(%rbp)
jge 0x3b98
movb $0x1, 0xa53a(%rip)      # 0xe0d2
cmpl $0x0, -0x60(%rbp)
jge 0x3bb2
cmpq $0x0, -0x38(%rbp)
jbe 0x3bb2
cmpl $0x0, -0x64(%rbp)
jle 0x3bb2
movb $0x1, 0xa520(%rip)      # 0xe0d2
cmpl $0x0, -0x64(%rbp)
jne 0x3bbf
movb $0x1, 0xa512(%rip)      # 0xe0d1
cmpl $0x0, -0x64(%rbp)
jge 0x3bcc
movb $0x1, 0xa507(%rip)      # 0xe0d3
movslq -0x60(%rbp), %rax
movq -0x38(%rbp), %rdx
movslq -0x5c(%rbp), %rcx
addq %rcx, %rdx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
subq %rdx, %rcx
cmpq %rcx, %rax
seta %al
andb $0x1, %al
movb %al, 0xa4e3(%rip)       # 0xe0d4
cmpl $0x1f, -0x28(%rbp)
jne 0x3c15
cmpl $0x0, -0xc(%rbp)
jne 0x3c15
movl -0x64(%rbp), %esi
leaq 0xa4d9(%rip), %rdi      # 0xe0e0
addq $0xf8, %rdi
callq 0xa730
jmp 0x3c2f
movslq -0x28(%rbp), %rax
leaq 0xa4c0(%rip), %rdi      # 0xe0e0
shlq $0x3, %rax
addq %rax, %rdi
movl -0x64(%rbp), %esi
callq 0xa730
jmp 0x3c31
jmp 0x3c33
cmpl $0xb, -0x10(%rbp)
jne 0x3ffa
leaq 0x79d0(%rip), %rdi      # 0xb614
movb $0x0, %al
callq 0x1030
cmpl $0x0, -0x4(%rbp)
je 0x3e10
movslq -0x24(%rbp), %rax
leaq 0xa480(%rip), %rdi      # 0xe0e0
shlq $0x3, %rax
addq %rax, %rdi
callq 0xa6c0
movq %rax, -0x70(%rbp)
movslq -0x20(%rbp), %rax
leaq 0xa465(%rip), %rdi      # 0xe0e0
shlq $0x3, %rax
addq %rax, %rdi
callq 0xa6c0
movq %rax, -0x78(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0x3ca1
movq -0x78(%rbp), %rax
movl -0x3c(%rbp), %ecx
shlq %cl, %rax
movq %rax, -0x78(%rbp)
jmp 0x3cbd
cmpl $0x1, -0x14(%rbp)
jne 0x3cbb
cmpl $0x2, -0x14(%rbp)
jne 0x3cbb
movq -0x78(%rbp), %rax
movl -0x3c(%rbp), %ecx
shrq %cl, %rax
movq %rax, -0x78(%rbp)
jmp 0x3cbd
movq $0x0, -0x80(%rbp)
testb $0x1, -0x29(%rbp)
je 0x3cdf
movq -0x78(%rbp), %rax
xorq $-0x1, %rax
movq %rax, -0x78(%rbp)
movq $0x1, -0x80(%rbp)
movq -0x70(%rbp), %rax
addq -0x78(%rbp), %rax
addq -0x80(%rbp), %rax
movq %rax, -0x88(%rbp)
cmpl $0x1f, -0x28(%rbp)
jne 0x3d1a
cmpl $0x0, -0xc(%rbp)
jne 0x3d1a
movq -0x88(%rbp), %rsi
leaq 0xa3d4(%rip), %rdi      # 0xe0e0
addq $0xf8, %rdi
callq 0xa710
jmp 0x3d38
movslq -0x28(%rbp), %rax
leaq 0xa3bb(%rip), %rdi      # 0xe0e0
shlq $0x3, %rax
addq %rax, %rdi
movq -0x88(%rbp), %rsi
callq 0xa710
cmpq $0x0, -0x70(%rbp)
jbe 0x3d65
cmpq $0x0, -0x78(%rbp)
jae 0x3d65
cmpq $0x0, -0x88(%rbp)
jae 0x3d65
movb $0x1, 0xa37b(%rip)      # 0xe0d2
leaq 0x7809(%rip), %rdi      # 0xb567
movb $0x0, %al
callq 0x1030
cmpq $0x0, -0x70(%rbp)
jae 0x3d92
cmpq $0x0, -0x78(%rbp)
jbe 0x3d92
cmpq $0x0, -0x88(%rbp)
jbe 0x3d92
movb $0x1, 0xa34e(%rip)      # 0xe0d2
leaq 0x77f4(%rip), %rdi      # 0xb57f
movb $0x0, %al
callq 0x1030
cmpq $0x0, -0x88(%rbp)
jne 0x3db1
movb $0x1, 0xa32e(%rip)      # 0xe0d1
leaq 0x77f0(%rip), %rdi      # 0xb59a
movb $0x0, %al
callq 0x1030
cmpq $0x0, -0x88(%rbp)
jae 0x3dd0
movb $0x1, 0xa311(%rip)      # 0xe0d3
leaq 0x77e8(%rip), %rdi      # 0xb5b1
movb $0x0, %al
callq 0x1030
movq -0x70(%rbp), %rax
movq -0x78(%rbp), %rdx
addq -0x80(%rbp), %rdx
movq $-0x1, %rcx
subq %rdx, %rcx
cmpq %rcx, %rax
seta %al
andb $0x1, %al
movb %al, 0xa2e0(%rip)       # 0xe0d4
testb $0x1, 0xa2d9(%rip)      # 0xe0d4
je 0x3e0b
leaq 0x7763(%rip), %rdi      # 0xb567
movb $0x0, %al
callq 0x1030
jmp 0x3ff8
movslq -0x24(%rbp), %rax
leaq 0xa2c5(%rip), %rdi      # 0xe0e0
shlq $0x3, %rax
addq %rax, %rdi
callq 0xa6e0
movl %eax, -0x8c(%rbp)
movslq -0x20(%rbp), %rax
leaq 0xa2a8(%rip), %rdi      # 0xe0e0
shlq $0x3, %rax
addq %rax, %rdi
callq 0xa6e0
movl %eax, -0x90(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0x3e63
movl -0x90(%rbp), %eax
movl -0x3c(%rbp), %ecx
shll %cl, %eax
movl %eax, -0x90(%rbp)
jmp 0x3e82
cmpl $0x1, -0x14(%rbp)
jne 0x3e80
cmpl $0x2, -0x14(%rbp)
jne 0x3e80
movl -0x90(%rbp), %eax
movl -0x3c(%rbp), %ecx
sarl %cl, %eax
movl %eax, -0x90(%rbp)
jmp 0x3e82
movl $0x0, -0x94(%rbp)
testb $0x1, -0x29(%rbp)
je 0x3eab
movl -0x90(%rbp), %eax
xorl $-0x1, %eax
movl %eax, -0x90(%rbp)
movl $0x1, -0x94(%rbp)
movl -0x8c(%rbp), %eax
addl -0x90(%rbp), %eax
addl -0x94(%rbp), %eax
movl %eax, -0x98(%rbp)
cmpl $0x1f, -0x28(%rbp)
jne 0x3eea
cmpl $0x0, -0xc(%rbp)
jne 0x3eea
movl -0x98(%rbp), %esi
leaq 0xa204(%rip), %rdi      # 0xe0e0
addq $0xf8, %rdi
callq 0xa730
jmp 0x3f07
movslq -0x28(%rbp), %rax
leaq 0xa1eb(%rip), %rdi      # 0xe0e0
shlq $0x3, %rax
addq %rax, %rdi
movl -0x98(%rbp), %esi
callq 0xa730
cmpl $0x0, -0x8c(%rbp)
jle 0x3f37
cmpl $0x0, -0x90(%rbp)
jge 0x3f37
cmpl $0x0, -0x98(%rbp)
jge 0x3f37
movb $0x1, 0xa1a9(%rip)      # 0xe0d2
leaq 0x7637(%rip), %rdi      # 0xb567
movb $0x0, %al
callq 0x1030
cmpl $0x0, -0x8c(%rbp)
jge 0x3f67
cmpl $0x0, -0x90(%rbp)
jle 0x3f67
cmpl $0x0, -0x98(%rbp)
jle 0x3f67
movb $0x1, 0xa179(%rip)      # 0xe0d2
leaq 0x76ca(%rip), %rdi      # 0xb62a
movb $0x0, %al
callq 0x1030
cmpl $0x0, -0x98(%rbp)
sete %al
andb $0x1, %al
movb %al, 0xa158(%rip)       # 0xe0d1
testb $0x1, 0xa151(%rip)      # 0xe0d1
je 0x3f90
leaq 0x7517(%rip), %rdi      # 0xb4a0
movb $0x0, %al
callq 0x1030
cmpl $0x0, -0x98(%rbp)
setl %al
andb $0x1, %al
movb %al, 0xa131(%rip)       # 0xe0d3
testb $0x1, 0xa12a(%rip)      # 0xe0d3
je 0x3fb9
leaq 0x7505(%rip), %rdi      # 0xb4b7
movb $0x0, %al
callq 0x1030
movl -0x8c(%rbp), %eax
movl -0x90(%rbp), %edx
addl -0x94(%rbp), %edx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
subl %edx, %ecx
cmpl %ecx, %eax
seta %al
andb $0x1, %al
movb %al, 0xa0f5(%rip)       # 0xe0d4
testb $0x1, 0xa0ee(%rip)      # 0xe0d4
je 0x3ff6
leaq 0x7657(%rip), %rdi      # 0xb646
movb $0x0, %al
callq 0x1030
jmp 0x3ff8
jmp 0x3ffa
addq $0xa0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)