b64cf4fc656ed4f6bf991b7ae42fee51ee512caf
[cacao.git] / src / vm / jit / sparc64 / codegen.h
1 /* src/vm/jit/sparc64/codegen.h - code generation macros and
2                                   definitions for SPARC64
3
4    Copyright (C) 1996-2005, 2006, 2007, 2008
5    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6
7    This file is part of CACAO.
8
9    This program is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2, or (at
12    your option) any later version.
13
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22    02110-1301, USA.
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 #include "md-abi.h" /* for INT_NATARG_CNT */
35
36 #include <assert.h>
37
38 /* debug defines **************************************************************/
39 #ifndef NDEBUG
40 # define PASS13BIT(imm) ((((s4)(imm)&0x1fff)<<19)>>19)
41 #else
42 # define PASS13BIT(imm) imm
43 #endif
44
45
46 /* from md-abi.c */
47 s4 nat_argintregs[INT_NATARG_CNT];
48
49 /* branch defines *************************************************************/
50
51 #define BRANCH_NOPS \
52     do { \
53         M_NOP; \
54         M_NOP; \
55     } while (0)
56
57
58 /* patcher defines ************************************************************/
59
60 #define PATCHER_CALL_INSTRUCTIONS    2     /* number of instructions          */
61 #define PATCHER_CALL_SIZE            2 * 4 /* size in bytes of a patcher call */
62
63 #define EXCEPTION_CHECK_INSTRUCTIONS 3     /* number of instructions          */
64 #define EXCEPTION_CHECK_SIZE         3 * 4 /* byte size of an exception check */
65
66 #define PATCHER_NOPS \
67     do { \
68         M_NOP; \
69         M_NOP; \
70     } while (0)
71
72
73 /* additional functions and macros to generate code ***************************/
74
75
76 /* MCODECHECK(icnt) */
77
78 #define MCODECHECK(icnt) \
79         do { \
80                 if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
81                         codegen_increase(cd); \
82         } while (0)
83
84
85 #define ALIGNCODENOP \
86     if ((s4) ((ptrint) cd->mcodeptr & 7)) { \
87         M_NOP; \
88     }
89
90 #define ALIGN_STACK_SLOTS(slots) \
91         if (slots & 1) \
92                 slots++;
93
94
95 /* M_INTMOVE:
96      generates an integer-move from register rs to rd.
97      if rs and rd are the same int-register, no code will be generated.
98 */ 
99
100 #define M_INTMOVE(rs,rd) if (rs != rd) { M_MOV(rs, rd); }
101
102
103 /* M_DBLMOVE:
104     generates a double floating-point-move from register (pair) rs to rd.
105     if rs and rd are the same double-register, no code will be generated
106 */ 
107
108 #define M_DBLMOVE(rs, rd) if (rs != rd) { M_DMOV (rs, rd); }
109
110
111 /* M_FLTMOVE:
112     generates a double floating-point-move from pseudo register rs to rd.
113         (ie. lower register of double rs pair to lower register of double rd pair)
114     if rs and rd are the same double-register, no code will be generated
115 */ 
116 #define M_FLTMOVE(rs, rd) if (rs != rd) { M_FMOV (rs, rd); }
117
118
119
120 #define M_COPY(s,d)                     emit_copy(jd, iptr, (s), (d))
121 #define ICONST(d,c)                     emit_iconst(cd, (d), (c))
122 #define LCONST(d,c)                     emit_lconst(cd, (d), (c))
123
124
125
126
127 /********************** instruction formats ***********************************/
128
129 #define REG     0
130 #define IMM     1
131
132 /* 3-address-operations: M_OP3
133  *       op  ..... opcode
134  *       op3 ..... operation
135  *       rs1 ..... register number source 1
136  *       rs2 ..... register number or constant integer source 2
137  *       rd  ..... register number destination
138  *       imm ..... switch to use rs2 as constant 13bit integer 
139  *                  (REG means: use b as register number)
140  *                  (IMM means: use b as signed immediate value)
141  */
142 #define M_OP3(op,op3,rd,rs1,rs2,imm) \
143         do { \
144                 assert(check_13bit_imm(rs2)); \
145                 *((u4 *) cd->mcodeptr) =  ((((s4) (op)) << 30) | ((rd) << 25) | ((op3) << 19) | ((rs1) << 14) | ((imm)<<13) | (imm?((rs2)&0x1fff):(rs2)) ); \
146                 cd->mcodeptr += 4; \
147         } while (0)
148
149
150 #define M_OP3_GET_RD(x)               (((x) >> 25) & 0x1f)
151 #define M_OP3_GET_RS(x)               (((x) >> 14) & 0x1f)
152 #define M_OP3_GET_IMM(x)              ( (x)        & 0x1fff)
153
154 /* 3-address-operations: M_OP3C
155  *       rcond ... condition opcode
156  *       rs2 ..... register number or 10bit signed immediate
157  *
158  */
159 #define M_OP3C(op,op3,rcond,rd,rs1,rs2,imm) \
160         do { \
161                 *((u4 *) cd->mcodeptr) = ((((s4) (op)) << 30) | ((rd) << 25) | ((op3) << 19) | ((rs1) << 14) | ((imm)<<13) | \
162                         ((rcond) << 10) | (imm?((rs2)&0x3ff):(rs2)) ); \
163                 cd->mcodeptr += 4; \
164         } while (0)
165
166
167 /* shift Format 3
168  *    op ..... opcode
169  *    op3..... op3 code
170  *    rs1 .... source reg 1
171  *    rs2 .... source reg 2 or immediate shift count (5 or 6 bits long depending whether 32 or 64 bit shift)
172  *    rd ..... dest reg
173  *    imm .... switch for constant
174  *    x ...... 0 => 32, 1 => 64 bit shift 
175  */
176 #define M_SHFT(op,op3,rs1,rs2,rd,imm,x) \
177         do { \
178                 *((u4 *) cd->mcodeptr) =  ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((rs1) << 14) | ((imm) << 13) | \
179                         ((x) << 12) | (((imm) && (x))?((rs2) & 0x3f):((rs2) & 0x1f)) ); \
180                 cd->mcodeptr += 4; \
181         } while (0)
182
183
184 /* Format 4
185  *    op ..... opcode
186  *    op3..... op3 code
187  *    cond ... condition opcode
188  *    rs2 .... source 2 or signed 11-bit constant
189  *    rd ..... dest reg
190  *    imm .... switch for constant
191  *    cc{0-2}  32-bit 64-bit or fp condition
192  */
193  #define M_FMT4(op,op3,rd,rs2,cond,cc2,cc1,cc0,imm) \
194         do { \
195                 *((u4 *) cd->mcodeptr) =  ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((cc2) << 18) |  ((cond) << 14) | \
196                         ((imm) << 13) | ((cc1) << 12) | ((cc0) << 11) | ((rs2) & 0x7ff) ); \
197                 cd->mcodeptr += 4; \
198         } while (0)
199
200
201 #define FR_X(r) (((r)<<1) + 1) /* transpose macro for floats which reside in upper half of double word */
202 #define DR_X(r) ((((r)*2)|(((r)*2)>>5)) & 0x1f) /* transpose & pack double, see SPARC spec.            */
203
204 /* 3-address-floating-point-operation
205  *   op .... opcode
206  *   op3,opf .... function-number
207  *   rd .... dest reg
208  *   rs1 ... source reg (-1 signals unused)
209  *   rs2 ... source reg
210  *   
211  *
212  */ 
213 #define M_FOP3(op,op3,opf,rd,rs1,rs2) \
214         do { \
215                 *((u4 *) cd->mcodeptr) =  ( (((s4)(op))<<30) | ((rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:(rs1)) << 14) | \
216                 ((opf)<<5) | (rs2) ); \
217                 cd->mcodeptr += 4; \
218         } while (0)
219 /* float addressing */
220 #define M_FOP3_FX(op,op3,opf,rd,rs1,rs2) \
221         do { \
222                 *((u4 *) cd->mcodeptr) =  ( (((s4)(op))<<30) | (FR_X(rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:FR_X(rs1)) << 14) | \
223                 ((opf)<<5) | FR_X(rs2) ); \
224                 cd->mcodeptr += 4; \
225         } while (0)
226 /* double addressing */
227 #define M_FOP3_DX(op,op3,opf,rd,rs1,rs2) \
228         do { \
229                 *((u4 *) cd->mcodeptr) =  ( (((s4)(op))<<30) | (DR_X(rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:DR_X(rs1)) << 14) | \
230                 ((opf)<<5) | DR_X(rs2) ); \
231                 cd->mcodeptr += 4; \
232         } while (0)
233
234 /* 3-address-floating-point-compare-operation
235  *   op .... opcode
236  *   op3,opf .... function-number
237  *   fcc ... floating point condition code (fcc0 - fcc3)
238  *   rs1 ... source reg
239  *   rs2 ... source reg
240  *   
241  *
242  */ 
243 #define M_FCMP_DX(op,op3,opf,fcc,rs1,rs2) \
244         do { \
245                 *((u4 *) cd->mcodeptr) =  ( (((s4)(op))<<30) | ((fcc)<<25) | ((op3)<<19) | (DR_X(rs1) << 14) | \
246                 ((opf)<<5) | DR_X(rs2) ); \
247                 cd->mcodeptr += 4; \
248         } while (0)
249         
250 #define M_FCMP_FX(op,op3,opf,fcc,rs1,rs2) \
251         do { \
252                 *((u4 *) cd->mcodeptr) =  ( (((s4)(op))<<30) | ((fcc)<<25) | ((op3)<<19) | (FR_X(rs1) << 14) | \
253                 ((opf)<<5) | FR_X(rs2) ); \
254                 cd->mcodeptr += 4; \
255         } while (0)
256
257 /**** format 2 operations ********/
258
259 /* branch on integer reg instruction 
260       op ..... opcode
261       rcond ...... condition to be tested
262       disp16 ... 16-bit relative address to be jumped to (divided by 4)
263       rs1 ..... register to be tested
264       p ..... prediction bit
265       anul .... annullment bit
266 */
267 #define M_BRAREG(op,rcond,rs1,disp16,p,anul) \
268         do { \
269                 *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((anul)<<29) | (0<<28) | ((rcond)<<25) | (3<<22) | \
270                         ( ((disp16)& 0xC000) << 6 ) | (p << 19) | ((rs1) << 14) | ((disp16)&0x3fff) ); \
271                 cd->mcodeptr += 4; \
272         } while (0)
273
274                 
275 /* branch on integer reg instruction 
276       op,op2 .... opcodes
277       cond ...... condition to be tested
278       disp19 ... 19-bit relative address to be jumped to (divided by 4)
279       ccx ..... 32(0) or 64(2) bit test
280       p ..... prediction bit
281       anul .... annullment bit
282 */              
283 #define M_BRACC(op,op2,cond,disp19,ccx,p,anul) \
284         do { \
285                 *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((anul)<<29) | ((cond)<<25) | (op2<<22) | (ccx<<20) | \
286                         (p << 19 ) | ((disp19) & 0x007ffff)  ); \
287                 cd->mcodeptr += 4; \
288         } while (0)
289
290         
291 /************** end-user instructions (see a SPARC asm manual) ***************/
292
293 #define M_SETHI(imm22, rd) \
294         do { \
295                 *((u4 *) cd->mcodeptr) = ((((s4)(0x00)) << 30) | ((rd) << 25) | ((0x04)<<22) | ((imm22)&0x3FFFFF) ); \
296                 cd->mcodeptr += 4; \
297         } while (0)
298
299 #define M_NOP M_SETHI(0,0)      /* nop */
300
301 #define M_AND(rs1,rs2,rd)       M_OP3(0x02,0x01,rd,rs1,rs2,REG)     /* 64b c = a &  b */
302 #define M_AND_IMM(rs1,rs2,rd)   M_OP3(0x02,0x01,rd,rs1,rs2,IMM)
303 #define M_ANDCC(rs1,rs2,rd)             M_OP3(0x02,0x11,rd,rs1,rs2,REG)
304 #define M_ANDCC_IMM(rs1,rs2,rd) M_OP3(0x02,0x11,rd,rs1,rs2,IMM)
305
306 #define M_OR(rs1,rs2,rd)        M_OP3(0x02,0x02,rd,rs1,rs2,REG)     /* rd = rs1 | rs2     */
307 #define M_OR_IMM(rs1,rs2,rd)    M_OP3(0x02,0x02,rd,rs1,rs2,IMM)
308 #define M_XOR(rs1,rs2,rd)       M_OP3(0x02,0x03,rd,rs1,rs2,REG)     /* rd = rs1 ^  rs2    */
309 #define M_XOR_IMM(rs1,rs2,rd)   M_OP3(0x02,0x03,rd,rs1,rs2,IMM)
310
311 #define M_MOV(rs,rd)            M_OR(REG_ZERO, rs, rd)              /* rd = rs            */
312 #define M_CLR(rd)               M_OR(REG_ZERO,REG_ZERO,rd)          /* rd = 0             */
313
314
315
316 #define M_SLLX(rs1,rs2,rd)              M_SHFT(0x02,0x25,rs1,rs2,rd,REG,1)      /* 64b rd = rs << rs2 */
317 #define M_SLLX_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,1)
318 #define M_SLL(rs1,rs2,rd)               M_SHFT(0x02,0x25,rs1,rs2,rd,REG,0)      /* 32b rd = rs << rs2 */
319 #define M_SLL_IMM(rs1,rs2,rd)   M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,0)
320 #define M_SRLX(rs1,rs2,rd)              M_SHFT(0x02,0x26,rs1,rs2,rd,REG,1)      /* 64b rd = rs >>>rs2 */
321 #define M_SRLX_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,1)
322 #define M_SRL(rs1,rs2,rd)               M_SHFT(0x02,0x26,rs1,rs2,rd,REG,0)      /* 32b rd = rs >>>rs2 */
323 #define M_SRL_IMM(rs1,rs2,rd)   M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,0)
324 #define M_SRAX(rs1,rs2,rd)              M_SHFT(0x02,0x27,rs1,rs2,rd,REG,1)      /* 64b rd = rs >> rs2 */
325 #define M_SRAX_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,1)
326 #define M_SRA(rs1,rs2,rd)       M_SHFT(0x02,0x27,rs1,rs2,rd,REG,0)  /* 32b rd = rs >> rs2 */
327 #define M_SRA_IMM(rs1,rs2,rd)   M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,0)
328
329 #define M_ISEXT(rs,rd)                  M_SRA(rs,REG_ZERO,rd)                 /* sign extend 32 bits*/
330
331
332 #define M_ADD(rs1,rs2,rd)       M_OP3(0x02,0x00,rd,rs1,rs2,REG)         /* 64b rd = rs1 + rs2 */
333 #define M_ADD_IMM(rs1,rs2,rd)   M_OP3(0x02,0x00,rd,rs1,rs2,IMM)
334 #define M_SUB(rs1,rs2,rd)       M_OP3(0x02,0x04,rd,rs1,rs2,REG)         /* 64b rd = rs1 - rs2 */
335 #define M_SUB_IMM(rs1,rs2,rd)   M_OP3(0x02,0x04,rd,rs1,rs2,IMM)
336 #define M_MULX(rs1,rs2,rd)      M_OP3(0x02,0x09,rd,rs1,rs2,REG)         /* 64b rd = rs1 * rs2 */
337 #define M_MULX_IMM(rs1,rs2,rd)  M_OP3(0x02,0x09,rd,rs1,rs2,IMM)
338 #define M_DIVX(rs1,rs2,rd)      M_OP3(0x02,0x2d,rd,rs1,rs2,REG)         /* 64b rd = rs1 / rs2 */
339
340 #define M_SUBcc(rs1,rs2,rd)     M_OP3(0x02,0x14,rd,rs1,rs2,REG)     /* sets xcc and icc   */
341 #define M_SUBcc_IMM(rs1,rs2,rd) M_OP3(0x02,0x14,rd,rs1,rs2,IMM)     /* sets xcc and icc   */
342
343
344
345 /**** compare and conditional ALU operations ***********/
346
347 #define M_CMP(rs1,rs2)          M_SUBcc(rs1,rs2,REG_ZERO)             
348 #define M_CMP_IMM(rs1,rs2)      M_SUBcc_IMM(rs1,rs2,REG_ZERO)
349
350
351 /* move integer register on (64-bit) condition */
352
353 #define M_XCMOVEQ(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x1,1,1,0,REG)   /* a==b ? rd=rs    */
354 #define M_XCMOVNE(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x9,1,1,0,REG)   /* a!=b ? rd=rs    */
355 #define M_XCMOVLT(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x3,1,1,0,REG)   /* a<b  ? rd=rs    */
356 #define M_XCMOVGE(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0xb,1,1,0,REG)   /* a>=b ? rd=rs    */
357 #define M_XCMOVLE(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x2,1,1,0,REG)   /* a<=b ? rd=rs    */
358 #define M_XCMOVGT(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0xa,1,1,0,REG)   /* a>b  ? rd=rs    */
359 #define M_XCMOVULE(rs,rd)       M_FMT4(0x2,0x2c,rd,rs,0x4,1,1,0,REG)   /* a<=b ? rd=rs (u)*/
360
361 #define M_XCMOVEQ_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x1,1,1,0,IMM)   /* a==b ? rd=rs    */
362 #define M_XCMOVNE_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x9,1,1,0,IMM)   /* a!=b ? rd=rs    */
363 #define M_XCMOVLT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x3,1,1,0,IMM)   /* a<b  ? rd=rs    */
364 #define M_XCMOVGE_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0xb,1,1,0,IMM)   /* a>=b ? rd=rs    */
365 #define M_XCMOVLE_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x2,1,1,0,IMM)   /* a<=b ? rd=rs    */
366 #define M_XCMOVGT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0xa,1,1,0,IMM)   /* a>b  ? rd=rs    */
367 #define M_XCMOVULE_IMM(rs,rd)   M_FMT4(0x2,0x2c,rd,rs,0x4,1,1,0,IMM)   /* a<=b ? rd=rs (u)*/
368
369 /* move integer register on (fcc0) floating point condition */
370
371 #define M_CMOVFGT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x6,0,0,0,IMM)   /* fa>fb  ? rd=rs  */
372 #define M_CMOVFLT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x4,0,0,0,IMM)   /* fa<fb  ? rd=rs  */
373 #define M_CMOVFEQ_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x9,0,0,0,IMM)   /* fa==fb ? rd=rs  */
374
375 /* move integer register on (32-bit) condition */
376
377
378
379 /* move integer register on register condition */
380
381 #define M_CMOVREQ(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x1,rd,rs1,rs2,REG)      /* rs1==0 ? rd=rs2 */
382 #define M_CMOVRNE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x5,rd,rs1,rs2,REG)      /* rs1!=0 ? rd=rs2 */
383 #define M_CMOVRLE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x2,rd,rs1,rs2,REG)      /* rs1<=0 ? rd=rs2 */
384 #define M_CMOVRLT(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x3,rd,rs1,rs2,REG)      /* rs1<0  ? rd=rs2 */
385 #define M_CMOVRGT(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x6,rd,rs1,rs2,REG)      /* rs1>0  ? rd=rs2 */
386 #define M_CMOVRGE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x7,rd,rs1,rs2,REG)      /* rs1>=0 ? rd=rs2 */
387
388 #define M_CMOVREQ_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x1,rd,rs1,rs2,IMM)  /* rs1==0 ? rd=rs2 */
389 #define M_CMOVRNE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x5,rd,rs1,rs2,IMM)  /* rs1!=0 ? rd=rs2 */
390 #define M_CMOVRLE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x2,rd,rs1,rs2,IMM)  /* rs1<=0 ? rd=rs2 */
391 #define M_CMOVRLT_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x3,rd,rs1,rs2,IMM)  /* rs1<0  ? rd=rs2 */
392 #define M_CMOVRGT_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x6,rd,rs1,rs2,IMM)  /* rs1>0  ? rd=rs2 */
393 #define M_CMOVRGE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x7,rd,rs1,rs2,IMM)  /* rs1>=0 ? rd=rs2 */
394
395
396 /**** big constant helpers *********/
397
398 /* #define FITS_13BIT_IMM(x)       ((x >= -4096) && (x <= 4095)) */
399
400 bool fits_13(s4 disp);
401 s4   get_lopart_disp(s4 disp);
402
403 #define abs(x) ((x) < 0 ? (-(x)) : (x))
404
405 #define sethi_part(x) ((x)>>10)
406 #define setlo_part(x) ((x) & 0x3ff)
407
408 #define DO_SETHI_REG(c,rd) \
409         do { \
410                 if (c > 0) { \
411                         M_SETHI(sethi_part(c), rd); \
412                         if (setlo_part(c)) { \
413                                 M_OR_IMM(rd, setlo_part(c), rd); \
414                         } \
415                 } \
416                 else { \
417                         M_SETHI(sethi_part(~c), rd); \
418                         M_XOR_IMM(rd, PASS13BIT(setlo_part(c) | 0xffffffffffff1c00), rd); \
419                 } \
420         } while (0)
421         
422 #define DO_SETHI_PART(c,rs,rd) \
423         do { \
424                 if (c > 0) { \
425                         M_SETHI(sethi_part(c), rd); \
426                         M_ADD(rs,rd,rd); \
427                 } \
428                 else { \
429                         M_SETHI(sethi_part(-c), rd); \
430                         M_SUB(rs,rd,rd); \
431                         assert(sethi_part(c) != 0xf); \
432                 } \
433         } while (0)
434         
435
436                 
437
438 #define M_LDA(rd,rs,disp) \
439     do { \
440         if (fits_13(disp)) { \
441             M_AADD_IMM(rs,disp,rd); \
442         } \
443         else { \
444             DO_SETHI_REG(disp,rd); \
445             M_AADD(rd,rs,rd); \
446         } \
447     } while (0)
448
449 /**** load/store operations ********/
450
451 #define M_SLDU(rd,rs,disp)      M_OP3(0x03,0x02,rd,rs,disp,IMM)        /* 16-bit load, uns*/
452 #define M_SLDS(rd,rs,disp)      M_OP3(0x03,0x0a,rd,rs,disp,IMM)        /* 16-bit load, sig*/
453 #define M_BLDS(rd,rs,disp)      M_OP3(0x03,0x09,rd,rs,disp,IMM)        /* 8-bit load, sig */
454
455
456 #define M_LDX_INTERN(rd,rs,disp) M_OP3(0x03,0x0b,rd,rs,disp,IMM)       /* 64-bit load, sig*/
457 #define M_LDX(rd,rs,disp) \
458         do { \
459         if (fits_13(disp)) { \
460             M_LDX_INTERN(rd,rs,disp); \
461         } \
462         else { \
463                 DO_SETHI_PART(disp,rs,rd); \
464                 M_LDX_INTERN(rd,rd,PASS13BIT(get_lopart_disp(disp))); \
465         } \
466     } while (0)
467
468 #define M_ILD_INTERN(rd,rs,disp) M_OP3(0x03,0x08,rd,rs,disp,IMM)       /* 32-bit load, sig */
469 #define M_ILD(rd,rs,disp) \
470         do { \
471         if (fits_13(disp)) { \
472             M_ILD_INTERN(rd,rs,disp); \
473        } \
474         else { \
475             DO_SETHI_PART(disp,rs,rd); \
476             M_ILD_INTERN(rd,rd,PASS13BIT(get_lopart_disp(disp))); \
477         } \
478     } while (0)
479
480
481
482 #define M_SST(rd,rs,disp)       M_OP3(0x03,0x06,rd,rs,disp,IMM)        /* 16-bit store     */
483 #define M_BST(rd,rs,disp)       M_OP3(0x03,0x05,rd,rs,disp,IMM)        /*  8-bit store     */
484
485 /* Stores with displacement overflow should only happen with PUTFIELD or on   */
486 /* the stack. The PUTFIELD instruction does not use REG_ITMP3 and a           */
487 /* reg_of_var call should not use REG_ITMP3!!!                                */
488
489 #define M_STX_INTERN(rd,rs,disp) M_OP3(0x03,0x0e,rd,rs,disp,IMM)       /* 64-bit store    */
490 #define M_STX(rd,rs,disp) \
491         do { \
492         if (fits_13(disp)) { \
493             M_STX_INTERN(rd,rs,disp); \
494         } \
495         else { \
496             DO_SETHI_PART(disp,rs,REG_ITMP3); \
497             M_STX_INTERN(rd,REG_ITMP3,PASS13BIT(get_lopart_disp(disp))); \
498         } \
499     } while (0)
500
501
502 #define M_IST_INTERN(rd,rs,disp) M_OP3(0x03,0x04,rd,rs,disp,IMM)       /* 32-bit store    */
503 #define M_IST(rd,rs,disp) \
504     do { \
505         if (fits_13(disp)) { \
506             M_IST_INTERN(rd,rs,disp); \
507        } \
508         else { \
509             DO_SETHI_PART(disp,rs,REG_ITMP3); \
510             M_IST_INTERN(rd,REG_ITMP3,PASS13BIT(get_lopart_disp(disp))); \
511         } \
512     } while (0)
513
514
515 /**** branch operations ********/
516 /* XXX prediction and annul bits currently set to defaults, but could be used for optimizations */
517
518 /* branch on integer register */
519
520 #define M_BEQZ(r,disp)          M_BRAREG(0x0,0x1,r,disp,1,0)          /* br r == 0   */
521 #define M_BLEZ(r,disp)          M_BRAREG(0x0,0x2,r,disp,1,0)          /* br r <= 0   */
522 #define M_BLTZ(r,disp)          M_BRAREG(0x0,0x3,r,disp,1,0)          /* br r < 0    */
523 #define M_BNEZ(r,disp)          M_BRAREG(0x0,0x5,r,disp,1,0)          /* br r != 0   */
524 #define M_BGTZ(r,disp)          M_BRAREG(0x0,0x6,r,disp,1,0)          /* br r > 0    */
525 #define M_BGEZ(r,disp)          M_BRAREG(0x0,0x7,r,disp,1,0)          /* br r >= 0   */
526
527
528 /* branch on (64-bit) integer condition codes */
529
530 #define M_XBEQ(disp)            M_BRACC(0x00,0x1,0x1,disp,2,1,0)      /* branch a==b */
531 #define M_XBNE(disp)            M_BRACC(0x00,0x1,0x9,disp,2,1,0)      /* branch a!=b */
532 #define M_XBGT(disp)            M_BRACC(0x00,0x1,0xa,disp,2,1,0)      /* branch a>b  */
533 #define M_XBLT(disp)            M_BRACC(0x00,0x1,0x3,disp,2,1,0)      /* branch a<b  */
534 #define M_XBGE(disp)            M_BRACC(0x00,0x1,0xb,disp,2,1,0)      /* branch a>=b */
535 #define M_XBLE(disp)            M_BRACC(0x00,0x1,0x2,disp,2,1,0)      /* branch a<=b */
536 #define M_XBUGE(disp)           M_BRACC(0x00,0x1,0xd,disp,2,1,0)      /* br uns a>=b */
537 #define M_XBUGT(disp)           M_BRACC(0x00,0x1,0xc,disp,2,1,0)      /* br uns a>b  */
538 #define M_XBULT(disp)           M_BRACC(0x00,0x1,0x5,disp,2,1,0)      /* br uns a<b  */
539
540 /* branch on (32-bit) integer condition codes */
541
542 #define M_BR(disp)              M_BRACC(0x00,0x1,0x8,disp,0,1,0)      /* branch      */
543 #define M_BEQ(disp)             M_BRACC(0x00,0x1,0x1,disp,0,1,0)      /* branch a==b */
544 #define M_BNE(disp)             M_BRACC(0x00,0x1,0x9,disp,0,1,0)      /* branch a!=b */
545 #define M_BGT(disp)             M_BRACC(0x00,0x1,0xa,disp,0,1,0)      /* branch a>b  */
546 #define M_BLT(disp)             M_BRACC(0x00,0x1,0x3,disp,0,1,0)      /* branch a<b  */
547 #define M_BGE(disp)             M_BRACC(0x00,0x1,0xb,disp,0,1,0)      /* branch a>=b */
548 #define M_BLE(disp)             M_BRACC(0x00,0x1,0x2,disp,0,1,0)      /* branch a<=b */
549 #define M_BULE(disp)            M_BRACC(0x00,0x1,0x4,disp,0,1,0)      /* br uns a<=b */
550 #define M_BUGT(disp)            M_BRACC(0x00,0x1,0xc,disp,0,1,0)      /* br uns a>b  */
551 #define M_BULT(disp)            M_BRACC(0x00,0x1,0x5,disp,0,1,0)      /* br uns a<b  */
552
553 /* branch on (fcc0) floating point condition codes */
554
555 #define M_FBR(disp)             M_BRACC(0x00,0x5,0x8,disp,0,1,0)      /* branch      */
556 #define M_FBU(disp)             M_BRACC(0x00,0x5,0x7,disp,0,1,0)      /* unordered   */
557 #define M_FBG(disp)             M_BRACC(0x00,0x5,0x6,disp,0,1,0)      /* branch a>b  */
558 #define M_FBL(disp)             M_BRACC(0x00,0x5,0x4,disp,0,1,0)      /* branch a<b  */
559 #define M_FBO(disp)             M_BRACC(0x00,0x5,0xf,disp,0,1,0)      /* br ordered  */
560
561
562
563 #define M_SAVE(rs1,rs2,rd)      M_OP3(0x02,0x3c,rd,rs1,rs2,IMM)
564 #define M_SAVE_REG(rs1,rs2,rd)  M_OP3(0x02,0x3c,rd,rs1,rs2,REG)
565 #define M_RESTORE(rs1,rs2,rd)   M_OP3(0x02,0x3d,rd,rs1,rs2,IMM)
566
567
568
569 #define M_JMP(rd,rs1,rs2)       M_OP3(0x02,0x38,rd, rs1,rs2,REG)  /* jump to rs1+rs2, adr of instr. saved to rd */
570 #define M_JMP_IMM(rd,rs1,rs2)   M_OP3(0x02,0x38,rd, rs1,rs2,IMM)
571 #define M_RET(rs1,imm)          M_OP3(0x02,0x38,REG_ZERO,rs1,imm,IMM) /* a jump which discards the current pc */
572
573 #define M_RETURN(rs1,imm)       M_OP3(0x02,0x39,0,rs1,imm,IMM) /* like ret, but does window restore */
574  
575 /**** floating point operations **/
576
577
578 #define M_DMOV(rs,rd)           M_FOP3_DX(0x02,0x34,0x02,rd,-1,rs)      /* rd = rs */
579 #define M_FMOV(rs,rd)           M_FOP3_FX(0x02,0x34,0x01,rd,-1,rs)      /* rd = rs */
580
581 #define M_FMOV_INTERN(rs,rd)    M_FOP3(0x02,0x34,0x01,rd,-1,rs)         /* rd = rs */
582
583 #define M_FNEG(rs,rd)           M_FOP3_FX(0x02,0x34,0x05,rd,-1,rs)              /* rd = -rs     */
584 #define M_DNEG(rs,rd)           M_FOP3_DX(0x02,0x34,0x06,rd,-1,rs)      /* rd = -rs     */
585
586 #define M_FADD(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x41,rd,rs1,rs2)  /* float add    */
587 #define M_DADD(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x42,rd,rs1,rs2)  /* double add   */
588 #define M_FSUB(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x045,rd,rs1,rs2)   /* float sub    */
589 #define M_DSUB(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x046,rd,rs1,rs2) /* double sub   */
590 #define M_FMUL(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x049,rd,rs1,rs2) /* float mul    */
591 #define M_DMUL(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x04a,rd,rs1,rs2) /* double mul   */
592 #define M_FDIV(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x04d,rd,rs1,rs2) /* float div    */
593 #define M_DDIV(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x04e,rd,rs1,rs2) /* double div   */
594
595
596 /**** compare and conditional FPU operations ***********/
597
598 /* rd field 0 ==> fcc target unit is fcc0 */
599 #define M_FCMP(rs1,rs2)             M_FCMP_FX(0x02,0x35,0x051,0,rs1,rs2)     /* compare flt  */
600 #define M_DCMP(rs1,rs2)             M_FCMP_DX(0x02,0x35,0x052,0,rs1,rs2)     /* compare dbl  */
601
602 /* conversion functions */
603
604 #define M_CVTIF(rs,rd)          M_FOP3_FX(0x02,0x34,0x0c4,rd,-1,rs)/* int2flt      */
605 #define M_CVTID(rs,rd)          M_FOP3(0x02,0x34,0x0c8,DR_X(rd),-1,FR_X(rs))  /* int2dbl      */
606 #define M_CVTLF(rs,rd)          M_FOP3(0x02,0x34,0x084,FR_X(rd),-1,DR_X(rs))  /* long2flt     */
607 #define M_CVTLD(rs,rd)          M_FOP3_DX(0x02,0x34,0x088,rd,-1,rs)    /* long2dbl     */
608
609 #define M_CVTFI(rs,rd)          M_FOP3_FX(0x02,0x34,0x0d1,rd,-1,rs)   /* flt2int   */
610 #define M_CVTDI(rs,rd)          M_FOP3(0x02,0x34,0x0d2,FR_X(rd),-1,DR_X(rs))     /* dbl2int   */
611 #define M_CVTFL(rs,rd)          M_FOP3(0x02,0x34,0x081,DR_X(rd),-1,FR_X(rs))     /* flt2long  */
612 #define M_CVTDL(rs,rd)          M_FOP3_DX(0x02,0x34,0x082,rd,-1,rs)       /* dbl2long  */
613
614 #define M_CVTFD(rs,rd)          M_FOP3(0x02,0x34,0x0c9,DR_X(rd),-1,FR_X(rs))     /* flt2dbl   */
615 #define M_CVTDF(rs,rd)          M_FOP3(0x02,0x34,0x0c6,FR_X(rd),-1,DR_X(rs))     /* dbl2float */
616
617
618
619 #define M_DLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x23,DR_X(rd),rs1,disp,IMM)    /* double (64-bit) load */
620 #define M_DLD(rd,rs,disp) \
621         do { \
622         s4 lo = (short) (disp); \
623         s4 hi = (short) (((disp) - lo) >> 13); \
624         if (hi == 0) { \
625             M_DLD_INTERN(rd,rs,lo); \
626         } else { \
627             M_SETHI(hi&0x3ffff8,rd); \
628             M_AADD(rs,rd,rd); \
629             M_DLD_INTERN(rd,rd,PASS13BIT(lo)); \
630         } \
631     } while (0)
632 /* Note for SETHI: sethi has a 22bit imm, only set upper 19 bits */ 
633
634 #define M_FLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x20,FR_X(rd),rs1,disp,IMM)    /* float (32-bit) load */
635 #define M_FLD(rd,rs,disp) \
636         do { \
637         s4 lo = (short) (disp); \
638         s4 hi = (short) (((disp) - lo) >> 13); \
639         if (hi == 0) { \
640             M_FLD_INTERN(rd,rs,lo); \
641         } else { \
642             M_SETHI(hi&0x3ffff8,rd); \
643             M_AADD(rs,rd,rd); \
644             M_FLD_INTERN(rd,rd,PASS13BIT(lo)); \
645         } \
646     } while (0)
647
648
649 #define M_FST_INTERN(rd,rs,disp) M_OP3(0x03,0x24,FR_X(rd),rs,disp,IMM)    /* float (32-bit) store  */
650 #define M_FST(rd,rs,disp) \
651     do { \
652         s4 lo = (short) (disp); \
653         s4 hi = (short) (((disp) - lo) >> 13); \
654         if (hi == 0) { \
655             M_FST_INTERN(rd,rs,lo); \
656         } else { \
657             M_SETHI(hi&0x3ffff8,REG_ITMP3); \
658             M_AADD(rs,REG_ITMP3,REG_ITMP3); \
659             M_FST_INTERN(rd,REG_ITMP3,PASS13BIT(lo)); \
660         } \
661     } while (0)
662     
663
664 #define M_DST_INTERN(rd,rs1,disp) M_OP3(0x03,0x27,DR_X(rd),rs1,disp,IMM)    /* double (64-bit) store */
665 #define M_DST(rd,rs,disp) \
666     do { \
667         s4 lo = (short) (disp); \
668         s4 hi = (short) (((disp) - lo) >> 13); \
669         if (hi == 0) { \
670             M_DST_INTERN(rd,rs,lo); \
671         } else { \
672             M_SETHI(hi&0x3ffff8,REG_ITMP3); \
673             M_AADD(rs,REG_ITMP3,REG_ITMP3); \
674             M_DST_INTERN(rd,REG_ITMP3,PASS13BIT(lo)); \
675         } \
676     } while (0)
677     
678     
679     
680 /*
681  * Address pseudo instruction
682  */
683
684 #define POINTERSHIFT 3 /* x8 */
685
686
687 #define M_ALD_INTERN(a,b,disp)  M_LDX_INTERN(a,b,disp)
688 #define M_ALD(rd,rs,disp)       M_LDX(rd,rs,disp)
689 #define M_AST_INTERN(a,b,disp)  M_STX_INTERN(a,b,disp)
690 #define M_AST(a,b,disp)         M_STX(a,b,disp)
691 #define M_AADD(a,b,c)           M_ADD(a,b,c)
692 #define M_AADD_IMM(a,b,c)       M_ADD_IMM(a,b,c)
693 #define M_ASUB_IMM(a,b,c)       M_SUB_IMM(a,b,c)
694 #define M_ASLL_IMM(a,b,c)       M_SLLX_IMM(a,b,c)
695         
696
697 #endif /* _CODEGEN_H */