12#define MAX_LABEL_REFS 32
39 uint32_t label_addrs[MAX_LABELS];
43 const char *label_names[MAX_LABELS];
57 uint32_t current_aligned_write_pos;
71#define ALIGNED_WRITE_POSITION_NONE 1
148static const x86opnd_t NO_OPND = { OPND_NONE, 0, .as.imm = 0 };
151static const x86opnd_t RIP = { OPND_REG, 64, .as.reg = { REG_IP, 5 }};
154static const x86opnd_t RAX = { OPND_REG, 64, .as.reg = { REG_GP, 0 }};
155static const x86opnd_t RCX = { OPND_REG, 64, .as.reg = { REG_GP, 1 }};
156static const x86opnd_t RDX = { OPND_REG, 64, .as.reg = { REG_GP, 2 }};
157static const x86opnd_t RBX = { OPND_REG, 64, .as.reg = { REG_GP, 3 }};
158static const x86opnd_t RSP = { OPND_REG, 64, .as.reg = { REG_GP, 4 }};
159static const x86opnd_t RBP = { OPND_REG, 64, .as.reg = { REG_GP, 5 }};
160static const x86opnd_t RSI = { OPND_REG, 64, .as.reg = { REG_GP, 6 }};
161static const x86opnd_t RDI = { OPND_REG, 64, .as.reg = { REG_GP, 7 }};
162static const x86opnd_t R8 = { OPND_REG, 64, .as.reg = { REG_GP, 8 }};
163static const x86opnd_t R9 = { OPND_REG, 64, .as.reg = { REG_GP, 9 }};
164static const x86opnd_t R10 = { OPND_REG, 64, .as.reg = { REG_GP, 10 }};
165static const x86opnd_t R11 = { OPND_REG, 64, .as.reg = { REG_GP, 11 }};
166static const x86opnd_t R12 = { OPND_REG, 64, .as.reg = { REG_GP, 12 }};
167static const x86opnd_t R13 = { OPND_REG, 64, .as.reg = { REG_GP, 13 }};
168static const x86opnd_t R14 = { OPND_REG, 64, .as.reg = { REG_GP, 14 }};
169static const x86opnd_t R15 = { OPND_REG, 64, .as.reg = { REG_GP, 15 }};
172static const x86opnd_t EAX = { OPND_REG, 32, .as.reg = { REG_GP, 0 }};
173static const x86opnd_t ECX = { OPND_REG, 32, .as.reg = { REG_GP, 1 }};
174static const x86opnd_t EDX = { OPND_REG, 32, .as.reg = { REG_GP, 2 }};
175static const x86opnd_t EBX = { OPND_REG, 32, .as.reg = { REG_GP, 3 }};
176static const x86opnd_t ESP = { OPND_REG, 32, .as.reg = { REG_GP, 4 }};
177static const x86opnd_t EBP = { OPND_REG, 32, .as.reg = { REG_GP, 5 }};
178static const x86opnd_t ESI = { OPND_REG, 32, .as.reg = { REG_GP, 6 }};
179static const x86opnd_t EDI = { OPND_REG, 32, .as.reg = { REG_GP, 7 }};
180static const x86opnd_t R8D = { OPND_REG, 32, .as.reg = { REG_GP, 8 }};
181static const x86opnd_t R9D = { OPND_REG, 32, .as.reg = { REG_GP, 9 }};
182static const x86opnd_t R10D = { OPND_REG, 32, .as.reg = { REG_GP, 10 }};
183static const x86opnd_t R11D = { OPND_REG, 32, .as.reg = { REG_GP, 11 }};
184static const x86opnd_t R12D = { OPND_REG, 32, .as.reg = { REG_GP, 12 }};
185static const x86opnd_t R13D = { OPND_REG, 32, .as.reg = { REG_GP, 13 }};
186static const x86opnd_t R14D = { OPND_REG, 32, .as.reg = { REG_GP, 14 }};
187static const x86opnd_t R15D = { OPND_REG, 32, .as.reg = { REG_GP, 15 }};
190static const x86opnd_t AX = { OPND_REG, 16, .as.reg = { REG_GP, 0 }};
191static const x86opnd_t CX = { OPND_REG, 16, .as.reg = { REG_GP, 1 }};
192static const x86opnd_t DX = { OPND_REG, 16, .as.reg = { REG_GP, 2 }};
193static const x86opnd_t BX = { OPND_REG, 16, .as.reg = { REG_GP, 3 }};
194static const x86opnd_t SP = { OPND_REG, 16, .as.reg = { REG_GP, 4 }};
195static const x86opnd_t BP = { OPND_REG, 16, .as.reg = { REG_GP, 5 }};
196static const x86opnd_t SI = { OPND_REG, 16, .as.reg = { REG_GP, 6 }};
197static const x86opnd_t DI = { OPND_REG, 16, .as.reg = { REG_GP, 7 }};
198static const x86opnd_t R8W = { OPND_REG, 16, .as.reg = { REG_GP, 8 }};
199static const x86opnd_t R9W = { OPND_REG, 16, .as.reg = { REG_GP, 9 }};
200static const x86opnd_t R10W = { OPND_REG, 16, .as.reg = { REG_GP, 10 }};
201static const x86opnd_t R11W = { OPND_REG, 16, .as.reg = { REG_GP, 11 }};
202static const x86opnd_t R12W = { OPND_REG, 16, .as.reg = { REG_GP, 12 }};
203static const x86opnd_t R13W = { OPND_REG, 16, .as.reg = { REG_GP, 13 }};
204static const x86opnd_t R14W = { OPND_REG, 16, .as.reg = { REG_GP, 14 }};
205static const x86opnd_t R15W = { OPND_REG, 16, .as.reg = { REG_GP, 15 }};
208static const x86opnd_t AL = { OPND_REG, 8, .as.reg = { REG_GP, 0 }};
209static const x86opnd_t CL = { OPND_REG, 8, .as.reg = { REG_GP, 1 }};
210static const x86opnd_t DL = { OPND_REG, 8, .as.reg = { REG_GP, 2 }};
211static const x86opnd_t BL = { OPND_REG, 8, .as.reg = { REG_GP, 3 }};
212static const x86opnd_t SPL = { OPND_REG, 8, .as.reg = { REG_GP, 4 }};
213static const x86opnd_t BPL = { OPND_REG, 8, .as.reg = { REG_GP, 5 }};
214static const x86opnd_t SIL = { OPND_REG, 8, .as.reg = { REG_GP, 6 }};
215static const x86opnd_t DIL = { OPND_REG, 8, .as.reg = { REG_GP, 7 }};
216static const x86opnd_t R8B = { OPND_REG, 8, .as.reg = { REG_GP, 8 }};
217static const x86opnd_t R9B = { OPND_REG, 8, .as.reg = { REG_GP, 9 }};
218static const x86opnd_t R10B = { OPND_REG, 8, .as.reg = { REG_GP, 10 }};
219static const x86opnd_t R11B = { OPND_REG, 8, .as.reg = { REG_GP, 11 }};
220static const x86opnd_t R12B = { OPND_REG, 8, .as.reg = { REG_GP, 12 }};
221static const x86opnd_t R13B = { OPND_REG, 8, .as.reg = { REG_GP, 13 }};
222static const x86opnd_t R14B = { OPND_REG, 8, .as.reg = { REG_GP, 14 }};
223static const x86opnd_t R15B = { OPND_REG, 8, .as.reg = { REG_GP, 15 }};
226#define NUM_C_ARG_REGS 6
227#define C_ARG_REGS ( (x86opnd_t[]){ RDI, RSI, RDX, RCX, R8, R9 } )
230static inline uint32_t sig_imm_size(int64_t imm);
231static inline uint32_t unsig_imm_size(uint64_t imm);
240static inline x86opnd_t imm_opnd(int64_t val);
243static inline x86opnd_t const_ptr_opnd(
const void *ptr);
246#define member_opnd(base_reg, struct_type, member_name) mem_opnd( \
247 8 * sizeof(((struct_type*)0)->member_name), \
249 offsetof(struct_type, member_name) \
253#define member_opnd_idx(base_reg, struct_type, member_name, idx) mem_opnd( \
254 8 * sizeof(((struct_type*)0)->member_name[0]), \
256 (offsetof(struct_type, member_name) + \
257 sizeof(((struct_type*)0)->member_name[0]) * idx) \
261static uint8_t *alloc_exec_mem(uint32_t mem_size);
264static inline void cb_init(
codeblock_t *cb, uint8_t *mem_block, uint32_t mem_size);
265static inline void cb_align_pos(
codeblock_t *cb, uint32_t multiple);
266static inline void cb_set_pos(
codeblock_t *cb, uint32_t pos);
267static inline void cb_set_write_ptr(
codeblock_t *cb, uint8_t *code_ptr);
268static inline uint8_t *cb_get_ptr(
const codeblock_t *cb, uint32_t index);
269static inline uint8_t *cb_get_write_ptr(
const codeblock_t *cb);
270static inline void cb_write_byte(
codeblock_t *cb, uint8_t
byte);
271static inline void cb_write_bytes(
codeblock_t *cb, uint32_t num_bytes, ...);
272static inline void cb_write_int(
codeblock_t *cb, uint64_t val, uint32_t num_bits);
273static inline uint32_t cb_new_label(
codeblock_t *cb,
const char *name);
274static inline void cb_write_label(
codeblock_t *cb, uint32_t label_idx);
275static inline void cb_label_ref(
codeblock_t *cb, uint32_t label_idx);
277static inline void cb_mark_all_writeable(
codeblock_t *cb);
278static inline void cb_mark_position_writeable(
codeblock_t *cb, uint32_t write_pos);
279static inline void cb_mark_all_executable(
codeblock_t *cb);
285static inline void call_label(
codeblock_t *cb, uint32_t label_idx);
321static inline void ja_label(
codeblock_t *cb, uint32_t label_idx);
322static inline void jae_label(
codeblock_t *cb, uint32_t label_idx);
323static inline void jb_label(
codeblock_t *cb, uint32_t label_idx);
324static inline void jbe_label(
codeblock_t *cb, uint32_t label_idx);
325static inline void jc_label(
codeblock_t *cb, uint32_t label_idx);
326static inline void je_label(
codeblock_t *cb, uint32_t label_idx);
327static inline void jg_label(
codeblock_t *cb, uint32_t label_idx);
328static inline void jge_label(
codeblock_t *cb, uint32_t label_idx);
329static inline void jl_label(
codeblock_t *cb, uint32_t label_idx);
330static inline void jle_label(
codeblock_t *cb, uint32_t label_idx);
331static inline void jna_label(
codeblock_t *cb, uint32_t label_idx);
332static inline void jnae_label(
codeblock_t *cb, uint32_t label_idx);
333static inline void jnb_label(
codeblock_t *cb, uint32_t label_idx);
334static inline void jnbe_label(
codeblock_t *cb, uint32_t label_idx);
335static inline void jnc_label(
codeblock_t *cb, uint32_t label_idx);
336static inline void jne_label(
codeblock_t *cb, uint32_t label_idx);
337static inline void jng_label(
codeblock_t *cb, uint32_t label_idx);
338static inline void jnge_label(
codeblock_t *cb, uint32_t label_idx);
339static inline void jnl_label(
codeblock_t *cb, uint32_t label_idx);
340static inline void jnle_label(
codeblock_t *cb, uint32_t label_idx);
341static inline void jno_label(
codeblock_t *cb, uint32_t label_idx);
342static inline void jnp_label(
codeblock_t *cb, uint32_t label_idx);
343static inline void jns_label(
codeblock_t *cb, uint32_t label_idx);
344static inline void jnz_label(
codeblock_t *cb, uint32_t label_idx);
345static inline void jo_label(
codeblock_t *cb, uint32_t label_idx);
346static inline void jp_label(
codeblock_t *cb, uint32_t label_idx);
347static inline void jpe_label(
codeblock_t *cb, uint32_t label_idx);
348static inline void jpo_label(
codeblock_t *cb, uint32_t label_idx);
349static inline void js_label(
codeblock_t *cb, uint32_t label_idx);
350static inline void jz_label(
codeblock_t *cb, uint32_t label_idx);
351static inline void ja_ptr(
codeblock_t *cb, uint8_t *ptr);
352static inline void jae_ptr(
codeblock_t *cb, uint8_t *ptr);
353static inline void jb_ptr(
codeblock_t *cb, uint8_t *ptr);
354static inline void jbe_ptr(
codeblock_t *cb, uint8_t *ptr);
355static inline void jc_ptr(
codeblock_t *cb, uint8_t *ptr);
356static inline void je_ptr(
codeblock_t *cb, uint8_t *ptr);
357static inline void jg_ptr(
codeblock_t *cb, uint8_t *ptr);
358static inline void jge_ptr(
codeblock_t *cb, uint8_t *ptr);
359static inline void jl_ptr(
codeblock_t *cb, uint8_t *ptr);
360static inline void jle_ptr(
codeblock_t *cb, uint8_t *ptr);
361static inline void jna_ptr(
codeblock_t *cb, uint8_t *ptr);
362static inline void jnae_ptr(
codeblock_t *cb, uint8_t *ptr);
363static inline void jnb_ptr(
codeblock_t *cb, uint8_t *ptr);
364static inline void jnbe_ptr(
codeblock_t *cb, uint8_t *ptr);
365static inline void jnc_ptr(
codeblock_t *cb, uint8_t *ptr);
366static inline void jne_ptr(
codeblock_t *cb, uint8_t *ptr);
367static inline void jng_ptr(
codeblock_t *cb, uint8_t *ptr);
368static inline void jnge_ptr(
codeblock_t *cb, uint8_t *ptr);
369static inline void jnl_ptr(
codeblock_t *cb, uint8_t *ptr);
370static inline void jnle_ptr(
codeblock_t *cb, uint8_t *ptr);
371static inline void jno_ptr(
codeblock_t *cb, uint8_t *ptr);
372static inline void jnp_ptr(
codeblock_t *cb, uint8_t *ptr);
373static inline void jns_ptr(
codeblock_t *cb, uint8_t *ptr);
374static inline void jnz_ptr(
codeblock_t *cb, uint8_t *ptr);
375static inline void jo_ptr(
codeblock_t *cb, uint8_t *ptr);
376static inline void jp_ptr(
codeblock_t *cb, uint8_t *ptr);
377static inline void jpe_ptr(
codeblock_t *cb, uint8_t *ptr);
378static inline void jpo_ptr(
codeblock_t *cb, uint8_t *ptr);
379static inline void js_ptr(
codeblock_t *cb, uint8_t *ptr);
380static inline void jz_ptr(
codeblock_t *cb, uint8_t *ptr);
381static inline void jmp_label(
codeblock_t *cb, uint32_t label_idx);
382static inline void jmp_ptr(
codeblock_t *cb, uint8_t *ptr);
384static inline void jmp32(
codeblock_t *cb, int32_t offset);
389static inline void nop(
codeblock_t *cb, uint32_t length);
406static inline void cb_write_lock_prefix(
codeblock_t *cb);
uint8_t base_reg_no
Base register number.
bool has_idx
Has index register flag.
bool is_iprel
IP-relative addressing flag.
uint8_t scale_exp
SIB scale exponent value (power of two, two bits)
int32_t disp
Constant displacement from the base, not scaled.
uint8_t idx_reg_no
Index register number.