// File: /workspace/github_c_makefile_star2_O1/Ihsoh[P]ilang/compiler/assembler/ins.c
// Function: ins_fill_EX
void ins_fill_EX(
	ParserContext *ctx,
	Instruction *ins,
	ParserASTNode *node,
	EncoderInstruction *enc_ins
) {
	assert(ctx);
	assert(ins);
	assert(node);
	assert(enc_ins);

	int arch = ASM_PARSER_CONTEXT_DATA_GET_ARCH(ctx);

	enc_ins->mod_rm_used = true;

	if (node->type == ASM_NODE_MEM) {
		int seg = ASM_MEM_AST_NODE_GET_SEG(node);
		if (seg == INS_AM_CS) {
			enc_ins->legacy_prefix.cs = true;
		}
		if (seg == INS_AM_SS) {
			enc_ins->legacy_prefix.ss = true;
		}
		if (seg == INS_AM_DS) {
			enc_ins->legacy_prefix.ds = true;
		}
		if (seg == INS_AM_ES) {
			enc_ins->legacy_prefix.es = true;
		}
		if (seg == INS_AM_FS) {
			enc_ins->legacy_prefix.fs = true;
		}
		if (seg == INS_AM_GS) {
			enc_ins->legacy_prefix.gs = true;
		}
	} else {
		enc_ins->legacy_prefix.cs = false;
		enc_ins->legacy_prefix.ss = false;
		enc_ins->legacy_prefix.ds = false;
		enc_ins->legacy_prefix.es = false;
		enc_ins->legacy_prefix.fs = false;
		enc_ins->legacy_prefix.gs = false;
	}

	if (node->type == ASM_NODE_REG) {
		InsRegister *ins_reg = ASM_REG_AST_NODE_GET_REG(node);
		assert(ins_reg);

		enc_ins->mod_rm.mod = 3;
		enc_ins->mod_rm.rm = ins_reg->index & 0x7;	// 0x7 == 0b0111

		if (ins_reg->index & 0x08) {	// 0x8 == 0b1000
			enc_ins->rex_prefix_used = true;
			enc_ins->rex_prefix.b = true;
		}

		if (arch == ASM_ARCH_BIT16) {
			// Operand size
			if (ins_reg->type == INS_REGISTER_GENERAL_4BYTE) {
				enc_ins->legacy_prefix.operand_size_override = true;
			}
		} else if (arch == ASM_ARCH_BIT32) {
			// Operand size
			if (ins_reg->type == INS_REGISTER_GENERAL_2BYTE) {
				enc_ins->legacy_prefix.operand_size_override = true;
			}
		} else if (arch == ASM_ARCH_BIT64) {
			// Operand size
			if (ins->superscript | INS_SS_d64) {
				if (ins_reg->type == INS_REGISTER_GENERAL_2BYTE) {
					enc_ins->legacy_prefix.operand_size_override = true;
				}
			} else {
				if (ins_reg->type == INS_REGISTER_GENERAL_2BYTE) {
					enc_ins->legacy_prefix.operand_size_override = true;
				} else if (ins_reg->type == INS_REGISTER_GENERAL_8BYTE) {
					enc_ins->rex_prefix_used = true;
					enc_ins->rex_prefix.w = true;
				}
			}
		}
	} else if (node->type == ASM_NODE_MEM
					&& ASM_MEM_AST_NODE_GET_ADDR_SIZE(node) == ASM_MEM_ADDR_SIZE_16) {
		int type = ASM_MEM_AST_NODE_GET_TYPE(node);
		int mod = ASM_MEM_AST_NODE_GET_MOD(node);
		int rm = ASM_MEM_AST_NODE_GET_RM(node);
		uint32_t disp = ASM_MEM_AST_NODE_GET_DISP(node);

		if (mod == -1 && rm == -1) {
			mod = 1;
			rm = 6;
			enc_ins->disp_len = 1;
			enc_ins->disp = 0;
		} else if (mod == 0 && rm == 0x6) {
			enc_ins->disp_len = 2;
			enc_ins->disp = disp;
		} else {
			if (mod == 0) {
				enc_ins->disp_len = 0;
			} else if (mod == 1) {
				enc_ins->disp_len = 1;
			} else if (mod == 2) {
				enc_ins->disp_len = 2;
			} else {
				assert(0);
			}
			enc_ins->disp = disp;
		}

		enc_ins->mod_rm.mod = mod;
		enc_ins->mod_rm.rm = rm;

		if (arch == ASM_ARCH_BIT16) {
			// Operand size
			if (type == ASM_MEM_TYPE_DWORD) {
				enc_ins->legacy_prefix.operand_size_override = true;
			}

			// Address size
			// None
		} else if (arch == ASM_ARCH_BIT32) {
			// Operand size
			if (type == ASM_MEM_TYPE_WORD) {
				enc_ins->legacy_prefix.operand_size_override = true;
			}

			// Address size
			enc_ins->legacy_prefix.address_size_override = true;
		} else if (arch == ASM_ARCH_BIT64) {
			assert(0);
		}
	} else if (node->type == ASM_NODE_MEM
					&& ASM_MEM_AST_NODE_GET_ADDR_SIZE(node) == ASM_MEM_ADDR_SIZE_32) {
		int type = ASM_MEM_AST_NODE_GET_TYPE(node);
		int mod = ASM_MEM_AST_NODE_GET_MOD(node);
		int rm = ASM_MEM_AST_NODE_GET_RM(node);
		int sib_base = ASM_MEM_AST_NODE_GET_SIB_BASE(node);
		int sib_index = ASM_MEM_AST_NODE_GET_SIB_INDEX(node);
		int sib_ss = ASM_MEM_AST_NODE_GET_SIB_SS(node);
		uint32_t disp = ASM_MEM_AST_NODE_GET_DISP(node);

		if (mod == 0 && rm == 0x5) {
			enc_ins->disp_len = 4;
			enc_ins->disp = disp;
		} else {
			if (mod == 0) {
				enc_ins->disp_len = 0;
			} else if (mod == 1) {
				enc_ins->disp_len = 1;
			} else if (mod == 2) {
				enc_ins->disp_len = 4;
			} else {
				assert(0);
			}
			enc_ins->disp = disp;
		}

		enc_ins->mod_rm.mod = mod;
		enc_ins->mod_rm.rm = rm;

		if (sib_base != -1 && sib_index != -1 && sib_ss != -1) {
			enc_ins->sib_used = true;
			enc_ins->sib.base = sib_base;
			enc_ins->sib.index = sib_index;
			enc_ins->sib.scale = sib_ss;
		}

		if (arch == ASM_ARCH_BIT16) {
			// Operand size
			if (type == ASM_MEM_TYPE_DWORD) {
				enc_ins->legacy_prefix.operand_size_override = true;
			}

			// Address size
			enc_ins->legacy_prefix.address_size_override = true;
		} else if (arch == ASM_ARCH_BIT32) {
			// Operand size
			if (type == ASM_MEM_TYPE_WORD) {
				enc_ins->legacy_prefix.operand_size_override = true;
			}

			// Address size
			// None
		} else if (arch == ASM_ARCH_BIT64) {
			// Operand size
			if (ins->superscript & INS_SS_d64) {
				if (type == ASM_MEM_TYPE_WORD) {
					enc_ins->legacy_prefix.operand_size_override = true;
				}
			} else {
				if (type == ASM_MEM_TYPE_WORD) {
					enc_ins->legacy_prefix.operand_size_override = true;
				} else if (type == ASM_MEM_TYPE_QWORD) {
					enc_ins->rex_prefix_used = true;
					enc_ins->rex_prefix.w = true;
				}
			}

			// Address size
			enc_ins->legacy_prefix.address_size_override = true;
		}
	} else if (node->type == ASM_NODE_MEM
					&& ASM_MEM_AST_NODE_GET_ADDR_SIZE(node) == ASM_MEM_ADDR_SIZE_64) {
		int type = ASM_MEM_AST_NODE_GET_TYPE(node);
		int mod = ASM_MEM_AST_NODE_GET_MOD(node);
		int rm = ASM_MEM_AST_NODE_GET_RM(node);
		int sib_base = ASM_MEM_AST_NODE_GET_SIB_BASE(node);
		int sib_index = ASM_MEM_AST_NODE_GET_SIB_INDEX(node);
		int sib_ss = ASM_MEM_AST_NODE_GET_SIB_SS(node);
		uint64_t disp = ASM_MEM_AST_NODE_GET_DISP(node);

		if (mod == -1 && rm == -1) {
			mod = 0x0;
			rm = 0x4;

			sib_base = 0x5;
			sib_index = 0x4;
			sib_ss = 0x0;

			enc_ins->disp_len = 4;
			enc_ins->disp = disp;
		} else if (mod == 0 && rm == 0x5) {
			enc_ins->disp_len = 4;
			enc_ins->disp = disp;
		} else {
			if (mod == 0) {
				enc_ins->disp_len = 0;
			} else if (mod == 1) {
				enc_ins->disp_len = 1;
			} else if (mod == 2) {
				enc_ins->disp_len = 4;
			} else {
				assert(0);
			}
			enc_ins->disp = disp;
		}

		enc_ins->mod_rm.mod = mod;
		enc_ins->mod_rm.rm = rm & 0x7;	// 0x7 == 0b0111
		if (rm & 0x8) {	// 0x8 == 0b1000
			enc_ins->rex_prefix_used = true;
			enc_ins->rex_prefix.b = true;
		}

		if (sib_base != -1 && sib_index != -1 && sib_ss != -1) {
			enc_ins->sib_used = true;
			
			enc_ins->sib.base = sib_base & 0x7;	// 0x7 == 0b0111
			if (sib_base & 0x8) {	// 0x8 == 0b1000
				enc_ins->rex_prefix_used = true;
				enc_ins->rex_prefix.b = true;
			}

			enc_ins->sib.index = sib_index & 0x7;	// 0x7 == 0b0111
			if (sib_index & 0x8) {	// 0x8 == 0b1000
				enc_ins->rex_prefix_used = true;
				enc_ins->rex_prefix.x = true;
			}

			enc_ins->sib.scale = sib_ss;
		}

		if (arch == ASM_ARCH_BIT16) {
			assert(0);
		} else if (arch == ASM_ARCH_BIT32) {
			assert(0);
		} else if (arch == ASM_ARCH_BIT64) {
			// Operand size
			if (ins->superscript & INS_SS_d64) {
				if (type == ASM_MEM_TYPE_WORD) {
					enc_ins->legacy_prefix.operand_size_override = true;
				}
			} else {
				if (type == ASM_MEM_TYPE_WORD) {
					enc_ins->legacy_prefix.operand_size_override = true;
				} else if (type == ASM_MEM_TYPE_QWORD) {
					enc_ins->rex_prefix_used = true;
					enc_ins->rex_prefix.w = true;
				}
			}

			// Address size
			// None
		}
	} else {
		assert(0);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
testq %rdi, %rdi
je 0x15cf3
testq %rsi, %rsi
je 0x15d12
testq %rdx, %rdx
je 0x15d31
testq %rcx, %rcx
je 0x15d50
movl 0xb0(%rdi), %eax
movb $0x1, 0x16(%rcx)
movl (%rdx), %edi
cmpl $0x600, %edi            # imm = 0x600
jne 0x158e7
movl 0x68(%rdx), %r8d
leal -0x8000(%r8), %r9d
roll $0x18, %r9d
cmpl $0x5, %r9d
ja 0x158f4
leaq 0x1bcef(%rip), %r10     # 0x31534
movslq (%r10,%r9,4), %r9
addq %r10, %r9
jmpq *%r9
movb $0x1, 0x3(%rcx)
leal -0x8100(%r8), %r9d
roll $0x18, %r9d
cmpl $0x4, %r9d
ja 0x158f4
leaq 0x1bcdd(%rip), %r10     # 0x3154c
movslq (%r10,%r9,4), %r9
addq %r10, %r9
jmpq *%r9
movb $0x1, 0x4(%rcx)
leal -0x8200(%r8), %r9d
roll $0x18, %r9d
cmpl $0x3, %r9d
ja 0x158f4
leaq 0x1bccb(%rip), %r10     # 0x31560
movslq (%r10,%r9,4), %r9
addq %r10, %r9
jmpq *%r9
movb $0x1, 0x5(%rcx)
cmpl $0x8500, %r8d           # imm = 0x8500
je 0x158e1
cmpl $0x8400, %r8d           # imm = 0x8400
je 0x158d4
cmpl $0x8300, %r8d           # imm = 0x8300
jne 0x158f4
movb $0x1, 0x6(%rcx)
cmpl $0x8500, %r8d           # imm = 0x8500
je 0x158e1
cmpl $0x8400, %r8d           # imm = 0x8400
jne 0x158f4
movb $0x1, 0x7(%rcx)
cmpl $0x8500, %r8d           # imm = 0x8500
jne 0x158f4
movb $0x1, 0x8(%rcx)
jmp 0x158f4
movw $0x0, 0x7(%rcx)
movl $0x0, 0x3(%rcx)
cmpl $0x600, %edi            # imm = 0x600
je 0x15961
cmpl $0x500, %edi            # imm = 0x500
jne 0x1599e
movq 0x60(%rdx), %rdx
testq %rdx, %rdx
je 0x15d8e
movb $0x3, 0x17(%rcx)
movl 0x10(%rdx), %esi
movl %esi, %edi
andb $0x7, %dil
movb %dil, 0x19(%rcx)
testb $0x8, %sil
je 0x15937
movb $0x1, %sil
movb %sil, 0xd(%rcx)
movb %sil, 0x11(%rcx)
cmpl $0x4, %eax
je 0x15a70
cmpl $0x2, %eax
je 0x15a70
cmpl $0x1, %eax
jne 0x15ce0
cmpl $0x4, 0xc(%rdx)
je 0x15cdc
jmp 0x15ce0
cmpl $0x1, 0x60(%rdx)
jne 0x1599e
movl 0x64(%rdx), %esi
movl 0x98(%rdx), %edi
movl 0x9c(%rdx), %r8d
movl %edi, %r9d
andl %r8d, %r9d
cmpl $-0x1, %r9d
jne 0x15b27
movb $0x1, 0x1e(%rcx)
movq $0x0, 0x20(%rcx)
movb $0x1, %dil
movb $0x6, %r8b
jmp 0x15c92
cmpl $0x600, %edi            # imm = 0x600
jne 0x15d6f
cmpl $0x2, 0x60(%rdx)
jne 0x15a12
movl 0x98(%rdx), %r11d
movl 0x9c(%rdx), %r10d
testl %r11d, %r11d
sete %r14b
cmpl $0x5, %r10d
sete %r15b
movl 0x64(%rdx), %edi
movl 0x90(%rdx), %ebx
movl 0xa0(%rdx), %r9d
movl 0xa4(%rdx), %r8d
movl 0xa8(%rdx), %edx
testl %r11d, %r11d
je 0x15ab9
movb $0x1, %r14b
cmpl $0x1, %r11d
je 0x15ac0
cmpl $0x2, %r11d
jne 0x15dcc
movb $0x4, %r14b
jmp 0x15ac0
cmpl $0x600, %edi            # imm = 0x600
jne 0x15d6f
cmpl $0x3, 0x60(%rdx)
jne 0x15d6f
movl 0x64(%rdx), %edi
movl 0x98(%rdx), %r11d
movl 0x9c(%rdx), %r10d
movq 0x90(%rdx), %rbx
movl %r11d, %r8d
andl %r10d, %r8d
cmpl $-0x1, %r8d
jne 0x15a7f
movb $0x4, 0x1e(%rcx)
movq %rbx, 0x20(%rcx)
xorl %r11d, %r11d
movl $0x5, %r9d
movl $0x4, %r10d
movl $0x4, %r8d
xorl %edx, %edx
jmp 0x15bb5
cmpl $0x3, 0xc(%rdx)
je 0x15cdc
jmp 0x15ce0
movl 0xa0(%rdx), %r9d
movl 0xa4(%rdx), %r8d
movl 0xa8(%rdx), %edx
movl %r10d, %r14d
xorl $0x5, %r14d
orl %r11d, %r14d
jne 0x15b68
movb $0x4, 0x1e(%rcx)
movq %rbx, 0x20(%rcx)
movl $0x5, %r10d
xorl %r11d, %r11d
jmp 0x15bb5
andb %r15b, %r14b
shlb $0x2, %r14b
movb %r14b, 0x1e(%rcx)
movq %rbx, 0x20(%rcx)
movb %r11b, 0x17(%rcx)
movb %r10b, 0x19(%rcx)
cmpl $-0x1, %r9d
setne %r10b
cmpl $-0x1, %r8d
setne %r11b
andb %r10b, %r11b
cmpl $-0x1, %edx
setne %r10b
andb %r11b, %r10b
cmpb $0x1, %r10b
jne 0x15b02
movb $0x1, 0x1a(%rcx)
movb %r9b, 0x1d(%rcx)
movb %r8b, 0x1c(%rcx)
movb %dl, 0x1b(%rcx)
cmpl $0x4, %eax
je 0x15b4b
cmpl $0x2, %eax
je 0x15c78
cmpl $0x1, %eax
jne 0x15ce0
cmpl $0x3, %edi
je 0x15ccd
jmp 0x15cd1
movl 0x90(%rdx), %edx
movl %r8d, %r9d
xorl $0x6, %r9d
orl %edi, %r9d
jne 0x15b85
movb $0x2, 0x1e(%rcx)
movq %rdx, 0x20(%rcx)
movb $0x6, %r8b
xorl %edi, %edi
jmp 0x15c92
testb $0x20, 0x8(%rsi)
jne 0x15b5a
cmpl $0x4, %edi
je 0x15ceb
cmpl $0x2, %edi
je 0x15ccd
jmp 0x15cd1
testl %r11d, %r11d
je 0x15baa
movb $0x1, %r14b
cmpl $0x1, %r11d
je 0x15bad
cmpl $0x2, %r11d
jne 0x15deb
movb $0x4, %r14b
jmp 0x15bad
testl %edi, %edi
je 0x15c87
movb $0x1, %r9b
cmpl $0x1, %edi
je 0x15c8a
cmpl $0x2, %edi
jne 0x15e0a
movb $0x2, %r9b
jmp 0x15c8a
xorl %r14d, %r14d
movb %r14b, 0x1e(%rcx)
movq %rbx, 0x20(%rcx)
movb %r11b, 0x17(%rcx)
movl %r10d, %r11d
andb $0x7, %r11b
movb %r11b, 0x19(%rcx)
testb $0x8, %r10b
je 0x15bd5
movb $0x1, %r10b
movb %r10b, 0xd(%rcx)
movb %r10b, 0x11(%rcx)
cmpl $-0x1, %r9d
setne %r10b
cmpl $-0x1, %r8d
setne %r11b
andb %r10b, %r11b
cmpl $-0x1, %edx
setne %r10b
andb %r11b, %r10b
cmpb $0x1, %r10b
jne 0x15c37
movb $0x1, 0x1a(%rcx)
movl %r9d, %r10d
andb $0x7, %r10b
movb %r10b, 0x1d(%rcx)
testb $0x8, %r9b
je 0x15c18
movb $0x1, %r9b
movb %r9b, 0xd(%rcx)
movb %r9b, 0x11(%rcx)
movl %r8d, %r9d
andb $0x7, %r9b
movb %r9b, 0x1c(%rcx)
testb $0x8, %r8b
je 0x15c34
movb $0x1, %r8b
movb %r8b, 0xd(%rcx)
movb %r8b, 0x10(%rcx)
movb %dl, 0x1b(%rcx)
cmpl $0x4, %eax
je 0x15c6d
cmpl $0x2, %eax
je 0x15dad
cmpl $0x1, %eax
jne 0x15ce0
leaq 0x1973f(%rip), %rdi     # 0x2f394
leaq 0x1b914(%rip), %rsi     # 0x31570
leaq 0x1bb96(%rip), %rcx     # 0x317f9
movl $0x408, %edx            # imm = 0x408
callq 0xa0b0
testb $0x20, 0x8(%rsi)
jne 0x15c78
cmpl $0x4, %edi
je 0x15c7f
cmpl $0x2, %edi
je 0x15cdc
jmp 0x15ce0
movw $0x101, 0xd(%rcx)       # imm = 0x101
jmp 0x15ce0
xorl %r9d, %r9d
movb %r9b, 0x1e(%rcx)
movq %rdx, 0x20(%rcx)
movb %dil, 0x17(%rcx)
movb %r8b, 0x19(%rcx)
cmpl $0x1, %eax
je 0x15cd7
cmpl $0x2, %eax
je 0x15cc8
cmpl $0x4, %eax
jne 0x15ce0
leaq 0x196e4(%rip), %rdi     # 0x2f394
leaq 0x1b8b9(%rip), %rsi     # 0x31570
leaq 0x1bb3b(%rip), %rcx     # 0x317f9
movl $0x382, %edx            # imm = 0x382
callq 0xa0b0
cmpl $0x2, %esi
jne 0x15cd1
movb $0x1, 0xb(%rcx)
movb $0x1, 0xc(%rcx)
jmp 0x15ce0
cmpl $0x3, %esi
jne 0x15ce0
movb $0x1, 0xb(%rcx)
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movw $0x101, 0xd(%rcx)       # imm = 0x101
jmp 0x15cd1
leaq 0x20a5c(%rip), %rdi     # 0x36756
leaq 0x1b86f(%rip), %rsi     # 0x31570
leaq 0x1baf1(%rip), %rcx     # 0x317f9
movl $0x307, %edx            # imm = 0x307
callq 0xa0b0
leaq 0x1ba61(%rip), %rdi     # 0x3177a
leaq 0x1b850(%rip), %rsi     # 0x31570
leaq 0x1bad2(%rip), %rcx     # 0x317f9
movl $0x308, %edx            # imm = 0x308
callq 0xa0b0
leaq 0x1cfc3(%rip), %rdi     # 0x32cfb
leaq 0x1b831(%rip), %rsi     # 0x31570
leaq 0x1bab3(%rip), %rcx     # 0x317f9
movl $0x309, %edx            # imm = 0x309
callq 0xa0b0
leaq 0x1ba1f(%rip), %rdi     # 0x31776
leaq 0x1b812(%rip), %rsi     # 0x31570
leaq 0x1ba94(%rip), %rcx     # 0x317f9
movl $0x30a, %edx            # imm = 0x30A
callq 0xa0b0
leaq 0x1961e(%rip), %rdi     # 0x2f394
leaq 0x1b7f3(%rip), %rsi     # 0x31570
leaq 0x1ba75(%rip), %rcx     # 0x317f9
movl $0x41e, %edx            # imm = 0x41E
callq 0xa0b0
leaq 0x1ba5c(%rip), %rdi     # 0x317f1
leaq 0x1b7d4(%rip), %rsi     # 0x31570
leaq 0x1ba56(%rip), %rcx     # 0x317f9
movl $0x32f, %edx            # imm = 0x32F
callq 0xa0b0
leaq 0x195e0(%rip), %rdi     # 0x2f394
leaq 0x1b7b5(%rip), %rsi     # 0x31570
leaq 0x1ba37(%rip), %rcx     # 0x317f9
movl $0x40a, %edx            # imm = 0x40A
callq 0xa0b0
leaq 0x195c1(%rip), %rdi     # 0x2f394
leaq 0x1b796(%rip), %rsi     # 0x31570
leaq 0x1ba18(%rip), %rcx     # 0x317f9
movl $0x399, %edx            # imm = 0x399
callq 0xa0b0
leaq 0x195a2(%rip), %rdi     # 0x2f394
leaq 0x1b777(%rip), %rsi     # 0x31570
leaq 0x1b9f9(%rip), %rcx     # 0x317f9
movl $0x3e9, %edx            # imm = 0x3E9
callq 0xa0b0
leaq 0x19583(%rip), %rdi     # 0x2f394
leaq 0x1b758(%rip), %rsi     # 0x31570
leaq 0x1b9da(%rip), %rcx     # 0x317f9
movl $0x369, %edx            # imm = 0x369
callq 0xa0b0