Merged revisions 7797-7917 via svnmerge from
[cacao.git] / src / vm / jit / sparc64 / codegen.h
1 /* src/vm/jit/sparc64/codegen.h - code generation macros and definitions for
2                                   Sparc64
3
4    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
5    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
6    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
7    J. Wenninger, Institut f. Computersprachen - TU Wien
8
9    This file is part of CACAO.
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2, or (at
14    your option) any later version.
15
16    This program is distributed in the hope that it will be useful, but
17    WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24    02110-1301, USA.
25
26    $Id: codegen.h 4722 2006-04-03 15:36:00Z twisti $
27
28 */
29
30 #ifndef _CODEGEN_H
31 #define _CODEGEN_H
32
33 #include "config.h"
34 #include "vm/types.h"
35
36 #include "vm/jit/jit.h"
37
38 #include "md-abi.h" /* for INT_NATARG_CNT */
39
40 #include <assert.h>
41
42 /* from md-abi.c */
43 s4 nat_argintregs[INT_NATARG_CNT];
44
45 /* branch defines *************************************************************/
46
47 #define BRANCH_NOPS \
48     do { \
49         M_NOP; \
50         M_NOP; \
51     } while (0)
52
53
54 /* patcher defines ************************************************************/
55
56 #define PATCHER_CALL_INSTRUCTIONS    2     /* number of instructions          */
57 #define PATCHER_CALL_SIZE            2 * 4 /* size in bytes of a patcher call */
58
59 #define EXCEPTION_CHECK_INSTRUCTIONS 3     /* number of instructions          */
60 #define EXCEPTION_CHECK_SIZE         3 * 4 /* byte size of an exception check */
61
62 #define PATCHER_NOPS \
63     do { \
64         M_NOP; \
65         M_NOP; \
66     } while (0)
67
68
69 /* stub defines ***************************************************************/
70
71 #define COMPILERSTUB_CODESIZE    4 * 4
72
73
74 /* additional functions and macros to generate code ***************************/
75
76
77 /* MCODECHECK(icnt) */
78
79 #define MCODECHECK(icnt) \
80         do { \
81                 if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
82                         codegen_increase(cd); \
83         } while (0)
84
85
86 #define ALIGNCODENOP \
87     if ((s4) ((ptrint) cd->mcodeptr & 7)) { \
88         M_NOP; \
89     }
90
91 #define ALIGN_STACK_SLOTS(slots) \
92         if (slots & 1) \
93                 slots++;
94
95
96 /* M_INTMOVE:
97      generates an integer-move from register rs to rd.
98      if rs and rd are the same int-register, no code will be generated.
99 */ 
100
101 #define M_INTMOVE(rs,rd) if (rs != rd) { M_MOV(rs, rd); }
102
103
104 /* M_DBLMOVE:
105     generates a double floating-point-move from register (pair) rs to rd.
106     if rs and rd are the same double-register, no code will be generated
107 */ 
108
109 #define M_DBLMOVE(rs, rd) if (rs != rd) { M_DMOV (rs, rd); }
110
111
112 /* M_FLTMOVE:
113     generates a double floating-point-move from pseudo register rs to rd.
114         (ie. lower register of double rs pair to lower register of double rd pair)
115     if rs and rd are the same double-register, no code will be generated
116 */ 
117 #define M_FLTMOVE(rs, rd) if (rs != rd) { M_FMOV (rs, rd); }
118
119
120
121 #define M_COPY(s,d)                     emit_copy(jd, iptr, (s), (d))
122 #define ICONST(d,c)                     emit_iconst(cd, (d), (c))
123 #define LCONST(d,c)                     emit_lconst(cd, (d), (c))
124
125
126
127
128 /********************** instruction formats ***********************************/
129
130 #define REG     0
131 #define IMM     1
132
133 /* 3-address-operations: M_OP3
134  *       op  ..... opcode
135  *       op3 ..... operation
136  *       rs1 ..... register number source 1
137  *       rs2 ..... register number or constant integer source 2
138  *       rd  ..... register number destination
139  *       imm ..... switch to use rs2 as constant 13bit integer 
140  *                  (REG means: use b as register number)
141  *                  (IMM means: use b as signed immediate value)
142  */
143 #define M_OP3(op,op3,rd,rs1,rs2,imm) \
144         do { \
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, 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,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,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,setlo_part(disp)); \
498                         assert(0); \
499         } \
500     } while (0)
501
502
503 #define M_IST_INTERN(rd,rs,disp) M_OP3(0x03,0x04,rd,rs,disp,IMM)       /* 32-bit store    */
504 #define M_IST(rd,rs,disp) \
505     do { \
506         if (fits_13(disp)) { \
507             M_IST_INTERN(rd,rs,disp); \
508        } \
509         else { \
510             DO_SETHI_PART(disp,rs,REG_ITMP3); \
511             M_IST_INTERN(rd,REG_ITMP3,setlo_part(disp)); \
512                         assert(0); \
513         } \
514     } while (0)
515
516
517 /**** branch operations ********/
518 /* XXX prediction and annul bits currently set to defaults, but could be used for optimizations */
519
520 /* branch on integer register */
521
522 #define M_BEQZ(r,disp)          M_BRAREG(0x0,0x1,r,disp,1,0)          /* br r == 0   */
523 #define M_BLEZ(r,disp)          M_BRAREG(0x0,0x2,r,disp,1,0)          /* br r <= 0   */
524 #define M_BLTZ(r,disp)          M_BRAREG(0x0,0x3,r,disp,1,0)          /* br r < 0    */
525 #define M_BNEZ(r,disp)          M_BRAREG(0x0,0x5,r,disp,1,0)          /* br r != 0   */
526 #define M_BGTZ(r,disp)          M_BRAREG(0x0,0x6,r,disp,1,0)          /* br r > 0    */
527 #define M_BGEZ(r,disp)          M_BRAREG(0x0,0x7,r,disp,1,0)          /* br r >= 0   */
528
529
530 /* branch on (64-bit) integer condition codes */
531
532 #define M_XBEQ(disp)            M_BRACC(0x00,0x1,0x1,disp,2,1,0)      /* branch a==b */
533 #define M_XBNE(disp)            M_BRACC(0x00,0x1,0x9,disp,2,1,0)      /* branch a!=b */
534 #define M_XBGT(disp)            M_BRACC(0x00,0x1,0xa,disp,2,1,0)      /* branch a>b  */
535 #define M_XBLT(disp)            M_BRACC(0x00,0x1,0x3,disp,2,1,0)      /* branch a<b  */
536 #define M_XBGE(disp)            M_BRACC(0x00,0x1,0xb,disp,2,1,0)      /* branch a>=b */
537 #define M_XBLE(disp)            M_BRACC(0x00,0x1,0x2,disp,2,1,0)      /* branch a<=b */
538 #define M_XBUGE(disp)           M_BRACC(0x00,0x1,0xd,disp,2,1,0)      /* br uns a>=b */
539 #define M_XBUGT(disp)           M_BRACC(0x00,0x1,0xc,disp,2,1,0)      /* br uns a>b  */
540 #define M_XBULT(disp)           M_BRACC(0x00,0x1,0x5,disp,2,1,0)      /* br uns a<b  */
541
542 /* branch on (32-bit) integer condition codes */
543
544 #define M_BR(disp)              M_BRACC(0x00,0x1,0x8,disp,0,1,0)      /* branch      */
545 #define M_BEQ(disp)             M_BRACC(0x00,0x1,0x1,disp,0,1,0)      /* branch a==b */
546 #define M_BNE(disp)             M_BRACC(0x00,0x1,0x9,disp,0,1,0)      /* branch a!=b */
547 #define M_BGT(disp)             M_BRACC(0x00,0x1,0xa,disp,0,1,0)      /* branch a>b  */
548 #define M_BLT(disp)             M_BRACC(0x00,0x1,0x3,disp,0,1,0)      /* branch a<b  */
549 #define M_BGE(disp)             M_BRACC(0x00,0x1,0xb,disp,0,1,0)      /* branch a>=b */
550 #define M_BLE(disp)             M_BRACC(0x00,0x1,0x2,disp,0,1,0)      /* branch a<=b */
551 #define M_BULE(disp)            M_BRACC(0x00,0x1,0x4,disp,0,1,0)      /* br uns a<=b */
552 #define M_BUGT(disp)            M_BRACC(0x00,0x1,0xc,disp,0,1,0)      /* br uns a>b  */
553 #define M_BULT(disp)            M_BRACC(0x00,0x1,0x5,disp,0,1,0)      /* br uns a<b  */
554
555 /* branch on (fcc0) floating point condition codes */
556
557 #define M_FBR(disp)             M_BRACC(0x00,0x5,0x8,disp,0,1,0)      /* branch      */
558 #define M_FBU(disp)             M_BRACC(0x00,0x5,0x7,disp,0,1,0)      /* unordered   */
559 #define M_FBG(disp)             M_BRACC(0x00,0x5,0x6,disp,0,1,0)      /* branch a>b  */
560 #define M_FBL(disp)             M_BRACC(0x00,0x5,0x4,disp,0,1,0)      /* branch a<b  */
561 #define M_FBO(disp)             M_BRACC(0x00,0x5,0xf,disp,0,1,0)      /* br ordered  */
562
563
564
565 #define M_SAVE(rs1,rs2,rd)      M_OP3(0x02,0x3c,rd,rs1,rs2,IMM)
566 #define M_RESTORE(rs1,rs2,rd)   M_OP3(0x02,0x3d,rd,rs1,rs2,IMM)
567
568
569
570 #define M_JMP(rd,rs1,rs2)       M_OP3(0x02,0x38,rd, rs1,rs2,REG)  /* jump to rs1+rs2, adr of instr. saved to rd */
571 #define M_JMP_IMM(rd,rs1,rs2)   M_OP3(0x02,0x38,rd, rs1,rs2,IMM)
572 #define M_RET(rs1,imm)          M_OP3(0x02,0x38,REG_ZERO,rs1,imm,IMM) /* a jump which discards the current pc */
573
574 #define M_RETURN(rs1,imm)       M_OP3(0x02,0x39,0,rs1,imm,IMM) /* like ret, but does window restore */
575  
576 /**** floating point operations **/
577
578
579 #define M_DMOV(rs,rd)           M_FOP3_DX(0x02,0x34,0x02,rd,-1,rs)      /* rd = rs */
580 #define M_FMOV(rs,rd)           M_FOP3_FX(0x02,0x34,0x01,rd,-1,rs)      /* rd = rs */
581
582 #define M_FMOV_INTERN(rs,rd)    M_FOP3(0x02,0x34,0x01,rd,-1,rs)         /* rd = rs */
583
584 #define M_FNEG(rs,rd)           M_FOP3_FX(0x02,0x34,0x05,rd,-1,rs)              /* rd = -rs     */
585 #define M_DNEG(rs,rd)           M_FOP3_DX(0x02,0x34,0x06,rd,-1,rs)      /* rd = -rs     */
586
587 #define M_FADD(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x41,rd,rs1,rs2)  /* float add    */
588 #define M_DADD(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x42,rd,rs1,rs2)  /* double add   */
589 #define M_FSUB(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x045,rd,rs1,rs2)   /* float sub    */
590 #define M_DSUB(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x046,rd,rs1,rs2) /* double sub   */
591 #define M_FMUL(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x049,rd,rs1,rs2) /* float mul    */
592 #define M_DMUL(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x04a,rd,rs1,rs2) /* double mul   */
593 #define M_FDIV(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x04d,rd,rs1,rs2) /* float div    */
594 #define M_DDIV(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x04e,rd,rs1,rs2) /* double div   */
595
596
597 /**** compare and conditional FPU operations ***********/
598
599 /* rd field 0 ==> fcc target unit is fcc0 */
600 #define M_FCMP(rs1,rs2)             M_FCMP_FX(0x02,0x35,0x051,0,rs1,rs2)     /* compare flt  */
601 #define M_DCMP(rs1,rs2)             M_FCMP_DX(0x02,0x35,0x052,0,rs1,rs2)     /* compare dbl  */
602
603 /* conversion functions */
604
605 #define M_CVTIF(rs,rd)          M_FOP3_FX(0x02,0x34,0x0c4,rd,-1,rs)/* int2flt      */
606 #define M_CVTID(rs,rd)          M_FOP3(0x02,0x34,0x0c8,DR_X(rd),-1,FR_X(rs))  /* int2dbl      */
607 #define M_CVTLF(rs,rd)          M_FOP3(0x02,0x34,0x084,FR_X(rd),-1,DR_X(rs))  /* long2flt     */
608 #define M_CVTLD(rs,rd)          M_FOP3_DX(0x02,0x34,0x088,rd,-1,rs)    /* long2dbl     */
609
610 #define M_CVTFI(rs,rd)          M_FOP3_FX(0x02,0x34,0x0d1,rd,-1,rs)   /* flt2int   */
611 #define M_CVTDI(rs,rd)          M_FOP3(0x02,0x34,0x0d2,FR_X(rd),-1,DR_X(rs))     /* dbl2int   */
612 #define M_CVTFL(rs,rd)          M_FOP3(0x02,0x34,0x081,DR_X(rd),-1,FR_X(rs))     /* flt2long  */
613 #define M_CVTDL(rs,rd)          M_FOP3_DX(0x02,0x34,0x082,rd,-1,rs)       /* dbl2long  */
614
615 #define M_CVTFD(rs,rd)          M_FOP3(0x02,0x34,0x0c9,DR_X(rd),-1,FR_X(rs))     /* flt2dbl   */
616 #define M_CVTDF(rs,rd)          M_FOP3(0x02,0x34,0x0c6,FR_X(rd),-1,DR_X(rs))     /* dbl2float */
617
618
619
620 #define M_DLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x23,DR_X(rd),rs1,disp,IMM)    /* double (64-bit) load */
621 #define M_DLD(rd,rs,disp) \
622         do { \
623         s4 lo = (short) (disp); \
624         s4 hi = (short) (((disp) - lo) >> 13); \
625         if (hi == 0) { \
626             M_DLD_INTERN(rd,rs,lo); \
627         } else { \
628             M_SETHI(hi&0x3ffff8,rd); \
629             M_AADD(rs,rd,rd); \
630             M_DLD_INTERN(rd,rd,lo); \
631         } \
632     } while (0)
633 /* Note for SETHI: sethi has a 22bit imm, only set upper 19 bits */ 
634
635 #define M_FLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x20,FR_X(rd),rs1,disp,IMM)    /* float (32-bit) load */
636 #define M_FLD(rd,rs,disp) \
637         do { \
638         s4 lo = (short) (disp); \
639         s4 hi = (short) (((disp) - lo) >> 13); \
640         if (hi == 0) { \
641             M_FLD_INTERN(rd,rs,lo); \
642         } else { \
643             M_SETHI(hi&0x3ffff8,rd); \
644             M_AADD(rs,rd,rd); \
645             M_FLD_INTERN(rd,rd,lo); \
646         } \
647     } while (0)
648
649
650 #define M_FST_INTERN(rd,rs,disp) M_OP3(0x03,0x24,FR_X(rd),rs,disp,IMM)    /* float (32-bit) store  */
651 #define M_FST(rd,rs,disp) \
652     do { \
653         s4 lo = (short) (disp); \
654         s4 hi = (short) (((disp) - lo) >> 13); \
655         if (hi == 0) { \
656             M_FST_INTERN(rd,rs,lo); \
657         } else { \
658             M_SETHI(hi&0x3ffff8,REG_ITMP3); \
659             M_AADD(rs,REG_ITMP3,REG_ITMP3); \
660             M_FST_INTERN(rd,REG_ITMP3,lo); \
661         } \
662     } while (0)
663     
664
665 #define M_DST_INTERN(rd,rs1,disp) M_OP3(0x03,0x27,DR_X(rd),rs1,disp,IMM)    /* double (64-bit) store */
666 #define M_DST(rd,rs,disp) \
667     do { \
668         s4 lo = (short) (disp); \
669         s4 hi = (short) (((disp) - lo) >> 13); \
670         if (hi == 0) { \
671             M_DST_INTERN(rd,rs,lo); \
672         } else { \
673             M_SETHI(hi&0x3ffff8,REG_ITMP3); \
674             M_AADD(rs,REG_ITMP3,REG_ITMP3); \
675             M_DST_INTERN(rd,REG_ITMP3,lo); \
676         } \
677     } while (0)
678     
679     
680     
681 /*
682  * Address pseudo instruction
683  */
684
685 #define POINTERSHIFT 3 /* x8 */
686
687
688 #define M_ALD_INTERN(a,b,disp)  M_LDX_INTERN(a,b,disp)
689 #define M_ALD(rd,rs,disp)       M_LDX(rd,rs,disp)
690 #define M_AST_INTERN(a,b,disp)  M_STX_INTERN(a,b,disp)
691 #define M_AST(a,b,disp)         M_STX(a,b,disp)
692 #define M_AADD(a,b,c)           M_ADD(a,b,c)
693 #define M_AADD_IMM(a,b,c)       M_ADD_IMM(a,b,c)
694 #define M_ASUB_IMM(a,b,c)       M_SUB_IMM(a,b,c)
695 #define M_ASLL_IMM(a,b,c)       M_SLLX_IMM(a,b,c)
696         
697
698 #endif /* _CODEGEN_H */