emit.h (6154B)
1 /* arch/x64/emit.h — shared x86-64 byte-level encoders, ABI tables, and type 2 * helpers. Used by emit.c (definitions), the standalone assembler (asm.c), and 3 * the NativeTarget codegen (native.c). Carries no codegen state (XImpl lives in 4 * native.c). */ 5 #ifndef KIT_ARCH_X64_EMIT_H 6 #define KIT_ARCH_X64_EMIT_H 7 8 #include <kit/cg.h> 9 #include <kit/compile.h> 10 11 #include "abi/abi.h" 12 #include "arch/mc.h" 13 #include "arch/x64/isa.h" 14 #include "core/core.h" 15 #include "core/slice.h" 16 #include "obj/obj.h" 17 18 /* ---- prologue placeholder budgets / Win64 constants ---- */ 19 #define X64_PROLOGUE_BYTES 96u 20 #define X64_PROLOGUE_BYTES_WIN64 192u 21 #define X64_PROLOGUE_BASE_BYTES 11u 22 #define X64_PROLOGUE_SRET_BYTES 7u 23 #define X64_PROLOGUE_SAVE_BYTES 7u 24 #define X64_PROLOGUE_XMM_SAVE_BYTES 8u 25 #define X64_PROLOGUE_CHKSTK_DELTA 6u 26 #define X64_WIN64_SHADOW_SPACE 32u 27 #define X64_MAX_CS_INT_REGS 7u 28 29 /* ---- per-OS ABI register layout (SysV vs Win64) ---- */ 30 typedef struct X64ABIRegs { 31 const u32* int_args; /* size = n_int_args */ 32 u32 n_int_args; /* 6 (SysV) / 4 (Win64) */ 33 u32 n_fp_args; /* 8 (SysV) / 4 (Win64) */ 34 int slot_shared_int_fp; /* 1 (Win64): arg slot index shared int/xmm */ 35 u32 shadow_space; /* 0 (SysV) / 32 (Win64) */ 36 int emit_sysv_vararg_save; /* 1 (SysV): emit 176B reg-save area */ 37 int vararg_fp_dup_to_gpr; /* 1 (Win64): variadic FP arg duped to GPR */ 38 u64 cs_int_mask; /* callee-saved GPRs */ 39 u64 cs_fp_mask; /* callee-saved XMMs */ 40 } X64ABIRegs; 41 42 const X64ABIRegs* x64_abi_for_os(KitOSKind os); 43 44 /* Per-instruction debug line rows. Declared here (mc.h only forward-declares 45 * Debug) so emit.c's encoders and native.c's lifecycle can both record rows 46 * without taking a full dependency on debug/debug.h. */ 47 extern void debug_emit_row(Debug*, ObjSecId text_section, u32 offset, SrcLoc); 48 extern void debug_func_pc_range(Debug*, ObjSecId text_section, u32 begin_ofs, 49 u32 end_ofs); 50 51 /* ---- type helpers ---- */ 52 #define CG_BUILTIN_ID(k) ((KitCgTypeId)((1u << 6) | (u32)(k))) 53 static inline int type_is_64(KitCgTypeId t) { 54 return t == CG_BUILTIN_ID(KIT_CG_BUILTIN_I64) || 55 t == CG_BUILTIN_ID(KIT_CG_BUILTIN_F64) || t >= (KitCgTypeId)(2u << 6); 56 } 57 static inline int type_is_fp_double(KitCgTypeId t) { 58 return t == CG_BUILTIN_ID(KIT_CG_BUILTIN_F64); 59 } 60 static inline u32 type_byte_size(KitCgTypeId t) { 61 if (t == CG_BUILTIN_ID(KIT_CG_BUILTIN_I8) || 62 t == CG_BUILTIN_ID(KIT_CG_BUILTIN_BOOL)) 63 return 1; 64 if (t == CG_BUILTIN_ID(KIT_CG_BUILTIN_I16)) return 2; 65 if (t == CG_BUILTIN_ID(KIT_CG_BUILTIN_I32) || 66 t == CG_BUILTIN_ID(KIT_CG_BUILTIN_F32)) 67 return 4; 68 if (t == CG_BUILTIN_ID(KIT_CG_BUILTIN_F128)) return 16; 69 return 8; 70 } 71 static inline int type_is_signed(KitCgTypeId t) { 72 (void)t; 73 return 0; 74 } 75 76 static inline void x64_abi_direct_reg_need(const ABIArgInfo* ai, u32* need_int, 77 u32* need_fp) { 78 *need_int = 0; 79 *need_fp = 0; 80 if (!ai || ai->kind != ABI_ARG_DIRECT) return; 81 for (u16 i = 0; i < ai->nparts; ++i) { 82 const ABIArgPart* p = &ai->parts[i]; 83 if (p->cls == ABI_CLASS_FP) 84 ++*need_fp; 85 else if (p->cls == ABI_CLASS_INT) 86 ++*need_int; 87 } 88 } 89 90 /* ---- byte-level encoders (defined in emit.c) ---- */ 91 void emit1(MCEmitter* mc, u8 b); 92 void emit_leave(MCEmitter* mc); 93 void emit_u32le(MCEmitter* mc, u32 v); 94 void emit_rex(MCEmitter* mc, int w, u32 reg, u32 index, u32 rm); 95 void emit_rex_force(MCEmitter* mc, int w, u32 reg, u32 index, u32 rm); 96 u8 modrm(u32 mod, u32 reg, u32 rm); 97 u8 sib(u32 scale, u32 index, u32 base); 98 void emit_mem_operand(MCEmitter* mc, u32 reg, u32 base, i32 disp); 99 void emit_rm_reg(MCEmitter* mc, u32 reg, u32 rm); 100 void emit_mov_rr(MCEmitter* mc, int w, u32 dst, u32 src); 101 void emit_mov_load(MCEmitter* mc, u32 size, int signed_ext, u32 dst, u32 base, 102 i32 disp); 103 void emit_mov_store(MCEmitter* mc, u32 size, u32 src, u32 base, i32 disp); 104 void emit_lea(MCEmitter* mc, u32 dst, u32 base, i32 disp); 105 void emit_mov_load_idx(MCEmitter* mc, u32 size, int signed_ext, u32 dst, 106 u32 base, u32 index, u32 log2_scale, i32 disp); 107 void emit_mov_store_idx(MCEmitter* mc, u32 size, u32 src, u32 base, u32 index, 108 u32 log2_scale, i32 disp); 109 void emit_ret(MCEmitter* mc); 110 void x64_emit_load_imm(MCEmitter* mc, int is64, u32 dst, i64 imm); 111 void emit_alu_rr(MCEmitter* mc, int w, u8 op, u32 dst, u32 src); 112 void emit_imul_rr(MCEmitter* mc, int w, u32 dst, u32 src); 113 void emit_f7_rm(MCEmitter* mc, int w, u32 sub, u32 reg); 114 void emit_shift_cl(MCEmitter* mc, int w, u32 sub, u32 reg); 115 void emit_shift_imm(MCEmitter* mc, int w, u32 sub, u32 reg, u8 imm); 116 void emit_cqo_or_cdq(MCEmitter* mc, int w); 117 void emit_xor_self(MCEmitter* mc, int w, u32 r); 118 void emit_cmp_imm8(MCEmitter* mc, int w, u32 reg, i8 imm); 119 void emit_alu_imm8(MCEmitter* mc, int w, u32 sub, u32 reg, i8 imm); 120 void emit_alu_imm32(MCEmitter* mc, int w, u32 sub, u32 reg, i32 imm); 121 void emit_imul_imm8(MCEmitter* mc, int w, u32 dst, u32 src, i8 imm); 122 void emit_imul_imm32(MCEmitter* mc, int w, u32 dst, u32 src, i32 imm); 123 int imm_fits_i8(i64 imm); 124 int imm_fits_i32(i64 imm); 125 void emit_test_self(MCEmitter* mc, int w, u32 reg); 126 void emit_setcc(MCEmitter* mc, u32 cc, u32 reg); 127 void emit_movzx_r32_r8(MCEmitter* mc, u32 dst, u32 src); 128 void emit_extend_rr(MCEmitter* mc, int w, int signed_ext, u32 src_size, u32 dst, 129 u32 src); 130 void emit_sse_rr(MCEmitter* mc, u8 prefix, u8 opcode, u32 dst, u32 src); 131 void emit_sse_load(MCEmitter* mc, u8 prefix, u8 opcode, u32 dst, u32 base, 132 i32 disp); 133 void emit_sse_store(MCEmitter* mc, u8 prefix, u8 opcode, u32 src, u32 base, 134 i32 disp); 135 void emit_sse_load_idx(MCEmitter* mc, u8 prefix, u8 opcode, u32 dst, u32 base, 136 u32 index, u32 log2_scale, i32 disp); 137 void emit_sse_store_idx(MCEmitter* mc, u8 prefix, u8 opcode, u32 src, u32 base, 138 u32 index, u32 log2_scale, i32 disp); 139 void emit_sse_rr_w(MCEmitter* mc, u8 prefix, u8 opcode, int w, u32 dst, 140 u32 src); 141 142 #endif