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 *
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. *
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. *
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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
23 #ifndef __ASSEMBLE_H__
24 #define __ASSEMBLE_H__
26 #include "r4300/recomph.h"
27 #include "api/callbacks.h"
31 extern long long int reg[32];
69 extern int branch_taken;
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);
77 static inline void put8(unsigned char octet)
79 (*inst_pointer)[code_length] = octet;
81 if (code_length == max_code_length)
83 *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192);
84 max_code_length += 8192;
88 static inline void put32(unsigned int dword)
90 if ((code_length + 4) >= max_code_length)
92 *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192);
93 max_code_length += 8192;
95 *((unsigned int *) (*inst_pointer + code_length)) = dword;
99 static inline void put64(unsigned long long qword)
101 if ((code_length + 8) >= max_code_length)
103 *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192);
104 max_code_length += 8192;
106 *((unsigned long long *) (*inst_pointer + code_length)) = qword;
110 static inline int rel_r15_offset(void *dest, const char *op_name)
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);
115 if (llabs(rel_offset) > 0x7fffffff)
117 DebugMessage(M64MSG_ERROR, "Error: destination %p more than 2GB away from r15 base %p in %s()", dest, reg, op_name);
121 return (int) rel_offset;
124 static inline void mov_memoffs32_eax(unsigned int *memoffs32)
127 put64((unsigned long long) memoffs32);
130 static inline void mov_rax_memoffs64(unsigned long long *memoffs64)
134 put64((unsigned long long) memoffs64);
137 static inline void mov_memoffs64_rax(unsigned long long *memoffs64)
141 put64((unsigned long long) memoffs64);
144 static inline void mov_m8rel_xreg8(unsigned char *m8, int xreg8)
146 int offset = rel_r15_offset(m8, "mov_m8rel_xreg8");
148 put8(0x41 | ((xreg8 & 8) >> 1));
150 put8(0x87 | ((xreg8 & 7) << 3));
154 static inline void mov_xreg16_m16rel(int xreg16, unsigned short *m16)
156 int offset = rel_r15_offset(m16, "mov_xreg16_m16rel");
159 put8(0x41 | ((xreg16 & 8) >> 1));
161 put8(0x87 | ((xreg16 & 7) << 3));
165 static inline void mov_m16rel_xreg16(unsigned short *m16, int xreg16)
167 int offset = rel_r15_offset(m16, "mov_m16rel_xreg16");
170 put8(0x41 | ((xreg16 & 8) >> 1));
172 put8(0x87 | ((xreg16 & 7) << 3));
176 static inline void cmp_xreg32_m32rel(int xreg32, unsigned int *m32)
178 int offset = rel_r15_offset(m32, "cmp_xreg32_m32rel");
180 put8(0x41 | ((xreg32 & 8) >> 1));
182 put8(0x87 | ((xreg32 & 7) << 3));
186 static inline void cmp_xreg64_m64rel(int xreg64, unsigned long long *m64)
188 int offset = rel_r15_offset(m64, "cmp_xreg64_m64rel");
190 put8(0x49 | ((xreg64 & 8) >> 1));
192 put8(0x87 | ((xreg64 & 7) << 3));
196 static inline void cmp_reg32_reg32(int reg1, int reg2)
199 put8((reg2 << 3) | reg1 | 0xC0);
202 static inline void cmp_reg64_reg64(int reg1, int reg2)
206 put8((reg2 << 3) | reg1 | 0xC0);
209 static inline void cmp_reg32_imm8(int reg32, unsigned char imm8)
216 static inline void cmp_reg64_imm8(int reg64, unsigned char imm8)
224 static inline void cmp_reg32_imm32(int reg32, unsigned int imm32)
231 static inline void cmp_reg64_imm32(int reg64, unsigned int imm32)
239 static inline void cmp_preg64preg64_imm8(int reg1, int reg2, unsigned char imm8)
243 put8((reg1 << 3) | reg2);
247 static inline void sete_m8rel(unsigned char *m8)
249 int offset = rel_r15_offset(m8, "sete_m8rel");
258 static inline void setne_m8rel(unsigned char *m8)
260 int offset = rel_r15_offset(m8, "setne_m8rel");
269 static inline void setl_m8rel(unsigned char *m8)
271 int offset = rel_r15_offset(m8, "setl_m8rel");
280 static inline void setle_m8rel(unsigned char *m8)
282 int offset = rel_r15_offset(m8, "setle_m8rel");
291 static inline void setg_m8rel(unsigned char *m8)
293 int offset = rel_r15_offset(m8, "setg_m8rel");
302 static inline void setge_m8rel(unsigned char *m8)
304 int offset = rel_r15_offset(m8, "setge_m8rel");
313 static inline void setl_reg8(unsigned int reg8)
315 put8(0x40); /* we need an REX prefix to use the uniform byte registers */
321 static inline void setb_reg8(unsigned int reg8)
323 put8(0x40); /* we need an REX prefix to use the uniform byte registers */
329 static inline void test_m32rel_imm32(unsigned int *m32, unsigned int imm32)
331 int offset = rel_r15_offset(m32, "test_m32rel_imm32");
340 static inline void add_m32rel_xreg32(unsigned int *m32, int xreg32)
342 int offset = rel_r15_offset(m32, "add_m32rel_xreg32");
344 put8(0x41 | ((xreg32 & 8) >> 1));
346 put8(0x87 | ((xreg32 & 7) << 3));
350 static inline void sub_xreg32_m32rel(int xreg32, unsigned int *m32)
352 int offset = rel_r15_offset(m32, "sub_xreg32_m32rel");
354 put8(0x41 | ((xreg32 & 8) >> 1));
356 put8(0x87 | ((xreg32 & 7) << 3));
360 static inline void sub_reg32_reg32(int reg1, int reg2)
363 put8((reg2 << 3) | reg1 | 0xC0);
366 static inline void sub_reg64_reg64(int reg1, int reg2)
370 put8((reg2 << 3) | reg1 | 0xC0);
373 static inline void sub_reg64_imm32(int reg64, unsigned int imm32)
381 static inline void sub_eax_imm32(unsigned int imm32)
387 static inline void jne_rj(unsigned char saut)
393 static inline void je_rj(unsigned char saut)
399 static inline void jbe_rj(unsigned char saut)
405 static inline void ja_rj(unsigned char saut)
411 static inline void jae_rj(unsigned char saut)
417 static inline void jp_rj(unsigned char saut)
423 static inline void je_near_rj(unsigned int saut)
430 static inline void mov_reg32_imm32(int reg32, unsigned int imm32)
436 static inline void mov_reg64_imm64(int reg64, unsigned long long imm64)
443 static inline void jmp_imm_short(char saut)
449 static inline void or_m32rel_imm32(unsigned int *m32, unsigned int imm32)
451 int offset = rel_r15_offset(m32, "or_m32rel_imm32");
460 static inline void or_reg64_reg64(unsigned int reg1, unsigned int reg2)
464 put8(0xC0 | (reg2 << 3) | reg1);
467 static inline void and_reg64_reg64(unsigned int reg1, unsigned int reg2)
471 put8(0xC0 | (reg2 << 3) | reg1);
474 static inline void and_m32rel_imm32(unsigned int *m32, unsigned int imm32)
476 int offset = rel_r15_offset(m32, "and_m32rel_imm32");
485 static inline void xor_reg32_reg32(unsigned int reg1, unsigned int reg2)
488 put8(0xC0 | (reg2 << 3) | reg1);
491 static inline void xor_reg64_reg64(unsigned int reg1, unsigned int reg2)
495 put8(0xC0 | (reg2 << 3) | reg1);
498 static inline void add_reg64_imm32(unsigned int reg64, unsigned int imm32)
506 static inline void add_reg32_imm32(unsigned int reg32, unsigned int imm32)
513 static inline void inc_m32rel(unsigned int *m32)
515 int offset = rel_r15_offset(m32, "inc_m32rel");
523 static inline void cmp_m32rel_imm32(unsigned int *m32, unsigned int imm32)
525 int offset = rel_r15_offset(m32, "cmp_m32rel_imm32");
534 static inline void cmp_eax_imm32(unsigned int imm32)
540 static inline void mov_m32rel_imm32(unsigned int *m32, unsigned int imm32)
542 int offset = rel_r15_offset(m32, "mov_m32rel_imm32");
551 static inline void jmp(unsigned int mi_addr)
557 add_jump(code_length-8, mi_addr, 1);
560 static inline void cdq(void)
565 static inline void call_reg64(unsigned int reg64)
571 static inline void shr_reg64_imm8(unsigned int reg64, unsigned char imm8)
579 static inline void shr_reg32_imm8(unsigned int reg32, unsigned char imm8)
586 static inline void shr_reg32_cl(unsigned int reg32)
592 static inline void shr_reg64_cl(unsigned int reg64)
599 static inline void sar_reg32_cl(unsigned int reg32)
605 static inline void sar_reg64_cl(unsigned int reg64)
612 static inline void shl_reg32_cl(unsigned int reg32)
618 static inline void shl_reg64_cl(unsigned int reg64)
625 static inline void sar_reg32_imm8(unsigned int reg32, unsigned char imm8)
632 static inline void sar_reg64_imm8(unsigned int reg64, unsigned char imm8)
640 static inline void mul_m32rel(unsigned int *m32)
642 int offset = rel_r15_offset(m32, "mul_m32rel");
650 static inline void imul_reg32(unsigned int reg32)
656 static inline void mul_reg64(unsigned int reg64)
663 static inline void mul_reg32(unsigned int reg32)
669 static inline void idiv_reg32(unsigned int reg32)
675 static inline void div_reg32(unsigned int reg32)
681 static inline void add_reg32_reg32(unsigned int reg1, unsigned int reg2)
684 put8(0xC0 | (reg2 << 3) | reg1);
687 static inline void add_reg64_reg64(unsigned int reg1, unsigned int reg2)
691 put8(0xC0 | (reg2 << 3) | reg1);
694 static inline void jmp_reg64(unsigned int reg64)
700 static inline void mov_reg32_preg64(unsigned int reg1, unsigned int reg2)
703 put8((reg1 << 3) | reg2);
706 static inline void mov_preg64_reg32(int reg1, int reg2)
709 put8((reg2 << 3) | reg1);
712 static inline void mov_reg64_preg64(int reg1, int reg2)
716 put8((reg1 << 3) | reg2);
719 static inline void mov_reg32_preg64preg64pimm32(int reg1, int reg2, int reg3, unsigned int imm32)
722 put8((reg1 << 3) | 0x84);
723 put8(reg2 | (reg3 << 3));
727 static inline void mov_preg64preg64pimm32_reg32(int reg1, int reg2, unsigned int imm32, int reg3)
730 put8((reg3 << 3) | 0x84);
731 put8(reg1 | (reg2 << 3));
735 static inline void mov_reg64_preg64preg64pimm32(int reg1, int reg2, int reg3, unsigned int imm32)
739 put8((reg1 << 3) | 0x84);
740 put8(reg2 | (reg3 << 3));
744 static inline void mov_reg32_preg64preg64(int reg1, int reg2, int reg3)
747 put8((reg1 << 3) | 0x04);
748 put8((reg2 << 3) | reg3);
751 static inline void mov_reg64_preg64preg64(int reg1, int reg2, int reg3)
755 put8((reg1 << 3) | 0x04);
756 put8(reg2 | (reg3 << 3));
759 static inline void mov_reg32_preg64pimm32(int reg1, int reg2, unsigned int imm32)
762 put8(0x80 | (reg1 << 3) | reg2);
766 static inline void mov_reg64_preg64pimm32(int reg1, int reg2, unsigned int imm32)
770 put8(0x80 | (reg1 << 3) | reg2);
774 static inline void mov_reg64_preg64pimm8(int reg1, int reg2, unsigned int imm8)
778 put8(0x40 | (reg1 << 3) | reg2);
782 static inline void mov_reg64_preg64x8preg64(int reg1, int reg2, int reg3)
786 put8((reg1 << 3) | 4);
787 put8(0xC0 | (reg2 << 3) | reg3);
790 static inline void mov_preg64preg64_reg8(int reg1, int reg2, int reg8)
793 put8(0x04 | (reg8 << 3));
794 put8((reg1 << 3) | reg2);
797 static inline void mov_preg64preg64_imm8(int reg1, int reg2, unsigned char imm8)
801 put8((reg1 << 3) | reg2);
805 static inline void mov_preg64preg64_reg16(int reg1, int reg2, int reg16)
809 put8(0x04 | (reg16 << 3));
810 put8((reg1 << 3) | reg2);
813 static inline void mov_preg64preg64_reg32(int reg1, int reg2, int reg32)
816 put8(0x04 | (reg32 << 3));
817 put8((reg1 << 3) | reg2);
820 static inline void mov_preg64pimm32_reg32(int reg1, unsigned int imm32, int reg2)
823 put8(0x80 | reg1 | (reg2 << 3));
827 static inline void mov_preg64pimm8_reg64(int reg1, unsigned int imm8, int reg2)
831 put8(0x40 | (reg2 << 3) | reg1);
835 static inline void add_eax_imm32(unsigned int imm32)
841 static inline void shl_reg32_imm8(unsigned int reg32, unsigned char imm8)
848 static inline void shl_reg64_imm8(unsigned int reg64, unsigned char imm8)
856 static inline void mov_reg32_reg32(unsigned int reg1, unsigned int reg2)
858 if (reg1 == reg2) return;
860 put8(0xC0 | (reg2 << 3) | reg1);
863 static inline void mov_reg64_reg64(unsigned int reg1, unsigned int reg2)
865 if (reg1 == reg2) return;
868 put8(0xC0 | (reg2 << 3) | reg1);
871 static inline void mov_xreg32_m32rel(unsigned int xreg32, unsigned int *m32)
873 int offset = rel_r15_offset(m32, "mov_xreg32_m32rel");
875 put8(0x41 | ((xreg32 & 8) >> 1));
877 put8(0x87 | ((xreg32 & 7) << 3));
881 static inline void mov_m32rel_xreg32(unsigned int *m32, unsigned int xreg32)
883 int offset = rel_r15_offset(m32, "mov_m32rel_xreg32");
885 put8(0x41 | ((xreg32 & 8) >> 1));
887 put8(0x87 | ((xreg32 & 7) << 3));
891 static inline void mov_xreg64_m64rel(unsigned int xreg64, unsigned long long* m64)
893 int offset = rel_r15_offset(m64, "mov_xreg64_m64rel");
895 put8(0x49 | ((xreg64 & 8) >> 1));
897 put8(0x87 | ((xreg64 & 7) << 3));
901 static inline void mov_m64rel_xreg64(unsigned long long *m64, unsigned int xreg64)
903 int offset = rel_r15_offset(m64, "mov_m64rel_xreg64");
905 put8(0x49 | ((xreg64 & 8) >> 1));
907 put8(0x87 | ((xreg64 & 7) << 3));
911 static inline void mov_xreg8_m8rel(int xreg8, unsigned char *m8)
913 int offset = rel_r15_offset(m8, "mov_xreg8_m8rel");
915 put8(0x41 | ((xreg8 & 8) >> 1));
917 put8(0x87 | ((xreg8 & 7) << 3));
921 static inline void and_eax_imm32(unsigned int imm32)
927 static inline void or_reg64_imm32(int reg64, unsigned int imm32)
935 static inline void and_reg32_imm32(int reg32, unsigned int imm32)
942 static inline void and_reg64_imm32(int reg64, unsigned int imm32)
950 static inline void and_reg64_imm8(int reg64, unsigned char imm8)
958 static inline void xor_reg64_imm32(int reg64, unsigned int imm32)
966 static inline void xor_reg8_imm8(int reg8, unsigned char imm8)
968 put8(0x40); /* we need an REX prefix to use the uniform byte registers */
974 static inline void not_reg64(unsigned int reg64)
981 static inline void neg_reg32(unsigned int reg32)
987 static inline void neg_reg64(unsigned int reg64)
994 static inline void movsx_xreg32_m8rel(int xreg32, unsigned char *m8)
996 int offset = rel_r15_offset(m8, "movsx_xreg32_m8rel");
998 put8(0x41 | ((xreg32 & 8) >> 1));
1001 put8(0x87 | ((xreg32 & 7) << 3));
1005 static inline void movsx_reg32_8preg64preg64(int reg1, int reg2, int reg3)
1009 put8((reg1 << 3) | 0x04);
1010 put8((reg2 << 3) | reg3);
1013 static inline void movsx_reg32_16preg64preg64(int reg1, int reg2, int reg3)
1017 put8((reg1 << 3) | 0x04);
1018 put8((reg2 << 3) | reg3);
1021 static inline void movsx_xreg32_m16rel(int xreg32, unsigned short *m16)
1023 int offset = rel_r15_offset(m16, "movsx_xreg32_m16rel");
1025 put8(0x41 | ((xreg32 & 8) >> 1));
1028 put8(0x87 | ((xreg32 & 7) << 3));
1032 static inline void movsxd_reg64_reg32(int reg64, int reg32)
1036 put8((reg64 << 3) | reg32 | 0xC0);
1039 static inline void fldcw_m16rel(unsigned short *m16)
1041 int offset = rel_r15_offset(m16, "fldcw_m16rel");
1049 static inline void fld_preg64_dword(int reg64)
1055 static inline void fdiv_preg64_dword(int reg64)
1061 static inline void fstp_preg64_dword(int reg64)
1067 static inline void fchs(void)
1073 static inline void fstp_preg64_qword(int reg64)
1079 static inline void fadd_preg64_dword(int reg64)
1085 static inline void fsub_preg64_dword(int reg64)
1091 static inline void fmul_preg64_dword(int reg64)
1097 static inline void fistp_preg64_dword(int reg64)
1103 static inline void fistp_preg64_qword(int reg64)
1109 static inline void fld_preg64_qword(int reg64)
1115 static inline void fild_preg64_qword(int reg64)
1121 static inline void fild_preg64_dword(int reg64)
1127 static inline void fadd_preg64_qword(int reg64)
1133 static inline void fdiv_preg64_qword(int reg64)
1139 static inline void fsub_preg64_qword(int reg64)
1145 static inline void fmul_preg64_qword(int reg64)
1151 static inline void fsqrt(void)
1157 static inline void fabs_(void)
1163 static inline void fcomip_fpreg(int fpreg)
1169 static inline void fucomip_fpreg(int fpreg)
1175 static inline void ffree_fpreg(int fpreg)
1181 #endif /* __ASSEMBLE_H__ */