a9dc001211215e0a651d4f01abd672fa7b12c027
[cacao.git] / src / vm / jit / mips / codegen.h
1 /* src/vm/jit/mips/codegen.h - code generation macros and definitions for MIPS
2
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
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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Andreas Krall
28
29    $Id: codegen.h 3476 2005-10-21 12:03:33Z twisti $
30
31 */
32
33
34 #ifndef _CODEGEN_H
35 #define _CODEGEN_H
36
37 #include "config.h"
38 #include "vm/types.h"
39
40
41 /* some defines ***************************************************************/
42
43 #define PATCHER_CALL_SIZE    2 * 4      /* size in bytes of a patcher call    */
44
45
46 /* additional functions and macros to generate code ***************************/
47
48 #ifdef STATISTICS
49 #define COUNT_SPILLS count_spills++
50 #else
51 #define COUNT_SPILLS
52 #endif
53
54
55 /* gen_nullptr_check(objreg) */
56
57 #define gen_nullptr_check(objreg) \
58     if (checknull) { \
59         M_BEQZ((objreg), 0); \
60         codegen_addxnullrefs(cd, mcodeptr); \
61         M_NOP; \
62     }
63
64 #define gen_bound_check \
65     if (checkbounds) { \
66         M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size)); \
67         M_CMPULT(s2, REG_ITMP3, REG_ITMP3); \
68         M_BEQZ(REG_ITMP3, 0); \
69         codegen_addxboundrefs(cd, mcodeptr, s2); \
70         M_NOP; \
71     }
72
73 #define gen_div_check(r) \
74     M_BEQZ((r), 0); \
75     codegen_addxdivrefs(cd, mcodeptr); \
76     M_NOP;
77
78
79 /* MCODECHECK(icnt) */
80
81 #define MCODECHECK(icnt) \
82         if ((mcodeptr + (icnt)) > cd->mcodeend) \
83         mcodeptr = codegen_increase(cd, (u1 *) mcodeptr)
84
85
86 #define ALIGNCODENOP \
87     if ((int) ((long) mcodeptr & 7)) { \
88         M_NOP; \
89     }
90
91
92 /* M_INTMOVE:
93      generates an integer-move from register a to b.
94      if a and b are the same int-register, no code will be generated.
95 */ 
96
97 #define M_INTMOVE(a,b) if (a != b) { M_MOV(a, b); }
98
99
100 /* M_FLTMOVE:
101     generates a floating-point-move from register a to b.
102     if a and b are the same float-register, no code will be generated
103 */ 
104
105 #define M_FLTMOVE(a,b) if (a != b) { M_DMOV(a, b); }
106
107 #define M_TFLTMOVE(t,a,b) \
108     do { \
109         if ((a) != (b)) \
110             if ((t) == TYPE_DBL) { \
111                 M_DMOV(a,b); \
112             } else { \
113                 M_FMOV(a,b); \
114             } \
115     } while (0)
116
117 #define M_TFLD(t,a,b,disp) \
118     if ((t) == TYPE_DBL) { \
119           M_DLD(a,b,disp); \
120     } else { \
121           M_FLD(a,b,disp); \
122     }
123
124 #define M_TFST(t,a,b,disp) \
125     if ((t)==TYPE_DBL) \
126           {M_DST(a,b,disp);} \
127     else \
128           {M_FST(a,b,disp);}
129
130 #define M_CCFLTMOVE(t1,t2,a,b) \
131         if ((t1)==(t2)) \
132           {M_TFLTMOVE(t1,a,b);} \
133         else \
134           if ((t1)==TYPE_DBL) \
135                 {M_CVTDF(a,b);} \
136           else \
137                 {M_CVTFD(a,b);}
138
139 #define M_CCFLD(t1,t2,a,b,disp) \
140     if ((t1)==(t2)) \
141           {M_DLD(a,b,disp);} \
142         else { \
143           M_DLD(REG_FTMP1,b,disp); \
144           if ((t1)==TYPE_DBL) \
145             {M_CVTDF(REG_FTMP1,a);} \
146           else \
147             {M_CVTFD(REG_FTMP1,a);} \
148         }
149           
150 #define M_CCFST(t1,t2,a,b,disp) \
151     if ((t1)==(t2)) \
152           {M_DST(a,b,disp);} \
153         else { \
154           if ((t1)==TYPE_DBL) \
155             {M_CVTDF(a,REG_FTMP1);} \
156           else \
157             {M_CVTFD(a,REG_FTMP1);} \
158           M_DST(REG_FTMP1,b,disp); \
159         }
160           
161
162 /* var_to_reg_xxx:
163     this function generates code to fetch data from a pseudo-register
164     into a real register. 
165     If the pseudo-register has actually been assigned to a real 
166     register, no code will be emitted, since following operations
167     can use this register directly.
168     
169     v: pseudoregister to be fetched from
170     tempregnum: temporary register to be used if v is actually spilled to ram
171
172     return: the register number, where the operand can be found after 
173             fetching (this wil be either tempregnum or the register
174             number allready given to v)
175 */
176
177 #define var_to_reg_int(regnr,v,tempnr) { \
178         if ((v)->flags & INMEMORY) { \
179                 COUNT_SPILLS; \
180         M_LLD(tempnr, REG_SP, 8 * (v)->regoff); \
181         regnr = tempnr; \
182         } else regnr = (v)->regoff; \
183 }
184
185
186 #define var_to_reg_flt(regnr,v,tempnr) { \
187         if ((v)->flags & INMEMORY) { \
188                 COUNT_SPILLS; \
189         M_DLD(tempnr, REG_SP, 8 * (v)->regoff); \
190         regnr = tempnr; \
191         } else regnr = (v)->regoff; \
192 }
193
194
195 /* store_reg_to_var_xxx:
196     This function generates the code to store the result of an operation
197     back into a spilled pseudo-variable.
198     If the pseudo-variable has not been spilled in the first place, this 
199     function will generate nothing.
200     
201     v ............ Pseudovariable
202     tempregnum ... Number of the temporary registers as returned by
203                    reg_of_var.
204 */      
205
206 #define store_reg_to_var_int(sptr, tempregnum) {       \
207         if ((sptr)->flags & INMEMORY) {                    \
208                 COUNT_SPILLS;                                  \
209                 M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
210                 }                                              \
211         }
212
213 #define store_reg_to_var_flt(sptr, tempregnum) {       \
214         if ((sptr)->flags & INMEMORY) {                    \
215                 COUNT_SPILLS;                                  \
216                 M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
217                 }                                              \
218         }
219
220
221 #define M_COPY(from,to) \
222         d = reg_of_var(rd, to, REG_IFTMP); \
223         if ((from->regoff != to->regoff) || \
224             ((from->flags ^ to->flags) & INMEMORY)) { \
225                 if (IS_FLT_DBL_TYPE(from->type)) { \
226                         var_to_reg_flt(s1, from, d); \
227                         M_TFLTMOVE(from->type, s1, d); \
228                         store_reg_to_var_flt(to, d); \
229                 } else { \
230                         var_to_reg_int(s1, from, d); \
231                         M_INTMOVE(s1, d); \
232                         store_reg_to_var_int(to, d); \
233                 } \
234         }
235
236
237 #define ICONST(r,c) \
238     if ((c) >= -32768 && (c) <= 32767) { \
239         M_IADD_IMM(REG_ZERO, (c), (r)); \
240     } else if ((c) >= 0 && (c) <= 0xffff) { \
241         M_OR_IMM(REG_ZERO, (c), (r)); \
242     } else { \
243         disp = dseg_adds4(cd, (c)); \
244         M_ILD((r), REG_PV, disp); \
245     }
246
247 #define LCONST(r,c) \
248     if ((c) >= -32768 && (c) <= 32767) { \
249         M_LADD_IMM(REG_ZERO, (c), (r)); \
250     } else if ((c) >= 0 && (c) <= 0xffff) { \
251         M_OR_IMM(REG_ZERO, (c), (r)); \
252     } else { \
253         disp = dseg_adds8(cd, (c)); \
254         M_LLD((r), REG_PV, disp); \
255     }
256
257
258 /* macros to create code ******************************************************/
259
260 /* code generation macros operands:
261       op ..... opcode
262       fu ..... function-number
263       rs ..... register number source 1
264       rt ..... register number or constant integer source 2
265       rd ..... register number destination
266       imm .... immediate/offset
267       sa ..... shift amount
268 */
269
270
271 #define M_ITYPE(op,rs,rt,imm) \
272     *(mcodeptr++) = (((op) << 26) | ((rs) << 21) | ((rt) << 16) | ((imm) & 0xffff))
273
274 #define M_JTYPE(op,imm) \
275     *(mcodeptr++) = (((op) << 26) | ((off) & 0x3ffffff))
276
277 #define M_RTYPE(op,rs,rt,rd,sa,fu) \
278     *(mcodeptr++) = (((op) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((sa) << 6) | (fu))
279
280 #define M_FP2(fu, fmt, fs, fd)       M_RTYPE(0x11, fmt,  0, fs, fd, fu)
281 #define M_FP3(fu, fmt, fs, ft, fd)   M_RTYPE(0x11, fmt, ft, fs, fd, fu)
282
283 #define FMT_F  16
284 #define FMT_D  17
285 #define FMT_I  20
286 #define FMT_L  21
287
288
289 /* macros for all used commands (see a MIPS-manual for description) ***********/
290
291 /* load/store macros use the form OPERATION(source/dest, base, offset)        */
292
293 #define M_LDA(a,b,disp) \
294     do { \
295         s4 lo = (short) (disp); \
296         s4 hi = (short) (((disp) - lo) >> 16); \
297         if (hi == 0) { \
298             M_AADD_IMM(b,lo,a); \
299         } else { \
300             M_LUI(REG_ITMP3,hi); \
301             M_AADD_IMM(REG_ITMP3,lo,REG_ITMP3); \
302             M_AADD(REG_ITMP3,b,a); \
303         } \
304     } while (0)
305
306 #define M_BLDS(a,b,disp)        M_ITYPE(0x20,b,a,disp)          /*  8 load    */
307 #define M_BLDU(a,b,disp)        M_ITYPE(0x24,b,a,disp)          /*  8 load    */
308 #define M_SLDS(a,b,disp)        M_ITYPE(0x21,b,a,disp)          /* 16 load    */
309 #define M_SLDU(a,b,disp)        M_ITYPE(0x25,b,a,disp)          /* 16 load    */
310
311 #define M_ILD_INTERN(a,b,disp)  M_ITYPE(0x23,b,a,disp)          /* 32 load    */
312 #define M_LLD_INTERN(a,b,disp)  M_ITYPE(0x37,b,a,disp)          /* 64 load    */
313
314 #define M_ILD(a,b,disp) \
315     do { \
316         s4 lo = (short) (disp); \
317         s4 hi = (short) (((disp) - lo) >> 16); \
318         if (hi == 0) { \
319             M_ILD_INTERN(a,b,lo); \
320         } else { \
321             M_LUI(a,hi); \
322             M_AADD(b,a,a); \
323             M_ILD_INTERN(a,a,lo); \
324         } \
325     } while (0)
326
327 #define M_LLD(a,b,disp) \
328     do { \
329         s4 lo = (short) (disp); \
330         s4 hi = (short) (((disp) - lo) >> 16); \
331         if (hi == 0) { \
332             M_LLD_INTERN(a,b,lo); \
333         } else { \
334             M_LUI(a,hi); \
335             M_AADD(b,a,a); \
336             M_LLD_INTERN(a,a,lo); \
337         } \
338     } while (0)
339
340 #define M_BST(a,b,disp)         M_ITYPE(0x28,b,a,disp)          /*  8 store   */
341 #define M_SST(a,b,disp)         M_ITYPE(0x29,b,a,disp)          /* 16 store   */
342
343 #define M_IST_INTERN(a,b,disp)  M_ITYPE(0x2b,b,a,disp)          /* 32 store   */
344 #define M_LST_INTERN(a,b,disp)  M_ITYPE(0x3f,b,a,disp)          /* 64 store   */
345
346 #define M_IST(a,b,disp) \
347     do { \
348         s4 lo = (short) (disp); \
349         s4 hi = (short) (((disp) - lo) >> 16); \
350         if (hi == 0) { \
351             M_IST_INTERN(a,b,lo); \
352         } else { \
353             M_LUI(REG_ITMP3, hi); \
354             M_AADD(b, REG_ITMP3, REG_ITMP3); \
355             M_IST_INTERN(a,REG_ITMP3,lo); \
356         } \
357     } while (0)
358
359 #define M_LST(a,b,disp) \
360     do { \
361         s4 lo = (short) (disp); \
362         s4 hi = (short) (((disp) - lo) >> 16); \
363         if (hi == 0) { \
364             M_LST_INTERN(a,b,lo); \
365         } else { \
366             M_LUI(REG_ITMP3, hi); \
367             M_AADD(b, REG_ITMP3, REG_ITMP3); \
368             M_LST_INTERN(a,REG_ITMP3,lo); \
369         } \
370     } while (0)
371
372 #define M_FLD_INTERN(a,b,disp)  M_ITYPE(0x31,b,a,disp)          /* load flt   */
373 #define M_DLD_INTERN(a,b,disp)  M_ITYPE(0x35,b,a,disp)          /* load dbl   */
374
375 #define M_FLD(a,b,disp) \
376     do { \
377         s4 lo = (short) (disp); \
378         s4 hi = (short) (((disp) - lo) >> 16); \
379         if (hi == 0) { \
380             M_FLD_INTERN(a,b,lo); \
381         } else { \
382             M_LUI(REG_ITMP3,hi); \
383             M_AADD(b,REG_ITMP3,REG_ITMP3); \
384             M_FLD_INTERN(a,REG_ITMP3,lo); \
385         } \
386     } while (0)
387
388 #define M_DLD(a,b,disp) \
389     do { \
390         s4 lo = (short) (disp); \
391         s4 hi = (short) (((disp) - lo) >> 16); \
392         if (hi == 0) { \
393             M_DLD_INTERN(a,b,lo); \
394         } else { \
395             M_LUI(REG_ITMP3,hi); \
396             M_AADD(b,REG_ITMP3,REG_ITMP3); \
397             M_DLD_INTERN(a,REG_ITMP3,lo); \
398         } \
399     } while (0)
400
401 #define M_FST_INTERN(a,b,disp)  M_ITYPE(0x39,b,a,disp)          /* store flt  */
402 #define M_DST_INTERN(a,b,disp)  M_ITYPE(0x3d,b,a,disp)          /* store dbl  */
403
404 #define M_FST(a,b,disp) \
405     do { \
406         s4 lo = (short) (disp); \
407         s4 hi = (short) (((disp) - lo) >> 16); \
408         if (hi == 0) { \
409             M_FST_INTERN(a,b,lo); \
410         } else { \
411             M_LUI(REG_ITMP3, hi); \
412             M_AADD(b, REG_ITMP3, REG_ITMP3); \
413             M_FST_INTERN(a,REG_ITMP3,lo); \
414         } \
415     } while (0)
416
417 #define M_DST(a,b,disp) \
418     do { \
419         s4 lo = (short) (disp); \
420         s4 hi = (short) (((disp) - lo) >> 16); \
421         if (hi == 0) { \
422             M_DST_INTERN(a,b,lo); \
423         } else { \
424             M_LUI(REG_ITMP3, hi); \
425             M_AADD(b, REG_ITMP3, REG_ITMP3); \
426             M_DST_INTERN(a,REG_ITMP3,lo); \
427         } \
428     } while (0)
429
430 #define M_BEQ(a,b,disp)         M_ITYPE(0x04,a,b,disp)          /* br a == b  */
431 #define M_BNE(a,b,disp)         M_ITYPE(0x05,a,b,disp)          /* br a != b  */
432 #define M_BEQZ(a,disp)          M_ITYPE(0x04,a,0,disp)          /* br a == 0  */
433 #define M_BLTZ(a,disp)          M_ITYPE(0x01,a,0,disp)          /* br a <  0  */
434 #define M_BLEZ(a,disp)          M_ITYPE(0x06,a,0,disp)          /* br a <= 0  */
435 #define M_BNEZ(a,disp)          M_ITYPE(0x05,a,0,disp)          /* br a != 0  */
436 #define M_BGEZ(a,disp)          M_ITYPE(0x01,a,1,disp)          /* br a >= 0  */
437 #define M_BGTZ(a,disp)          M_ITYPE(0x07,a,0,disp)          /* br a >  0  */
438
439 #define M_BEQL(a,b,disp)        M_ITYPE(0x14,a,b,disp)          /* br a == b  */
440 #define M_BNEL(a,b,disp)        M_ITYPE(0x15,a,b,disp)          /* br a != b  */
441 #define M_BEQZL(a,disp)         M_ITYPE(0x14,a,0,disp)          /* br a == 0  */
442 #define M_BLTZL(a,disp)         M_ITYPE(0x01,a,2,disp)          /* br a <  0  */
443 #define M_BLEZL(a,disp)         M_ITYPE(0x16,a,0,disp)          /* br a <= 0  */
444 #define M_BNEZL(a,disp)         M_ITYPE(0x15,a,0,disp)          /* br a != 0  */
445 #define M_BGEZL(a,disp)         M_ITYPE(0x01,a,3,disp)          /* br a >= 0  */
446 #define M_BGTZL(a,disp)         M_ITYPE(0x17,a,0,disp)          /* br a >  0  */
447
448 #define M_BR(disp)              M_ITYPE(0x04,0,0,disp)          /* branch     */
449 #define M_BRS(disp)             M_ITYPE(0x01,0,17,disp)         /* branch sbr */
450
451 #define M_JMP(a)                M_RTYPE(0,a,0,0,0,0x08)         /* jump       */
452 #define M_JSR(r,a)              M_RTYPE(0,a,0,r,0,0x09)         /* call       */
453 #define M_RET(a)                M_RTYPE(0,a,0,0,0,0x08)         /* return     */
454
455 #define M_TGE(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x30)  /* trp a >= b */
456 #define M_TGEU(a,b,code)        M_RTYPE(0,a,b,0,code&3ff,0x31)  /* trp a >= b */
457 #define M_TLT(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x32)  /* trp a <  b */
458 #define M_TLTU(a,b,code)        M_RTYPE(0,a,b,0,code&3ff,0x33)  /* trp a <  b */
459 #define M_TEQ(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x34)  /* trp a == b */
460 #define M_TNE(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x36)  /* trp a != b */
461 #define M_TLE(a,b,code)         M_RTYPE(0,b,a,0,code&3ff,0x30)  /* trp a <= b */
462 #define M_TLEU(a,b,code)        M_RTYPE(0,b,a,0,code&3ff,0x31)  /* trp a <= b */
463 #define M_TGT(a,b,code)         M_RTYPE(0,b,a,0,code&3ff,0x32)  /* trp a >  b */
464 #define M_TGTU(a,b,code)        M_RTYPE(0,b,a,0,code&3ff,0x33)  /* trp a >  b */
465
466 #define M_TGE_IMM(a,b)          M_ITYPE(1,a,0x08,b)             /* trp a >= b */
467 #define M_TGEU_IMM(a,b)         M_ITYPE(1,a,0x09,b)             /* trp a >= b */
468 #define M_TLT_IMM(a,b)          M_ITYPE(1,a,0x0a,b)             /* trp a <  b */
469 #define M_TLTU_IMM(a,b)         M_ITYPE(1,a,0x0b,b)             /* trp a <  b */
470 #define M_TEQ_IMM(a,b)          M_ITYPE(1,a,0x0c,b)             /* trp a == b */
471 #define M_TNE_IMM(a,b)          M_ITYPE(1,a,0x0e,b)             /* trp a != b */
472 #if 0
473 #define M_TGT_IMM(a,b)          M_ITYPE(1,a,0x08,b+1)           /* trp a >  b */
474 #define M_TGTU_IMM(a,b)         M_ITYPE(1,a,0x09,b+1)           /* trp a >  b */
475 #define M_TLE_IMM(a,b)          M_ITYPE(1,a,0x0a,b+1)           /* trp a <= b */
476 #define M_TLEU_IMM(a,b)         M_ITYPE(1,a,0x0b,b+1)           /* trp a <= b */
477 #endif
478
479 /* arithmetic macros use the form OPERATION(source, source/immediate, dest)   */
480
481 #define M_IADD(a,b,c)           M_RTYPE(0,a,b,c,0,0x21)         /* 32 add     */
482 #define M_LADD(a,b,c)           M_RTYPE(0,a,b,c,0,0x2d)         /* 64 add     */
483 #define M_ISUB(a,b,c)           M_RTYPE(0,a,b,c,0,0x23)         /* 32 sub     */
484 #define M_LSUB(a,b,c)           M_RTYPE(0,a,b,c,0,0x2f)         /* 64 sub     */
485 #define M_IMUL(a,b)             M_ITYPE(0,a,b,0x18)             /* 32 mul     */
486 #define M_LMUL(a,b)             M_ITYPE(0,a,b,0x1c)             /* 64 mul     */
487 #define M_IDIV(a,b)             M_ITYPE(0,a,b,0x1a)             /* 32 div     */
488 #define M_LDIV(a,b)             M_ITYPE(0,a,b,0x1e)             /* 64 div     */
489
490 #define M_MFLO(a)               M_RTYPE(0,0,0,a,0,0x12)         /* quotient   */
491 #define M_MFHI(a)               M_RTYPE(0,0,0,a,0,0x10)         /* remainder  */
492
493 #define M_IADD_IMM(a,b,c)       M_ITYPE(0x09,a,c,b)             /* 32 add     */
494 #define M_LADD_IMM(a,b,c)       M_ITYPE(0x19,a,c,b)             /* 64 add     */
495 #define M_ISUB_IMM(a,b,c)       M_ITYPE(0x09,a,c,-(b))          /* 32 sub     */
496 #define M_LSUB_IMM(a,b,c)       M_ITYPE(0x19,a,c,-(b))          /* 64 sub     */
497
498 #define M_LUI(a,imm)            M_ITYPE(0x0f,0,a,imm)           /* a = imm<<16*/
499
500 #define M_CMPLT(a,b,c)          M_RTYPE(0,a,b,c,0,0x2a)         /* c = a <  b */
501 #define M_CMPGT(a,b,c)          M_RTYPE(0,b,a,c,0,0x2a)         /* c = a >  b */
502
503 #define M_CMPULT(a,b,c)         M_RTYPE(0,a,b,c,0,0x2b)         /* c = a <  b */
504 #define M_CMPUGT(a,b,c)         M_RTYPE(0,b,a,c,0,0x2b)         /* c = a >  b */
505
506 #define M_CMPLT_IMM(a,b,c)      M_ITYPE(0x0a,a,c,b)             /* c = a <  b */
507 #define M_CMPULT_IMM(a,b,c)     M_ITYPE(0x0b,a,c,b)             /* c = a <  b */
508
509 #define M_AND(a,b,c)            M_RTYPE(0,a,b,c,0,0x24)         /* c = a &  b */
510 #define M_OR( a,b,c)            M_RTYPE(0,a,b,c,0,0x25)         /* c = a |  b */
511 #define M_XOR(a,b,c)            M_RTYPE(0,a,b,c,0,0x26)         /* c = a ^  b */
512
513 #define M_AND_IMM(a,b,c)        M_ITYPE(0x0c,a,c,b)             /* c = a &  b */
514 #define M_OR_IMM( a,b,c)        M_ITYPE(0x0d,a,c,b)             /* c = a |  b */
515 #define M_XOR_IMM(a,b,c)        M_ITYPE(0x0e,a,c,b)             /* c = a ^  b */
516
517 #define M_CZEXT(a,c)            M_AND_IMM(a,0xffff,c)           /* c = zext(a)*/
518
519 #define M_ISLL(a,b,c)           M_RTYPE(0,b,a,c,0,0x04)         /* c = a << b */
520 #define M_ISRL(a,b,c)           M_RTYPE(0,b,a,c,0,0x06)         /* c = a >>>b */
521 #define M_ISRA(a,b,c)           M_RTYPE(0,b,a,c,0,0x07)         /* c = a >> b */
522 #define M_LSLL(a,b,c)           M_RTYPE(0,b,a,c,0,0x14)         /* c = a << b */
523 #define M_LSRL(a,b,c)           M_RTYPE(0,b,a,c,0,0x16)         /* c = a >>>b */
524 #define M_LSRA(a,b,c)           M_RTYPE(0,b,a,c,0,0x17)         /* c = a >> b */
525
526 #define M_ISLL_IMM(a,b,c)       M_RTYPE(0,0,a,c,(b)&31,0x00)    /* c = a << b */
527 #define M_ISRL_IMM(a,b,c)       M_RTYPE(0,0,a,c,(b)&31,0x02)    /* c = a >>>b */
528 #define M_ISRA_IMM(a,b,c)       M_RTYPE(0,0,a,c,(b)&31,0x03)    /* c = a >> b */
529 #define M_LSLL_IMM(a,b,c) M_RTYPE(0,0,a,c,(b)&31,0x38+((b)>>3&4)) /*c = a << b*/
530 #define M_LSRL_IMM(a,b,c) M_RTYPE(0,0,a,c,(b)&31,0x3a+((b)>>3&4)) /*c = a >>>b*/
531 #define M_LSRA_IMM(a,b,c) M_RTYPE(0,0,a,c,(b)&31,0x3b+((b)>>3&4)) /*c = a >> b*/
532
533 #define M_MOV(a,c)              M_OR(a,0,c)                     /* c = a      */
534 #define M_CLR(c)                M_OR(0,0,c)                     /* c = 0      */
535 #define M_NOP                   M_ISLL_IMM(0,0,0)               /* ;          */
536
537 /* floating point macros use the form OPERATION(source, source, dest)         */
538
539 #define M_FADD(a,b,c)           M_FP3(0x00,FMT_F,a,b,c)         /* flt add    */
540 #define M_DADD(a,b,c)           M_FP3(0x00,FMT_D,a,b,c)         /* dbl add    */
541 #define M_FSUB(a,b,c)           M_FP3(0x01,FMT_F,a,b,c)         /* flt sub    */
542 #define M_DSUB(a,b,c)           M_FP3(0x01,FMT_D,a,b,c)         /* dbl sub    */
543 #define M_FMUL(a,b,c)           M_FP3(0x02,FMT_F,a,b,c)         /* flt mul    */
544 #define M_DMUL(a,b,c)           M_FP3(0x02,FMT_D,a,b,c)         /* dbl mul    */
545 #define M_FDIV(a,b,c)           M_FP3(0x03,FMT_F,a,b,c)         /* flt div    */
546 #define M_DDIV(a,b,c)           M_FP3(0x03,FMT_D,a,b,c)         /* dbl div    */
547
548 #define M_FSQRT(a,c)            M_FP2(0x04,FMT_F,a,c)           /* flt sqrt   */
549 #define M_DSQRT(a,c)            M_FP2(0x04,FMT_D,a,c)           /* dbl sqrt   */
550 #define M_FABS(a,c)             M_FP2(0x05,FMT_F,a,c)           /* flt abs    */
551 #define M_DABS(a,c)             M_FP2(0x05,FMT_D,a,c)           /* dbl abs    */
552 #define M_FMOV(a,c)             M_FP2(0x06,FMT_F,a,c)           /* flt mov    */
553 #define M_DMOV(a,c)             M_FP2(0x06,FMT_D,a,c)           /* dbl mov    */
554 #define M_FNEG(a,c)             M_FP2(0x07,FMT_F,a,c)           /* flt neg    */
555 #define M_DNEG(a,c)             M_FP2(0x07,FMT_D,a,c)           /* dbl neg    */
556
557 #define M_ROUNDFI(a,c)          M_FP2(0x0c,FMT_F,a,c)           /* flt roundi */
558 #define M_ROUNDDI(a,c)          M_FP2(0x0c,FMT_D,a,c)           /* dbl roundi */
559 #define M_TRUNCFI(a,c)          M_FP2(0x0d,FMT_F,a,c)           /* flt trunci */
560 #define M_TRUNCDI(a,c)          M_FP2(0x0d,FMT_D,a,c)           /* dbl trunci */
561 #define M_CEILFI(a,c)           M_FP2(0x0e,FMT_F,a,c)           /* flt ceili  */
562 #define M_CEILDI(a,c)           M_FP2(0x0e,FMT_D,a,c)           /* dbl ceili  */
563 #define M_FLOORFI(a,c)          M_FP2(0x0f,FMT_F,a,c)           /* flt trunci */
564 #define M_FLOORDI(a,c)          M_FP2(0x0f,FMT_D,a,c)           /* dbl trunci */
565
566 #define M_ROUNDFL(a,c)          M_FP2(0x08,FMT_F,a,c)           /* flt roundl */
567 #define M_ROUNDDL(a,c)          M_FP2(0x08,FMT_D,a,c)           /* dbl roundl */
568 #define M_TRUNCFL(a,c)          M_FP2(0x09,FMT_F,a,c)           /* flt truncl */
569 #define M_TRUNCDL(a,c)          M_FP2(0x09,FMT_D,a,c)           /* dbl truncl */
570 #define M_CEILFL(a,c)           M_FP2(0x0a,FMT_F,a,c)           /* flt ceill  */
571 #define M_CEILDL(a,c)           M_FP2(0x0a,FMT_D,a,c)           /* dbl ceill  */
572 #define M_FLOORFL(a,c)          M_FP2(0x0b,FMT_F,a,c)           /* flt truncl */
573 #define M_FLOORDL(a,c)          M_FP2(0x0b,FMT_D,a,c)           /* dbl truncl */
574
575 #define M_CVTDF(a,c)            M_FP2(0x20,FMT_D,a,c)           /* dbl2flt    */
576 #define M_CVTIF(a,c)            M_FP2(0x20,FMT_I,a,c)           /* int2flt    */
577 #define M_CVTLF(a,c)            M_FP2(0x20,FMT_L,a,c)           /* long2flt   */
578 #define M_CVTFD(a,c)            M_FP2(0x21,FMT_F,a,c)           /* flt2dbl    */
579 #define M_CVTID(a,c)            M_FP2(0x21,FMT_I,a,c)           /* int2dbl    */
580 #define M_CVTLD(a,c)            M_FP2(0x21,FMT_L,a,c)           /* long2dbl   */
581 #define M_CVTFI(a,c)            M_FP2(0x24,FMT_F,a,c)           /* flt2int    */
582 #define M_CVTDI(a,c)            M_FP2(0x24,FMT_D,a,c)           /* dbl2int    */
583 #define M_CVTFL(a,c)            M_FP2(0x25,FMT_F,a,c)           /* flt2long   */
584 #define M_CVTDL(a,c)            M_FP2(0x25,FMT_D,a,c)           /* dbl2long   */
585
586 #define M_MOVDI(d,i)            M_FP3(0,0,d,i,0)                /* i = d      */
587 #define M_MOVDL(d,l)            M_FP3(0,1,d,l,0)                /* l = d      */
588 #define M_MOVID(i,d)            M_FP3(0,4,d,i,0)                /* d = i      */
589 #define M_MOVLD(l,d)            M_FP3(0,5,d,l,0)                /* d = l      */
590
591 #define M_DMFC1(l,f)            M_FP3(0,1,f,l,0)
592 #define M_DMTC1(l,f)            M_FP3(0,5,f,l,0)
593
594 #define M_FCMPFF(a,b)           M_FP3(0x30,FMT_F,a,b,0)         /* c = a == b */
595 #define M_FCMPFD(a,b)           M_FP3(0x30,FMT_D,a,b,0)         /* c = a == b */
596 #define M_FCMPUNF(a,b)          M_FP3(0x31,FMT_F,a,b,0)         /* c = a == b */
597 #define M_FCMPUND(a,b)          M_FP3(0x31,FMT_D,a,b,0)         /* c = a == b */
598 #define M_FCMPEQF(a,b)          M_FP3(0x32,FMT_F,a,b,0)         /* c = a == b */
599 #define M_FCMPEQD(a,b)          M_FP3(0x32,FMT_D,a,b,0)         /* c = a == b */
600 #define M_FCMPUEQF(a,b)         M_FP3(0x33,FMT_F,a,b,0)         /* c = a == b */
601 #define M_FCMPUEQD(a,b)         M_FP3(0x33,FMT_D,a,b,0)         /* c = a == b */
602 #define M_FCMPOLTF(a,b)         M_FP3(0x34,FMT_F,a,b,0)         /* c = a <  b */
603 #define M_FCMPOLTD(a,b)         M_FP3(0x34,FMT_D,a,b,0)         /* c = a <  b */
604 #define M_FCMPULTF(a,b)         M_FP3(0x35,FMT_F,a,b,0)         /* c = a <  b */
605 #define M_FCMPULTD(a,b)         M_FP3(0x35,FMT_D,a,b,0)         /* c = a <  b */
606 #define M_FCMPOLEF(a,b)         M_FP3(0x36,FMT_F,a,b,0)         /* c = a <= b */
607 #define M_FCMPOLED(a,b)         M_FP3(0x36,FMT_D,a,b,0)         /* c = a <= b */
608 #define M_FCMPULEF(a,b)         M_FP3(0x37,FMT_F,a,b,0)         /* c = a <= b */
609 #define M_FCMPULED(a,b)         M_FP3(0x37,FMT_D,a,b,0)         /* c = a <= b */
610
611 #define M_FBF(disp)             M_ITYPE(0x11,8,0,disp)          /* br false   */
612 #define M_FBT(disp)             M_ITYPE(0x11,8,1,disp)          /* br true    */
613 #define M_FBFL(disp)            M_ITYPE(0x11,8,2,disp)          /* br false   */
614 #define M_FBTL(disp)            M_ITYPE(0x11,8,3,disp)          /* br true    */
615
616 #define M_CMOVF(a,b)                    M_RTYPE(0x00,a,0,b,0,1)
617 #define M_CMOVT(a,b)                    M_RTYPE(0x00,a,1,b,0,1)
618
619
620 /*
621  * Load Address pseudo instruction:
622  * -n32 addressing mode -> 32 bit addrs, -64 addressing mode -> 64 bit addrs
623  */
624 #if SIZEOF_VOID_P == 8
625
626 #define POINTERSHIFT 3
627
628 #define M_ALD_INTERN(a,b,disp)  M_LLD_INTERN(a,b,disp)
629 #define M_ALD(a,b,disp)         M_LLD(a,b,disp)
630 #define M_AST_INTERN(a,b,disp)  M_LST_INTERN(a,b,disp)
631 #define M_AST(a,b,disp)         M_LST(a,b,disp)
632 #define M_AADD(a,b,c)           M_LADD(a,b,c)
633 #define M_AADD_IMM(a,b,c)       M_LADD_IMM(a,b,c)
634 #define M_ASUB_IMM(a,b,c)       M_LSUB_IMM(a,b,c)
635 #define M_ASLL_IMM(a,b,c)       M_LSLL_IMM(a,b,c)
636
637 #else /* SIZEOF_VOID_P == 8 */
638
639 #define POINTERSHIFT 2
640
641 #define M_ALD_INTERN(a,b,disp)  M_ILD_INTERN(a,b,disp)
642 #define M_ALD(a,b,disp)         M_ILD(a,b,disp)
643 #define M_AST_INTERN(a,b,disp)  M_IST_INTERN(a,b,disp)
644 #define M_AST(a,b,disp)         M_IST(a,b,disp)
645 #define M_AADD(a,b,c)           M_IADD(a,b,c)
646 #define M_AADD_IMM(a,b,c)       M_IADD_IMM(a,b,c)
647 #define M_ASUB_IMM(a,b,c)       M_ISUB_IMM(a,b,c)
648 #define M_ASLL_IMM(a,b,c)       M_ISLL_IMM(a,b,c)
649
650 #endif /* SIZEOF_VOID_P == 8 */
651
652
653 /* function gen_resolvebranch **************************************************
654
655         backpatches a branch instruction; MIPS branch instructions are very
656         regular, so it is only necessary to overwrite some fixed bits in the
657         instruction.
658
659         parameters: ip ... pointer to instruction after branch (void*)
660                     so ... offset of instruction after branch  (s4)
661                     to ... offset of branch target             (s4)
662
663 *******************************************************************************/
664
665 #define gen_resolvebranch(ip,so,to) \
666     do { \
667         s4 offset; \
668         \
669         offset = ((s4) (to) - (so)) >> 2; \
670         \
671         /* On the MIPS we can only branch signed 16-bit instruction words */ \
672         /* (signed 18-bit = 32KB = +/- 16KB). Check this!                 */ \
673         \
674         if ((offset < (s4) 0xffff8000) || (offset > (s4) 0x00007fff)) { \
675             throw_cacao_exception_exit(string_java_lang_InternalError, \
676                                        "Jump offset is out of range: %d > +/-%d", \
677                                        offset, 0x00007fff); \
678         } \
679         \
680         ((s4 *) (ip))[-1] |= (offset & 0x0000ffff); \
681     } while (0)
682
683
684 /* function prototypes ********************************************************/
685
686 void docacheflush(u1 *p, long bytelen);
687
688 #endif /* _CODEGEN_H */
689
690
691 /*
692  * These are local overrides for various environment variables in Emacs.
693  * Please do not remove this and leave it at the end of the file, where
694  * Emacs will automagically detect them.
695  * ---------------------------------------------------------------------
696  * Local variables:
697  * mode: c
698  * indent-tabs-mode: t
699  * c-basic-offset: 4
700  * tab-width: 4
701  * End:
702  */