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