tcg-s390: Use more risbg in the tlb sequence

Elides two insns from the sequence.  The resulting tlb compare
sequence is satisfyingly minimal:

	risbg  %r2,%r8,51,186,56
	risbg  %r3,%r8,61,178,0
	cg     %r3,904(%r10,%r2)
	lg     %r2,920(%r10,%r2)
	jlh    tlb_miss

Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2014-03-23 19:35:44 -04:00
parent fb5964152d
commit 547ec12141

View file

@ -933,6 +933,20 @@ static inline bool risbg_mask(uint64_t c)
return c == -lsb; return c == -lsb;
} }
static void tgen_andi_risbg(TCGContext *s, TCGReg out, TCGReg in, uint64_t val)
{
int msb, lsb;
if ((val & 0x8000000000000001ull) == 0x8000000000000001ull) {
/* Achieve wraparound by swapping msb and lsb. */
msb = 64 - ctz64(~val);
lsb = clz64(~val) - 1;
} else {
msb = clz64(val);
lsb = 63 - ctz64(val);
}
tcg_out_risbg(s, out, in, msb, lsb, 0, 1);
}
static void tgen_andi(TCGContext *s, TCGType type, TCGReg dest, uint64_t val) static void tgen_andi(TCGContext *s, TCGType type, TCGReg dest, uint64_t val)
{ {
static const S390Opcode ni_insns[4] = { static const S390Opcode ni_insns[4] = {
@ -980,16 +994,7 @@ static void tgen_andi(TCGContext *s, TCGType type, TCGReg dest, uint64_t val)
} }
} }
if ((facilities & FACILITY_GEN_INST_EXT) && risbg_mask(val)) { if ((facilities & FACILITY_GEN_INST_EXT) && risbg_mask(val)) {
int msb, lsb; tgen_andi_risbg(s, dest, dest, val);
if ((val & 0x8000000000000001ull) == 0x8000000000000001ull) {
/* Achieve wraparound by swapping msb and lsb. */
msb = 64 - ctz64(~val);
lsb = clz64(~val) - 1;
} else {
msb = clz64(val);
lsb = 63 - ctz64(val);
}
tcg_out_risbg(s, dest, dest, msb, lsb, 0, 1);
return; return;
} }
@ -1398,22 +1403,24 @@ static TCGReg tcg_out_tlb_read(TCGContext* s, TCGReg addr_reg, TCGMemOp opc,
int mem_index, bool is_ld) int mem_index, bool is_ld)
{ {
TCGMemOp s_bits = opc & MO_SIZE; TCGMemOp s_bits = opc & MO_SIZE;
uint64_t tlb_mask = TARGET_PAGE_MASK | ((1 << s_bits) - 1);
int ofs; int ofs;
tcg_out_sh64(s, RSY_SRLG, TCG_REG_R2, addr_reg, TCG_REG_NONE, if (facilities & FACILITY_GEN_INST_EXT) {
TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); tcg_out_risbg(s, TCG_REG_R2, addr_reg,
64 - CPU_TLB_BITS - CPU_TLB_ENTRY_BITS,
if (TARGET_LONG_BITS == 32) { 63 - CPU_TLB_ENTRY_BITS,
tgen_ext32u(s, TCG_REG_R3, addr_reg); 64 + CPU_TLB_ENTRY_BITS - TARGET_PAGE_BITS, 1);
tgen_andi_risbg(s, TCG_REG_R3, addr_reg, tlb_mask);
} else { } else {
tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R3, addr_reg); tcg_out_sh64(s, RSY_SRLG, TCG_REG_R2, addr_reg, TCG_REG_NONE,
TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_R3, addr_reg);
tgen_andi(s, TCG_TYPE_I64, TCG_REG_R2,
(CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
tgen_andi(s, TCG_TYPE_TL, TCG_REG_R3, tlb_mask);
} }
tgen_andi(s, TCG_TYPE_I64, TCG_REG_R2,
(CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
tgen_andi(s, TCG_TYPE_I64, TCG_REG_R3,
TARGET_PAGE_MASK | ((1 << s_bits) - 1));
if (is_ld) { if (is_ld) {
ofs = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read); ofs = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read);
} else { } else {