1 /* src/vm/jit/sparc64/codegen.h - code generation macros and definitions for
4 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
5 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
6 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
7 J. Wenninger, Institut f. Computersprachen - TU Wien
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "vm/jit/jit.h"
36 #include "md-abi.h" /* for INT_NATARG_CNT */
40 /* debug defines **************************************************************/
42 # define PASS13BIT(imm) ((((s4)(imm)&0x1fff)<<19)>>19)
44 # define PASS13BIT(imm) imm
49 s4 nat_argintregs[INT_NATARG_CNT];
51 /* branch defines *************************************************************/
60 /* patcher defines ************************************************************/
62 #define PATCHER_CALL_INSTRUCTIONS 2 /* number of instructions */
63 #define PATCHER_CALL_SIZE 2 * 4 /* size in bytes of a patcher call */
65 #define EXCEPTION_CHECK_INSTRUCTIONS 3 /* number of instructions */
66 #define EXCEPTION_CHECK_SIZE 3 * 4 /* byte size of an exception check */
68 #define PATCHER_NOPS \
75 /* stub defines ***************************************************************/
77 #define COMPILERSTUB_CODESIZE 4 * 4
80 /* additional functions and macros to generate code ***************************/
83 /* MCODECHECK(icnt) */
85 #define MCODECHECK(icnt) \
87 if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
88 codegen_increase(cd); \
92 #define ALIGNCODENOP \
93 if ((s4) ((ptrint) cd->mcodeptr & 7)) { \
97 #define ALIGN_STACK_SLOTS(slots) \
103 generates an integer-move from register rs to rd.
104 if rs and rd are the same int-register, no code will be generated.
107 #define M_INTMOVE(rs,rd) if (rs != rd) { M_MOV(rs, rd); }
111 generates a double floating-point-move from register (pair) rs to rd.
112 if rs and rd are the same double-register, no code will be generated
115 #define M_DBLMOVE(rs, rd) if (rs != rd) { M_DMOV (rs, rd); }
119 generates a double floating-point-move from pseudo register rs to rd.
120 (ie. lower register of double rs pair to lower register of double rd pair)
121 if rs and rd are the same double-register, no code will be generated
123 #define M_FLTMOVE(rs, rd) if (rs != rd) { M_FMOV (rs, rd); }
127 #define M_COPY(s,d) emit_copy(jd, iptr, (s), (d))
128 #define ICONST(d,c) emit_iconst(cd, (d), (c))
129 #define LCONST(d,c) emit_lconst(cd, (d), (c))
134 /********************** instruction formats ***********************************/
139 /* 3-address-operations: M_OP3
141 * op3 ..... operation
142 * rs1 ..... register number source 1
143 * rs2 ..... register number or constant integer source 2
144 * rd ..... register number destination
145 * imm ..... switch to use rs2 as constant 13bit integer
146 * (REG means: use b as register number)
147 * (IMM means: use b as signed immediate value)
149 #define M_OP3(op,op3,rd,rs1,rs2,imm) \
151 assert(check_13bit_imm(rs2)); \
152 *((u4 *) cd->mcodeptr) = ((((s4) (op)) << 30) | ((rd) << 25) | ((op3) << 19) | ((rs1) << 14) | ((imm)<<13) | (imm?((rs2)&0x1fff):(rs2)) ); \
157 #define M_OP3_GET_RD(x) (((x) >> 25) & 0x1f)
158 #define M_OP3_GET_RS(x) (((x) >> 14) & 0x1f)
159 #define M_OP3_GET_IMM(x) ( (x) & 0x1fff)
161 /* 3-address-operations: M_OP3C
162 * rcond ... condition opcode
163 * rs2 ..... register number or 10bit signed immediate
166 #define M_OP3C(op,op3,rcond,rd,rs1,rs2,imm) \
168 *((u4 *) cd->mcodeptr) = ((((s4) (op)) << 30) | ((rd) << 25) | ((op3) << 19) | ((rs1) << 14) | ((imm)<<13) | \
169 ((rcond) << 10) | (imm?((rs2)&0x3ff):(rs2)) ); \
177 * rs1 .... source reg 1
178 * rs2 .... source reg 2 or immediate shift count (5 or 6 bits long depending whether 32 or 64 bit shift)
180 * imm .... switch for constant
181 * x ...... 0 => 32, 1 => 64 bit shift
183 #define M_SHFT(op,op3,rs1,rs2,rd,imm,x) \
185 *((u4 *) cd->mcodeptr) = ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((rs1) << 14) | ((imm) << 13) | \
186 ((x) << 12) | (((imm) && (x))?((rs2) & 0x3f):((rs2) & 0x1f)) ); \
194 * cond ... condition opcode
195 * rs2 .... source 2 or signed 11-bit constant
197 * imm .... switch for constant
198 * cc{0-2} 32-bit 64-bit or fp condition
200 #define M_FMT4(op,op3,rd,rs2,cond,cc2,cc1,cc0,imm) \
202 *((u4 *) cd->mcodeptr) = ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((cc2) << 18) | ((cond) << 14) | \
203 ((imm) << 13) | ((cc1) << 12) | ((cc0) << 11) | ((rs2) & 0x7ff) ); \
208 #define FR_X(r) (((r)<<1) + 1) /* transpose macro for floats which reside in upper half of double word */
209 #define DR_X(r) ((((r)*2)|(((r)*2)>>5)) & 0x1f) /* transpose & pack double, see SPARC spec. */
211 /* 3-address-floating-point-operation
213 * op3,opf .... function-number
215 * rs1 ... source reg (-1 signals unused)
220 #define M_FOP3(op,op3,opf,rd,rs1,rs2) \
222 *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:(rs1)) << 14) | \
223 ((opf)<<5) | (rs2) ); \
226 /* float addressing */
227 #define M_FOP3_FX(op,op3,opf,rd,rs1,rs2) \
229 *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | (FR_X(rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:FR_X(rs1)) << 14) | \
230 ((opf)<<5) | FR_X(rs2) ); \
233 /* double addressing */
234 #define M_FOP3_DX(op,op3,opf,rd,rs1,rs2) \
236 *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | (DR_X(rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:DR_X(rs1)) << 14) | \
237 ((opf)<<5) | DR_X(rs2) ); \
241 /* 3-address-floating-point-compare-operation
243 * op3,opf .... function-number
244 * fcc ... floating point condition code (fcc0 - fcc3)
250 #define M_FCMP_DX(op,op3,opf,fcc,rs1,rs2) \
252 *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((fcc)<<25) | ((op3)<<19) | (DR_X(rs1) << 14) | \
253 ((opf)<<5) | DR_X(rs2) ); \
257 #define M_FCMP_FX(op,op3,opf,fcc,rs1,rs2) \
259 *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((fcc)<<25) | ((op3)<<19) | (FR_X(rs1) << 14) | \
260 ((opf)<<5) | FR_X(rs2) ); \
264 /**** format 2 operations ********/
266 /* branch on integer reg instruction
268 rcond ...... condition to be tested
269 disp16 ... 16-bit relative address to be jumped to (divided by 4)
270 rs1 ..... register to be tested
271 p ..... prediction bit
272 anul .... annullment bit
274 #define M_BRAREG(op,rcond,rs1,disp16,p,anul) \
276 *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((anul)<<29) | (0<<28) | ((rcond)<<25) | (3<<22) | \
277 ( ((disp16)& 0xC000) << 6 ) | (p << 19) | ((rs1) << 14) | ((disp16)&0x3fff) ); \
282 /* branch on integer reg instruction
284 cond ...... condition to be tested
285 disp19 ... 19-bit relative address to be jumped to (divided by 4)
286 ccx ..... 32(0) or 64(2) bit test
287 p ..... prediction bit
288 anul .... annullment bit
290 #define M_BRACC(op,op2,cond,disp19,ccx,p,anul) \
292 *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((anul)<<29) | ((cond)<<25) | (op2<<22) | (ccx<<20) | \
293 (p << 19 ) | ((disp19) & 0x007ffff) ); \
298 /************** end-user instructions (see a SPARC asm manual) ***************/
300 #define M_SETHI(imm22, rd) \
302 *((u4 *) cd->mcodeptr) = ((((s4)(0x00)) << 30) | ((rd) << 25) | ((0x04)<<22) | ((imm22)&0x3FFFFF) ); \
306 #define M_NOP M_SETHI(0,0) /* nop */
308 #define M_AND(rs1,rs2,rd) M_OP3(0x02,0x01,rd,rs1,rs2,REG) /* 64b c = a & b */
309 #define M_AND_IMM(rs1,rs2,rd) M_OP3(0x02,0x01,rd,rs1,rs2,IMM)
310 #define M_ANDCC(rs1,rs2,rd) M_OP3(0x02,0x11,rd,rs1,rs2,REG)
311 #define M_ANDCC_IMM(rs1,rs2,rd) M_OP3(0x02,0x11,rd,rs1,rs2,IMM)
313 #define M_OR(rs1,rs2,rd) M_OP3(0x02,0x02,rd,rs1,rs2,REG) /* rd = rs1 | rs2 */
314 #define M_OR_IMM(rs1,rs2,rd) M_OP3(0x02,0x02,rd,rs1,rs2,IMM)
315 #define M_XOR(rs1,rs2,rd) M_OP3(0x02,0x03,rd,rs1,rs2,REG) /* rd = rs1 ^ rs2 */
316 #define M_XOR_IMM(rs1,rs2,rd) M_OP3(0x02,0x03,rd,rs1,rs2,IMM)
318 #define M_MOV(rs,rd) M_OR(REG_ZERO, rs, rd) /* rd = rs */
319 #define M_CLR(rd) M_OR(REG_ZERO,REG_ZERO,rd) /* rd = 0 */
323 #define M_SLLX(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,REG,1) /* 64b rd = rs << rs2 */
324 #define M_SLLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,1)
325 #define M_SLL(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,REG,0) /* 32b rd = rs << rs2 */
326 #define M_SLL_IMM(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,0)
327 #define M_SRLX(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,REG,1) /* 64b rd = rs >>>rs2 */
328 #define M_SRLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,1)
329 #define M_SRL(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,REG,0) /* 32b rd = rs >>>rs2 */
330 #define M_SRL_IMM(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,0)
331 #define M_SRAX(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,REG,1) /* 64b rd = rs >> rs2 */
332 #define M_SRAX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,1)
333 #define M_SRA(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,REG,0) /* 32b rd = rs >> rs2 */
334 #define M_SRA_IMM(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,0)
336 #define M_ISEXT(rs,rd) M_SRA(rs,REG_ZERO,rd) /* sign extend 32 bits*/
339 #define M_ADD(rs1,rs2,rd) M_OP3(0x02,0x00,rd,rs1,rs2,REG) /* 64b rd = rs1 + rs2 */
340 #define M_ADD_IMM(rs1,rs2,rd) M_OP3(0x02,0x00,rd,rs1,rs2,IMM)
341 #define M_SUB(rs1,rs2,rd) M_OP3(0x02,0x04,rd,rs1,rs2,REG) /* 64b rd = rs1 - rs2 */
342 #define M_SUB_IMM(rs1,rs2,rd) M_OP3(0x02,0x04,rd,rs1,rs2,IMM)
343 #define M_MULX(rs1,rs2,rd) M_OP3(0x02,0x09,rd,rs1,rs2,REG) /* 64b rd = rs1 * rs2 */
344 #define M_MULX_IMM(rs1,rs2,rd) M_OP3(0x02,0x09,rd,rs1,rs2,IMM)
345 #define M_DIVX(rs1,rs2,rd) M_OP3(0x02,0x2d,rd,rs1,rs2,REG) /* 64b rd = rs1 / rs2 */
347 #define M_SUBcc(rs1,rs2,rd) M_OP3(0x02,0x14,rd,rs1,rs2,REG) /* sets xcc and icc */
348 #define M_SUBcc_IMM(rs1,rs2,rd) M_OP3(0x02,0x14,rd,rs1,rs2,IMM) /* sets xcc and icc */
352 /**** compare and conditional ALU operations ***********/
354 #define M_CMP(rs1,rs2) M_SUBcc(rs1,rs2,REG_ZERO)
355 #define M_CMP_IMM(rs1,rs2) M_SUBcc_IMM(rs1,rs2,REG_ZERO)
358 /* move integer register on (64-bit) condition */
360 #define M_XCMOVEQ(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x1,1,1,0,REG) /* a==b ? rd=rs */
361 #define M_XCMOVNE(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x9,1,1,0,REG) /* a!=b ? rd=rs */
362 #define M_XCMOVLT(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x3,1,1,0,REG) /* a<b ? rd=rs */
363 #define M_XCMOVGE(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0xb,1,1,0,REG) /* a>=b ? rd=rs */
364 #define M_XCMOVLE(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x2,1,1,0,REG) /* a<=b ? rd=rs */
365 #define M_XCMOVGT(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0xa,1,1,0,REG) /* a>b ? rd=rs */
366 #define M_XCMOVULE(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x4,1,1,0,REG) /* a<=b ? rd=rs (u)*/
368 #define M_XCMOVEQ_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x1,1,1,0,IMM) /* a==b ? rd=rs */
369 #define M_XCMOVNE_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x9,1,1,0,IMM) /* a!=b ? rd=rs */
370 #define M_XCMOVLT_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x3,1,1,0,IMM) /* a<b ? rd=rs */
371 #define M_XCMOVGE_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0xb,1,1,0,IMM) /* a>=b ? rd=rs */
372 #define M_XCMOVLE_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x2,1,1,0,IMM) /* a<=b ? rd=rs */
373 #define M_XCMOVGT_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0xa,1,1,0,IMM) /* a>b ? rd=rs */
374 #define M_XCMOVULE_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x4,1,1,0,IMM) /* a<=b ? rd=rs (u)*/
376 /* move integer register on (fcc0) floating point condition */
378 #define M_CMOVFGT_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x6,0,0,0,IMM) /* fa>fb ? rd=rs */
379 #define M_CMOVFLT_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x4,0,0,0,IMM) /* fa<fb ? rd=rs */
380 #define M_CMOVFEQ_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x9,0,0,0,IMM) /* fa==fb ? rd=rs */
382 /* move integer register on (32-bit) condition */
386 /* move integer register on register condition */
388 #define M_CMOVREQ(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x1,rd,rs1,rs2,REG) /* rs1==0 ? rd=rs2 */
389 #define M_CMOVRNE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x5,rd,rs1,rs2,REG) /* rs1!=0 ? rd=rs2 */
390 #define M_CMOVRLE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x2,rd,rs1,rs2,REG) /* rs1<=0 ? rd=rs2 */
391 #define M_CMOVRLT(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x3,rd,rs1,rs2,REG) /* rs1<0 ? rd=rs2 */
392 #define M_CMOVRGT(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x6,rd,rs1,rs2,REG) /* rs1>0 ? rd=rs2 */
393 #define M_CMOVRGE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x7,rd,rs1,rs2,REG) /* rs1>=0 ? rd=rs2 */
395 #define M_CMOVREQ_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x1,rd,rs1,rs2,IMM) /* rs1==0 ? rd=rs2 */
396 #define M_CMOVRNE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x5,rd,rs1,rs2,IMM) /* rs1!=0 ? rd=rs2 */
397 #define M_CMOVRLE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x2,rd,rs1,rs2,IMM) /* rs1<=0 ? rd=rs2 */
398 #define M_CMOVRLT_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x3,rd,rs1,rs2,IMM) /* rs1<0 ? rd=rs2 */
399 #define M_CMOVRGT_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x6,rd,rs1,rs2,IMM) /* rs1>0 ? rd=rs2 */
400 #define M_CMOVRGE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x7,rd,rs1,rs2,IMM) /* rs1>=0 ? rd=rs2 */
403 /**** big constant helpers *********/
405 /* #define FITS_13BIT_IMM(x) ((x >= -4096) && (x <= 4095)) */
407 bool fits_13(s4 disp);
408 s4 get_lopart_disp(s4 disp);
410 #define abs(x) ((x) < 0 ? (-(x)) : (x))
412 #define sethi_part(x) ((x)>>10)
413 #define setlo_part(x) ((x) & 0x3ff)
415 #define DO_SETHI_REG(c,rd) \
418 M_SETHI(sethi_part(c), rd); \
419 if (setlo_part(c)) { \
420 M_OR_IMM(rd, setlo_part(c), rd); \
424 M_SETHI(sethi_part(~c), rd); \
425 M_XOR_IMM(rd, PASS13BIT(setlo_part(c) | 0xffffffffffff1c00), rd); \
429 #define DO_SETHI_PART(c,rs,rd) \
432 M_SETHI(sethi_part(c), rd); \
436 M_SETHI(sethi_part(-c), rd); \
438 assert(sethi_part(c) != 0xf); \
445 #define M_LDA(rd,rs,disp) \
447 if (fits_13(disp)) { \
448 M_AADD_IMM(rs,disp,rd); \
451 DO_SETHI_REG(disp,rd); \
456 /**** load/store operations ********/
458 #define M_SLDU(rd,rs,disp) M_OP3(0x03,0x02,rd,rs,disp,IMM) /* 16-bit load, uns*/
459 #define M_SLDS(rd,rs,disp) M_OP3(0x03,0x0a,rd,rs,disp,IMM) /* 16-bit load, sig*/
460 #define M_BLDS(rd,rs,disp) M_OP3(0x03,0x09,rd,rs,disp,IMM) /* 8-bit load, sig */
463 #define M_LDX_INTERN(rd,rs,disp) M_OP3(0x03,0x0b,rd,rs,disp,IMM) /* 64-bit load, sig*/
464 #define M_LDX(rd,rs,disp) \
466 if (fits_13(disp)) { \
467 M_LDX_INTERN(rd,rs,disp); \
470 DO_SETHI_PART(disp,rs,rd); \
471 M_LDX_INTERN(rd,rd,PASS13BIT(get_lopart_disp(disp))); \
475 #define M_ILD_INTERN(rd,rs,disp) M_OP3(0x03,0x08,rd,rs,disp,IMM) /* 32-bit load, sig */
476 #define M_ILD(rd,rs,disp) \
478 if (fits_13(disp)) { \
479 M_ILD_INTERN(rd,rs,disp); \
482 DO_SETHI_PART(disp,rs,rd); \
483 M_ILD_INTERN(rd,rd,PASS13BIT(get_lopart_disp(disp))); \
489 #define M_SST(rd,rs,disp) M_OP3(0x03,0x06,rd,rs,disp,IMM) /* 16-bit store */
490 #define M_BST(rd,rs,disp) M_OP3(0x03,0x05,rd,rs,disp,IMM) /* 8-bit store */
492 /* Stores with displacement overflow should only happen with PUTFIELD or on */
493 /* the stack. The PUTFIELD instruction does not use REG_ITMP3 and a */
494 /* reg_of_var call should not use REG_ITMP3!!! */
496 #define M_STX_INTERN(rd,rs,disp) M_OP3(0x03,0x0e,rd,rs,disp,IMM) /* 64-bit store */
497 #define M_STX(rd,rs,disp) \
499 if (fits_13(disp)) { \
500 M_STX_INTERN(rd,rs,disp); \
503 DO_SETHI_PART(disp,rs,REG_ITMP3); \
504 M_STX_INTERN(rd,REG_ITMP3,PASS13BIT(get_lopart_disp(disp))); \
509 #define M_IST_INTERN(rd,rs,disp) M_OP3(0x03,0x04,rd,rs,disp,IMM) /* 32-bit store */
510 #define M_IST(rd,rs,disp) \
512 if (fits_13(disp)) { \
513 M_IST_INTERN(rd,rs,disp); \
516 DO_SETHI_PART(disp,rs,REG_ITMP3); \
517 M_IST_INTERN(rd,REG_ITMP3,PASS13BIT(get_lopart_disp(disp))); \
522 /**** branch operations ********/
523 /* XXX prediction and annul bits currently set to defaults, but could be used for optimizations */
525 /* branch on integer register */
527 #define M_BEQZ(r,disp) M_BRAREG(0x0,0x1,r,disp,1,0) /* br r == 0 */
528 #define M_BLEZ(r,disp) M_BRAREG(0x0,0x2,r,disp,1,0) /* br r <= 0 */
529 #define M_BLTZ(r,disp) M_BRAREG(0x0,0x3,r,disp,1,0) /* br r < 0 */
530 #define M_BNEZ(r,disp) M_BRAREG(0x0,0x5,r,disp,1,0) /* br r != 0 */
531 #define M_BGTZ(r,disp) M_BRAREG(0x0,0x6,r,disp,1,0) /* br r > 0 */
532 #define M_BGEZ(r,disp) M_BRAREG(0x0,0x7,r,disp,1,0) /* br r >= 0 */
535 /* branch on (64-bit) integer condition codes */
537 #define M_XBEQ(disp) M_BRACC(0x00,0x1,0x1,disp,2,1,0) /* branch a==b */
538 #define M_XBNE(disp) M_BRACC(0x00,0x1,0x9,disp,2,1,0) /* branch a!=b */
539 #define M_XBGT(disp) M_BRACC(0x00,0x1,0xa,disp,2,1,0) /* branch a>b */
540 #define M_XBLT(disp) M_BRACC(0x00,0x1,0x3,disp,2,1,0) /* branch a<b */
541 #define M_XBGE(disp) M_BRACC(0x00,0x1,0xb,disp,2,1,0) /* branch a>=b */
542 #define M_XBLE(disp) M_BRACC(0x00,0x1,0x2,disp,2,1,0) /* branch a<=b */
543 #define M_XBUGE(disp) M_BRACC(0x00,0x1,0xd,disp,2,1,0) /* br uns a>=b */
544 #define M_XBUGT(disp) M_BRACC(0x00,0x1,0xc,disp,2,1,0) /* br uns a>b */
545 #define M_XBULT(disp) M_BRACC(0x00,0x1,0x5,disp,2,1,0) /* br uns a<b */
547 /* branch on (32-bit) integer condition codes */
549 #define M_BR(disp) M_BRACC(0x00,0x1,0x8,disp,0,1,0) /* branch */
550 #define M_BEQ(disp) M_BRACC(0x00,0x1,0x1,disp,0,1,0) /* branch a==b */
551 #define M_BNE(disp) M_BRACC(0x00,0x1,0x9,disp,0,1,0) /* branch a!=b */
552 #define M_BGT(disp) M_BRACC(0x00,0x1,0xa,disp,0,1,0) /* branch a>b */
553 #define M_BLT(disp) M_BRACC(0x00,0x1,0x3,disp,0,1,0) /* branch a<b */
554 #define M_BGE(disp) M_BRACC(0x00,0x1,0xb,disp,0,1,0) /* branch a>=b */
555 #define M_BLE(disp) M_BRACC(0x00,0x1,0x2,disp,0,1,0) /* branch a<=b */
556 #define M_BULE(disp) M_BRACC(0x00,0x1,0x4,disp,0,1,0) /* br uns a<=b */
557 #define M_BUGT(disp) M_BRACC(0x00,0x1,0xc,disp,0,1,0) /* br uns a>b */
558 #define M_BULT(disp) M_BRACC(0x00,0x1,0x5,disp,0,1,0) /* br uns a<b */
560 /* branch on (fcc0) floating point condition codes */
562 #define M_FBR(disp) M_BRACC(0x00,0x5,0x8,disp,0,1,0) /* branch */
563 #define M_FBU(disp) M_BRACC(0x00,0x5,0x7,disp,0,1,0) /* unordered */
564 #define M_FBG(disp) M_BRACC(0x00,0x5,0x6,disp,0,1,0) /* branch a>b */
565 #define M_FBL(disp) M_BRACC(0x00,0x5,0x4,disp,0,1,0) /* branch a<b */
566 #define M_FBO(disp) M_BRACC(0x00,0x5,0xf,disp,0,1,0) /* br ordered */
570 #define M_SAVE(rs1,rs2,rd) M_OP3(0x02,0x3c,rd,rs1,rs2,IMM)
571 #define M_SAVE_REG(rs1,rs2,rd) M_OP3(0x02,0x3c,rd,rs1,rs2,REG)
572 #define M_RESTORE(rs1,rs2,rd) M_OP3(0x02,0x3d,rd,rs1,rs2,IMM)
576 #define M_JMP(rd,rs1,rs2) M_OP3(0x02,0x38,rd, rs1,rs2,REG) /* jump to rs1+rs2, adr of instr. saved to rd */
577 #define M_JMP_IMM(rd,rs1,rs2) M_OP3(0x02,0x38,rd, rs1,rs2,IMM)
578 #define M_RET(rs1,imm) M_OP3(0x02,0x38,REG_ZERO,rs1,imm,IMM) /* a jump which discards the current pc */
580 #define M_RETURN(rs1,imm) M_OP3(0x02,0x39,0,rs1,imm,IMM) /* like ret, but does window restore */
582 /**** floating point operations **/
585 #define M_DMOV(rs,rd) M_FOP3_DX(0x02,0x34,0x02,rd,-1,rs) /* rd = rs */
586 #define M_FMOV(rs,rd) M_FOP3_FX(0x02,0x34,0x01,rd,-1,rs) /* rd = rs */
588 #define M_FMOV_INTERN(rs,rd) M_FOP3(0x02,0x34,0x01,rd,-1,rs) /* rd = rs */
590 #define M_FNEG(rs,rd) M_FOP3_FX(0x02,0x34,0x05,rd,-1,rs) /* rd = -rs */
591 #define M_DNEG(rs,rd) M_FOP3_DX(0x02,0x34,0x06,rd,-1,rs) /* rd = -rs */
593 #define M_FADD(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x41,rd,rs1,rs2) /* float add */
594 #define M_DADD(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x42,rd,rs1,rs2) /* double add */
595 #define M_FSUB(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x045,rd,rs1,rs2) /* float sub */
596 #define M_DSUB(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x046,rd,rs1,rs2) /* double sub */
597 #define M_FMUL(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x049,rd,rs1,rs2) /* float mul */
598 #define M_DMUL(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x04a,rd,rs1,rs2) /* double mul */
599 #define M_FDIV(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x04d,rd,rs1,rs2) /* float div */
600 #define M_DDIV(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x04e,rd,rs1,rs2) /* double div */
603 /**** compare and conditional FPU operations ***********/
605 /* rd field 0 ==> fcc target unit is fcc0 */
606 #define M_FCMP(rs1,rs2) M_FCMP_FX(0x02,0x35,0x051,0,rs1,rs2) /* compare flt */
607 #define M_DCMP(rs1,rs2) M_FCMP_DX(0x02,0x35,0x052,0,rs1,rs2) /* compare dbl */
609 /* conversion functions */
611 #define M_CVTIF(rs,rd) M_FOP3_FX(0x02,0x34,0x0c4,rd,-1,rs)/* int2flt */
612 #define M_CVTID(rs,rd) M_FOP3(0x02,0x34,0x0c8,DR_X(rd),-1,FR_X(rs)) /* int2dbl */
613 #define M_CVTLF(rs,rd) M_FOP3(0x02,0x34,0x084,FR_X(rd),-1,DR_X(rs)) /* long2flt */
614 #define M_CVTLD(rs,rd) M_FOP3_DX(0x02,0x34,0x088,rd,-1,rs) /* long2dbl */
616 #define M_CVTFI(rs,rd) M_FOP3_FX(0x02,0x34,0x0d1,rd,-1,rs) /* flt2int */
617 #define M_CVTDI(rs,rd) M_FOP3(0x02,0x34,0x0d2,FR_X(rd),-1,DR_X(rs)) /* dbl2int */
618 #define M_CVTFL(rs,rd) M_FOP3(0x02,0x34,0x081,DR_X(rd),-1,FR_X(rs)) /* flt2long */
619 #define M_CVTDL(rs,rd) M_FOP3_DX(0x02,0x34,0x082,rd,-1,rs) /* dbl2long */
621 #define M_CVTFD(rs,rd) M_FOP3(0x02,0x34,0x0c9,DR_X(rd),-1,FR_X(rs)) /* flt2dbl */
622 #define M_CVTDF(rs,rd) M_FOP3(0x02,0x34,0x0c6,FR_X(rd),-1,DR_X(rs)) /* dbl2float */
626 #define M_DLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x23,DR_X(rd),rs1,disp,IMM) /* double (64-bit) load */
627 #define M_DLD(rd,rs,disp) \
629 s4 lo = (short) (disp); \
630 s4 hi = (short) (((disp) - lo) >> 13); \
632 M_DLD_INTERN(rd,rs,lo); \
634 M_SETHI(hi&0x3ffff8,rd); \
636 M_DLD_INTERN(rd,rd,PASS13BIT(lo)); \
639 /* Note for SETHI: sethi has a 22bit imm, only set upper 19 bits */
641 #define M_FLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x20,FR_X(rd),rs1,disp,IMM) /* float (32-bit) load */
642 #define M_FLD(rd,rs,disp) \
644 s4 lo = (short) (disp); \
645 s4 hi = (short) (((disp) - lo) >> 13); \
647 M_FLD_INTERN(rd,rs,lo); \
649 M_SETHI(hi&0x3ffff8,rd); \
651 M_FLD_INTERN(rd,rd,PASS13BIT(lo)); \
656 #define M_FST_INTERN(rd,rs,disp) M_OP3(0x03,0x24,FR_X(rd),rs,disp,IMM) /* float (32-bit) store */
657 #define M_FST(rd,rs,disp) \
659 s4 lo = (short) (disp); \
660 s4 hi = (short) (((disp) - lo) >> 13); \
662 M_FST_INTERN(rd,rs,lo); \
664 M_SETHI(hi&0x3ffff8,REG_ITMP3); \
665 M_AADD(rs,REG_ITMP3,REG_ITMP3); \
666 M_FST_INTERN(rd,REG_ITMP3,PASS13BIT(lo)); \
671 #define M_DST_INTERN(rd,rs1,disp) M_OP3(0x03,0x27,DR_X(rd),rs1,disp,IMM) /* double (64-bit) store */
672 #define M_DST(rd,rs,disp) \
674 s4 lo = (short) (disp); \
675 s4 hi = (short) (((disp) - lo) >> 13); \
677 M_DST_INTERN(rd,rs,lo); \
679 M_SETHI(hi&0x3ffff8,REG_ITMP3); \
680 M_AADD(rs,REG_ITMP3,REG_ITMP3); \
681 M_DST_INTERN(rd,REG_ITMP3,PASS13BIT(lo)); \
688 * Address pseudo instruction
691 #define POINTERSHIFT 3 /* x8 */
694 #define M_ALD_INTERN(a,b,disp) M_LDX_INTERN(a,b,disp)
695 #define M_ALD(rd,rs,disp) M_LDX(rd,rs,disp)
696 #define M_AST_INTERN(a,b,disp) M_STX_INTERN(a,b,disp)
697 #define M_AST(a,b,disp) M_STX(a,b,disp)
698 #define M_AADD(a,b,c) M_ADD(a,b,c)
699 #define M_AADD_IMM(a,b,c) M_ADD_IMM(a,b,c)
700 #define M_ASUB_IMM(a,b,c) M_SUB_IMM(a,b,c)
701 #define M_ASLL_IMM(a,b,c) M_SLLX_IMM(a,b,c)
704 #endif /* _CODEGEN_H */