Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / x86_64 / assemble.h
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