#ifndef __SCC_X86_MIR_H__ #define __SCC_X86_MIR_H__ #include "../scc_mir.h" #include #include #include #include #include typedef struct { scc_x86_iform_t opcode; // must be int or enum int num_operands; scc_x86_operand_value_t operands[3]; scc_pos_t src_loc; } scc_x86_instr_t; typedef union scc_mir_x86_instr { scc_mir_instr_t instr; scc_x86_instr_t x86_instr; } scc_mir_x86_instr_t; typedef SCC_VEC(scc_mir_x86_instr_t) scc_mir_x86_instr_vec_t; #define SCC_MIR_X86_BBLOCK_INSTRS(bb) ((scc_mir_x86_instr_vec_t *)&bb->values) #define SCC_MIR_X86_BBLOCK_INSTRS_C(bb) \ ((const scc_mir_x86_instr_vec_t *)&bb->values) static inline cbool scc_x86_reg_is_vreg(scc_x86_reg_t reg) { return reg >= SCC_X86_REG_COUNT; } static inline cbool scc_x86_op_is_vreg(const scc_x86_operand_value_t *op) { return op->kind == SCC_X86_OPR_REG && scc_x86_reg_is_vreg(op->reg); } static inline int scc_x86_reg_get_vreg(scc_x86_reg_t reg) { return (int)reg - (int)SCC_X86_REG_COUNT; } static inline int scc_x86_op_get_vreg(const scc_x86_operand_value_t *op) { return scc_x86_reg_get_vreg(op->reg); } static inline void scc_x86_op_set_preg(scc_x86_operand_value_t *op, scc_x86_reg_t preg) { op->kind = SCC_X86_OPR_REG; op->reg = preg; } // slot_id 编码为 base=INVALID, disp=slot_id static inline scc_x86_operand_value_t scc_x86_op_slot(int slot_id, u8 size) { scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_MEM}; o.mem.base = SCC_X86_REG_INVALID; o.mem.index = SCC_X86_REG_INVALID; o.mem.scale = 1; o.mem.disp.displacement = slot_id; o.mem.disp.displacement_bits = 0; o.size = size; return o; } static inline bool scc_x86_op_is_slot(const scc_x86_operand_value_t *op) { return op->kind == SCC_X86_OPR_MEM && op->mem.base == SCC_X86_REG_INVALID; } static inline int scc_x86_op_slot_id(const scc_x86_operand_value_t *op) { return op->mem.disp.displacement; } static inline void scc_mir_x86_instr_0(scc_mir_x86_instr_t *out, scc_x86_iform_t opcode, scc_pos_t pos) { out->x86_instr.opcode = opcode; out->x86_instr.num_operands = 0; out->x86_instr.src_loc = pos; } static inline void scc_mir_x86_instr_1(scc_mir_x86_instr_t *out, scc_x86_iform_t opcode, scc_x86_operand_value_t op0, scc_pos_t pos) { out->x86_instr.opcode = opcode; out->x86_instr.num_operands = 1; out->x86_instr.operands[0] = op0; out->x86_instr.src_loc = pos; } static inline void scc_mir_x86_instr_2(scc_mir_x86_instr_t *out, scc_x86_iform_t opcode, scc_x86_operand_value_t op0, scc_x86_operand_value_t op1, scc_pos_t pos) { out->x86_instr.opcode = opcode; out->x86_instr.num_operands = 2; out->x86_instr.operands[0] = op0; out->x86_instr.operands[1] = op1; out->x86_instr.src_loc = pos; } static inline void scc_mir_x86_instr_3(scc_mir_x86_instr_t *out, scc_x86_iform_t opcode, scc_x86_operand_value_t op0, scc_x86_operand_value_t op1, scc_x86_operand_value_t op2, scc_pos_t pos) { out->x86_instr.opcode = opcode; out->x86_instr.num_operands = 3; out->x86_instr.operands[0] = op0; out->x86_instr.operands[1] = op1; out->x86_instr.operands[2] = op2; out->x86_instr.src_loc = pos; } void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec, scc_x86_operand_value_t dst, scc_x86_operand_value_t src); void scc_x86_emit_load_to_vec(scc_mir_x86_instr_vec_t *vec, scc_x86_operand_value_t dst, scc_x86_operand_value_t src_addr); void scc_x86_emit_store_to_vec(scc_mir_x86_instr_vec_t *vec, scc_x86_operand_value_t dst_addr, scc_x86_operand_value_t src); #endif /* __SCC_X86_MIR_H__ */