// File: /workspace/github_c_makefile_star2_O3/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 0x15991
testq %rsi, %rsi
je 0x159b0
testq %rdx, %rdx
je 0x159cf
testq %rcx, %rcx
je 0x159ee
movl 0xb0(%rdi), %eax
movb $0x1, 0x16(%rcx)
movl (%rdx), %edi
cmpl $0x600, %edi            # imm = 0x600
jne 0x1557c
movl 0x68(%rdx), %edi
leal -0x8000(%rdi), %r8d
roll $0x18, %r8d
cmpl $0x5, %r8d
ja 0x1561f
leaq 0x1aff7(%rip), %r9      # 0x304e4
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 0x1561f
leaq 0x1afe5(%rip), %r9      # 0x304fc
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 0x1561f
leaq 0x1afcf(%rip), %r9      # 0x30510
movslq (%r9,%r8,4), %r8
addq %r9, %r8
jmpq *%r8
movb $0x1, 0x5(%rcx)
cmpl $0x8500, %edi           # imm = 0x8500
je 0x1561b
cmpl $0x8400, %edi           # imm = 0x8400
je 0x15609
cmpl $0x8300, %edi           # imm = 0x8300
jne 0x1561f
movb $0x1, 0x6(%rcx)
jmp 0x1561f
movw $0x0, 0x7(%rcx)
movl $0x0, 0x3(%rcx)
cmpl $0x500, %edi            # imm = 0x500
jne 0x15a0d
movq 0x60(%rdx), %rdx
testq %rdx, %rdx
je 0x15a2c
movb $0x3, 0x17(%rcx)
movl 0x10(%rdx), %esi
movl %esi, %edi
andb $0x7, %dil
movb %dil, 0x19(%rcx)
testb $0x8, %sil
je 0x155c4
movb $0x1, %sil
movb %sil, 0xd(%rcx)
movb %sil, 0x11(%rcx)
cmpl $0x4, %eax
je 0x155e6
cmpl $0x2, %eax
je 0x155e6
cmpl $0x1, %eax
jne 0x1597e
cmpl $0x4, 0xc(%rdx)
je 0x1597a
jmp 0x1597e
cmpl $0x3, 0xc(%rdx)
je 0x1597a
jmp 0x1597e
movb $0x1, 0x6(%rcx)
cmpl $0x8500, %edi           # imm = 0x8500
je 0x1561b
cmpl $0x8400, %edi           # imm = 0x8400
jne 0x1561f
movb $0x1, 0x7(%rcx)
jmp 0x1561f
movb $0x1, 0x7(%rcx)
cmpl $0x8500, %edi           # imm = 0x8500
jne 0x1561f
movb $0x1, 0x8(%rcx)
movl 0x60(%rdx), %edi
cmpl $0x3, %edi
je 0x156d2
cmpl $0x2, %edi
je 0x15670
cmpl $0x1, %edi
jne 0x15a0d
movl 0x64(%rdx), %esi
movl 0x98(%rdx), %edi
movl 0x9c(%rdx), %r8d
movl %edi, %r9d
andl %r8d, %r9d
cmpl $-0x1, %r9d
jne 0x157e5
movb $0x1, 0x1e(%rcx)
movq $0x0, 0x20(%rcx)
movb $0x1, %dil
movb $0x6, %r8b
jmp 0x15930
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 0x15823
movb $0x1, %r14b
cmpl $0x1, %r11d
je 0x1582a
cmpl $0x2, %r11d
jne 0x15a6a
movb $0x4, %r14b
jmp 0x1582a
movl 0x64(%rdx), %edi
movl 0x98(%rdx), %r14d
movl 0x9c(%rdx), %r11d
movq 0x90(%rdx), %r10
movl %r14d, %r8d
andl %r11d, %r8d
cmpl $-0x1, %r8d
jne 0x15708
xorl %edx, %edx
movl $0x4, %r8d
movl $0x5, %r9d
movb $0x4, %bl
jmp 0x1572e
movl 0xa0(%rdx), %r9d
movl 0xa4(%rdx), %r8d
movl 0xa8(%rdx), %edx
movl %r11d, %r15d
xorl $0x5, %r15d
movb $0x5, %bl
orl %r14d, %r15d
jne 0x1589b
movb $0x4, 0x1e(%rcx)
movq %r10, 0x20(%rcx)
movl $0x19, %r10d
movl $0x17, %r14d
xorl %r11d, %r11d
movb %r11b, (%rcx,%r14)
movb %bl, (%rcx,%r10)
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 0x157af
movb $0x1, 0x1a(%rcx)
movl %r9d, %r10d
andb $0x7, %r10b
movb %r10b, 0x1d(%rcx)
testb $0x8, %r9b
je 0x15790
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 0x157ac
movb $0x1, %r8b
movb %r8b, 0xd(%rcx)
movb %r8b, 0x10(%rcx)
movb %dl, 0x1b(%rcx)
cmpl $0x4, %eax
je 0x1580d
cmpl $0x2, %eax
je 0x15a4b
cmpl $0x1, %eax
jne 0x1597e
leaq 0x18ba3(%rip), %rdi     # 0x2e370
leaq 0x1ad4c(%rip), %rsi     # 0x30520
leaq 0x1afce(%rip), %rcx     # 0x307a9
movl $0x408, %edx            # imm = 0x408
callq 0xa0b0
movl 0x90(%rdx), %edx
movl %r8d, %r9d
xorl $0x6, %r9d
orl %edi, %r9d
jne 0x158b6
movb $0x2, 0x1e(%rcx)
movq %rdx, 0x20(%rcx)
movb $0x6, %r8b
xorl %edi, %edi
jmp 0x15930
testb $0x20, 0x8(%rsi)
jne 0x1588d
cmpl $0x4, %edi
jne 0x1588d
movw $0x101, 0xd(%rcx)       # imm = 0x101
jmp 0x1597e
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 0x1586c
movb $0x1, 0x1a(%rcx)
movb %r9b, 0x1d(%rcx)
movb %r8b, 0x1c(%rcx)
movb %dl, 0x1b(%rcx)
cmpl $0x4, %eax
je 0x158d0
cmpl $0x2, %eax
je 0x1588d
cmpl $0x1, %eax
jne 0x1597e
cmpl $0x3, %edi
je 0x1596b
jmp 0x1596f
cmpl $0x2, %edi
je 0x1597a
jmp 0x1597e
testl %r14d, %r14d
je 0x158ed
movb $0x1, %bl
cmpl $0x1, %r14d
je 0x158ef
cmpl $0x2, %r14d
jne 0x15a89
movb $0x4, %bl
jmp 0x158ef
testl %edi, %edi
je 0x15925
movb $0x1, %r9b
cmpl $0x1, %edi
je 0x15928
cmpl $0x2, %edi
jne 0x15aa8
movb $0x2, %r9b
jmp 0x15928
testb $0x20, 0x8(%rsi)
jne 0x158df
cmpl $0x4, %edi
je 0x15989
cmpl $0x2, %edi
je 0x1596b
jmp 0x1596f
xorl %ebx, %ebx
movb %bl, 0x1e(%rcx)
movq %r10, 0x20(%rcx)
movb %r14b, 0x17(%rcx)
movl %r11d, %r10d
andb $0x7, %r10b
movb %r10b, 0x19(%rcx)
testb $0x8, %r11b
je 0x1574d
movl $0x11, %r10d
movb $0x1, %r11b
movl $0xd, %r14d
movb $0x1, %bl
jmp 0x15745
xorl %r9d, %r9d
movb %r9b, 0x1e(%rcx)
movq %rdx, 0x20(%rcx)
movb %dil, 0x17(%rcx)
movb %r8b, 0x19(%rcx)
cmpl $0x1, %eax
je 0x15975
cmpl $0x2, %eax
je 0x15966
cmpl $0x4, %eax
jne 0x1597e
leaq 0x18a22(%rip), %rdi     # 0x2e370
leaq 0x1abcb(%rip), %rsi     # 0x30520
leaq 0x1ae4d(%rip), %rcx     # 0x307a9
movl $0x382, %edx            # imm = 0x382
callq 0xa0b0
cmpl $0x2, %esi
jne 0x1596f
movb $0x1, 0xb(%rcx)
movb $0x1, 0xc(%rcx)
jmp 0x1597e
cmpl $0x3, %esi
jne 0x1597e
movb $0x1, 0xb(%rcx)
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movw $0x101, 0xd(%rcx)       # imm = 0x101
jmp 0x1596f
leaq 0x1a42c(%rip), %rdi     # 0x2fdc4
leaq 0x1ab81(%rip), %rsi     # 0x30520
leaq 0x1ae03(%rip), %rcx     # 0x307a9
movl $0x307, %edx            # imm = 0x307
callq 0xa0b0
leaq 0x1ad73(%rip), %rdi     # 0x3072a
leaq 0x1ab62(%rip), %rsi     # 0x30520
leaq 0x1ade4(%rip), %rcx     # 0x307a9
movl $0x308, %edx            # imm = 0x308
callq 0xa0b0
leaq 0x1c2d5(%rip), %rdi     # 0x31cab
leaq 0x1ab43(%rip), %rsi     # 0x30520
leaq 0x1adc5(%rip), %rcx     # 0x307a9
movl $0x309, %edx            # imm = 0x309
callq 0xa0b0
leaq 0x1ad31(%rip), %rdi     # 0x30726
leaq 0x1ab24(%rip), %rsi     # 0x30520
leaq 0x1ada6(%rip), %rcx     # 0x307a9
movl $0x30a, %edx            # imm = 0x30A
callq 0xa0b0
leaq 0x1895c(%rip), %rdi     # 0x2e370
leaq 0x1ab05(%rip), %rsi     # 0x30520
leaq 0x1ad87(%rip), %rcx     # 0x307a9
movl $0x41e, %edx            # imm = 0x41E
callq 0xa0b0
leaq 0x1ad6e(%rip), %rdi     # 0x307a1
leaq 0x1aae6(%rip), %rsi     # 0x30520
leaq 0x1ad68(%rip), %rcx     # 0x307a9
movl $0x32f, %edx            # imm = 0x32F
callq 0xa0b0
leaq 0x1891e(%rip), %rdi     # 0x2e370
leaq 0x1aac7(%rip), %rsi     # 0x30520
leaq 0x1ad49(%rip), %rcx     # 0x307a9
movl $0x40a, %edx            # imm = 0x40A
callq 0xa0b0
leaq 0x188ff(%rip), %rdi     # 0x2e370
leaq 0x1aaa8(%rip), %rsi     # 0x30520
leaq 0x1ad2a(%rip), %rcx     # 0x307a9
movl $0x399, %edx            # imm = 0x399
callq 0xa0b0
leaq 0x188e0(%rip), %rdi     # 0x2e370
leaq 0x1aa89(%rip), %rsi     # 0x30520
leaq 0x1ad0b(%rip), %rcx     # 0x307a9
movl $0x3e9, %edx            # imm = 0x3E9
callq 0xa0b0
leaq 0x188c1(%rip), %rdi     # 0x2e370
leaq 0x1aa6a(%rip), %rsi     # 0x30520
leaq 0x1acec(%rip), %rcx     # 0x307a9
movl $0x369, %edx            # imm = 0x369
callq 0xa0b0