* src/vm/jit/sparc64/codegen.h: Fixed float register mapping and compare macros.
[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)<<1) + 1)
211 #define DR_X(r) (((r)<<1)|((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 #define M_SUBcc(rs1,rs2,rd)     M_OP3(0x02,0x14,rd,rs1,rs2,REG)     /* sets xcc and icc   */
326 #define M_SUBcc_IMM(rs1,rs2,rd) M_OP3(0x02,0x14,rd,rs1,rs2,IMM)     /* sets xcc and icc   */
327
328
329
330 /**** compare and conditional ALU operations ***********/
331
332 #define M_CMP(rs1,rs2)          M_SUBcc(rs1,rs2,REG_ZERO)             
333 #define M_CMP_IMM(rs1,rs2)      M_SUBcc_IMM(rs1,rs2,REG_ZERO)
334
335
336 /* move integer register on (64-bit) condition */
337
338 #define M_XCMOVEQ(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x1,1,1,0,REG)   /* a==b ? rd=rs    */
339 #define M_XCMOVNE(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x9,1,1,0,REG)   /* a!=b ? rd=rs    */
340 #define M_XCMOVLT(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x3,1,1,0,REG)   /* a<b  ? rd=rs    */
341 #define M_XCMOVGE(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0xb,1,1,0,REG)   /* a>=b ? rd=rs    */
342 #define M_XCMOVLE(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x2,1,1,0,REG)   /* a<=b ? rd=rs    */
343 #define M_XCMOVGT(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0xa,1,1,0,REG)   /* a>b  ? rd=rs    */
344
345 #define M_XCMOVEQ_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x1,1,1,0,IMM)   /* a==b ? rd=rs    */
346 #define M_XCMOVNE_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x9,1,1,0,IMM)   /* a!=b ? rd=rs    */
347 #define M_XCMOVLT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x3,1,1,0,IMM)   /* a<b  ? rd=rs    */
348 #define M_XCMOVGE_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0xb,1,1,0,IMM)   /* a>=b ? rd=rs    */
349 #define M_XCMOVLE_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x2,1,1,0,IMM)   /* a<=b ? rd=rs    */
350 #define M_XCMOVGT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0xa,1,1,0,IMM)   /* a>b  ? rd=rs    */
351
352 /* move integer register on (fcc0) floating point condition */
353
354 #define M_CMOVFGT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x6,0,0,0,IMM)   /* fa>fb  ? rd=rs  */
355 #define M_CMOVFLT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x4,0,0,0,IMM)   /* fa<fb  ? rd=rs  */
356 #define M_CMOVFEQ_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x9,0,0,0,IMM)   /* fa==fb ? rd=rs  */
357
358 /* move integer register on (32-bit) condition */
359
360
361
362 /* move integer register on register condition */
363
364 #define M_CMOVREQ(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x1,rd,rs1,rs2,REG)      /* rs1==0 ? rd=rs2 */
365 #define M_CMOVRNE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x5,rd,rs1,rs2,REG)      /* rs1!=0 ? rd=rs2 */
366 #define M_CMOVRLE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x2,rd,rs1,rs2,REG)      /* rs1<=0 ? rd=rs2 */
367 #define M_CMOVRLT(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x3,rd,rs1,rs2,REG)      /* rs1<0  ? rd=rs2 */
368 #define M_CMOVRGT(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x6,rd,rs1,rs2,REG)      /* rs1>0  ? rd=rs2 */
369 #define M_CMOVRGE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x7,rd,rs1,rs2,REG)      /* rs1>=0 ? rd=rs2 */
370
371 #define M_CMOVREQ_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x1,rd,rs1,rs2,IMM)  /* rs1==0 ? rd=rs2 */
372 #define M_CMOVRNE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x5,rd,rs1,rs2,IMM)  /* rs1!=0 ? rd=rs2 */
373 #define M_CMOVRLE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x2,rd,rs1,rs2,IMM)  /* rs1<=0 ? rd=rs2 */
374 #define M_CMOVRLT_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x3,rd,rs1,rs2,IMM)  /* rs1<0  ? rd=rs2 */
375 #define M_CMOVRGT_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x6,rd,rs1,rs2,IMM)  /* rs1>0  ? rd=rs2 */
376 #define M_CMOVRGE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x7,rd,rs1,rs2,IMM)  /* rs1>=0 ? rd=rs2 */
377
378
379 /**** load/store operations ********/
380
381 #define M_LDA(rd,rs,disp) \
382     do { \
383         s4 lo = (short) (disp); \
384         s4 hi = (short) (((disp) - lo) >> 13); \
385         if (hi == 0) { \
386             M_AADD_IMM(rs,lo,rd); \
387         } else { \
388             M_SETHI(hi&0x3ffff8,rd); \
389             M_AADD_IMM(rd,lo,rd); \
390             M_AADD(rd,rs,rd); \
391         } \
392     } while (0)
393
394 #define M_SLDU(rd,rs,disp)      M_OP3(0x03,0x02,rd,rs,disp,IMM)        /* 16-bit load, uns*/
395 #define M_SLDS(rd,rs,disp)      M_OP3(0x03,0x0a,rd,rs,disp,IMM)        /* 16-bit load, sig*/
396 #define M_BLDS(rd,rs,disp)      M_OP3(0x03,0x09,rd,rs,disp,IMM)        /* 8-bit load, sig */
397
398
399 #define M_LDX_INTERN(rd,rs,disp) M_OP3(0x03,0x0b,rd,rs,disp,IMM)       /* 64-bit load, sig*/
400 #define M_LDX(rd,rs,disp) \
401         do { \
402         s4 lo = (short) (disp); \
403         s4 hi = (short) (((disp) - lo) >> 13); \
404         if (hi == 0) { \
405             M_LDX_INTERN(rd,rs,lo); \
406         } else { \
407             M_SETHI(hi&0x3ffff8,rd); \
408             M_AADD(rs,rd,rd); \
409             M_LDX_INTERN(rd,rd,lo); \
410         } \
411     } while (0)
412
413 #define M_ILD_INTERN(rd,rs,disp) M_OP3(0x03,0x08,rd,rs,disp,IMM)       /* 32-bit load, sig */
414 #define M_ILD(rd,rs,disp) \
415         do { \
416         s4 lo = (short) (disp); \
417         s4 hi = (short) (((disp) - lo) >> 13); \
418         if (hi == 0) { \
419             M_ILD_INTERN(rd,rs,lo); \
420         } else { \
421             M_SETHI(hi&0x3ffff8,rd); \
422             M_AADD(rs,rd,rd); \
423             M_ILD_INTERN(rd,rd,lo); \
424         } \
425     } while (0)
426
427
428
429 #define M_SST(rd,rs,disp)       M_OP3(0x03,0x06,rd,rs,disp,IMM)        /* 16-bit store     */
430 #define M_BST(rd,rs,disp)       M_OP3(0x03,0x05,rd,rs,disp,IMM)        /*  8-bit store     */
431
432 /* Stores with displacement overflow should only happen with PUTFIELD or on   */
433 /* the stack. The PUTFIELD instruction does not use REG_ITMP3 and a           */
434 /* reg_of_var call should not use REG_ITMP3!!!                                */
435
436 #define M_STX_INTERN(rd,rs,disp) M_OP3(0x03,0x0e,rd,rs,disp,IMM)       /* 64-bit store    */
437 #define M_STX(rd,rs,disp) \
438         do { \
439         s4 lo = (short) (disp); \
440         s4 hi = (short) (((disp) - lo) >> 13); \
441         if (hi == 0) { \
442             M_STX_INTERN(rd,rs,lo); \
443         } else { \
444             M_SETHI(hi&0x3ffff8,REG_ITMP3); /* sethi has a 22bit imm, only set upper 19 bits */ \
445             M_AADD(rs,REG_ITMP3,REG_ITMP3); \
446             M_STX_INTERN(rd,REG_ITMP3,lo); \
447         } \
448     } while (0)
449
450
451 #define M_IST_INTERN(rd,rs,disp) M_OP3(0x03,0x04,rd,rs,disp,IMM)       /* 32-bit store    */
452 #define M_IST(rd,rs,disp) \
453     do { \
454         s4 lo = (short) (disp); \
455         s4 hi = (short) (((disp) - lo) >> 13); \
456         if (hi == 0) { \
457             M_IST_INTERN(rd,rs,lo); \
458         } else { \
459             M_SETHI(hi&0x3ffff8,REG_ITMP3); /* sethi has a 22bit imm, only set upper 19 bits */ \
460             M_AADD(rs,REG_ITMP3,REG_ITMP3); \
461             M_IST_INTERN(rd,REG_ITMP3,lo); \
462         } \
463     } while (0)
464
465
466 /**** branch operations ********/
467 /* XXX prediction and annul bits currently set to defaults, but could be used for optimizations */
468
469 /* branch on integer register */
470
471 #define M_BEQZ(r,disp)          M_BRAREG(0x0,0x1,r,disp,1,0)          /* br r == 0   */
472 #define M_BLEZ(r,disp)          M_BRAREG(0x0,0x2,r,disp,1,0)          /* br r <= 0   */
473 #define M_BLTZ(r,disp)          M_BRAREG(0x0,0x3,r,disp,1,0)          /* br r < 0    */
474 #define M_BNEZ(r,disp)          M_BRAREG(0x0,0x5,r,disp,1,0)          /* br r != 0   */
475 #define M_BGTZ(r,disp)          M_BRAREG(0x0,0x6,r,disp,1,0)          /* br r > 0    */
476 #define M_BGEZ(r,disp)          M_BRAREG(0x0,0x7,r,disp,1,0)          /* br r >= 0   */
477
478
479 /* branch on (64-bit) integer condition codes */
480
481 #define M_XBEQ(disp)            M_BRACC(0x00,0x1,0x1,disp,2,1,0)      /* branch a==b */
482 #define M_XBNE(disp)            M_BRACC(0x00,0x1,0x9,disp,2,1,0)      /* branch a!=b */
483 #define M_XBGT(disp)            M_BRACC(0x00,0x1,0xa,disp,2,1,0)      /* branch a>b  */
484 #define M_XBLT(disp)            M_BRACC(0x00,0x1,0x3,disp,2,1,0)      /* branch a<b  */
485 #define M_XBGE(disp)            M_BRACC(0x00,0x1,0xb,disp,2,1,0)      /* branch a>=b */
486 #define M_XBLE(disp)            M_BRACC(0x00,0x1,0x2,disp,2,1,0)      /* branch a<=b */
487 #define M_XBUGE(disp)           M_BRACC(0x00,0x1,0xd,disp,2,1,0)      /* br uns a>=b */
488 #define M_XBULT(disp)           M_BRACC(0x00,0x1,0x5,disp,2,1,0)      /* br uns a<b  */
489
490 /* branch on (32-bit) integer condition codes */
491
492 #define M_BR(disp)              M_BRACC(0x00,0x1,0x8,disp,0,1,0)      /* branch      */
493 #define M_BEQ(disp)             M_BRACC(0x00,0x1,0x1,disp,0,1,0)      /* branch a==b */
494 #define M_BNE(disp)             M_BRACC(0x00,0x1,0x9,disp,0,1,0)      /* branch a!=b */
495 #define M_BGT(disp)             M_BRACC(0x00,0x1,0xa,disp,0,1,0)      /* branch a>b  */
496 #define M_BLT(disp)             M_BRACC(0x00,0x1,0x3,disp,0,1,0)      /* branch a<b  */
497 #define M_BGE(disp)             M_BRACC(0x00,0x1,0xb,disp,0,1,0)      /* branch a>=b */
498 #define M_BLE(disp)             M_BRACC(0x00,0x1,0x2,disp,0,1,0)      /* branch a<=b */
499 #define M_BULE(disp)            M_BRACC(0x00,0x1,0x4,disp,0,1,0)      /* br uns a<=b */
500 #define M_BULT(disp)            M_BRACC(0x00,0x1,0x5,disp,0,1,0)      /* br uns a<b  */
501
502
503
504 #define M_SAVE(rs1,rs2,rd)      M_OP3(0x02,0x3c,rd,rs1,rs2,IMM)
505 #define M_RESTORE(rs1,rs2,rd)   M_OP3(0x02,0x3d,rd,rs1,rs2,IMM)
506
507
508
509 #define M_JMP(rd,rs1,rs2)       M_OP3(0x02,0x38,rd, rs1,rs2,REG)  /* jump to rs1+rs2, adr of instr. saved to rd */
510 #define M_JMP_IMM(rd,rs1,rs2)   M_OP3(0x02,0x38,rd, rs1,rs2,IMM)
511 #define M_RET(rs1,imm)          M_OP3(0x02,0x38,REG_ZERO,rs1,imm,IMM) /* a jump which discards the current pc */
512
513 #define M_RETURN(rs1,imm)       M_OP3(0x02,0x39,0,rs1,imm,IMM) /* like ret, but does window restore */
514  
515 /**** floating point operations **/
516
517
518 #define M_DMOV(rs,rd)           M_FOP3_DX(0x02,0x34,0x02,rd,-1,rs)      /* rd = rs */
519 #define M_FMOV(rs,rd)           M_FOP3_FX(0x02,0x34,0x01,rd,-1,rs)  /* rd = rs */
520
521 #define M_FNEG(rs,rd)           M_FOP3_FX(0x02,0x34,0x05,rd,-1,rs)              /* rd = -rs     */
522 #define M_DNEG(rs,rd)           M_FOP3_DX(0x02,0x34,0x06,rd,-1,rs)      /* rd = -rs     */
523
524 #define M_FADD(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x41,rd,rs1,rs2)  /* float add    */
525 #define M_DADD(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x42,rd,rs1,rs2)  /* double add   */
526 #define M_FSUB(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x045,rd,rs1,rs2)   /* float sub    */
527 #define M_DSUB(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x046,rd,rs1,rs2) /* double sub   */
528 #define M_FMUL(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x049,rd,rs1,rs2) /* float mul    */
529 #define M_DMUL(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x04a,rd,rs1,rs2) /* double mul   */
530 #define M_FDIV(rs1,rs2,rd)      M_FOP3_FX(0x02,0x34,0x04d,rd,rs1,rs2) /* float div    */
531 #define M_DDIV(rs1,rs2,rd)      M_FOP3_DX(0x02,0x34,0x04e,rd,rs1,rs2) /* double div   */
532
533
534 /**** compare and conditional FPU operations ***********/
535
536 /* rd field 0 ==> fcc target unit is fcc0 */
537 #define M_FCMP(rs1,rs2)             M_FOP3_FX(0x02,0x35,0x051,0,rs1,rs2) /* set fcc flt  */
538 #define M_DCMP(rs1,rs2)             M_FOP3_DX(0x02,0x35,0x052,0,rs1,rs2)     /* set fcc dbl  */
539
540 /* conversion functions */
541
542 #define M_CVTIF(rs,rd)          M_FOP3_FX(0x02,0x34,0x0c4,rd,-1,rs)/* int2flt      */
543 #define M_CVTID(rs,rd)          M_FOP3(0x02,0x34,0x0c8,DR_X(rd),-1,FR_X(rs))  /* int2dbl      */
544 #define M_CVTLF(rs,rd)          M_FOP3(0x02,0x34,0x084,FR_X(rd),-1,DR_X(rs))  /* long2flt     */
545 #define M_CVTLD(rs,rd)          M_FOP3_DX(0x02,0x34,0x088,rd,-1,rs)    /* long2dbl     */
546
547 #define M_CVTFI(rs,rd)          M_FOP3_FX(0x02,0x34,0x0d1,rd,-1,rs)   /* flt2int   */
548 #define M_CVTDI(rs,rd)          M_FOP3(0x02,0x34,0x0d2,FR_X(rd),-1,DR_X(rs))     /* dbl2int   */
549 #define M_CVTFL(rs,rd)          M_FOP3(0x02,0x34,0x081,DR_X(rd),-1,FR_X(rs))     /* flt2long  */
550 #define M_CVTDL(rs,rd)          M_FOP3_DX(0x02,0x34,0x082,rd,-1,rs)       /* dbl2long  */
551
552 #define M_CVTFD(rs,rd)          M_FOP3(0x02,0x34,0x0c9,DR_X(rs),-1,FR_X(rs))     /* flt2dbl   */
553 #define M_CVTDF(rs,rd)          M_FOP3(0x02,0x34,0x0c6,FR_X(rs),-1,DR_X(rs))     /* dbl2float */
554
555
556
557 #define M_DLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x23,DR_X(rd),rs1,disp,IMM)    /* double (64-bit) load */
558 #define M_DLD(rd,rs,disp) \
559         do { \
560         s4 lo = (short) (disp); \
561         s4 hi = (short) (((disp) - lo) >> 13); \
562         if (hi == 0) { \
563             M_DLD_INTERN(rd,rs,lo); \
564         } else { \
565             M_SETHI(hi&0x3ffff8,rd); \
566             M_AADD(rs,rd,rd); \
567             M_DLD_INTERN(rd,rd,lo); \
568         } \
569     } while (0)
570 /* Note for SETHI: sethi has a 22bit imm, only set upper 19 bits */ 
571
572 #define M_FLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x20,FR_X(rd),rs1,disp,IMM)    /* float (32-bit) load */
573 #define M_FLD(rd,rs,disp) \
574         do { \
575         s4 lo = (short) (disp); \
576         s4 hi = (short) (((disp) - lo) >> 13); \
577         if (hi == 0) { \
578             M_FLD_INTERN(rd,rs,lo); \
579         } else { \
580             M_SETHI(hi&0x3ffff8,rd); \
581             M_AADD(rs,rd,rd); \
582             M_FLD_INTERN(rd,rd,lo); \
583         } \
584     } while (0)
585
586
587 #define M_FST_INTERN(rd,rs,disp) M_OP3(0x03,0x24,FR_X(rd),rs,disp,IMM)    /* float (32-bit) store  */
588 #define M_FST(rd,rs,disp) \
589     do { \
590         s4 lo = (short) (disp); \
591         s4 hi = (short) (((disp) - lo) >> 13); \
592         if (hi == 0) { \
593             M_FST_INTERN(rd,rs,lo); \
594         } else { \
595             M_SETHI(hi&0x3ffff8,REG_ITMP3); \
596             M_AADD(rs,REG_ITMP3,REG_ITMP3); \
597             M_FST_INTERN(rd,REG_ITMP3,lo); \
598         } \
599     } while (0)
600     
601
602 #define M_DST_INTERN(rd,rs1,disp) M_OP3(0x03,0x27,DR_X(rd),rs1,disp,IMM)    /* double (64-bit) store */
603 #define M_DST(rd,rs,disp) \
604     do { \
605         s4 lo = (short) (disp); \
606         s4 hi = (short) (((disp) - lo) >> 13); \
607         if (hi == 0) { \
608             M_DST_INTERN(rd,rs,lo); \
609         } else { \
610             M_SETHI(hi&0x3ffff8,REG_ITMP3); \
611             M_AADD(rs,REG_ITMP3,REG_ITMP3); \
612             M_DST_INTERN(rd,REG_ITMP3,lo); \
613         } \
614     } while (0)
615     
616     
617     
618 /*
619  * Address pseudo instruction
620  */
621
622 #define POINTERSHIFT 3 /* x8 */
623
624
625 #define M_ALD_INTERN(a,b,disp)  M_LDX_INTERN(a,b,disp)
626 #define M_ALD(rd,rs,disp)       M_LDX(rd,rs,disp)
627 #define M_AST_INTERN(a,b,disp)  M_STX_INTERN(a,b,disp)
628 #define M_AST(a,b,disp)         M_STX(a,b,disp)
629 #define M_AADD(a,b,c)           M_ADD(a,b,c)
630 #define M_AADD_IMM(a,b,c)       M_ADD_IMM(a,b,c)
631 #define M_ASUB_IMM(a,b,c)       M_SUB_IMM(a,b,c)
632 #define M_ASLL_IMM(a,b,c)       M_SLLX_IMM(a,b,c)
633
634
635
636
637 /* var_to_reg_xxx **************************************************************
638
639    This function generates code to fetch data from a pseudo-register
640    into a real register. If the pseudo-register has actually been
641    assigned to a real register, no code will be emitted, since
642    following operations can use this register directly.
643     
644    v: pseudoregister to be fetched from
645    tempregnum: temporary register to be used if v is actually spilled to ram
646
647    return: the register number, where the operand can be found after 
648            fetching (this wil be either tempregnum or the register
649            number allready given to v)
650
651 *******************************************************************************/
652
653 #define var_to_reg_int(regnr,v,tempnr) \
654     do { \
655         if ((v)->flags & INMEMORY) { \
656             COUNT_SPILLS; \
657             M_LDX(tempnr, REG_SP, (v)->regoff * 8); \
658             regnr = tempnr; \
659         } else { \
660             regnr = (v)->regoff; \
661         } \
662     } while (0)
663                                                                                                                                   
664
665                                                                                                                                   
666         
667 #endif /* _CODEGEN_H */