mirror of https://github.com/xqemu/xqemu.git
tcg-sparc: Drop use of Bicc in favor of BPcc
Now that we're always sparcv9, we can not bother using Bicc for 32-bit branches and BPcc for 64-bit branches and instead always use BPcc. New interfaces allow less direct use of tcg_out32 and raw numbers inside the qemu_ld/st routines. Signed-off-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
fd84ea2391
commit
a115f3ea47
|
@ -115,101 +115,6 @@ static const int tcg_target_call_oarg_regs[] = {
|
||||||
TCG_REG_O3,
|
TCG_REG_O3,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int check_fit_tl(tcg_target_long val, unsigned int bits)
|
|
||||||
{
|
|
||||||
return (val << ((sizeof(tcg_target_long) * 8 - bits))
|
|
||||||
>> (sizeof(tcg_target_long) * 8 - bits)) == val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int check_fit_i32(uint32_t val, unsigned int bits)
|
|
||||||
{
|
|
||||||
return ((val << (32 - bits)) >> (32 - bits)) == val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void patch_reloc(uint8_t *code_ptr, int type,
|
|
||||||
tcg_target_long value, tcg_target_long addend)
|
|
||||||
{
|
|
||||||
value += addend;
|
|
||||||
switch (type) {
|
|
||||||
case R_SPARC_32:
|
|
||||||
if (value != (uint32_t)value)
|
|
||||||
tcg_abort();
|
|
||||||
*(uint32_t *)code_ptr = value;
|
|
||||||
break;
|
|
||||||
case R_SPARC_WDISP22:
|
|
||||||
value -= (long)code_ptr;
|
|
||||||
value >>= 2;
|
|
||||||
if (!check_fit_tl(value, 22))
|
|
||||||
tcg_abort();
|
|
||||||
*(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x3fffff) | value;
|
|
||||||
break;
|
|
||||||
case R_SPARC_WDISP19:
|
|
||||||
value -= (long)code_ptr;
|
|
||||||
value >>= 2;
|
|
||||||
if (!check_fit_tl(value, 19))
|
|
||||||
tcg_abort();
|
|
||||||
*(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x7ffff) | value;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tcg_abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse target specific constraints */
|
|
||||||
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
|
||||||
{
|
|
||||||
const char *ct_str;
|
|
||||||
|
|
||||||
ct_str = *pct_str;
|
|
||||||
switch (ct_str[0]) {
|
|
||||||
case 'r':
|
|
||||||
ct->ct |= TCG_CT_REG;
|
|
||||||
tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
|
|
||||||
break;
|
|
||||||
case 'L': /* qemu_ld/st constraint */
|
|
||||||
ct->ct |= TCG_CT_REG;
|
|
||||||
tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
|
|
||||||
// Helper args
|
|
||||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
|
|
||||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
|
|
||||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
|
|
||||||
break;
|
|
||||||
case 'I':
|
|
||||||
ct->ct |= TCG_CT_CONST_S11;
|
|
||||||
break;
|
|
||||||
case 'J':
|
|
||||||
ct->ct |= TCG_CT_CONST_S13;
|
|
||||||
break;
|
|
||||||
case 'Z':
|
|
||||||
ct->ct |= TCG_CT_CONST_ZERO;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ct_str++;
|
|
||||||
*pct_str = ct_str;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* test if a constant matches the constraint */
|
|
||||||
static inline int tcg_target_const_match(tcg_target_long val,
|
|
||||||
const TCGArgConstraint *arg_ct)
|
|
||||||
{
|
|
||||||
int ct = arg_ct->ct;
|
|
||||||
|
|
||||||
if (ct & TCG_CT_CONST) {
|
|
||||||
return 1;
|
|
||||||
} else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
|
|
||||||
return 1;
|
|
||||||
} else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) {
|
|
||||||
return 1;
|
|
||||||
} else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INSN_OP(x) ((x) << 30)
|
#define INSN_OP(x) ((x) << 30)
|
||||||
#define INSN_OP2(x) ((x) << 22)
|
#define INSN_OP2(x) ((x) << 22)
|
||||||
#define INSN_OP3(x) ((x) << 19)
|
#define INSN_OP3(x) ((x) << 19)
|
||||||
|
@ -222,9 +127,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
|
||||||
#define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff))
|
#define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff))
|
||||||
#define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
|
#define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
|
||||||
#define INSN_OFF19(x) (((x) >> 2) & 0x07ffff)
|
#define INSN_OFF19(x) (((x) >> 2) & 0x07ffff)
|
||||||
#define INSN_OFF22(x) (((x) >> 2) & 0x3fffff)
|
#define INSN_COND(x) ((x) << 25)
|
||||||
|
|
||||||
#define INSN_COND(x, a) (((x) << 25) | ((a) << 29))
|
|
||||||
#define COND_N 0x0
|
#define COND_N 0x0
|
||||||
#define COND_E 0x1
|
#define COND_E 0x1
|
||||||
#define COND_LE 0x2
|
#define COND_LE 0x2
|
||||||
|
@ -241,11 +145,17 @@ static inline int tcg_target_const_match(tcg_target_long val,
|
||||||
#define COND_CC 0xd
|
#define COND_CC 0xd
|
||||||
#define COND_POS 0xe
|
#define COND_POS 0xe
|
||||||
#define COND_VC 0xf
|
#define COND_VC 0xf
|
||||||
#define BA (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2))
|
#define BA (INSN_OP(0) | INSN_COND(COND_A) | INSN_OP2(0x2))
|
||||||
|
|
||||||
#define MOVCC_ICC (1 << 18)
|
#define MOVCC_ICC (1 << 18)
|
||||||
#define MOVCC_XCC (1 << 18 | 1 << 12)
|
#define MOVCC_XCC (1 << 18 | 1 << 12)
|
||||||
|
|
||||||
|
#define BPCC_ICC 0
|
||||||
|
#define BPCC_XCC (2 << 20)
|
||||||
|
#define BPCC_PT (1 << 19)
|
||||||
|
#define BPCC_PN 0
|
||||||
|
#define BPCC_A (1 << 29)
|
||||||
|
|
||||||
#define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00))
|
#define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00))
|
||||||
#define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10))
|
#define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10))
|
||||||
#define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01))
|
#define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01))
|
||||||
|
@ -318,6 +228,99 @@ static inline int tcg_target_const_match(tcg_target_long val,
|
||||||
#define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE))
|
#define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE))
|
||||||
#define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE))
|
#define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE))
|
||||||
|
|
||||||
|
static inline int check_fit_tl(tcg_target_long val, unsigned int bits)
|
||||||
|
{
|
||||||
|
return (val << ((sizeof(tcg_target_long) * 8 - bits))
|
||||||
|
>> (sizeof(tcg_target_long) * 8 - bits)) == val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int check_fit_i32(uint32_t val, unsigned int bits)
|
||||||
|
{
|
||||||
|
return ((val << (32 - bits)) >> (32 - bits)) == val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void patch_reloc(uint8_t *code_ptr, int type,
|
||||||
|
tcg_target_long value, tcg_target_long addend)
|
||||||
|
{
|
||||||
|
uint32_t insn;
|
||||||
|
value += addend;
|
||||||
|
switch (type) {
|
||||||
|
case R_SPARC_32:
|
||||||
|
if (value != (uint32_t)value) {
|
||||||
|
tcg_abort();
|
||||||
|
}
|
||||||
|
*(uint32_t *)code_ptr = value;
|
||||||
|
break;
|
||||||
|
case R_SPARC_WDISP19:
|
||||||
|
value -= (long)code_ptr;
|
||||||
|
if (!check_fit_tl(value >> 2, 19)) {
|
||||||
|
tcg_abort();
|
||||||
|
}
|
||||||
|
insn = *(uint32_t *)code_ptr;
|
||||||
|
insn &= ~INSN_OFF19(-1);
|
||||||
|
insn |= INSN_OFF19(value);
|
||||||
|
*(uint32_t *)code_ptr = insn;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tcg_abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse target specific constraints */
|
||||||
|
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||||
|
{
|
||||||
|
const char *ct_str;
|
||||||
|
|
||||||
|
ct_str = *pct_str;
|
||||||
|
switch (ct_str[0]) {
|
||||||
|
case 'r':
|
||||||
|
ct->ct |= TCG_CT_REG;
|
||||||
|
tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
|
||||||
|
break;
|
||||||
|
case 'L': /* qemu_ld/st constraint */
|
||||||
|
ct->ct |= TCG_CT_REG;
|
||||||
|
tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
|
||||||
|
// Helper args
|
||||||
|
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
|
||||||
|
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
|
||||||
|
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
ct->ct |= TCG_CT_CONST_S11;
|
||||||
|
break;
|
||||||
|
case 'J':
|
||||||
|
ct->ct |= TCG_CT_CONST_S13;
|
||||||
|
break;
|
||||||
|
case 'Z':
|
||||||
|
ct->ct |= TCG_CT_CONST_ZERO;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ct_str++;
|
||||||
|
*pct_str = ct_str;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test if a constant matches the constraint */
|
||||||
|
static inline int tcg_target_const_match(tcg_target_long val,
|
||||||
|
const TCGArgConstraint *arg_ct)
|
||||||
|
{
|
||||||
|
int ct = arg_ct->ct;
|
||||||
|
|
||||||
|
if (ct & TCG_CT_CONST) {
|
||||||
|
return 1;
|
||||||
|
} else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
|
||||||
|
return 1;
|
||||||
|
} else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) {
|
||||||
|
return 1;
|
||||||
|
} else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
|
static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
|
||||||
int op)
|
int op)
|
||||||
{
|
{
|
||||||
|
@ -486,39 +489,6 @@ static inline void tcg_out_nop(TCGContext *s)
|
||||||
tcg_out_sethi(s, TCG_REG_G0, 0);
|
tcg_out_sethi(s, TCG_REG_G0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index)
|
|
||||||
{
|
|
||||||
TCGLabel *l = &s->labels[label_index];
|
|
||||||
uint32_t off22;
|
|
||||||
|
|
||||||
if (l->has_value) {
|
|
||||||
off22 = INSN_OFF22(l->u.value - (unsigned long)s->code_ptr);
|
|
||||||
} else {
|
|
||||||
/* Make sure to preserve destinations during retranslation. */
|
|
||||||
off22 = *(uint32_t *)s->code_ptr & INSN_OFF22(-1);
|
|
||||||
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP22, label_index, 0);
|
|
||||||
}
|
|
||||||
tcg_out32(s, INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | off22);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if TCG_TARGET_REG_BITS == 64
|
|
||||||
static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
|
|
||||||
{
|
|
||||||
TCGLabel *l = &s->labels[label_index];
|
|
||||||
uint32_t off19;
|
|
||||||
|
|
||||||
if (l->has_value) {
|
|
||||||
off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr);
|
|
||||||
} else {
|
|
||||||
/* Make sure to preserve destinations during retranslation. */
|
|
||||||
off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1);
|
|
||||||
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label_index, 0);
|
|
||||||
}
|
|
||||||
tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
|
|
||||||
(0x5 << 19) | off19));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const uint8_t tcg_cond_to_bcond[] = {
|
static const uint8_t tcg_cond_to_bcond[] = {
|
||||||
[TCG_COND_EQ] = COND_E,
|
[TCG_COND_EQ] = COND_E,
|
||||||
[TCG_COND_NE] = COND_NE,
|
[TCG_COND_NE] = COND_NE,
|
||||||
|
@ -532,17 +502,36 @@ static const uint8_t tcg_cond_to_bcond[] = {
|
||||||
[TCG_COND_GTU] = COND_GU,
|
[TCG_COND_GTU] = COND_GU,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void tcg_out_bpcc0(TCGContext *s, int scond, int flags, int off19)
|
||||||
|
{
|
||||||
|
tcg_out32(s, INSN_OP(0) | INSN_OP2(1) | INSN_COND(scond) | flags | off19);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_bpcc(TCGContext *s, int scond, int flags, int label)
|
||||||
|
{
|
||||||
|
TCGLabel *l = &s->labels[label];
|
||||||
|
int off19;
|
||||||
|
|
||||||
|
if (l->has_value) {
|
||||||
|
off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr);
|
||||||
|
} else {
|
||||||
|
/* Make sure to preserve destinations during retranslation. */
|
||||||
|
off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1);
|
||||||
|
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label, 0);
|
||||||
|
}
|
||||||
|
tcg_out_bpcc0(s, scond, flags, off19);
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_cmp(TCGContext *s, TCGArg c1, TCGArg c2, int c2const)
|
static void tcg_out_cmp(TCGContext *s, TCGArg c1, TCGArg c2, int c2const)
|
||||||
{
|
{
|
||||||
tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, ARITH_SUBCC);
|
tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, ARITH_SUBCC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond,
|
static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, TCGArg arg1,
|
||||||
TCGArg arg1, TCGArg arg2, int const_arg2,
|
TCGArg arg2, int const_arg2, int label)
|
||||||
int label_index)
|
|
||||||
{
|
{
|
||||||
tcg_out_cmp(s, arg1, arg2, const_arg2);
|
tcg_out_cmp(s, arg1, arg2, const_arg2);
|
||||||
tcg_out_branch_i32(s, tcg_cond_to_bcond[cond], label_index);
|
tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_ICC | BPCC_PT, label);
|
||||||
tcg_out_nop(s);
|
tcg_out_nop(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,12 +552,11 @@ static void tcg_out_movcond_i32(TCGContext *s, TCGCond cond, TCGArg ret,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TCG_TARGET_REG_BITS == 64
|
#if TCG_TARGET_REG_BITS == 64
|
||||||
static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond,
|
static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGArg arg1,
|
||||||
TCGArg arg1, TCGArg arg2, int const_arg2,
|
TCGArg arg2, int const_arg2, int label)
|
||||||
int label_index)
|
|
||||||
{
|
{
|
||||||
tcg_out_cmp(s, arg1, arg2, const_arg2);
|
tcg_out_cmp(s, arg1, arg2, const_arg2);
|
||||||
tcg_out_branch_i64(s, tcg_cond_to_bcond[cond], label_index);
|
tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, label);
|
||||||
tcg_out_nop(s);
|
tcg_out_nop(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,32 +573,32 @@ static void tcg_out_brcond2_i32(TCGContext *s, TCGCond cond,
|
||||||
TCGArg bl, int blconst,
|
TCGArg bl, int blconst,
|
||||||
TCGArg bh, int bhconst, int label_dest)
|
TCGArg bh, int bhconst, int label_dest)
|
||||||
{
|
{
|
||||||
int cc, label_next = gen_new_label();
|
int scond, label_next = gen_new_label();
|
||||||
|
|
||||||
tcg_out_cmp(s, ah, bh, bhconst);
|
tcg_out_cmp(s, ah, bh, bhconst);
|
||||||
|
|
||||||
/* Note that we fill one of the delay slots with the second compare. */
|
/* Note that we fill one of the delay slots with the second compare. */
|
||||||
switch (cond) {
|
switch (cond) {
|
||||||
case TCG_COND_EQ:
|
case TCG_COND_EQ:
|
||||||
tcg_out_branch_i32(s, COND_NE, label_next);
|
tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_next);
|
||||||
tcg_out_cmp(s, al, bl, blconst);
|
tcg_out_cmp(s, al, bl, blconst);
|
||||||
tcg_out_branch_i32(s, COND_E, label_dest);
|
tcg_out_bpcc(s, COND_E, BPCC_ICC | BPCC_PT, label_dest);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TCG_COND_NE:
|
case TCG_COND_NE:
|
||||||
tcg_out_branch_i32(s, COND_NE, label_dest);
|
tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_dest);
|
||||||
tcg_out_cmp(s, al, bl, blconst);
|
tcg_out_cmp(s, al, bl, blconst);
|
||||||
tcg_out_branch_i32(s, COND_NE, label_dest);
|
tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_dest);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cc = tcg_cond_to_bcond[tcg_high_cond(cond)];
|
scond = tcg_cond_to_bcond[tcg_high_cond(cond)];
|
||||||
tcg_out_branch_i32(s, cc, label_dest);
|
tcg_out_bpcc(s, scond, BPCC_ICC | BPCC_PT, label_dest);
|
||||||
tcg_out_nop(s);
|
tcg_out_nop(s);
|
||||||
tcg_out_branch_i32(s, COND_NE, label_next);
|
tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_next);
|
||||||
tcg_out_cmp(s, al, bl, blconst);
|
tcg_out_cmp(s, al, bl, blconst);
|
||||||
cc = tcg_cond_to_bcond[tcg_unsigned_cond(cond)];
|
scond = tcg_cond_to_bcond[tcg_unsigned_cond(cond)];
|
||||||
tcg_out_branch_i32(s, cc, label_dest);
|
tcg_out_bpcc(s, scond, BPCC_ICC | BPCC_PT, label_dest);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tcg_out_nop(s);
|
tcg_out_nop(s);
|
||||||
|
@ -903,8 +891,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
|
||||||
|
|
||||||
/* bne,pn %[xi]cc, label0 */
|
/* bne,pn %[xi]cc, label0 */
|
||||||
label_ptr[0] = (uint32_t *)s->code_ptr;
|
label_ptr[0] = (uint32_t *)s->code_ptr;
|
||||||
tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_NE, 0) | INSN_OP2(0x1)
|
tcg_out_bpcc0(s, COND_NE, BPCC_PN
|
||||||
| ((TARGET_LONG_BITS == 64) << 21)));
|
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
||||||
|
|
||||||
/* TLB Hit. */
|
/* TLB Hit. */
|
||||||
/* Load all 64-bits into an O/G register. */
|
/* Load all 64-bits into an O/G register. */
|
||||||
|
@ -919,8 +907,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
|
||||||
|
|
||||||
/* b,a,pt label1 */
|
/* b,a,pt label1 */
|
||||||
label_ptr[1] = (uint32_t *)s->code_ptr;
|
label_ptr[1] = (uint32_t *)s->code_ptr;
|
||||||
tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x1)
|
tcg_out_bpcc0(s, COND_A, BPCC_A | BPCC_PT, 0);
|
||||||
| (1 << 29) | (1 << 19)));
|
|
||||||
} else {
|
} else {
|
||||||
/* The fast path is exactly one insn. Thus we can perform the
|
/* The fast path is exactly one insn. Thus we can perform the
|
||||||
entire TLB Hit in the (annulled) delay slot of the branch
|
entire TLB Hit in the (annulled) delay slot of the branch
|
||||||
|
@ -929,9 +916,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
|
||||||
/* beq,a,pt %[xi]cc, label0 */
|
/* beq,a,pt %[xi]cc, label0 */
|
||||||
label_ptr[0] = NULL;
|
label_ptr[0] = NULL;
|
||||||
label_ptr[1] = (uint32_t *)s->code_ptr;
|
label_ptr[1] = (uint32_t *)s->code_ptr;
|
||||||
tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1)
|
tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
|
||||||
| ((TARGET_LONG_BITS == 64) << 21)
|
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
||||||
| (1 << 29) | (1 << 19)));
|
|
||||||
/* delay slot */
|
/* delay slot */
|
||||||
tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]);
|
tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]);
|
||||||
}
|
}
|
||||||
|
@ -1050,9 +1036,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop)
|
||||||
TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */
|
TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */
|
||||||
/* beq,a,pt %[xi]cc, label0 */
|
/* beq,a,pt %[xi]cc, label0 */
|
||||||
label_ptr = (uint32_t *)s->code_ptr;
|
label_ptr = (uint32_t *)s->code_ptr;
|
||||||
tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1)
|
tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
|
||||||
| ((TARGET_LONG_BITS == 64) << 21)
|
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
||||||
| (1 << 29) | (1 << 19)));
|
|
||||||
/* delay slot */
|
/* delay slot */
|
||||||
tcg_out_ldst_rr(s, datafull, addr_reg, TCG_REG_O1, qemu_st_opc[sizeop]);
|
tcg_out_ldst_rr(s, datafull, addr_reg, TCG_REG_O1, qemu_st_opc[sizeop]);
|
||||||
|
|
||||||
|
@ -1143,7 +1128,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
||||||
tcg_out_nop(s);
|
tcg_out_nop(s);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_br:
|
case INDEX_op_br:
|
||||||
tcg_out_branch_i32(s, COND_A, args[0]);
|
tcg_out_bpcc(s, COND_A, BPCC_PT, args[0]);
|
||||||
tcg_out_nop(s);
|
tcg_out_nop(s);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_movi_i32:
|
case INDEX_op_movi_i32:
|
||||||
|
|
Loading…
Reference in New Issue