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