#include #include #include #if 1 #ifdef LOG_INFO #undef LOG_INFO #endif #define LOG_INFO(...) #endif /* ---------- 内部辅助 ---------- */ static inline void emit_u8(scc_mcode_t *m, uint8_t v) { scc_mcode_add_u8(m, v); } static inline void emit_u16(scc_mcode_t *m, uint16_t v) { scc_mcode_add_u16(m, v); } static inline void emit_u32(scc_mcode_t *m, uint32_t v) { scc_mcode_add_u32(m, v); } static inline void emit_u64(scc_mcode_t *m, uint64_t v) { scc_mcode_add_u64(m, v); } /* ---------- 寄存器查询 ---------- */ static inline uint16_t scc_reg_width(scc_x86_reg_t reg) { if (reg >= SCC_X86_REG_COUNT || reg == SCC_X86_REG_INVALID) return 0; return scc_x86_reg_table[reg].width; } static inline int scc_reg_ordinal(scc_x86_reg_t reg) { if (reg >= SCC_X86_REG_COUNT || reg == SCC_X86_REG_INVALID) return 0; return scc_x86_reg_table[reg].ordinal; } static int reg_low3(scc_x86_reg_t reg) { if (reg == SCC_X86_REG_INVALID) return 0; // RIP/EIP/IP 必须返回 5,否则无法编码 RIP 相对寻址 if (reg == SCC_X86_REG_RIP || reg == SCC_X86_REG_EIP || reg == SCC_X86_REG_IP) return 5; return scc_reg_ordinal(reg) & 7; } static int reg_rex_bit(scc_x86_reg_t reg) { if (reg == SCC_X86_REG_INVALID) return 0; // RIP 不需要 REX 扩展 if (reg == SCC_X86_REG_RIP || reg == SCC_X86_REG_EIP || reg == SCC_X86_REG_IP) return 0; if (reg >= SCC_X86_REG_AH && reg <= SCC_X86_REG_DH) return 0; return (scc_reg_ordinal(reg) >= 8) ? 1 : 0; } /* ---------- 操作数宽度推导 ---------- */ static int infer_operand_width(const scc_x86_iform_info_t *info, const scc_x86_operand_value_t ops[]) { for (int i = 0; i < info->num_explicit_ops; i++) { if (ops[i].kind == SCC_X86_OPR_REG && !info->ops[i].is_implicit) { uint16_t w; if (ops[i].size_bits > 0 && ops[i].reg >= SCC_X86_REG_R8 && ops[i].reg <= SCC_X86_REG_R15) { /* R8-R15:宽度由 size_bits 字段推导(单位:bit) */ w = ops[i].size_bits; } else { w = scc_reg_width(ops[i].reg); } if (w > 0) return w; } } const char *eosz = info->encode.eosz; int default_64 = info->encode.default_64b; if (!scc_strcmp(eosz, "o16")) return 16; if (!scc_strcmp(eosz, "o32")) return 32; if (!scc_strcmp(eosz, "o64")) return 64; if (!scc_strcmp(eosz, "oszall") || !scc_strcmp(eosz, "osznot16")) return default_64 ? 64 : 32; return 32; } /* ---------- 前缀决策 ---------- */ static int need_rexw(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op, scc_x86_reg_t rm_op, scc_x86_reg_t base, scc_x86_reg_t idx) { if (enc->rex_w == 1) return 1; if (enc->rex_w == 0) return 0; int has_64bit_op = 0; if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 64) has_64bit_op = 1; if (rm_op != SCC_X86_REG_INVALID && scc_reg_width(rm_op) == 64) has_64bit_op = 1; if (base != SCC_X86_REG_INVALID && scc_reg_width(base) == 64) has_64bit_op = 1; if (idx != SCC_X86_REG_INVALID && scc_reg_width(idx) == 64) has_64bit_op = 1; if (enc->default_64b) { return (reg_op != SCC_X86_REG_INVALID && reg_rex_bit(reg_op)) || (rm_op != SCC_X86_REG_INVALID && reg_rex_bit(rm_op)) || (base != SCC_X86_REG_INVALID && reg_rex_bit(base)) || (idx != SCC_X86_REG_INVALID && reg_rex_bit(idx)) ? 1 : 0; } return has_64bit_op; } static int need_66_prefix(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op, scc_x86_reg_t rm_op) { if (enc->osz_required) return 1; if (!scc_strcmp(enc->eosz, "o32") || !scc_strcmp(enc->eosz, "o64")) return 0; if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 16) return 1; if (rm_op != SCC_X86_REG_INVALID && scc_reg_width(rm_op) == 16) return 1; return 0; } static int need_67_prefix(const scc_x86_encoding_t *enc, scc_x86_reg_t base, scc_x86_reg_t idx) { (void)enc; (void)base; (void)idx; return 0; } static void emit_legacy_prefixes(scc_mcode_t *m, const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op, scc_x86_reg_t rm_op, scc_x86_reg_t base, scc_x86_reg_t idx) { if (enc->has_lock) emit_u8(m, 0xF0); if (enc->f2_required) emit_u8(m, 0xF2); if (enc->f3_required) emit_u8(m, 0xF3); if (need_66_prefix(enc, reg_op, rm_op)) emit_u8(m, 0x66); if (need_67_prefix(enc, base, idx)) emit_u8(m, 0x67); } static void emit_rex(scc_mcode_t *m, const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op, scc_x86_reg_t rm_op, scc_x86_reg_t base, scc_x86_reg_t idx, int op_width) { // 新增 op_width 参数 int rex = 0x40; // 仅当 op_width == 64 时才考虑 REX.W if (op_width == 64 && need_rexw(enc, reg_op, rm_op, base, idx)) rex |= 8; if (reg_op != SCC_X86_REG_INVALID && reg_rex_bit(reg_op)) rex |= 4; if (idx != SCC_X86_REG_INVALID && reg_rex_bit(idx)) rex |= 2; scc_x86_reg_t b = (rm_op != SCC_X86_REG_INVALID) ? rm_op : base; if (b != SCC_X86_REG_INVALID && reg_rex_bit(b)) rex |= 1; if (rex != 0x40) { LOG_INFO("[REX] emit 0x%02x", (uint8_t)rex); emit_u8(m, (uint8_t)rex); } } static void emit_escape_map(scc_mcode_t *m, const scc_x86_encoding_t *enc) { if (enc->map == 1) { emit_u8(m, 0x0F); } else if (enc->map == 2) { emit_u8(m, 0x0F); emit_u8(m, 0x38); } else if (enc->map == 3) { emit_u8(m, 0x0F); emit_u8(m, 0x3A); } } static void emit_opcode(scc_mcode_t *m, const scc_x86_encoding_t *enc, scc_x86_reg_t rm_reg, scc_x86_reg_t base_reg, int op_width) { for (int i = 0; i < enc->opcode_len; i++) { uint8_t byte = enc->opcode[i]; if (enc->partial_opcode && i == enc->opcode_len - 1) { scc_x86_reg_t target = (rm_reg != SCC_X86_REG_INVALID) ? rm_reg : base_reg; if (target != SCC_X86_REG_INVALID) byte |= (reg_low3(target) & 7); } /* MOV r8, imm8: B8-BF → B0-B7 */ if (op_width == 8 && (byte & 0xF8) == 0xB8) byte -= 8; emit_u8(m, byte); } } static int scale_to_enc(uint8_t scale) { switch (scale) { case 1: return 0; case 2: return 1; case 4: return 2; case 8: return 3; default: return -1; } } /* 修正:位移大小只由数值范围决定,与基址寄存器无关 */ static int disp_size(int32_t disp, scc_x86_reg_t base) { if (disp == 0) { /* RBP/R13 with disp=0: must use mod=01 + disp8=0, because mod=00 + r/m=101 means RIP-relative */ if (base == SCC_X86_REG_RBP || base == SCC_X86_REG_R13) return 8; return 0; } if (disp >= -128 && disp <= 127) return 8; return 32; } /* ---------- 立即数发射 ---------- */ static void emit_immediate(scc_mcode_t *m, const scc_x86_encoding_t *enc, const scc_x86_operand_t *tmpl, int imm_idx, int64_t imm_val, int op_width) { const char *oc2 = tmpl[imm_idx].oc2; int imm_size = enc->imm_size; if (!scc_strcmp(oc2, "b")) imm_size = 1; else if (!scc_strcmp(oc2, "w")) imm_size = 2; else if (!scc_strcmp(oc2, "z")) imm_size = (op_width <= 16) ? op_width / 8 : (op_width <= 32 ? 4 : 4); else if (!scc_strcmp(oc2, "v")) imm_size = op_width / 8; else if (!scc_strcmp(oc2, "d") || !scc_strcmp(oc2, "ss")) imm_size = 4; else if (!scc_strcmp(oc2, "q")) imm_size = 8; LOG_INFO("[IMM] val=%lld size=%d", imm_val, imm_size); switch (imm_size) { case 1: emit_u8(m, (uint8_t)imm_val); break; case 2: emit_u16(m, (uint16_t)imm_val); break; case 4: emit_u32(m, (uint32_t)imm_val); break; case 8: emit_u64(m, (uint64_t)imm_val); break; default: break; } } /* ---------- ModR/M + SIB + 位移 + 立即数 ---------- */ static void emit_modrm_sib_disp(scc_mcode_t *m, const scc_x86_iform_info_t *info, const scc_x86_operand_value_t ops[], int op_width) { const scc_x86_encoding_t *enc = &info->encode; const scc_x86_operand_t *tmpl = info->ops; int num_ops = info->num_explicit_ops; scc_x86_reg_t reg_r = SCC_X86_REG_INVALID; scc_x86_reg_t reg_b = SCC_X86_REG_INVALID; int has_mem = 0; scc_x86_mem_t memdesc = {0}; int64_t imm_val = 0; int imm_idx = -1; for (int i = 0; i < num_ops; i++) { const char *tname = tmpl[i].name; if (ops[i].kind == SCC_X86_OPR_REG) { LOG_INFO("[OPD] %d: REG kind, name=\"%s\" reg=%d", i, tname, ops[i].reg); if (scc_strcmp(tname, "REG0") == 0) reg_r = ops[i].reg; else if (scc_strcmp(tname, "REG1") == 0) reg_b = ops[i].reg; else { if (reg_r == SCC_X86_REG_INVALID) reg_r = ops[i].reg; else if (reg_b == SCC_X86_REG_INVALID) reg_b = ops[i].reg; } } else if (ops[i].kind == SCC_X86_OPR_MEM) { has_mem = 1; memdesc = ops[i].mem; } else if (ops[i].kind == SCC_X86_OPR_IMM) { imm_val = ops[i].imm0; imm_idx = i; } } LOG_INFO("[MODRM] reg_r=%d (ord=%d) reg_b=%d (ord=%d)", reg_r, scc_reg_ordinal(reg_r), reg_b, scc_reg_ordinal(reg_b)); uint8_t modrm = 0; if (has_mem) { // ========== RIP 相对寻址特殊处理 ========== if (memdesc.base == SCC_X86_REG_RIP && memdesc.index == SCC_X86_REG_INVALID) { // RIP 相对:mod=00, r/m=101,位移固定 32 位 if (reg_r != SCC_X86_REG_INVALID) modrm |= (reg_low3(reg_r) & 7) << 3; else if (enc->modrm_reg_fix >= 0) modrm |= (enc->modrm_reg_fix & 7) << 3; modrm |= 0x05; // r/m = 101 emit_u8(m, modrm); // 写入 32 位位移(小端) int32_t disp32 = (int32_t)memdesc.disp.displacement; emit_u32(m, (uint32_t)disp32); // 处理立即数(如果有) if (imm_idx >= 0) { emit_immediate(m, enc, tmpl, imm_idx, imm_val, op_width); } return; // 已处理完,跳过后续 SIB/位移逻辑 } // ========================================== if (reg_r != SCC_X86_REG_INVALID) modrm |= (reg_low3(reg_r) & 7) << 3; else if (enc->modrm_reg_fix >= 0) modrm |= (enc->modrm_reg_fix & 7) << 3; int32_t disp = memdesc.disp.displacement; // 优先使用用户指定的 displacement_bits,转换为字节数 int dsize = 0; if (memdesc.disp.displacement_bits != 0) { dsize = memdesc.disp.displacement_bits / 8; if (dsize != 1 && dsize != 2 && dsize != 4 && dsize != 8) dsize = 0; // 无效则回退 } if (dsize == 0) { // 使用自动计算:disp_size 返回位数,除以 8 得字节数 int bits = disp_size(disp, memdesc.base); dsize = bits / 8; } // 设置 ModRM 的 mod 字段 if (dsize == 0) modrm |= 0x00; else if (dsize == 1) modrm |= 0x40; else if (dsize == 2 || dsize == 4 || dsize == 8) modrm |= 0x80; // 2/4/8 字节位移均使用 mod=10b if (memdesc.index != SCC_X86_REG_INVALID) { // SIB 寻址 modrm |= 4; int idx_ord = scc_reg_ordinal(memdesc.index); int base_ord = scc_reg_ordinal(memdesc.base); int scale_enc = scale_to_enc(memdesc.scale); if (scale_enc < 0) return; uint8_t sib = (uint8_t)((scale_enc << 6) | ((idx_ord & 7) << 3) | (base_ord & 7)); emit_u8(m, modrm); emit_u8(m, sib); if (dsize == 1) emit_u8(m, (uint8_t)disp); else if (dsize == 2) emit_u16(m, (uint16_t)disp); else if (dsize == 4) emit_u32(m, (uint32_t)disp); else if (dsize == 8) emit_u64(m, (uint64_t)disp); } else if (memdesc.base == SCC_X86_REG_INVALID) { // 绝对地址:mod=00, r/m=101,位移 32 位 modrm |= 5; emit_u8(m, modrm); emit_u32(m, (uint32_t)disp); } else { // 一般基址寻址 int base_ord = scc_reg_ordinal(memdesc.base); if (memdesc.base == SCC_X86_REG_RSP || memdesc.base == SCC_X86_REG_R12) { // 需要 SIB(基址为 RSP/R12 时强制) modrm |= 4; uint8_t sib = (uint8_t)((base_ord & 7) | (4 << 3)); emit_u8(m, modrm); emit_u8(m, sib); if (dsize == 1) emit_u8(m, (uint8_t)disp); else if (dsize == 2) emit_u16(m, (uint16_t)disp); else if (dsize == 4) emit_u32(m, (uint32_t)disp); else if (dsize == 8) emit_u64(m, (uint64_t)disp); } else { modrm |= (base_ord & 7); emit_u8(m, modrm); if (dsize == 1) emit_u8(m, (uint8_t)disp); else if (dsize == 2) emit_u16(m, (uint16_t)disp); else if (dsize == 4) emit_u32(m, (uint32_t)disp); else if (dsize == 8) emit_u64(m, (uint64_t)disp); } } } else { // 没有内存操作数:寄存器-寄存器或单个寄存器 int is_single_reg_op = (info->num_explicit_ops == 1 && enc->modrm_reg_fix == -1 && enc->modrm_rm_fix == -1 && enc->mod_fix == 3); if (is_single_reg_op && reg_r != SCC_X86_REG_INVALID && reg_b == SCC_X86_REG_INVALID) { modrm = 0xC0 | (reg_low3(reg_r) & 7); emit_u8(m, modrm); LOG_INFO("[MODRM] single reg operand treated as rm, emit 0x%02x", modrm); } else { modrm = 0xC0; if (enc->modrm_reg_fix >= 0) modrm |= (enc->modrm_reg_fix & 7) << 3; else if (reg_r != SCC_X86_REG_INVALID) modrm |= (reg_low3(reg_r) & 7) << 3; if (enc->modrm_rm_fix >= 0) { modrm |= enc->modrm_rm_fix & 7; } else if (reg_b != SCC_X86_REG_INVALID) { modrm |= reg_low3(reg_b) & 7; } else if (enc->modrm_reg_fix >= 0 && reg_r != SCC_X86_REG_INVALID) { modrm |= reg_low3(reg_r) & 7; } else if (reg_r != SCC_X86_REG_INVALID) { modrm |= reg_low3(reg_r) & 7; } emit_u8(m, modrm); } } LOG_INFO("[MODRM] emit byte 0x%02x", modrm); // 立即数在 ModRM 后发射 if (imm_idx >= 0) { emit_immediate(m, enc, tmpl, imm_idx, imm_val, op_width); } } /* ---------- 主编码入口 ---------- */ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform, const scc_x86_operand_value_t *ops) { if (!mcode || !ops) return -1; if (iform >= SCC_X86_IFORM_COUNT) Panic("invalid iform %d", iform); const scc_x86_iform_info_t *info = &scc_x86_iform_table[iform]; int num_ops = info->num_explicit_ops; const scc_x86_encoding_t *enc = &info->encode; const scc_x86_operand_t *tmpl = info->ops; LOG_INFO("[ENCODE] %s", info->iform_name); scc_x86_reg_t reg_field = SCC_X86_REG_INVALID; scc_x86_reg_t rm_field = SCC_X86_REG_INVALID; scc_x86_reg_t base_reg = SCC_X86_REG_INVALID; scc_x86_reg_t idx_reg = SCC_X86_REG_INVALID; int64_t imm_val = 0; int imm_idx = -1; for (int i = 0; i < num_ops; i++) { const char *tname = tmpl[i].name; if (ops[i].kind == SCC_X86_OPR_REG) { if (scc_strcmp(tname, "REG0") == 0) { if (enc->modrm_reg_fix >= 0) rm_field = ops[i].reg; else reg_field = ops[i].reg; } else if (scc_strcmp(tname, "REG1") == 0) { if (enc->modrm_rm_fix >= 0) reg_field = ops[i].reg; else rm_field = ops[i].reg; } else { if (reg_field == SCC_X86_REG_INVALID) reg_field = ops[i].reg; else if (rm_field == SCC_X86_REG_INVALID) rm_field = ops[i].reg; } } else if (ops[i].kind == SCC_X86_OPR_MEM) { base_reg = ops[i].mem.base; idx_reg = ops[i].mem.index; } else if (ops[i].kind == SCC_X86_OPR_IMM) { imm_val = ops[i].imm0; imm_idx = i; } else if (ops[i].kind == SCC_X86_OPR_RELBR) { imm_val = ops[i].brdisp; // i32 → i64 自动符号扩展 imm_idx = i; } } // 特殊处理 SETZ 等单寄存器指令 if (enc->has_modrm && info->num_explicit_ops == 1 && enc->modrm_reg_fix == -1 && enc->modrm_rm_fix == -1 && enc->mod_fix == 3) { if (reg_field != SCC_X86_REG_INVALID && rm_field == SCC_X86_REG_INVALID) { rm_field = reg_field; reg_field = SCC_X86_REG_INVALID; } } int op_width = infer_operand_width(info, ops); LOG_INFO("[OPWIDTH] %d bits", op_width); if (!enc->has_modrm) { rm_field = reg_field; reg_field = SCC_X86_REG_INVALID; } emit_legacy_prefixes(mcode, enc, reg_field, rm_field, base_reg, idx_reg); emit_rex(mcode, enc, reg_field, rm_field, base_reg, idx_reg, op_width); emit_escape_map(mcode, enc); if (enc->has_modrm) { emit_opcode(mcode, enc, rm_field, base_reg, op_width); emit_modrm_sib_disp(mcode, info, ops, op_width); } else { emit_opcode(mcode, enc, rm_field, base_reg, op_width); if (imm_idx >= 0) { emit_immediate(mcode, enc, tmpl, imm_idx, imm_val, op_width); } } return 0; }