/* src/vm/jit/i386/emitfuncs.h - emit function prototypes

   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
   J. Wenninger, Institut f. Computersprachen - TU Wien

   This file is part of CACAO.

   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, 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.

   Contact: cacao@cacaojvm.org

   Authors: Christian Thalinger

   Changes:

*/


#ifndef _EMITFUNCS_H
#define _EMITFUNCS_H

#include "vm/types.h"

#include "vm/jit/codegen-common.h"


#define REG_AL       0
#define REG_CL       1
#define REG_DL       2
#define REG_BL       3
#define REG_AH       4
#define REG_CH       5
#define REG_DH       6
#define REG_BH       7


/* opcodes for alu instructions */

#define ALU_ADD      0
#define ALU_OR       1
#define ALU_ADC      2
#define ALU_SBB      3
#define ALU_AND      4
#define ALU_SUB      5
#define ALU_XOR      6
#define ALU_CMP      7


#define SHIFT_ROL    0
#define SHIFT_ROR    1
#define SHIFT_RCL    2
#define SHIFT_RCR    3
#define SHIFT_SHL    4
#define SHIFT_SHR    5
#define SHIFT_SAR    7


#define CC_O         0
#define CC_NO        1
#define CC_B         2
#define CC_C         2
#define CC_NAE       2
#define CC_AE        3
#define CC_NB        3
#define CC_NC        3
#define CC_E         4
#define CC_Z         4
#define CC_NE        5
#define CC_NZ        5
#define CC_BE        6
#define CC_NA        6
#define CC_A         7
#define CC_NBE       7
#define CC_S         8
#define CC_LZ        8
#define CC_NS        9
#define CC_GEZ       9
#define CC_P         0x0a
#define CC_PE        0x0a
#define CC_NP        0x0b
#define CC_PO        0x0b
#define CC_L         0x0c
#define CC_NGE       0x0c
#define CC_GE        0x0d
#define CC_NL        0x0d
#define CC_LE        0x0e
#define CC_NG        0x0e
#define CC_G         0x0f
#define CC_NLE       0x0f


/* modrm and stuff */

#define emit_address_byte(mod,reg,rm) \
    do { \
        *(cd->mcodeptr++) = ((((mod) & 0x03) << 6) | (((reg) & 0x07) << 3) | (((rm) & 0x07))); \
    } while (0)


#define emit_imm8(imm) \
    do { \
        *(cd->mcodeptr++) = (u1) ((imm) & 0xff); \
    } while (0)


#define emit_imm16(imm) \
    do { \
        imm_union imb; \
        imb.i = (int) (imm); \
        *(cd->mcodeptr++) = imb.b[0]; \
        *(cd->mcodeptr++) = imb.b[1]; \
    } while (0)


#define emit_imm32(imm) \
    do { \
        imm_union imb; \
        imb.i = (int) (imm); \
        *(cd->mcodeptr++) = imb.b[0]; \
        *(cd->mcodeptr++) = imb.b[1]; \
        *(cd->mcodeptr++) = imb.b[2]; \
        *(cd->mcodeptr++) = imb.b[3]; \
    } while (0)


#define emit_mem(r,mem) \
    do { \
        emit_address_byte(0,(r),5); \
        emit_imm32((mem)); \
    } while (0)


/* convenience macros *********************************************************/

#define emit_reg(reg,rm)                emit_address_byte(3,(reg),(rm))


/* integer instructions */

