X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=source%2Fmupen64plus-core%2Fsrc%2Fr4300%2Fx86_64%2Fassemble.h;fp=source%2Fmupen64plus-core%2Fsrc%2Fr4300%2Fx86_64%2Fassemble.h;h=087646b25357f846ce851c568a86c6d3a6f1ec6a;hb=451ab91e3827a6384981b3300e2a7000d2eaba58;hp=0000000000000000000000000000000000000000;hpb=a2ab25365b5b0dddbee476d695d8a31151407581;p=mupen64plus-pandora.git diff --git a/source/mupen64plus-core/src/r4300/x86_64/assemble.h b/source/mupen64plus-core/src/r4300/x86_64/assemble.h new file mode 100644 index 0000000..087646b --- /dev/null +++ b/source/mupen64plus-core/src/r4300/x86_64/assemble.h @@ -0,0 +1,1182 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - assemble.c * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2007 Richard Goedeken (Richard42) * + * Copyright (C) 2002 Hacktarux * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef __ASSEMBLE_H__ +#define __ASSEMBLE_H__ + +#include "r4300/recomph.h" +#include "api/callbacks.h" + +#include + +extern long long int reg[32]; + +#define RAX 0 +#define RCX 1 +#define RDX 2 +#define RBX 3 +#define RSP 4 +#define RBP 5 +#define RSI 6 +#define RDI 7 + +#define EAX 0 +#define ECX 1 +#define EDX 2 +#define EBX 3 +#define ESP 4 +#define EBP 5 +#define ESI 6 +#define EDI 7 + +#define AX 0 +#define CX 1 +#define DX 2 +#define BX 3 +#define SP 4 +#define BP 5 +#define SI 6 +#define DI 7 + +#define AL 0 +#define CL 1 +#define DL 2 +#define BL 3 +#define AH 4 +#define CH 5 +#define DH 6 +#define BH 7 + +extern int branch_taken; + +void jump_start_rel8(void); +void jump_end_rel8(void); +void jump_start_rel32(void); +void jump_end_rel32(void); +void add_jump(unsigned int pc_addr, unsigned int mi_addr, unsigned int absolute64); + +static inline void put8(unsigned char octet) +{ + (*inst_pointer)[code_length] = octet; + code_length++; + if (code_length == max_code_length) + { + *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); + max_code_length += 8192; + } +} + +static inline void put32(unsigned int dword) +{ + if ((code_length + 4) >= max_code_length) + { + *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); + max_code_length += 8192; + } + *((unsigned int *) (*inst_pointer + code_length)) = dword; + code_length += 4; +} + +static inline void put64(unsigned long long qword) +{ + if ((code_length + 8) >= max_code_length) + { + *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); + max_code_length += 8192; + } + *((unsigned long long *) (*inst_pointer + code_length)) = qword; + code_length += 8; +} + +static inline int rel_r15_offset(void *dest, const char *op_name) +{ + /* calculate the destination pointer's offset from the base of the r4300 registers */ + long long rel_offset = (long long) ((unsigned char *) dest - (unsigned char *) reg); + + if (llabs(rel_offset) > 0x7fffffff) + { + DebugMessage(M64MSG_ERROR, "Error: destination %p more than 2GB away from r15 base %p in %s()", dest, reg, op_name); + asm(" int $3; "); + } + + return (int) rel_offset; +} + +static inline void mov_memoffs32_eax(unsigned int *memoffs32) +{ + put8(0xA3); + put64((unsigned long long) memoffs32); +} + +static inline void mov_rax_memoffs64(unsigned long long *memoffs64) +{ + put8(0x48); + put8(0xA1); + put64((unsigned long long) memoffs64); +} + +static inline void mov_memoffs64_rax(unsigned long long *memoffs64) +{ + put8(0x48); + put8(0xA3); + put64((unsigned long long) memoffs64); +} + +static inline void mov_m8rel_xreg8(unsigned char *m8, int xreg8) +{ + int offset = rel_r15_offset(m8, "mov_m8rel_xreg8"); + + put8(0x41 | ((xreg8 & 8) >> 1)); + put8(0x88); + put8(0x87 | ((xreg8 & 7) << 3)); + put32(offset); +} + +static inline void mov_xreg16_m16rel(int xreg16, unsigned short *m16) +{ + int offset = rel_r15_offset(m16, "mov_xreg16_m16rel"); + + put8(0x66); + put8(0x41 | ((xreg16 & 8) >> 1)); + put8(0x8B); + put8(0x87 | ((xreg16 & 7) << 3)); + put32(offset); +} + +static inline void mov_m16rel_xreg16(unsigned short *m16, int xreg16) +{ + int offset = rel_r15_offset(m16, "mov_m16rel_xreg16"); + + put8(0x66); + put8(0x41 | ((xreg16 & 8) >> 1)); + put8(0x89); + put8(0x87 | ((xreg16 & 7) << 3)); + put32(offset); +} + +static inline void cmp_xreg32_m32rel(int xreg32, unsigned int *m32) +{ + int offset = rel_r15_offset(m32, "cmp_xreg32_m32rel"); + + put8(0x41 | ((xreg32 & 8) >> 1)); + put8(0x3B); + put8(0x87 | ((xreg32 & 7) << 3)); + put32(offset); +} + +static inline void cmp_xreg64_m64rel(int xreg64, unsigned long long *m64) +{ + int offset = rel_r15_offset(m64, "cmp_xreg64_m64rel"); + + put8(0x49 | ((xreg64 & 8) >> 1)); + put8(0x3B); + put8(0x87 | ((xreg64 & 7) << 3)); + put32(offset); +} + +static inline void cmp_reg32_reg32(int reg1, int reg2) +{ + put8(0x39); + put8((reg2 << 3) | reg1 | 0xC0); +} + +static inline void cmp_reg64_reg64(int reg1, int reg2) +{ + put8(0x48); + put8(0x39); + put8((reg2 << 3) | reg1 | 0xC0); +} + +static inline void cmp_reg32_imm8(int reg32, unsigned char imm8) +{ + put8(0x83); + put8(0xF8 + reg32); + put8(imm8); +} + +static inline void cmp_reg64_imm8(int reg64, unsigned char imm8) +{ + put8(0x48); + put8(0x83); + put8(0xF8 + reg64); + put8(imm8); +} + +static inline void cmp_reg32_imm32(int reg32, unsigned int imm32) +{ + put8(0x81); + put8(0xF8 + reg32); + put32(imm32); +} + +static inline void cmp_reg64_imm32(int reg64, unsigned int imm32) +{ + put8(0x48); + put8(0x81); + put8(0xF8 + reg64); + put32(imm32); +} + +static inline void cmp_preg64preg64_imm8(int reg1, int reg2, unsigned char imm8) +{ + put8(0x80); + put8(0x3C); + put8((reg1 << 3) | reg2); + put8(imm8); +} + +static inline void sete_m8rel(unsigned char *m8) +{ + int offset = rel_r15_offset(m8, "sete_m8rel"); + + put8(0x41); + put8(0x0F); + put8(0x94); + put8(0x87); + put32(offset); +} + +static inline void setne_m8rel(unsigned char *m8) +{ + int offset = rel_r15_offset(m8, "setne_m8rel"); + + put8(0x41); + put8(0x0F); + put8(0x95); + put8(0x87); + put32(offset); +} + +static inline void setl_m8rel(unsigned char *m8) +{ + int offset = rel_r15_offset(m8, "setl_m8rel"); + + put8(0x41); + put8(0x0F); + put8(0x9C); + put8(0x87); + put32(offset); +} + +static inline void setle_m8rel(unsigned char *m8) +{ + int offset = rel_r15_offset(m8, "setle_m8rel"); + + put8(0x41); + put8(0x0F); + put8(0x9E); + put8(0x87); + put32(offset); +} + +static inline void setg_m8rel(unsigned char *m8) +{ + int offset = rel_r15_offset(m8, "setg_m8rel"); + + put8(0x41); + put8(0x0F); + put8(0x9F); + put8(0x87); + put32(offset); +} + +static inline void setge_m8rel(unsigned char *m8) +{ + int offset = rel_r15_offset(m8, "setge_m8rel"); + + put8(0x41); + put8(0x0F); + put8(0x9D); + put8(0x87); + put32(offset); +} + +static inline void setl_reg8(unsigned int reg8) +{ + put8(0x40); /* we need an REX prefix to use the uniform byte registers */ + put8(0x0F); + put8(0x9C); + put8(0xC0 | reg8); +} + +static inline void setb_reg8(unsigned int reg8) +{ + put8(0x40); /* we need an REX prefix to use the uniform byte registers */ + put8(0x0F); + put8(0x92); + put8(0xC0 | reg8); +} + +static inline void test_m32rel_imm32(unsigned int *m32, unsigned int imm32) +{ + int offset = rel_r15_offset(m32, "test_m32rel_imm32"); + + put8(0x41); + put8(0xF7); + put8(0x87); + put32(offset); + put32(imm32); +} + +static inline void add_m32rel_xreg32(unsigned int *m32, int xreg32) +{ + int offset = rel_r15_offset(m32, "add_m32rel_xreg32"); + + put8(0x41 | ((xreg32 & 8) >> 1)); + put8(0x01); + put8(0x87 | ((xreg32 & 7) << 3)); + put32(offset); +} + +static inline void sub_xreg32_m32rel(int xreg32, unsigned int *m32) +{ + int offset = rel_r15_offset(m32, "sub_xreg32_m32rel"); + + put8(0x41 | ((xreg32 & 8) >> 1)); + put8(0x2B); + put8(0x87 | ((xreg32 & 7) << 3)); + put32(offset); +} + +static inline void sub_reg32_reg32(int reg1, int reg2) +{ + put8(0x29); + put8((reg2 << 3) | reg1 | 0xC0); +} + +static inline void sub_reg64_reg64(int reg1, int reg2) +{ + put8(0x48); + put8(0x29); + put8((reg2 << 3) | reg1 | 0xC0); +} + +static inline void sub_reg64_imm32(int reg64, unsigned int imm32) +{ + put8(0x48); + put8(0x81); + put8(0xE8 + reg64); + put32(imm32); +} + +static inline void sub_eax_imm32(unsigned int imm32) +{ + put8(0x2D); + put32(imm32); +} + +static inline void jne_rj(unsigned char saut) +{ + put8(0x75); + put8(saut); +} + +static inline void je_rj(unsigned char saut) +{ + put8(0x74); + put8(saut); +} + +static inline void jbe_rj(unsigned char saut) +{ + put8(0x76); + put8(saut); +} + +static inline void ja_rj(unsigned char saut) +{ + put8(0x77); + put8(saut); +} + +static inline void jae_rj(unsigned char saut) +{ + put8(0x73); + put8(saut); +} + +static inline void jp_rj(unsigned char saut) +{ + put8(0x7A); + put8(saut); +} + +static inline void je_near_rj(unsigned int saut) +{ + put8(0x0F); + put8(0x84); + put32(saut); +} + +static inline void mov_reg32_imm32(int reg32, unsigned int imm32) +{ + put8(0xB8+reg32); + put32(imm32); +} + +static inline void mov_reg64_imm64(int reg64, unsigned long long imm64) +{ + put8(0x48); + put8(0xB8+reg64); + put64(imm64); +} + +static inline void jmp_imm_short(char saut) +{ + put8(0xEB); + put8(saut); +} + +static inline void or_m32rel_imm32(unsigned int *m32, unsigned int imm32) +{ + int offset = rel_r15_offset(m32, "or_m32rel_imm32"); + + put8(0x41); + put8(0x81); + put8(0x8F); + put32(offset); + put32(imm32); +} + +static inline void or_reg64_reg64(unsigned int reg1, unsigned int reg2) +{ + put8(0x48); + put8(0x09); + put8(0xC0 | (reg2 << 3) | reg1); +} + +static inline void and_reg64_reg64(unsigned int reg1, unsigned int reg2) +{ + put8(0x48); + put8(0x21); + put8(0xC0 | (reg2 << 3) | reg1); +} + +static inline void and_m32rel_imm32(unsigned int *m32, unsigned int imm32) +{ + int offset = rel_r15_offset(m32, "and_m32rel_imm32"); + + put8(0x41); + put8(0x81); + put8(0xA7); + put32(offset); + put32(imm32); +} + +static inline void xor_reg32_reg32(unsigned int reg1, unsigned int reg2) +{ + put8(0x31); + put8(0xC0 | (reg2 << 3) | reg1); +} + +static inline void xor_reg64_reg64(unsigned int reg1, unsigned int reg2) +{ + put8(0x48); + put8(0x31); + put8(0xC0 | (reg2 << 3) | reg1); +} + +static inline void add_reg64_imm32(unsigned int reg64, unsigned int imm32) +{ + put8(0x48); + put8(0x81); + put8(0xC0+reg64); + put32(imm32); +} + +static inline void add_reg32_imm32(unsigned int reg32, unsigned int imm32) +{ + put8(0x81); + put8(0xC0+reg32); + put32(imm32); +} + +static inline void inc_m32rel(unsigned int *m32) +{ + int offset = rel_r15_offset(m32, "inc_m32rel"); + + put8(0x41); + put8(0xFF); + put8(0x87); + put32(offset); +} + +static inline void cmp_m32rel_imm32(unsigned int *m32, unsigned int imm32) +{ + int offset = rel_r15_offset(m32, "cmp_m32rel_imm32"); + + put8(0x41); + put8(0x81); + put8(0xBF); + put32(offset); + put32(imm32); +} + +static inline void cmp_eax_imm32(unsigned int imm32) +{ + put8(0x3D); + put32(imm32); +} + +static inline void mov_m32rel_imm32(unsigned int *m32, unsigned int imm32) +{ + int offset = rel_r15_offset(m32, "mov_m32rel_imm32"); + + put8(0x41); + put8(0xC7); + put8(0x87); + put32(offset); + put32(imm32); +} + +static inline void jmp(unsigned int mi_addr) +{ + put8(0xFF); + put8(0x25); + put32(0); + put64(0); + add_jump(code_length-8, mi_addr, 1); +} + +static inline void cdq(void) +{ + put8(0x99); +} + +static inline void call_reg64(unsigned int reg64) +{ + put8(0xFF); + put8(0xD0+reg64); +} + +static inline void shr_reg64_imm8(unsigned int reg64, unsigned char imm8) +{ + put8(0x48); + put8(0xC1); + put8(0xE8+reg64); + put8(imm8); +} + +static inline void shr_reg32_imm8(unsigned int reg32, unsigned char imm8) +{ + put8(0xC1); + put8(0xE8+reg32); + put8(imm8); +} + +static inline void shr_reg32_cl(unsigned int reg32) +{ + put8(0xD3); + put8(0xE8+reg32); +} + +static inline void shr_reg64_cl(unsigned int reg64) +{ + put8(0x48); + put8(0xD3); + put8(0xE8+reg64); +} + +static inline void sar_reg32_cl(unsigned int reg32) +{ + put8(0xD3); + put8(0xF8+reg32); +} + +static inline void sar_reg64_cl(unsigned int reg64) +{ + put8(0x48); + put8(0xD3); + put8(0xF8+reg64); +} + +static inline void shl_reg32_cl(unsigned int reg32) +{ + put8(0xD3); + put8(0xE0+reg32); +} + +static inline void shl_reg64_cl(unsigned int reg64) +{ + put8(0x48); + put8(0xD3); + put8(0xE0+reg64); +} + +static inline void sar_reg32_imm8(unsigned int reg32, unsigned char imm8) +{ + put8(0xC1); + put8(0xF8+reg32); + put8(imm8); +} + +static inline void sar_reg64_imm8(unsigned int reg64, unsigned char imm8) +{ + put8(0x48); + put8(0xC1); + put8(0xF8+reg64); + put8(imm8); +} + +static inline void mul_m32rel(unsigned int *m32) +{ + int offset = rel_r15_offset(m32, "mul_m32rel"); + + put8(0x41); + put8(0xF7); + put8(0xA7); + put32(offset); +} + +static inline void imul_reg32(unsigned int reg32) +{ + put8(0xF7); + put8(0xE8+reg32); +} + +static inline void mul_reg64(unsigned int reg64) +{ + put8(0x48); + put8(0xF7); + put8(0xE0+reg64); +} + +static inline void mul_reg32(unsigned int reg32) +{ + put8(0xF7); + put8(0xE0+reg32); +} + +static inline void idiv_reg32(unsigned int reg32) +{ + put8(0xF7); + put8(0xF8+reg32); +} + +static inline void div_reg32(unsigned int reg32) +{ + put8(0xF7); + put8(0xF0+reg32); +} + +static inline void add_reg32_reg32(unsigned int reg1, unsigned int reg2) +{ + put8(0x01); + put8(0xC0 | (reg2 << 3) | reg1); +} + +static inline void add_reg64_reg64(unsigned int reg1, unsigned int reg2) +{ + put8(0x48); + put8(0x01); + put8(0xC0 | (reg2 << 3) | reg1); +} + +static inline void jmp_reg64(unsigned int reg64) +{ + put8(0xFF); + put8(0xE0 + reg64); +} + +static inline void mov_reg32_preg64(unsigned int reg1, unsigned int reg2) +{ + put8(0x8B); + put8((reg1 << 3) | reg2); +} + +static inline void mov_preg64_reg32(int reg1, int reg2) +{ + put8(0x89); + put8((reg2 << 3) | reg1); +} + +static inline void mov_reg64_preg64(int reg1, int reg2) +{ + put8(0x48); + put8(0x8B); + put8((reg1 << 3) | reg2); +} + +static inline void mov_reg32_preg64preg64pimm32(int reg1, int reg2, int reg3, unsigned int imm32) +{ + put8(0x8B); + put8((reg1 << 3) | 0x84); + put8(reg2 | (reg3 << 3)); + put32(imm32); +} + +static inline void mov_preg64preg64pimm32_reg32(int reg1, int reg2, unsigned int imm32, int reg3) +{ + put8(0x89); + put8((reg3 << 3) | 0x84); + put8(reg1 | (reg2 << 3)); + put32(imm32); +} + +static inline void mov_reg64_preg64preg64pimm32(int reg1, int reg2, int reg3, unsigned int imm32) +{ + put8(0x48); + put8(0x8B); + put8((reg1 << 3) | 0x84); + put8(reg2 | (reg3 << 3)); + put32(imm32); +} + +static inline void mov_reg32_preg64preg64(int reg1, int reg2, int reg3) +{ + put8(0x8B); + put8((reg1 << 3) | 0x04); + put8((reg2 << 3) | reg3); +} + +static inline void mov_reg64_preg64preg64(int reg1, int reg2, int reg3) +{ + put8(0x48); + put8(0x8B); + put8((reg1 << 3) | 0x04); + put8(reg2 | (reg3 << 3)); +} + +static inline void mov_reg32_preg64pimm32(int reg1, int reg2, unsigned int imm32) +{ + put8(0x8B); + put8(0x80 | (reg1 << 3) | reg2); + put32(imm32); +} + +static inline void mov_reg64_preg64pimm32(int reg1, int reg2, unsigned int imm32) +{ + put8(0x48); + put8(0x8B); + put8(0x80 | (reg1 << 3) | reg2); + put32(imm32); +} + +static inline void mov_reg64_preg64pimm8(int reg1, int reg2, unsigned int imm8) +{ + put8(0x48); + put8(0x8B); + put8(0x40 | (reg1 << 3) | reg2); + put8(imm8); +} + +static inline void mov_reg64_preg64x8preg64(int reg1, int reg2, int reg3) +{ + put8(0x48); + put8(0x8B); + put8((reg1 << 3) | 4); + put8(0xC0 | (reg2 << 3) | reg3); +} + +static inline void mov_preg64preg64_reg8(int reg1, int reg2, int reg8) +{ + put8(0x88); + put8(0x04 | (reg8 << 3)); + put8((reg1 << 3) | reg2); +} + +static inline void mov_preg64preg64_imm8(int reg1, int reg2, unsigned char imm8) +{ + put8(0xC6); + put8(0x04); + put8((reg1 << 3) | reg2); + put8(imm8); +} + +static inline void mov_preg64preg64_reg16(int reg1, int reg2, int reg16) +{ + put8(0x66); + put8(0x89); + put8(0x04 | (reg16 << 3)); + put8((reg1 << 3) | reg2); +} + +static inline void mov_preg64preg64_reg32(int reg1, int reg2, int reg32) +{ + put8(0x89); + put8(0x04 | (reg32 << 3)); + put8((reg1 << 3) | reg2); +} + +static inline void mov_preg64pimm32_reg32(int reg1, unsigned int imm32, int reg2) +{ + put8(0x89); + put8(0x80 | reg1 | (reg2 << 3)); + put32(imm32); +} + +static inline void mov_preg64pimm8_reg64(int reg1, unsigned int imm8, int reg2) +{ + put8(0x48); + put8(0x89); + put8(0x40 | (reg2 << 3) | reg1); + put8(imm8); +} + +static inline void add_eax_imm32(unsigned int imm32) +{ + put8(0x05); + put32(imm32); +} + +static inline void shl_reg32_imm8(unsigned int reg32, unsigned char imm8) +{ + put8(0xC1); + put8(0xE0 + reg32); + put8(imm8); +} + +static inline void shl_reg64_imm8(unsigned int reg64, unsigned char imm8) +{ + put8(0x48); + put8(0xC1); + put8(0xE0 + reg64); + put8(imm8); +} + +static inline void mov_reg32_reg32(unsigned int reg1, unsigned int reg2) +{ + if (reg1 == reg2) return; + put8(0x89); + put8(0xC0 | (reg2 << 3) | reg1); +} + +static inline void mov_reg64_reg64(unsigned int reg1, unsigned int reg2) +{ + if (reg1 == reg2) return; + put8(0x48); + put8(0x89); + put8(0xC0 | (reg2 << 3) | reg1); +} + +static inline void mov_xreg32_m32rel(unsigned int xreg32, unsigned int *m32) +{ + int offset = rel_r15_offset(m32, "mov_xreg32_m32rel"); + + put8(0x41 | ((xreg32 & 8) >> 1)); + put8(0x8B); + put8(0x87 | ((xreg32 & 7) << 3)); + put32(offset); +} + +static inline void mov_m32rel_xreg32(unsigned int *m32, unsigned int xreg32) +{ + int offset = rel_r15_offset(m32, "mov_m32rel_xreg32"); + + put8(0x41 | ((xreg32 & 8) >> 1)); + put8(0x89); + put8(0x87 | ((xreg32 & 7) << 3)); + put32(offset); +} + +static inline void mov_xreg64_m64rel(unsigned int xreg64, unsigned long long* m64) +{ + int offset = rel_r15_offset(m64, "mov_xreg64_m64rel"); + + put8(0x49 | ((xreg64 & 8) >> 1)); + put8(0x8B); + put8(0x87 | ((xreg64 & 7) << 3)); + put32(offset); +} + +static inline void mov_m64rel_xreg64(unsigned long long *m64, unsigned int xreg64) +{ + int offset = rel_r15_offset(m64, "mov_m64rel_xreg64"); + + put8(0x49 | ((xreg64 & 8) >> 1)); + put8(0x89); + put8(0x87 | ((xreg64 & 7) << 3)); + put32(offset); +} + +static inline void mov_xreg8_m8rel(int xreg8, unsigned char *m8) +{ + int offset = rel_r15_offset(m8, "mov_xreg8_m8rel"); + + put8(0x41 | ((xreg8 & 8) >> 1)); + put8(0x8A); + put8(0x87 | ((xreg8 & 7) << 3)); + put32(offset); +} + +static inline void and_eax_imm32(unsigned int imm32) +{ + put8(0x25); + put32(imm32); +} + +static inline void or_reg64_imm32(int reg64, unsigned int imm32) +{ + put8(0x48); + put8(0x81); + put8(0xC8 + reg64); + put32(imm32); +} + +static inline void and_reg32_imm32(int reg32, unsigned int imm32) +{ + put8(0x81); + put8(0xE0 + reg32); + put32(imm32); +} + +static inline void and_reg64_imm32(int reg64, unsigned int imm32) +{ + put8(0x48); + put8(0x81); + put8(0xE0 + reg64); + put32(imm32); +} + +static inline void and_reg64_imm8(int reg64, unsigned char imm8) +{ + put8(0x48); + put8(0x83); + put8(0xE0 + reg64); + put8(imm8); +} + +static inline void xor_reg64_imm32(int reg64, unsigned int imm32) +{ + put8(0x48); + put8(0x81); + put8(0xF0 + reg64); + put32(imm32); +} + +static inline void xor_reg8_imm8(int reg8, unsigned char imm8) +{ + put8(0x40); /* we need an REX prefix to use the uniform byte registers */ + put8(0x80); + put8(0xF0 + reg8); + put8(imm8); +} + +static inline void not_reg64(unsigned int reg64) +{ + put8(0x48); + put8(0xF7); + put8(0xD0 + reg64); +} + +static inline void neg_reg32(unsigned int reg32) +{ + put8(0xF7); + put8(0xD8 + reg32); +} + +static inline void neg_reg64(unsigned int reg64) +{ + put8(0x48); + put8(0xF7); + put8(0xD8 + reg64); +} + +static inline void movsx_xreg32_m8rel(int xreg32, unsigned char *m8) +{ + int offset = rel_r15_offset(m8, "movsx_xreg32_m8rel"); + + put8(0x41 | ((xreg32 & 8) >> 1)); + put8(0x0F); + put8(0xBE); + put8(0x87 | ((xreg32 & 7) << 3)); + put32(offset); +} + +static inline void movsx_reg32_8preg64preg64(int reg1, int reg2, int reg3) +{ + put8(0x0F); + put8(0xBE); + put8((reg1 << 3) | 0x04); + put8((reg2 << 3) | reg3); +} + +static inline void movsx_reg32_16preg64preg64(int reg1, int reg2, int reg3) +{ + put8(0x0F); + put8(0xBF); + put8((reg1 << 3) | 0x04); + put8((reg2 << 3) | reg3); +} + +static inline void movsx_xreg32_m16rel(int xreg32, unsigned short *m16) +{ + int offset = rel_r15_offset(m16, "movsx_xreg32_m16rel"); + + put8(0x41 | ((xreg32 & 8) >> 1)); + put8(0x0F); + put8(0xBF); + put8(0x87 | ((xreg32 & 7) << 3)); + put32(offset); +} + +static inline void movsxd_reg64_reg32(int reg64, int reg32) +{ + put8(0x48); + put8(0x63); + put8((reg64 << 3) | reg32 | 0xC0); +} + +static inline void fldcw_m16rel(unsigned short *m16) +{ + int offset = rel_r15_offset(m16, "fldcw_m16rel"); + + put8(0x41); + put8(0xD9); + put8(0xAF); + put32(offset); +} + +static inline void fld_preg64_dword(int reg64) +{ + put8(0xD9); + put8(reg64); +} + +static inline void fdiv_preg64_dword(int reg64) +{ + put8(0xD8); + put8(0x30 + reg64); +} + +static inline void fstp_preg64_dword(int reg64) +{ + put8(0xD9); + put8(0x18 + reg64); +} + +static inline void fchs(void) +{ + put8(0xD9); + put8(0xE0); +} + +static inline void fstp_preg64_qword(int reg64) +{ + put8(0xDD); + put8(0x18 + reg64); +} + +static inline void fadd_preg64_dword(int reg64) +{ + put8(0xD8); + put8(reg64); +} + +static inline void fsub_preg64_dword(int reg64) +{ + put8(0xD8); + put8(0x20 + reg64); +} + +static inline void fmul_preg64_dword(int reg64) +{ + put8(0xD8); + put8(0x08 + reg64); +} + +static inline void fistp_preg64_dword(int reg64) +{ + put8(0xDB); + put8(0x18 + reg64); +} + +static inline void fistp_preg64_qword(int reg64) +{ + put8(0xDF); + put8(0x38 + reg64); +} + +static inline void fld_preg64_qword(int reg64) +{ + put8(0xDD); + put8(reg64); +} + +static inline void fild_preg64_qword(int reg64) +{ + put8(0xDF); + put8(0x28+reg64); +} + +static inline void fild_preg64_dword(int reg64) +{ + put8(0xDB); + put8(reg64); +} + +static inline void fadd_preg64_qword(int reg64) +{ + put8(0xDC); + put8(reg64); +} + +static inline void fdiv_preg64_qword(int reg64) +{ + put8(0xDC); + put8(0x30 + reg64); +} + +static inline void fsub_preg64_qword(int reg64) +{ + put8(0xDC); + put8(0x20 + reg64); +} + +static inline void fmul_preg64_qword(int reg64) +{ + put8(0xDC); + put8(0x08 + reg64); +} + +static inline void fsqrt(void) +{ + put8(0xD9); + put8(0xFA); +} + +static inline void fabs_(void) +{ + put8(0xD9); + put8(0xE1); +} + +static inline void fcomip_fpreg(int fpreg) +{ + put8(0xDF); + put8(0xF0 + fpreg); +} + +static inline void fucomip_fpreg(int fpreg) +{ + put8(0xDF); + put8(0xE8 + fpreg); +} + +static inline void ffree_fpreg(int fpreg) +{ + put8(0xDD); + put8(0xC0 + fpreg); +} + +#endif /* __ASSEMBLE_H__ */ +