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