void emit_mov_reg_reg(codegendata *cd, s4 reg, s4 dreg);
void emit_mov_imm_reg(codegendata *cd, s4 imm, s4 dreg);
void emit_movb_imm_reg(codegendata *cd, s4 imm, s4 dreg);
void emit_mov_membase_reg(codegendata *cd, s4 basereg, s4 disp, s4 reg);
void emit_mov_membase32_reg(codegendata *cd, s4 basereg, s4 disp, s4 reg);
void emit_mov_reg_membase(codegendata *cd, s4 reg, s4 basereg, s4 disp);
void emit_mov_reg_membase32(codegendata *cd, s4 reg, s4 basereg, s4 disp);
void emit_mov_memindex_reg(codegendata *cd, s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg);
void emit_mov_reg_memindex(codegendata *cd, s4 reg, s4 disp, s4 basereg, s4 indexreg, s4 scale);
void emit_movw_reg_memindex(codegendata *cd, s4 reg, s4 disp, s4 basereg, s4 indexreg, s4 scale);
void emit_movb_reg_memindex(codegendata *cd, s4 reg, s4 disp, s4 basereg, s4 indexreg, s4 scale);
void emit_mov_reg_mem(codegendata *cd, s4 reg, s4 mem);
void emit_mov_mem_reg(codegendata *cd, s4 mem, s4 dreg);
void emit_mov_imm_mem(codegendata *cd, s4 imm, s4 mem);
void emit_mov_imm_membase(codegendata *cd, s4 imm, s4 basereg, s4 disp);
void emit_mov_imm_membase32(codegendata *cd, s4 imm, s4 basereg, s4 disp);
void emit_movb_imm_membase(codegendata *cd, s4 imm, s4 basereg, s4 disp);
void emit_movsbl_reg_reg(codegendata *cd, s4 a, s4 b);
void emit_movsbl_memindex_reg(codegendata *cd, s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg);
void emit_movswl_reg_reg(codegendata *cd, s4 a, s4 b);
void emit_movswl_memindex_reg(codegendata *cd, s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg);
void emit_movzbl_reg_reg(codegendata *cd, s4 a, s4 b);
void emit_movzwl_reg_reg(codegendata *cd, s4 a, s4 b);
void emit_movzwl_memindex_reg(codegendata *cd, s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg);
void emit_mov_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale);
void emit_movw_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale);
void emit_movb_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale);

void emit_alu_reg_reg(codegendata *cd, s4 opc, s4 reg, s4 dreg);
void emit_alu_reg_membase(codegendata *cd, s4 opc, s4 reg, s4 basereg, s4 disp);
void emit_alu_membase_reg(codegendata *cd, s4 opc, s4 basereg, s4 disp, s4 reg);
void emit_alu_imm_reg(codegendata *cd, s4 opc, s4 imm, s4 reg);
void emit_alu_imm32_reg(codegendata *cd, s4 opc, s4 imm, s4 reg);
void emit_alu_imm_membase(codegendata *cd, s4 opc, s4 imm, s4 basereg, s4 disp);
void emit_alu_imm_memabs(codegendata *cd, s4 opc, s4 imm, s4 disp);
void emit_test_reg_reg(codegendata *cd, s4 reg, s4 dreg);
void emit_test_imm_reg(codegendata *cd, s4 imm, s4 dreg);
void emit_dec_mem(codegendata *cd, s4 mem);
void emit_imul_reg_reg(codegendata *cd, s4 reg, s4 dreg);
void emit_imul_membase_reg(codegendata *cd, s4 basereg, s4 disp, s4 dreg);
void emit_imul_imm_reg(codegendata *cd, s4 imm, s4 reg);
void emit_imul_imm_reg_reg(codegendata *cd, s4 imm, s4 reg, s4 dreg);
void emit_imul_imm_membase_reg(codegendata *cd, s4 imm, s4 basereg, s4 disp, s4 dreg);
void emit_mul_reg(codegendata *cd, s4 reg);
void emit_idiv_reg(codegendata *cd, s4 reg);
void emit_shift_reg(codegendata *cd, s4 opc, s4 reg);
void emit_shift_imm_reg(codegendata *cd, s4 opc, s4 imm, s4 reg);
void emit_shld_reg_reg(codegendata *cd, s4 reg, s4 dreg);
void emit_shld_imm_reg_reg(codegendata *cd, s4 imm, s4 reg, s4 dreg);
void emit_shld_reg_membase(codegendata *cd, s4 reg, s4 basereg, s4 disp);
void emit_shrd_reg_reg(codegendata *cd, s4 reg, s4 dreg);
void emit_shrd_imm_reg_reg(codegendata *cd, s4 imm, s4 reg, s4 dreg);
void emit_shrd_reg_membase(codegendata *cd, s4 reg, s4 basereg, s4 disp);
void emit_jmp_imm(codegendata *cd, s4 imm);
void emit_jmp_reg(codegendata *cd, s4 reg);
void emit_jcc(codegendata *cd, s4 opc, s4 imm);
void emit_setcc_reg(codegendata *cd, s4 opc, s4 reg);
void emit_setcc_membase(codegendata *cd, s4 opc, s4 basereg, s4 disp);
void emit_xadd_reg_mem(codegendata *cd, s4 reg, s4 mem);
void emit_neg_reg(codegendata *cd, s4 reg);
void emit_push_imm(codegendata *cd, s4 imm);
void emit_pop_reg(codegendata *cd, s4 reg);
void emit_push_reg(codegendata *cd, s4 reg);
void emit_lock(codegendata *cd);
void emit_call_reg(codegendata *cd, s4 reg);
void emit_call_imm(codegendata *cd, s4 imm);
void emit_call_mem(codegendata *cd, s4 mem);


