* Removed all Id tags.
[cacao.git] / src / vm / jit / m68k / codegen.h
1 /* src/vm/jit/m68k/codegen.h
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25 */
26
27
28 #ifndef _CODEGEN_H
29 #define _CODEGEN_H
30
31 #include "config.h"
32
33 #include <stdint.h>
34
35 #include "md-abi.h"
36 #include "vm/jit/m68k/emit.h"
37
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 /* branch defines *************************************************************/
47
48 #define BRANCH_NOPS \
49     do { \
50         if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { \
51             M_NOP; \
52             M_NOP; \
53             M_NOP; \
54         } else { \
55             M_NOP; \
56             M_NOP; \
57         } \
58     } while (0)
59
60
61 /* patcher defines ************************************************************/
62
63 #define PATCHER_NOPS \
64         do { M_TPFL; M_TPF; M_TPF } while (0);
65
66 #define PATCHER_CALL_SIZE       (3*2)
67
68 /* stub defines ***************************************************************/
69
70 #define COMPILERSTUB_CODESIZE (6+6+2)
71
72
73 /* coldfire instruction format:
74  * -----------------------------
75  * | Op Word                    |
76  * |____________________________|
77  * | extension word 1(optional) |
78  * |____________________________|
79  * | extension word 2(optional) |
80  * |____________________________|
81  *
82  *
83  * Opword:
84  *
85  *                     | effective addr
86  *                     |  mode |  reg.
87  * x x x x x x x x x x | M M M | R R R
88  *
89  * MMM = 000 ---> data register   direct: RRR = register
90  * MMM = 001 ---> addr register   direct: RRR = register
91  * MMM = 010 ---> addr register indirect: RRR = register
92  * MMM = 011 ---> addr reg ind postincr : RRR = register
93  * MMM = 100 ---> addr reg ind predecr  : RRR = register
94  * MMM = 101 ---> addr reg ind + displac: RRR = register + ext.wrd.1
95  * MMM = 110 ---> addr reg ind + scaled index and 8 bit displacement
96  * MMM = 111, RRR = 010 ---> PC ind. with displacement + ext.wrd.1
97  * MMM = 111, RRR = 011 ---> PC ind. with scaled inex + 8but displacement
98  * MMM = 111, RRR = 000 + ext.wrd.1 ---> absolute short
99  * MMM = 111, RRR = 001 + ext.wrd.1+2 -> absolute long
100  * MMM = 111, RRR = 100 + ext.wrd1/2 --> immediate data
101  */
102
103 /* one word opcodes */
104 #define OPWORD(op, mode, reg) \
105         do { \
106                 *((u2*)cd->mcodeptr) = (u2) (((op) << 6) | ((mode)<<3) | (reg)); \
107                 cd->mcodeptr += 2; \
108         } while(0);
109 /* opword + one extension word */
110 /* usage of int16_t instead of s2 as is clashes with variable name */
111 #define OPWORD_IMM16(op, mode, reg, imm) \
112         do { \
113                 *((u2*)cd->mcodeptr) = (u2) (((op) << 6) | ((mode)<<3) | (reg)); \
114                 cd->mcodeptr += 2; \
115                 *((int16_t*)(cd->mcodeptr)) = imm; \
116                 cd->mcodeptr += 2; \
117         } while(0);
118
119 /* opword + two extension words */
120 /* usage of int32_t instead of s4 as is clashes with variable name */
121 #define OPWORD_IMM32(op, mode, reg, imm) \
122         do { \
123                 *((u2*)cd->mcodeptr) = (u2) (((op) << 6) | ((mode)<<3) | (reg)); \
124                 cd->mcodeptr += 2; \
125                 *((int32_t*)(cd->mcodeptr)) = imm; \
126                 cd->mcodeptr += 4; \
127         } while(0);
128
129 /* create NOPS to align basicblock boundaries 
130  * using real nops here as they are not executed, so no performance penalty
131  **/
132 #define ALIGNCODENOP \
133     do { \
134         for (s1 = 0; s1 < (s4) (((ptrint) cd->mcodeptr) & 7); s1++) \
135             M_NOP; \
136     } while (0)
137
138
139
140
141 #define M_NOP           OPWORD(0x139,6,1)                               /* 0x4371 do not use as it syncs pipeline */
142 #define M_ILLEGAL       OPWORD(0x12b,7,4)                               /* 0x4afc */
143 #define M_TPF           OPWORD(0x147,7,4)                               /* tfp with no  ext. word use instead of NOP*/
144 #define M_TPFW          OPWORD(0x147,7,2)                               /* tfp with one ext. word */
145 #define M_TPFL          OPWORD(0x147,7,3)                               /* tfp with two ext. word */
146
147 /*M_XMOVX....M_XMOVX(source, destination) */
148 #define M_IMOV(a,b)     OPWORD( ( (2<<6) | ((b) << 3) | 0), 0, (a))     /* move.l */
149 #define M_AMOV(a,b)     OPWORD( ( (2<<6) | ((b) << 3) | 1), 1, (a))     /* movea.l */
150 #define M_IMOV_IMM(a,b) emit_mov_imm_reg(cd, (a), (b))
151 #define M_AMOV_IMM(a,b) OPWORD_IMM32( ( (2<<6) | ((b) << 3) | 1), 7, 4, (a))
152
153 /* for sure generates a 32 bit immedeate form, needed when there are patchers involved */
154 #define M_IMOV_IMM32(a,b)       OPWORD_IMM32(((2<<6) | ((b) << 3) | 0), 7, 4, (a))
155
156 #define M_ICLR(a)       OPWORD(0x10a, 0, (a))                           /* clr.l */
157 #define M_ISET(a)       OPWORD( ( (0xa <<6) | (0 << 3) | 5), 0, (a))    /* mov3q #-1 */
158
159 #define M_JMP(a)        OPWORD(0x13b,2,(a))                             /* jmp %aX@ */
160 #define M_JMP_IMM(a)    OPWORD_IMM32(0x13b,7,1,(a))                     /* jmp.l */
161 #define M_JSR(a)        OPWORD(0x13a,2,(a))                             /* jsr %aX@ */
162 #define M_JSR_IMM(a)    OPWORD_IMM32(0x13a,7,1,(a))                     /* jsr.l */
163 #define M_BSR_IMM(a)    OPWORD_IMM32(0x187,7,7,(a))                     /* bsr.l */
164 #define M_JSR_PCREL(a)  OPWORD_IMM16(0x13a,7,2,(a))                     /* jsr.l (d16,PC) */
165
166 #define M_RET           OPWORD(0x139,6,5)                               /* 0x4375 */
167 #define M_LINK(a,b)     OPWORD_IMM16(0x139,2,(a), (b))                  /* link */
168 #define M_UNLK(a)       OPWORD(0x139, 3, (a))                           /* unlk */
169
170 /* push and pop are implemented using move.l */
171 /* we need 3 variants, data, address and float registers */
172 /* also a POPALL and PUSHALL for verbose:call code, use them only there! */
173 #define M_IPUSH(a)              OPWORD(0xbc,0,(a))
174 #define M_APUSH(a)              OPWORD(0xbc,1,(a))
175
176 #define M_IPOP(a)               OPWORD( ( (2<<6) | ((a) << 3) | 0 ), 3, REG_SP)
177 #define M_APOP(a)               OPWORD( ( (2<<6) | ((a) << 3) | 1 ), 3, REG_SP)         /* movea.l acutally */
178
179
180 #define M_IPUSH_IMM(a)          OPWORD_IMM32(0x121,7,1, (a))                            /* pea.l */
181
182 #if 0
183 #define M_PUSHALL               OPWORD_IMM16(0x123,2,REG_SP,0xFFFF)                     /* A0-A7, D0-D7 pushed onto stack */
184 #define M_POPALL                OPWORD_IMM16(0x133,2,REG_SP,0xFFFF)                     /* A0-A7, D0-D7 poped off stack */
185 #endif
186
187 /* M_XLD(a,b,c)....M_XLD(destinationreg, addressbase, offset)   */
188 #define M_ILD(a,b,c)            OPWORD_IMM16( ( (2<<6) | ((a) << 3) | 0), 5, (b), (c))
189 #define M_ALD(a,b,c)            OPWORD_IMM16( ( (2<<6) | ((a) << 3) | 1), 5, (b), (c))
190 #define M_LLD(a,b,c)            do {\
191                                         M_ILD(GET_HIGH_REG(a), (b), (c));\
192                                         M_ILD(GET_LOW_REG (a), (b), (c)+4);\
193                                 } while(0);
194
195 #if !defined(ENABLE_SOFTFLOAT)
196         #define M_FLD(a,b,c)            OPWORD_IMM32( 0x3c8, 5, (b), ( (( (0x11 << 10) | ((a)<<7) | 0x40 )<<16) | (((int16_t)(c)) & 0x0000ffff)) )
197         #define M_DLD(a,b,c)            OPWORD_IMM32( 0x3c8, 5, (b), ( (( (0x15 << 10) | ((a)<<7) | 0x44 )<<16) | (((int16_t)(c)) & 0x0000ffff)) )
198 #endif
199
200 /* M_XST(a,b,c)....M_XST(sourceregister, addressbase, offset)   */
201 #define M_IST(a,b,c)            OPWORD_IMM16( ( (2<<6) | ((b) << 3) | 5), 0, (a), (c))
202 #define M_AST(a,b,c)            OPWORD_IMM16( ( (2<<6) | ((b) << 3) | 5), 1, (a), (c))
203 #define M_LST(a,b,c)            do      {\
204                                         M_IST(GET_HIGH_REG(a), (b), (c));\
205                                         M_IST(GET_LOW_REG (a), (b), (c)+4);\
206                                 } while(0);
207
208 #if !defined(ENABLE_SOFTFLOAT)
209         #define M_FST(a,b,c)            OPWORD_IMM32( 0x3c8, 5, (b), ( ((  (0x19 <<10) | ((a)<<7) | 0  )<<16) | (((int16_t)(c)) & 0x0000ffff)) )
210         #define M_DST(a,b,c)            OPWORD_IMM32( 0x3c8, 5, (b), ( ((  (0x1d <<10) | ((a)<<7) | 0  )<<16) | (((int16_t)(c)) & 0x0000ffff)) )
211         #define M_FSTORE(a,b,c)         OPWORD_IMM32( 0x3c8, 5, (b), ( ( (0xf << 12) | (1 << (7-(a))) ) <<16) | (((int16_t)(c)) & 0x0000ffff))
212         #define M_FLOAD(a,b,c)          OPWORD_IMM32( 0x3c8, 5, (b), ( ( (0xd << 12) | (1 << (7-(a))) ) <<16) | (((int16_t)(c)) & 0x0000ffff))
213 #endif
214
215 /*M_XADD_IMM(a,b)...M_XADD_IMM(offset, reg) */
216 #define M_AADD_IMM(a,b)         OPWORD_IMM32( ( (0xd<<6) | ((b)<<3) | 7), 7, 4, (a))
217 #define M_IADD_IMM(a,b)         OPWORD_IMM32( ( (0xd<<6) | ((b)<<3) | 2), 7, 4, (a))
218 #define M_ISUB_IMM(a,b)         M_IADD_IMM(-(a), (b))
219
220 /* M_OP(source, dest) ...  dest (OP) source -> dest*/
221 #define M_ISUB(a,b)             OPWORD ( ( (9<<6)   | ((b)<<3) | 2), 0, (a))                    /* sub.l */
222 #define M_ISUBX(a,b)    OPWORD ( ( (9<<6)   | ((b)<<3) | 6), 0, (a))                    /* subx.l */
223 #define M_IADD(a,b)             OPWORD ( ( (0xd<<6) | ((b)<<3) | 2), 0, (a))                    /* add.l */
224 #define M_IADDX(a,b)    OPWORD ( ( (0xd<<6) | ((b)<<3) | 6), 0, (a))                    /* addx.l */
225
226 #define M_IMUL(a,b)             OPWORD_IMM16 ( 0x130, 0, (a), ( ((b) << 12) | (1 << 11)))       /* muls.l */
227 #define M_IDIV(a,b)             OPWORD_IMM16 ( 0x131, 0, (a), ( ((b) << 12) | (1 << 11) | (b))) /* divs.l */
228
229 #define M_ISSL(a,b)             OPWORD ( ( (0xe<<6) | ((a) << 3) | 6), 4, (b))                  /* asl.l */
230 #define M_ISSR(a,b)             OPWORD ( ( (0xe<<6) | ((a) << 3) | 2), 4, (b))                  /* asr.l */
231 #define M_IUSR(a,b)             OPWORD ( ( (0xe<<6) | ((a) << 3) | 2), 5, (b))                  /* lsr.l */
232
233 #define M_IAND(a,b)             OPWORD ( ( (0xc<<6) | ((b) << 3) | 2), 0, (a))                  /* and.l */
234 #define M_IOR(a,b)              OPWORD ( ( (0x8<<6) | ((b) << 3) | 2), 0, (a))                  /* or.l */
235 #define M_IXOR(a,b)             OPWORD ( ( (0xb<<6) | ((a) << 3) | 6), 0, (b))                  /* eor.l */
236
237
238 /* M_IX_IMM(imm, register)      */
239 #define M_IAND_IMM(a,b)         OPWORD_IMM32( 0xa, 0, (b), (a))                                 /* andi.l # */
240 #define M_IOR_IMM(a,b)          OPWORD_IMM32( 0x2, 0, (b), (a))                                 /* ori.l # */
241 #define M_IXOR_IMM(a,b)         OPWORD_IMM32( 0x2a,0, (b), (a))                                 /* eori.l # */
242
243
244 /* ultra sepcial 3 register form, b%a = c, (a!=c) */
245 #define M_IREM(a,b,c)           OPWORD_IMM16 ( 0x131, 0, (a), ( ((b) << 12) | (1 << 11) | (c))) /* rems.l */
246
247 /* M_OP(dest) */
248 #define M_INEG(a)               OPWORD(0x112, 0, (a))                                           /* neg.l */
249 #define M_INEGX(a)              OPWORD(0x102, 0, (a))                                           /* neg.l */
250
251 /* only generate opcode when condition true */
252 #define OPWORD_COND(c, u,v,w)   \
253         do { \
254                 if ( (c) ) { OPWORD( (u),(v),(w) ) }  \
255         } while(0);
256 #define OPWORD_IMM16_COND(c, u,v,w,x)   \
257         do { \
258                 if ( (c) ) { OPWORD_IMM16( (u),(v),(w),(x) ) }  \
259         } while(0);
260 /* assert on the opcode */
261 #define OPWORD_ASSERT(a, u,v,w) \
262         do { \
263                 assert((a)); \
264                 OPWORD( (u),(v),(w) )  \
265         } while(0);
266
267 /* M_XMOVE....M_XMOVE(sourcereg, destreg) */
268 #define M_INTMOVE(a,b)          OPWORD_COND(((a) != (b)), ( ( 2<<6) | ((b) << 3) | 0), 0, (a));
269 #define M_ADRMOVE(a,b)          OPWORD_COND(((a) != (b)), ( ( 2<<6) | ((b) << 3) | 1), 1, (a));
270 #define M_INT2ADRMOVE(a,b)      OPWORD( ( (2<<6) | ((b) << 3) | 1), 0, (a));
271 #define M_ADR2INTMOVE(a,b)      OPWORD( ( (2<<6) | ((b) << 3) | 0), 1, (a));
272 #define M_LNGMOVE(a,b)          do      {\
273                                         M_INTMOVE(GET_LOW_REG (a), GET_LOW_REG (b));\
274                                         M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b));\
275                                 } while(0);
276
277 #if !defined(ENABLE_SOFTLFOAT)
278         #define M_FLTMOVE(a,b)          OPWORD_IMM16_COND( ((a)!=(b)), 0x3c8, 0, 0, ((a)<<10) | ((b)<<7) | 0x40)
279         #define M_INT2FLTMOVE(a,b)      OPWORD_IMM16( 0x3c8, 0, (a), ((0x11 << 10) | ((b) << 7) | 0x40 )) 
280         #define M_DBLMOVE(a,b)          OPWORD_IMM16_COND( ((a)!=(b)), 0x3c8, 0, 0, ((a)<<10) | ((b)<<7) | 0x44)
281 #endif
282 /* M_XTST....M_XTST(register) */
283 #define M_ITST(a)               OPWORD(0x12a, 0, (a))                   /* tst.l */
284 #define M_ATST(a)               OPWORD(0x12a, 1, (a))                   /* tst.l */
285
286 /* M_XCMPI....M_XMCPI(immideate, register) */
287 #define M_ICMP_IMM(a,b)         OPWORD_IMM32( 0x32, 0, (b), (a))
288 #if 0
289 #define M_ACMPI(a,b)            OPWORD_IMM32( ( (0xb << 6) | ((b) << 3) | 7), 7, 4, (a))        /* cmpa.l # */
290 #endif
291 /* M_XCMP....M_XCMP(reg1, reg2) */
292 #define M_ICMP(b,a)             OPWORD( ( (0xb << 6) | ((a) << 3) | 2), 0, (b))                 /* cmp.l */
293 #define M_ACMP(b,a)             OPWORD( ( (0xb << 6) | ((a) << 3) | 7), 1, (b))                 /* cmpa.l */
294
295
296 /* All kind of branches one could ever possibly need, each with 16 and 32 bit displacement */
297 /* BRANCH16 and BRANCH32 are helpers */
298 #define BRANCH8(cond,imm) \
299         do { \
300                 *((u2*)cd->mcodeptr) = (u2) (((0x6) << 12) | ((cond)<<8) | (int8_t)imm); \
301                 cd->mcodeptr += 2; \
302         } while(0);
303
304 #define BRANCH16(cond,imm) \
305         do { \
306                 *((u2*)cd->mcodeptr) = (u2) (((0x6) << 12) | ((cond)<<8) | 0x00); \
307                 cd->mcodeptr += 2; \
308                 *((int16_t*)(cd->mcodeptr)) = imm; \
309                 cd->mcodeptr += 2; \
310         } while(0);
311 #define BRANCH32(cond,imm) \
312         do { \
313                 *((u2*)cd->mcodeptr) = (u2) (((0x6) << 12) | ((cond)<<8) | 0xff); \
314                 cd->mcodeptr += 2; \
315                 *((int32_t*)(cd->mcodeptr)) = imm; \
316                 cd->mcodeptr += 4; \
317         } while(0);
318
319 #define M_BR_16(a)                      BRANCH16(0x0, (a))      /* branch always */
320 #define M_BR_32(a)                      BRANCH32(0x0, (a))
321
322 #define M_BCS(a)                        BRANCH8 (0x5, (a))      /* carry set */
323
324 #define M_BEQ(a)                        BRANCH8 (0x7, (a))
325 #define M_BEQ_16(a)                     BRANCH16(0x7, (a))
326 #define M_BEQ_32(a)                     BRANCH32(0x7, (a))
327
328 #define M_BNE(a)                        BRANCH8 (0x6, (a))
329 #define M_BNE_16(a)                     BRANCH16(0x6, (a))
330 #define M_BNE_32(a)                     BRANCH32(0x6, (a))
331
332 #define M_BLT(a)                        BRANCH8 (0xd, (a))
333 #define M_BLT_16(a)                     BRANCH16(0xd, (a))
334 #define M_BLT_32(a)                     BRANCH32(0xd, (a))
335
336 #define M_BGE(a)                        BRANCH8 (0xc, (a))
337 #define M_BGE_16(a)                     BRANCH16(0xc, (a))
338 #define M_BGE_32(a)                     BRANCH32(0xc, (a))
339
340 #define M_BGT(a)                        BRANCH8 (0xe, (a))
341 #define M_BGT_16(a)                     BRANCH16(0xe, (a))
342 #define M_BGT_32(a)                     BRANCH32(0xe, (a))
343
344 #define M_BLE(a)                        BRANCH8 (0xf, (a))
345 #define M_BLE_16(a)                     BRANCH16(0xf, (a))
346 #define M_BLE_32(a)                     BRANCH32(0xf, (a))
347
348 #define M_BHI(a)                        BRANCH8 (0x2, (a))
349 #define M_BHI_16(a)                     BRANCH16(0x2, (a))
350 #define M_BHI_32(a)                     BRANCH32(0x2, (a))
351
352 #define M_BLS(a)                        BRANCH8 (0x3, (a))
353
354 #define M_BMI(a)                        BRANCH8(0xb, (a))
355 #define M_BPL(a)                        BRANCH8(0xa, (a))
356
357 #define M_BNAN_16(a)                    M_ILLEGAL               /* TODO */
358 #define M_BNAN_32(a)                    M_ILLEGAL
359
360
361
362 /* array store/load stuff */
363 /* M_LXXX(baseaddressregister, targetregister)  */
364 /* M_SXXX(baseaddressregsiter, sourceregister)  */
365 #define M_LBZX(a,c)                     OPWORD( ( (1<<6) | ((c) << 3) | 0), 2, (a))     /* move.l */
366 #define M_LHZX(a,c)                     OPWORD( ( (3<<6) | ((c) << 3) | 0), 2, (a))
367 #define M_LWZX(a,c)                     OPWORD( ( (2<<6) | ((c) << 3) | 0), 2, (a))
368 #define M_LAX(a,c)                      OPWORD( ( (2<<6) | ((c) << 3) | 1), 2, (a))     /* movea.l */
369
370 #define M_STBX(a,c)                     OPWORD( ( (1<<6) | ((a) << 3) | 2), 0, (c))     /* move.l */
371 #define M_STHX(a,c)                     OPWORD( ( (3<<6) | ((a) << 3) | 2), 0, (c))
372 #define M_STWX(a,c)                     OPWORD( ( (2<<6) | ((a) << 3) | 2), 0, (c))
373 #define M_STAX(a,c)                     OPWORD( ( (2<<6) | ((a) << 3) | 2), 1, (c))     /* movea.l */
374
375
376 #define M_BSEXT(a,b)                    OPWORD( ( (7<<6) | ((b) << 3) | 4), 0, (a))     /* mvs.b */
377 #define M_CZEXT(a,b)                    OPWORD( ( (7<<6) | ((b) << 3) | 7), 0, (a))     /* mvz.w */
378 #define M_SSEXT(a,b)                    OPWORD( ( (7<<6) | ((b) << 3) | 5), 0, (a))     /* mvs.w */
379 #define M_HSEXT(a,b)                    M_ILLEGAL
380
381 /* adds content of integer reg a to address register b, result is b */
382 #define M_AADDINT(a,b)                  OPWORD( ( (0xd<<6) | ((b) << 3) | 7), 0, (a))   /* adda.l */
383 #define M_ASUBINT(a,b)                  OPWORD( ( (0x9<<6) | ((b) << 3) | 7), 0, (a))   /* suba.l */
384
385 /* immideate a shift left int register b, immideate has 3 bits */
386 #define M_ISSL_IMM(a,b)                 OPWORD_ASSERT( ((a)<=7), ( (0xe<<6) | ((a) << 3) | 6), 1, (b))  /* lsl */
387 #define M_ISSR_IMM(a,b)                 OPWORD_ASSERT( ((a)<=7), ( (0xe<<6) | ((a) << 3) | 2), 0, (b))  /* lsl */
388 #define M_IUSR_IMM(a,b)                 OPWORD_ASSERT( ((a)<=7), ( (0xe<<6) | ((a) << 3) | 2), 1, (b))  /* lsl */
389
390
391 /* constant handling */
392 /* XCONST(constant value, register) */
393 #define LCONST(a,b)                     do {\
394                                                 M_IMOV_IMM(((uint32_t)(a)), GET_LOW_REG((b)));\
395                                                 M_IMOV_IMM(((uint32_t)(a>>32)), GET_HIGH_REG((b)));\
396                                         } while(0);
397
398 #if !defined(ENABLE_SOFTFLOAT)
399         #define FCONST(a,b)             do      {\
400                                                         M_IMOV_IMM((a), REG_ITMP1);\
401                                                         OPWORD_IMM16( 0x3c8, 0, REG_ITMP1, ( (0x11 << 10) | ((b)<<7) | 0x40) );\
402                                                 } while(0);
403 #endif
404
405 #define M_TRAP_SETREGISTER(a)           OPWORD( 0x128, 0, (a))          /* tst.b */
406 #define M_TRAP(a) \
407         do { \
408                 *((u2*)cd->mcodeptr) = (u2) ( 0x4e40 | (a) ); \
409                 cd->mcodeptr += 2; \
410         } while(0);
411
412
413 #if !defined(ENABLE_SOFTFLOAT)
414         
415         #define M_FCMP(b,a)             OPWORD_IMM16(0x3c8, 0, 0, ((a)<<10) | ((b)<<7) | 0x38 )                 /* fcmp.d */
416
417         #define M_BFEQ(a)               OPWORD_IMM16(0x3ca, 0, 0x01, (a))
418         #define M_BFLT(a)               OPWORD_IMM16(0x3ca, 0, 0x14, (a))
419         #define M_BFGT(a)               OPWORD_IMM16(0x3ca, 0, 0x12, (a))
420         #define M_BFUN(a)               OPWORD_IMM16(0x3ca, 0, 0x10, (a))
421
422         #define M_FADD(a,b)             OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x62 )             /* fsadd */
423         #define M_DADD(a,b)             OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x66 )             /* fdadd */
424
425         #define M_FSUB(a,b)             OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x68 )             /* fssub */
426         #define M_DSUB(a,b)             OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x6c )             /* fdsub */
427
428         #define M_FMUL(a,b)             OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x63 )             /* fsmul */
429         #define M_DMUL(a,b)             OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x67 )             /* fdmul */
430
431         #define M_FDIV(a,b)             OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x60 )             /* fsdiv */
432         #define M_DDIV(a,b)             OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x64 )             /* fddiv */
433
434         #define M_D2F(a,b)              OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x44 )             /* fsmoved */
435         #define M_F2D(a,b)              OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x40 )             /* fdmoved */
436
437         #define M_FNEG(a,b)             OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x5a )             /* fneg.s */
438         #define M_DNEG(a,b)             OPWORD_IMM16(0x3c8, 0, 0, ((a) << 10) | ((b) << 7) | 0x5e )             /* fneg.d */
439 #endif
440
441 #endif /* _CODEGEN_H */
442
443 /*
444  * These are local overrides for various environment variables in Emacs.
445  * Please do not remove this and leave it at the end of the file, where
446  * Emacs will automagically detect them.
447  * ---------------------------------------------------------------------
448  * Local variables:
449  * mode: c
450  * indent-tabs-mode: t
451  * c-basic-offset: 4
452  * tab-width: 4
453  * End:
454  * vim:noexpandtab:sw=4:ts=4:
455  */