Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-gen-x86-64.h view on Meta::CPAN
/*
* jit-gen-x86-64.h - Macros for generating x86_64 code.
*
* Copyright (C) 2008 Southern Storm Software, Pty Ltd.
*
* This file is part of the libjit library.
*
* The libjit library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 2.1 of
* the License, or (at your option) any later version.
*
* The libjit library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the libjit library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef _JIT_GEN_X86_64_H
#define _JIT_GEN_X86_64_H
#include <jit/jit-defs.h>
#include "jit-gen-x86.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* X86_64 64 bit general purpose integer registers.
*/
typedef enum
{
X86_64_RAX = 0,
X86_64_RCX = 1,
X86_64_RDX = 2,
X86_64_RBX = 3,
X86_64_RSP = 4,
X86_64_RBP = 5,
X86_64_RSI = 6,
X86_64_RDI = 7,
X86_64_R8 = 8,
X86_64_R9 = 9,
X86_64_R10 = 10,
X86_64_R11 = 11,
X86_64_R12 = 12,
X86_64_R13 = 13,
X86_64_R14 = 14,
X86_64_R15 = 15,
X86_64_RIP = 16 /* This register encoding doesn't exist in the */
/* instructions. It's used for RIP relative encoding. */
} X86_64_Reg_No;
/*
* X86-64 xmm registers.
*/
typedef enum
{
libjit/jit/jit-gen-x86-64.h view on Meta::CPAN
do { \
x86_memindex_emit((inst), ((r) & 0x7), ((basereg) & 0x7), (disp), ((indexreg) & 0x7), (shift)); \
} while(0)
/*
* RSP, RBP and the corresponding upper registers (R12 and R13) can't be used
* for relative addressing without displacement because their codes are used
* for encoding addressing modes with diplacement.
* So we do a membase addressing in this case with a zero offset.
*/
#define x86_64_regp_emit(inst, r, regno) \
do { \
switch(regno) \
{ \
case X86_64_RSP: \
case X86_64_RBP: \
case X86_64_R12: \
case X86_64_R13: \
{ \
x86_64_membase_emit((inst), (r), (regno), 0); \
} \
break; \
default: \
{ \
x86_address_byte((inst), 0, ((r) & 0x7), ((regno) & 0x7)); \
} \
break; \
} \
} while(0)
/*
* Helper to encode an opcode where the encoding is different between
* 8bit and 16 ... 64 bit width in the following way:
* 8 bit == opcode given
* 16 ... 64 bit = opcode given | 0x1
*/
#define x86_64_opcode1_emit(inst, opc, size) \
do { \
switch ((size)) \
{ \
case 1: \
{ \
*(inst)++ = (unsigned char)(opc); \
} \
break; \
case 2: \
case 4: \
case 8: \
{ \
*(inst)++ = ((unsigned char)(opc) | 0x1); \
} \
break;\
default: \
{ \
jit_assert(0); \
} \
} \
} while(0)
/*
* Macros to implement the simple opcodes.
*/
#define x86_64_alu_reg_reg_size(inst, opc, dreg, sreg, size) \
do { \
switch(size) \
{ \
case 1: \
{ \
x86_64_rex_emit(inst, size, (dreg), 0, (sreg)); \
*(inst)++ = (((unsigned char)(opc)) << 3) + 2; \
x86_64_reg_emit((inst), (dreg), (sreg)); \
} \
break; \
case 2: \
{ \
*(inst)++ = (unsigned char)0x66; \
} \
case 4: \
case 8: \
{ \
x86_64_rex_emit(inst, size, (dreg), 0, (sreg)); \
*(inst)++ = (((unsigned char)(opc)) << 3) + 3; \
x86_64_reg_emit((inst), (dreg), (sreg)); \
} \
} \
} while(0)
#define x86_64_alu_regp_reg_size(inst, opc, dregp, sreg, size) \
do { \
switch(size) \
{ \
case 1: \
{ \
x86_64_rex_emit(inst, size, (sreg), 0, (dregp)); \
*(inst)++ = (((unsigned char)(opc)) << 3); \
x86_64_regp_emit((inst), (sreg), (dregp)); \
} \
break; \
case 2: \
{ \
*(inst)++ = (unsigned char)0x66; \
} \
case 4: \
case 8: \
{ \
x86_64_rex_emit(inst, size, (sreg), 0, (dregp)); \
*(inst)++ = (((unsigned char)(opc)) << 3) + 1; \
x86_64_regp_emit((inst), (sreg), (dregp)); \
} \
} \
} while(0)
#define x86_64_alu_mem_reg_size(inst, opc, mem, sreg, size) \
do { \
switch(size) \
{ \
case 1: \
{ \
x86_64_rex_emit(inst, size, (sreg), 0, 0); \
*(inst)++ = (((unsigned char)(opc)) << 3); \
x86_64_mem_emit((inst), (sreg), (mem)); \
libjit/jit/jit-gen-x86-64.h view on Meta::CPAN
x86_64_rex_emit(inst, (size), (r), (indexreg), (basereg)); \
*(inst)++ = (unsigned char)(opc1); \
*(inst)++ = (unsigned char)(opc2); \
x86_64_memindex_emit((inst), (r), (basereg), (disp), (indexreg), (shift)); \
} while(0)
/*
* xmm instructions with a prefix and three opcodes
*/
#define x86_64_p1_xmm3_reg_reg_size(inst, p1, opc1, opc2, opc3, r, reg, size) \
do { \
*(inst)++ = (unsigned char)(p1); \
x86_64_rex_emit(inst, (size), (r), 0, (reg)); \
*(inst)++ = (unsigned char)(opc1); \
*(inst)++ = (unsigned char)(opc2); \
*(inst)++ = (unsigned char)(opc3); \
x86_64_reg_emit(inst, (r), (reg)); \
} while(0)
#define x86_64_p1_xmm3_reg_regp_size(inst, p1, opc1, opc2, opc3, r, regp, size) \
do { \
*(inst)++ = (unsigned char)(p1); \
x86_64_rex_emit(inst, (size), (r), 0, (regp)); \
*(inst)++ = (unsigned char)(opc1); \
*(inst)++ = (unsigned char)(opc2); \
*(inst)++ = (unsigned char)(opc3); \
x86_64_regp_emit(inst, (r), (regp)); \
} while(0)
#define x86_64_p1_xmm3_reg_mem_size(inst, p1, opc1, opc2, opc3, r, mem, size) \
do { \
*(inst)++ = (unsigned char)(p1); \
x86_64_rex_emit(inst, (size), (r), 0, 0); \
*(inst)++ = (unsigned char)(opc1); \
*(inst)++ = (unsigned char)(opc2); \
*(inst)++ = (unsigned char)(opc3); \
x86_64_mem_emit(inst, (r), (mem)); \
} while(0)
#define x86_64_p1_xmm3_reg_membase_size(inst, p1, opc1, opc2, opc3, r, basereg, disp, size) \
do { \
*(inst)++ = (unsigned char)(p1); \
x86_64_rex_emit(inst, (size), (r), 0, (basereg)); \
*(inst)++ = (unsigned char)(opc1); \
*(inst)++ = (unsigned char)(opc2); \
*(inst)++ = (unsigned char)(opc3); \
x86_64_membase_emit(inst, (r), (basereg), (disp)); \
} while(0)
#define x86_64_p1_xmm3_reg_memindex_size(inst, p1, opc1, opc2, opc3, r, basereg, disp, indexreg, shift, size) \
do { \
*(inst)++ = (unsigned char)(p1); \
x86_64_rex_emit(inst, (size), (r), (indexreg), (basereg)); \
*(inst)++ = (unsigned char)(opc1); \
*(inst)++ = (unsigned char)(opc2); \
*(inst)++ = (unsigned char)(opc3); \
x86_64_memindex_emit((inst), (r), (basereg), (disp), (indexreg), (shift)); \
} while(0)
/*
* xmm1: Macro for use of the X86_64_XMM1 enum
*/
#define x86_64_xmm1_reg_reg(inst, opc, dreg, sreg, is_double) \
do { \
x86_64_p1_xmm2_reg_reg_size((inst), ((is_double) ? 0xf2 : 0xf3), 0x0f, (opc), (dreg), (sreg), 0); \
} while(0)
#define x86_64_xmm1_reg_regp(inst, opc, dreg, sregp, is_double) \
do { \
x86_64_p1_xmm2_reg_regp_size((inst), ((is_double) ? 0xf2 : 0xf3), 0x0f, (opc), (dreg), (sregp), 0); \
} while(0)
#define x86_64_xmm1_reg_mem(inst, opc, dreg, mem, is_double) \
do { \
x86_64_p1_xmm2_reg_mem_size((inst), ((is_double) ? 0xf2 : 0xf3), 0x0f, (opc), (dreg), (mem), 0); \
} while(0)
#define x86_64_xmm1_reg_membase(inst, opc, dreg, basereg, disp, is_double) \
do { \
x86_64_p1_xmm2_reg_membase_size((inst), ((is_double) ? 0xf2 : 0xf3), 0x0f, (opc), (dreg), (basereg), (disp), 0); \
} while(0)
#define x86_64_xmm1_reg_memindex(inst, opc, dreg, basereg, disp, indexreg, shift, is_double) \
do { \
x86_64_p1_xmm2_reg_memindex_size((inst), ((is_double) ? 0xf2 : 0xf3), 0x0f, (opc), (dreg), (basereg), (disp), (indexreg), (shift), 0); \
} while(0)
/*
* Load and store MXCSR register state
*/
/*
* ldmxcsr: Load MXCSR register
*/
#define x86_64_ldmxcsr_regp(inst, sregp) \
do { \
x86_64_xmm2_reg_regp((inst), 0x0f, 0xae, 2, (sregp)); \
} while(0)
#define x86_64_ldmxcsr_mem(inst, mem) \
do { \
x86_64_xmm2_reg_mem((inst), 0x0f, 0xae, 2, (mem)); \
} while(0)
#define x86_64_ldmxcsr_membase(inst, basereg, disp) \
do { \
x86_64_xmm2_reg_membase((inst), 0x0f, 0xae, 2, (basereg), (disp)); \
} while(0)
#define x86_64_ldmxcsr_memindex(inst, basereg, disp, indexreg, shift) \
do { \
x86_64_xmm2_reg_memindex((inst), 0x0f, 0xae, 2, (basereg), (disp), (indexreg), (shift)); \
} while(0)
/*
* stmxcsr: Store MXCSR register
*/
#define x86_64_stmxcsr_regp(inst, sregp) \
do { \
x86_64_xmm2_reg_regp((inst), 0x0f, 0xae, 3, (sregp)); \
} while(0)
libjit/jit/jit-gen-x86-64.h view on Meta::CPAN
x86_64_p1_xmm2_reg_memindex_size((inst), 0xf3, 0x0f, 0x5c, (dreg), (basereg), (disp), (indexreg), (shift), 0); \
} while(0)
/*
* mulss: Multiply scalar single precision float values
*/
#define x86_64_mulss_reg_reg(inst, dreg, sreg) \
do { \
x86_64_p1_xmm2_reg_reg_size((inst), 0xf3, 0x0f, 0x59, (dreg), (sreg), 0); \
} while(0)
#define x86_64_mulss_reg_regp(inst, dreg, sregp) \
do { \
x86_64_p1_xmm2_reg_regp_size((inst), 0xf3, 0x0f, 0x59, (dreg), (sregp), 0); \
} while(0)
#define x86_64_mulss_reg_mem(inst, dreg, mem) \
do { \
x86_64_p1_xmm2_reg_mem_size((inst), 0xf3, 0x0f, 0x59, (dreg), (mem), 0); \
} while(0)
#define x86_64_mulss_reg_membase(inst, dreg, basereg, disp) \
do { \
x86_64_p1_xmm2_reg_membase_size((inst), 0xf3, 0x0f, 0x59, (dreg), (basereg), (disp), 0); \
} while(0)
#define x86_64_mulss_reg_memindex(inst, dreg, basereg, disp, indexreg, shift) \
do { \
x86_64_p1_xmm2_reg_memindex_size((inst), 0xf3, 0x0f, 0x59, (dreg), (basereg), (disp), (indexreg), (shift), 0); \
} while(0)
/*
* divss: Divide scalar single precision float values
*/
#define x86_64_divss_reg_reg(inst, dreg, sreg) \
do { \
x86_64_p1_xmm2_reg_reg_size((inst), 0xf3, 0x0f, 0x5e, (dreg), (sreg), 0); \
} while(0)
#define x86_64_divss_reg_regp(inst, dreg, sregp) \
do { \
x86_64_p1_xmm2_reg_regp_size((inst), 0xf3, 0x0f, 0x5e, (dreg), (sregp), 0); \
} while(0)
#define x86_64_divss_reg_mem(inst, dreg, mem) \
do { \
x86_64_p1_xmm2_reg_mem_size((inst), 0xf3, 0x0f, 0x5e, (dreg), (mem), 0); \
} while(0)
#define x86_64_divss_reg_membase(inst, dreg, basereg, disp) \
do { \
x86_64_p1_xmm2_reg_membase_size((inst), 0xf3, 0x0f, 0x5e, (dreg), (basereg), (disp), 0); \
} while(0)
#define x86_64_divss_reg_memindex(inst, dreg, basereg, disp, indexreg, shift) \
do { \
x86_64_p1_xmm2_reg_memindex_size((inst), 0xf3, 0x0f, 0x5e, (dreg), (basereg), (disp), (indexreg), (shift), 0); \
} while(0)
/*
* Macros for the logical operations with packed single precision values.
*/
#define x86_64_plops_reg_reg(inst, op, dreg, sreg) \
do { \
x86_64_xmm2_reg_reg((inst), 0x0f, (op), (dreg), (sreg)); \
} while(0)
#define x86_64_plops_reg_regp(inst, op, dreg, sregp) \
do { \
x86_64_xmm2_reg_regp((inst), 0x0f, (op), (dreg), (sregp)); \
} while(0)
#define x86_64_plops_reg_mem(inst, op, dreg, mem) \
do { \
x86_64_xmm2_reg_mem((inst), 0x0f, (op), (dreg), (mem)); \
} while(0)
#define x86_64_plops_reg_membase(inst, op, dreg, basereg, disp) \
do { \
x86_64_xmm2_reg_membase((inst), 0x0f, (op), (dreg), (basereg), (disp)); \
} while(0)
#define x86_64_plops_reg_memindex(inst, op, dreg, basereg, disp, indexreg, shift) \
do { \
x86_64_xmm2_reg_memindex((inst), 0x0f, (op), (dreg), (basereg), (disp), (indexreg), (shift)); \
} while(0)
/*
* andps: And
*/
#define x86_64_andps_reg_reg(inst, dreg, sreg) \
do { \
x86_64_xmm2_reg_reg((inst), 0x0f, 0x54, (dreg), (sreg)); \
} while(0)
#define x86_64_andps_reg_regp(inst, dreg, sregp) \
do { \
x86_64_xmm2_reg_regp((inst), 0x0f, 0x54, (dreg), (sregp)); \
} while(0)
#define x86_64_andps_reg_mem(inst, dreg, mem) \
do { \
x86_64_xmm2_reg_mem((inst), 0x0f, 0x54, (dreg), (mem)); \
} while(0)
#define x86_64_andps_reg_membase(inst, dreg, basereg, disp) \
do { \
x86_64_xmm2_reg_membase((inst), 0x0f, 0x54, (dreg), (basereg), (disp)); \
} while(0)
#define x86_64_andps_reg_memindex(inst, dreg, basereg, disp, indexreg, shift) \
do { \
x86_64_xmm2_reg_memindex((inst), 0x0f, 0x54, (dreg), (basereg), (disp), (indexreg), (shift)); \
} while(0)
/*
* orps: Or
*/
#define x86_64_orps_reg_reg(inst, dreg, sreg) \
do { \
x86_64_xmm2_reg_reg((inst), 0x0f, 0x56, (dreg), (sreg)); \
libjit/jit/jit-gen-x86-64.h view on Meta::CPAN
} while(0)
/*
* minss: Minimum value
*/
#define x86_64_minss_reg_reg(inst, dreg, sreg) \
do { \
x86_64_p1_xmm2_reg_reg_size((inst), 0xf3, 0x0f, 0x5d, (dreg), (sreg), 0); \
} while(0)
#define x86_64_minss_reg_regp(inst, dreg, sregp) \
do { \
x86_64_p1_xmm2_reg_regp_size((inst), 0xf3, 0x0f, 0x5d, (dreg), (sregp), 0); \
} while(0)
#define x86_64_minss_reg_mem(inst, dreg, mem) \
do { \
x86_64_p1_xmm2_reg_mem_size((inst), 0xf3, 0x0f, 0x5d, (dreg), (mem), 0); \
} while(0)
#define x86_64_minss_reg_membase(inst, dreg, basereg, disp) \
do { \
x86_64_p1_xmm2_reg_membase_size((inst), 0xf3, 0x0f, 0x5d, (dreg), (basereg), (disp), 0); \
} while(0)
#define x86_64_minss_reg_memindex(inst, dreg, basereg, disp, indexreg, shift) \
do { \
x86_64_p1_xmm2_reg_memindex_size((inst), 0xf3, 0x0f, 0x5d, (dreg), (basereg), (disp), (indexreg), (shift), 0); \
} while(0)
/*
* sqrtss: Square root
*/
#define x86_64_sqrtss_reg_reg(inst, dreg, sreg) \
do { \
x86_64_p1_xmm2_reg_reg_size((inst), 0xf3, 0x0f, 0x51, (dreg), (sreg), 0); \
} while(0)
#define x86_64_sqrtss_reg_regp(inst, dreg, sregp) \
do { \
x86_64_p1_xmm2_reg_regp_size((inst), 0xf3, 0x0f, 0x51, (dreg), (sregp), 0); \
} while(0)
#define x86_64_sqrtss_reg_mem(inst, dreg, mem) \
do { \
x86_64_p1_xmm2_reg_mem_size((inst), 0xf3, 0x0f, 0x51, (dreg), (mem), 0); \
} while(0)
#define x86_64_sqrtss_reg_membase(inst, dreg, basereg, disp) \
do { \
x86_64_p1_xmm2_reg_membase_size((inst), 0xf3, 0x0f, 0x51, (dreg), (basereg), (disp), 0); \
} while(0)
#define x86_64_sqrtss_reg_memindex(inst, dreg, basereg, disp, indexreg, shift) \
do { \
x86_64_p1_xmm2_reg_memindex_size((inst), 0xf3, 0x0f, 0x51, (dreg), (basereg), (disp), (indexreg), (shift), 0); \
} while(0)
/*
* Macros for the logical operations with packed double precision values.
*/
#define x86_64_plopd_reg_reg(inst, op, dreg, sreg) \
do { \
x86_64_p1_xmm2_reg_reg_size((inst), 0x66, 0x0f, (op), (dreg), (sreg), 0); \
} while(0)
#define x86_64_plopd_reg_regp(inst, op, dreg, sregp) \
do { \
x86_64_p1_xmm2_reg_regp_size((inst), 0x66, 0x0f, (op), (dreg), (sregp), 0); \
} while(0)
#define x86_64_plopd_reg_mem(inst, op, dreg, mem) \
do { \
x86_64_p1_xmm2_reg_mem_size((inst), 0x66, 0x0f, (op), (dreg), (mem), 0); \
} while(0)
#define x86_64_plopd_reg_membase(inst, op, dreg, basereg, disp) \
do { \
x86_64_p1_xmm2_reg_membase_size((inst), 0x66, 0x0f, (op), (dreg), (basereg), (disp), 0); \
} while(0)
#define x86_64_plopd_reg_memindex(inst, op, dreg, basereg, disp, indexreg, shift) \
do { \
x86_64_xmm2_reg_memindex_size((inst), 0x66, 0x0f, (op), (dreg), (basereg), (disp), (indexreg), (shift), 0); \
} while(0)
/*
* addsd: Add scalar double precision float values
*/
#define x86_64_addsd_reg_reg(inst, dreg, sreg) \
do { \
x86_64_p1_xmm2_reg_reg_size((inst), 0xf2, 0x0f, 0x58, (dreg), (sreg), 0); \
} while(0)
#define x86_64_addsd_reg_regp(inst, dreg, sregp) \
do { \
x86_64_p1_xmm2_reg_regp_size((inst), 0xf2, 0x0f, 0x58, (dreg), (sregp), 0); \
} while(0)
#define x86_64_addsd_reg_mem(inst, dreg, mem) \
do { \
x86_64_p1_xmm2_reg_mem_size((inst), 0xf2, 0x0f, 0x58, (dreg), (mem), 0); \
} while(0)
#define x86_64_addsd_reg_membase(inst, dreg, basereg, disp) \
do { \
x86_64_p1_xmm2_reg_membase_size((inst), 0xf2, 0x0f, 0x58, (dreg), (basereg), (disp), 0); \
} while(0)
#define x86_64_addsd_reg_memindex(inst, dreg, basereg, disp, indexreg, shift) \
do { \
x86_64_p1_xmm2_reg_memindex_size((inst), 0xf2, 0x0f, 0x58, (dreg), (basereg), (disp), (indexreg), (shift), 0); \
} while(0)
/*
* subsd: Substract scalar double precision float values
*/
#define x86_64_subsd_reg_reg(inst, dreg, sreg) \
do { \
x86_64_p1_xmm2_reg_reg_size((inst), 0xf2, 0x0f, 0x5c, (dreg), (sreg), 0); \
( run in 1.226 second using v1.01-cache-2.11-cpan-39bf76dae61 )