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 )