* src/vm/jit/jit.c: Moved to .cpp.
[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, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #ifndef _CODEGEN_H
27 #define _CODEGEN_H
28
29 #include "config.h"
30 #include "vm/types.h"
31
32 #include "vm/jit/jit.hpp"
33
34
35 /* additional functions and macros to generate code ***************************/
36
37 /* MCODECHECK(icnt) */
38
39 #define MCODECHECK(icnt) \
40     do { \
41         if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
42             codegen_increase(cd); \
43     } while (0)
44
45
46 #define ALIGNCODENOP \
47     if ((s4) ((ptrint) cd->mcodeptr & 7)) { \
48         M_NOP; \
49     }
50
51 #define M_INTMOVE(a,b) \
52     do { \
53         if ((a) != (b)) \
54             M_MOV(a, b); \
55     } while (0)
56
57 #if SIZEOF_VOID_P == 8
58
59 #define M_LNGMOVE(a,b)    M_INTMOVE(a,b)
60
61 #else /* SIZEOF_VOID_P == 8 */
62
63 #define M_LNGMOVE(a,b) \
64     do { \
65         if (GET_LOW_REG(b) == GET_HIGH_REG(a)) { \
66             assert(GET_HIGH_REG(b) == GET_LOW_REG(a)); \
67             M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
68             M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
69         } else { \
70             M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
71             M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
72         } \
73     } while (0)
74
75 #endif /* SIZEOF_VOID_P == 8 */
76
77 #define M_FLTMOVE(a,b) \
78     do { \
79         if ((a) != (b)) \
80             M_FMOV(a, b); \
81     } while (0)
82
83 #define M_DBLMOVE(a,b) \
84     do { \
85         if ((a) != (b)) \
86             M_DMOV(a, b); \
87     } while (0)
88
89 #define ICONST(r,c)                     emit_iconst(cd, (r), (c))
90 #define LCONST(r,c)                     emit_lconst(cd, (r), (c))
91
92
93 /* branch defines *************************************************************/
94
95 #define BRANCH_NOPS \
96     do { \
97         if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { \
98             M_NOP; \
99             M_NOP; \
100             M_NOP; \
101             M_NOP; \
102             M_NOP; \
103             M_NOP; \
104         } \
105         else { \
106             M_NOP; \
107             M_NOP; \
108         } \
109     } while (0)
110
111
112 /* patcher defines ************************************************************/
113
114 #define PATCHER_CALL_INSTRUCTIONS    1     /* number of instructions          */
115 #define PATCHER_CALL_SIZE            1 * 4 /* size in bytes of a patcher call */
116
117 #define PATCHER_NOPS \
118     do { \
119         M_NOP; \
120     } while (0)
121
122
123 /* macros to create code ******************************************************/
124
125 /* code generation macros operands:
126       op ..... opcode
127       fu ..... function-number
128       rs ..... register number source 1
129       rt ..... register number or constant integer source 2
130       rd ..... register number destination
131       imm .... immediate/offset
132       sa ..... shift amount
133 */
134
135
136 #define M_ITYPE(op,rs,rt,imm) \
137     do { \
138         *((u4 *) cd->mcodeptr) = (((op) << 26) | ((rs) << 21) | ((rt) << 16) | ((imm) & 0xffff)); \
139         cd->mcodeptr += 4; \
140     } while (0)
141
142 #define M_ITYPE_GET_RS(x)               (((x) >> 21) & 0x1f  )
143 #define M_ITYPE_GET_RT(x)               (((x) >> 16) & 0x1f  )
144 #define M_ITYPE_GET_IMM(x)              ( (x)        & 0xffff)
145
146
147 #define M_JTYPE(op,imm) \
148     do { \
149         *((u4 *) cd->mcodeptr) = (((op) << 26) | ((off) & 0x3ffffff)); \
150         cd->mcodeptr += 4; \
151     } while (0)
152
153 #define M_RTYPE(op,rs,rt,rd,sa,fu) \
154     do { \
155         *((u4 *) cd->mcodeptr) = (((op) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((sa) << 6) | (fu)); \
156         cd->mcodeptr += 4; \
157     } while (0)
158
159 #define M_FP2(fu, fmt, fs, fd)       M_RTYPE(0x11, fmt,  0, fs, fd, fu)
160 #define M_FP3(fu, fmt, fs, ft, fd)   M_RTYPE(0x11, fmt, ft, fs, fd, fu)
161
162 #define FMT_F  16
163 #define FMT_D  17
164 #define FMT_I  20
165 #define FMT_L  21
166
167
168 /* macros for all used commands (see a MIPS-manual for description) ***********/
169
170 /* load/store macros use the form OPERATION(source/dest, base, offset)        */
171
172 #define M_LDA(a,b,disp) \
173     do { \
174         s4 lo = (short) (disp); \
175         s4 hi = (short) (((disp) - lo) >> 16); \
176         if (hi == 0) { \
177             M_AADD_IMM(b,lo,a); \
178         } else { \
179             M_LUI(REG_ITMP3, hi); \
180             M_AADD_IMM(REG_ITMP3, lo, REG_ITMP3); \
181             M_AADD(b, REG_ITMP3, a); \
182         } \
183     } while (0)
184
185 #define M_BLDS(a,b,disp)        M_ITYPE(0x20,b,a,disp)          /*  8 load    */
186 #define M_BLDU(a,b,disp)        M_ITYPE(0x24,b,a,disp)          /*  8 load    */
187 #define M_SLDS(a,b,disp)        M_ITYPE(0x21,b,a,disp)          /* 16 load    */
188 #define M_SLDU(a,b,disp)        M_ITYPE(0x25,b,a,disp)          /* 16 load    */
189
190 #define M_ILD_INTERN(a,b,disp)  M_ITYPE(0x23,b,a,disp)          /* 32 load    */
191
192 #define M_ILD(a,b,disp) \
193     do { \
194         s4 lo = (short) (disp); \
195         s4 hi = (short) (((disp) - lo) >> 16); \
196         if (hi == 0) { \
197             M_ILD_INTERN(a,b,lo); \
198         } else { \
199             M_LUI(a,hi); \
200             M_AADD(b,a,a); \
201             M_ILD_INTERN(a,a,lo); \
202         } \
203     } while (0)
204
205 #if SIZEOF_VOID_P == 8
206
207 #define M_LLD_INTERN(a,b,disp)  M_ITYPE(0x37,b,a,disp)          /* 64 load    */
208
209 #else /* SIZEOF_VOID_P == 8 */
210
211 # if WORDS_BIGENDIAN == 1
212
213 /* ATTENTION: b may be equal to GET_LOW_REG(a) (displacement overflow case ) */
214
215 #define M_LLD_INTERN(a,b,disp) \
216     do { \
217         M_ILD_INTERN(GET_HIGH_REG(a), b, disp); \
218         M_ILD_INTERN(GET_LOW_REG(a), b, disp + 4); \
219     } while (0)
220
221 /* this macro is specially for ICMD_GETFIELD since the base (source)
222    register may be one of the destination registers */
223
224 #define M_LLD_GETFIELD(a,b,disp) \
225     do { \
226         s4 lo = (short) (disp); \
227         s4 hi = (short) (((disp) - lo) >> 16); \
228         if (hi == 0) { \
229             if (GET_HIGH_REG(a) == (b)) { \
230                 M_ILD_INTERN(GET_LOW_REG(a), b, disp + 4); \
231                 M_ILD_INTERN(GET_HIGH_REG(a), b, disp); \
232             } else { \
233                 M_ILD_INTERN(GET_HIGH_REG(a), b, disp); \
234                 M_ILD_INTERN(GET_LOW_REG(a), b, disp + 4); \
235             } \
236         } else { \
237             M_LUI(GET_LOW_REG(a), hi); \
238             M_AADD(b, GET_LOW_REG(a), GET_LOW_REG(a)); \
239             M_LLD_INTERN(a, GET_LOW_REG(a), lo); \
240         } \
241     } while (0)
242
243 # else /* if WORDS_BIGENDIAN == 1 */
244
245 /* ATTENTION: b may be equal to GET_LOW_REG(a) (displacement overflow case ) */
246
247 #define M_LLD_INTERN(a,b,disp) \
248     do { \
249         M_ILD_INTERN(GET_HIGH_REG(a), b, disp + 4); \
250         M_ILD_INTERN(GET_LOW_REG(a), b, disp); \
251     } while (0)
252
253 /* this macro is specially for ICMD_GETFIELD since the base (source)
254    register may be one of the destination registers */
255
256 #define M_LLD_GETFIELD(a,b,disp) \
257     do { \
258         s4 lo = (short) (disp); \
259         s4 hi = (short) (((disp) - lo) >> 16); \
260         if (hi == 0) { \
261             if (GET_HIGH_REG(a) == (b)) { \
262                 M_ILD_INTERN(GET_LOW_REG(a), b, disp); \
263                 M_ILD_INTERN(GET_HIGH_REG(a), b, disp + 4); \
264             } else { \
265                 M_ILD_INTERN(GET_HIGH_REG(a), b, disp + 4); \
266                 M_ILD_INTERN(GET_LOW_REG(a), b, disp); \
267             } \
268         } else { \
269             M_LUI(GET_LOW_REG(a), hi); \
270             M_AADD(b, GET_LOW_REG(a), GET_LOW_REG(a)); \
271             M_LLD_INTERN(a, GET_LOW_REG(a), lo); \
272         } \
273     } while (0)
274
275 # endif /* if WORDS_BIGENDIAN == 1 */
276
277 #endif /* SIZEOF_VOID_P == 8 */
278
279 #define M_LLD(a,b,disp) \
280     do { \
281         s4 lo = (short) (disp); \
282         s4 hi = (short) (((disp) - lo) >> 16); \
283         if (hi == 0) { \
284             M_LLD_INTERN(a, b, lo); \
285         } else { \
286             M_LUI(GET_LOW_REG(a), hi); \
287             M_AADD(b, GET_LOW_REG(a), GET_LOW_REG(a)); \
288             M_LLD_INTERN(a, GET_LOW_REG(a), lo); \
289         } \
290     } while (0)
291
292 #define M_BST(a,b,disp)         M_ITYPE(0x28,b,a,disp)          /*  8 store   */
293 #define M_SST(a,b,disp)         M_ITYPE(0x29,b,a,disp)          /* 16 store   */
294
295 #define M_IST_INTERN(a,b,disp)  M_ITYPE(0x2b,b,a,disp)          /* 32 store   */
296
297 #define M_IST(a,b,disp) \
298     do { \
299         s4 lo = (short) (disp); \
300         s4 hi = (short) (((disp) - lo) >> 16); \
301         if (hi == 0) { \
302             M_IST_INTERN(a,b,lo); \
303         } else { \
304             M_LUI(REG_ITMP3, hi); \
305             M_AADD(b, REG_ITMP3, REG_ITMP3); \
306             M_IST_INTERN(a, REG_ITMP3, lo); \
307         } \
308     } while (0)
309
310 #if SIZEOF_VOID_P == 8
311
312 #define M_LST_INTERN(a,b,disp)  M_ITYPE(0x3f,b,a,disp)          /* 64 store   */
313
314 #else /* SIZEOF_VOID_P == 8 */
315
316 #if WORDS_BIGENDIAN == 1
317
318 #define M_LST_INTERN(a,b,disp) \
319     do { \
320         M_IST_INTERN(GET_HIGH_REG(a), b, disp); \
321         M_IST_INTERN(GET_LOW_REG(a), b, disp + 4); \
322     } while (0)
323
324 #else /* if WORDS_BIGENDIAN == 1 */
325
326 #define M_LST_INTERN(a,b,disp) \
327     do { \
328         M_IST_INTERN(GET_HIGH_REG(a), b, disp + 4); \
329         M_IST_INTERN(GET_LOW_REG(a), b, disp); \
330     } while (0)
331
332 #endif /* if WORDS_BIGENDIAN == 1 */
333
334 #endif /* SIZEOF_VOID_P == 8 */
335
336 #define M_LST(a,b,disp) \
337     do { \
338         s4 lo = (short) (disp); \
339         s4 hi = (short) (((disp) - lo) >> 16); \
340         if (hi == 0) { \
341             M_LST_INTERN(a,b,lo); \
342         } else { \
343             M_LUI(REG_ITMP3, hi); \
344             M_AADD(b, REG_ITMP3, REG_ITMP3); \
345             M_LST_INTERN(a, REG_ITMP3, lo); \
346         } \
347     } while (0)
348
349 #define M_FLD_INTERN(a,b,disp)  M_ITYPE(0x31,b,a,disp)          /* load flt   */
350 #define M_DLD_INTERN(a,b,disp)  M_ITYPE(0x35,b,a,disp)          /* load dbl   */
351
352 #define M_FLD(a,b,disp) \
353     do { \
354         s4 lo = (short) (disp); \
355         s4 hi = (short) (((disp) - lo) >> 16); \
356         if (hi == 0) { \
357             M_FLD_INTERN(a,b,lo); \
358         } else { \
359             M_LUI(REG_ITMP3, hi); \
360             M_AADD(b, REG_ITMP3, REG_ITMP3); \
361             M_FLD_INTERN(a, REG_ITMP3, lo); \
362         } \
363     } while (0)
364
365 #define M_DLD(a,b,disp) \
366     do { \
367         s4 lo = (short) (disp); \
368         s4 hi = (short) (((disp) - lo) >> 16); \
369         if (hi == 0) { \
370             M_DLD_INTERN(a,b,lo); \
371         } else { \
372             M_LUI(REG_ITMP3, hi); \
373             M_AADD(b, REG_ITMP3, REG_ITMP3); \
374             M_DLD_INTERN(a, REG_ITMP3, lo); \
375         } \
376     } while (0)
377
378 #define M_FST_INTERN(a,b,disp)  M_ITYPE(0x39,b,a,disp)          /* store flt  */
379 #define M_DST_INTERN(a,b,disp)  M_ITYPE(0x3d,b,a,disp)          /* store dbl  */
380
381 #define M_FST(a,b,disp) \
382     do { \
383         s4 lo = (short) (disp); \
384         s4 hi = (short) (((disp) - lo) >> 16); \
385         if (hi == 0) { \
386             M_FST_INTERN(a,b,lo); \
387         } else { \
388             M_LUI(REG_ITMP3, hi); \
389             M_AADD(b, REG_ITMP3, REG_ITMP3); \
390             M_FST_INTERN(a, REG_ITMP3, lo); \
391         } \
392     } while (0)
393
394 #define M_DST(a,b,disp) \
395     do { \
396         s4 lo = (short) (disp); \
397         s4 hi = (short) (((disp) - lo) >> 16); \
398         if (hi == 0) { \
399             M_DST_INTERN(a,b,lo); \
400         } else { \
401             M_LUI(REG_ITMP3, hi); \
402             M_AADD(b, REG_ITMP3, REG_ITMP3); \
403             M_DST_INTERN(a, REG_ITMP3, lo); \
404         } \
405     } while (0)
406
407 #define M_BEQ(a,b,disp)         M_ITYPE(0x04,a,b,disp)          /* br a == b  */
408 #define M_BNE(a,b,disp)         M_ITYPE(0x05,a,b,disp)          /* br a != b  */
409 #define M_BEQZ(a,disp)          M_ITYPE(0x04,a,0,disp)          /* br a == 0  */
410 #define M_BLTZ(a,disp)          M_ITYPE(0x01,a,0,disp)          /* br a <  0  */
411 #define M_BLEZ(a,disp)          M_ITYPE(0x06,a,0,disp)          /* br a <= 0  */
412 #define M_BNEZ(a,disp)          M_ITYPE(0x05,a,0,disp)          /* br a != 0  */
413 #define M_BGEZ(a,disp)          M_ITYPE(0x01,a,1,disp)          /* br a >= 0  */
414 #define M_BGTZ(a,disp)          M_ITYPE(0x07,a,0,disp)          /* br a >  0  */
415
416 #if 0
417 #define M_BEQL(a,b,disp)        M_ITYPE(0x14,a,b,disp)          /* br a == b  */
418 #define M_BNEL(a,b,disp)        M_ITYPE(0x15,a,b,disp)          /* br a != b  */
419 #define M_BEQZL(a,disp)         M_ITYPE(0x14,a,0,disp)          /* br a == 0  */
420 #define M_BLTZL(a,disp)         M_ITYPE(0x01,a,2,disp)          /* br a <  0  */
421 #define M_BLEZL(a,disp)         M_ITYPE(0x16,a,0,disp)          /* br a <= 0  */
422 #define M_BNEZL(a,disp)         M_ITYPE(0x15,a,0,disp)          /* br a != 0  */
423 #define M_BGEZL(a,disp)         M_ITYPE(0x01,a,3,disp)          /* br a >= 0  */
424 #define M_BGTZL(a,disp)         M_ITYPE(0x17,a,0,disp)          /* br a >  0  */
425 #endif
426
427 #define M_BR(disp)              M_ITYPE(0x04,0,0,disp)          /* branch     */
428 #define M_BRS(disp)             M_ITYPE(0x01,0,17,disp)         /* branch sbr */
429
430 #define M_JMP(a)                M_RTYPE(0,a,0,0,0,0x08)         /* jump       */
431 #define M_JSR(r,a)              M_RTYPE(0,a,0,r,0,0x09)         /* call       */
432 #define M_RET(a)                M_RTYPE(0,a,0,0,0,0x08)         /* return     */
433
434 #define M_TGE(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x30)  /* trp a >= b */
435 #define M_TGEU(a,b,code)        M_RTYPE(0,a,b,0,code&3ff,0x31)  /* trp a >= b */
436 #define M_TLT(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x32)  /* trp a <  b */
437 #define M_TLTU(a,b,code)        M_RTYPE(0,a,b,0,code&3ff,0x33)  /* trp a <  b */
438 #define M_TEQ(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x34)  /* trp a == b */
439 #define M_TNE(a,b,code)         M_RTYPE(0,a,b,0,code&3ff,0x36)  /* trp a != b */
440 #define M_TLE(a,b,code)         M_RTYPE(0,b,a,0,code&3ff,0x30)  /* trp a <= b */
441 #define M_TLEU(a,b,code)        M_RTYPE(0,b,a,0,code&3ff,0x31)  /* trp a <= b */
442 #define M_TGT(a,b,code)         M_RTYPE(0,b,a,0,code&3ff,0x32)  /* trp a >  b */
443 #define M_TGTU(a,b,code)        M_RTYPE(0,b,a,0,code&3ff,0x33)  /* trp a >  b */
444
445 #define M_TGE_IMM(a,b)          M_ITYPE(1,a,0x08,b)             /* trp a >= b */
446 #define M_TGEU_IMM(a,b)         M_ITYPE(1,a,0x09,b)             /* trp a >= b */
447 #define M_TLT_IMM(a,b)          M_ITYPE(1,a,0x0a,b)             /* trp a <  b */
448 #define M_TLTU_IMM(a,b)         M_ITYPE(1,a,0x0b,b)             /* trp a <  b */
449 #define M_TEQ_IMM(a,b)          M_ITYPE(1,a,0x0c,b)             /* trp a == b */
450 #define M_TNE_IMM(a,b)          M_ITYPE(1,a,0x0e,b)             /* trp a != b */
451 #if 0
452 #define M_TGT_IMM(a,b)          M_ITYPE(1,a,0x08,b+1)           /* trp a >  b */
453 #define M_TGTU_IMM(a,b)         M_ITYPE(1,a,0x09,b+1)           /* trp a >  b */
454 #define M_TLE_IMM(a,b)          M_ITYPE(1,a,0x0a,b+1)           /* trp a <= b */
455 #define M_TLEU_IMM(a,b)         M_ITYPE(1,a,0x0b,b+1)           /* trp a <= b */
456 #endif
457
458 /* arithmetic macros use the form OPERATION(source, source/immediate, dest)   */
459
460 #define M_IADD(a,b,c)           M_RTYPE(0,a,b,c,0,0x21)         /* 32 add     */
461 #define M_LADD(a,b,c)           M_RTYPE(0,a,b,c,0,0x2d)         /* 64 add     */
462 #define M_ISUB(a,b,c)           M_RTYPE(0,a,b,c,0,0x23)         /* 32 sub     */
463 #define M_LSUB(a,b,c)           M_RTYPE(0,a,b,c,0,0x2f)         /* 64 sub     */
464 #define M_IMUL(a,b)             M_ITYPE(0,a,b,0x18)             /* 32 mul     */
465 #define M_IMULU(a,b)            M_ITYPE(0,a,b,0x19)             /* 32 mul     */
466 #define M_LMUL(a,b)             M_ITYPE(0,a,b,0x1c)             /* 64 mul     */
467 #define M_IDIV(a,b)             M_ITYPE(0,a,b,0x1a)             /* 32 div     */
468 #define M_LDIV(a,b)             M_ITYPE(0,a,b,0x1e)             /* 64 div     */
469
470 #define M_MFLO(a)               M_RTYPE(0,0,0,a,0,0x12)         /* quotient   */
471 #define M_MFHI(a)               M_RTYPE(0,0,0,a,0,0x10)         /* remainder  */
472
473 #define M_IADD_IMM(a,b,c)       M_ITYPE(0x09,a,c,b)             /* 32 add     */
474 #define M_LADD_IMM(a,b,c)       M_ITYPE(0x19,a,c,b)             /* 64 add     */
475 #define M_ISUB_IMM(a,b,c)       M_IADD_IMM(a,-(b),c)            /* 32 sub     */
476 #define M_LSUB_IMM(a,b,c)       M_LADD_IMM(a,-(b),c)            /* 64 sub     */
477
478 #define M_LUI(a,imm)            M_ITYPE(0x0f,0,a,imm)           /* a = imm<<16*/
479
480 #define M_CMPLT(a,b,c)          M_RTYPE(0,a,b,c,0,0x2a)         /* c = a <  b */
481 #define M_CMPGT(a,b,c)          M_RTYPE(0,b,a,c,0,0x2a)         /* c = a >  b */
482
483 #define M_CMPULT(a,b,c)         M_RTYPE(0,a,b,c,0,0x2b)         /* c = a <  b */
484 #define M_CMPUGT(a,b,c)         M_RTYPE(0,b,a,c,0,0x2b)         /* c = a >  b */
485
486 #define M_CMPLT_IMM(a,b,c)      M_ITYPE(0x0a,a,c,b)             /* c = a <  b */
487 #define M_CMPULT_IMM(a,b,c)     M_ITYPE(0x0b,a,c,b)             /* c = a <  b */
488
489 #define M_AND(a,b,c)            M_RTYPE(0,a,b,c,0,0x24)         /* c = a &  b */
490 #define M_OR( a,b,c)            M_RTYPE(0,a,b,c,0,0x25)         /* c = a |  b */
491 #define M_XOR(a,b,c)            M_RTYPE(0,a,b,c,0,0x26)         /* c = a ^  b */
492
493 #define M_AND_IMM(a,b,c)        M_ITYPE(0x0c,a,c,b)             /* c = a &  b */
494 #define M_OR_IMM( a,b,c)        M_ITYPE(0x0d,a,c,b)             /* c = a |  b */
495 #define M_XOR_IMM(a,b,c)        M_ITYPE(0x0e,a,c,b)             /* c = a ^  b */
496
497 #define M_ISLL(a,b,c)           M_RTYPE(0,b,a,c,0,0x04)         /* c = a << b */
498 #define M_ISRL(a,b,c)           M_RTYPE(0,b,a,c,0,0x06)         /* c = a >>>b */
499 #define M_ISRA(a,b,c)           M_RTYPE(0,b,a,c,0,0x07)         /* c = a >> b */
500 #define M_LSLL(a,b,c)           M_RTYPE(0,b,a,c,0,0x14)         /* c = a << b */
501 #define M_LSRL(a,b,c)           M_RTYPE(0,b,a,c,0,0x16)         /* c = a >>>b */
502 #define M_LSRA(a,b,c)           M_RTYPE(0,b,a,c,0,0x17)         /* c = a >> b */
503
504 #define M_ISLL_IMM(a,b,c)       M_RTYPE(0,0,a,c,(b)&31,0x00)    /* c = a << b */
505 #define M_ISRL_IMM(a,b,c)       M_RTYPE(0,0,a,c,(b)&31,0x02)    /* c = a >>>b */
506 #define M_ISRA_IMM(a,b,c)       M_RTYPE(0,0,a,c,(b)&31,0x03)    /* c = a >> b */
507 #define M_LSLL_IMM(a,b,c) M_RTYPE(0,0,a,c,(b)&31,0x38+((b)>>3&4)) /*c = a << b*/
508 #define M_LSRL_IMM(a,b,c) M_RTYPE(0,0,a,c,(b)&31,0x3a+((b)>>3&4)) /*c = a >>>b*/
509 #define M_LSRA_IMM(a,b,c) M_RTYPE(0,0,a,c,(b)&31,0x3b+((b)>>3&4)) /*c = a >> b*/
510
511 #define M_MOV(a,c)              M_OR(a,0,c)                     /* c = a      */
512 #define M_CLR(c)                M_OR(0,0,c)                     /* c = 0      */
513 #define M_NOP                   M_ISLL_IMM(0,0,0)               /* ;          */
514
515 /* floating point macros use the form OPERATION(source, source, dest)         */
516
517 #define M_FADD(a,b,c)           M_FP3(0x00,FMT_F,a,b,c)         /* flt add    */
518 #define M_DADD(a,b,c)           M_FP3(0x00,FMT_D,a,b,c)         /* dbl add    */
519 #define M_FSUB(a,b,c)           M_FP3(0x01,FMT_F,a,b,c)         /* flt sub    */
520 #define M_DSUB(a,b,c)           M_FP3(0x01,FMT_D,a,b,c)         /* dbl sub    */
521 #define M_FMUL(a,b,c)           M_FP3(0x02,FMT_F,a,b,c)         /* flt mul    */
522 #define M_DMUL(a,b,c)           M_FP3(0x02,FMT_D,a,b,c)         /* dbl mul    */
523 #define M_FDIV(a,b,c)           M_FP3(0x03,FMT_F,a,b,c)         /* flt div    */
524 #define M_DDIV(a,b,c)           M_FP3(0x03,FMT_D,a,b,c)         /* dbl div    */
525
526 #define M_FSQRT(a,c)            M_FP2(0x04,FMT_F,a,c)           /* flt sqrt   */
527 #define M_DSQRT(a,c)            M_FP2(0x04,FMT_D,a,c)           /* dbl sqrt   */
528 #define M_FABS(a,c)             M_FP2(0x05,FMT_F,a,c)           /* flt abs    */
529 #define M_DABS(a,c)             M_FP2(0x05,FMT_D,a,c)           /* dbl abs    */
530 #define M_FMOV(a,c)             M_FP2(0x06,FMT_F,a,c)           /* flt mov    */
531 #define M_DMOV(a,c)             M_FP2(0x06,FMT_D,a,c)           /* dbl mov    */
532 #define M_FNEG(a,c)             M_FP2(0x07,FMT_F,a,c)           /* flt neg    */
533 #define M_DNEG(a,c)             M_FP2(0x07,FMT_D,a,c)           /* dbl neg    */
534
535 #define M_ROUNDFI(a,c)          M_FP2(0x0c,FMT_F,a,c)           /* flt roundi */
536 #define M_ROUNDDI(a,c)          M_FP2(0x0c,FMT_D,a,c)           /* dbl roundi */
537 #define M_TRUNCFI(a,c)          M_FP2(0x0d,FMT_F,a,c)           /* flt trunci */
538 #define M_TRUNCDI(a,c)          M_FP2(0x0d,FMT_D,a,c)           /* dbl trunci */
539 #define M_CEILFI(a,c)           M_FP2(0x0e,FMT_F,a,c)           /* flt ceili  */
540 #define M_CEILDI(a,c)           M_FP2(0x0e,FMT_D,a,c)           /* dbl ceili  */
541 #define M_FLOORFI(a,c)          M_FP2(0x0f,FMT_F,a,c)           /* flt trunci */
542 #define M_FLOORDI(a,c)          M_FP2(0x0f,FMT_D,a,c)           /* dbl trunci */
543
544 #define M_ROUNDFL(a,c)          M_FP2(0x08,FMT_F,a,c)           /* flt roundl */
545 #define M_ROUNDDL(a,c)          M_FP2(0x08,FMT_D,a,c)           /* dbl roundl */
546 #define M_TRUNCFL(a,c)          M_FP2(0x09,FMT_F,a,c)           /* flt truncl */
547 #define M_TRUNCDL(a,c)          M_FP2(0x09,FMT_D,a,c)           /* dbl truncl */
548 #define M_CEILFL(a,c)           M_FP2(0x0a,FMT_F,a,c)           /* flt ceill  */
549 #define M_CEILDL(a,c)           M_FP2(0x0a,FMT_D,a,c)           /* dbl ceill  */
550 #define M_FLOORFL(a,c)          M_FP2(0x0b,FMT_F,a,c)           /* flt truncl */
551 #define M_FLOORDL(a,c)          M_FP2(0x0b,FMT_D,a,c)           /* dbl truncl */
552
553 #define M_CVTDF(a,c)            M_FP2(0x20,FMT_D,a,c)           /* dbl2flt    */
554 #define M_CVTIF(a,c)            M_FP2(0x20,FMT_I,a,c)           /* int2flt    */
555 #define M_CVTLF(a,c)            M_FP2(0x20,FMT_L,a,c)           /* long2flt   */
556 #define M_CVTFD(a,c)            M_FP2(0x21,FMT_F,a,c)           /* flt2dbl    */
557 #define M_CVTID(a,c)            M_FP2(0x21,FMT_I,a,c)           /* int2dbl    */
558 #define M_CVTLD(a,c)            M_FP2(0x21,FMT_L,a,c)           /* long2dbl   */
559 #define M_CVTFI(a,c)            M_FP2(0x24,FMT_F,a,c)           /* flt2int    */
560 #define M_CVTDI(a,c)            M_FP2(0x24,FMT_D,a,c)           /* dbl2int    */
561 #define M_CVTFL(a,c)            M_FP2(0x25,FMT_F,a,c)           /* flt2long   */
562 #define M_CVTDL(a,c)            M_FP2(0x25,FMT_D,a,c)           /* dbl2long   */
563
564 #define M_MOVDI(d,i)            M_FP3(0,0,d,i,0)                /* i = d      */
565 #define M_MOVDL(d,l)            M_FP3(0,1,d,l,0)                /* l = d      */
566 #define M_MOVID(i,d)            M_FP3(0,4,d,i,0)                /* d = i      */
567 #define M_MOVLD(l,d)            M_FP3(0,5,d,l,0)                /* d = l      */
568
569 #define M_MFC1(l,f)             M_FP3(0,0,f,l,0)
570 #define M_MTC1(l,f)             M_FP3(0,4,f,l,0)
571
572 #define M_DMFC1(l,f)            M_FP3(0,1,f,l,0)
573 #define M_DMTC1(l,f)            M_FP3(0,5,f,l,0)
574
575 #define M_FCMPFF(a,b)           M_FP3(0x30,FMT_F,a,b,0)         /* c = a == b */
576 #define M_FCMPFD(a,b)           M_FP3(0x30,FMT_D,a,b,0)         /* c = a == b */
577 #define M_FCMPUNF(a,b)          M_FP3(0x31,FMT_F,a,b,0)         /* c = a == b */
578 #define M_FCMPUND(a,b)          M_FP3(0x31,FMT_D,a,b,0)         /* c = a == b */
579 #define M_FCMPEQF(a,b)          M_FP3(0x32,FMT_F,a,b,0)         /* c = a == b */
580 #define M_FCMPEQD(a,b)          M_FP3(0x32,FMT_D,a,b,0)         /* c = a == b */
581 #define M_FCMPUEQF(a,b)         M_FP3(0x33,FMT_F,a,b,0)         /* c = a == b */
582 #define M_FCMPUEQD(a,b)         M_FP3(0x33,FMT_D,a,b,0)         /* c = a == b */
583 #define M_FCMPOLTF(a,b)         M_FP3(0x34,FMT_F,a,b,0)         /* c = a <  b */
584 #define M_FCMPOLTD(a,b)         M_FP3(0x34,FMT_D,a,b,0)         /* c = a <  b */
585 #define M_FCMPULTF(a,b)         M_FP3(0x35,FMT_F,a,b,0)         /* c = a <  b */
586 #define M_FCMPULTD(a,b)         M_FP3(0x35,FMT_D,a,b,0)         /* c = a <  b */
587 #define M_FCMPOLEF(a,b)         M_FP3(0x36,FMT_F,a,b,0)         /* c = a <= b */
588 #define M_FCMPOLED(a,b)         M_FP3(0x36,FMT_D,a,b,0)         /* c = a <= b */
589 #define M_FCMPULEF(a,b)         M_FP3(0x37,FMT_F,a,b,0)         /* c = a <= b */
590 #define M_FCMPULED(a,b)         M_FP3(0x37,FMT_D,a,b,0)         /* c = a <= b */
591
592 #define M_FBF(disp)             M_ITYPE(0x11,8,0,disp)          /* br false   */
593 #define M_FBT(disp)             M_ITYPE(0x11,8,1,disp)          /* br true    */
594 #define M_FBFL(disp)            M_ITYPE(0x11,8,2,disp)          /* br false   */
595 #define M_FBTL(disp)            M_ITYPE(0x11,8,3,disp)          /* br true    */
596
597 #define M_CMOVF(a,b)                    M_RTYPE(0x00,a,0,b,0,1)
598 #define M_CMOVT(a,b)                    M_RTYPE(0x00,a,1,b,0,1)
599
600
601 /*
602  * Load Address pseudo instruction:
603  * -n32 addressing mode -> 32 bit addrs, -64 addressing mode -> 64 bit addrs
604  */
605 #if SIZEOF_VOID_P == 8
606
607 #define POINTERSHIFT 3
608
609 #define M_ALD_INTERN(a,b,disp)  M_LLD_INTERN(a,b,disp)
610 #define M_ALD(a,b,disp)         M_LLD(a,b,disp)
611 #define M_AST_INTERN(a,b,disp)  M_LST_INTERN(a,b,disp)
612 #define M_AST(a,b,disp)         M_LST(a,b,disp)
613 #define M_AADD(a,b,c)           M_LADD(a,b,c)
614 #define M_AADD_IMM(a,b,c)       M_LADD_IMM(a,b,c)
615 #define M_ASUB_IMM(a,b,c)       M_LSUB_IMM(a,b,c)
616 #define M_ASLL_IMM(a,b,c)       M_LSLL_IMM(a,b,c)
617
618 #else /* SIZEOF_VOID_P == 8 */
619
620 #define POINTERSHIFT 2
621
622 #define M_ALD_INTERN(a,b,disp)  M_ILD_INTERN(a,b,disp)
623 #define M_ALD(a,b,disp)         M_ILD(a,b,disp)
624 #define M_AST_INTERN(a,b,disp)  M_IST_INTERN(a,b,disp)
625 #define M_AST(a,b,disp)         M_IST(a,b,disp)
626 #define M_AADD(a,b,c)           M_IADD(a,b,c)
627 #define M_AADD_IMM(a,b,c)       M_IADD_IMM(a,b,c)
628 #define M_ASUB_IMM(a,b,c)       M_ISUB_IMM(a,b,c)
629 #define M_ASLL_IMM(a,b,c)       M_ISLL_IMM(a,b,c)
630
631 #endif /* SIZEOF_VOID_P == 8 */
632
633 #endif /* _CODEGEN_H */
634
635
636 /*
637  * These are local overrides for various environment variables in Emacs.
638  * Please do not remove this and leave it at the end of the file, where
639  * Emacs will automagically detect them.
640  * ---------------------------------------------------------------------
641  * Local variables:
642  * mode: c
643  * indent-tabs-mode: t
644  * c-basic-offset: 4
645  * tab-width: 4
646  * End:
647  */