1 /* src/vm/jit/i386/codegen.h - code generation macros and definitions for i386
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
32 $Id: codegen.h 2496 2005-05-23 08:06:06Z twisti $
43 /* let LSRA allocate reserved registers (REG_ITMP[1|2|3]) */
44 #define LSRA_USES_REG_RES
47 /* SET_ARG_STACKSLOTS ***************************************************
48 Macro for stack.c to set Argument Stackslots
50 Sets the first call_argcount stackslots of curstack to varkind ARGVAR, if
51 they to not have the SAVEDVAR flag set. According to the calling
52 conventions these stackslots are assigned argument registers or memory
56 i: Number of arguments for this method
57 curstack: instack of the method invokation
63 copy: Points to first stackslot after the parameters
64 rd->ifmemuse: max. number of stackslots used for spilling parameters
66 ************************************************************************/
67 #if defined(HAS_4BYTE_STACKSLOT)
68 #define SET_ARG_STACKSLOTS { \
72 stacksize+=IS_2_WORD_TYPE(copy->type)?2:1; \
77 if (stacksize > rd->ifmemuse) \
78 rd->ifmemuse = stacksize; \
80 stacksize -= IS_2_WORD_TYPE(copy->type)?2:1; \
81 if (!(copy->flags & SAVEDVAR)) { \
82 copy->varkind = ARGVAR; \
84 copy->flags |= INMEMORY; \
85 copy->regoff = stacksize; \
91 #define SET_ARG_STACKSLOTS { \
93 if (i > rd->ifmemuse) \
96 if (!(copy->flags & SAVEDVAR)) { \
97 copy->varkind = ARGVAR; \
99 copy->flags |= INMEMORY; \
105 #endif /* defined(HAS_4BYTE_STACKSLOTS) */
107 /* additional functions and macros to generate code ***************************/
109 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
113 #define COUNT_SPILLS count_spills++
119 #define CALCOFFSETBYTES(var, reg, val) \
120 if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
121 else if ((s4) (val) != 0) (var) += 1; \
122 else if ((reg) == EBP) (var) += 1;
125 #define CALCIMMEDIATEBYTES(var, val) \
126 if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
130 /* gen_nullptr_check(objreg) */
132 #define gen_nullptr_check(objreg) \
134 i386_test_reg_reg(cd, (objreg), (objreg)); \
135 i386_jcc(cd, I386_CC_E, 0); \
136 codegen_addxnullrefs(cd, cd->mcodeptr); \
139 #define gen_bound_check \
141 i386_alu_membase_reg(cd, ALU_CMP, s1, OFFSET(java_arrayheader, size), s2); \
142 i386_jcc(cd, I386_CC_AE, 0); \
143 codegen_addxboundrefs(cd, cd->mcodeptr, s2); \
146 #define gen_div_check(v) \
148 if ((v)->flags & INMEMORY) { \
149 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4); \
151 i386_test_reg_reg(cd, src->regoff, src->regoff); \
153 i386_jcc(cd, I386_CC_E, 0); \
154 codegen_addxdivrefs(cd, cd->mcodeptr); \
158 /* MCODECHECK(icnt) */
160 #define MCODECHECK(icnt) \
161 if ((cd->mcodeptr + (icnt)) > (u1 *) cd->mcodeend) \
162 cd->mcodeptr = (u1 *) codegen_increase(cd, cd->mcodeptr)
166 generates an integer-move from register a to b.
167 if a and b are the same int-register, no code will be generated.
170 #define M_INTMOVE(reg,dreg) \
171 if ((reg) != (dreg)) { \
172 i386_mov_reg_reg(cd, (reg),(dreg)); \
177 generates a floating-point-move from register a to b.
178 if a and b are the same float-register, no code will be generated
181 #define M_FLTMOVE(reg,dreg) \
183 log_text("M_FLTMOVE"); \
188 #define M_LNGMEMMOVE(reg,dreg) \
190 i386_mov_membase_reg(cd, REG_SP, (reg) * 4, REG_ITMP1); \
191 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (dreg) * 4); \
192 i386_mov_membase_reg(cd, REG_SP, (reg) * 4 + 4, REG_ITMP1); \
193 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (dreg) * 4 + 4); \
198 this function generates code to fetch data from a pseudo-register
199 into a real register.
200 If the pseudo-register has actually been assigned to a real
201 register, no code will be emitted, since following operations
202 can use this register directly.
204 v: pseudoregister to be fetched from
205 tempregnum: temporary register to be used if v is actually spilled to ram
207 return: the register number, where the operand can be found after
208 fetching (this wil be either tempregnum or the register
209 number allready given to v)
212 #define var_to_reg_int(regnr,v,tempnr) \
213 if ((v)->flags & INMEMORY) { \
215 i386_mov_membase_reg(cd, REG_SP, (v)->regoff * 4, tempnr); \
218 regnr = (v)->regoff; \
223 #define var_to_reg_flt(regnr,v,tempnr) \
224 if ((v)->type == TYPE_FLT) { \
225 if ((v)->flags & INMEMORY) { \
227 i386_flds_membase(cd, REG_SP, (v)->regoff * 4); \
231 i386_fld_reg(cd, (v)->regoff + fpu_st_offset); \
233 regnr = (v)->regoff; \
236 if ((v)->flags & INMEMORY) { \
238 i386_fldl_membase(cd, REG_SP, (v)->regoff * 4); \
242 i386_fld_reg(cd, (v)->regoff + fpu_st_offset); \
244 regnr = (v)->regoff; \
248 #define NEW_var_to_reg_flt(regnr,v,tempnr) \
249 if ((v)->type == TYPE_FLT) { \
250 if ((v)->flags & INMEMORY) { \
252 i386_flds_membase(cd, REG_SP, (v)->regoff * 4); \
256 regnr = (v)->regoff; \
259 if ((v)->flags & INMEMORY) { \
261 i386_fldl_membase(cd, REG_SP, (v)->regoff * 4); \
265 regnr = (v)->regoff; \
270 /* store_reg_to_var_xxx:
271 This function generates the code to store the result of an operation
272 back into a spilled pseudo-variable.
273 If the pseudo-variable has not been spilled in the first place, this
274 function will generate nothing.
276 v ............ Pseudovariable
277 tempregnum ... Number of the temporary registers as returned by
281 #define store_reg_to_var_int(sptr, tempregnum) \
282 if ((sptr)->flags & INMEMORY) { \
284 i386_mov_reg_membase(cd, tempregnum, REG_SP, (sptr)->regoff * 4); \
288 #define store_reg_to_var_flt(sptr, tempregnum) \
289 if ((sptr)->type == TYPE_FLT) { \
290 if ((sptr)->flags & INMEMORY) { \
292 i386_fstps_membase(cd, REG_SP, (sptr)->regoff * 4); \
295 /* i386_fxch_reg((sptr)->regoff);*/ \
296 i386_fstp_reg(cd, (sptr)->regoff + fpu_st_offset); \
300 if ((sptr)->flags & INMEMORY) { \
302 i386_fstpl_membase(cd, REG_SP, (sptr)->regoff * 4); \
305 /* i386_fxch_reg((sptr)->regoff);*/ \
306 i386_fstp_reg(cd, (sptr)->regoff + fpu_st_offset); \
312 #define M_COPY(from,to) \
313 d = reg_of_var(rd, to, REG_ITMP1); \
314 if ((from->regoff != to->regoff) || \
315 ((from->flags ^ to->flags) & INMEMORY)) { \
316 if (IS_FLT_DBL_TYPE(from->type)) { \
317 var_to_reg_flt(s1, from, d); \
318 /*M_FLTMOVE(s1, d);*/ \
319 store_reg_to_var_flt(to, d); \
321 if (!IS_2_WORD_TYPE(from->type)) { \
322 if (to->flags & INMEMORY) { \
323 if (from->flags & INMEMORY) { \
324 i386_mov_membase_reg(cd, REG_SP, from->regoff * 4, REG_ITMP1); \
325 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, to->regoff * 4); \
327 i386_mov_reg_membase(cd, from->regoff, REG_SP, to->regoff * 4); \
330 if (from->flags & INMEMORY) { \
331 i386_mov_membase_reg(cd, REG_SP, from->regoff * 4, to->regoff); \
333 i386_mov_reg_reg(cd, from->regoff, to->regoff); \
337 M_LNGMEMMOVE(from->regoff, to->regoff); \
342 /* macros to create code ******************************************************/
357 /* opcodes for alu instructions */
385 I386_CC_B = 2, I386_CC_C = 2, I386_CC_NAE = 2,
386 I386_CC_BE = 6, I386_CC_NA = 6,
387 I386_CC_AE = 3, I386_CC_NB = 3, I386_CC_NC = 3,
388 I386_CC_E = 4, I386_CC_Z = 4,
389 I386_CC_NE = 5, I386_CC_NZ = 5,
390 I386_CC_A = 7, I386_CC_NBE = 7,
391 I386_CC_S = 8, I386_CC_LZ = 8,
392 I386_CC_NS = 9, I386_CC_GEZ = 9,
393 I386_CC_P = 0x0a, I386_CC_PE = 0x0a,
394 I386_CC_NP = 0x0b, I386_CC_PO = 0x0b,
395 I386_CC_L = 0x0c, I386_CC_NGE = 0x0c,
396 I386_CC_GE = 0x0d, I386_CC_NL = 0x0d,
397 I386_CC_LE = 0x0e, I386_CC_NG = 0x0e,
398 I386_CC_G = 0x0f, I386_CC_NLE = 0x0f,
403 /* modrm and stuff */
405 #define i386_address_byte(mod,reg,rm) \
406 *(cd->mcodeptr++) = ((((mod) & 0x03) << 6) | (((reg) & 0x07) << 3) | (((rm) & 0x07)));
409 #define i386_emit_reg(reg,rm) \
410 i386_address_byte(3,(reg),(rm));
413 #define i386_is_imm8(imm) \
414 (((int)(imm) >= -128 && (int)(imm) <= 127))
417 #define i386_emit_imm8(imm) \
418 *(cd->mcodeptr++) = (u1) ((imm) & 0xff);
421 #define i386_emit_imm16(imm) \
424 imb.i = (int) (imm); \
425 *(cd->mcodeptr++) = imb.b[0]; \
426 *(cd->mcodeptr++) = imb.b[1]; \
430 #define i386_emit_imm32(imm) \
433 imb.i = (int) (imm); \
434 *(cd->mcodeptr++) = imb.b[0]; \
435 *(cd->mcodeptr++) = imb.b[1]; \
436 *(cd->mcodeptr++) = imb.b[2]; \
437 *(cd->mcodeptr++) = imb.b[3]; \
441 #define i386_emit_mem(r,mem) \
443 i386_address_byte(0,(r),5); \
444 i386_emit_imm32((mem)); \
448 #define i386_emit_membase(basereg,disp,dreg) \
450 if ((basereg) == ESP) { \
452 i386_address_byte(0, (dreg), ESP); \
453 i386_address_byte(0, ESP, ESP); \
454 } else if (i386_is_imm8((disp))) { \
455 i386_address_byte(1, (dreg), ESP); \
456 i386_address_byte(0, ESP, ESP); \
457 i386_emit_imm8((disp)); \
459 i386_address_byte(2, (dreg), ESP); \
460 i386_address_byte(0, ESP, ESP); \
461 i386_emit_imm32((disp)); \
466 if ((disp) == 0 && (basereg) != EBP) { \
467 i386_address_byte(0, (dreg), (basereg)); \
471 if (i386_is_imm8((disp))) { \
472 i386_address_byte(1, (dreg), (basereg)); \
473 i386_emit_imm8((disp)); \
475 i386_address_byte(2, (dreg), (basereg)); \
476 i386_emit_imm32((disp)); \
481 #define i386_emit_membase32(basereg,disp,dreg) \
483 if ((basereg) == ESP) { \
484 i386_address_byte(2, (dreg), ESP); \
485 i386_address_byte(0, ESP, ESP); \
486 i386_emit_imm32((disp)); \
488 i386_address_byte(2, (dreg), (basereg)); \
489 i386_emit_imm32((disp)); \
494 #define i386_emit_memindex(reg,disp,basereg,indexreg,scale) \
496 if ((basereg) == -1) { \
497 i386_address_byte(0, (reg), 4); \
498 i386_address_byte((scale), (indexreg), 5); \
499 i386_emit_imm32((disp)); \
501 } else if ((disp) == 0 && (basereg) != EBP) { \
502 i386_address_byte(0, (reg), 4); \
503 i386_address_byte((scale), (indexreg), (basereg)); \
505 } else if (i386_is_imm8((disp))) { \
506 i386_address_byte(1, (reg), 4); \
507 i386_address_byte((scale), (indexreg), (basereg)); \
508 i386_emit_imm8 ((disp)); \
511 i386_address_byte(2, (reg), 4); \
512 i386_address_byte((scale), (indexreg), (basereg)); \
513 i386_emit_imm32((disp)); \
518 /* macros to create code ******************************************************/
520 #define M_ILD(a,b,disp) i386_mov_membase_reg(cd, (b), (disp), (a))
522 #define M_IST(a,b,disp) i386_mov_reg_membase(cd, (a), (b), (disp))
524 #define M_IADD_IMM(a,b) i386_alu_imm_reg(cd, ALU_ADD, (a), (b))
525 #define M_ISUB_IMM(a,b) i386_alu_imm_reg(cd, ALU_SUB, (a), (b))
527 #define M_NOP i386_nop(cd)
530 /* function gen_resolvebranch **************************************************
532 backpatches a branch instruction
534 parameters: ip ... pointer to instruction after branch (void*)
535 so ... offset of instruction after branch (s4)
536 to ... offset of branch target (s4)
538 *******************************************************************************/
540 #define gen_resolvebranch(ip,so,to) \
541 *((void **) ((ip) - 4)) = (void **) ((to) - (so));
544 /* function prototypes */
546 void thread_restartcriticalsection(ucontext_t *);
548 #endif /* _CODEGEN_H */
552 * These are local overrides for various environment variables in Emacs.
553 * Please do not remove this and leave it at the end of the file, where
554 * Emacs will automagically detect them.
555 * ---------------------------------------------------------------------
558 * indent-tabs-mode: t