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