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