// File: /workspace/github_c_makefile_star2_O2/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 0x14e42
testq %rsi, %rsi
je 0x14e61
testq %rdx, %rdx
je 0x14e80
testq %rcx, %rcx
je 0x14e9f
movl 0xb0(%rdi), %eax
movb $0x1, 0x16(%rcx)
movl (%rdx), %edi
cmpl $0x600, %edi            # imm = 0x600
jne 0x14a3c
movl 0x68(%rdx), %edi
leal -0x8000(%rdi), %r8d
roll $0x18, %r8d
cmpl $0x5, %r8d
ja 0x14adb
leaq 0x1ab47(%rip), %r9      # 0x2f4f4
movslq (%r9,%r8,4), %r8
addq %r9, %r8
jmpq *%r8
movb $0x1, 0x3(%rcx)
leal -0x8100(%rdi), %r8d
roll $0x18, %r8d
cmpl $0x4, %r8d
ja 0x14adb
leaq 0x1ab35(%rip), %r9      # 0x2f50c
movslq (%r9,%r8,4), %r8
addq %r9, %r8
jmpq *%r8
movb $0x1, 0x4(%rcx)
leal -0x8200(%rdi), %r8d
roll $0x18, %r8d
cmpl $0x3, %r8d
ja 0x14adb
leaq 0x1ab1f(%rip), %r9      # 0x2f520
movslq (%r9,%r8,4), %r8
addq %r9, %r8
jmpq *%r8
movb $0x1, 0x5(%rcx)
cmpl $0x8500, %edi           # imm = 0x8500
je 0x14ad7
cmpl $0x8400, %edi           # imm = 0x8400
je 0x14ac5
cmpl $0x8300, %edi           # imm = 0x8300
jne 0x14adb
movb $0x1, 0x6(%rcx)
jmp 0x14adb
andl $0x0, 0x3(%rcx)
andw $0x0, 0x7(%rcx)
cmpl $0x500, %edi            # imm = 0x500
jne 0x14ebe
movq 0x60(%rdx), %rdx
testq %rdx, %rdx
je 0x14edd
movb $0x3, 0x17(%rcx)
movl 0x10(%rdx), %esi
movl %esi, %edi
andb $0x7, %dil
movb %dil, 0x19(%rcx)
testb $0x8, %sil
je 0x14a80
movb $0x1, %sil
movb %sil, 0xd(%rcx)
movb %sil, 0x11(%rcx)
cmpl $0x4, %eax
je 0x14aa2
cmpl $0x2, %eax
je 0x14aa2
cmpl $0x1, %eax
jne 0x14e27
cmpl $0x4, 0xc(%rdx)
je 0x14e23
jmp 0x14e27
cmpl $0x3, 0xc(%rdx)
je 0x14e23
jmp 0x14e27
movb $0x1, 0x6(%rcx)
cmpl $0x8500, %edi           # imm = 0x8500
je 0x14ad7
cmpl $0x8400, %edi           # imm = 0x8400
jne 0x14adb
movb $0x1, 0x7(%rcx)
jmp 0x14adb
movb $0x1, 0x7(%rcx)
cmpl $0x8500, %edi           # imm = 0x8500
jne 0x14adb
movb $0x1, 0x8(%rcx)
movl 0x60(%rdx), %edi
cmpl $0x3, %edi
je 0x14b8b
cmpl $0x2, %edi
je 0x14b29
cmpl $0x1, %edi
jne 0x14ebe
movl 0x64(%rdx), %esi
movl 0x98(%rdx), %edi
movl 0x9c(%rdx), %r8d
movl %edi, %r9d
andl %r8d, %r9d
cmpl $-0x1, %r9d
jne 0x14c04
movb $0x1, 0x1e(%rcx)
andq $0x0, 0x20(%rcx)
movb $0x1, %dil
movb $0x6, %r8b
jmp 0x14dd9
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 0x14c2c
movb $0x1, %r14b
cmpl $0x1, %r11d
je 0x14c33
cmpl $0x2, %r11d
jne 0x14f1b
movb $0x4, %r14b
jmp 0x14c33
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 0x14bcc
movb $0x4, 0x1e(%rcx)
movq %rbx, 0x20(%rcx)
xorl %r11d, %r11d
pushq $0x5
popq %r9
pushq $0x4
popq %r10
movl %r10d, %r8d
xorl %edx, %edx
jmp 0x14d04
movl 0xa0(%rdx), %r9d
movl 0xa4(%rdx), %r8d
movl 0xa8(%rdx), %edx
movl %r10d, %r14d
xorl $0x5, %r14d
orl %r11d, %r14d
jne 0x14c9a
movb $0x4, 0x1e(%rcx)
movq %rbx, 0x20(%rcx)
pushq $0x5
popq %r10
xorl %r11d, %r11d
jmp 0x14d04
movl 0x90(%rdx), %edx
movl %r8d, %r9d
xorl $0x6, %r9d
orl %edi, %r9d
jne 0x14cb7
movb $0x2, 0x1e(%rcx)
movq %rdx, 0x20(%rcx)
movb $0x6, %r8b
xorl %edi, %edi
jmp 0x14dd9
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 0x14c75
movb $0x1, 0x1a(%rcx)
movb %r9b, 0x1d(%rcx)
movb %r8b, 0x1c(%rcx)
movb %dl, 0x1b(%rcx)
cmpl $0x4, %eax
je 0x14cdc
cmpl $0x2, %eax
je 0x14dc7
cmpl $0x1, %eax
jne 0x14e27
cmpl $0x3, %edi
je 0x14e14
jmp 0x14e18
testl %r11d, %r11d
je 0x14cf9
movb $0x1, %r14b
cmpl $0x1, %r11d
je 0x14cfc
cmpl $0x2, %r11d
jne 0x14f3a
movb $0x4, %r14b
jmp 0x14cfc
testl %edi, %edi
je 0x14dce
movb $0x1, %r9b
cmpl $0x1, %edi
je 0x14dd1
cmpl $0x2, %edi
jne 0x14f59
movb $0x2, %r9b
jmp 0x14dd1
testb $0x20, 0x8(%rsi)
jne 0x14ceb
cmpl $0x4, %edi
je 0x14e3a
cmpl $0x2, %edi
je 0x14e14
jmp 0x14e18
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 0x14d24
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 0x14d86
movb $0x1, 0x1a(%rcx)
movl %r9d, %r10d
andb $0x7, %r10b
movb %r10b, 0x1d(%rcx)
testb $0x8, %r9b
je 0x14d67
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 0x14d83
movb $0x1, %r8b
movb %r8b, 0xd(%rcx)
movb %r8b, 0x10(%rcx)
movb %dl, 0x1b(%rcx)
cmpl $0x4, %eax
je 0x14dbc
cmpl $0x2, %eax
je 0x14efc
cmpl $0x1, %eax
jne 0x14e27
leaq 0x185cc(%rip), %rdi     # 0x2d370
leaq 0x1a785(%rip), %rsi     # 0x2f530
leaq 0x1aa07(%rip), %rcx     # 0x2f7b9
movl $0x408, %edx            # imm = 0x408
callq 0xa0b0
testb $0x20, 0x8(%rsi)
jne 0x14dc7
cmpl $0x4, %edi
je 0x14e32
cmpl $0x2, %edi
je 0x14e23
jmp 0x14e27
xorl %r9d, %r9d
movb %r9b, 0x1e(%rcx)
movq %rdx, 0x20(%rcx)
movb %dil, 0x17(%rcx)
movb %r8b, 0x19(%rcx)
cmpl $0x1, %eax
je 0x14e1e
cmpl $0x2, %eax
je 0x14e0f
cmpl $0x4, %eax
jne 0x14e27
leaq 0x18579(%rip), %rdi     # 0x2d370
leaq 0x1a732(%rip), %rsi     # 0x2f530
leaq 0x1a9b4(%rip), %rcx     # 0x2f7b9
movl $0x382, %edx            # imm = 0x382
callq 0xa0b0
cmpl $0x2, %esi
jne 0x14e18
movb $0x1, 0xb(%rcx)
movb $0x1, 0xc(%rcx)
jmp 0x14e27
cmpl $0x3, %esi
jne 0x14e27
movb $0x1, 0xb(%rcx)
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movw $0x101, 0xd(%rcx)       # imm = 0x101
jmp 0x14e27
movw $0x101, 0xd(%rcx)       # imm = 0x101
jmp 0x14e18
leaq 0x19f8b(%rip), %rdi     # 0x2edd4
leaq 0x1a6e0(%rip), %rsi     # 0x2f530
leaq 0x1a962(%rip), %rcx     # 0x2f7b9
movl $0x307, %edx            # imm = 0x307
callq 0xa0b0
leaq 0x1a8d2(%rip), %rdi     # 0x2f73a
leaq 0x1a6c1(%rip), %rsi     # 0x2f530
leaq 0x1a943(%rip), %rcx     # 0x2f7b9
movl $0x308, %edx            # imm = 0x308
callq 0xa0b0
leaq 0x1be34(%rip), %rdi     # 0x30cbb
leaq 0x1a6a2(%rip), %rsi     # 0x2f530
leaq 0x1a924(%rip), %rcx     # 0x2f7b9
movl $0x309, %edx            # imm = 0x309
callq 0xa0b0
leaq 0x1a890(%rip), %rdi     # 0x2f736
leaq 0x1a683(%rip), %rsi     # 0x2f530
leaq 0x1a905(%rip), %rcx     # 0x2f7b9
movl $0x30a, %edx            # imm = 0x30A
callq 0xa0b0
leaq 0x184ab(%rip), %rdi     # 0x2d370
leaq 0x1a664(%rip), %rsi     # 0x2f530
leaq 0x1a8e6(%rip), %rcx     # 0x2f7b9
movl $0x41e, %edx            # imm = 0x41E
callq 0xa0b0
leaq 0x1a8cd(%rip), %rdi     # 0x2f7b1
leaq 0x1a645(%rip), %rsi     # 0x2f530
leaq 0x1a8c7(%rip), %rcx     # 0x2f7b9
movl $0x32f, %edx            # imm = 0x32F
callq 0xa0b0
leaq 0x1846d(%rip), %rdi     # 0x2d370
leaq 0x1a626(%rip), %rsi     # 0x2f530
leaq 0x1a8a8(%rip), %rcx     # 0x2f7b9
movl $0x40a, %edx            # imm = 0x40A
callq 0xa0b0
leaq 0x1844e(%rip), %rdi     # 0x2d370
leaq 0x1a607(%rip), %rsi     # 0x2f530
leaq 0x1a889(%rip), %rcx     # 0x2f7b9
movl $0x399, %edx            # imm = 0x399
callq 0xa0b0
leaq 0x1842f(%rip), %rdi     # 0x2d370
leaq 0x1a5e8(%rip), %rsi     # 0x2f530
leaq 0x1a86a(%rip), %rcx     # 0x2f7b9
movl $0x3e9, %edx            # imm = 0x3E9
callq 0xa0b0
leaq 0x18410(%rip), %rdi     # 0x2d370
leaq 0x1a5c9(%rip), %rsi     # 0x2f530
leaq 0x1a84b(%rip), %rcx     # 0x2f7b9
movl $0x369, %edx            # imm = 0x369
callq 0xa0b0