- 将scc_ast_def.h中的attr_of从union改为struct以修复结构定义问题 - 添加type_abi依赖到ast2ir模块的cbuild.toml配置文件中 - 重命名scc_ast2ir.h中的abi字段为type_abi,并更新相关初始化函数签名 - 移除废弃的scc_abi_type.h和相关平台ABI头文件 - 添加辅助函数is_variadic_marker和fixed_param_count用于处理可变参数 - 添加数组和聚合类型初始化的辅助函数
546 lines
19 KiB
C
546 lines
19 KiB
C
#include <x86/scc_x86_encode.h>
|
||
#include <x86/scc_x86_iform.h>
|
||
#include <x86/scc_x86_reg.h>
|
||
|
||
#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;
|
||
} |