* src/vm/jit/i386/codegen.c (codegen): Changed signature to use
[cacao.git] / src / vm / jit / i386 / codegen.h
1 /* src/vm/jit/i386/codegen.h - code generation macros and definitions for i386
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
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.
14
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.
19
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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Andreas Krall
28             Christian Thalinger
29
30    Changes:
31
32    $Id: codegen.h 4702 2006-03-28 15:41:58Z twisti $
33
34 */
35
36
37 #ifndef _CODEGEN_H
38 #define _CODEGEN_H
39
40 #include "config.h"
41 #include "vm/types.h"
42
43 #include "vm/jit/jit.h"
44
45
46 #if defined(ENABLE_LSRA)
47 /* let LSRA allocate reserved registers (REG_ITMP[1|2|3]) */
48 # define LSRA_USES_REG_RES
49 #endif
50
51 /* some defines ***************************************************************/
52
53 #define PATCHER_CALL_SIZE    5          /* size in bytes of a patcher call    */
54
55
56 /* additional functions and macros to generate code ***************************/
57
58 #define CALCOFFSETBYTES(var, reg, val) \
59     if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
60     else if ((s4) (val) != 0) (var) += 1; \
61     else if ((reg) == EBP) (var) += 1;
62
63
64 #define CALCIMMEDIATEBYTES(var, val) \
65     if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
66     else (var) += 1;
67
68
69 #define ALIGNCODENOP \
70     do { \
71         for (s1 = 0; s1 < (s4) (((ptrint) cd->mcodeptr) & 7); s1++) \
72             M_NOP; \
73     } while (0)
74
75
76 /* gen_nullptr_check(objreg) */
77
78 #define gen_nullptr_check(objreg) \
79     if (checknull) { \
80         M_TEST(objreg); \
81         M_BEQ(0); \
82             codegen_add_nullpointerexception_ref(cd, cd->mcodeptr); \
83     }
84
85 #define gen_bound_check \
86     if (checkbounds) { \
87         M_CMP_MEMBASE(s1, OFFSET(java_arrayheader, size), s2); \
88         M_BAE(0); \
89         codegen_add_arrayindexoutofboundsexception_ref(cd, cd->mcodeptr, s2); \
90     }
91
92 #define gen_div_check(v) \
93     if (checknull) { \
94         if ((v)->flags & INMEMORY) \
95             M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 4); \
96         else \
97             M_TEST(src->regoff); \
98         M_BEQ(0); \
99         codegen_add_arithmeticexception_ref(cd, cd->mcodeptr); \
100     }
101
102
103 /* MCODECHECK(icnt) */
104
105 #define MCODECHECK(icnt) \
106         if ((cd->mcodeptr + (icnt)) > (u1 *) cd->mcodeend) \
107         cd->mcodeptr = (u1 *) codegen_increase(cd, cd->mcodeptr)
108
109
110 /* M_INTMOVE:
111      generates an integer-move from register a to b.
112      if a and b are the same int-register, no code will be generated.
113 */ 
114
115 #define M_INTMOVE(reg,dreg) \
116     if ((reg) != (dreg)) { \
117         i386_mov_reg_reg(cd, (reg),(dreg)); \
118     }
119
120
121 /* M_FLTMOVE:
122     generates a floating-point-move from register a to b.
123     if a and b are the same float-register, no code will be generated
124 */
125
126 #define M_FLTMOVE(reg,dreg) \
127     do { \
128         log_text("M_FLTMOVE"); \
129         assert(0); \
130     } while (0)
131
132
133 #define M_LNGMEMMOVE(reg,dreg) \
134     do { \
135         i386_mov_membase_reg(cd, REG_SP, (reg) * 4, REG_ITMP1); \
136         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (dreg) * 4); \
137         i386_mov_membase_reg(cd, REG_SP, (reg) * 4 + 4, REG_ITMP1); \
138         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (dreg) * 4 + 4); \
139     } while (0)
140
141
142 /* var_to_reg_xxx:
143     this function generates code to fetch data from a pseudo-register
144     into a real register. 
145     If the pseudo-register has actually been assigned to a real 
146     register, no code will be emitted, since following operations
147     can use this register directly.
148     
149     v: pseudoregister to be fetched from
150     tempregnum: temporary register to be used if v is actually spilled to ram
151
152     return: the register number, where the operand can be found after 
153             fetching (this wil be either tempregnum or the register
154             number allready given to v)
155 */
156
157 #define var_to_reg_int(regnr,v,tempnr) \
158     do { \
159         if ((v)->flags & INMEMORY) { \
160             COUNT_SPILLS; \
161             M_ILD(tempnr, REG_SP, (v)->regoff * 4); \
162             regnr = tempnr; \
163         } else { \
164             regnr = (v)->regoff; \
165         } \
166     } while (0)
167
168 #define var_to_reg_lng(regnr,v,tempnr) \
169     do { \
170         if ((v)->flags & INMEMORY) { \
171             COUNT_SPILLS; \
172             M_LLD(tempnr, REG_SP, (v)->regoff * 4); \
173             regnr = tempnr; \
174         } else { \
175             regnr = (v)->regoff; \
176         } \
177     } while (0)
178
179 #define var_to_reg_flt(regnr,v,tempnr) \
180     if ((v)->type == TYPE_FLT) { \
181         if ((v)->flags & INMEMORY) { \
182             COUNT_SPILLS; \
183             i386_flds_membase(cd, REG_SP, (v)->regoff * 4); \
184             fpu_st_offset++; \
185             regnr = tempnr; \
186         } else { \
187             i386_fld_reg(cd, (v)->regoff + fpu_st_offset); \
188             fpu_st_offset++; \
189             regnr = (v)->regoff; \
190         } \
191     } else { \
192         if ((v)->flags & INMEMORY) { \
193             COUNT_SPILLS; \
194             i386_fldl_membase(cd, REG_SP, (v)->regoff * 4); \
195             fpu_st_offset++; \
196             regnr = tempnr; \
197         } else { \
198             i386_fld_reg(cd, (v)->regoff + fpu_st_offset); \
199             fpu_st_offset++; \
200             regnr = (v)->regoff; \
201         } \
202     }
203
204 #define NEW_var_to_reg_flt(regnr,v,tempnr) \
205     if ((v)->type == TYPE_FLT) { \
206        if ((v)->flags & INMEMORY) { \
207             COUNT_SPILLS; \
208             i386_flds_membase(cd, REG_SP, (v)->regoff * 4); \
209             fpu_st_offset++; \
210             regnr = tempnr; \
211         } else { \
212             regnr = (v)->regoff; \
213         } \
214     } else { \
215         if ((v)->flags & INMEMORY) { \
216             COUNT_SPILLS; \
217             i386_fldl_membase(cd, REG_SP, (v)->regoff * 4); \
218             fpu_st_offset++; \
219             regnr = tempnr; \
220         } else { \
221             regnr = (v)->regoff; \
222         } \
223     }
224
225
226 /* store_reg_to_var_xxx:
227     This function generates the code to store the result of an operation
228     back into a spilled pseudo-variable.
229     If the pseudo-variable has not been spilled in the first place, this 
230     function will generate nothing.
231     
232     v ............ Pseudovariable
233     tempregnum ... Number of the temporary registers as returned by
234                    reg_of_var.
235 */      
236
237 #define store_reg_to_var_int(sptr, tempregnum) \
238     if ((sptr)->flags & INMEMORY) { \
239         COUNT_SPILLS; \
240         M_IST(tempregnum, REG_SP, (sptr)->regoff * 4); \
241     }
242
243
244 #define store_reg_to_var_lng(sptr, tempregnum) \
245     if ((sptr)->flags & INMEMORY) { \
246         COUNT_SPILLS; \
247         M_LST(tempregnum, REG_SP, (sptr)->regoff * 4); \
248     }
249
250
251 #define store_reg_to_var_flt(sptr, tempregnum) \
252     if ((sptr)->type == TYPE_FLT) { \
253         if ((sptr)->flags & INMEMORY) { \
254              COUNT_SPILLS; \
255              i386_fstps_membase(cd, REG_SP, (sptr)->regoff * 4); \
256              fpu_st_offset--; \
257         } else { \
258 /*                  i386_fxch_reg((sptr)->regoff);*/ \
259              i386_fstp_reg(cd, (sptr)->regoff + fpu_st_offset); \
260              fpu_st_offset--; \
261         } \
262     } else { \
263         if ((sptr)->flags & INMEMORY) { \
264             COUNT_SPILLS; \
265             i386_fstpl_membase(cd, REG_SP, (sptr)->regoff * 4); \
266             fpu_st_offset--; \
267         } else { \
268 /*                  i386_fxch_reg((sptr)->regoff);*/ \
269             i386_fstp_reg(cd, (sptr)->regoff + fpu_st_offset); \
270             fpu_st_offset--; \
271         } \
272     }
273
274
275 #define M_COPY(from,to) \
276     d = codegen_reg_of_var(rd, iptr->opc, (to), REG_ITMP1); \
277         if ((from->regoff != to->regoff) || \
278             ((from->flags ^ to->flags) & INMEMORY)) { \
279                 if (IS_FLT_DBL_TYPE(from->type)) { \
280                         var_to_reg_flt(s1, from, d); \
281                         /*M_FLTMOVE(s1, d);*/ \
282                         store_reg_to_var_flt(to, d); \
283                 } else { \
284             if (!IS_2_WORD_TYPE(from->type)) { \
285                 if (to->flags & INMEMORY) { \
286                      if (from->flags & INMEMORY) { \
287                          i386_mov_membase_reg(cd, REG_SP, from->regoff * 4, REG_ITMP1); \
288                          i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, to->regoff * 4); \
289                      } else { \
290                          i386_mov_reg_membase(cd, from->regoff, REG_SP, to->regoff * 4); \
291                      } \
292                 } else { \
293                      if (from->flags & INMEMORY) { \
294                          i386_mov_membase_reg(cd, REG_SP, from->regoff * 4, to->regoff); \
295                      } else { \
296                          i386_mov_reg_reg(cd, from->regoff, to->regoff); \
297                      } \
298                 } \
299             } else { \
300                 M_LNGMEMMOVE(from->regoff, to->regoff); \
301             } \
302                 } \
303         }
304
305 /* macros to create code ******************************************************/
306
307 typedef enum {
308     REG_AL = 0,
309     REG_CL = 1,
310     REG_DL = 2,
311     REG_BL = 3,
312     REG_AH = 4,
313     REG_CH = 5,
314     REG_DH = 6,
315     REG_BH = 7,
316     REG_NREGB
317 } I386_RegB_No;
318
319
320 /* opcodes for alu instructions */
321
322 typedef enum {
323     ALU_ADD = 0,
324     ALU_OR  = 1,
325     ALU_ADC = 2,
326     ALU_SBB = 3,
327     ALU_AND = 4,
328     ALU_SUB = 5,
329     ALU_XOR = 6,
330     ALU_CMP = 7,
331     ALU_NALU
332 } I386_ALU_Opcode;
333
334 typedef enum {
335     I386_ROL = 0,
336     I386_ROR = 1,
337     I386_RCL = 2,
338     I386_RCR = 3,
339     I386_SHL = 4,
340     I386_SHR = 5,
341     I386_SAR = 7,
342     I386_NSHIFT = 8
343 } I386_Shift_Opcode;
344
345 typedef enum {
346     I386_CC_O = 0,
347     I386_CC_NO = 1,
348     I386_CC_B = 2, I386_CC_C = 2, I386_CC_NAE = 2,
349     I386_CC_BE = 6, I386_CC_NA = 6,
350     I386_CC_AE = 3, I386_CC_NB = 3, I386_CC_NC = 3,
351     I386_CC_E = 4, I386_CC_Z = 4,
352     I386_CC_NE = 5, I386_CC_NZ = 5,
353     I386_CC_A = 7, I386_CC_NBE = 7,
354     I386_CC_S = 8, I386_CC_LZ = 8,
355     I386_CC_NS = 9, I386_CC_GEZ = 9,
356     I386_CC_P = 0x0a, I386_CC_PE = 0x0a,
357     I386_CC_NP = 0x0b, I386_CC_PO = 0x0b,
358     I386_CC_L = 0x0c, I386_CC_NGE = 0x0c,
359     I386_CC_GE = 0x0d, I386_CC_NL = 0x0d,
360     I386_CC_LE = 0x0e, I386_CC_NG = 0x0e,
361     I386_CC_G = 0x0f, I386_CC_NLE = 0x0f,
362     I386_NCC
363 } I386_CC;
364
365
366 /* modrm and stuff */
367
368 #define i386_address_byte(mod,reg,rm) \
369     *(cd->mcodeptr++) = ((((mod) & 0x03) << 6) | (((reg) & 0x07) << 3) | (((rm) & 0x07)));
370
371
372 #define i386_emit_reg(reg,rm) \
373     i386_address_byte(3,(reg),(rm));
374
375
376 #define i386_is_imm8(imm) \
377     (((int)(imm) >= -128 && (int)(imm) <= 127))
378
379
380 #define i386_emit_imm8(imm) \
381     *(cd->mcodeptr++) = (u1) ((imm) & 0xff);
382
383
384 #define i386_emit_imm16(imm) \
385     do { \
386         imm_union imb; \
387         imb.i = (int) (imm); \
388         *(cd->mcodeptr++) = imb.b[0]; \
389         *(cd->mcodeptr++) = imb.b[1]; \
390     } while (0)
391
392
393 #define i386_emit_imm32(imm) \
394     do { \
395         imm_union imb; \
396         imb.i = (int) (imm); \
397         *(cd->mcodeptr++) = imb.b[0]; \
398         *(cd->mcodeptr++) = imb.b[1]; \
399         *(cd->mcodeptr++) = imb.b[2]; \
400         *(cd->mcodeptr++) = imb.b[3]; \
401     } while (0)
402
403
404 #define i386_emit_mem(r,mem) \
405     do { \
406         i386_address_byte(0,(r),5); \
407         i386_emit_imm32((mem)); \
408     } while (0)
409
410
411 #define i386_emit_membase(basereg,disp,dreg) \
412     do { \
413         if ((basereg) == ESP) { \
414             if ((disp) == 0) { \
415                 i386_address_byte(0, (dreg), ESP); \
416                 i386_address_byte(0, ESP, ESP); \
417             } else if (i386_is_imm8((disp))) { \
418                 i386_address_byte(1, (dreg), ESP); \
419                 i386_address_byte(0, ESP, ESP); \
420                 i386_emit_imm8((disp)); \
421             } else { \
422                 i386_address_byte(2, (dreg), ESP); \
423                 i386_address_byte(0, ESP, ESP); \
424                 i386_emit_imm32((disp)); \
425             } \
426             break; \
427         } \
428         \
429         if ((disp) == 0 && (basereg) != EBP) { \
430             i386_address_byte(0, (dreg), (basereg)); \
431             break; \
432         } \
433         \
434         if (i386_is_imm8((disp))) { \
435             i386_address_byte(1, (dreg), (basereg)); \
436             i386_emit_imm8((disp)); \
437         } else { \
438             i386_address_byte(2, (dreg), (basereg)); \
439             i386_emit_imm32((disp)); \
440         } \
441     } while (0)
442
443
444 #define i386_emit_membase32(basereg,disp,dreg) \
445     do { \
446         if ((basereg) == ESP) { \
447             i386_address_byte(2, (dreg), ESP); \
448             i386_address_byte(0, ESP, ESP); \
449             i386_emit_imm32((disp)); \
450         } else { \
451             i386_address_byte(2, (dreg), (basereg)); \
452             i386_emit_imm32((disp)); \
453         } \
454     } while (0)
455
456
457 #define i386_emit_memindex(reg,disp,basereg,indexreg,scale) \
458     do { \
459         if ((basereg) == -1) { \
460             i386_address_byte(0, (reg), 4); \
461             i386_address_byte((scale), (indexreg), 5); \
462             i386_emit_imm32((disp)); \
463         \
464         } else if ((disp) == 0 && (basereg) != EBP) { \
465             i386_address_byte(0, (reg), 4); \
466             i386_address_byte((scale), (indexreg), (basereg)); \
467         \
468         } else if (i386_is_imm8((disp))) { \
469             i386_address_byte(1, (reg), 4); \
470             i386_address_byte((scale), (indexreg), (basereg)); \
471             i386_emit_imm8 ((disp)); \
472         \
473         } else { \
474             i386_address_byte(2, (reg), 4); \
475             i386_address_byte((scale), (indexreg), (basereg)); \
476             i386_emit_imm32((disp)); \
477         }    \
478      } while (0)
479
480
481 /* macros to create code ******************************************************/
482
483 #define M_ILD(a,b,disp)         i386_mov_membase_reg(cd, (b), (disp), (a))
484 #define M_ALD(a,b,disp)         M_ILD(a,b,disp)
485
486 #define M_ILD32(a,b,disp)       i386_mov_membase32_reg(cd, (b), (disp), (a))
487
488 #define M_LLD(a,b,disp) \
489     do { \
490         M_ILD(GET_LOW_REG(a),b,disp); \
491         M_ILD(GET_HIGH_REG(a),b,disp + 4); \
492     } while (0)
493
494 #define M_LLD32(a,b,disp) \
495     do { \
496         M_ILD32(GET_LOW_REG(a),b,disp); \
497         M_ILD32(GET_HIGH_REG(a),b,disp + 4); \
498     } while (0)
499
500 #define M_IST(a,b,disp)         i386_mov_reg_membase(cd, (a), (b), (disp))
501 #define M_IST_IMM(a,b,disp)     i386_mov_imm_membase(cd, (u4) (a), (b), (disp))
502 #define M_AST(a,b,disp)         M_IST(a,b,disp)
503 #define M_AST_IMM(a,b,disp)     M_IST_IMM(a,b,disp)
504
505 #define M_IST32(a,b,disp)       i386_mov_reg_membase32(cd, (a), (b), (disp))
506 #define M_IST32_IMM(a,b,disp)   i386_mov_imm_membase32(cd, (u4) (a), (b), (disp))
507
508 #define M_LST(a,b,disp) \
509     do { \
510         M_IST(GET_LOW_REG(a),b,disp); \
511         M_IST(GET_HIGH_REG(a),b,disp + 4); \
512     } while (0)
513
514 #define M_LST32(a,b,disp) \
515     do { \
516         M_IST32(GET_LOW_REG(a),b,disp); \
517         M_IST32(GET_HIGH_REG(a),b,disp + 4); \
518     } while (0)
519
520 #define M_LST_IMM(a,b,disp) \
521     do { \
522         M_IST_IMM(a,b,disp); \
523         M_IST_IMM(a >> 32,b,disp + 4); \
524     } while (0)
525
526 #define M_LST32_IMM(a,b,disp) \
527     do { \
528         M_IST32_IMM(a,b,disp); \
529         M_IST32_IMM(a >> 32,b,disp + 4); \
530     } while (0)
531
532 #define M_IADD_IMM(a,b)         i386_alu_imm_reg(cd, ALU_ADD, (a), (b))
533 #define M_IADD_IMM32(a,b)       i386_alu_imm32_reg(cd, ALU_ADD, (a), (b))
534 #define M_ISUB_IMM(a,b)         i386_alu_imm_reg(cd, ALU_SUB, (a), (b))
535
536 #define M_IADD_IMM_MEMBASE(a,b,c) i386_alu_imm_membase(cd, ALU_ADD, (a), (b), (c))
537
538 #define M_AADD_IMM(a,b)         M_IADD_IMM(a,b)
539 #define M_AADD_IMM32(a,b)       M_IADD_IMM32(a,b)
540 #define M_ASUB_IMM(a,b)         M_ISUB_IMM(a,b)
541
542 #define M_OR_MEMBASE(a,b,c)     i386_alu_membase_reg(cd, ALU_OR, (a), (b), (c))
543 #define M_XOR(a,b)              i386_alu_reg_reg(cd, ALU_XOR, (a), (b))
544 #define M_CLR(a)                M_XOR(a,a)
545
546 #define M_PUSH(a)               i386_push_reg(cd, (a))
547 #define M_PUSH_IMM(a)           i386_push_imm(cd, (s4) (a))
548 #define M_POP(a)                i386_pop_reg(cd, (a))
549
550 #define M_MOV(a,b)              i386_mov_reg_reg(cd, (a), (b))
551 #define M_MOV_IMM(a,b)          i386_mov_imm_reg(cd, (u4) (a), (b))
552
553 #define M_TEST(a)               i386_test_reg_reg(cd, (a), (a))
554
555 #define M_CMP(a,b)              i386_alu_reg_reg(cd, ALU_CMP, (a), (b))
556 #define M_CMP_MEMBASE(a,b,c)    i386_alu_membase_reg(cd, ALU_CMP, (a), (b), (c))
557
558 #define M_CMP_IMM_MEMBASE(a,b,c) i386_alu_imm_membase(cd, ALU_CMP, (a), (b), (c))
559
560 #define M_CALL(a)               i386_call_reg(cd, (a))
561 #define M_CALL_IMM(a)           i386_call_imm(cd, (a))
562 #define M_RET                   i386_ret(cd)
563
564 #define M_BEQ(a)                i386_jcc(cd, I386_CC_E, (a))
565 #define M_BNE(a)                i386_jcc(cd, I386_CC_NE, (a))
566 #define M_BLT(a)                i386_jcc(cd, I386_CC_L, (a))
567 #define M_BLE(a)                i386_jcc(cd, I386_CC_LE, (a))
568 #define M_BGE(a)                i386_jcc(cd, I386_CC_GE, (a))
569 #define M_BGT(a)                i386_jcc(cd, I386_CC_G, (a))
570
571 #define M_BBE(a)                i386_jcc(cd, I386_CC_BE, (a))
572 #define M_BAE(a)                i386_jcc(cd, I386_CC_AE, (a))
573
574 #define M_JMP(a)                i386_jmp_reg(cd, (a))
575 #define M_JMP_IMM(a)            i386_jmp_imm(cd, (a))
576
577 #define M_NOP                   i386_nop(cd)
578
579
580 /* function gen_resolvebranch **************************************************
581
582     backpatches a branch instruction
583
584     parameters: ip ... pointer to instruction after branch (void*)
585                 so ... offset of instruction after branch  (s4)
586                 to ... offset of branch target             (s4)
587
588 *******************************************************************************/
589
590 #define gen_resolvebranch(ip,so,to) \
591     *((void **) ((ip) - 4)) = (void **) ((to) - (so));
592
593
594 #endif /* _CODEGEN_H */
595
596
597 /*
598  * These are local overrides for various environment variables in Emacs.
599  * Please do not remove this and leave it at the end of the file, where
600  * Emacs will automagically detect them.
601  * ---------------------------------------------------------------------
602  * Local variables:
603  * mode: c
604  * indent-tabs-mode: t
605  * c-basic-offset: 4
606  * tab-width: 4
607  * End:
608  */