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