2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 #include "tcg-be-null.h"
28 static const char * const tcg_target_reg_names
[TCG_TARGET_NB_REGS
] = {
70 /* Note that sparcv8plus can only hold 64 bit quantities in %g and %o
71 registers. These are saved manually by the kernel in full 64-bit
72 slots. The %i and %l registers are saved by the register window
73 mechanism, which only allocates space for 32 bits. Given that this
74 window spill/fill can happen on any signal, we must consider the
75 high bits of the %i and %l registers garbage at all times. */
77 # define ALL_64 0xffffffffu
79 # define ALL_64 0xffffu
82 /* Define some temporary registers. T2 is used for constant generation. */
83 #define TCG_REG_T1 TCG_REG_G1
84 #define TCG_REG_T2 TCG_REG_O7
86 #ifdef CONFIG_USE_GUEST_BASE
87 # define TCG_GUEST_BASE_REG TCG_REG_I5
89 # define TCG_GUEST_BASE_REG TCG_REG_G0
92 static const int tcg_target_reg_alloc_order
[] = {
122 static const int tcg_target_call_iarg_regs
[6] = {
131 static const int tcg_target_call_oarg_regs
[] = {
138 #define INSN_OP(x) ((x) << 30)
139 #define INSN_OP2(x) ((x) << 22)
140 #define INSN_OP3(x) ((x) << 19)
141 #define INSN_OPF(x) ((x) << 5)
142 #define INSN_RD(x) ((x) << 25)
143 #define INSN_RS1(x) ((x) << 14)
144 #define INSN_RS2(x) (x)
145 #define INSN_ASI(x) ((x) << 5)
147 #define INSN_IMM10(x) ((1 << 13) | ((x) & 0x3ff))
148 #define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff))
149 #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
150 #define INSN_OFF16(x) ((((x) >> 2) & 0x3fff) | ((((x) >> 16) & 3) << 20))
151 #define INSN_OFF19(x) (((x) >> 2) & 0x07ffff)
152 #define INSN_COND(x) ((x) << 25)
170 #define BA (INSN_OP(0) | INSN_COND(COND_A) | INSN_OP2(0x2))
179 #define MOVCC_ICC (1 << 18)
180 #define MOVCC_XCC (1 << 18 | 1 << 12)
183 #define BPCC_XCC (2 << 20)
184 #define BPCC_PT (1 << 19)
186 #define BPCC_A (1 << 29)
188 #define BPR_PT BPCC_PT
190 #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00))
191 #define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10))
192 #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01))
193 #define ARITH_ANDN (INSN_OP(2) | INSN_OP3(0x05))
194 #define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02))
195 #define ARITH_ORCC (INSN_OP(2) | INSN_OP3(0x12))
196 #define ARITH_ORN (INSN_OP(2) | INSN_OP3(0x06))
197 #define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03))
198 #define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x04))
199 #define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14))
200 #define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x08))
201 #define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c))
202 #define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a))
203 #define ARITH_SMUL (INSN_OP(2) | INSN_OP3(0x0b))
204 #define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e))
205 #define ARITH_SDIV (INSN_OP(2) | INSN_OP3(0x0f))
206 #define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09))
207 #define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d))
208 #define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d))
209 #define ARITH_MOVCC (INSN_OP(2) | INSN_OP3(0x2c))
210 #define ARITH_MOVR (INSN_OP(2) | INSN_OP3(0x2f))
212 #define SHIFT_SLL (INSN_OP(2) | INSN_OP3(0x25))
213 #define SHIFT_SRL (INSN_OP(2) | INSN_OP3(0x26))
214 #define SHIFT_SRA (INSN_OP(2) | INSN_OP3(0x27))
216 #define SHIFT_SLLX (INSN_OP(2) | INSN_OP3(0x25) | (1 << 12))
217 #define SHIFT_SRLX (INSN_OP(2) | INSN_OP3(0x26) | (1 << 12))
218 #define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12))
220 #define RDY (INSN_OP(2) | INSN_OP3(0x28) | INSN_RS1(0))
221 #define WRY (INSN_OP(2) | INSN_OP3(0x30) | INSN_RD(0))
222 #define JMPL (INSN_OP(2) | INSN_OP3(0x38))
223 #define RETURN (INSN_OP(2) | INSN_OP3(0x39))
224 #define SAVE (INSN_OP(2) | INSN_OP3(0x3c))
225 #define RESTORE (INSN_OP(2) | INSN_OP3(0x3d))
226 #define SETHI (INSN_OP(0) | INSN_OP2(0x4))
227 #define CALL INSN_OP(1)
228 #define LDUB (INSN_OP(3) | INSN_OP3(0x01))
229 #define LDSB (INSN_OP(3) | INSN_OP3(0x09))
230 #define LDUH (INSN_OP(3) | INSN_OP3(0x02))
231 #define LDSH (INSN_OP(3) | INSN_OP3(0x0a))
232 #define LDUW (INSN_OP(3) | INSN_OP3(0x00))
233 #define LDSW (INSN_OP(3) | INSN_OP3(0x08))
234 #define LDX (INSN_OP(3) | INSN_OP3(0x0b))
235 #define STB (INSN_OP(3) | INSN_OP3(0x05))
236 #define STH (INSN_OP(3) | INSN_OP3(0x06))
237 #define STW (INSN_OP(3) | INSN_OP3(0x04))
238 #define STX (INSN_OP(3) | INSN_OP3(0x0e))
239 #define LDUBA (INSN_OP(3) | INSN_OP3(0x11))
240 #define LDSBA (INSN_OP(3) | INSN_OP3(0x19))
241 #define LDUHA (INSN_OP(3) | INSN_OP3(0x12))
242 #define LDSHA (INSN_OP(3) | INSN_OP3(0x1a))
243 #define LDUWA (INSN_OP(3) | INSN_OP3(0x10))
244 #define LDSWA (INSN_OP(3) | INSN_OP3(0x18))
245 #define LDXA (INSN_OP(3) | INSN_OP3(0x1b))
246 #define STBA (INSN_OP(3) | INSN_OP3(0x15))
247 #define STHA (INSN_OP(3) | INSN_OP3(0x16))
248 #define STWA (INSN_OP(3) | INSN_OP3(0x14))
249 #define STXA (INSN_OP(3) | INSN_OP3(0x1e))
251 #ifndef ASI_PRIMARY_LITTLE
252 #define ASI_PRIMARY_LITTLE 0x88
255 #define LDUH_LE (LDUHA | INSN_ASI(ASI_PRIMARY_LITTLE))
256 #define LDSH_LE (LDSHA | INSN_ASI(ASI_PRIMARY_LITTLE))
257 #define LDUW_LE (LDUWA | INSN_ASI(ASI_PRIMARY_LITTLE))
258 #define LDSW_LE (LDSWA | INSN_ASI(ASI_PRIMARY_LITTLE))
259 #define LDX_LE (LDXA | INSN_ASI(ASI_PRIMARY_LITTLE))
261 #define STH_LE (STHA | INSN_ASI(ASI_PRIMARY_LITTLE))
262 #define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE))
263 #define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE))
265 static inline int check_fit_i64(int64_t val
, unsigned int bits
)
267 return val
== sextract64(val
, 0, bits
);
270 static inline int check_fit_i32(int32_t val
, unsigned int bits
)
272 return val
== sextract32(val
, 0, bits
);
275 #define check_fit_tl check_fit_i64
277 # define check_fit_ptr check_fit_i64
279 # define check_fit_ptr check_fit_i32
282 static void patch_reloc(uint8_t *code_ptr
, int type
,
283 intptr_t value
, intptr_t addend
)
289 if (value
!= (uint32_t)value
) {
292 *(uint32_t *)code_ptr
= value
;
294 case R_SPARC_WDISP16
:
295 value
-= (intptr_t)code_ptr
;
296 if (!check_fit_ptr(value
>> 2, 16)) {
299 insn
= *(uint32_t *)code_ptr
;
300 insn
&= ~INSN_OFF16(-1);
301 insn
|= INSN_OFF16(value
);
302 *(uint32_t *)code_ptr
= insn
;
304 case R_SPARC_WDISP19
:
305 value
-= (intptr_t)code_ptr
;
306 if (!check_fit_ptr(value
>> 2, 19)) {
309 insn
= *(uint32_t *)code_ptr
;
310 insn
&= ~INSN_OFF19(-1);
311 insn
|= INSN_OFF19(value
);
312 *(uint32_t *)code_ptr
= insn
;
319 /* parse target specific constraints */
320 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
)
327 ct
->ct
|= TCG_CT_REG
;
328 tcg_regset_set32(ct
->u
.regs
, 0, 0xffffffff);
331 ct
->ct
|= TCG_CT_REG
;
332 tcg_regset_set32(ct
->u
.regs
, 0, ALL_64
);
334 case 'A': /* qemu_ld/st address constraint */
335 ct
->ct
|= TCG_CT_REG
;
336 tcg_regset_set32(ct
->u
.regs
, 0,
337 TARGET_LONG_BITS
== 64 ? ALL_64
: 0xffffffff);
339 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_O0
);
340 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_O1
);
341 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_O2
);
343 case 's': /* qemu_st data 32-bit constraint */
344 ct
->ct
|= TCG_CT_REG
;
345 tcg_regset_set32(ct
->u
.regs
, 0, 0xffffffff);
346 goto reserve_helpers
;
347 case 'S': /* qemu_st data 64-bit constraint */
348 ct
->ct
|= TCG_CT_REG
;
349 tcg_regset_set32(ct
->u
.regs
, 0, ALL_64
);
350 goto reserve_helpers
;
352 ct
->ct
|= TCG_CT_CONST_S11
;
355 ct
->ct
|= TCG_CT_CONST_S13
;
358 ct
->ct
|= TCG_CT_CONST_ZERO
;
368 /* test if a constant matches the constraint */
369 static inline int tcg_target_const_match(tcg_target_long val
, TCGType type
,
370 const TCGArgConstraint
*arg_ct
)
374 if (ct
& TCG_CT_CONST
) {
378 if (type
== TCG_TYPE_I32
) {
382 if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0) {
384 } else if ((ct
& TCG_CT_CONST_S11
) && check_fit_tl(val
, 11)) {
386 } else if ((ct
& TCG_CT_CONST_S13
) && check_fit_tl(val
, 13)) {
393 static inline void tcg_out_arith(TCGContext
*s
, int rd
, int rs1
, int rs2
,
396 tcg_out32(s
, op
| INSN_RD(rd
) | INSN_RS1(rs1
) |
400 static inline void tcg_out_arithi(TCGContext
*s
, int rd
, int rs1
,
401 uint32_t offset
, int op
)
403 tcg_out32(s
, op
| INSN_RD(rd
) | INSN_RS1(rs1
) |
407 static void tcg_out_arithc(TCGContext
*s
, int rd
, int rs1
,
408 int val2
, int val2const
, int op
)
410 tcg_out32(s
, op
| INSN_RD(rd
) | INSN_RS1(rs1
)
411 | (val2const
? INSN_IMM13(val2
) : INSN_RS2(val2
)));
414 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
,
415 TCGReg ret
, TCGReg arg
)
418 tcg_out_arith(s
, ret
, arg
, TCG_REG_G0
, ARITH_OR
);
422 static inline void tcg_out_sethi(TCGContext
*s
, int ret
, uint32_t arg
)
424 tcg_out32(s
, SETHI
| INSN_RD(ret
) | ((arg
& 0xfffffc00) >> 10));
427 static inline void tcg_out_movi_imm13(TCGContext
*s
, int ret
, uint32_t arg
)
429 tcg_out_arithi(s
, ret
, TCG_REG_G0
, arg
, ARITH_OR
);
432 static void tcg_out_movi(TCGContext
*s
, TCGType type
,
433 TCGReg ret
, tcg_target_long arg
)
435 tcg_target_long hi
, lo
= (int32_t)arg
;
437 /* A 13-bit constant sign-extended to 64-bits. */
438 if (check_fit_tl(arg
, 13)) {
439 tcg_out_movi_imm13(s
, ret
, arg
);
443 /* A 32-bit constant, or 32-bit zero-extended to 64-bits. */
444 if (type
== TCG_TYPE_I32
|| arg
== (uint32_t)arg
) {
445 tcg_out_sethi(s
, ret
, arg
);
447 tcg_out_arithi(s
, ret
, ret
, arg
& 0x3ff, ARITH_OR
);
452 /* A 32-bit constant sign-extended to 64-bits. */
454 tcg_out_sethi(s
, ret
, ~arg
);
455 tcg_out_arithi(s
, ret
, ret
, (arg
& 0x3ff) | -0x400, ARITH_XOR
);
459 /* A 64-bit constant decomposed into 2 32-bit pieces. */
460 if (check_fit_i32(lo
, 13)) {
461 hi
= (arg
- lo
) >> 32;
462 tcg_out_movi(s
, TCG_TYPE_I32
, ret
, hi
);
463 tcg_out_arithi(s
, ret
, ret
, 32, SHIFT_SLLX
);
464 tcg_out_arithi(s
, ret
, ret
, lo
, ARITH_ADD
);
467 tcg_out_movi(s
, TCG_TYPE_I32
, ret
, hi
);
468 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T2
, lo
);
469 tcg_out_arithi(s
, ret
, ret
, 32, SHIFT_SLLX
);
470 tcg_out_arith(s
, ret
, ret
, TCG_REG_T2
, ARITH_OR
);
474 static inline void tcg_out_ldst_rr(TCGContext
*s
, int data
, int a1
,
477 tcg_out32(s
, op
| INSN_RD(data
) | INSN_RS1(a1
) | INSN_RS2(a2
));
480 static inline void tcg_out_ldst(TCGContext
*s
, int ret
, int addr
,
483 if (check_fit_ptr(offset
, 13)) {
484 tcg_out32(s
, op
| INSN_RD(ret
) | INSN_RS1(addr
) |
487 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_T1
, offset
);
488 tcg_out_ldst_rr(s
, ret
, addr
, TCG_REG_T1
, op
);
492 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg ret
,
493 TCGReg arg1
, intptr_t arg2
)
495 tcg_out_ldst(s
, ret
, arg1
, arg2
, (type
== TCG_TYPE_I32
? LDUW
: LDX
));
498 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
,
499 TCGReg arg1
, intptr_t arg2
)
501 tcg_out_ldst(s
, arg
, arg1
, arg2
, (type
== TCG_TYPE_I32
? STW
: STX
));
504 static inline void tcg_out_ld_ptr(TCGContext
*s
, TCGReg ret
, uintptr_t arg
)
506 TCGReg base
= TCG_REG_G0
;
507 if (!check_fit_ptr(arg
, 10)) {
508 tcg_out_movi(s
, TCG_TYPE_PTR
, ret
, arg
& ~0x3ff);
511 tcg_out_ld(s
, TCG_TYPE_PTR
, ret
, base
, arg
& 0x3ff);
514 static inline void tcg_out_sety(TCGContext
*s
, int rs
)
516 tcg_out32(s
, WRY
| INSN_RS1(TCG_REG_G0
) | INSN_RS2(rs
));
519 static inline void tcg_out_rdy(TCGContext
*s
, int rd
)
521 tcg_out32(s
, RDY
| INSN_RD(rd
));
524 static inline void tcg_out_addi(TCGContext
*s
, int reg
, tcg_target_long val
)
527 if (check_fit_tl(val
, 13))
528 tcg_out_arithi(s
, reg
, reg
, val
, ARITH_ADD
);
530 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_T1
, val
);
531 tcg_out_arith(s
, reg
, reg
, TCG_REG_T1
, ARITH_ADD
);
536 static void tcg_out_div32(TCGContext
*s
, int rd
, int rs1
,
537 int val2
, int val2const
, int uns
)
539 /* Load Y with the sign/zero extension of RS1 to 64-bits. */
541 tcg_out_sety(s
, TCG_REG_G0
);
543 tcg_out_arithi(s
, TCG_REG_T1
, rs1
, 31, SHIFT_SRA
);
544 tcg_out_sety(s
, TCG_REG_T1
);
547 tcg_out_arithc(s
, rd
, rs1
, val2
, val2const
,
548 uns
? ARITH_UDIV
: ARITH_SDIV
);
551 static inline void tcg_out_nop(TCGContext
*s
)
553 tcg_out_sethi(s
, TCG_REG_G0
, 0);
556 static const uint8_t tcg_cond_to_bcond
[] = {
557 [TCG_COND_EQ
] = COND_E
,
558 [TCG_COND_NE
] = COND_NE
,
559 [TCG_COND_LT
] = COND_L
,
560 [TCG_COND_GE
] = COND_GE
,
561 [TCG_COND_LE
] = COND_LE
,
562 [TCG_COND_GT
] = COND_G
,
563 [TCG_COND_LTU
] = COND_CS
,
564 [TCG_COND_GEU
] = COND_CC
,
565 [TCG_COND_LEU
] = COND_LEU
,
566 [TCG_COND_GTU
] = COND_GU
,
569 static const uint8_t tcg_cond_to_rcond
[] = {
570 [TCG_COND_EQ
] = RCOND_Z
,
571 [TCG_COND_NE
] = RCOND_NZ
,
572 [TCG_COND_LT
] = RCOND_LZ
,
573 [TCG_COND_GT
] = RCOND_GZ
,
574 [TCG_COND_LE
] = RCOND_LEZ
,
575 [TCG_COND_GE
] = RCOND_GEZ
578 static void tcg_out_bpcc0(TCGContext
*s
, int scond
, int flags
, int off19
)
580 tcg_out32(s
, INSN_OP(0) | INSN_OP2(1) | INSN_COND(scond
) | flags
| off19
);
583 static void tcg_out_bpcc(TCGContext
*s
, int scond
, int flags
, int label
)
585 TCGLabel
*l
= &s
->labels
[label
];
589 off19
= INSN_OFF19(l
->u
.value
- (unsigned long)s
->code_ptr
);
591 /* Make sure to preserve destinations during retranslation. */
592 off19
= *(uint32_t *)s
->code_ptr
& INSN_OFF19(-1);
593 tcg_out_reloc(s
, s
->code_ptr
, R_SPARC_WDISP19
, label
, 0);
595 tcg_out_bpcc0(s
, scond
, flags
, off19
);
598 static void tcg_out_cmp(TCGContext
*s
, TCGArg c1
, TCGArg c2
, int c2const
)
600 tcg_out_arithc(s
, TCG_REG_G0
, c1
, c2
, c2const
, ARITH_SUBCC
);
603 static void tcg_out_brcond_i32(TCGContext
*s
, TCGCond cond
, TCGArg arg1
,
604 TCGArg arg2
, int const_arg2
, int label
)
606 tcg_out_cmp(s
, arg1
, arg2
, const_arg2
);
607 tcg_out_bpcc(s
, tcg_cond_to_bcond
[cond
], BPCC_ICC
| BPCC_PT
, label
);
611 static void tcg_out_movcc(TCGContext
*s
, TCGCond cond
, int cc
, TCGArg ret
,
612 TCGArg v1
, int v1const
)
614 tcg_out32(s
, ARITH_MOVCC
| cc
| INSN_RD(ret
)
615 | INSN_RS1(tcg_cond_to_bcond
[cond
])
616 | (v1const
? INSN_IMM11(v1
) : INSN_RS2(v1
)));
619 static void tcg_out_movcond_i32(TCGContext
*s
, TCGCond cond
, TCGArg ret
,
620 TCGArg c1
, TCGArg c2
, int c2const
,
621 TCGArg v1
, int v1const
)
623 tcg_out_cmp(s
, c1
, c2
, c2const
);
624 tcg_out_movcc(s
, cond
, MOVCC_ICC
, ret
, v1
, v1const
);
627 static void tcg_out_brcond_i64(TCGContext
*s
, TCGCond cond
, TCGArg arg1
,
628 TCGArg arg2
, int const_arg2
, int label
)
630 /* For 64-bit signed comparisons vs zero, we can avoid the compare. */
631 if (arg2
== 0 && !is_unsigned_cond(cond
)) {
632 TCGLabel
*l
= &s
->labels
[label
];
636 off16
= INSN_OFF16(l
->u
.value
- (unsigned long)s
->code_ptr
);
638 /* Make sure to preserve destinations during retranslation. */
639 off16
= *(uint32_t *)s
->code_ptr
& INSN_OFF16(-1);
640 tcg_out_reloc(s
, s
->code_ptr
, R_SPARC_WDISP16
, label
, 0);
642 tcg_out32(s
, INSN_OP(0) | INSN_OP2(3) | BPR_PT
| INSN_RS1(arg1
)
643 | INSN_COND(tcg_cond_to_rcond
[cond
]) | off16
);
645 tcg_out_cmp(s
, arg1
, arg2
, const_arg2
);
646 tcg_out_bpcc(s
, tcg_cond_to_bcond
[cond
], BPCC_XCC
| BPCC_PT
, label
);
651 static void tcg_out_movr(TCGContext
*s
, TCGCond cond
, TCGArg ret
, TCGArg c1
,
652 TCGArg v1
, int v1const
)
654 tcg_out32(s
, ARITH_MOVR
| INSN_RD(ret
) | INSN_RS1(c1
)
655 | (tcg_cond_to_rcond
[cond
] << 10)
656 | (v1const
? INSN_IMM10(v1
) : INSN_RS2(v1
)));
659 static void tcg_out_movcond_i64(TCGContext
*s
, TCGCond cond
, TCGArg ret
,
660 TCGArg c1
, TCGArg c2
, int c2const
,
661 TCGArg v1
, int v1const
)
663 /* For 64-bit signed comparisons vs zero, we can avoid the compare.
664 Note that the immediate range is one bit smaller, so we must check
666 if (c2
== 0 && !is_unsigned_cond(cond
)
667 && (!v1const
|| check_fit_tl(v1
, 10))) {
668 tcg_out_movr(s
, cond
, ret
, c1
, v1
, v1const
);
670 tcg_out_cmp(s
, c1
, c2
, c2const
);
671 tcg_out_movcc(s
, cond
, MOVCC_XCC
, ret
, v1
, v1const
);
675 static void tcg_out_setcond_i32(TCGContext
*s
, TCGCond cond
, TCGArg ret
,
676 TCGArg c1
, TCGArg c2
, int c2const
)
678 /* For 32-bit comparisons, we can play games with ADDX/SUBX. */
682 /* The result of the comparison is in the carry bit. */
687 /* For equality, we can transform to inequality vs zero. */
689 tcg_out_arithc(s
, ret
, c1
, c2
, c2const
, ARITH_XOR
);
691 c1
= TCG_REG_G0
, c2
= ret
, c2const
= 0;
692 cond
= (cond
== TCG_COND_EQ
? TCG_COND_GEU
: TCG_COND_LTU
);
697 /* If we don't need to load a constant into a register, we can
698 swap the operands on GTU/LEU. There's no benefit to loading
699 the constant into a temporary register. */
700 if (!c2const
|| c2
== 0) {
705 cond
= tcg_swap_cond(cond
);
711 tcg_out_cmp(s
, c1
, c2
, c2const
);
712 tcg_out_movi_imm13(s
, ret
, 0);
713 tcg_out_movcc(s
, cond
, MOVCC_ICC
, ret
, 1, 1);
717 tcg_out_cmp(s
, c1
, c2
, c2const
);
718 if (cond
== TCG_COND_LTU
) {
719 tcg_out_arithi(s
, ret
, TCG_REG_G0
, 0, ARITH_ADDX
);
721 tcg_out_arithi(s
, ret
, TCG_REG_G0
, -1, ARITH_SUBX
);
725 static void tcg_out_setcond_i64(TCGContext
*s
, TCGCond cond
, TCGArg ret
,
726 TCGArg c1
, TCGArg c2
, int c2const
)
728 /* For 64-bit signed comparisons vs zero, we can avoid the compare
729 if the input does not overlap the output. */
730 if (c2
== 0 && !is_unsigned_cond(cond
) && c1
!= ret
) {
731 tcg_out_movi_imm13(s
, ret
, 0);
732 tcg_out_movr(s
, cond
, ret
, c1
, 1, 1);
734 tcg_out_cmp(s
, c1
, c2
, c2const
);
735 tcg_out_movi_imm13(s
, ret
, 0);
736 tcg_out_movcc(s
, cond
, MOVCC_XCC
, ret
, 1, 1);
740 static void tcg_out_addsub2(TCGContext
*s
, TCGArg rl
, TCGArg rh
,
741 TCGArg al
, TCGArg ah
, TCGArg bl
, int blconst
,
742 TCGArg bh
, int bhconst
, int opl
, int oph
)
744 TCGArg tmp
= TCG_REG_T1
;
746 /* Note that the low parts are fully consumed before tmp is set. */
747 if (rl
!= ah
&& (bhconst
|| rl
!= bh
)) {
751 tcg_out_arithc(s
, tmp
, al
, bl
, blconst
, opl
);
752 tcg_out_arithc(s
, rh
, ah
, bh
, bhconst
, oph
);
753 tcg_out_mov(s
, TCG_TYPE_I32
, rl
, tmp
);
756 static inline void tcg_out_calli(TCGContext
*s
, uintptr_t dest
)
758 intptr_t disp
= dest
- (uintptr_t)s
->code_ptr
;
760 if (disp
== (int32_t)disp
) {
761 tcg_out32(s
, CALL
| (uint32_t)disp
>> 2);
763 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_T1
, dest
& ~0xfff);
764 tcg_out_arithi(s
, TCG_REG_O7
, TCG_REG_T1
, dest
& 0xfff, JMPL
);
768 #ifdef CONFIG_SOFTMMU
769 static uintptr_t qemu_ld_trampoline
[16];
770 static uintptr_t qemu_st_trampoline
[16];
772 static void build_trampolines(TCGContext
*s
)
774 static uintptr_t const qemu_ld_helpers
[16] = {
775 [MO_UB
] = (uintptr_t)helper_ret_ldub_mmu
,
776 [MO_SB
] = (uintptr_t)helper_ret_ldsb_mmu
,
777 [MO_LEUW
] = (uintptr_t)helper_le_lduw_mmu
,
778 [MO_LESW
] = (uintptr_t)helper_le_ldsw_mmu
,
779 [MO_LEUL
] = (uintptr_t)helper_le_ldul_mmu
,
780 [MO_LEQ
] = (uintptr_t)helper_le_ldq_mmu
,
781 [MO_BEUW
] = (uintptr_t)helper_be_lduw_mmu
,
782 [MO_BESW
] = (uintptr_t)helper_be_ldsw_mmu
,
783 [MO_BEUL
] = (uintptr_t)helper_be_ldul_mmu
,
784 [MO_BEQ
] = (uintptr_t)helper_be_ldq_mmu
,
786 static uintptr_t const qemu_st_helpers
[16] = {
787 [MO_UB
] = (uintptr_t)helper_ret_stb_mmu
,
788 [MO_LEUW
] = (uintptr_t)helper_le_stw_mmu
,
789 [MO_LEUL
] = (uintptr_t)helper_le_stl_mmu
,
790 [MO_LEQ
] = (uintptr_t)helper_le_stq_mmu
,
791 [MO_BEUW
] = (uintptr_t)helper_be_stw_mmu
,
792 [MO_BEUL
] = (uintptr_t)helper_be_stl_mmu
,
793 [MO_BEQ
] = (uintptr_t)helper_be_stq_mmu
,
800 for (i
= 0; i
< 16; ++i
) {
801 if (qemu_ld_helpers
[i
] == 0) {
805 /* May as well align the trampoline. */
806 tramp
= (uintptr_t)s
->code_ptr
;
811 qemu_ld_trampoline
[i
] = tramp
;
813 if (SPARC64
|| TARGET_LONG_BITS
== 32) {
816 /* Install the high part of the address. */
817 tcg_out_arithi(s
, TCG_REG_O1
, TCG_REG_O2
, 32, SHIFT_SRLX
);
821 /* Set the retaddr operand. */
822 tcg_out_mov(s
, TCG_TYPE_PTR
, ra
, TCG_REG_O7
);
823 /* Set the env operand. */
824 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_REG_O0
, TCG_AREG0
);
826 tcg_out_calli(s
, qemu_ld_helpers
[i
]);
827 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_REG_O7
, ra
);
830 for (i
= 0; i
< 16; ++i
) {
831 if (qemu_st_helpers
[i
] == 0) {
835 /* May as well align the trampoline. */
836 tramp
= (uintptr_t)s
->code_ptr
;
841 qemu_st_trampoline
[i
] = tramp
;
847 if (TARGET_LONG_BITS
== 64) {
848 /* Install the high part of the address. */
849 tcg_out_arithi(s
, ra
, ra
+ 1, 32, SHIFT_SRLX
);
854 if ((i
& MO_SIZE
) == MO_64
) {
855 /* Install the high part of the data. */
856 tcg_out_arithi(s
, ra
, ra
+ 1, 32, SHIFT_SRLX
);
861 /* Skip the mem_index argument. */
865 /* Set the retaddr operand. */
866 if (ra
>= TCG_REG_O6
) {
867 tcg_out_st(s
, TCG_TYPE_PTR
, TCG_REG_O7
, TCG_REG_CALL_STACK
,
868 TCG_TARGET_CALL_STACK_OFFSET
);
871 tcg_out_mov(s
, TCG_TYPE_PTR
, ra
, TCG_REG_O7
);
872 /* Set the env operand. */
873 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_REG_O0
, TCG_AREG0
);
875 tcg_out_calli(s
, qemu_st_helpers
[i
]);
876 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_REG_O7
, ra
);
881 /* Generate global QEMU prologue and epilogue code */
882 static void tcg_target_qemu_prologue(TCGContext
*s
)
884 int tmp_buf_size
, frame_size
;
886 /* The TCG temp buffer is at the top of the frame, immediately
887 below the frame pointer. */
888 tmp_buf_size
= CPU_TEMP_BUF_NLONGS
* (int)sizeof(long);
889 tcg_set_frame(s
, TCG_REG_I6
, TCG_TARGET_STACK_BIAS
- tmp_buf_size
,
892 /* TCG_TARGET_CALL_STACK_OFFSET includes the stack bias, but is
893 otherwise the minimal frame usable by callees. */
894 frame_size
= TCG_TARGET_CALL_STACK_OFFSET
- TCG_TARGET_STACK_BIAS
;
895 frame_size
+= TCG_STATIC_CALL_ARGS_SIZE
+ tmp_buf_size
;
896 frame_size
+= TCG_TARGET_STACK_ALIGN
- 1;
897 frame_size
&= -TCG_TARGET_STACK_ALIGN
;
898 tcg_out32(s
, SAVE
| INSN_RD(TCG_REG_O6
) | INSN_RS1(TCG_REG_O6
) |
899 INSN_IMM13(-frame_size
));
901 #ifdef CONFIG_USE_GUEST_BASE
902 if (GUEST_BASE
!= 0) {
903 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_GUEST_BASE_REG
, GUEST_BASE
);
904 tcg_regset_set_reg(s
->reserved_regs
, TCG_GUEST_BASE_REG
);
908 tcg_out_arithi(s
, TCG_REG_G0
, TCG_REG_I1
, 0, JMPL
);
912 /* No epilogue required. We issue ret + restore directly in the TB. */
914 #ifdef CONFIG_SOFTMMU
915 build_trampolines(s
);
919 #if defined(CONFIG_SOFTMMU)
920 /* Perform the TLB load and compare.
923 ADDRLO and ADDRHI contain the possible two parts of the address.
925 MEM_INDEX and S_BITS are the memory context and log2 size of the load.
927 WHICH is the offset into the CPUTLBEntry structure of the slot to read.
928 This should be offsetof addr_read or addr_write.
930 The result of the TLB comparison is in %[ix]cc. The sanitized address
931 is in the returned register, maybe %o0. The TLB addend is in %o1. */
933 static TCGReg
tcg_out_tlb_load(TCGContext
*s
, TCGReg addr
, int mem_index
,
934 TCGMemOp s_bits
, int which
)
936 const TCGReg r0
= TCG_REG_O0
;
937 const TCGReg r1
= TCG_REG_O1
;
938 const TCGReg r2
= TCG_REG_O2
;
941 /* Shift the page number down. */
942 tcg_out_arithi(s
, r1
, addr
, TARGET_PAGE_BITS
, SHIFT_SRL
);
944 /* Mask out the page offset, except for the required alignment. */
945 tcg_out_movi(s
, TCG_TYPE_TL
, TCG_REG_T1
,
946 TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
948 /* Mask the tlb index. */
949 tcg_out_arithi(s
, r1
, r1
, CPU_TLB_SIZE
- 1, ARITH_AND
);
951 /* Mask page, part 2. */
952 tcg_out_arith(s
, r0
, addr
, TCG_REG_T1
, ARITH_AND
);
954 /* Shift the tlb index into place. */
955 tcg_out_arithi(s
, r1
, r1
, CPU_TLB_ENTRY_BITS
, SHIFT_SLL
);
957 /* Relative to the current ENV. */
958 tcg_out_arith(s
, r1
, TCG_AREG0
, r1
, ARITH_ADD
);
960 /* Find a base address that can load both tlb comparator and addend. */
961 tlb_ofs
= offsetof(CPUArchState
, tlb_table
[mem_index
][0]);
962 if (!check_fit_ptr(tlb_ofs
+ sizeof(CPUTLBEntry
), 13)) {
963 tcg_out_addi(s
, r1
, tlb_ofs
& ~0x3ff);
967 /* Load the tlb comparator and the addend. */
968 tcg_out_ld(s
, TCG_TYPE_TL
, r2
, r1
, tlb_ofs
+ which
);
969 tcg_out_ld(s
, TCG_TYPE_PTR
, r1
, r1
, tlb_ofs
+offsetof(CPUTLBEntry
, addend
));
971 /* subcc arg0, arg2, %g0 */
972 tcg_out_cmp(s
, r0
, r2
, 0);
974 /* If the guest address must be zero-extended, do so now. */
975 if (SPARC64
&& TARGET_LONG_BITS
== 32) {
976 tcg_out_arithi(s
, r0
, addr
, 0, SHIFT_SRL
);
981 #endif /* CONFIG_SOFTMMU */
983 static const int qemu_ld_opc
[16] = {
1000 static const int qemu_st_opc
[16] = {
1012 static void tcg_out_qemu_ld(TCGContext
*s
, TCGReg data
, TCGReg addr
,
1013 TCGMemOp memop
, int memi
, bool is_64
)
1015 #ifdef CONFIG_SOFTMMU
1016 TCGMemOp s_bits
= memop
& MO_SIZE
;
1017 TCGReg addrz
, param
;
1019 uint32_t *label_ptr
;
1021 addrz
= tcg_out_tlb_load(s
, addr
, memi
, s_bits
,
1022 offsetof(CPUTLBEntry
, addr_read
));
1024 /* The fast path is exactly one insn. Thus we can perform the
1025 entire TLB Hit in the (annulled) delay slot of the branch
1026 over the TLB Miss case. */
1028 /* beq,a,pt %[xi]cc, label0 */
1029 label_ptr
= (uint32_t *)s
->code_ptr
;
1030 tcg_out_bpcc0(s
, COND_E
, BPCC_A
| BPCC_PT
1031 | (TARGET_LONG_BITS
== 64 ? BPCC_XCC
: BPCC_ICC
), 0);
1033 tcg_out_ldst_rr(s
, data
, addrz
, TCG_REG_O1
, qemu_ld_opc
[memop
]);
1038 if (!SPARC64
&& TARGET_LONG_BITS
== 64) {
1039 /* Skip the high-part; we'll perform the extract in the trampoline. */
1042 tcg_out_mov(s
, TCG_TYPE_REG
, param
++, addr
);
1044 /* We use the helpers to extend SB and SW data, leaving the case
1045 of SL needing explicit extending below. */
1046 if ((memop
& ~MO_BSWAP
) == MO_SL
) {
1047 func
= qemu_ld_trampoline
[memop
& ~MO_SIGN
];
1049 func
= qemu_ld_trampoline
[memop
];
1052 tcg_out_calli(s
, func
);
1054 tcg_out_movi(s
, TCG_TYPE_I32
, param
, memi
);
1056 /* Recall that all of the helpers return 64-bit results.
1057 Which complicates things for sparcv8plus. */
1059 /* We let the helper sign-extend SB and SW, but leave SL for here. */
1060 if (is_64
&& (memop
& ~MO_BSWAP
) == MO_SL
) {
1061 tcg_out_arithi(s
, data
, TCG_REG_O0
, 0, SHIFT_SRA
);
1063 tcg_out_mov(s
, TCG_TYPE_REG
, data
, TCG_REG_O0
);
1066 if (s_bits
== MO_64
) {
1067 tcg_out_arithi(s
, TCG_REG_O0
, TCG_REG_O0
, 32, SHIFT_SLLX
);
1068 tcg_out_arithi(s
, TCG_REG_O1
, TCG_REG_O1
, 0, SHIFT_SRL
);
1069 tcg_out_arith(s
, data
, TCG_REG_O0
, TCG_REG_O1
, ARITH_OR
);
1071 /* Re-extend from 32-bit rather than reassembling when we
1072 know the high register must be an extension. */
1073 tcg_out_arithi(s
, data
, TCG_REG_O1
, 0,
1074 memop
& MO_SIGN
? SHIFT_SRA
: SHIFT_SRL
);
1076 tcg_out_mov(s
, TCG_TYPE_I32
, data
, TCG_REG_O1
);
1080 *label_ptr
|= INSN_OFF19((uintptr_t)s
->code_ptr
- (uintptr_t)label_ptr
);
1082 if (SPARC64
&& TARGET_LONG_BITS
== 32) {
1083 tcg_out_arithi(s
, TCG_REG_T1
, addr
, 0, SHIFT_SRL
);
1086 tcg_out_ldst_rr(s
, data
, addr
,
1087 (GUEST_BASE
? TCG_GUEST_BASE_REG
: TCG_REG_G0
),
1088 qemu_ld_opc
[memop
]);
1089 #endif /* CONFIG_SOFTMMU */
1092 static void tcg_out_qemu_st(TCGContext
*s
, TCGReg data
, TCGReg addr
,
1093 TCGMemOp memop
, int memi
)
1095 #ifdef CONFIG_SOFTMMU
1096 TCGMemOp s_bits
= memop
& MO_SIZE
;
1097 TCGReg addrz
, param
;
1099 uint32_t *label_ptr
;
1101 addrz
= tcg_out_tlb_load(s
, addr
, memi
, s_bits
,
1102 offsetof(CPUTLBEntry
, addr_write
));
1104 /* The fast path is exactly one insn. Thus we can perform the entire
1105 TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */
1106 /* beq,a,pt %[xi]cc, label0 */
1107 label_ptr
= (uint32_t *)s
->code_ptr
;
1108 tcg_out_bpcc0(s
, COND_E
, BPCC_A
| BPCC_PT
1109 | (TARGET_LONG_BITS
== 64 ? BPCC_XCC
: BPCC_ICC
), 0);
1111 tcg_out_ldst_rr(s
, data
, addrz
, TCG_REG_O1
, qemu_st_opc
[memop
]);
1116 if (!SPARC64
&& TARGET_LONG_BITS
== 64) {
1117 /* Skip the high-part; we'll perform the extract in the trampoline. */
1120 tcg_out_mov(s
, TCG_TYPE_REG
, param
++, addr
);
1121 if (!SPARC64
&& s_bits
== MO_64
) {
1122 /* Skip the high-part; we'll perform the extract in the trampoline. */
1125 tcg_out_mov(s
, TCG_TYPE_REG
, param
++, data
);
1127 func
= qemu_st_trampoline
[memop
];
1129 tcg_out_calli(s
, func
);
1131 tcg_out_movi(s
, TCG_TYPE_REG
, param
, memi
);
1133 *label_ptr
|= INSN_OFF19((uintptr_t)s
->code_ptr
- (uintptr_t)label_ptr
);
1135 if (SPARC64
&& TARGET_LONG_BITS
== 32) {
1136 tcg_out_arithi(s
, TCG_REG_T1
, addr
, 0, SHIFT_SRL
);
1139 tcg_out_ldst_rr(s
, data
, addr
,
1140 (GUEST_BASE
? TCG_GUEST_BASE_REG
: TCG_REG_G0
),
1141 qemu_st_opc
[memop
]);
1142 #endif /* CONFIG_SOFTMMU */
1145 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
, const TCGArg
*args
,
1146 const int *const_args
)
1151 case INDEX_op_exit_tb
:
1152 if (check_fit_ptr(args
[0], 13)) {
1153 tcg_out_arithi(s
, TCG_REG_G0
, TCG_REG_I7
, 8, RETURN
);
1154 tcg_out_movi_imm13(s
, TCG_REG_O0
, args
[0]);
1156 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_I0
, args
[0] & ~0x3ff);
1157 tcg_out_arithi(s
, TCG_REG_G0
, TCG_REG_I7
, 8, RETURN
);
1158 tcg_out_arithi(s
, TCG_REG_O0
, TCG_REG_O0
,
1159 args
[0] & 0x3ff, ARITH_OR
);
1162 case INDEX_op_goto_tb
:
1163 if (s
->tb_jmp_offset
) {
1164 /* direct jump method */
1165 uint32_t old_insn
= *(uint32_t *)s
->code_ptr
;
1166 s
->tb_jmp_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1167 /* Make sure to preserve links during retranslation. */
1168 tcg_out32(s
, CALL
| (old_insn
& ~INSN_OP(-1)));
1170 /* indirect jump method */
1171 tcg_out_ld_ptr(s
, TCG_REG_T1
, (uintptr_t)(s
->tb_next
+ args
[0]));
1172 tcg_out_arithi(s
, TCG_REG_G0
, TCG_REG_T1
, 0, JMPL
);
1175 s
->tb_next_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1178 if (const_args
[0]) {
1179 tcg_out_calli(s
, args
[0]);
1181 tcg_out_arithi(s
, TCG_REG_O7
, args
[0], 0, JMPL
);
1187 tcg_out_bpcc(s
, COND_A
, BPCC_PT
, args
[0]);
1190 case INDEX_op_movi_i32
:
1191 tcg_out_movi(s
, TCG_TYPE_I32
, args
[0], (uint32_t)args
[1]);
1194 #define OP_32_64(x) \
1195 glue(glue(case INDEX_op_, x), _i32): \
1196 glue(glue(case INDEX_op_, x), _i64)
1199 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDUB
);
1202 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDSB
);
1205 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDUH
);
1208 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDSH
);
1210 case INDEX_op_ld_i32
:
1211 case INDEX_op_ld32u_i64
:
1212 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDUW
);
1215 tcg_out_ldst(s
, args
[0], args
[1], args
[2], STB
);
1218 tcg_out_ldst(s
, args
[0], args
[1], args
[2], STH
);
1220 case INDEX_op_st_i32
:
1221 case INDEX_op_st32_i64
:
1222 tcg_out_ldst(s
, args
[0], args
[1], args
[2], STW
);
1245 case INDEX_op_shl_i32
:
1248 /* Limit immediate shift count lest we create an illegal insn. */
1249 tcg_out_arithc(s
, args
[0], args
[1], args
[2] & 31, const_args
[2], c
);
1251 case INDEX_op_shr_i32
:
1254 case INDEX_op_sar_i32
:
1257 case INDEX_op_mul_i32
:
1268 case INDEX_op_div_i32
:
1269 tcg_out_div32(s
, args
[0], args
[1], args
[2], const_args
[2], 0);
1271 case INDEX_op_divu_i32
:
1272 tcg_out_div32(s
, args
[0], args
[1], args
[2], const_args
[2], 1);
1275 case INDEX_op_brcond_i32
:
1276 tcg_out_brcond_i32(s
, args
[2], args
[0], args
[1], const_args
[1],
1279 case INDEX_op_setcond_i32
:
1280 tcg_out_setcond_i32(s
, args
[3], args
[0], args
[1],
1281 args
[2], const_args
[2]);
1283 case INDEX_op_movcond_i32
:
1284 tcg_out_movcond_i32(s
, args
[5], args
[0], args
[1],
1285 args
[2], const_args
[2], args
[3], const_args
[3]);
1288 case INDEX_op_add2_i32
:
1289 tcg_out_addsub2(s
, args
[0], args
[1], args
[2], args
[3],
1290 args
[4], const_args
[4], args
[5], const_args
[5],
1291 ARITH_ADDCC
, ARITH_ADDX
);
1293 case INDEX_op_sub2_i32
:
1294 tcg_out_addsub2(s
, args
[0], args
[1], args
[2], args
[3],
1295 args
[4], const_args
[4], args
[5], const_args
[5],
1296 ARITH_SUBCC
, ARITH_SUBX
);
1298 case INDEX_op_mulu2_i32
:
1301 case INDEX_op_muls2_i32
:
1304 /* The 32-bit multiply insns produce a full 64-bit result. If the
1305 destination register can hold it, we can avoid the slower RDY. */
1306 tcg_out_arithc(s
, args
[0], args
[2], args
[3], const_args
[3], c
);
1307 if (SPARC64
|| args
[0] <= TCG_REG_O7
) {
1308 tcg_out_arithi(s
, args
[1], args
[0], 32, SHIFT_SRLX
);
1310 tcg_out_rdy(s
, args
[1]);
1314 case INDEX_op_qemu_ld_i32
:
1315 tcg_out_qemu_ld(s
, args
[0], args
[1], args
[2], args
[3], false);
1317 case INDEX_op_qemu_ld_i64
:
1318 tcg_out_qemu_ld(s
, args
[0], args
[1], args
[2], args
[3], true);
1320 case INDEX_op_qemu_st_i32
:
1321 tcg_out_qemu_st(s
, args
[0], args
[1], args
[2], args
[3]);
1323 case INDEX_op_qemu_st_i64
:
1324 tcg_out_qemu_st(s
, args
[0], args
[1], args
[2], args
[3]);
1327 case INDEX_op_movi_i64
:
1328 tcg_out_movi(s
, TCG_TYPE_I64
, args
[0], args
[1]);
1330 case INDEX_op_ld32s_i64
:
1331 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDSW
);
1333 case INDEX_op_ld_i64
:
1334 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDX
);
1336 case INDEX_op_st_i64
:
1337 tcg_out_ldst(s
, args
[0], args
[1], args
[2], STX
);
1339 case INDEX_op_shl_i64
:
1342 /* Limit immediate shift count lest we create an illegal insn. */
1343 tcg_out_arithc(s
, args
[0], args
[1], args
[2] & 63, const_args
[2], c
);
1345 case INDEX_op_shr_i64
:
1348 case INDEX_op_sar_i64
:
1351 case INDEX_op_mul_i64
:
1354 case INDEX_op_div_i64
:
1357 case INDEX_op_divu_i64
:
1360 case INDEX_op_ext32s_i64
:
1361 tcg_out_arithi(s
, args
[0], args
[1], 0, SHIFT_SRA
);
1363 case INDEX_op_ext32u_i64
:
1364 tcg_out_arithi(s
, args
[0], args
[1], 0, SHIFT_SRL
);
1366 case INDEX_op_trunc_shr_i32
:
1368 tcg_out_mov(s
, TCG_TYPE_I32
, args
[0], args
[1]);
1370 tcg_out_arithi(s
, args
[0], args
[1], args
[2], SHIFT_SRLX
);
1374 case INDEX_op_brcond_i64
:
1375 tcg_out_brcond_i64(s
, args
[2], args
[0], args
[1], const_args
[1],
1378 case INDEX_op_setcond_i64
:
1379 tcg_out_setcond_i64(s
, args
[3], args
[0], args
[1],
1380 args
[2], const_args
[2]);
1382 case INDEX_op_movcond_i64
:
1383 tcg_out_movcond_i64(s
, args
[5], args
[0], args
[1],
1384 args
[2], const_args
[2], args
[3], const_args
[3]);
1388 tcg_out_arithc(s
, args
[0], args
[1], args
[2], const_args
[2], c
);
1392 tcg_out_arithc(s
, args
[0], TCG_REG_G0
, args
[1], const_args
[1], c
);
1396 fprintf(stderr
, "unknown opcode 0x%x\n", opc
);
1401 static const TCGTargetOpDef sparc_op_defs
[] = {
1402 { INDEX_op_exit_tb
, { } },
1403 { INDEX_op_goto_tb
, { } },
1404 { INDEX_op_call
, { "ri" } },
1405 { INDEX_op_br
, { } },
1407 { INDEX_op_mov_i32
, { "r", "r" } },
1408 { INDEX_op_movi_i32
, { "r" } },
1409 { INDEX_op_ld8u_i32
, { "r", "r" } },
1410 { INDEX_op_ld8s_i32
, { "r", "r" } },
1411 { INDEX_op_ld16u_i32
, { "r", "r" } },
1412 { INDEX_op_ld16s_i32
, { "r", "r" } },
1413 { INDEX_op_ld_i32
, { "r", "r" } },
1414 { INDEX_op_st8_i32
, { "rZ", "r" } },
1415 { INDEX_op_st16_i32
, { "rZ", "r" } },
1416 { INDEX_op_st_i32
, { "rZ", "r" } },
1418 { INDEX_op_add_i32
, { "r", "rZ", "rJ" } },
1419 { INDEX_op_mul_i32
, { "r", "rZ", "rJ" } },
1420 { INDEX_op_div_i32
, { "r", "rZ", "rJ" } },
1421 { INDEX_op_divu_i32
, { "r", "rZ", "rJ" } },
1422 { INDEX_op_sub_i32
, { "r", "rZ", "rJ" } },
1423 { INDEX_op_and_i32
, { "r", "rZ", "rJ" } },
1424 { INDEX_op_andc_i32
, { "r", "rZ", "rJ" } },
1425 { INDEX_op_or_i32
, { "r", "rZ", "rJ" } },
1426 { INDEX_op_orc_i32
, { "r", "rZ", "rJ" } },
1427 { INDEX_op_xor_i32
, { "r", "rZ", "rJ" } },
1429 { INDEX_op_shl_i32
, { "r", "rZ", "rJ" } },
1430 { INDEX_op_shr_i32
, { "r", "rZ", "rJ" } },
1431 { INDEX_op_sar_i32
, { "r", "rZ", "rJ" } },
1433 { INDEX_op_neg_i32
, { "r", "rJ" } },
1434 { INDEX_op_not_i32
, { "r", "rJ" } },
1436 { INDEX_op_brcond_i32
, { "rZ", "rJ" } },
1437 { INDEX_op_setcond_i32
, { "r", "rZ", "rJ" } },
1438 { INDEX_op_movcond_i32
, { "r", "rZ", "rJ", "rI", "0" } },
1440 { INDEX_op_add2_i32
, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1441 { INDEX_op_sub2_i32
, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1442 { INDEX_op_mulu2_i32
, { "r", "r", "rZ", "rJ" } },
1443 { INDEX_op_muls2_i32
, { "r", "r", "rZ", "rJ" } },
1445 { INDEX_op_mov_i64
, { "R", "R" } },
1446 { INDEX_op_movi_i64
, { "R" } },
1447 { INDEX_op_ld8u_i64
, { "R", "r" } },
1448 { INDEX_op_ld8s_i64
, { "R", "r" } },
1449 { INDEX_op_ld16u_i64
, { "R", "r" } },
1450 { INDEX_op_ld16s_i64
, { "R", "r" } },
1451 { INDEX_op_ld32u_i64
, { "R", "r" } },
1452 { INDEX_op_ld32s_i64
, { "R", "r" } },
1453 { INDEX_op_ld_i64
, { "R", "r" } },
1454 { INDEX_op_st8_i64
, { "RZ", "r" } },
1455 { INDEX_op_st16_i64
, { "RZ", "r" } },
1456 { INDEX_op_st32_i64
, { "RZ", "r" } },
1457 { INDEX_op_st_i64
, { "RZ", "r" } },
1459 { INDEX_op_add_i64
, { "R", "RZ", "RJ" } },
1460 { INDEX_op_mul_i64
, { "R", "RZ", "RJ" } },
1461 { INDEX_op_div_i64
, { "R", "RZ", "RJ" } },
1462 { INDEX_op_divu_i64
, { "R", "RZ", "RJ" } },
1463 { INDEX_op_sub_i64
, { "R", "RZ", "RJ" } },
1464 { INDEX_op_and_i64
, { "R", "RZ", "RJ" } },
1465 { INDEX_op_andc_i64
, { "R", "RZ", "RJ" } },
1466 { INDEX_op_or_i64
, { "R", "RZ", "RJ" } },
1467 { INDEX_op_orc_i64
, { "R", "RZ", "RJ" } },
1468 { INDEX_op_xor_i64
, { "R", "RZ", "RJ" } },
1470 { INDEX_op_shl_i64
, { "R", "RZ", "RJ" } },
1471 { INDEX_op_shr_i64
, { "R", "RZ", "RJ" } },
1472 { INDEX_op_sar_i64
, { "R", "RZ", "RJ" } },
1474 { INDEX_op_neg_i64
, { "R", "RJ" } },
1475 { INDEX_op_not_i64
, { "R", "RJ" } },
1477 { INDEX_op_ext32s_i64
, { "R", "r" } },
1478 { INDEX_op_ext32u_i64
, { "R", "r" } },
1479 { INDEX_op_trunc_shr_i32
, { "r", "R" } },
1481 { INDEX_op_brcond_i64
, { "RZ", "RJ" } },
1482 { INDEX_op_setcond_i64
, { "R", "RZ", "RJ" } },
1483 { INDEX_op_movcond_i64
, { "R", "RZ", "RJ", "RI", "0" } },
1485 { INDEX_op_qemu_ld_i32
, { "r", "A" } },
1486 { INDEX_op_qemu_ld_i64
, { "R", "A" } },
1487 { INDEX_op_qemu_st_i32
, { "s", "A" } },
1488 { INDEX_op_qemu_st_i64
, { "S", "A" } },
1493 static void tcg_target_init(TCGContext
*s
)
1495 tcg_regset_set32(tcg_target_available_regs
[TCG_TYPE_I32
], 0, 0xffffffff);
1496 tcg_regset_set32(tcg_target_available_regs
[TCG_TYPE_I64
], 0, ALL_64
);
1498 tcg_regset_set32(tcg_target_call_clobber_regs
, 0,
1514 tcg_regset_clear(s
->reserved_regs
);
1515 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_G0
); /* zero */
1516 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_G6
); /* reserved for os */
1517 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_G7
); /* thread pointer */
1518 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_I6
); /* frame pointer */
1519 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_I7
); /* return address */
1520 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_O6
); /* stack pointer */
1521 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_T1
); /* for internal use */
1522 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_T2
); /* for internal use */
1524 tcg_add_target_add_op_defs(sparc_op_defs
);
1528 # define ELF_HOST_MACHINE EM_SPARCV9
1530 # define ELF_HOST_MACHINE EM_SPARC32PLUS
1531 # define ELF_HOST_FLAGS EF_SPARC_32PLUS
1536 DebugFrameFDEHeader fde
;
1537 uint8_t fde_def_cfa
[SPARC64
? 4 : 2];
1538 uint8_t fde_win_save
;
1539 uint8_t fde_ret_save
[3];
1542 static DebugFrame debug_frame
= {
1543 .cie
.len
= sizeof(DebugFrameCIE
)-4, /* length after .len member */
1546 .cie
.code_align
= 1,
1547 .cie
.data_align
= -sizeof(void *) & 0x7f,
1548 .cie
.return_column
= 15, /* o7 */
1550 /* Total FDE size does not include the "len" member. */
1551 .fde
.len
= sizeof(DebugFrame
) - offsetof(DebugFrame
, fde
.cie_offset
),
1555 12, 30, /* DW_CFA_def_cfa i6, 2047 */
1556 (2047 & 0x7f) | 0x80, (2047 >> 7)
1558 13, 30 /* DW_CFA_def_cfa_register i6 */
1561 .fde_win_save
= 0x2d, /* DW_CFA_GNU_window_save */
1562 .fde_ret_save
= { 9, 15, 31 }, /* DW_CFA_register o7, i7 */
1565 void tcg_register_jit(void *buf
, size_t buf_size
)
1567 debug_frame
.fde
.func_start
= (uintptr_t)buf
;
1568 debug_frame
.fde
.func_len
= buf_size
;
1570 tcg_register_jit_int(buf
, buf_size
, &debug_frame
, sizeof(debug_frame
));
1573 void tb_set_jmp_target1(uintptr_t jmp_addr
, uintptr_t addr
)
1575 uint32_t *ptr
= (uint32_t *)jmp_addr
;
1576 uintptr_t disp
= addr
- jmp_addr
;
1578 /* We can reach the entire address space for 32-bit. For 64-bit
1579 the code_gen_buffer can't be larger than 2GB. */
1580 assert(disp
== (int32_t)disp
);
1582 *ptr
= CALL
| (uint32_t)disp
>> 2;
1583 flush_icache_range(jmp_addr
, jmp_addr
+ 4);