X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fi386%2Fcodegen.h;h=aa635ed5673c119c6d1a72d908db4758e1e284d1;hb=9f859ad50d3d5d98c185d40b86b2179bc4dc9aeb;hp=bd0660efbb3a0b59011d88f7cdcc0d2f53208d28;hpb=49a8b7350e39817ceff2632ab32f99503ed1efe2;p=cacao.git diff --git a/src/vm/jit/i386/codegen.h b/src/vm/jit/i386/codegen.h index bd0660efb..aa635ed56 100644 --- a/src/vm/jit/i386/codegen.h +++ b/src/vm/jit/i386/codegen.h @@ -1,9 +1,9 @@ -/* jit/i386/codegen.h - code generation macros and definitions for i386 +/* src/vm/jit/i386/codegen.h - code generation macros and definitions for i386 - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 - R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, - M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, - P. Tomsich, J. Wenninger + Copyright (C) 1996-2005, 2006, 2007 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. @@ -19,15 +19,8 @@ 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. - - Contact: cacao@complang.tuwien.ac.at - - Authors: Andreas Krall - Christian Thalinger - - $Id: codegen.h 1250 2004-06-30 20:23:09Z twisti $ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ @@ -35,67 +28,22 @@ #ifndef _CODEGEN_H #define _CODEGEN_H +#include "config.h" +#include "vm/types.h" -#include -#include "jit/jit.h" - - -/* define x86 register numbers */ -#define EAX 0 -#define ECX 1 -#define EDX 2 -#define EBX 3 -#define ESP 4 -#define EBP 5 -#define ESI 6 -#define EDI 7 - - -/* preallocated registers *****************************************************/ - -/* integer registers */ - -#define REG_RESULT EAX /* to deliver method results */ -#define REG_RESULT2 EDX /* to deliver long method results */ - -#define REG_ITMP1 EAX /* temporary register */ -#define REG_ITMP2 ECX /* temporary register */ -#define REG_ITMP3 EDX /* temporary register */ - -#define REG_NULL -1 /* used for reg_of_var where d is not needed */ - -#define REG_ITMP1_XPTR EAX /* exception pointer = temporary register 1 */ -#define REG_ITMP2_XPC ECX /* exception pc = temporary register 2 */ - -#define REG_SP ESP /* stack pointer */ - -/* floating point registers */ - -#define REG_FRESULT 0 /* to deliver floating point method results */ -#define REG_FTMP1 6 /* temporary floating point register */ -#define REG_FTMP2 7 /* temporary floating point register */ -#define REG_FTMP3 7 /* temporary floating point register */ +#include "vm/jit/i386/emit.h" +#include "vm/jit/jit.h" -#define INT_SAV_CNT 3 /* number of int callee saved registers */ -#define INT_ARG_CNT 0 /* number of int argument registers */ -#define FLT_SAV_CNT 0 /* number of flt callee saved registers */ -#define FLT_ARG_CNT 0 /* number of flt argument registers */ +#if defined(ENABLE_LSRA) +/* let LSRA allocate reserved registers (REG_ITMP[1|2|3]) */ +# define LSRA_USES_REG_RES +#endif /* additional functions and macros to generate code ***************************/ -#define BlockPtrOfPC(pc) ((basicblock *) iptr->target) - - -#ifdef STATISTICS -#define COUNT_SPILLS count_spills++ -#else -#define COUNT_SPILLS -#endif - - #define CALCOFFSETBYTES(var, reg, val) \ if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \ else if ((s4) (val) != 0) (var) += 1; \ @@ -107,34 +55,44 @@ else (var) += 1; -/* gen_nullptr_check(objreg) */ - -#define gen_nullptr_check(objreg) \ - if (checknull) { \ - i386_test_reg_reg((objreg), (objreg)); \ - i386_jcc(I386_CC_E, 0); \ - codegen_addxnullrefs(mcodeptr); \ - } - -#define gen_bound_check \ - if (checkbounds) { \ - i386_alu_membase_reg(I386_CMP, s1, OFFSET(java_arrayheader, size), s2); \ - i386_jcc(I386_CC_AE, 0); \ - codegen_addxboundrefs(mcodeptr, s2); \ - } +#define ALIGNCODENOP \ + do { \ + for (s1 = 0; s1 < (s4) (((ptrint) cd->mcodeptr) & 7); s1++) \ + M_NOP; \ + } while (0) /* MCODECHECK(icnt) */ #define MCODECHECK(icnt) \ - if ((mcodeptr + (icnt)) > (u1*) mcodeend) mcodeptr = (u1*) codegen_increase((u1*) mcodeptr) + do { \ + if ((cd->mcodeptr + (icnt)) > (u1 *) cd->mcodeend) \ + codegen_increase(cd); \ + } while (0) + /* M_INTMOVE: generates an integer-move from register a to b. if a and b are the same int-register, no code will be generated. */ -#define M_INTMOVE(reg,dreg) if ((reg) != (dreg)) { i386_mov_reg_reg((reg),(dreg)); } +#define M_INTMOVE(a,b) \ + do { \ + if ((a) != (b)) \ + M_MOV(a, b); \ + } while (0) + +#define M_LNGMOVE(a,b) \ + do { \ + if (GET_HIGH_REG(a) == GET_LOW_REG(b)) { \ + assert((GET_LOW_REG(a) != GET_HIGH_REG(b))); \ + M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \ + M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \ + } else { \ + M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \ + M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \ + } \ + } while (0) /* M_FLTMOVE: @@ -142,318 +100,247 @@ if a and b are the same float-register, no code will be generated */ -#define M_FLTMOVE(reg,dreg) panic("M_FLTMOVE"); +#define M_FLTMOVE(reg,dreg) \ + do { \ + if ((reg) != (dreg)) { \ + log_text("M_FLTMOVE"); \ + assert(0); \ + } \ + } while (0) + -#define M_LNGMEMMOVE(reg,dreg) \ +#define ICONST(d,c) \ do { \ - i386_mov_membase_reg(REG_SP, (reg) * 8, REG_ITMP1); \ - i386_mov_reg_membase(REG_ITMP1, REG_SP, (dreg) * 8); \ - i386_mov_membase_reg(REG_SP, (reg) * 8 + 4, REG_ITMP1); \ - i386_mov_reg_membase(REG_ITMP1, REG_SP, (dreg) * 8 + 4); \ + if ((c) == 0) \ + M_CLR(d); \ + else \ + M_MOV_IMM((c), d); \ } while (0) -/* var_to_reg_xxx: - this function generates code to fetch data from a pseudo-register - into a real register. - If the pseudo-register has actually been assigned to a real - register, no code will be emitted, since following operations - can use this register directly. - - v: pseudoregister to be fetched from - tempregnum: temporary register to be used if v is actually spilled to ram +#define LCONST(d,c) \ + do { \ + if ((c) == 0) { \ + M_CLR(GET_LOW_REG(d)); \ + M_CLR(GET_HIGH_REG(d)); \ + } else { \ + M_MOV_IMM((c), GET_LOW_REG(d)); \ + M_MOV_IMM((c) >> 32, GET_HIGH_REG(d)); \ + } \ + } while (0) - return: the register number, where the operand can be found after - fetching (this wil be either tempregnum or the register - number allready given to v) -*/ -#define var_to_reg_int(regnr,v,tempnr) \ - if ((v)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - i386_mov_membase_reg(REG_SP, (v)->regoff * 8, tempnr); \ - regnr = tempnr; \ - } else { \ - regnr = (v)->regoff; \ - } +/* branch defines *************************************************************/ +#define BRANCH_UNCONDITIONAL_SIZE 5 /* size in bytes of a branch */ +#define BRANCH_CONDITIONAL_SIZE 6 /* size in bytes of a branch */ +#define BRANCH_NOPS \ + do { \ + M_NOP; \ + M_NOP; \ + M_NOP; \ + M_NOP; \ + M_NOP; \ + M_NOP; \ + } while (0) -#define var_to_reg_flt(regnr,v,tempnr) \ - if ((v)->type == TYPE_FLT) { \ - if ((v)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - i386_flds_membase(REG_SP, (v)->regoff * 8); \ - fpu_st_offset++; \ - regnr = tempnr; \ - } else { \ - i386_fld_reg((v)->regoff + fpu_st_offset); \ - fpu_st_offset++; \ - regnr = (v)->regoff; \ - } \ - } else { \ - if ((v)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - i386_fldl_membase(REG_SP, (v)->regoff * 8); \ - fpu_st_offset++; \ - regnr = tempnr; \ - } else { \ - i386_fld_reg((v)->regoff + fpu_st_offset); \ - fpu_st_offset++; \ - regnr = (v)->regoff; \ - } \ - } - -#define NEW_var_to_reg_flt(regnr,v,tempnr) \ - if ((v)->type == TYPE_FLT) { \ - if ((v)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - i386_flds_membase(REG_SP, (v)->regoff * 8); \ - fpu_st_offset++; \ - regnr = tempnr; \ - } else { \ - regnr = (v)->regoff; \ - } \ - } else { \ - if ((v)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - i386_fldl_membase(REG_SP, (v)->regoff * 8); \ - fpu_st_offset++; \ - regnr = tempnr; \ - } else { \ - regnr = (v)->regoff; \ - } \ - } - - -/* store_reg_to_var_xxx: - This function generates the code to store the result of an operation - back into a spilled pseudo-variable. - If the pseudo-variable has not been spilled in the first place, this - function will generate nothing. - - v ............ Pseudovariable - tempregnum ... Number of the temporary registers as returned by - reg_of_var. -*/ - -#define store_reg_to_var_int(sptr, tempregnum) \ - if ((sptr)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - i386_mov_reg_membase(tempregnum, REG_SP, (sptr)->regoff * 8); \ - } - - -#define store_reg_to_var_flt(sptr, tempregnum) \ - if ((sptr)->type == TYPE_FLT) { \ - if ((sptr)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - i386_fstps_membase(REG_SP, (sptr)->regoff * 8); \ - fpu_st_offset--; \ - } else { \ -/* i386_fxch_reg((sptr)->regoff);*/ \ - i386_fstp_reg((sptr)->regoff + fpu_st_offset); \ - fpu_st_offset--; \ - } \ - } else { \ - if ((sptr)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - i386_fstpl_membase(REG_SP, (sptr)->regoff * 8); \ - fpu_st_offset--; \ - } else { \ -/* i386_fxch_reg((sptr)->regoff);*/ \ - i386_fstp_reg((sptr)->regoff + fpu_st_offset); \ - fpu_st_offset--; \ - } \ - } +/* patcher defines ************************************************************/ -/* macros to create code ******************************************************/ +#define PATCHER_CALL_SIZE 5 /* size in bytes of a patcher call */ -typedef enum { - I386_AL = 0, - I386_CL = 1, - I386_DL = 2, - I386_BL = 3, - I386_AH = 4, - I386_CH = 5, - I386_DH = 6, - I386_BH = 7, - I386_NREGB -} I386_RegB_No; - - -/* opcodes for alu instructions */ - -typedef enum { - I386_ADD = 0, - I386_OR = 1, - I386_ADC = 2, - I386_SBB = 3, - I386_AND = 4, - I386_SUB = 5, - I386_XOR = 6, - I386_CMP = 7, - I386_NALU -} I386_ALU_Opcode; - -typedef enum { - I386_ROL = 0, - I386_ROR = 1, - I386_RCL = 2, - I386_RCR = 3, - I386_SHL = 4, - I386_SHR = 5, - I386_SAR = 7, - I386_NSHIFT = 8 -} I386_Shift_Opcode; - -typedef enum { - I386_CC_O = 0, - I386_CC_NO = 1, - I386_CC_B = 2, I386_CC_C = 2, I386_CC_NAE = 2, - I386_CC_BE = 6, I386_CC_NA = 6, - I386_CC_AE = 3, I386_CC_NB = 3, I386_CC_NC = 3, - I386_CC_E = 4, I386_CC_Z = 4, - I386_CC_NE = 5, I386_CC_NZ = 5, - I386_CC_A = 7, I386_CC_NBE = 7, - I386_CC_S = 8, I386_CC_LZ = 8, - I386_CC_NS = 9, I386_CC_GEZ = 9, - I386_CC_P = 0x0a, I386_CC_PE = 0x0a, - I386_CC_NP = 0x0b, I386_CC_PO = 0x0b, - I386_CC_L = 0x0c, I386_CC_NGE = 0x0c, - I386_CC_GE = 0x0d, I386_CC_NL = 0x0d, - I386_CC_LE = 0x0e, I386_CC_NG = 0x0e, - I386_CC_G = 0x0f, I386_CC_NLE = 0x0f, - I386_NCC -} I386_CC; - - -/* modrm and stuff */ - -#define i386_address_byte(mod, reg, rm) \ - *(mcodeptr++) = ((((mod) & 0x03) << 6) | (((reg) & 0x07) << 3) | (((rm) & 0x07))); - - -#define i386_emit_reg(reg,rm) \ - i386_address_byte(3,(reg),(rm)); - - -#define i386_is_imm8(imm) \ - (((int)(imm) >= -128 && (int)(imm) <= 127)) - - -#define i386_emit_imm8(imm) \ - *(mcodeptr++) = (u1) ((imm) & 0xff); - - -#define i386_emit_imm16(imm) \ +#define PATCHER_NOPS \ do { \ - imm_union imb; \ - imb.i = (int) (imm); \ - *(mcodeptr++) = imb.b[0]; \ - *(mcodeptr++) = imb.b[1]; \ + M_NOP; \ + M_NOP; \ + M_NOP; \ + M_NOP; \ + M_NOP; \ } while (0) -#define i386_emit_imm32(imm) \ +/* stub defines ***************************************************************/ + +#define COMPILERSTUB_CODESIZE 12 + + +/* macros to create code ******************************************************/ + +#define M_ILD(a,b,disp) emit_mov_membase_reg(cd, (b), (disp), (a)) +#define M_ILD32(a,b,disp) emit_mov_membase32_reg(cd, (b), (disp), (a)) + +#define M_ALD(a,b,disp) M_ILD(a,b,disp) +#define M_ALD32(a,b,disp) M_ILD32(a,b,disp) + +#define M_ALD_MEM(a,disp) emit_mov_mem_reg(cd, (disp), (a)) + +#define M_ALD_MEM_GET_OPC(p) (*(p)) +#define M_ALD_MEM_GET_MOD(p) (((*(p + 1)) >> 6) & 0x03) +#define M_ALD_MEM_GET_REG(p) (((*(p + 1)) >> 3) & 0x07) +#define M_ALD_MEM_GET_RM(p) (((*(p + 1)) ) & 0x07) +#define M_ALD_MEM_GET_DISP(p) (*((u4 *) (p + 2))) + +#define M_LLD(a,b,disp) \ do { \ - imm_union imb; \ - imb.i = (int) (imm); \ - *(mcodeptr++) = imb.b[0]; \ - *(mcodeptr++) = imb.b[1]; \ - *(mcodeptr++) = imb.b[2]; \ - *(mcodeptr++) = imb.b[3]; \ + M_ILD(GET_LOW_REG(a),b,disp); \ + M_ILD(GET_HIGH_REG(a),b,disp + 4); \ } while (0) - -#define i386_emit_mem(r,mem) \ +#define M_LLD32(a,b,disp) \ do { \ - i386_address_byte(0,(r),5); \ - i386_emit_imm32((mem)); \ + M_ILD32(GET_LOW_REG(a),b,disp); \ + M_ILD32(GET_HIGH_REG(a),b,disp + 4); \ } while (0) +#define M_IST(a,b,disp) emit_mov_reg_membase(cd, (a), (b), (disp)) +#define M_IST_IMM(a,b,disp) emit_mov_imm_membase(cd, (u4) (a), (b), (disp)) +#define M_AST(a,b,disp) M_IST(a,b,disp) +#define M_AST_IMM(a,b,disp) M_IST_IMM(a,b,disp) + +#define M_IST32(a,b,disp) emit_mov_reg_membase32(cd, (a), (b), (disp)) +#define M_IST32_IMM(a,b,disp) emit_mov_imm_membase32(cd, (u4) (a), (b), (disp)) -#define i386_emit_membase(basereg,disp,dreg) \ +#define M_LST(a,b,disp) \ do { \ - if ((basereg) == ESP) { \ - if ((disp) == 0) { \ - i386_address_byte(0, (dreg), ESP); \ - i386_address_byte(0, ESP, ESP); \ - } else if (i386_is_imm8((disp))) { \ - i386_address_byte(1, (dreg), ESP); \ - i386_address_byte(0, ESP, ESP); \ - i386_emit_imm8((disp)); \ - } else { \ - i386_address_byte(2, (dreg), ESP); \ - i386_address_byte(0, ESP, ESP); \ - i386_emit_imm32((disp)); \ - } \ - break; \ - } \ - \ - if ((disp) == 0 && (basereg) != EBP) { \ - i386_address_byte(0, (dreg), (basereg)); \ - break; \ - } \ - \ - if (i386_is_imm8((disp))) { \ - i386_address_byte(1, (dreg), (basereg)); \ - i386_emit_imm8((disp)); \ - } else { \ - i386_address_byte(2, (dreg), (basereg)); \ - i386_emit_imm32((disp)); \ - } \ + M_IST(GET_LOW_REG(a),b,disp); \ + M_IST(GET_HIGH_REG(a),b,disp + 4); \ } while (0) +#define M_LST32(a,b,disp) \ + do { \ + M_IST32(GET_LOW_REG(a),b,disp); \ + M_IST32(GET_HIGH_REG(a),b,disp + 4); \ + } while (0) -#define i386_emit_memindex(reg,disp,basereg,indexreg,scale) \ +#define M_LST_IMM(a,b,disp) \ do { \ - if ((basereg) == -1) { \ - i386_address_byte(0, (reg), 4); \ - i386_address_byte((scale), (indexreg), 5); \ - i386_emit_imm32((disp)); \ - \ - } else if ((disp) == 0 && (basereg) != EBP) { \ - i386_address_byte(0, (reg), 4); \ - i386_address_byte((scale), (indexreg), (basereg)); \ - \ - } else if (i386_is_imm8((disp))) { \ - i386_address_byte(1, (reg), 4); \ - i386_address_byte((scale), (indexreg), (basereg)); \ - i386_emit_imm8 ((disp)); \ - \ - } else { \ - i386_address_byte(2, (reg), 4); \ - i386_address_byte((scale), (indexreg), (basereg)); \ - i386_emit_imm32((disp)); \ - } \ - } while (0) + M_IST_IMM(a,b,disp); \ + M_IST_IMM(a >> 32,b,disp + 4); \ + } while (0) + +#define M_LST32_IMM(a,b,disp) \ + do { \ + M_IST32_IMM(a,b,disp); \ + M_IST32_IMM(a >> 32,b,disp + 4); \ + } while (0) + +#define M_IADD(a,b) emit_alu_reg_reg(cd, ALU_ADD, (a), (b)) +#define M_ISUB(a,b) emit_alu_reg_reg(cd, ALU_SUB, (a), (b)) +#define M_IMUL(a,b) emit_imul_reg_reg(cd, (a), (b)) +#define M_IDIV(a) emit_idiv_reg(cd, (a)) + +#define M_MUL(a) emit_mul_reg(cd, (a)) + +#define M_IADD_IMM(a,b) emit_alu_imm_reg(cd, ALU_ADD, (a), (b)) +#define M_ISUB_IMM(a,b) emit_alu_imm_reg(cd, ALU_SUB, (a), (b)) +#define M_IMUL_IMM(a,b,c) emit_imul_imm_reg_reg(cd, (b), (a), (c)) + +#define M_IADD_IMM32(a,b) emit_alu_imm32_reg(cd, ALU_ADD, (a), (b)) +#define M_ISUB_IMM32(a,b) emit_alu_imm32_reg(cd, ALU_SUB, (a), (b)) + +#define M_IADD_IMM_MEMBASE(a,b,c) emit_alu_imm_membase(cd, ALU_ADD, (a), (b), (c)) + +#define M_ISUB_IMM_MEMABS(a,b) emit_alu_imm_memabs(cd, ALU_SUB, (a), (b)) + +#define M_IADDC(a,b) emit_alu_reg_reg(cd, ALU_ADC, (a), (b)) +#define M_ISUBB(a,b) emit_alu_reg_reg(cd, ALU_SBB, (a), (b)) + +#define M_IADDC_IMM(a,b) emit_alu_imm_reg(cd, ALU_ADC, (a), (b)) +#define M_ISUBB_IMM(a,b) emit_alu_imm_reg(cd, ALU_SBB, (a), (b)) + +#define M_AADD_IMM(a,b) M_IADD_IMM(a,b) +#define M_AADD_IMM32(a,b) M_IADD_IMM32(a,b) +#define M_ASUB_IMM(a,b) M_ISUB_IMM(a,b) + +#define M_NEG(a) emit_neg_reg(cd, (a)) + +#define M_AND(a,b) emit_alu_reg_reg(cd, ALU_AND, (a), (b)) +#define M_OR(a,b) emit_alu_reg_reg(cd, ALU_OR, (a), (b)) +#define M_XOR(a,b) emit_alu_reg_reg(cd, ALU_XOR, (a), (b)) + +#define M_AND_IMM(a,b) emit_alu_imm_reg(cd, ALU_AND, (a), (b)) +#define M_OR_IMM(a,b) emit_alu_imm_reg(cd, ALU_OR, (a), (b)) +#define M_XOR_IMM(a,b) emit_alu_imm_reg(cd, ALU_XOR, (a), (b)) + +#define M_AND_IMM32(a,b) emit_alu_imm32_reg(cd, ALU_AND, (a), (b)) + +#define M_CLR(a) M_XOR(a,a) + +#define M_PUSH(a) emit_push_reg(cd, (a)) +#define M_PUSH_IMM(a) emit_push_imm(cd, (s4) (a)) +#define M_POP(a) emit_pop_reg(cd, (a)) + +#define M_MOV(a,b) emit_mov_reg_reg(cd, (a), (b)) +#define M_MOV_IMM(a,b) emit_mov_imm_reg(cd, (u4) (a), (b)) + +#define M_TEST(a) emit_test_reg_reg(cd, (a), (a)) +#define M_TEST_IMM(a,b) emit_test_imm_reg(cd, (a), (b)) + +#define M_CMP(a,b) emit_alu_reg_reg(cd, ALU_CMP, (a), (b)) +#define M_CMP_MEMBASE(a,b,c) emit_alu_membase_reg(cd, ALU_CMP, (a), (b), (c)) + +#define M_CMP_IMM(a,b) emit_alu_imm_reg(cd, ALU_CMP, (a), (b)) +#define M_CMP_IMM_MEMBASE(a,b,c) emit_alu_imm_membase(cd, ALU_CMP, (a), (b), (c)) + +#define M_CMP_IMM32(a,b) emit_alu_imm32_reg(cd, ALU_CMP, (a), (b)) + +#define M_BSEXT(a,b) /* XXX does not work, because of nibbles */ +#define M_SSEXT(a,b) emit_movswl_reg_reg(cd, (a), (b)) + +#define M_CZEXT(a,b) emit_movzwl_reg_reg(cd, (a), (b)) + +#define M_CLTD emit_cltd(cd) + +#define M_SLL(a) emit_shift_reg(cd, SHIFT_SHL, (a)) +#define M_SRA(a) emit_shift_reg(cd, SHIFT_SAR, (a)) +#define M_SRL(a) emit_shift_reg(cd, SHIFT_SHR, (a)) + +#define M_SLL_IMM(a,b) emit_shift_imm_reg(cd, SHIFT_SHL, (a), (b)) +#define M_SRA_IMM(a,b) emit_shift_imm_reg(cd, SHIFT_SAR, (a), (b)) +#define M_SRL_IMM(a,b) emit_shift_imm_reg(cd, SHIFT_SHR, (a), (b)) + +#define M_SLLD(a,b) emit_shld_reg_reg(cd, (a), (b)) +#define M_SRLD(a,b) emit_shrd_reg_reg(cd, (a), (b)) + +#define M_SLLD_IMM(a,b,c) emit_shld_imm_reg_reg(cd, (a), (b), (c)) +#define M_SRLD_IMM(a,b,c) emit_shrd_imm_reg_reg(cd, (a), (b), (c)) + +#define M_CALL(a) emit_call_reg(cd, (a)) +#define M_CALL_IMM(a) emit_call_imm(cd, (a)) +#define M_RET emit_ret(cd) +#define M_BEQ(a) emit_jcc(cd, CC_E, (a)) +#define M_BNE(a) emit_jcc(cd, CC_NE, (a)) +#define M_BLT(a) emit_jcc(cd, CC_L, (a)) +#define M_BLE(a) emit_jcc(cd, CC_LE, (a)) +#define M_BGE(a) emit_jcc(cd, CC_GE, (a)) +#define M_BGT(a) emit_jcc(cd, CC_G, (a)) -/* function gen_resolvebranch ************************************************** +#define M_BB(a) emit_jcc(cd, CC_B, (a)) +#define M_BBE(a) emit_jcc(cd, CC_BE, (a)) +#define M_BAE(a) emit_jcc(cd, CC_AE, (a)) +#define M_BA(a) emit_jcc(cd, CC_A, (a)) +#define M_BNS(a) emit_jcc(cd, CC_NS, (a)) +#define M_BS(a) emit_jcc(cd, CC_S, (a)) - backpatches a branch instruction +#define M_JMP(a) emit_jmp_reg(cd, (a)) +#define M_JMP_IMM(a) emit_jmp_imm(cd, (a)) - parameters: ip ... pointer to instruction after branch (void*) - so ... offset of instruction after branch (s4) - to ... offset of branch target (s4) +#define M_NOP emit_nop(cd) -*******************************************************************************/ -#define gen_resolvebranch(ip,so,to) \ - *((void **) ((ip) - 4)) = (void **) ((to) - (so)); +#define M_FLD(a,b,disp) emit_flds_membase(cd, (b), (disp)) +#define M_DLD(a,b,disp) emit_fldl_membase(cd, (b), (disp)) +#define M_FLD32(a,b,disp) emit_flds_membase32(cd, (b), (disp)) +#define M_DLD32(a,b,disp) emit_fldl_membase32(cd, (b), (disp)) -/* function prototypes */ +#define M_FST(a,b,disp) emit_fstps_membase(cd, (b), (disp)) +#define M_DST(a,b,disp) emit_fstpl_membase(cd, (b), (disp)) -void codegen_init(); -void *codegen_findmethod(void *pc); -void init_exceptions(); -void codegen(methodinfo *m); -void codegen_close(); -void dseg_display(s4 *s4ptr); -void thread_restartcriticalsection(ucontext_t*); +#define M_FSTNP(a,b,disp) emit_fsts_membase(cd, (b), (disp)) +#define M_DSTNP(a,b,disp) emit_fstl_membase(cd, (b), (disp)) #endif /* _CODEGEN_H */