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