// File: /workspace/github_c_makefile_star2_O3/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
xorl %ecx, %ecx
movl %ecx, 0x14(%rsp)
movl $0xfffff000, 0x38(%rsp) # imm = 0xFFFFF000
movl $0x1000, 0x10(%rsp)     # imm = 0x1000
movl $0x80000000, %eax       # imm = 0x80000000
movl %eax, 0x34(%rsp)
movl %eax, 0x30(%rsp)
movl $0x7ffff000, 0x2c(%rsp) # imm = 0x7FFFF000
movl %ecx, 0x20(%rsp)
movl %ecx, 0x1c(%rsp)
cmpl $0x2, %edi
jl 0x660d
movl $0x0, 0xc(%rsp)
movl $0x1, %r13d
leaq 0x754e(%rip), %r15      # 0xd852
leaq 0x7564(%rip), %r12      # 0xd86f
movl $0x0, 0x8(%rsp)
movl $0x0, 0x18(%rsp)
movslq %r13d, %rax
movq (%r14,%rax,8), %rbp
movq %rbp, %rdi
movq %r15, %rsi
callq 0x10c0
testl %eax, %eax
je 0x644e
movq %rbp, %rdi
movq %r12, %rsi
callq 0x10c0
testl %eax, %eax
je 0x6468
movq %rbp, %rdi
leaq 0x753a(%rip), %rsi      # 0xd88c
callq 0x10c0
testl %eax, %eax
je 0x6487
movq %rbp, %rdi
leaq 0x753e(%rip), %rsi      # 0xd8a7
callq 0x10c0
testl %eax, %eax
je 0x64c9
movq %rbp, %rdi
leaq 0x752f(%rip), %rsi      # 0xd8af
callq 0x10c0
testl %eax, %eax
je 0x64d3
movq %rbp, %rdi
leaq 0x7554(%rip), %rsi      # 0xd8eb
callq 0x10c0
testl %eax, %eax
je 0x64fc
movq %rbp, %rdi
leaq 0x7579(%rip), %rsi      # 0xd927
callq 0x10c0
testl %eax, %eax
je 0x6525
movq %rbp, %rdi
leaq 0x75a4(%rip), %rsi      # 0xd969
callq 0x10c0
testl %eax, %eax
je 0x692d
movq %rbp, %rdi
leaq 0x7594(%rip), %rsi      # 0xd970
callq 0x10c0
testl %eax, %eax
je 0x6552
movq %rbp, %rdi
leaq 0x75e3(%rip), %rsi      # 0xd9d6
callq 0x10c0
testl %eax, %eax
je 0x6586
movq %rbp, %rdi
leaq 0x762d(%rip), %rsi      # 0xda37
callq 0x10c0
testl %eax, %eax
je 0x65ba
movq %rbp, %rdi
leaq 0x7629(%rip), %rsi      # 0xda4a
callq 0x10c0
testl %eax, %eax
je 0x65c7
movq %rbp, %rdi
leaq 0x7658(%rip), %rsi      # 0xda90
callq 0x10c0
testl %eax, %eax
jne 0x69fa
movb $0x1, 0xccf4(%rip)      # 0x13140
jmp 0x64b8
incl %r13d
cmpl %ebx, %r13d
jge 0x6957
movslq %r13d, %rax
movq (%r14,%rax,8), %rdi
callq 0x9ecc
jmp 0x64b0
incl %r13d
cmpl %ebx, %r13d
jge 0x6961
movslq %r13d, %rax
movq (%r14,%rax,8), %rsi
leaq 0x14(%rsp), %rdi
callq 0x9f20
jmp 0x64b0
incl %r13d
cmpl %ebx, %r13d
jge 0x696b
movslq %r13d, %rax
movq (%r14,%rax,8), %rcx
leaq 0x14(%rsp), %rdi
leaq 0x10(%rsp), %rsi
leaq 0xcc81(%rip), %rdx      # 0x1312c
callq 0xa26c
testl %eax, %eax
je 0x6a15
incl %r13d
cmpl %ebx, %r13d
jl 0x631b
jmp 0x6625
movl $0x1, 0xc(%rsp)
jmp 0x64b8
incl %r13d
cmpl %ebx, %r13d
jge 0x6975
movslq %r13d, %rax
movq (%r14,%rax,8), %rbp
leaq 0x14(%rsp), %rdi
movq %rbp, %rsi
callq 0x61d8
testl %eax, %eax
jne 0x64b8
jmp 0x697f
incl %r13d
cmpl %ebx, %r13d
jge 0x6992
movslq %r13d, %rax
movq (%r14,%rax,8), %rbp
leaq 0x38(%rsp), %rdi
movq %rbp, %rsi
callq 0x61d8
testl %eax, %eax
jne 0x64b8
jmp 0x6999
incl %r13d
cmpl %ebx, %r13d
jge 0x69ac
movslq %r13d, %rax
movq (%r14,%rax,8), %rbp
leaq 0x10(%rsp), %rdi
movq %rbp, %rsi
callq 0x61d8
testl %eax, %eax
jne 0x64b8
jmp 0x69b3
movb $0x1, 0xcbeb(%rip)      # 0x13144
incl %r13d
cmpl %ebx, %r13d
jge 0x69c6
movslq %r13d, %rax
movq (%r14,%rax,8), %rbp
leaq 0x34(%rsp), %rdi
movq %rbp, %rsi
callq 0x61d8
testl %eax, %eax
jne 0x64b8
jmp 0x69cd
movb $0x1, 0xcb9b(%rip)      # 0x13128
incl %r13d
cmpl %ebx, %r13d
jge 0x69e0
movslq %r13d, %rax
movq (%r14,%rax,8), %rbp
leaq 0x30(%rsp), %rdi
movq %rbp, %rsi
callq 0x61d8
testl %eax, %eax
jne 0x64b8
jmp 0x69e7
movl $0x1, 0x18(%rsp)
jmp 0x64b8
incl %r13d
cmpl %ebx, %r13d
jge 0x6a2b
movslq %r13d, %rax
movq (%r14,%rax,8), %rbp
leaq 0x2c(%rsp), %rdi
movq %rbp, %rsi
callq 0x61d8
movl $0x1, 0x8(%rsp)
testl %eax, %eax
jne 0x64b8
movq 0xc9fa(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x744a(%rip), %rsi      # 0xda52
jmp 0x6a0b
movl $0x0, 0x18(%rsp)
movl $0x1, %r13d
xorl %r12d, %r12d
xorl %r15d, %r15d
xorl %ebp, %ebp
jmp 0x6631
xorl %ebp, %ebp
movl 0xc(%rsp), %r15d
movl 0x8(%rsp), %r12d
movl 0x10(%rsp), %esi
movl 0x38(%rsp), %ecx
movl %ecx, %edi
subl %esi, %edi
jb 0x68fb
movl 0x14(%rsp), %eax
movl %eax, 0xcad3(%rip)      # 0x13120
movl $0x2, 0xcacd(%rip)      # 0x13124
movq %rcx, 0x40(%rsp)
movl %ecx, 0xcaae(%rip)      # 0x13110
callq 0x6caf
testb %bpl, %bpl
je 0x67ea
movl 0x10(%rsp), %eax
movl $0x0, 0x28(%rsp)
movl %ebx, %edi
subl %r13d, %edi
movl %edi, 0x20(%rsp)
cmpl $0x3fffffff, %edi       # imm = 0x3FFFFFFF
jae 0x6905
leal 0x4(,%rdi,4), %ecx
cmpl %ecx, %eax
jb 0x690f
movq 0x40(%rsp), %rdx
movl %edx, %ebp
subl %eax, %ebp
movl %edx, %esi
subl %ecx, %esi
movl %esi, 0x4(%rsp)
movl %esi, 0x1c(%rsp)
xorl %eax, %eax
cmpl %r13d, %ebx
je 0x6776
movl %esi, 0x3c(%rsp)
movl %r12d, 0x8(%rsp)
movl %r15d, 0xc(%rsp)
movslq %r13d, %rax
leaq (%r14,%rax,8), %rax
movq %rax, 0x50(%rsp)
movl %ebp, 0x24(%rsp)
notl %ebp
movq %rdi, 0x48(%rsp)
movl %edi, %r12d
leal (%rdx,%r13,4), %r14d
shll $0x2, %ebx
subl %ebx, %r14d
addl $-0x4, %r14d
xorl %ebx, %ebx
movl 0x4(%rsp), %r13d
movq 0x50(%rsp), %rax
movq (%rax,%rbx,8), %r15
movq %r15, %rdi
callq 0x1080
cmpl 0x24(%rsp), %r13d
je 0x6938
leal (%r13,%rbp), %ecx
cmpq %rcx, %rax
ja 0x6938
incl %eax
subl %eax, %r13d
movl %r13d, 0x4(%rsp)
movq %r15, %rdi
movl %r13d, %esi
movl %eax, %edx
callq 0x6b71
leaq 0x4(%rsp), %rdi
movl %r14d, %esi
movl $0x4, %edx
callq 0x6b71
incq %rbx
addl $0x4, %r14d
cmpq %r12, %rbx
jb 0x66f8
movq 0x48(%rsp), %rax
shll $0x2, %eax
movl 0xc(%rsp), %r15d
movl 0x8(%rsp), %r12d
movl 0x24(%rsp), %ebp
movl 0x3c(%rsp), %esi
addl %eax, %esi
leaq 0x28(%rsp), %rdi
movl $0x4, %edx
callq 0x6b71
movl 0x4(%rsp), %esi
movl %esi, %eax
subl %ebp, %eax
cmpl $0xb, %eax
jbe 0x6919
leal -0xc(%rsi), %eax
movl %eax, 0x4(%rsp)
addl $-0x4, %esi
leaq 0x1c(%rsp), %rdi
movl $0x4, %edx
callq 0x6b71
movl 0x4(%rsp), %esi
addl $0x4, %esi
leaq 0x20(%rsp), %rdi
movl $0x4, %edx
callq 0x6b71
leaq 0x28(%rsp), %rdi
movl $0xfffffff0, (%rdi)     # imm = 0xFFFFFFF0
movl 0x4(%rsp), %esi
movl $0x4, %edx
callq 0x6b71
movl 0x4(%rsp), %eax
movl %eax, 0xc926(%rip)      # 0x13110
cmpl $0x0, 0x18(%rsp)
je 0x67ff
movq 0xc938(%rip), %rax      # 0x13130
movq %rax, 0xc939(%rip)      # 0x13138
cmpb $0x1, 0xc93e(%rip)      # 0x13144
jne 0x6819
movl 0x34(%rsp), %edi
callq 0xa768
testl %eax, %eax
je 0x6a15
cmpb $0x1, 0xc908(%rip)      # 0x13128
jne 0x6842
movl 0x30(%rsp), %esi
movl 0x20(%rsp), %edx
movl 0x1c(%rsp), %ecx
leaq 0xc8f7(%rip), %rdi      # 0x1312c
callq 0xadc0
testl %eax, %eax
je 0x6a15
testl %r12d, %r12d
je 0x68a2
movl 0x2c(%rsp), %ebx
cmpl $0xfffff001, %ebx       # imm = 0xFFFFF001
jae 0x6923
movl %ebx, 0xc903(%rip)      # 0x13160
movl %ebx, %edi
movl $0x1000, %esi           # imm = 0x1000
callq 0x6caf
leal 0x4(%rbx), %edi
movq 0x40(%rsp), %r14
movl %r14d, %esi
movl $0x4, %edx
callq 0x6f54
leal 0x8(%rbx), %edi
subl 0x10(%rsp), %r14d
movl %r14d, %esi
movl $0x4, %edx
callq 0x6f54
leal 0x18(%rbx), %edi
movl %ebx, %esi
movl $0x4, %edx
callq 0x6f54
testl %r15d, %r15d
je 0x68c0
movq 0xc722(%rip), %rax      # 0x12fd0
movq (%rax), %rdi
callq 0x1f8c
movl $0xa, %edi
callq 0x1040
callq 0x2125
xorl %ebx, %ebx
testl %eax, %eax
je 0x6a1a
movq 0xc6fa(%rip), %r14      # 0x12fd0
testl %r15d, %r15d
je 0x68ed
movq (%r14), %rdi
callq 0x1f8c
movl $0xa, %edi
callq 0x1040
callq 0x2125
testl %eax, %eax
jne 0x68d6
jmp 0x6a1a
callq 0x17e7
jmp 0x6a15
callq 0x17c5
jmp 0x6a15
callq 0x17a3
jmp 0x6a15
callq 0x1781
jmp 0x6a15
callq 0x175f
jmp 0x6a15
incl %r13d
movb $0x1, %bpl
jmp 0x6627
movq 0xc6b9(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x71c7(%rip), %rsi      # 0xdb10
movl %ebx, %edx
xorl %eax, %eax
callq 0x10d0
jmp 0x6a15
callq 0x173d
jmp 0x6a15
callq 0x171b
jmp 0x6a15
callq 0x16f9
jmp 0x6a15
callq 0x16d7
jmp 0x6a15
movq 0xc672(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x6f25(%rip), %rsi      # 0xd8b5
jmp 0x6a0b
callq 0x16b5
jmp 0x6a15
movq 0xc658(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x6f47(%rip), %rsi      # 0xd8f1
jmp 0x6a0b
callq 0x1693
jmp 0x6a15
movq 0xc63e(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x6f6f(%rip), %rsi      # 0xd933
jmp 0x6a0b
callq 0x1671
jmp 0x6a15
movq 0xc624(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x6fa0(%rip), %rsi      # 0xd97e
jmp 0x6a0b
callq 0x164f
jmp 0x6a15
movq 0xc60a(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x6fea(%rip), %rsi      # 0xd9e2
jmp 0x6a0b
movq 0xc5f7(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x708e(%rip), %rsi      # 0xda99
movq %rbp, %rdx
xorl %eax, %eax
callq 0x10d0
movl $0x1, %ebx
movl %ebx, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x162d
jmp 0x6a15
nop