/* floating point instructions */

void emit_fld1(codegendata *cd);
void emit_fldz(codegendata *cd);
void emit_fld_reg(codegendata *cd, s4 reg);
void emit_flds_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_flds_membase32(codegendata *cd, s4 basereg, s4 disp);
void emit_fldl_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fldl_membase32(codegendata *cd, s4 basereg, s4 disp);
void emit_fldt_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_flds_memindex(codegendata *cd, s4 disp, s4 basereg, s4 indexreg, s4 scale);
void emit_fldl_memindex(codegendata *cd, s4 disp, s4 basereg, s4 indexreg, s4 scale);
void emit_flds_mem(codegendata *cd, s4 mem);
void emit_fldl_mem(codegendata *cd, s4 mem);
void emit_fildl_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fildll_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fst_reg(codegendata *cd, s4 reg);
void emit_fsts_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fstl_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fsts_memindex(codegendata *cd, s4 disp, s4 basereg, s4 indexreg, s4 scale);
void emit_fstl_memindex(codegendata *cd, s4 disp, s4 basereg, s4 indexreg, s4 scale);
void emit_fstp_reg(codegendata *cd, s4 reg);
void emit_fstps_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fstps_membase32(codegendata *cd, s4 basereg, s4 disp);
void emit_fstpl_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fstpl_membase32(codegendata *cd, s4 basereg, s4 disp);
void emit_fstpt_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fstps_memindex(codegendata *cd, s4 disp, s4 basereg, s4 indexreg, s4 scale);
void emit_fstpl_memindex(codegendata *cd, s4 disp, s4 basereg, s4 indexreg, s4 scale);
void emit_fstps_mem(codegendata *cd, s4 mem);
void emit_fstpl_mem(codegendata *cd, s4 mem);
void emit_fistl_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fistpl_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fistpll_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fchs(codegendata *cd);
void emit_faddp(codegendata *cd);
void emit_fadd_reg_st(codegendata *cd, s4 reg);
void emit_fadd_st_reg(codegendata *cd, s4 reg);
void emit_faddp_st_reg(codegendata *cd, s4 reg);
void emit_fadds_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_faddl_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fsub_reg_st(codegendata *cd, s4 reg);
void emit_fsub_st_reg(codegendata *cd, s4 reg);
void emit_fsubp_st_reg(codegendata *cd, s4 reg);
void emit_fsubp(codegendata *cd);
void emit_fsubs_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fsubl_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fmul_reg_st(codegendata *cd, s4 reg);
void emit_fmul_st_reg(codegendata *cd, s4 reg);
void emit_fmulp(codegendata *cd);
void emit_fmulp_st_reg(codegendata *cd, s4 reg);
void emit_fmuls_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fmull_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_fdiv_reg_st(codegendata *cd, s4 reg);
void emit_fdiv_st_reg(codegendata *cd, s4 reg);
void emit_fdivp(codegendata *cd);
void emit_fdivp_st_reg(codegendata *cd, s4 reg);
void emit_fxch(codegendata *cd);
void emit_fxch_reg(codegendata *cd, s4 reg);
void emit_fprem(codegendata *cd);
void emit_fprem1(codegendata *cd);
void emit_fucom(codegendata *cd);
void emit_fucom_reg(codegendata *cd, s4 reg);
void emit_fucomp_reg(codegendata *cd, s4 reg);
void emit_fucompp(codegendata *cd);
void emit_fnstsw(codegendata *cd);
void emit_sahf(codegendata *cd);
void emit_finit(codegendata *cd);
void emit_fldcw_mem(codegendata *cd, s4 mem);
void emit_fldcw_membase(codegendata *cd, s4 basereg, s4 disp);
void emit_wait(codegendata *cd);
void emit_ffree_reg(codegendata *cd, s4 reg);
void emit_fdecstp(codegendata *cd);
void emit_fincstp(codegendata *cd);

#if defined(ENABLE_ESCAPE_CHECK)
void emit_escape_check(codegendata *cd, s4 reg);
void emit_escape_annotate_object(codegendata *cd, methodinfo *m);
#endif

#endif /* _EMITFUNCS_H */


/*
 * These are local overrides for various environment variables in Emacs.
 * Please do not remove this and leave it at the end of the file, where
 * Emacs will automagically detect them.
 * ---------------------------------------------------------------------
 * Local variables:
 * mode: c
 * indent-tabs-mode: t
 * c-basic-offset: 4
 * tab-width: 4
 * End:
 */
