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