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