451ab91e |
1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus - assemble.c * |
3 | * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * |
4 | * Copyright (C) 2007 Richard Goedeken (Richard42) * |
5 | * Copyright (C) 2002 Hacktarux * |
6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * |
9 | * the Free Software Foundation; either version 2 of the License, or * |
10 | * (at your option) any later version. * |
11 | * * |
12 | * This program is distributed in the hope that it will be useful, * |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
15 | * GNU General Public License for more details. * |
16 | * * |
17 | * You should have received a copy of the GNU General Public License * |
18 | * along with this program; if not, write to the * |
19 | * Free Software Foundation, Inc., * |
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
21 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
22 | |
23 | #ifndef __ASSEMBLE_H__ |
24 | #define __ASSEMBLE_H__ |
25 | |
26 | #include "r4300/recomph.h" |
27 | #include "api/callbacks.h" |
28 | |
29 | #include <stdlib.h> |
30 | |
31 | extern long long int reg[32]; |
32 | |
33 | #define RAX 0 |
34 | #define RCX 1 |
35 | #define RDX 2 |
36 | #define RBX 3 |
37 | #define RSP 4 |
38 | #define RBP 5 |
39 | #define RSI 6 |
40 | #define RDI 7 |
41 | |
42 | #define EAX 0 |
43 | #define ECX 1 |
44 | #define EDX 2 |
45 | #define EBX 3 |
46 | #define ESP 4 |
47 | #define EBP 5 |
48 | #define ESI 6 |
49 | #define EDI 7 |
50 | |
51 | #define AX 0 |
52 | #define CX 1 |
53 | #define DX 2 |
54 | #define BX 3 |
55 | #define SP 4 |
56 | #define BP 5 |
57 | #define SI 6 |
58 | #define DI 7 |
59 | |
60 | #define AL 0 |
61 | #define CL 1 |
62 | #define DL 2 |
63 | #define BL 3 |
64 | #define AH 4 |
65 | #define CH 5 |
66 | #define DH 6 |
67 | #define BH 7 |
68 | |
69 | extern int branch_taken; |
70 | |
71 | void jump_start_rel8(void); |
72 | void jump_end_rel8(void); |
73 | void jump_start_rel32(void); |
74 | void jump_end_rel32(void); |
75 | void add_jump(unsigned int pc_addr, unsigned int mi_addr, unsigned int absolute64); |
76 | |
77 | static inline void put8(unsigned char octet) |
78 | { |
79 | (*inst_pointer)[code_length] = octet; |
80 | code_length++; |
81 | if (code_length == max_code_length) |
82 | { |
83 | *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); |
84 | max_code_length += 8192; |
85 | } |
86 | } |
87 | |
88 | static inline void put32(unsigned int dword) |
89 | { |
90 | if ((code_length + 4) >= max_code_length) |
91 | { |
92 | *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); |
93 | max_code_length += 8192; |
94 | } |
95 | *((unsigned int *) (*inst_pointer + code_length)) = dword; |
96 | code_length += 4; |
97 | } |
98 | |
99 | static inline void put64(unsigned long long qword) |
100 | { |
101 | if ((code_length + 8) >= max_code_length) |
102 | { |
103 | *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); |
104 | max_code_length += 8192; |
105 | } |
106 | *((unsigned long long *) (*inst_pointer + code_length)) = qword; |
107 | code_length += 8; |
108 | } |
109 | |
110 | static inline int rel_r15_offset(void *dest, const char *op_name) |
111 | { |
112 | /* calculate the destination pointer's offset from the base of the r4300 registers */ |
113 | long long rel_offset = (long long) ((unsigned char *) dest - (unsigned char *) reg); |
114 | |
115 | if (llabs(rel_offset) > 0x7fffffff) |
116 | { |
117 | DebugMessage(M64MSG_ERROR, "Error: destination %p more than 2GB away from r15 base %p in %s()", dest, reg, op_name); |
118 | asm(" int $3; "); |
119 | } |
120 | |
121 | return (int) rel_offset; |
122 | } |
123 | |
124 | static inline void mov_memoffs32_eax(unsigned int *memoffs32) |
125 | { |
126 | put8(0xA3); |
127 | put64((unsigned long long) memoffs32); |
128 | } |
129 | |
130 | static inline void mov_rax_memoffs64(unsigned long long *memoffs64) |
131 | { |
132 | put8(0x48); |
133 | put8(0xA1); |
134 | put64((unsigned long long) memoffs64); |
135 | } |
136 | |
137 | static inline void mov_memoffs64_rax(unsigned long long *memoffs64) |
138 | { |
139 | put8(0x48); |
140 | put8(0xA3); |
141 | put64((unsigned long long) memoffs64); |
142 | } |
143 | |
144 | static inline void mov_m8rel_xreg8(unsigned char *m8, int xreg8) |
145 | { |
146 | int offset = rel_r15_offset(m8, "mov_m8rel_xreg8"); |
147 | |
148 | put8(0x41 | ((xreg8 & 8) >> 1)); |
149 | put8(0x88); |
150 | put8(0x87 | ((xreg8 & 7) << 3)); |
151 | put32(offset); |
152 | } |
153 | |
154 | static inline void mov_xreg16_m16rel(int xreg16, unsigned short *m16) |
155 | { |
156 | int offset = rel_r15_offset(m16, "mov_xreg16_m16rel"); |
157 | |
158 | put8(0x66); |
159 | put8(0x41 | ((xreg16 & 8) >> 1)); |
160 | put8(0x8B); |
161 | put8(0x87 | ((xreg16 & 7) << 3)); |
162 | put32(offset); |
163 | } |
164 | |
165 | static inline void mov_m16rel_xreg16(unsigned short *m16, int xreg16) |
166 | { |
167 | int offset = rel_r15_offset(m16, "mov_m16rel_xreg16"); |
168 | |
169 | put8(0x66); |
170 | put8(0x41 | ((xreg16 & 8) >> 1)); |
171 | put8(0x89); |
172 | put8(0x87 | ((xreg16 & 7) << 3)); |
173 | put32(offset); |
174 | } |
175 | |
176 | static inline void cmp_xreg32_m32rel(int xreg32, unsigned int *m32) |
177 | { |
178 | int offset = rel_r15_offset(m32, "cmp_xreg32_m32rel"); |
179 | |
180 | put8(0x41 | ((xreg32 & 8) >> 1)); |
181 | put8(0x3B); |
182 | put8(0x87 | ((xreg32 & 7) << 3)); |
183 | put32(offset); |
184 | } |
185 | |
186 | static inline void cmp_xreg64_m64rel(int xreg64, unsigned long long *m64) |
187 | { |
188 | int offset = rel_r15_offset(m64, "cmp_xreg64_m64rel"); |
189 | |
190 | put8(0x49 | ((xreg64 & 8) >> 1)); |
191 | put8(0x3B); |
192 | put8(0x87 | ((xreg64 & 7) << 3)); |
193 | put32(offset); |
194 | } |
195 | |
196 | static inline void cmp_reg32_reg32(int reg1, int reg2) |
197 | { |
198 | put8(0x39); |
199 | put8((reg2 << 3) | reg1 | 0xC0); |
200 | } |
201 | |
202 | static inline void cmp_reg64_reg64(int reg1, int reg2) |
203 | { |
204 | put8(0x48); |
205 | put8(0x39); |
206 | put8((reg2 << 3) | reg1 | 0xC0); |
207 | } |
208 | |
209 | static inline void cmp_reg32_imm8(int reg32, unsigned char imm8) |
210 | { |
211 | put8(0x83); |
212 | put8(0xF8 + reg32); |
213 | put8(imm8); |
214 | } |
215 | |
216 | static inline void cmp_reg64_imm8(int reg64, unsigned char imm8) |
217 | { |
218 | put8(0x48); |
219 | put8(0x83); |
220 | put8(0xF8 + reg64); |
221 | put8(imm8); |
222 | } |
223 | |
224 | static inline void cmp_reg32_imm32(int reg32, unsigned int imm32) |
225 | { |
226 | put8(0x81); |
227 | put8(0xF8 + reg32); |
228 | put32(imm32); |
229 | } |
230 | |
231 | static inline void cmp_reg64_imm32(int reg64, unsigned int imm32) |
232 | { |
233 | put8(0x48); |
234 | put8(0x81); |
235 | put8(0xF8 + reg64); |
236 | put32(imm32); |
237 | } |
238 | |
239 | static inline void cmp_preg64preg64_imm8(int reg1, int reg2, unsigned char imm8) |
240 | { |
241 | put8(0x80); |
242 | put8(0x3C); |
243 | put8((reg1 << 3) | reg2); |
244 | put8(imm8); |
245 | } |
246 | |
247 | static inline void sete_m8rel(unsigned char *m8) |
248 | { |
249 | int offset = rel_r15_offset(m8, "sete_m8rel"); |
250 | |
251 | put8(0x41); |
252 | put8(0x0F); |
253 | put8(0x94); |
254 | put8(0x87); |
255 | put32(offset); |
256 | } |
257 | |
258 | static inline void setne_m8rel(unsigned char *m8) |
259 | { |
260 | int offset = rel_r15_offset(m8, "setne_m8rel"); |
261 | |
262 | put8(0x41); |
263 | put8(0x0F); |
264 | put8(0x95); |
265 | put8(0x87); |
266 | put32(offset); |
267 | } |
268 | |
269 | static inline void setl_m8rel(unsigned char *m8) |
270 | { |
271 | int offset = rel_r15_offset(m8, "setl_m8rel"); |
272 | |
273 | put8(0x41); |
274 | put8(0x0F); |
275 | put8(0x9C); |
276 | put8(0x87); |
277 | put32(offset); |
278 | } |
279 | |
280 | static inline void setle_m8rel(unsigned char *m8) |
281 | { |
282 | int offset = rel_r15_offset(m8, "setle_m8rel"); |
283 | |
284 | put8(0x41); |
285 | put8(0x0F); |
286 | put8(0x9E); |
287 | put8(0x87); |
288 | put32(offset); |
289 | } |
290 | |
291 | static inline void setg_m8rel(unsigned char *m8) |
292 | { |
293 | int offset = rel_r15_offset(m8, "setg_m8rel"); |
294 | |
295 | put8(0x41); |
296 | put8(0x0F); |
297 | put8(0x9F); |
298 | put8(0x87); |
299 | put32(offset); |
300 | } |
301 | |
302 | static inline void setge_m8rel(unsigned char *m8) |
303 | { |
304 | int offset = rel_r15_offset(m8, "setge_m8rel"); |
305 | |
306 | put8(0x41); |
307 | put8(0x0F); |
308 | put8(0x9D); |
309 | put8(0x87); |
310 | put32(offset); |
311 | } |
312 | |
313 | static inline void setl_reg8(unsigned int reg8) |
314 | { |
315 | put8(0x40); /* we need an REX prefix to use the uniform byte registers */ |
316 | put8(0x0F); |
317 | put8(0x9C); |
318 | put8(0xC0 | reg8); |
319 | } |
320 | |
321 | static inline void setb_reg8(unsigned int reg8) |
322 | { |
323 | put8(0x40); /* we need an REX prefix to use the uniform byte registers */ |
324 | put8(0x0F); |
325 | put8(0x92); |
326 | put8(0xC0 | reg8); |
327 | } |
328 | |
329 | static inline void test_m32rel_imm32(unsigned int *m32, unsigned int imm32) |
330 | { |
331 | int offset = rel_r15_offset(m32, "test_m32rel_imm32"); |
332 | |
333 | put8(0x41); |
334 | put8(0xF7); |
335 | put8(0x87); |
336 | put32(offset); |
337 | put32(imm32); |
338 | } |
339 | |
340 | static inline void add_m32rel_xreg32(unsigned int *m32, int xreg32) |
341 | { |
342 | int offset = rel_r15_offset(m32, "add_m32rel_xreg32"); |
343 | |
344 | put8(0x41 | ((xreg32 & 8) >> 1)); |
345 | put8(0x01); |
346 | put8(0x87 | ((xreg32 & 7) << 3)); |
347 | put32(offset); |
348 | } |
349 | |
350 | static inline void sub_xreg32_m32rel(int xreg32, unsigned int *m32) |
351 | { |
352 | int offset = rel_r15_offset(m32, "sub_xreg32_m32rel"); |
353 | |
354 | put8(0x41 | ((xreg32 & 8) >> 1)); |
355 | put8(0x2B); |
356 | put8(0x87 | ((xreg32 & 7) << 3)); |
357 | put32(offset); |
358 | } |
359 | |
360 | static inline void sub_reg32_reg32(int reg1, int reg2) |
361 | { |
362 | put8(0x29); |
363 | put8((reg2 << 3) | reg1 | 0xC0); |
364 | } |
365 | |
366 | static inline void sub_reg64_reg64(int reg1, int reg2) |
367 | { |
368 | put8(0x48); |
369 | put8(0x29); |
370 | put8((reg2 << 3) | reg1 | 0xC0); |
371 | } |
372 | |
373 | static inline void sub_reg64_imm32(int reg64, unsigned int imm32) |
374 | { |
375 | put8(0x48); |
376 | put8(0x81); |
377 | put8(0xE8 + reg64); |
378 | put32(imm32); |
379 | } |
380 | |
381 | static inline void sub_eax_imm32(unsigned int imm32) |
382 | { |
383 | put8(0x2D); |
384 | put32(imm32); |
385 | } |
386 | |
387 | static inline void jne_rj(unsigned char saut) |
388 | { |
389 | put8(0x75); |
390 | put8(saut); |
391 | } |
392 | |
393 | static inline void je_rj(unsigned char saut) |
394 | { |
395 | put8(0x74); |
396 | put8(saut); |
397 | } |
398 | |
399 | static inline void jbe_rj(unsigned char saut) |
400 | { |
401 | put8(0x76); |
402 | put8(saut); |
403 | } |
404 | |
405 | static inline void ja_rj(unsigned char saut) |
406 | { |
407 | put8(0x77); |
408 | put8(saut); |
409 | } |
410 | |
411 | static inline void jae_rj(unsigned char saut) |
412 | { |
413 | put8(0x73); |
414 | put8(saut); |
415 | } |
416 | |
417 | static inline void jp_rj(unsigned char saut) |
418 | { |
419 | put8(0x7A); |
420 | put8(saut); |
421 | } |
422 | |
423 | static inline void je_near_rj(unsigned int saut) |
424 | { |
425 | put8(0x0F); |
426 | put8(0x84); |
427 | put32(saut); |
428 | } |
429 | |
430 | static inline void mov_reg32_imm32(int reg32, unsigned int imm32) |
431 | { |
432 | put8(0xB8+reg32); |
433 | put32(imm32); |
434 | } |
435 | |
436 | static inline void mov_reg64_imm64(int reg64, unsigned long long imm64) |
437 | { |
438 | put8(0x48); |
439 | put8(0xB8+reg64); |
440 | put64(imm64); |
441 | } |
442 | |
443 | static inline void jmp_imm_short(char saut) |
444 | { |
445 | put8(0xEB); |
446 | put8(saut); |
447 | } |
448 | |
449 | static inline void or_m32rel_imm32(unsigned int *m32, unsigned int imm32) |
450 | { |
451 | int offset = rel_r15_offset(m32, "or_m32rel_imm32"); |
452 | |
453 | put8(0x41); |
454 | put8(0x81); |
455 | put8(0x8F); |
456 | put32(offset); |
457 | put32(imm32); |
458 | } |
459 | |
460 | static inline void or_reg64_reg64(unsigned int reg1, unsigned int reg2) |
461 | { |
462 | put8(0x48); |
463 | put8(0x09); |
464 | put8(0xC0 | (reg2 << 3) | reg1); |
465 | } |
466 | |
467 | static inline void and_reg64_reg64(unsigned int reg1, unsigned int reg2) |
468 | { |
469 | put8(0x48); |
470 | put8(0x21); |
471 | put8(0xC0 | (reg2 << 3) | reg1); |
472 | } |
473 | |
474 | static inline void and_m32rel_imm32(unsigned int *m32, unsigned int imm32) |
475 | { |
476 | int offset = rel_r15_offset(m32, "and_m32rel_imm32"); |
477 | |
478 | put8(0x41); |
479 | put8(0x81); |
480 | put8(0xA7); |
481 | put32(offset); |
482 | put32(imm32); |
483 | } |
484 | |
485 | static inline void xor_reg32_reg32(unsigned int reg1, unsigned int reg2) |
486 | { |
487 | put8(0x31); |
488 | put8(0xC0 | (reg2 << 3) | reg1); |
489 | } |
490 | |
491 | static inline void xor_reg64_reg64(unsigned int reg1, unsigned int reg2) |
492 | { |
493 | put8(0x48); |
494 | put8(0x31); |
495 | put8(0xC0 | (reg2 << 3) | reg1); |
496 | } |
497 | |
498 | static inline void add_reg64_imm32(unsigned int reg64, unsigned int imm32) |
499 | { |
500 | put8(0x48); |
501 | put8(0x81); |
502 | put8(0xC0+reg64); |
503 | put32(imm32); |
504 | } |
505 | |
506 | static inline void add_reg32_imm32(unsigned int reg32, unsigned int imm32) |
507 | { |
508 | put8(0x81); |
509 | put8(0xC0+reg32); |
510 | put32(imm32); |
511 | } |
512 | |
513 | static inline void inc_m32rel(unsigned int *m32) |
514 | { |
515 | int offset = rel_r15_offset(m32, "inc_m32rel"); |
516 | |
517 | put8(0x41); |
518 | put8(0xFF); |
519 | put8(0x87); |
520 | put32(offset); |
521 | } |
522 | |
523 | static inline void cmp_m32rel_imm32(unsigned int *m32, unsigned int imm32) |
524 | { |
525 | int offset = rel_r15_offset(m32, "cmp_m32rel_imm32"); |
526 | |
527 | put8(0x41); |
528 | put8(0x81); |
529 | put8(0xBF); |
530 | put32(offset); |
531 | put32(imm32); |
532 | } |
533 | |
534 | static inline void cmp_eax_imm32(unsigned int imm32) |
535 | { |
536 | put8(0x3D); |
537 | put32(imm32); |
538 | } |
539 | |
540 | static inline void mov_m32rel_imm32(unsigned int *m32, unsigned int imm32) |
541 | { |
542 | int offset = rel_r15_offset(m32, "mov_m32rel_imm32"); |
543 | |
544 | put8(0x41); |
545 | put8(0xC7); |
546 | put8(0x87); |
547 | put32(offset); |
548 | put32(imm32); |
549 | } |
550 | |
551 | static inline void jmp(unsigned int mi_addr) |
552 | { |
553 | put8(0xFF); |
554 | put8(0x25); |
555 | put32(0); |
556 | put64(0); |
557 | add_jump(code_length-8, mi_addr, 1); |
558 | } |
559 | |
560 | static inline void cdq(void) |
561 | { |
562 | put8(0x99); |
563 | } |
564 | |
565 | static inline void call_reg64(unsigned int reg64) |
566 | { |
567 | put8(0xFF); |
568 | put8(0xD0+reg64); |
569 | } |
570 | |
571 | static inline void shr_reg64_imm8(unsigned int reg64, unsigned char imm8) |
572 | { |
573 | put8(0x48); |
574 | put8(0xC1); |
575 | put8(0xE8+reg64); |
576 | put8(imm8); |
577 | } |
578 | |
579 | static inline void shr_reg32_imm8(unsigned int reg32, unsigned char imm8) |
580 | { |
581 | put8(0xC1); |
582 | put8(0xE8+reg32); |
583 | put8(imm8); |
584 | } |
585 | |
586 | static inline void shr_reg32_cl(unsigned int reg32) |
587 | { |
588 | put8(0xD3); |
589 | put8(0xE8+reg32); |
590 | } |
591 | |
592 | static inline void shr_reg64_cl(unsigned int reg64) |
593 | { |
594 | put8(0x48); |
595 | put8(0xD3); |
596 | put8(0xE8+reg64); |
597 | } |
598 | |
599 | static inline void sar_reg32_cl(unsigned int reg32) |
600 | { |
601 | put8(0xD3); |
602 | put8(0xF8+reg32); |
603 | } |
604 | |
605 | static inline void sar_reg64_cl(unsigned int reg64) |
606 | { |
607 | put8(0x48); |
608 | put8(0xD3); |
609 | put8(0xF8+reg64); |
610 | } |
611 | |
612 | static inline void shl_reg32_cl(unsigned int reg32) |
613 | { |
614 | put8(0xD3); |
615 | put8(0xE0+reg32); |
616 | } |
617 | |
618 | static inline void shl_reg64_cl(unsigned int reg64) |
619 | { |
620 | put8(0x48); |
621 | put8(0xD3); |
622 | put8(0xE0+reg64); |
623 | } |
624 | |
625 | static inline void sar_reg32_imm8(unsigned int reg32, unsigned char imm8) |
626 | { |
627 | put8(0xC1); |
628 | put8(0xF8+reg32); |
629 | put8(imm8); |
630 | } |
631 | |
632 | static inline void sar_reg64_imm8(unsigned int reg64, unsigned char imm8) |
633 | { |
634 | put8(0x48); |
635 | put8(0xC1); |
636 | put8(0xF8+reg64); |
637 | put8(imm8); |
638 | } |
639 | |
640 | static inline void mul_m32rel(unsigned int *m32) |
641 | { |
642 | int offset = rel_r15_offset(m32, "mul_m32rel"); |
643 | |
644 | put8(0x41); |
645 | put8(0xF7); |
646 | put8(0xA7); |
647 | put32(offset); |
648 | } |
649 | |
650 | static inline void imul_reg32(unsigned int reg32) |
651 | { |
652 | put8(0xF7); |
653 | put8(0xE8+reg32); |
654 | } |
655 | |
656 | static inline void mul_reg64(unsigned int reg64) |
657 | { |
658 | put8(0x48); |
659 | put8(0xF7); |
660 | put8(0xE0+reg64); |
661 | } |
662 | |
663 | static inline void mul_reg32(unsigned int reg32) |
664 | { |
665 | put8(0xF7); |
666 | put8(0xE0+reg32); |
667 | } |
668 | |
669 | static inline void idiv_reg32(unsigned int reg32) |
670 | { |
671 | put8(0xF7); |
672 | put8(0xF8+reg32); |
673 | } |
674 | |
675 | static inline void div_reg32(unsigned int reg32) |
676 | { |
677 | put8(0xF7); |
678 | put8(0xF0+reg32); |
679 | } |
680 | |
681 | static inline void add_reg32_reg32(unsigned int reg1, unsigned int reg2) |
682 | { |
683 | put8(0x01); |
684 | put8(0xC0 | (reg2 << 3) | reg1); |
685 | } |
686 | |
687 | static inline void add_reg64_reg64(unsigned int reg1, unsigned int reg2) |
688 | { |
689 | put8(0x48); |
690 | put8(0x01); |
691 | put8(0xC0 | (reg2 << 3) | reg1); |
692 | } |
693 | |
694 | static inline void jmp_reg64(unsigned int reg64) |
695 | { |
696 | put8(0xFF); |
697 | put8(0xE0 + reg64); |
698 | } |
699 | |
700 | static inline void mov_reg32_preg64(unsigned int reg1, unsigned int reg2) |
701 | { |
702 | put8(0x8B); |
703 | put8((reg1 << 3) | reg2); |
704 | } |
705 | |
706 | static inline void mov_preg64_reg32(int reg1, int reg2) |
707 | { |
708 | put8(0x89); |
709 | put8((reg2 << 3) | reg1); |
710 | } |
711 | |
712 | static inline void mov_reg64_preg64(int reg1, int reg2) |
713 | { |
714 | put8(0x48); |
715 | put8(0x8B); |
716 | put8((reg1 << 3) | reg2); |
717 | } |
718 | |
719 | static inline void mov_reg32_preg64preg64pimm32(int reg1, int reg2, int reg3, unsigned int imm32) |
720 | { |
721 | put8(0x8B); |
722 | put8((reg1 << 3) | 0x84); |
723 | put8(reg2 | (reg3 << 3)); |
724 | put32(imm32); |
725 | } |
726 | |
727 | static inline void mov_preg64preg64pimm32_reg32(int reg1, int reg2, unsigned int imm32, int reg3) |
728 | { |
729 | put8(0x89); |
730 | put8((reg3 << 3) | 0x84); |
731 | put8(reg1 | (reg2 << 3)); |
732 | put32(imm32); |
733 | } |
734 | |
735 | static inline void mov_reg64_preg64preg64pimm32(int reg1, int reg2, int reg3, unsigned int imm32) |
736 | { |
737 | put8(0x48); |
738 | put8(0x8B); |
739 | put8((reg1 << 3) | 0x84); |
740 | put8(reg2 | (reg3 << 3)); |
741 | put32(imm32); |
742 | } |
743 | |
744 | static inline void mov_reg32_preg64preg64(int reg1, int reg2, int reg3) |
745 | { |
746 | put8(0x8B); |
747 | put8((reg1 << 3) | 0x04); |
748 | put8((reg2 << 3) | reg3); |
749 | } |
750 | |
751 | static inline void mov_reg64_preg64preg64(int reg1, int reg2, int reg3) |
752 | { |
753 | put8(0x48); |
754 | put8(0x8B); |
755 | put8((reg1 << 3) | 0x04); |
756 | put8(reg2 | (reg3 << 3)); |
757 | } |
758 | |
759 | static inline void mov_reg32_preg64pimm32(int reg1, int reg2, unsigned int imm32) |
760 | { |
761 | put8(0x8B); |
762 | put8(0x80 | (reg1 << 3) | reg2); |
763 | put32(imm32); |
764 | } |
765 | |
766 | static inline void mov_reg64_preg64pimm32(int reg1, int reg2, unsigned int imm32) |
767 | { |
768 | put8(0x48); |
769 | put8(0x8B); |
770 | put8(0x80 | (reg1 << 3) | reg2); |
771 | put32(imm32); |
772 | } |
773 | |
774 | static inline void mov_reg64_preg64pimm8(int reg1, int reg2, unsigned int imm8) |
775 | { |
776 | put8(0x48); |
777 | put8(0x8B); |
778 | put8(0x40 | (reg1 << 3) | reg2); |
779 | put8(imm8); |
780 | } |
781 | |
782 | static inline void mov_reg64_preg64x8preg64(int reg1, int reg2, int reg3) |
783 | { |
784 | put8(0x48); |
785 | put8(0x8B); |
786 | put8((reg1 << 3) | 4); |
787 | put8(0xC0 | (reg2 << 3) | reg3); |
788 | } |
789 | |
790 | static inline void mov_preg64preg64_reg8(int reg1, int reg2, int reg8) |
791 | { |
792 | put8(0x88); |
793 | put8(0x04 | (reg8 << 3)); |
794 | put8((reg1 << 3) | reg2); |
795 | } |
796 | |
797 | static inline void mov_preg64preg64_imm8(int reg1, int reg2, unsigned char imm8) |
798 | { |
799 | put8(0xC6); |
800 | put8(0x04); |
801 | put8((reg1 << 3) | reg2); |
802 | put8(imm8); |
803 | } |
804 | |
805 | static inline void mov_preg64preg64_reg16(int reg1, int reg2, int reg16) |
806 | { |
807 | put8(0x66); |
808 | put8(0x89); |
809 | put8(0x04 | (reg16 << 3)); |
810 | put8((reg1 << 3) | reg2); |
811 | } |
812 | |
813 | static inline void mov_preg64preg64_reg32(int reg1, int reg2, int reg32) |
814 | { |
815 | put8(0x89); |
816 | put8(0x04 | (reg32 << 3)); |
817 | put8((reg1 << 3) | reg2); |
818 | } |
819 | |
820 | static inline void mov_preg64pimm32_reg32(int reg1, unsigned int imm32, int reg2) |
821 | { |
822 | put8(0x89); |
823 | put8(0x80 | reg1 | (reg2 << 3)); |
824 | put32(imm32); |
825 | } |
826 | |
827 | static inline void mov_preg64pimm8_reg64(int reg1, unsigned int imm8, int reg2) |
828 | { |
829 | put8(0x48); |
830 | put8(0x89); |
831 | put8(0x40 | (reg2 << 3) | reg1); |
832 | put8(imm8); |
833 | } |
834 | |
835 | static inline void add_eax_imm32(unsigned int imm32) |
836 | { |
837 | put8(0x05); |
838 | put32(imm32); |
839 | } |
840 | |
841 | static inline void shl_reg32_imm8(unsigned int reg32, unsigned char imm8) |
842 | { |
843 | put8(0xC1); |
844 | put8(0xE0 + reg32); |
845 | put8(imm8); |
846 | } |
847 | |
848 | static inline void shl_reg64_imm8(unsigned int reg64, unsigned char imm8) |
849 | { |
850 | put8(0x48); |
851 | put8(0xC1); |
852 | put8(0xE0 + reg64); |
853 | put8(imm8); |
854 | } |
855 | |
856 | static inline void mov_reg32_reg32(unsigned int reg1, unsigned int reg2) |
857 | { |
858 | if (reg1 == reg2) return; |
859 | put8(0x89); |
860 | put8(0xC0 | (reg2 << 3) | reg1); |
861 | } |
862 | |
863 | static inline void mov_reg64_reg64(unsigned int reg1, unsigned int reg2) |
864 | { |
865 | if (reg1 == reg2) return; |
866 | put8(0x48); |
867 | put8(0x89); |
868 | put8(0xC0 | (reg2 << 3) | reg1); |
869 | } |
870 | |
871 | static inline void mov_xreg32_m32rel(unsigned int xreg32, unsigned int *m32) |
872 | { |
873 | int offset = rel_r15_offset(m32, "mov_xreg32_m32rel"); |
874 | |
875 | put8(0x41 | ((xreg32 & 8) >> 1)); |
876 | put8(0x8B); |
877 | put8(0x87 | ((xreg32 & 7) << 3)); |
878 | put32(offset); |
879 | } |
880 | |
881 | static inline void mov_m32rel_xreg32(unsigned int *m32, unsigned int xreg32) |
882 | { |
883 | int offset = rel_r15_offset(m32, "mov_m32rel_xreg32"); |
884 | |
885 | put8(0x41 | ((xreg32 & 8) >> 1)); |
886 | put8(0x89); |
887 | put8(0x87 | ((xreg32 & 7) << 3)); |
888 | put32(offset); |
889 | } |
890 | |
891 | static inline void mov_xreg64_m64rel(unsigned int xreg64, unsigned long long* m64) |
892 | { |
893 | int offset = rel_r15_offset(m64, "mov_xreg64_m64rel"); |
894 | |
895 | put8(0x49 | ((xreg64 & 8) >> 1)); |
896 | put8(0x8B); |
897 | put8(0x87 | ((xreg64 & 7) << 3)); |
898 | put32(offset); |
899 | } |
900 | |
901 | static inline void mov_m64rel_xreg64(unsigned long long *m64, unsigned int xreg64) |
902 | { |
903 | int offset = rel_r15_offset(m64, "mov_m64rel_xreg64"); |
904 | |
905 | put8(0x49 | ((xreg64 & 8) >> 1)); |
906 | put8(0x89); |
907 | put8(0x87 | ((xreg64 & 7) << 3)); |
908 | put32(offset); |
909 | } |
910 | |
911 | static inline void mov_xreg8_m8rel(int xreg8, unsigned char *m8) |
912 | { |
913 | int offset = rel_r15_offset(m8, "mov_xreg8_m8rel"); |
914 | |
915 | put8(0x41 | ((xreg8 & 8) >> 1)); |
916 | put8(0x8A); |
917 | put8(0x87 | ((xreg8 & 7) << 3)); |
918 | put32(offset); |
919 | } |
920 | |
921 | static inline void and_eax_imm32(unsigned int imm32) |
922 | { |
923 | put8(0x25); |
924 | put32(imm32); |
925 | } |
926 | |
927 | static inline void or_reg64_imm32(int reg64, unsigned int imm32) |
928 | { |
929 | put8(0x48); |
930 | put8(0x81); |
931 | put8(0xC8 + reg64); |
932 | put32(imm32); |
933 | } |
934 | |
935 | static inline void and_reg32_imm32(int reg32, unsigned int imm32) |
936 | { |
937 | put8(0x81); |
938 | put8(0xE0 + reg32); |
939 | put32(imm32); |
940 | } |
941 | |
942 | static inline void and_reg64_imm32(int reg64, unsigned int imm32) |
943 | { |
944 | put8(0x48); |
945 | put8(0x81); |
946 | put8(0xE0 + reg64); |
947 | put32(imm32); |
948 | } |
949 | |
950 | static inline void and_reg64_imm8(int reg64, unsigned char imm8) |
951 | { |
952 | put8(0x48); |
953 | put8(0x83); |
954 | put8(0xE0 + reg64); |
955 | put8(imm8); |
956 | } |
957 | |
958 | static inline void xor_reg64_imm32(int reg64, unsigned int imm32) |
959 | { |
960 | put8(0x48); |
961 | put8(0x81); |
962 | put8(0xF0 + reg64); |
963 | put32(imm32); |
964 | } |
965 | |
966 | static inline void xor_reg8_imm8(int reg8, unsigned char imm8) |
967 | { |
968 | put8(0x40); /* we need an REX prefix to use the uniform byte registers */ |
969 | put8(0x80); |
970 | put8(0xF0 + reg8); |
971 | put8(imm8); |
972 | } |
973 | |
974 | static inline void not_reg64(unsigned int reg64) |
975 | { |
976 | put8(0x48); |
977 | put8(0xF7); |
978 | put8(0xD0 + reg64); |
979 | } |
980 | |
981 | static inline void neg_reg32(unsigned int reg32) |
982 | { |
983 | put8(0xF7); |
984 | put8(0xD8 + reg32); |
985 | } |
986 | |
987 | static inline void neg_reg64(unsigned int reg64) |
988 | { |
989 | put8(0x48); |
990 | put8(0xF7); |
991 | put8(0xD8 + reg64); |
992 | } |
993 | |
994 | static inline void movsx_xreg32_m8rel(int xreg32, unsigned char *m8) |
995 | { |
996 | int offset = rel_r15_offset(m8, "movsx_xreg32_m8rel"); |
997 | |
998 | put8(0x41 | ((xreg32 & 8) >> 1)); |
999 | put8(0x0F); |
1000 | put8(0xBE); |
1001 | put8(0x87 | ((xreg32 & 7) << 3)); |
1002 | put32(offset); |
1003 | } |
1004 | |
1005 | static inline void movsx_reg32_8preg64preg64(int reg1, int reg2, int reg3) |
1006 | { |
1007 | put8(0x0F); |
1008 | put8(0xBE); |
1009 | put8((reg1 << 3) | 0x04); |
1010 | put8((reg2 << 3) | reg3); |
1011 | } |
1012 | |
1013 | static inline void movsx_reg32_16preg64preg64(int reg1, int reg2, int reg3) |
1014 | { |
1015 | put8(0x0F); |
1016 | put8(0xBF); |
1017 | put8((reg1 << 3) | 0x04); |
1018 | put8((reg2 << 3) | reg3); |
1019 | } |
1020 | |
1021 | static inline void movsx_xreg32_m16rel(int xreg32, unsigned short *m16) |
1022 | { |
1023 | int offset = rel_r15_offset(m16, "movsx_xreg32_m16rel"); |
1024 | |
1025 | put8(0x41 | ((xreg32 & 8) >> 1)); |
1026 | put8(0x0F); |
1027 | put8(0xBF); |
1028 | put8(0x87 | ((xreg32 & 7) << 3)); |
1029 | put32(offset); |
1030 | } |
1031 | |
1032 | static inline void movsxd_reg64_reg32(int reg64, int reg32) |
1033 | { |
1034 | put8(0x48); |
1035 | put8(0x63); |
1036 | put8((reg64 << 3) | reg32 | 0xC0); |
1037 | } |
1038 | |
1039 | static inline void fldcw_m16rel(unsigned short *m16) |
1040 | { |
1041 | int offset = rel_r15_offset(m16, "fldcw_m16rel"); |
1042 | |
1043 | put8(0x41); |
1044 | put8(0xD9); |
1045 | put8(0xAF); |
1046 | put32(offset); |
1047 | } |
1048 | |
1049 | static inline void fld_preg64_dword(int reg64) |
1050 | { |
1051 | put8(0xD9); |
1052 | put8(reg64); |
1053 | } |
1054 | |
1055 | static inline void fdiv_preg64_dword(int reg64) |
1056 | { |
1057 | put8(0xD8); |
1058 | put8(0x30 + reg64); |
1059 | } |
1060 | |
1061 | static inline void fstp_preg64_dword(int reg64) |
1062 | { |
1063 | put8(0xD9); |
1064 | put8(0x18 + reg64); |
1065 | } |
1066 | |
1067 | static inline void fchs(void) |
1068 | { |
1069 | put8(0xD9); |
1070 | put8(0xE0); |
1071 | } |
1072 | |
1073 | static inline void fstp_preg64_qword(int reg64) |
1074 | { |
1075 | put8(0xDD); |
1076 | put8(0x18 + reg64); |
1077 | } |
1078 | |
1079 | static inline void fadd_preg64_dword(int reg64) |
1080 | { |
1081 | put8(0xD8); |
1082 | put8(reg64); |
1083 | } |
1084 | |
1085 | static inline void fsub_preg64_dword(int reg64) |
1086 | { |
1087 | put8(0xD8); |
1088 | put8(0x20 + reg64); |
1089 | } |
1090 | |
1091 | static inline void fmul_preg64_dword(int reg64) |
1092 | { |
1093 | put8(0xD8); |
1094 | put8(0x08 + reg64); |
1095 | } |
1096 | |
1097 | static inline void fistp_preg64_dword(int reg64) |
1098 | { |
1099 | put8(0xDB); |
1100 | put8(0x18 + reg64); |
1101 | } |
1102 | |
1103 | static inline void fistp_preg64_qword(int reg64) |
1104 | { |
1105 | put8(0xDF); |
1106 | put8(0x38 + reg64); |
1107 | } |
1108 | |
1109 | static inline void fld_preg64_qword(int reg64) |
1110 | { |
1111 | put8(0xDD); |
1112 | put8(reg64); |
1113 | } |
1114 | |
1115 | static inline void fild_preg64_qword(int reg64) |
1116 | { |
1117 | put8(0xDF); |
1118 | put8(0x28+reg64); |
1119 | } |
1120 | |
1121 | static inline void fild_preg64_dword(int reg64) |
1122 | { |
1123 | put8(0xDB); |
1124 | put8(reg64); |
1125 | } |
1126 | |
1127 | static inline void fadd_preg64_qword(int reg64) |
1128 | { |
1129 | put8(0xDC); |
1130 | put8(reg64); |
1131 | } |
1132 | |
1133 | static inline void fdiv_preg64_qword(int reg64) |
1134 | { |
1135 | put8(0xDC); |
1136 | put8(0x30 + reg64); |
1137 | } |
1138 | |
1139 | static inline void fsub_preg64_qword(int reg64) |
1140 | { |
1141 | put8(0xDC); |
1142 | put8(0x20 + reg64); |
1143 | } |
1144 | |
1145 | static inline void fmul_preg64_qword(int reg64) |
1146 | { |
1147 | put8(0xDC); |
1148 | put8(0x08 + reg64); |
1149 | } |
1150 | |
1151 | static inline void fsqrt(void) |
1152 | { |
1153 | put8(0xD9); |
1154 | put8(0xFA); |
1155 | } |
1156 | |
1157 | static inline void fabs_(void) |
1158 | { |
1159 | put8(0xD9); |
1160 | put8(0xE1); |
1161 | } |
1162 | |
1163 | static inline void fcomip_fpreg(int fpreg) |
1164 | { |
1165 | put8(0xDF); |
1166 | put8(0xF0 + fpreg); |
1167 | } |
1168 | |
1169 | static inline void fucomip_fpreg(int fpreg) |
1170 | { |
1171 | put8(0xDF); |
1172 | put8(0xE8 + fpreg); |
1173 | } |
1174 | |
1175 | static inline void ffree_fpreg(int fpreg) |
1176 | { |
1177 | put8(0xDD); |
1178 | put8(0xC0 + fpreg); |
1179 | } |
1180 | |
1181 | #endif /* __ASSEMBLE_H__ */ |
1182 | |