// File: /workspace/github_c_makefile_star2_O3/jkbenaim[P]psfrag/psfrag.c
// Function: cmd_depends
char *cmd_depends(int argc, char **argv)
{
	__label__ out_return, out_dbclose, out_unmap, out_droptable;
	struct MappedFile_s m;
	char *msg = NULL;
	int rc;
	int fragnum;
	char pcode[6];

	switch (argc) {
	case 0 ... 2:
		msg = "must specify a Pokemon Stadium rom";
		goto out_return;
		break;
	case 3:
		msg = "must specify a fragment number";
		goto out_return;
		break;
	default:
		break;
	}

	rc = DB_Init(&db, ":memory:");
	if (rc != SQLITE_OK) {
		msg = "DB_Init oopsed";
		goto out_return;
	}

	m = MappedFile_Open(argv[2], false);
	if (m.data == NULL) {
		msg = "couldn't open rom";
		goto out_dbclose;
	}

	if (m.size < (1048576 + 4096)) {
		msg = "rom too small";
		goto out_unmap;
	}

	get_pcode(pcode, m.data);

	rc = DB_FragSearch(db, m.data, m.size);
	if (rc != SQLITE_OK) {
		msg = "DB_FragSearch oopsed";
		goto out_unmap;
	}

	fragnum = atoi(argv[3]);
	int fragaddr = DB_GetAddrForNum(db, fragnum);
	if (fragaddr == -1) {
		msg = "no fragment by that number";
		goto out_unmap;
	}
	//parse_relocs(m.data + fragaddr);
	uint32_t *fragbytes = m.data + fragaddr;

	// start

	rc = sqlite3_exec(
		db,
		"create temp table relocs(reloc_id integer primary key, pcode, fragnum, far, type, addr, target_addr, target_frag);",
		NULL, NULL, NULL
	);
	if (rc != SQLITE_OK) {
		msg = "create temp table failed";
		goto out_unmap;
	};

	sqlite3_stmt *stmt = NULL;
	rc = sqlite3_prepare_v2(
		db,
		"insert into temp.relocs(pcode, fragnum, far, type, addr, target_addr, target_frag) values (?, ?, ?, ?, ?, ?, ?);",
		-1,
		&stmt,
		NULL
	);
	if (rc != SQLITE_OK) {
		msg = "prepare";
		goto out_droptable;
	}

	rc = DB_Begin(db);
	if (rc != SQLITE_OK) {
		msg = "begin transaction";
		goto out_droptable;
	}
	struct fragment_s frag;
	memcpy(&frag, fragbytes, sizeof(struct fragment_s));
	uint32_t *words = (uint32_t *)fragbytes;
	uint32_t *reloc_words = words;
	reloc_words += htonl(frag.offset_relocs) / sizeof(uint32_t);
	uint32_t num_relocs = htonl(reloc_words[0]);
	reloc_words++;
	printf("%d relocations.\n", num_relocs);
	for(int i = 0; i<num_relocs; i++) {
		uint32_t reloc = htonl(reloc_words[i]);
		bool foreign = reloc & 0x80000000;
		uint32_t type = reloc & 0x7F000000;
		uint32_t addr = reloc & 0x00FFFFFF;
		uint32_t target = htonl(words[addr>>2]);
		uint32_t loc = -1;
		uint32_t n;
		int loc_fragnum = -2;

		char *zType = NULL;

		switch (type) {
		case 0x02000000:
			zType = "ptr";
			loc = target;
			break;
		case 0x04000000:
			zType = "j";
			loc = (target & 0x03FFFFFF) << 2;
			loc |= 0x80000000;
			break;
		case 0x05000000:
			zType = "lui";
			loc = (target & 0x0000FFFF) << 16;
			loc |= 0x80000000;
			break;
		case 0x06000000:
			zType = "addiu";
			loc = (target & 0x0000FFFF);
			if (!foreign)
				loc += get_vma(&frag);
			break;
		default:
			zType = "unknown";
			loc = -1;
			break;
		}

		n = (loc & 0x0FF00000)>>20;
		loc_fragnum = n - 16;
// 		printf("%5d %08x %8x %08x\t%s\t%d\n",
// 			i,
// 			reloc,
// 			addr,
// 			loc,
// 			zType,
// 			loc_fragnum
// 		);
		if (loc_fragnum < 0) continue;
// "insert into temp.relocs(pcode, fragnum, far, type, addr, target_addr, target_frag) values (?, ?, ?, ?, ?, ?, ?);"
		rc = sqlite3_bind_text(stmt, 1, pcode, -1, SQLITE_TRANSIENT);
		if (rc != SQLITE_OK) {msg = "bind 1";}
		rc = sqlite3_bind_int64(stmt, 2, fragnum);
		if (rc != SQLITE_OK) {msg = "bind 2";}
		rc = sqlite3_bind_int64(stmt, 3, foreign);
		if (rc != SQLITE_OK) {msg = "bind 3";}
		rc = sqlite3_bind_text(stmt, 4, zType, -1, SQLITE_STATIC);
		if (rc != SQLITE_OK) {msg = "bind 4";}
		rc = sqlite3_bind_int64(stmt, 5, addr);
		if (rc != SQLITE_OK) {msg = "bind 5";}
		rc = sqlite3_bind_int64(stmt, 6, loc);
		if (rc != SQLITE_OK) {msg = "bind 6";}
		rc = sqlite3_bind_int64(stmt, 7, loc_fragnum);
		if (rc != SQLITE_OK) {msg = "bind 7";}

		rc = sqlite3_step(stmt);
		if (rc != SQLITE_DONE) {msg = "step";}

		rc = sqlite3_reset(stmt);
		if (rc != SQLITE_OK) {msg = "reset";}
	}

	DB_End(db);

	rc = sqlite3_finalize(stmt);
	if (rc != SQLITE_OK) {msg = "finalize1"; goto out_droptable;}

	rc = sqlite3_prepare(
		db,
		"select distinct target_frag from temp.relocs where target_frag != fragnum order by target_frag;",
		-1,
		&stmt,
		NULL
	);
	if (rc != SQLITE_OK) { msg = "prepare2"; goto out_droptable;}

	bool did_print_first = false;
	while (SQLITE_DONE != (rc=sqlite3_step(stmt))) switch (rc) {
	case SQLITE_BUSY:
		break;
	case SQLITE_ERROR:
		msg = "sqlite3_step returned SQLITE_ERROR";
		goto out_finalize;
		break;
	case SQLITE_MISUSE:
		msg = "sqlite3_step returned SQLITE_MISUSE";
		goto out_finalize;
		break;
	default:
		msg = "sqlite3_step returned some other error";
		goto out_finalize;
		break;
	case SQLITE_ROW:
		printf("%s%d", did_print_first?", ":"Depends on ",sqlite3_column_int(stmt, 0));
		did_print_first = true;
		break;
	}

	if (did_print_first) {
		printf(".\n");
	} else {
		printf("No dependencies.\n");
	}

out_finalize:
	rc = sqlite3_finalize(stmt);
	if (!msg)
		if (rc != SQLITE_OK) {msg = "finalize2"; goto out_droptable;}
out_droptable:
	rc = sqlite3_exec(
		db,
		"drop table temp.relocs;",
		NULL, NULL, NULL
	);
out_unmap:
	MappedFile_Close(m);
out_dbclose:
	DB_Close(db);
out_return:
	if (msg) {
		return msg;
	} else {
		return NULL;
	}

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
cmpl $0x4, %edi
jae 0x8675
movl %edi, %eax
leaq 0x9e8b4(%rip), %rcx     # 0xa6f20
movq (%rcx,%rax,8), %rbx
jmp 0x8724
movq %rsi, %r14
leaq 0xa2b89(%rip), %rdi     # 0xab208
leaq 0x7dd19(%rip), %rsi     # 0x8639f
callq 0x93e4
testl %eax, %eax
je 0x869b
leaq 0x7dd12(%rip), %rbx     # 0x863a8
jmp 0x8724
movq 0x10(%r14), %rsi
leaq 0x58(%rsp), %rbx
movq %rbx, %rdi
xorl %edx, %edx
callq 0x9919
movq (%rbx), %rbx
testq %rbx, %rbx
je 0x86cd
movq 0x60(%rsp), %r15
cmpq $0x101000, %r15         # imm = 0x101000
jae 0x86d6
leaq 0x7dcfe(%rip), %rbx     # 0x863c9
jmp 0x8700
leaq 0x7dce3(%rip), %rbx     # 0x863b7
jmp 0x8718
leaq 0x42(%rsp), %rdi
movq %rbx, %rsi
callq 0x99c4
movq 0xa2b1e(%rip), %rdi     # 0xab208
movq %rbx, %rsi
movq %r15, %rdx
callq 0x96c6
testl %eax, %eax
je 0x8739
leaq 0x7dcd7(%rip), %rbx     # 0x863d7
movq 0x68(%rsp), %rax
movq %rax, 0x10(%rsp)
movups 0x58(%rsp), %xmm0
movups %xmm0, (%rsp)
callq 0x99aa
movq 0xa2ae9(%rip), %rdi     # 0xab208
callq 0x9410
movq %rbx, %rax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x18(%r14), %rdi
callq 0x82d0
movl %eax, %ebp
movq 0xa2abd(%rip), %rdi     # 0xab208
movl %eax, %esi
callq 0x9624
cmpl $-0x1, %eax
je 0x8784
movl %eax, %r14d
movq 0xa2aa7(%rip), %rdi     # 0xab208
leaq 0x7dde9(%rip), %rsi     # 0x86551
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x1497e
testl %eax, %eax
je 0x8790
leaq 0x7de45(%rip), %rbx     # 0x865c4
jmp 0x8700
leaq 0x7dcc4(%rip), %rbx     # 0x8644f
jmp 0x8700
leaq 0x20(%rsp), %rcx
movq $0x0, (%rcx)
movq 0xa2a65(%rip), %rdi     # 0xab208
leaq 0x7de33(%rip), %rsi     # 0x865dd
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
xorl %r8d, %r8d
callq 0x14dad
testl %eax, %eax
je 0x87c7
leaq 0x7e2c2(%rip), %rbx     # 0x86a84
jmp 0x8b97
movq 0xa2a3a(%rip), %rdi     # 0xab208
callq 0x9415
testl %eax, %eax
je 0x87e3
leaq 0x7de70(%rip), %rbx     # 0x8664e
jmp 0x8b97
movslq %r14d, %rax
addq %rax, %rbx
movups (%rbx), %xmm0
movups 0x10(%rbx), %xmm1
movaps %xmm1, 0x80(%rsp)
movaps %xmm0, 0x70(%rsp)
movl 0x84(%rsp), %r15d
bswapl %r15d
andl $-0x4, %r15d
movl (%rbx,%r15), %r14d
movl %r14d, %r13d
bswapl %r13d
leaq 0x7de43(%rip), %rdi     # 0x86660
xorl %r12d, %r12d
movl %r13d, %esi
xorl %eax, %eax
callq 0x80e0
testl %r14d, %r14d
je 0x8a83
addq %rbx, %r15
cmpl $0x1, %r13d
adcl $0x0, %r13d
movslq %ebp, %rax
movq %rax, 0x48(%rsp)
xorl %r14d, %r14d
xorl %r12d, %r12d
movq %r15, %rdx
movq %r15, 0x38(%rsp)
movq %r13, %rsi
movq %r13, 0x30(%rsp)
movl 0x4(%rdx,%r14,4), %ebp
bswapl %ebp
movl %ebp, %eax
andl $0x7f000000, %eax       # imm = 0x7F000000
addl $0xfe000000, %eax       # imm = 0xFE000000
shrl $0x18, %eax
movl $0xef, %r15d
cmpl $0x4, %eax
ja 0x8a72
movl %ebp, %ecx
andl $0xfffffc, %ecx         # imm = 0xFFFFFC
movl (%rbx,%rcx), %r13d
bswapl %r13d
leaq 0x7d76d(%rip), %rcx     # 0x86004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
leaq 0x7dddc(%rip), %rdi     # 0x86681
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
jmpq *%rax
leaq 0x7ddbe(%rip), %rdi     # 0x86671
jmp 0x890a
shll $0x10, %r13d
orl $0x80000000, %r13d      # imm = 0x80000000
leaq 0x7ddb0(%rip), %rdi     # 0x86677
jmp 0x890a
andl $0x3ffffff, %r13d       # imm = 0x3FFFFFF
leal -0x80000000(,%r13,4), %r13d
leaq 0x7dd96(%rip), %rdi     # 0x86675
jmp 0x890a
movzwl %r13w, %r13d
testl %ebp, %ebp
js 0x8903
leaq 0x70(%rsp), %rdi
callq 0x9846
movq 0x30(%rsp), %rsi
movq 0x38(%rsp), %rdx
addl %r13d, %eax
movl %eax, %r13d
leaq 0x7dd71(%rip), %rdi     # 0x8667b
movl %r13d, %eax
shrl $0x14, %eax
movzbl %al, %r15d
movl %r13d, %ecx
subl $0x10, %r15d
jb 0x8a64
movq %rdi, 0x50(%rsp)
movl %ecx, 0x2c(%rsp)
movl %ebp, %r13d
andl $0xffffff, %r13d        # imm = 0xFFFFFF
movq 0x20(%rsp), %rdi
movl $0x1, %esi
leaq 0x42(%rsp), %rdx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movq $-0x1, %r8
callq 0x1257a
testl %eax, %eax
leaq 0x7dd2c(%rip), %rax     # 0x86689
cmovneq %rax, %r12
movq 0x20(%rsp), %rdi
movl $0x2, %esi
movq 0x48(%rsp), %rdx
callq 0x12444
testl %eax, %eax
leaq 0x7dd12(%rip), %rax     # 0x86690
cmovneq %rax, %r12
movq 0x20(%rsp), %rdi
shrl $0x1f, %ebp
movl $0x3, %esi
movq %rbp, %rdx
callq 0x12444
testl %eax, %eax
leaq 0x7dcf7(%rip), %rax     # 0x86697
cmovneq %rax, %r12
movq 0x20(%rsp), %rdi
movl $0x4, %esi
movq 0x50(%rsp), %rdx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
xorl %r8d, %r8d
callq 0x1257a
testl %eax, %eax
leaq 0x7dcd5(%rip), %rax     # 0x8669e
cmovneq %rax, %r12
movq 0x20(%rsp), %rdi
movl %r13d, %edx
movl $0x5, %esi
callq 0x12444
testl %eax, %eax
leaq 0x7dcbd(%rip), %rax     # 0x866a5
cmovneq %rax, %r12
movq 0x20(%rsp), %rdi
movl 0x2c(%rsp), %edx
movl $0x6, %esi
callq 0x12444
testl %eax, %eax
leaq 0x7dca4(%rip), %rax     # 0x866ac
cmovneq %rax, %r12
movq 0x20(%rsp), %rdi
movl %r15d, %edx
movl $0x7, %esi
callq 0x12444
testl %eax, %eax
leaq 0x7dc8c(%rip), %rax     # 0x866b3
cmovneq %rax, %r12
movq 0x20(%rsp), %rdi
callq 0x10dca
cmpl $0x65, %eax
leaq 0x7e037(%rip), %rax     # 0x86a76
cmovneq %rax, %r12
movq 0x20(%rsp), %rdi
callq 0x10214
movq 0x30(%rsp), %rsi
movq 0x38(%rsp), %rdx
testl %eax, %eax
leaq 0x7dc5a(%rip), %rax     # 0x866ba
cmovneq %rax, %r12
incq %r14
cmpq %r14, %rsi
jne 0x885c
jmp 0x8a83
leaq 0x7dc08(%rip), %rdi     # 0x86681
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
jmp 0x8921
movq 0xa277e(%rip), %rdi     # 0xab208
callq 0x9428
movq 0x20(%rsp), %rdi
callq 0x100a7
testl %eax, %eax
je 0x8aa9
leaq 0x7dc1c(%rip), %rbx     # 0x866c0
jmp 0x8b97
movq 0xa2758(%rip), %rdi     # 0xab208
leaq 0x7dc13(%rip), %rsi     # 0x866ca
leaq 0x20(%rsp), %rcx
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
xorl %r8d, %r8d
callq 0x15666
testl %eax, %eax
je 0x8ad9
leaq 0x7dc56(%rip), %rbx     # 0x8672a
jmp 0x8b97
xorl %ebp, %ebp
leaq 0x7dc56(%rip), %r15     # 0x86738
leaq 0x7dc52(%rip), %r13     # 0x8673b
leaq 0x7dc43(%rip), %rbx     # 0x86733
movq 0x20(%rsp), %rdi
callq 0x10dca
cmpl $0x5, %eax
je 0x8af0
cmpl $0x63, %eax
jle 0x8b39
cmpl $0x65, %eax
je 0x8b55
cmpl $0x64, %eax
jne 0x8b4c
testb $0x1, %bpl
movq %r13, %r14
cmovneq %r15, %r14
movq 0x20(%rsp), %rdi
xorl %esi, %esi
callq 0x11ee9
movq %rbx, %rdi
movq %r14, %rsi
movl %eax, %edx
xorl %eax, %eax
callq 0x80e0
movb $0x1, %bpl
jmp 0x8af0
cmpl $0x1, %eax
je 0x8b64
cmpl $0x15, %eax
jne 0x8b4c
leaq 0x7d7b4(%rip), %r12     # 0x862fe
jmp 0x8b79
leaq 0x7d7cf(%rip), %r12     # 0x86322
jmp 0x8b79
testb $0x1, %bpl
je 0x8b6d
leaq 0x84089(%rip), %rdi     # 0x8cbeb
jmp 0x8b74
leaq 0x7d770(%rip), %r12     # 0x862db
jmp 0x8b79
leaq 0x7dcd8(%rip), %rdi     # 0x8684c
callq 0x8090
movq 0x20(%rsp), %rdi
callq 0x100a7
testl %eax, %eax
leaq 0x7dbbb(%rip), %rbx     # 0x86747
cmoveq %r12, %rbx
testq %r12, %r12
cmovneq %r12, %rbx
movq 0xa266a(%rip), %rdi     # 0xab208
leaq 0x7dbac(%rip), %rsi     # 0x86751
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x1497e
jmp 0x8700