Files
scc/libs/mcode/src/scc_x86_encode.c
zzy 31d7e91ef1 refactor(ast2ir): 重构ABI类型系统并修复union结构问题
- 将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用于处理可变参数
- 添加数组和聚合类型初始化的辅助函数
2026-06-01 12:14:13 +08:00

546 lines
19 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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;
}