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