diff options
author | Richard Henderson <rth@twiddle.net> | 2014-03-23 19:35:44 -0400 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2014-05-15 00:10:42 -0400 |
commit | 547ec12141c3e5b5e5313a0634be369c6a199920 (patch) | |
tree | 975ac15cb527c0e9c4f53165c983a45d4dc7e74e /tcg | |
parent | fb5964152d96bda7eee4e53c887f08824e91064f (diff) |
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>
Diffstat (limited to 'tcg')
-rw-r--r-- | tcg/s390/tcg-target.c | 49 |
1 files changed, 28 insertions, 21 deletions
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index 1c955dbe93..cd60c0162d 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -933,6 +933,20 @@ static inline bool risbg_mask(uint64_t c) 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 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)) { - 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, dest, dest, msb, lsb, 0, 1); + tgen_andi_risbg(s, dest, dest, val); return; } @@ -1398,22 +1403,24 @@ static TCGReg tcg_out_tlb_read(TCGContext* s, TCGReg addr_reg, TCGMemOp opc, int mem_index, bool is_ld) { TCGMemOp s_bits = opc & MO_SIZE; + uint64_t tlb_mask = TARGET_PAGE_MASK | ((1 << s_bits) - 1); int ofs; - tcg_out_sh64(s, RSY_SRLG, TCG_REG_R2, addr_reg, TCG_REG_NONE, - TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); - - if (TARGET_LONG_BITS == 32) { - tgen_ext32u(s, TCG_REG_R3, addr_reg); + if (facilities & FACILITY_GEN_INST_EXT) { + tcg_out_risbg(s, TCG_REG_R2, addr_reg, + 64 - CPU_TLB_BITS - CPU_TLB_ENTRY_BITS, + 63 - CPU_TLB_ENTRY_BITS, + 64 + CPU_TLB_ENTRY_BITS - TARGET_PAGE_BITS, 1); + tgen_andi_risbg(s, TCG_REG_R3, addr_reg, tlb_mask); } 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) { ofs = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read); } else { |