8 // Maximum number of labels to link
11 // Maximum number of label references
12 #define MAX_LABEL_REFS 32
14 // Reference to an ASM label
15 typedef struct LabelRef
17 // Position in the code block where the label reference exists
20 // Label which this refers to
25 // Block of executable memory into which instructions can be written
26 typedef struct CodeBlock
29 // Users are advised to not use this directly.
35 // Current writing position
38 // Table of registered label addresses
39 uint32_t label_addrs
[MAX_LABELS
];
41 // Table of registered label names
42 // Note that these should be constant strings only
43 const char *label_names
[MAX_LABELS
];
45 // References to labels
46 labelref_t label_refs
[MAX_LABEL_REFS
];
48 // Number of labels registeered
51 // Number of references to labels
55 // Keep track of the current aligned write position.
56 // Used for changing protection when writing to the JIT buffer
57 uint32_t current_aligned_write_pos
;
59 // Set if the assembler is unable to output some instructions,
60 // for example, when there is not enough space or when a jump
61 // target is too far away.
64 // Flag to enable or disable comments
70 // 1 is not aligned so this won't match any pages
71 #define ALIGNED_WRITE_POSITION_NONE 1
94 // Register index number
101 /// Base register number
104 /// Index register number
107 /// SIB scale exponent value (power of two, two bits)
110 /// Has index register flag
113 // TODO: should this be here, or should we have an extra operand type?
114 /// IP-relative addressing flag
117 /// Constant displacement from the base, not scaled
122 typedef struct X86Opnd
138 // Signed immediate value
141 // Unsigned immediate value
147 // Dummy none/null operand
148 static const x86opnd_t NO_OPND
= { OPND_NONE
, 0, .as
.imm
= 0 };
150 // Instruction pointer
151 static const x86opnd_t RIP
= { OPND_REG
, 64, .as
.reg
= { REG_IP
, 5 }};
153 // 64-bit GP registers
154 static const x86opnd_t RAX
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 0 }};
155 static const x86opnd_t RCX
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 1 }};
156 static const x86opnd_t RDX
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 2 }};
157 static const x86opnd_t RBX
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 3 }};
158 static const x86opnd_t RSP
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 4 }};
159 static const x86opnd_t RBP
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 5 }};
160 static const x86opnd_t RSI
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 6 }};
161 static const x86opnd_t RDI
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 7 }};
162 static const x86opnd_t R8
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 8 }};
163 static const x86opnd_t R9
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 9 }};
164 static const x86opnd_t R10
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 10 }};
165 static const x86opnd_t R11
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 11 }};
166 static const x86opnd_t R12
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 12 }};
167 static const x86opnd_t R13
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 13 }};
168 static const x86opnd_t R14
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 14 }};
169 static const x86opnd_t R15
= { OPND_REG
, 64, .as
.reg
= { REG_GP
, 15 }};
171 // 32-bit GP registers
172 static const x86opnd_t EAX
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 0 }};
173 static const x86opnd_t ECX
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 1 }};
174 static const x86opnd_t EDX
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 2 }};
175 static const x86opnd_t EBX
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 3 }};
176 static const x86opnd_t ESP
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 4 }};
177 static const x86opnd_t EBP
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 5 }};
178 static const x86opnd_t ESI
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 6 }};
179 static const x86opnd_t EDI
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 7 }};
180 static const x86opnd_t R8D
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 8 }};
181 static const x86opnd_t R9D
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 9 }};
182 static const x86opnd_t R10D
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 10 }};
183 static const x86opnd_t R11D
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 11 }};
184 static const x86opnd_t R12D
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 12 }};
185 static const x86opnd_t R13D
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 13 }};
186 static const x86opnd_t R14D
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 14 }};
187 static const x86opnd_t R15D
= { OPND_REG
, 32, .as
.reg
= { REG_GP
, 15 }};
189 // 16-bit GP registers
190 static const x86opnd_t AX
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 0 }};
191 static const x86opnd_t CX
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 1 }};
192 static const x86opnd_t DX
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 2 }};
193 static const x86opnd_t BX
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 3 }};
194 static const x86opnd_t SP
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 4 }};
195 static const x86opnd_t BP
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 5 }};
196 static const x86opnd_t SI
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 6 }};
197 static const x86opnd_t DI
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 7 }};
198 static const x86opnd_t R8W
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 8 }};
199 static const x86opnd_t R9W
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 9 }};
200 static const x86opnd_t R10W
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 10 }};
201 static const x86opnd_t R11W
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 11 }};
202 static const x86opnd_t R12W
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 12 }};
203 static const x86opnd_t R13W
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 13 }};
204 static const x86opnd_t R14W
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 14 }};
205 static const x86opnd_t R15W
= { OPND_REG
, 16, .as
.reg
= { REG_GP
, 15 }};
207 // 8-bit GP registers
208 static const x86opnd_t AL
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 0 }};
209 static const x86opnd_t CL
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 1 }};
210 static const x86opnd_t DL
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 2 }};
211 static const x86opnd_t BL
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 3 }};
212 static const x86opnd_t SPL
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 4 }};
213 static const x86opnd_t BPL
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 5 }};
214 static const x86opnd_t SIL
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 6 }};
215 static const x86opnd_t DIL
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 7 }};
216 static const x86opnd_t R8B
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 8 }};
217 static const x86opnd_t R9B
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 9 }};
218 static const x86opnd_t R10B
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 10 }};
219 static const x86opnd_t R11B
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 11 }};
220 static const x86opnd_t R12B
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 12 }};
221 static const x86opnd_t R13B
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 13 }};
222 static const x86opnd_t R14B
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 14 }};
223 static const x86opnd_t R15B
= { OPND_REG
, 8, .as
.reg
= { REG_GP
, 15 }};
225 // C argument registers
226 #define NUM_C_ARG_REGS 6
227 #define C_ARG_REGS ( (x86opnd_t[]){ RDI, RSI, RDX, RCX, R8, R9 } )
229 // Compute the number of bits needed to store a signed or unsigned value
230 static inline uint32_t sig_imm_size(int64_t imm
);
231 static inline uint32_t unsig_imm_size(uint64_t imm
);
233 // Memory operand with base register and displacement/offset
234 static inline x86opnd_t
mem_opnd(uint32_t num_bits
, x86opnd_t base_reg
, int32_t disp
);
236 // Scale-index-base memory operand
237 static inline x86opnd_t
mem_opnd_sib(uint32_t num_bits
, x86opnd_t base_reg
, x86opnd_t index_reg
, int32_t scale
, int32_t disp
);
239 // Immediate number operand
240 static inline x86opnd_t
imm_opnd(int64_t val
);
242 // Constant pointer operand
243 static inline x86opnd_t
const_ptr_opnd(const void *ptr
);
245 // Struct member operand
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) \
252 // Struct member operand with an array index
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) \
260 // Allocate executable memory
261 static uint8_t *alloc_exec_mem(uint32_t mem_size
);
263 // Code block functions
264 static inline void cb_init(codeblock_t
*cb
, uint8_t *mem_block
, uint32_t mem_size
);
265 static inline void cb_align_pos(codeblock_t
*cb
, uint32_t multiple
);
266 static inline void cb_set_pos(codeblock_t
*cb
, uint32_t pos
);
267 static inline void cb_set_write_ptr(codeblock_t
*cb
, uint8_t *code_ptr
);
268 static inline uint8_t *cb_get_ptr(const codeblock_t
*cb
, uint32_t index
);
269 static inline uint8_t *cb_get_write_ptr(const codeblock_t
*cb
);
270 static inline void cb_write_byte(codeblock_t
*cb
, uint8_t byte
);
271 static inline void cb_write_bytes(codeblock_t
*cb
, uint32_t num_bytes
, ...);
272 static inline void cb_write_int(codeblock_t
*cb
, uint64_t val
, uint32_t num_bits
);
273 static inline uint32_t cb_new_label(codeblock_t
*cb
, const char *name
);
274 static inline void cb_write_label(codeblock_t
*cb
, uint32_t label_idx
);
275 static inline void cb_label_ref(codeblock_t
*cb
, uint32_t label_idx
);
276 static inline void cb_link_labels(codeblock_t
*cb
);
277 static inline void cb_mark_all_writeable(codeblock_t
*cb
);
278 static inline void cb_mark_position_writeable(codeblock_t
*cb
, uint32_t write_pos
);
279 static inline void cb_mark_all_executable(codeblock_t
*cb
);
281 // Encode individual instructions into a code block
282 static inline void add(codeblock_t
*cb
, x86opnd_t opnd0
, x86opnd_t opnd1
);
283 static inline void and(codeblock_t
*cb
, x86opnd_t opnd0
, x86opnd_t opnd1
);
284 static inline void call_ptr(codeblock_t
*cb
, x86opnd_t scratch_reg
, uint8_t *dst_ptr
);
285 static inline void call_label(codeblock_t
*cb
, uint32_t label_idx
);
286 static inline void call(codeblock_t
*cb
, x86opnd_t opnd
);
287 static inline void cmova(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
288 static inline void cmovae(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
289 static inline void cmovb(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
290 static inline void cmovbe(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
291 static inline void cmovc(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
292 static inline void cmove(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
293 static inline void cmovg(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
294 static inline void cmovge(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
295 static inline void cmovl(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
296 static inline void cmovle(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
297 static inline void cmovna(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
298 static inline void cmovnae(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
299 static inline void cmovnb(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
300 static inline void cmovnbe(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
301 static inline void cmovnc(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
302 static inline void cmovne(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
303 static inline void cmovng(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
304 static inline void cmovnge(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
305 static inline void cmovnl(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
306 static inline void cmovnle(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
307 static inline void cmovno(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
308 static inline void cmovnp(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
309 static inline void cmovns(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
310 static inline void cmovnz(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
311 static inline void cmovo(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
312 static inline void cmovp(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
313 static inline void cmovpe(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
314 static inline void cmovpo(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
315 static inline void cmovs(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
316 static inline void cmovz(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
317 static inline void cmp(codeblock_t
*cb
, x86opnd_t opnd0
, x86opnd_t opnd1
);
318 static inline void cdq(codeblock_t
*cb
);
319 static inline void cqo(codeblock_t
*cb
);
320 static inline void int3(codeblock_t
*cb
);
321 static inline void ja_label(codeblock_t
*cb
, uint32_t label_idx
);
322 static inline void jae_label(codeblock_t
*cb
, uint32_t label_idx
);
323 static inline void jb_label(codeblock_t
*cb
, uint32_t label_idx
);
324 static inline void jbe_label(codeblock_t
*cb
, uint32_t label_idx
);
325 static inline void jc_label(codeblock_t
*cb
, uint32_t label_idx
);
326 static inline void je_label(codeblock_t
*cb
, uint32_t label_idx
);
327 static inline void jg_label(codeblock_t
*cb
, uint32_t label_idx
);
328 static inline void jge_label(codeblock_t
*cb
, uint32_t label_idx
);
329 static inline void jl_label(codeblock_t
*cb
, uint32_t label_idx
);
330 static inline void jle_label(codeblock_t
*cb
, uint32_t label_idx
);
331 static inline void jna_label(codeblock_t
*cb
, uint32_t label_idx
);
332 static inline void jnae_label(codeblock_t
*cb
, uint32_t label_idx
);
333 static inline void jnb_label(codeblock_t
*cb
, uint32_t label_idx
);
334 static inline void jnbe_label(codeblock_t
*cb
, uint32_t label_idx
);
335 static inline void jnc_label(codeblock_t
*cb
, uint32_t label_idx
);
336 static inline void jne_label(codeblock_t
*cb
, uint32_t label_idx
);
337 static inline void jng_label(codeblock_t
*cb
, uint32_t label_idx
);
338 static inline void jnge_label(codeblock_t
*cb
, uint32_t label_idx
);
339 static inline void jnl_label(codeblock_t
*cb
, uint32_t label_idx
);
340 static inline void jnle_label(codeblock_t
*cb
, uint32_t label_idx
);
341 static inline void jno_label(codeblock_t
*cb
, uint32_t label_idx
);
342 static inline void jnp_label(codeblock_t
*cb
, uint32_t label_idx
);
343 static inline void jns_label(codeblock_t
*cb
, uint32_t label_idx
);
344 static inline void jnz_label(codeblock_t
*cb
, uint32_t label_idx
);
345 static inline void jo_label(codeblock_t
*cb
, uint32_t label_idx
);
346 static inline void jp_label(codeblock_t
*cb
, uint32_t label_idx
);
347 static inline void jpe_label(codeblock_t
*cb
, uint32_t label_idx
);
348 static inline void jpo_label(codeblock_t
*cb
, uint32_t label_idx
);
349 static inline void js_label(codeblock_t
*cb
, uint32_t label_idx
);
350 static inline void jz_label(codeblock_t
*cb
, uint32_t label_idx
);
351 static inline void ja_ptr(codeblock_t
*cb
, uint8_t *ptr
);
352 static inline void jae_ptr(codeblock_t
*cb
, uint8_t *ptr
);
353 static inline void jb_ptr(codeblock_t
*cb
, uint8_t *ptr
);
354 static inline void jbe_ptr(codeblock_t
*cb
, uint8_t *ptr
);
355 static inline void jc_ptr(codeblock_t
*cb
, uint8_t *ptr
);
356 static inline void je_ptr(codeblock_t
*cb
, uint8_t *ptr
);
357 static inline void jg_ptr(codeblock_t
*cb
, uint8_t *ptr
);
358 static inline void jge_ptr(codeblock_t
*cb
, uint8_t *ptr
);
359 static inline void jl_ptr(codeblock_t
*cb
, uint8_t *ptr
);
360 static inline void jle_ptr(codeblock_t
*cb
, uint8_t *ptr
);
361 static inline void jna_ptr(codeblock_t
*cb
, uint8_t *ptr
);
362 static inline void jnae_ptr(codeblock_t
*cb
, uint8_t *ptr
);
363 static inline void jnb_ptr(codeblock_t
*cb
, uint8_t *ptr
);
364 static inline void jnbe_ptr(codeblock_t
*cb
, uint8_t *ptr
);
365 static inline void jnc_ptr(codeblock_t
*cb
, uint8_t *ptr
);
366 static inline void jne_ptr(codeblock_t
*cb
, uint8_t *ptr
);
367 static inline void jng_ptr(codeblock_t
*cb
, uint8_t *ptr
);
368 static inline void jnge_ptr(codeblock_t
*cb
, uint8_t *ptr
);
369 static inline void jnl_ptr(codeblock_t
*cb
, uint8_t *ptr
);
370 static inline void jnle_ptr(codeblock_t
*cb
, uint8_t *ptr
);
371 static inline void jno_ptr(codeblock_t
*cb
, uint8_t *ptr
);
372 static inline void jnp_ptr(codeblock_t
*cb
, uint8_t *ptr
);
373 static inline void jns_ptr(codeblock_t
*cb
, uint8_t *ptr
);
374 static inline void jnz_ptr(codeblock_t
*cb
, uint8_t *ptr
);
375 static inline void jo_ptr(codeblock_t
*cb
, uint8_t *ptr
);
376 static inline void jp_ptr(codeblock_t
*cb
, uint8_t *ptr
);
377 static inline void jpe_ptr(codeblock_t
*cb
, uint8_t *ptr
);
378 static inline void jpo_ptr(codeblock_t
*cb
, uint8_t *ptr
);
379 static inline void js_ptr(codeblock_t
*cb
, uint8_t *ptr
);
380 static inline void jz_ptr(codeblock_t
*cb
, uint8_t *ptr
);
381 static inline void jmp_label(codeblock_t
*cb
, uint32_t label_idx
);
382 static inline void jmp_ptr(codeblock_t
*cb
, uint8_t *ptr
);
383 static inline void jmp_rm(codeblock_t
*cb
, x86opnd_t opnd
);
384 static inline void jmp32(codeblock_t
*cb
, int32_t offset
);
385 static inline void lea(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
386 static inline void mov(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
387 static inline void movsx(codeblock_t
*cb
, x86opnd_t dst
, x86opnd_t src
);
388 static inline void neg(codeblock_t
*cb
, x86opnd_t opnd
);
389 static inline void nop(codeblock_t
*cb
, uint32_t length
);
390 static inline void not(codeblock_t
*cb
, x86opnd_t opnd
);
391 static inline void or(codeblock_t
*cb
, x86opnd_t opnd0
, x86opnd_t opnd1
);
392 static inline void pop(codeblock_t
*cb
, x86opnd_t reg
);
393 static inline void popfq(codeblock_t
*cb
);
394 static inline void push(codeblock_t
*cb
, x86opnd_t opnd
);
395 static inline void pushfq(codeblock_t
*cb
);
396 static inline void ret(codeblock_t
*cb
);
397 static inline void sal(codeblock_t
*cb
, x86opnd_t opnd0
, x86opnd_t opnd1
);
398 static inline void sar(codeblock_t
*cb
, x86opnd_t opnd0
, x86opnd_t opnd1
);
399 static inline void shl(codeblock_t
*cb
, x86opnd_t opnd0
, x86opnd_t opnd1
);
400 static inline void shr(codeblock_t
*cb
, x86opnd_t opnd0
, x86opnd_t opnd1
);
401 static inline void sub(codeblock_t
*cb
, x86opnd_t opnd0
, x86opnd_t opnd1
);
402 static inline void test(codeblock_t
*cb
, x86opnd_t rm_opnd
, x86opnd_t test_opnd
);
403 static inline void ud2(codeblock_t
*cb
);
404 static inline void xchg(codeblock_t
*cb
, x86opnd_t rm_opnd
, x86opnd_t r_opnd
);
405 static inline void xor(codeblock_t
*cb
, x86opnd_t opnd0
, x86opnd_t opnd1
);
406 static inline void cb_write_lock_prefix(codeblock_t
*cb
);