// File: /workspace/github_c_makefile_star2_O1/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, %rbx
movl %edi, %r14d
xorl %ecx, %ecx
movl %ecx, 0x1c(%rsp)
movl $0xfffff000, 0x44(%rsp) # imm = 0xFFFFF000
movl $0x1000, 0x18(%rsp)     # imm = 0x1000
movl $0x80000000, %eax       # imm = 0x80000000
movl %eax, 0x40(%rsp)
movl %eax, 0x3c(%rsp)
movl $0x7ffff000, 0x38(%rsp) # imm = 0x7FFFF000
movl %ecx, 0x14(%rsp)
movl %ecx, 0x10(%rsp)
movl $0x1, %r13d
cmpl $0x2, %edi
setge %r12b
jl 0x67fe
movl $0x0, 0x2c(%rsp)
leaq 0x72f6(%rip), %r15      # 0xd7ea
movl $0x0, 0x24(%rsp)
movl $0x0, 0x28(%rsp)
movslq %r13d, %rax
movq (%rbx,%rax,8), %rbp
movq %rbp, %rdi
movq %r15, %rsi
callq 0x10c0
testl %eax, %eax
je 0x663b
movq %rbp, %rdi
leaq 0x72df(%rip), %rsi      # 0xd807
callq 0x10c0
testl %eax, %eax
je 0x6655
movq %rbp, %rdi
leaq 0x72e5(%rip), %rsi      # 0xd824
callq 0x10c0
testl %eax, %eax
je 0x6674
movq %rbp, %rdi
leaq 0x72e9(%rip), %rsi      # 0xd83f
callq 0x10c0
testl %eax, %eax
je 0x66ba
movq %rbp, %rdi
leaq 0x72da(%rip), %rsi      # 0xd847
callq 0x10c0
testl %eax, %eax
je 0x66c4
movq %rbp, %rdi
leaq 0x72ff(%rip), %rsi      # 0xd883
callq 0x10c0
testl %eax, %eax
je 0x66ed
movq %rbp, %rdi
leaq 0x7324(%rip), %rsi      # 0xd8bf
callq 0x10c0
testl %eax, %eax
je 0x6716
movq %rbp, %rdi
leaq 0x734f(%rip), %rsi      # 0xd901
callq 0x10c0
testl %eax, %eax
je 0x6b4d
movq %rbp, %rdi
leaq 0x733f(%rip), %rsi      # 0xd908
callq 0x10c0
testl %eax, %eax
je 0x6743
movq %rbp, %rdi
leaq 0x738e(%rip), %rsi      # 0xd96e
callq 0x10c0
testl %eax, %eax
je 0x6777
movq %rbp, %rdi
leaq 0x73d8(%rip), %rsi      # 0xd9cf
callq 0x10c0
testl %eax, %eax
je 0x67ab
movq %rbp, %rdi
leaq 0x73d4(%rip), %rsi      # 0xd9e2
callq 0x10c0
testl %eax, %eax
je 0x67b8
movq %rbp, %rdi
leaq 0x7403(%rip), %rsi      # 0xda28
callq 0x10c0
testl %eax, %eax
jne 0x6bf8
movb $0x1, 0xcb07(%rip)      # 0x13140
jmp 0x66a5
incl %r13d
cmpl %r14d, %r13d
jge 0x6b55
movslq %r13d, %rax
movq (%rbx,%rax,8), %rdi
callq 0xa98c
jmp 0x669d
incl %r13d
cmpl %r14d, %r13d
jge 0x6b5f
movslq %r13d, %rax
movq (%rbx,%rax,8), %rsi
leaq 0x1c(%rsp), %rdi
callq 0xa9e0
jmp 0x669d
incl %r13d
cmpl %r14d, %r13d
jge 0x6b69
movslq %r13d, %rax
movq (%rbx,%rax,8), %rcx
leaq 0x1c(%rsp), %rdi
leaq 0x18(%rsp), %rsi
leaq 0xca94(%rip), %rdx      # 0x1312c
callq 0xad34
testl %eax, %eax
je 0x6c13
incl %r13d
cmpl %r14d, %r13d
setl %r12b
jl 0x6504
jmp 0x6816
movl $0x1, 0x2c(%rsp)
jmp 0x66a5
incl %r13d
cmpl %r14d, %r13d
jge 0x6b73
movslq %r13d, %rax
movq (%rbx,%rax,8), %rbp
leaq 0x1c(%rsp), %rdi
movq %rbp, %rsi
callq 0x63d7
testl %eax, %eax
jne 0x66a5
jmp 0x6b7d
incl %r13d
cmpl %r14d, %r13d
jge 0x6b90
movslq %r13d, %rax
movq (%rbx,%rax,8), %rbp
leaq 0x44(%rsp), %rdi
movq %rbp, %rsi
callq 0x63d7
testl %eax, %eax
jne 0x66a5
jmp 0x6b97
incl %r13d
cmpl %r14d, %r13d
jge 0x6baa
movslq %r13d, %rax
movq (%rbx,%rax,8), %rbp
leaq 0x18(%rsp), %rdi
movq %rbp, %rsi
callq 0x63d7
testl %eax, %eax
jne 0x66a5
jmp 0x6bb1
movb $0x1, 0xc9fa(%rip)      # 0x13144
incl %r13d
cmpl %r14d, %r13d
jge 0x6bc4
movslq %r13d, %rax
movq (%rbx,%rax,8), %rbp
leaq 0x40(%rsp), %rdi
movq %rbp, %rsi
callq 0x63d7
testl %eax, %eax
jne 0x66a5
jmp 0x6bcb
movb $0x1, 0xc9aa(%rip)      # 0x13128
incl %r13d
cmpl %r14d, %r13d
jge 0x6bde
movslq %r13d, %rax
movq (%rbx,%rax,8), %rbp
leaq 0x3c(%rsp), %rdi
movq %rbp, %rsi
callq 0x63d7
testl %eax, %eax
jne 0x66a5
jmp 0x6be5
movl $0x1, 0x28(%rsp)
jmp 0x66a5
incl %r13d
cmpl %r14d, %r13d
jge 0x6c2b
movslq %r13d, %rax
movq (%rbx,%rax,8), %rbp
leaq 0x38(%rsp), %rdi
movq %rbp, %rsi
callq 0x63d7
movl $0x1, 0x24(%rsp)
testl %eax, %eax
jne 0x66a5
movq 0xc809(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x71f1(%rip), %rsi      # 0xd9ea
jmp 0x6c09
movl $0x0, 0x28(%rsp)
movl $0x0, 0x24(%rsp)
movl $0x0, 0x2c(%rsp)
movl 0x18(%rsp), %esi
movl 0x44(%rsp), %r15d
movl %r15d, %edi
subl %esi, %edi
jb 0x6a05
movl 0x1c(%rsp), %eax
movl %eax, 0xc8ec(%rip)      # 0x13120
movl $0x2, 0xc8e6(%rip)      # 0x13124
movl %r15d, 0xc8cb(%rip)     # 0x13110
callq 0x6edb
testb $0x1, %r12b
je 0x6a32
movl 0x18(%rsp), %eax
movl %r15d, 0xc(%rsp)
movl $0x0, 0x34(%rsp)
subl %r13d, %r14d
movl %r14d, 0x14(%rsp)
cmpl $0x3fffffff, %r14d      # imm = 0x3FFFFFFF
jae 0x6a0f
leal 0x4(,%r14,4), %ecx
cmpl %ecx, %eax
jb 0x6a16
movl %r15d, %ebp
subl %eax, %ebp
movl %r15d, %eax
subl %ecx, %eax
movl %eax, 0xc(%rsp)
movl %eax, 0x10(%rsp)
movl 0x14(%rsp), %esi
testl %esi, %esi
je 0x696c
movl %r15d, 0x30(%rsp)
movslq %r13d, %rax
leaq (%rbx,%rax,8), %rax
movq %rax, 0x50(%rsp)
movl %ebp, %eax
notl %eax
movq %rax, 0x48(%rsp)
xorl %ebx, %ebx
xorl %r12d, %r12d
movl $0x0, 0x20(%rsp)
movl 0xc(%rsp), %r13d
movq 0x50(%rsp), %rax
movq (%rax,%r12,8), %r15
movq %r15, %rdi
callq 0x1080
movl %ebp, %r14d
cmpl %ebp, %r13d
setne %cl
movq 0x48(%rsp), %rdx
addl %r13d, %edx
cmpq %rdx, %rax
setbe %bpl
andb %cl, %bpl
je 0x6947
incl %eax
subl %eax, %r13d
movl %r13d, 0xc(%rsp)
movq %r15, %rdi
movl %r13d, %esi
movl %eax, %edx
callq 0x6d8a
movl 0x10(%rsp), %esi
addl %ebx, %esi
leaq 0xc(%rsp), %rdi
movl $0x4, %edx
callq 0x6d8a
testb %bpl, %bpl
je 0x6971
incq %r12
movl 0x14(%rsp), %esi
addl $0x4, %ebx
cmpq %rsi, %r12
movl %r14d, %ebp
jb 0x68cf
jmp 0x6982
movq 0xc6aa(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x7150(%rip), %rsi      # 0xdaa8
movl %r12d, %edx
xorl %eax, %eax
callq 0x10d0
movl $0x1, 0x20(%rsp)
jmp 0x692e
xorl %r14d, %r14d
jmp 0x698c
xorl %eax, %eax
movl 0x30(%rsp), %r15d
movl 0x20(%rsp), %r14d
jmp 0x6a2a
movl 0x30(%rsp), %r15d
movl 0x20(%rsp), %r14d
shll $0x2, %esi
addl 0x10(%rsp), %esi
leaq 0x34(%rsp), %rdi
movl $0x4, %edx
callq 0x6d8a
movl 0xc(%rsp), %esi
movl %esi, %eax
subl %ebp, %eax
cmpl $0xb, %eax
jbe 0x6a1d
leal -0xc(%rsi), %eax
movl %eax, 0xc(%rsp)
addl $-0x4, %esi
leaq 0x10(%rsp), %rdi
movl $0x4, %edx
callq 0x6d8a
movl 0xc(%rsp), %esi
addl $0x4, %esi
leaq 0x14(%rsp), %rdi
movl $0x4, %edx
callq 0x6d8a
leaq 0x34(%rsp), %rdi
movl $0xfffffff0, (%rdi)     # imm = 0xFFFFFFF0
movl 0xc(%rsp), %esi
movl $0x4, %edx
callq 0x6d8a
movl 0xc(%rsp), %eax
movl %eax, 0xc70f(%rip)      # 0x13110
movb $0x1, %al
jmp 0x6a2a
callq 0x17e7
jmp 0x6c13
callq 0x17a3
jmp 0x6a22
callq 0x1781
jmp 0x6a22
callq 0x175f
movl $0x1, %r14d
xorl %eax, %eax
testb %al, %al
je 0x6c19
cmpl $0x0, 0x28(%rsp)
je 0x6a47
movq 0xc6f0(%rip), %rax      # 0x13130
movq %rax, 0xc6f1(%rip)      # 0x13138
cmpb $0x1, 0xc6f6(%rip)      # 0x13144
movl 0x2c(%rsp), %ebp
jne 0x6a65
movl 0x40(%rsp), %edi
callq 0xb270
testl %eax, %eax
je 0x6c13
cmpb $0x1, 0xc6bc(%rip)      # 0x13128
jne 0x6a8e
movl 0x3c(%rsp), %esi
movl 0x14(%rsp), %edx
movl 0x10(%rsp), %ecx
leaq 0xc6ab(%rip), %rdi      # 0x1312c
callq 0xb930
testl %eax, %eax
je 0x6c13
cmpl $0x0, 0x24(%rsp)
je 0x6aeb
movl 0x38(%rsp), %ebx
cmpl $0xfffff001, %ebx       # imm = 0xFFFFF001
jae 0x6b43
movl %ebx, 0xc6b5(%rip)      # 0x13160
movl %ebx, %edi
movl $0x1000, %esi           # imm = 0x1000
callq 0x6edb
leal 0x4(%rbx), %edi
movl %r15d, %esi
movl $0x4, %edx
callq 0x71e8
leal 0x8(%rbx), %edi
subl 0x18(%rsp), %r15d
movl %r15d, %esi
movl $0x4, %edx
callq 0x71e8
leal 0x18(%rbx), %edi
movl %ebx, %esi
movl $0x4, %edx
callq 0x71e8
testl %ebp, %ebp
je 0x6b08
movq 0xc4da(%rip), %rax      # 0x12fd0
movq (%rax), %rdi
callq 0x1fac
movl $0xa, %edi
callq 0x1040
callq 0x211a
xorl %r14d, %r14d
testl %eax, %eax
je 0x6c19
movq 0xc4b1(%rip), %rbx      # 0x12fd0
testl %ebp, %ebp
je 0x6b35
movq (%rbx), %rdi
callq 0x1fac
movl $0xa, %edi
callq 0x1040
callq 0x211a
testl %eax, %eax
jne 0x6b1f
jmp 0x6c19
callq 0x17c5
jmp 0x6c13
incl %r13d
jmp 0x6816
callq 0x173d
jmp 0x6c13
callq 0x171b
jmp 0x6c13
callq 0x16f9
jmp 0x6c13
callq 0x16d7
jmp 0x6c13
movq 0xc474(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x6cbf(%rip), %rsi      # 0xd84d
jmp 0x6c09
callq 0x16b5
jmp 0x6c13
movq 0xc45a(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x6ce1(%rip), %rsi      # 0xd889
jmp 0x6c09
callq 0x1693
jmp 0x6c13
movq 0xc440(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x6d09(%rip), %rsi      # 0xd8cb
jmp 0x6c09
callq 0x1671
jmp 0x6c13
movq 0xc426(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x6d3a(%rip), %rsi      # 0xd916
jmp 0x6c09
callq 0x164f
jmp 0x6c13
movq 0xc40c(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x6d84(%rip), %rsi      # 0xd97a
jmp 0x6c09
movq 0xc3f9(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x6e28(%rip), %rsi      # 0xda31
movq %rbp, %rdx
xorl %eax, %eax
callq 0x10d0
movl $0x1, %r14d
movl %r14d, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x162d
jmp 0x6c13
nop