// File: sangwoojun[P]rv32emulator/emulator.cpp
// Function: normalize_labels(instr*, label_loc*, int, source*)
void normalize_labels(instr* imem, label_loc* labels, int label_count, source* src) {
	for ( int i = 0; i < DATA_OFFSET/4; i++ ) {
		instr* ii = &imem[i];
		if ( ii->op == UNIMPL ) continue;

		if ( ii->a1.type == OPTYPE_LABEL ) {
			ii->a1.type = OPTYPE_IMM;
			ii->a1.imm = label_addr(ii->a1.label, labels, label_count, ii->orig_line);
		}
		if ( ii->a2.type == OPTYPE_LABEL ) {
			ii->a2.type = OPTYPE_IMM;
			ii->a2.imm = label_addr(ii->a2.label, labels, label_count, ii->orig_line);
			switch (ii->op) {
				case LUI: {
					ii->a2.imm = (ii->a2.imm>>12); 
					char areg[4]; sprintf(areg, "x%02d", ii->a1.reg);
					char immu[12]; sprintf(immu, "0x%08x" , ii->a2.imm);
					//printf( "LUI %d 0x%x %s\n", ii->a1.reg, ii->a2.imm, immu );
					append_source("lui", areg, immu, NULL, src, ii);
					break;
				}
				case JAL:
				int pc = (i*4);
				int target = ii->a3.imm;
				int diff = pc - target;
				if ( diff < 0 ) diff = -diff;

				if ( diff >= (1<<21) ) {
					printf( "JAL instruction target out of bounds\n" );
					exit(3);
				}
				break;
			}
		}
		if ( ii->a3.type == OPTYPE_LABEL ) {
			ii->a3.type = OPTYPE_IMM;
			ii->a3.imm = label_addr(ii->a3.label, labels, label_count, ii->orig_line);
			switch(ii->op) {
				case ADDI: {
					ii->a3.imm = ii->a3.imm&((1<<12)-1);
					char a1reg[4]; sprintf(a1reg, "x%02d", ii->a1.reg);
					char a2reg[4]; sprintf(a2reg, "x%02d", ii->a2.reg);
					char immd[12]; sprintf(immd, "0x%08x" , ii->a3.imm);
					//printf( "ADDI %d %d 0x%x %s\n", ii->a1.reg, ii->a2.reg, ii->a3.imm, immd );
					append_source("addi", a1reg, a2reg, immd, src, ii);
					break;
				}
				case BEQ: case BGE: case BGEU: case BLT: case BLTU: case BNE: {
					int pc = (i*4);
					int target = ii->a3.imm;
					int diff = pc - target;
					if ( diff < 0 ) diff = -diff;

					if ( diff >= (1<<13) ) {
						printf( "Branch instruction target out of bounds\n" );
						exit(3);
					}
					break;
				}
			}
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq %rcx, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
cmpl $0x2000, -0x24(%rbp)    # imm = 0x2000
jge 0x6b78
movq -0x8(%rbp), %rax
movslq -0x24(%rbp), %rcx
imulq $0x98, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x68d2
jmp 0x6b6a
movq -0x30(%rbp), %rax
cmpl $0x3, 0x4(%rax)
jne 0x6912
movq -0x30(%rbp), %rax
movl $0x2, 0x4(%rax)
movq -0x30(%rbp), %rdi
addq $0x4, %rdi
addq $0x4, %rdi
movq -0x10(%rbp), %rsi
movl -0x14(%rbp), %edx
movq -0x30(%rbp), %rax
movl 0x90(%rax), %ecx
callq 0x3d10
movl %eax, %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x2c(%rax)
movq -0x30(%rbp), %rax
cmpl $0x3, 0x30(%rax)
jne 0x6a26
movq -0x30(%rbp), %rax
movl $0x2, 0x30(%rax)
movq -0x30(%rbp), %rax
movq %rax, %rdi
addq $0x34, %rdi
movq -0x10(%rbp), %rsi
movl -0x14(%rbp), %edx
movl 0x90(%rax), %ecx
callq 0x3d10
movl %eax, %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x58(%rax)
movq -0x30(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x70(%rbp)
subl $0xc, %eax
je 0x69d4
jmp 0x6961
movl -0x70(%rbp), %eax
subl $0x12, %eax
jne 0x6a24
jmp 0x696f
movq -0x30(%rbp), %rax
movl 0x58(%rax), %ecx
shrl $0xc, %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x58(%rax)
leaq -0x34(%rbp), %rdi
movq -0x30(%rbp), %rax
movl 0x28(%rax), %edx
leaq 0x4c94(%rip), %rsi      # 0xb626
movb $0x0, %al
callq 0x2060
leaq -0x40(%rbp), %rdi
movq -0x30(%rbp), %rax
movl 0x58(%rax), %edx
leaq 0x4c81(%rip), %rsi      # 0xb62c
movb $0x0, %al
callq 0x2060
leaq -0x34(%rbp), %rsi
leaq -0x40(%rbp), %rdx
movq -0x20(%rbp), %r8
movq -0x30(%rbp), %r9
leaq 0x4a86(%rip), %rdi      # 0xb44f
xorl %eax, %eax
movl %eax, %ecx
callq 0x3b70
jmp 0x6a24
movl -0x24(%rbp), %eax
shll $0x2, %eax
movl %eax, -0x44(%rbp)
movq -0x30(%rbp), %rax
movl 0x84(%rax), %eax
movl %eax, -0x48(%rbp)
movl -0x44(%rbp), %eax
subl -0x48(%rbp), %eax
movl %eax, -0x4c(%rbp)
cmpl $0x0, -0x4c(%rbp)
jge 0x6a01
xorl %eax, %eax
subl -0x4c(%rbp), %eax
movl %eax, -0x4c(%rbp)
cmpl $0x200000, -0x4c(%rbp)  # imm = 0x200000
jl 0x6a22
leaq 0x4ed7(%rip), %rdi      # 0xb8e8
movb $0x0, %al
callq 0x2040
movl $0x3, %edi
callq 0x2250
jmp 0x6a24
jmp 0x6a26
movq -0x30(%rbp), %rax
cmpl $0x3, 0x5c(%rax)
jne 0x6b68
movq -0x30(%rbp), %rax
movl $0x2, 0x5c(%rax)
movq -0x30(%rbp), %rax
movq %rax, %rdi
addq $0x60, %rdi
movq -0x10(%rbp), %rsi
movl -0x14(%rbp), %edx
movl 0x90(%rax), %ecx
callq 0x3d10
movl %eax, %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x84(%rax)
movq -0x30(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x74(%rbp)
subl $0x2, %eax
je 0x6a8c
jmp 0x6a78
movl -0x74(%rbp), %eax
addl $-0x6, %eax
subl $0x6, %eax
jb 0x6b16
jmp 0x6b66
movq -0x30(%rbp), %rax
movl 0x84(%rax), %ecx
andl $0xfff, %ecx            # imm = 0xFFF
movq -0x30(%rbp), %rax
movl %ecx, 0x84(%rax)
leaq -0x50(%rbp), %rdi
movq -0x30(%rbp), %rax
movl 0x28(%rax), %edx
leaq 0x4b6e(%rip), %rsi      # 0xb626
movb $0x0, %al
callq 0x2060
leaq -0x54(%rbp), %rdi
movq -0x30(%rbp), %rax
movl 0x54(%rax), %edx
leaq 0x4b55(%rip), %rsi      # 0xb626
movb $0x0, %al
callq 0x2060
leaq -0x60(%rbp), %rdi
movq -0x30(%rbp), %rax
movl 0x84(%rax), %edx
leaq 0x4b3f(%rip), %rsi      # 0xb62c
movb $0x0, %al
callq 0x2060
leaq -0x50(%rbp), %rsi
leaq -0x54(%rbp), %rdx
leaq -0x60(%rbp), %rcx
movq -0x20(%rbp), %r8
movq -0x30(%rbp), %r9
leaq 0x48d4(%rip), %rdi      # 0xb3e3
callq 0x3b70
jmp 0x6b66
movl -0x24(%rbp), %eax
shll $0x2, %eax
movl %eax, -0x64(%rbp)
movq -0x30(%rbp), %rax
movl 0x84(%rax), %eax
movl %eax, -0x68(%rbp)
movl -0x64(%rbp), %eax
subl -0x68(%rbp), %eax
movl %eax, -0x6c(%rbp)
cmpl $0x0, -0x6c(%rbp)
jge 0x6b43
xorl %eax, %eax
subl -0x6c(%rbp), %eax
movl %eax, -0x6c(%rbp)
cmpl $0x2000, -0x6c(%rbp)    # imm = 0x2000
jl 0x6b64
leaq 0x4dbb(%rip), %rdi      # 0xb90e
movb $0x0, %al
callq 0x2040
movl $0x3, %edi
callq 0x2250
jmp 0x6b66
jmp 0x6b68
jmp 0x6b6a
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x68a1
addq $0x80, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)