// File: /workspace/github_c_makefile_star2_O2/mikecat[P]x86_interpreter/x86_interpreter.c
// Function: main
int main(int argc, char *argv[]) {
	int i;
	int enable_trace = 0;
	int enable_args = 0;
	int import_as_iat = 0;
	int enable_fs = 0;
	uint32_t initial_eip = 0;
	uint32_t initial_esp = UINT32_C(0xfffff000);
	uint32_t stack_size = 4096;
	uint32_t xv6_syscall_work = UINT32_C(0x80000000);
	uint32_t pe_import_work = UINT32_C(0x80000000);
	uint32_t fs_addr = UINT32_C(0x7ffff000);
	uint32_t argc2 = 0, argv_addr = 0;
	for (i = 1; i < argc; i++) {
		if (strcmp(argv[i], "--raw") == 0) {
			if (++i < argc) { if (!read_raw(argv[i])) return 1; }
			else { fprintf(stderr, "no filename for --raw\n"); return 1; }
		} else if (strcmp(argv[i], "--elf") == 0) {
			if (++i < argc) { if (!read_elf(&initial_eip, argv[i])) return 1; }
			else { fprintf(stderr, "no filename for --elf\n"); return 1; }
		} else if (strcmp(argv[i], "--pe") == 0) {
			if (++i < argc) { if (!read_pe(&initial_eip, &stack_size, &import_params, argv[i])) return 1; }
			else { fprintf(stderr, "no filename for --pe\n"); return 1; }
		} else if (strcmp(argv[i], "--trace") == 0) {
			enable_trace = 1;
		} else if (strcmp(argv[i], "--eip") == 0) {
			if (++i < argc) {
				if (!str_to_uint32(&initial_eip, argv[i])) {
					fprintf(stderr, "invalid initial eip value %s\n", argv[i]);
					return 1;
				}
			} else { fprintf(stderr, "no eip value for --eip\n"); return 1;}
		} else if (strcmp(argv[i], "--esp") == 0) {
			if (++i < argc) {
				if (!str_to_uint32(&initial_esp, argv[i])) {
					fprintf(stderr, "invalid initial esp value %s\n", argv[i]);
					return 1;
				}
			} else { fprintf(stderr, "no esp value for --esp\n"); return 1;}
		} else if (strcmp(argv[i], "--stacksize") == 0) {
			if (++i < argc) {
				if (!str_to_uint32(&stack_size, argv[i])) {
					fprintf(stderr, "invalid stack size %s\n", argv[i]);
					return 1;
				}
			} else { fprintf(stderr, "no stack size for --stacksize\n"); return 1;}
		} else if (strcmp(argv[i], "--args") == 0) {
			i++;
			enable_args = 1;
			break;
		} else if (strcmp(argv[i], "--xv6-syscall") == 0) {
			use_xv6_syscall = 1;
			if (++i < argc) {
				if (!str_to_uint32(&xv6_syscall_work, argv[i])) {
					fprintf(stderr, "invalid xv6 system call work buffer origin %s\n", argv[i]);
					return 1;
				}
			} else { fprintf(stderr, "no work buffer origin for --xv6-syscall\n"); return 1;}
		} else if (strcmp(argv[i], "--pe-import") == 0) {
			use_pe_import = 1;
			if (++i < argc) {
				if (!str_to_uint32(&pe_import_work, argv[i])) {
					fprintf(stderr, "invalid PE import libs work buffer origin %s\n", argv[i]);
					return 1;
				}
			} else { fprintf(stderr, "no work buffer origin for --pe-import\n"); return 1;}
		} else if (strcmp(argv[i], "--pe-import-as-iat") == 0) {
			import_as_iat = 1;
		} else if (strcmp(argv[i], "--pe-fs") == 0) {
			enable_fs = 1;
			if (++i < argc) {
				if (!str_to_uint32(&fs_addr, argv[i])) {
					fprintf(stderr, "invalid FS buffer origin %s\n", argv[i]);
					return 1;
				}
			} else { fprintf(stderr, "no FS buffer origin for --pe-fs\n"); return 1;}
		} else if (strcmp(argv[i], "--strict") == 0) {
			strict_mode = 1;
		} else {
			fprintf(stderr, "unknown command line option %s\n", argv[i]);
			return 1;
		}
	}
	if (stack_size > initial_esp) {
		fprintf(stderr, "stack too big compared to esp\n");
		return 1;
	}

	eip = initial_eip;
	eflags = UINT32_C(0x00000002);
	regs[ESP] = initial_esp;
	dmemory_allocate(initial_esp - stack_size, stack_size);
	if (enable_args) {
		uint32_t j;
		char** argv2 = argv + i;
		uint32_t stack_limit = initial_esp - stack_size;
		uint32_t current_addr = initial_esp;
		uint32_t num_buffer = 0;
		argc2 = argc - i;
		/* argvが指す配列の領域を確保する */
		if (argc2 == UINT32_MAX || UINT32_MAX / 4 < (argc2 + 1)) {
			fprintf(stderr, "too many arguments\n");
			return 1;
		}
		if (current_addr - stack_limit < 4 * (argc2 + 1)) {
			fprintf(stderr, "stack too small to hold argv table\n");
			return 1;
		}
		current_addr -= 4 * (argc2 + 1);
		argv_addr = current_addr;
		/* 引数の文字列とargvが指す配列の値を書き込む */
		for (j = 0; j < argc2; j++) {
			uint32_t stack_left = current_addr - stack_limit;
			size_t alen = strlen(argv2[j]);
			if (stack_left == 0 || stack_left - 1 < alen) {
				fprintf(stderr, "stack too small to hold argv[%"PRIu32"]\n", j);
				return 1;
			}
			current_addr -= alen + 1;
			dmemory_write(argv2[j], current_addr, alen + 1);
			dmemory_write(&current_addr, argv_addr + j * 4, sizeof(current_addr));
		}
		dmemory_write(&num_buffer, argv_addr + argc2 * 4, sizeof(num_buffer));
		if (current_addr - stack_limit < 12) {
			fprintf(stderr, "stack too small to hold arguments\n");
			return 1;
		}
		/* main関数に渡す引数とダミーのリターンアドレスを書き込む */
		current_addr -= 12;
		dmemory_write(&argv_addr, current_addr + 8, sizeof(argv_addr));
		dmemory_write(&argc2, current_addr + 4, sizeof(argc2));
		num_buffer = UINT32_C(0xfffffff0);
		dmemory_write(&num_buffer, current_addr, sizeof(num_buffer));
		regs[ESP] = current_addr;
	}
	if (import_as_iat) {
		import_params.iat_addr = import_params.import_addr;
		import_params.iat_size = import_params.import_size;
	}
	if (use_xv6_syscall) {
		if (!initialize_xv6_syscall(xv6_syscall_work)) return 1;
	}
	if (use_pe_import) {
		if (!pe_import_initialize(&import_params, pe_import_work, argc2, argv_addr)) return 1;
	}
	if (enable_fs) {
		if (UINT32_MAX - 0x1000  + 1 < fs_addr) {
			fprintf(stderr, "FS buffer address too high!\n");
			return 1;
		}
		segment_offsets[FS] = fs_addr;
		dmemory_allocate(fs_addr, 0x1000);
		dmem_write_uint(fs_addr + 0x004, initial_esp, 4);
		dmem_write_uint(fs_addr + 0x008, initial_esp - stack_size, 4);
		dmem_write_uint(fs_addr + 0x018, fs_addr, 4);
	}

	if (enable_trace) {
		print_regs(stdout);
		putchar('\n');
	}
	while(step()) {
		if (enable_trace) {
			print_regs(stdout);
			putchar('\n');
		}
	}
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rsi, %r14
movl %edi, %ebx
leaq 0x8(%rsp), %rax
andl $0x0, (%rax)
leaq 0x38(%rsp), %rax
movl $0xfffff000, (%rax)     # imm = 0xFFFFF000
leaq 0x4(%rsp), %rax
movl $0x1000, (%rax)         # imm = 0x1000
movl $0x80000000, %eax       # imm = 0x80000000
leaq 0x34(%rsp), %rcx
movl %eax, (%rcx)
leaq 0x30(%rsp), %rcx
movl %eax, (%rcx)
andl $0x0, 0x10(%rsp)
leaq 0x2c(%rsp), %rax
andl $0x0, 0xc(%rsp)
movl $0x7ffff000, (%rax)     # imm = 0x7FFFF000
pushq $0x1
popq %rax
movl $0x0, 0x18(%rsp)
leaq 0x73c0(%rip), %r12      # 0xc812
leaq 0x73d6(%rip), %rbp      # 0xc82f
movl $0x0, 0x14(%rsp)
movl $0x0, 0x20(%rsp)
movl %eax, 0x1c(%rsp)
movl %eax, %r15d
cmpl %ebx, %r15d
jge 0x575f
movslq %r15d, %rax
movq (%r14,%rax,8), %r13
movq %r13, %rdi
movq %r12, %rsi
callq 0x10c0
testl %eax, %eax
je 0x55ac
movq %r13, %rdi
movq %rbp, %rsi
callq 0x10c0
testl %eax, %eax
je 0x55c6
movq %r13, %rdi
leaq 0x739c(%rip), %rsi      # 0xc84c
callq 0x10c0
testl %eax, %eax
je 0x55e5
movq %r13, %rdi
leaq 0x73a0(%rip), %rsi      # 0xc867
callq 0x10c0
testl %eax, %eax
je 0x561e
movq %r13, %rdi
leaq 0x7391(%rip), %rsi      # 0xc86f
callq 0x10c0
testl %eax, %eax
je 0x5627
movq %r13, %rdi
leaq 0x73b6(%rip), %rsi      # 0xc8ab
callq 0x10c0
testl %eax, %eax
je 0x5650
movq %r13, %rdi
leaq 0x73db(%rip), %rsi      # 0xc8e7
callq 0x10c0
testl %eax, %eax
je 0x5679
movq %r13, %rdi
leaq 0x7406(%rip), %rsi      # 0xc929
callq 0x10c0
testl %eax, %eax
je 0x59f0
movq %r13, %rdi
leaq 0x73f6(%rip), %rsi      # 0xc930
callq 0x10c0
testl %eax, %eax
je 0x56a6
movq %r13, %rdi
leaq 0x7445(%rip), %rsi      # 0xc996
callq 0x10c0
testl %eax, %eax
je 0x56da
movq %r13, %rdi
leaq 0x748f(%rip), %rsi      # 0xc9f7
callq 0x10c0
testl %eax, %eax
je 0x570e
movq %r13, %rdi
leaq 0x748b(%rip), %rsi      # 0xca0a
callq 0x10c0
testl %eax, %eax
je 0x571a
movq %r13, %rdi
leaq 0x74ba(%rip), %rsi      # 0xca50
callq 0x10c0
testl %eax, %eax
jne 0x5b97
movb $0x1, 0xcb96(%rip)      # 0x12140
jmp 0x5616
incl %r15d
cmpl %ebx, %r15d
jge 0x5a58
movslq %r15d, %rax
movq (%r14,%rax,8), %rdi
callq 0x8d24
jmp 0x560e
incl %r15d
cmpl %ebx, %r15d
jge 0x5a80
movslq %r15d, %rax
movq (%r14,%rax,8), %rsi
leaq 0x8(%rsp), %rdi
callq 0x8d70
jmp 0x560e
incl %r15d
cmpl %ebx, %r15d
jge 0x5aaf
movslq %r15d, %rax
movq (%r14,%rax,8), %rcx
leaq 0x8(%rsp), %rdi
leaq 0x4(%rsp), %rsi
leaq 0xcb23(%rip), %rdx      # 0x1212c
callq 0x9108
testl %eax, %eax
je 0x5a9c
incl %r15d
jmp 0x5470
pushq $0x1
popq %rax
movl %eax, 0x20(%rsp)
jmp 0x5616
incl %r15d
cmpl %ebx, %r15d
jge 0x5ac4
movslq %r15d, %rax
movq (%r14,%rax,8), %r13
leaq 0x8(%rsp), %rdi
movq %r13, %rsi
callq 0x533e
testl %eax, %eax
jne 0x5616
jmp 0x5ad7
incl %r15d
cmpl %ebx, %r15d
jge 0x5aed
movslq %r15d, %rax
movq (%r14,%rax,8), %r13
leaq 0x38(%rsp), %rdi
movq %r13, %rsi
callq 0x533e
testl %eax, %eax
jne 0x5616
jmp 0x5b02
incl %r15d
cmpl %ebx, %r15d
jge 0x5b18
movslq %r15d, %rax
movq (%r14,%rax,8), %r13
leaq 0x4(%rsp), %rdi
movq %r13, %rsi
callq 0x533e
testl %eax, %eax
jne 0x5616
jmp 0x5b2e
movb $0x1, 0xca97(%rip)      # 0x12144
incl %r15d
cmpl %ebx, %r15d
jge 0x5b41
movslq %r15d, %rax
movq (%r14,%rax,8), %r13
leaq 0x34(%rsp), %rdi
movq %r13, %rsi
callq 0x533e
testl %eax, %eax
jne 0x5616
jmp 0x5b59
movb $0x1, 0xca47(%rip)      # 0x12128
incl %r15d
cmpl %ebx, %r15d
jge 0x5b6c
movslq %r15d, %rax
movq (%r14,%rax,8), %r13
leaq 0x30(%rsp), %rdi
movq %r13, %rsi
callq 0x533e
testl %eax, %eax
jne 0x5616
jmp 0x5b84
pushq $0x1
popq %rax
movl %eax, 0x18(%rsp)
jmp 0x5616
incl %r15d
cmpl %ebx, %r15d
jge 0x5bb7
movslq %r15d, %rax
movq (%r14,%rax,8), %r13
leaq 0x2c(%rsp), %rdi
movq %r13, %rsi
callq 0x533e
pushq $0x1
popq %rcx
movl %ecx, 0x14(%rsp)
testl %eax, %eax
jne 0x5616
movq 0xc8a8(%rip), %rax      # 0x11ff8
movq (%rax), %rdi
leaq 0x72b8(%rip), %rsi      # 0xca12
jmp 0x5ba8
movl %r15d, %r12d
movl 0x4(%rsp), %esi
movl 0x38(%rsp), %r13d
movl %r13d, %edi
subl %esi, %edi
jb 0x59d8
movl 0x8(%rsp), %eax
movl %eax, 0xc9a0(%rip)      # 0x12120
movl $0x2, 0xc99a(%rip)      # 0x12124
movl %r13d, 0xc97f(%rip)     # 0x12110
callq 0x5e70
cmpl %ebx, %r15d
jge 0x58e8
movl 0x4(%rsp), %eax
andl $0x0, 0x28(%rsp)
movl %ebx, %esi
subl %r12d, %esi
movl %esi, 0x10(%rsp)
cmpl $0x3fffffff, %esi       # imm = 0x3FFFFFFF
jae 0x59f9
leal 0x4(,%rsi,4), %ecx
cmpl %ecx, %eax
jb 0x5a11
movslq %r12d, %rdx
leaq (%r14,%rdx,8), %rdx
movq %rdx, 0x50(%rsp)
movl %r13d, %edx
subl %eax, %edx
movl %r13d, %eax
subl %ecx, %eax
movq %rsp, %rcx
movl %eax, (%rcx)
movl %eax, 0x3c(%rsp)
movl %eax, 0xc(%rsp)
movl %edx, 0x24(%rsp)
movl %edx, %r15d
notl %r15d
movl %esi, %ebp
shll $0x2, %esi
movq %rsi, 0x48(%rsp)
movq %r13, 0x40(%rsp)
leal (%r13,%r12,4), %r13d
shll $0x2, %ebx
subl %ebx, %r13d
addl $-0x4, %r13d
xorl %r12d, %r12d
cmpq %rbp, %r12
jae 0x5874
movl (%rsp), %ebx
movq 0x50(%rsp), %rax
movq (%rax,%r12,8), %r14
movq %r14, %rdi
callq 0x1080
cmpl 0x24(%rsp), %ebx
je 0x5a26
leal (%rbx,%r15), %ecx
cmpq %rcx, %rax
ja 0x5a26
incl %eax
subl %eax, %ebx
movl %ebx, (%rsp)
movq %r14, %rdi
movl %ebx, %esi
movl %eax, %edx
callq 0x5d3e
movq %rsp, %rdi
movl %r13d, %esi
pushq $0x4
popq %rdx
callq 0x5d3e
incq %r12
addl $0x4, %r13d
jmp 0x581a
movl 0x3c(%rsp), %esi
addl 0x48(%rsp), %esi
leaq 0x28(%rsp), %rdi
pushq $0x4
popq %rdx
callq 0x5d3e
movl (%rsp), %esi
movl %esi, %eax
subl 0x24(%rsp), %eax
cmpl $0xb, %eax
jbe 0x5a43
leal -0xc(%rsi), %eax
movl %eax, (%rsp)
addl $-0x4, %esi
leaq 0xc(%rsp), %rdi
pushq $0x4
popq %rbx
movl %ebx, %edx
callq 0x5d3e
movl (%rsp), %esi
addl $0x4, %esi
leaq 0x10(%rsp), %rdi
movl %ebx, %edx
callq 0x5d3e
leaq 0x28(%rsp), %rdi
movl $0xfffffff0, (%rdi)     # imm = 0xFFFFFFF0
movl (%rsp), %esi
movl %ebx, %edx
callq 0x5d3e
movl (%rsp), %eax
movl %eax, 0xc82d(%rip)      # 0x12110
movq 0x40(%rsp), %r13
cmpl $0x0, 0x18(%rsp)
je 0x58fd
movq 0xc83a(%rip), %rax      # 0x12130
movq %rax, 0xc83b(%rip)      # 0x12138
cmpb $0x1, 0xc840(%rip)      # 0x12144
movl 0x20(%rsp), %ebp
jne 0x591b
movl 0x34(%rsp), %edi
callq 0x963c
testl %eax, %eax
je 0x5a9c
cmpb $0x1, 0xc806(%rip)      # 0x12128
jne 0x5944
movl 0x30(%rsp), %esi
movl 0x10(%rsp), %edx
movl 0xc(%rsp), %ecx
leaq 0xc7f5(%rip), %rdi      # 0x1212c
callq 0x9ca0
testl %eax, %eax
je 0x5a9c
cmpl $0x0, 0x14(%rsp)
je 0x59be
movl 0x2c(%rsp), %r14d
cmpl $0xfffff001, %r14d      # imm = 0xFFFFF001
jae 0x5a6b
movl %r14d, 0xc7fc(%rip)     # 0x12160
movl %r14d, %edi
movl $0x1000, %esi           # imm = 0x1000
callq 0x5e70
leal 0x4(%r14), %edi
pushq $0x4
popq %rbx
movl %r13d, %esi
movl %ebx, %edx
callq 0x6110
leal 0x8(%r14), %edi
subl 0x4(%rsp), %r13d
movl %r13d, %esi
movl %ebx, %edx
callq 0x6110
leal 0x18(%r14), %edi
movl %r14d, %esi
movl %ebx, %edx
callq 0x6110
jmp 0x59be
movq 0xc624(%rip), %rax      # 0x11fd0
movq (%rax), %rdi
callq 0x12ac
pushq $0xa
popq %rdi
callq 0x1040
jmp 0x59c2
testl %ebp, %ebp
jne 0x59a5
callq 0x1426
testl %eax, %eax
jne 0x59be
movl $0x0, 0x1c(%rsp)
jmp 0x5a9c
movq 0xc619(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x7090(%rip), %rdi      # 0xca79
pushq $0x1e
jmp 0x5a93
leal 0x1(%r15), %r12d
jmp 0x5762
movq 0xc5f8(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x708e(%rip), %rdi      # 0xca98
pushq $0x13
jmp 0x5a93
movq 0xc5e0(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x708a(%rip), %rdi      # 0xcaac
pushq $0x23
jmp 0x5a93
movq 0xc5cb(%rip), %rax      # 0x11ff8
movq (%rax), %rdi
leaq 0x7099(%rip), %rsi      # 0xcad0
movl %r12d, %edx
xorl %eax, %eax
callq 0x10d0
jmp 0x5a9c
movq 0xc5ae(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x709e(%rip), %rdi      # 0xcaf2
pushq $0x22
jmp 0x5a93
movq 0xc599(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x6daf(%rip), %rdi      # 0xc818
jmp 0x5a91
movq 0xc586(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x7099(%rip), %rdi      # 0xcb15
pushq $0x1c
jmp 0x5a93
movq 0xc571(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x6da4(%rip), %rdi      # 0xc835
pushq $0x16
popq %rsi
pushq $0x1
popq %rdx
callq 0x1190
movl 0x1c(%rsp), %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0xc542(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x6d91(%rip), %rdi      # 0xc851
pushq $0x15
jmp 0x5a93
movq 0xc52d(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x6dbe(%rip), %rdi      # 0xc893
jmp 0x5afe
movq 0xc51a(%rip), %rax      # 0x11ff8
movq (%rax), %rdi
leaq 0x6d8d(%rip), %rsi      # 0xc875
jmp 0x5ba8
movq 0xc504(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x6dd1(%rip), %rdi      # 0xc8cf
pushq $0x17
jmp 0x5a93
movq 0xc4ef(%rip), %rax      # 0x11ff8
movq (%rax), %rdi
leaq 0x6d9e(%rip), %rsi      # 0xc8b1
jmp 0x5ba8
movq 0xc4d9(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x6de1(%rip), %rdi      # 0xc90a
jmp 0x59e9
movq 0xc4c3(%rip), %rax      # 0x11ff8
movq (%rax), %rdi
leaq 0x6db4(%rip), %rsi      # 0xc8f3
jmp 0x5ba8
movq 0xc4b0(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x6e1b(%rip), %rdi      # 0xc96d
pushq $0x28
jmp 0x5a93
movq 0xc498(%rip), %rax      # 0x11ff8
movq (%rax), %rdi
leaq 0x6dd4(%rip), %rsi      # 0xc93e
jmp 0x5ba8
movq 0xc485(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x6e53(%rip), %rdi      # 0xc9d0
pushq $0x26
jmp 0x5a93
movq 0xc46d(%rip), %rax      # 0x11ff8
movq (%rax), %rdi
leaq 0x6e0d(%rip), %rsi      # 0xc9a2
jmp 0x5ba8
movq 0xc45a(%rip), %rax      # 0x11ff8
movq (%rax), %rdi
leaq 0x6eb1(%rip), %rsi      # 0xca59
movq %r13, %rdx
xorl %eax, %eax
callq 0x10d0
jmp 0x5a9c
movq 0xc43a(%rip), %rax      # 0x11ff8
movq (%rax), %rcx
leaq 0x6e67(%rip), %rdi      # 0xca2f
pushq $0x20
jmp 0x5a93
nop