Reentrant compiler changes.
[cacao.git] / src / vm / jit / mips / codegen.h
1 /* jit/mips/codegen.h - code generation macros and definitions for mips
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    Institut f. Computersprachen, TU Wien
5    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
6    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
7    P. Tomsich, J. Wenninger
8
9    This file is part of CACAO.
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2, or (at
14    your option) any later version.
15
16    This program is distributed in the hope that it will be useful, but
17    WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24    02111-1307, USA.
25
26    Contact: cacao@complang.tuwien.ac.at
27
28    Authors: Andreas Krall
29
30    $Id: codegen.h 1349 2004-07-22 12:08:29Z twisti $
31
32 */
33
34
35 #ifndef _CODEGEN_H
36 #define _CODEGEN_H
37
38 #include "jit/jit.h"
39
40
41 /* see also file calling.doc for explanation of calling conventions           */
42
43 /* preallocated registers *****************************************************/
44
45 /* integer registers */
46   
47 #define REG_ZERO        0    /* allways zero                                  */
48
49 #define REG_RESULT      2    /* to deliver method results                     */ 
50
51 #define REG_ITMP1       1    /* temporary register                            */
52 #define REG_ITMP2       3    /* temporary register and method pointer         */
53 #define REG_ITMP3       25   /* temporary register                            */
54
55 #define REG_ARG_0       4    /* argument register                             */
56 #define REG_ARG_1       5    /* argument register                             */
57 #define REG_ARG_2       6    /* argument register                             */
58 #define REG_ARG_3       7    /* argument register                             */
59 #define REG_ARG_4       8    /* argument register                             */
60 #define REG_ARG_5       9    /* argument register                             */
61
62 #define REG_RA          31   /* return address                                */
63 #define REG_SP          29   /* stack pointer                                 */
64 #define REG_GP          28   /* global pointer                                */
65
66 #define REG_PV          30   /* procedure vector, must be provided by caller  */
67 #define REG_METHODPTR   25   /* pointer to the place from where the procedure */
68                              /* vector has been fetched                       */
69 #define REG_ITMP1_XPTR  1    /* exception pointer = temporary register 1      */
70 #define REG_ITMP2_XPC   3    /* exception pc = temporary register 2           */
71
72 /* floating point registers */
73
74 #define REG_FRESULT     0    /* to deliver floating point method results      */ 
75 #define REG_FTMP1       1    /* temporary floating point register             */
76 #define REG_FTMP2       2    /* temporary floating point register             */
77 #define REG_FTMP3       3    /* temporary floating point register             */
78
79 #define REG_IFTMP       1    /* temporary integer and floating point register */
80
81
82 #define INT_SAV_CNT      8   /* number of int callee saved registers          */
83 #define INT_ARG_CNT      8   /* number of int argument registers              */
84
85 #define FLT_SAV_CNT      4   /* number of flt callee saved registers          */
86 #define FLT_ARG_CNT      8   /* number of flt argument registers              */
87
88
89 /* additional functions and macros to generate code ***************************/
90
91 /* #define BlockPtrOfPC(pc)        block+block_index[pc] */
92 #define BlockPtrOfPC(pc)  ((basicblock *) iptr->target)
93
94
95 #ifdef STATISTICS
96 #define COUNT_SPILLS count_spills++
97 #else
98 #define COUNT_SPILLS
99 #endif
100
101
102 /* gen_nullptr_check(objreg) */
103
104 #define gen_nullptr_check(objreg) \
105     if (checknull) { \
106         M_BEQZ((objreg), 0); \
107         codegen_addxnullrefs(m, mcodeptr); \
108         M_NOP; \
109     }
110
111 #define gen_bound_check \
112     if (checkbounds) { \
113         M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size)); \
114         M_CMPULT(s2, REG_ITMP3, REG_ITMP3); \
115         M_BEQZ(REG_ITMP3, 0); \
116         codegen_addxboundrefs(m, mcodeptr, s2); \
117         M_NOP; \
118     }
119
120
121 /* MCODECHECK(icnt) */
122
123 #define MCODECHECK(icnt) \
124         if ((mcodeptr + (icnt)) > cd->mcodeend) \
125         mcodeptr = codegen_increase(m, (u1 *) mcodeptr)
126
127 /* M_INTMOVE:
128      generates an integer-move from register a to b.
129      if a and b are the same int-register, no code will be generated.
130 */ 
131
132 #define M_INTMOVE(a,b) if (a != b) { M_MOV(a, b); }
133
134
135 /* M_FLTMOVE:
136     generates a floating-point-move from register a to b.
137     if a and b are the same float-register, no code will be generated
138 */ 
139
140 #define M_FLTMOVE(a,b) if (a != b) { M_DMOV(a, b); }
141
142 #define M_TFLTMOVE(t,a,b) \
143         {if(a!=b) \
144                 if ((t)==TYPE_DBL) \
145                     {M_DMOV(a,b);} \
146                 else {M_FMOV(a,b);} \
147         }
148
149 #define M_TFLD(t,a,b,disp) \
150     if ((t)==TYPE_DBL) \
151           {M_DLD(a,b,disp);} \
152     else \
153           {M_FLD(a,b,disp);}
154
155 #define M_TFST(t,a,b,disp) \
156     if ((t)==TYPE_DBL) \
157           {M_DST(a,b,disp);} \
158     else \
159           {M_FST(a,b,disp);}
160
161 #define M_CCFLTMOVE(t1,t2,a,b) \
162         if ((t1)==(t2)) \
163           {M_TFLTMOVE(t1,a,b);} \
164         else \
165           if ((t1)==TYPE_DBL) \
166                 {M_CVTDF(a,b);} \
167           else \
168                 {M_CVTFD(a,b);}
169
170 #define M_CCFLD(t1,t2,a,b,disp) \
171     if ((t1)==(t2)) \
172           {M_DLD(a,b,disp);} \
173         else { \
174           M_DLD(REG_FTMP1,b,disp); \
175           if ((t1)==TYPE_DBL) \
176             {M_CVTDF(REG_FTMP1,a);} \
177           else \
178             {M_CVTFD(REG_FTMP1,a);} \
179         }
180           
181 #define M_CCFST(t1,t2,a,b,disp) \
182     if ((t1)==(t2)) \
183           {M_DST(a,b,disp);} \
184         else { \
185           if ((t1)==TYPE_DBL) \
186             {M_CVTDF(a,REG_FTMP1);} \
187           else \
188             {M_CVTFD(a,REG_FTMP1);} \
189           M_DST(REG_FTMP1,b,disp); \
190         }
191           
192
193 /* var_to_reg_xxx:
194     this function generates code to fetch data from a pseudo-register
195     into a real register. 
196     If the pseudo-register has actually been assigned to a real 
197     register, no code will be emitted, since following operations
198     can use this register directly.
199     
200     v: pseudoregister to be fetched from
201     tempregnum: temporary register to be used if v is actually spilled to ram
202
203     return: the register number, where the operand can be found after 
204             fetching (this wil be either tempregnum or the register
205             number allready given to v)
206 */
207
208 #define var_to_reg_int(regnr,v,tempnr) { \
209         if ((v)->flags & INMEMORY) \
210                 {COUNT_SPILLS;M_LLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
211         else regnr=(v)->regoff; \
212 }
213
214
215 #define var_to_reg_flt(regnr,v,tempnr) { \
216         if ((v)->flags & INMEMORY) \
217                 {COUNT_SPILLS;M_DLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
218         else regnr=(v)->regoff; \
219 }
220
221
222 /* store_reg_to_var_xxx:
223     This function generates the code to store the result of an operation
224     back into a spilled pseudo-variable.
225     If the pseudo-variable has not been spilled in the first place, this 
226     function will generate nothing.
227     
228     v ............ Pseudovariable
229     tempregnum ... Number of the temporary registers as returned by
230                    reg_of_var.
231 */      
232
233 #define store_reg_to_var_int(sptr, tempregnum) {       \
234         if ((sptr)->flags & INMEMORY) {                    \
235                 COUNT_SPILLS;                                  \
236                 M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
237                 }                                              \
238         }
239
240 #define store_reg_to_var_flt(sptr, tempregnum) {       \
241         if ((sptr)->flags & INMEMORY) {                    \
242                 COUNT_SPILLS;                                  \
243                 M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
244                 }                                              \
245         }
246
247
248 #define M_COPY(from,to) \
249         d = reg_of_var(m, to, REG_IFTMP); \
250         if ((from->regoff != to->regoff) || \
251             ((from->flags ^ to->flags) & INMEMORY)) { \
252                 if (IS_FLT_DBL_TYPE(from->type)) { \
253                         var_to_reg_flt(s1, from, d); \
254                         M_TFLTMOVE(from->type, s1, d); \
255                         store_reg_to_var_flt(to, d); \
256                 } else { \
257                         var_to_reg_int(s1, from, d); \
258                         M_INTMOVE(s1, d); \
259                         store_reg_to_var_int(to, d); \
260                 } \
261         }
262
263
264 #define ICONST(r,c) \
265     if ((c) >= -32768 && (c) <= 32767) { \
266         M_IADD_IMM(REG_ZERO, (c), (r)); \
267     } else if ((c) >= 0 && (c) <= 0xffff) { \
268         M_OR_IMM(REG_ZERO, (c), (r)); \
269     } else { \
270         a = dseg_adds4(m, (c)); \
271         M_ILD((r), REG_PV, a); \
272     }
273
274 #define LCONST(r,c) \
275     if ((c) >= -32768 && (c) <= 32767) { \
276         M_LADD_IMM(REG_ZERO, (c), (r)); \
277     } else if ((c) >= 0 && (c) <= 0xffff) { \
278         M_OR_IMM(REG_ZERO, (c), (r)); \
279     } else { \
280         a = dseg_adds8(m, (c)); \
281         M_LLD((r), REG_PV, a); \
282     }
283
284
285 /* macros to create code ******************************************************/
286
287 /* code generation macros operands:
288       op ..... opcode
289       fu ..... function-number
290       rs ..... register number source 1
291       rt ..... register number or constant integer source 2
292       rd ..... register number destination
293       imm .... immediate/offset
294       sa ..... shift amount
295 */
296
297
298 #define M_ITYPE(op, rs, rt, imm)\
299   *(mcodeptr++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((imm)&0xffff))
300
301 #define M_JTYPE(op, imm)\
302   *(mcodeptr++) = (((op)<<26)|((off)&0x3ffffff))
303
304 #define M_RTYPE(op, rs, rt, rd, sa, fu)\
305   *(mcodeptr++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((rd)<<11)|((sa)<<6)|(fu))
306
307 #define M_FP2(fu, fmt, fs, fd)       M_RTYPE(0x11, fmt,  0, fs, fd, fu)
308 #define M_FP3(fu, fmt, fs, ft, fd)   M_RTYPE(0x11, fmt, ft, fs, fd, fu)
309
310 #define FMT_F  16
311 #define FMT_D  17
312 #define FMT_I  20
313 #define FMT_L  21
314
315 /* macros for all used commands (see a MIPS-manual for description) ***********/ 
316
317 /* load/store macros use the form OPERATION(source/dest, base, offset)        */
318
319 #define M_BLDS(a,b,disp)        M_ITYPE(0x20,b,a,disp)          /*  8 load    */
320 #define M_BLDU(a,b,disp)        M_ITYPE(0x24,b,a,disp)          /*  8 load    */
321 #define M_SLDS(a,b,disp)        M_ITYPE(0x21,b,a,disp)          /* 16 load    */
322 #define M_SLDU(a,b,disp)        M_ITYPE(0x25,b,a,disp)          /* 16 load    */
323 #define M_ILD(a,b,disp)         M_ITYPE(0x23,b,a,disp)          /* 32 load    */
324 #define M_LLD(a,b,disp)         M_ITYPE(0x37,b,a,disp)          /* 64 load    */
325 #define M_BST(a,b,disp)         M_ITYPE(0x28,b,a,disp)          /*  8 store   */
326 #define M_SST(a,b,disp)         M_ITYPE(0x29,b,a,disp)          /* 16 store   */
327 #define M_IST(a,b,disp)         M_ITYPE(0x2b,b,a,disp)          /* 32 store   */
328 #define M_LST(a,b,disp)         M_ITYPE(0x3f,b,a,disp)          /* 64 store   */
329
330 #define M_FLD(a,b,disp)         M_ITYPE(0x31,b,a,disp)          /* load flt   */
331 #define M_DLD(a,b,disp)         M_ITYPE(0x35,b,a,disp)          /* load dbl   */
332 #define M_FST(a,b,disp)         M_ITYPE(0x39,b,a,disp)          /* store flt  */
333 #define M_DST(a,b,disp)         M_ITYPE(0x3d,b,a,disp)          /* store dbl  */
334
335 #define M_BEQ(a,b,disp)         M_ITYPE(0x04,a,b,disp)          /* br a == b  */
336 #define M_BNE(a,b,disp)         M_ITYPE(0x05,a,b,disp)          /* br a != b  */
337 #define M_BEQZ(a,disp)          M_ITYPE(0x04,a,0,disp)          /* br a == 0  */
338 #define M_BLTZ(a,disp)          M_ITYPE(0x01,a,0,disp)          /* br a <  0  */
339 #define M_BLEZ(a,disp)          M_ITYPE(0x06,a,0,disp)          /* br a <= 0  */
340 #define M_BNEZ(a,disp)          M_ITYPE(0x05,a,0,disp)          /* br a != 0  */
341 #define M_BGEZ(a,disp)          M_ITYPE(0x01,a,1,disp)          /* br a >= 0  */
342 #define M_BGTZ(a,disp)          M_ITYPE(0x07,a,0,disp)          /* br a >  0  */
343
344 #define M_BEQL(a,b,disp)        M_ITYPE(0x14,a,b,disp)          /* br a == b  */
345 #define M_BNEL(a,b,disp)        M_ITYPE(0x15,a,b,disp)          /* br a != b  */
346 #define M_BEQZL(a,disp)         M_ITYPE(0x14,a,0,disp)          /* br a == 0  */
347 #define M_BLTZL(a,disp)         M_ITYPE(0x01,a,2,disp)          /* br a <  0  */
348 #define M_BLEZL(a,disp)         M_ITYPE(0x16,a,0,disp)          /* br a <= 0  */
349 #define M_BNEZL(a,disp)         M_ITYPE(0x15,a,0,disp)          /* br a != 0  */
350 #define M_BGEZL(a,disp)         M_ITYPE(0x01,a,3,disp)          /* br a >= 0  */
351 #define M_BGTZL(a,disp)         M_ITYPE(0x17,a,0,disp)          /* br a >  0  */
352
353 #define M_BR(disp)              M_ITYPE(0x04,0,0,disp)          /* branch     */
354 #define M_BRS(disp)             M_ITYPE(0x01,0,17,disp)         /* branch sbr */
355
356 #define M_JMP(a)                M_RTYPE(0,a,0,0,0,0x08)         /* jump       */
357 #define M_JSR(r,a)              M_RTYPE(0,a,0,r,0,0x09)         /* call       */
358 #define M_RET(a)                M_RTYPE(0,a,0,0,0,0x08)         /* return     */
359
360 #define M_TGE(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x30)  /* trp a >= b */
361 #define M_TGEU(a,b,code)        M_RTYPE(0,a,b,0,code&3ff,0x31)  /* trp a >= b */
362 #define M_TLT(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x32)  /* trp a <  b */
363 #define M_TLTU(a,b,code)        M_RTYPE(0,a,b,0,code&3ff,0x33)  /* trp a <  b */
364 #define M_TEQ(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x34)  /* trp a == b */
365 #define M_TNE(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x36)  /* trp a != b */
366 #define M_TLE(a,b,code)         M_RTYPE(0,b,a,0,code&3ff,0x30)  /* trp a <= b */
367 #define M_TLEU(a,b,code)        M_RTYPE(0,b,a,0,code&3ff,0x31)  /* trp a <= b */
368 #define M_TGT(a,b,code)         M_RTYPE(0,b,a,0,code&3ff,0x32)  /* trp a >  b */
369 #define M_TGTU(a,b,code)        M_RTYPE(0,b,a,0,code&3ff,0x33)  /* trp a >  b */
370
371 #define M_TGE_IMM(a,b)          M_ITYPE(1,a,0x08,b)             /* trp a >= b */
372 #define M_TGEU_IMM(a,b)         M_ITYPE(1,a,0x09,b)             /* trp a >= b */
373 #define M_TLT_IMM(a,b)          M_ITYPE(1,a,0x0a,b)             /* trp a <  b */
374 #define M_TLTU_IMM(a,b)         M_ITYPE(1,a,0x0b,b)             /* trp a <  b */
375 #define M_TEQ_IMM(a,b)          M_ITYPE(1,a,0x0c,b)             /* trp a == b */
376 #define M_TNE_IMM(a,b)          M_ITYPE(1,a,0x0e,b)             /* trp a != b */
377 #if 0
378 #define M_TGT_IMM(a,b)          M_ITYPE(1,a,0x08,b+1)           /* trp a >  b */
379 #define M_TGTU_IMM(a,b)         M_ITYPE(1,a,0x09,b+1)           /* trp a >  b */
380 #define M_TLE_IMM(a,b)          M_ITYPE(1,a,0x0a,b+1)           /* trp a <= b */
381 #define M_TLEU_IMM(a,b)         M_ITYPE(1,a,0x0b,b+1)           /* trp a <= b */
382 #endif
383
384 /* arithmetic macros use the form OPERATION(source, source/immediate, dest)   */
385
386 #define M_IADD(a,b,c)           M_RTYPE(0,a,b,c,0,0x21)         /* 32 add     */
387 #define M_LADD(a,b,c)           M_RTYPE(0,a,b,c,0,0x2d)         /* 64 add     */
388 #define M_ISUB(a,b,c)           M_RTYPE(0,a,b,c,0,0x23)         /* 32 sub     */
389 #define M_LSUB(a,b,c)           M_RTYPE(0,a,b,c,0,0x2f)         /* 64 sub     */
390 #define M_IMUL(a,b)             M_ITYPE(0,a,b,0x18)             /* 32 mul     */
391 #define M_LMUL(a,b)             M_ITYPE(0,a,b,0x1c)             /* 64 mul     */
392 #define M_IDIV(a,b)             M_ITYPE(0,a,b,0x1a)             /* 32 div     */
393 #define M_LDIV(a,b)             M_ITYPE(0,a,b,0x1e)             /* 64 div     */
394
395 #define M_MFLO(a)               M_RTYPE(0,0,0,a,0,0x12)         /* quotient   */
396 #define M_MFHI(a)               M_RTYPE(0,0,0,a,0,0x10)         /* remainder  */
397
398 #define M_IADD_IMM(a,b,c)       M_ITYPE(0x09,a,c,b)             /* 32 add     */
399 #define M_LADD_IMM(a,b,c)       M_ITYPE(0x19,a,c,b)             /* 64 add     */
400 #define M_ISUB_IMM(a,b,c)       M_ITYPE(0x09,a,c,-(b))          /* 32 sub     */
401 #define M_LSUB_IMM(a,b,c)       M_ITYPE(0x19,a,c,-(b))          /* 64 sub     */
402
403 #define M_LUI(a,imm)            M_ITYPE(0x0f,0,a,imm)           /* a = imm<<16*/
404
405 #define M_CMPLT(a,b,c)          M_RTYPE(0,a,b,c,0,0x2a)         /* c = a <  b */
406 #define M_CMPGT(a,b,c)          M_RTYPE(0,b,a,c,0,0x2a)         /* c = a >  b */
407
408 #define M_CMPULT(a,b,c)         M_RTYPE(0,a,b,c,0,0x2b)         /* c = a <  b */
409 #define M_CMPUGT(a,b,c)         M_RTYPE(0,b,a,c,0,0x2b)         /* c = a >  b */
410
411 #define M_CMPLT_IMM(a,b,c)      M_ITYPE(0x0a,a,c,b)             /* c = a <  b */
412 #define M_CMPULT_IMM(a,b,c)     M_ITYPE(0x0b,a,c,b)             /* c = a <  b */
413
414 #define M_AND(a,b,c)            M_RTYPE(0,a,b,c,0,0x24)         /* c = a &  b */
415 #define M_OR( a,b,c)            M_RTYPE(0,a,b,c,0,0x25)         /* c = a |  b */
416 #define M_XOR(a,b,c)            M_RTYPE(0,a,b,c,0,0x26)         /* c = a ^  b */
417
418 #define M_AND_IMM(a,b,c)        M_ITYPE(0x0c,a,c,b)             /* c = a &  b */
419 #define M_OR_IMM( a,b,c)        M_ITYPE(0x0d,a,c,b)             /* c = a |  b */
420 #define M_XOR_IMM(a,b,c)        M_ITYPE(0x0e,a,c,b)             /* c = a ^  b */
421
422 #define M_CZEXT(a,c)            M_AND_IMM(a,0xffff,c)           /* c = zext(a)*/
423
424 #define M_ISLL(a,b,c)           M_RTYPE(0,b,a,c,0,0x04)         /* c = a << b */
425 #define M_ISRL(a,b,c)           M_RTYPE(0,b,a,c,0,0x06)         /* c = a >>>b */
426 #define M_ISRA(a,b,c)           M_RTYPE(0,b,a,c,0,0x07)         /* c = a >> b */
427 #define M_LSLL(a,b,c)           M_RTYPE(0,b,a,c,0,0x14)         /* c = a << b */
428 #define M_LSRL(a,b,c)           M_RTYPE(0,b,a,c,0,0x16)         /* c = a >>>b */
429 #define M_LSRA(a,b,c)           M_RTYPE(0,b,a,c,0,0x17)         /* c = a >> b */
430
431 #define M_ISLL_IMM(a,b,c)       M_RTYPE(0,0,a,c,(b)&31,0x00)    /* c = a << b */
432 #define M_ISRL_IMM(a,b,c)       M_RTYPE(0,0,a,c,(b)&31,0x02)    /* c = a >>>b */
433 #define M_ISRA_IMM(a,b,c)       M_RTYPE(0,0,a,c,(b)&31,0x03)    /* c = a >> b */
434 #define M_LSLL_IMM(a,b,c) M_RTYPE(0,0,a,c,(b)&31,0x38+((b)>>3&4)) /*c = a << b*/
435 #define M_LSRL_IMM(a,b,c) M_RTYPE(0,0,a,c,(b)&31,0x3a+((b)>>3&4)) /*c = a >>>b*/
436 #define M_LSRA_IMM(a,b,c) M_RTYPE(0,0,a,c,(b)&31,0x3b+((b)>>3&4)) /*c = a >> b*/
437
438 #define M_MOV(a,c)              M_OR(a,0,c)                     /* c = a      */
439 #define M_CLR(c)                M_OR(0,0,c)                     /* c = 0      */
440 #define M_NOP                   M_ISLL_IMM(0,0,0)               /* ;          */
441
442 /* floating point macros use the form OPERATION(source, source, dest)         */
443
444 #define M_FADD(a,b,c)           M_FP3(0x00,FMT_F,a,b,c)         /* flt add    */
445 #define M_DADD(a,b,c)           M_FP3(0x00,FMT_D,a,b,c)         /* dbl add    */
446 #define M_FSUB(a,b,c)           M_FP3(0x01,FMT_F,a,b,c)         /* flt sub    */
447 #define M_DSUB(a,b,c)           M_FP3(0x01,FMT_D,a,b,c)         /* dbl sub    */
448 #define M_FMUL(a,b,c)           M_FP3(0x02,FMT_F,a,b,c)         /* flt mul    */
449 #define M_DMUL(a,b,c)           M_FP3(0x02,FMT_D,a,b,c)         /* dbl mul    */
450 #define M_FDIV(a,b,c)           M_FP3(0x03,FMT_F,a,b,c)         /* flt div    */
451 #define M_DDIV(a,b,c)           M_FP3(0x03,FMT_D,a,b,c)         /* dbl div    */
452
453 #define M_FSQRT(a,c)            M_FP2(0x04,FMT_F,a,c)           /* flt sqrt   */
454 #define M_DSQRT(a,c)            M_FP2(0x04,FMT_D,a,c)           /* dbl sqrt   */
455 #define M_FABS(a,c)             M_FP2(0x05,FMT_F,a,c)           /* flt abs    */
456 #define M_DABS(a,c)             M_FP2(0x05,FMT_D,a,c)           /* dbl abs    */
457 #define M_FMOV(a,c)             M_FP2(0x06,FMT_F,a,c)           /* flt mov    */
458 #define M_DMOV(a,c)             M_FP2(0x06,FMT_D,a,c)           /* dbl mov    */
459 #define M_FNEG(a,c)             M_FP2(0x07,FMT_F,a,c)           /* flt neg    */
460 #define M_DNEG(a,c)             M_FP2(0x07,FMT_D,a,c)           /* dbl neg    */
461
462 #define M_ROUNDFI(a,c)          M_FP2(0x0c,FMT_F,a,c)           /* flt roundi */
463 #define M_ROUNDDI(a,c)          M_FP2(0x0c,FMT_D,a,c)           /* dbl roundi */
464 #define M_TRUNCFI(a,c)          M_FP2(0x0d,FMT_F,a,c)           /* flt trunci */
465 #define M_TRUNCDI(a,c)          M_FP2(0x0d,FMT_D,a,c)           /* dbl trunci */
466 #define M_CEILFI(a,c)           M_FP2(0x0e,FMT_F,a,c)           /* flt ceili  */
467 #define M_CEILDI(a,c)           M_FP2(0x0e,FMT_D,a,c)           /* dbl ceili  */
468 #define M_FLOORFI(a,c)          M_FP2(0x0f,FMT_F,a,c)           /* flt trunci */
469 #define M_FLOORDI(a,c)          M_FP2(0x0f,FMT_D,a,c)           /* dbl trunci */
470
471 #define M_ROUNDFL(a,c)          M_FP2(0x08,FMT_F,a,c)           /* flt roundl */
472 #define M_ROUNDDL(a,c)          M_FP2(0x08,FMT_D,a,c)           /* dbl roundl */
473 #define M_TRUNCFL(a,c)          M_FP2(0x09,FMT_F,a,c)           /* flt truncl */
474 #define M_TRUNCDL(a,c)          M_FP2(0x09,FMT_D,a,c)           /* dbl truncl */
475 #define M_CEILFL(a,c)           M_FP2(0x0a,FMT_F,a,c)           /* flt ceill  */
476 #define M_CEILDL(a,c)           M_FP2(0x0a,FMT_D,a,c)           /* dbl ceill  */
477 #define M_FLOORFL(a,c)          M_FP2(0x0b,FMT_F,a,c)           /* flt truncl */
478 #define M_FLOORDL(a,c)          M_FP2(0x0b,FMT_D,a,c)           /* dbl truncl */
479
480 #define M_CVTDF(a,c)            M_FP2(0x20,FMT_D,a,c)           /* dbl2flt    */
481 #define M_CVTIF(a,c)            M_FP2(0x20,FMT_I,a,c)           /* int2flt    */
482 #define M_CVTLF(a,c)            M_FP2(0x20,FMT_L,a,c)           /* long2flt   */
483 #define M_CVTFD(a,c)            M_FP2(0x21,FMT_F,a,c)           /* flt2dbl    */
484 #define M_CVTID(a,c)            M_FP2(0x21,FMT_I,a,c)           /* int2dbl    */
485 #define M_CVTLD(a,c)            M_FP2(0x21,FMT_L,a,c)           /* long2dbl   */
486 #define M_CVTFI(a,c)            M_FP2(0x24,FMT_F,a,c)           /* flt2int    */
487 #define M_CVTDI(a,c)            M_FP2(0x24,FMT_D,a,c)           /* dbl2int    */
488 #define M_CVTFL(a,c)            M_FP2(0x25,FMT_F,a,c)           /* flt2long   */
489 #define M_CVTDL(a,c)            M_FP2(0x25,FMT_D,a,c)           /* dbl2long   */
490
491 #define M_MOVDI(d,i)            M_FP3(0,0,d,i,0)                /* i = d      */
492 #define M_MOVDL(d,l)            M_FP3(0,1,d,l,0)                /* l = d      */
493 #define M_MOVID(i,d)            M_FP3(0,4,d,i,0)                /* d = i      */
494 #define M_MOVLD(l,d)            M_FP3(0,5,d,l,0)                /* d = l      */
495
496 #define M_DMFC1(l,f)            M_FP3(0,1,f,l,0)
497 #define M_DMTC1(l,f)            M_FP3(0,5,f,l,0)
498
499 #define M_FCMPFF(a,b)           M_FP3(0x30,FMT_F,a,b,0)         /* c = a == b */
500 #define M_FCMPFD(a,b)           M_FP3(0x30,FMT_D,a,b,0)         /* c = a == b */
501 #define M_FCMPUNF(a,b)          M_FP3(0x31,FMT_F,a,b,0)         /* c = a == b */
502 #define M_FCMPUND(a,b)          M_FP3(0x31,FMT_D,a,b,0)         /* c = a == b */
503 #define M_FCMPEQF(a,b)          M_FP3(0x32,FMT_F,a,b,0)         /* c = a == b */
504 #define M_FCMPEQD(a,b)          M_FP3(0x32,FMT_D,a,b,0)         /* c = a == b */
505 #define M_FCMPUEQF(a,b)         M_FP3(0x33,FMT_F,a,b,0)         /* c = a == b */
506 #define M_FCMPUEQD(a,b)         M_FP3(0x33,FMT_D,a,b,0)         /* c = a == b */
507 #define M_FCMPOLTF(a,b)         M_FP3(0x34,FMT_F,a,b,0)         /* c = a <  b */
508 #define M_FCMPOLTD(a,b)         M_FP3(0x34,FMT_D,a,b,0)         /* c = a <  b */
509 #define M_FCMPULTF(a,b)         M_FP3(0x35,FMT_F,a,b,0)         /* c = a <  b */
510 #define M_FCMPULTD(a,b)         M_FP3(0x35,FMT_D,a,b,0)         /* c = a <  b */
511 #define M_FCMPOLEF(a,b)         M_FP3(0x36,FMT_F,a,b,0)         /* c = a <= b */
512 #define M_FCMPOLED(a,b)         M_FP3(0x36,FMT_D,a,b,0)         /* c = a <= b */
513 #define M_FCMPULEF(a,b)         M_FP3(0x37,FMT_F,a,b,0)         /* c = a <= b */
514 #define M_FCMPULED(a,b)         M_FP3(0x37,FMT_D,a,b,0)         /* c = a <= b */
515
516 #define M_FBF(disp)             M_ITYPE(0x11,8,0,disp)          /* br false   */
517 #define M_FBT(disp)             M_ITYPE(0x11,8,1,disp)          /* br true    */
518 #define M_FBFL(disp)            M_ITYPE(0x11,8,2,disp)          /* br false   */
519 #define M_FBTL(disp)            M_ITYPE(0x11,8,3,disp)          /* br true    */
520
521 #define M_CMOVF(a,b)                    M_RTYPE(0x00,a,0,b,0,1)
522 #define M_CMOVT(a,b)                    M_RTYPE(0x00,a,1,b,0,1)
523
524 /*
525  * Load Address pseudo instruction:
526  * -n32 addressing mode -> 32 bit addrs, -64 addressing mode -> 64 bit addrs
527  */
528 #if POINTERSIZE==8
529 #define POINTERSHIFT 3
530 #define M_ALD(a,b,disp)         M_LLD(a,b,disp)
531 #define M_AST(a,b,disp)         M_LST(a,b,disp)
532 #define M_AADD(a,b,c)           M_LADD(a,b,c)
533 #define M_ASLL_IMM(a,b,c)       M_LSLL_IMM(a,b,c)
534 #define M_LDA(a,b,disp)         M_LADD_IMM(b,disp,a)            /* a = b+disp */
535 #else
536 #define POINTERSHIFT 2
537 #define M_ALD(a,b,disp)         M_ILD(a,b,disp)
538 #define M_AST(a,b,disp)         M_IST(a,b,disp)
539 #define M_AADD(a,b,c)           M_IADD(a,b,c)
540 #define M_ASLL_IMM(a,b,c)       M_ISLL_IMM(a,b,c)
541 #define M_LDA(a,b,disp)         M_IADD_IMM(b,disp,a)            /* a = b+disp */
542 #endif
543
544 /* macros for special commands (see an Alpha-manual for description) **********/ 
545
546 #if 0
547 #define M_CMOVEQ(a,b,c)         M_OP3 (0x11,0x24, a,b,c,0)     /* a==0 ? c=b  */
548 #define M_CMOVNE(a,b,c)         M_OP3 (0x11,0x26, a,b,c,0)     /* a!=0 ? c=b  */
549 #define M_CMOVLT(a,b,c)         M_OP3 (0x11,0x44, a,b,c,0)     /* a< 0 ? c=b  */
550 #define M_CMOVGE(a,b,c)         M_OP3 (0x11,0x46, a,b,c,0)     /* a>=0 ? c=b  */
551 #define M_CMOVLE(a,b,c)         M_OP3 (0x11,0x64, a,b,c,0)     /* a<=0 ? c=b  */
552 #define M_CMOVGT(a,b,c)         M_OP3 (0x11,0x66, a,b,c,0)     /* a> 0 ? c=b  */
553
554 #define M_CMOVEQ_IMM(a,b,c)     M_OP3 (0x11,0x24, a,b,c,1)     /* a==0 ? c=b  */
555 #define M_CMOVNE_IMM(a,b,c)     M_OP3 (0x11,0x26, a,b,c,1)     /* a!=0 ? c=b  */
556 #define M_CMOVLT_IMM(a,b,c)     M_OP3 (0x11,0x44, a,b,c,1)     /* a< 0 ? c=b  */
557 #define M_CMOVGE_IMM(a,b,c)     M_OP3 (0x11,0x46, a,b,c,1)     /* a>=0 ? c=b  */
558 #define M_CMOVLE_IMM(a,b,c)     M_OP3 (0x11,0x64, a,b,c,1)     /* a<=0 ? c=b  */
559 #define M_CMOVGT_IMM(a,b,c)     M_OP3 (0x11,0x66, a,b,c,1)     /* a> 0 ? c=b  */
560 #endif
561
562 /* function gen_resolvebranch **************************************************
563
564         backpatches a branch instruction; MIPS branch instructions are very
565         regular, so it is only necessary to overwrite some fixed bits in the
566         instruction.
567
568         parameters: ip ... pointer to instruction after branch (void*)
569                     so ... offset of instruction after branch  (s4)
570                     to ... offset of branch target             (s4)
571
572 *******************************************************************************/
573
574 #define gen_resolvebranch(ip,so,to) ((s4*)(ip))[-1]|=((s4)(to)-(so))>>2&0xffff
575
576
577 /* function prototypes */
578
579 void docacheflush(u1 *p, long bytelen);
580
581 #endif /* _CODEGEN_H */
582
583
584 /*
585  * These are local overrides for various environment variables in Emacs.
586  * Please do not remove this and leave it at the end of the file, where
587  * Emacs will automagically detect them.
588  * ---------------------------------------------------------------------
589  * Local variables:
590  * mode: c
591  * indent-tabs-mode: t
592  * c-basic-offset: 4
593  * tab-width: 4
594  * End:
595  */