提交 60e9e3f1 编写于 作者: D David Hildenbrand 提交者: Cornelia Huck

s390x/tcg: Implement VECTOR LOAD TO BLOCK BOUNDARY

Very similar to LOAD COUNT TO BLOCK BOUNDARY, but instead of only
calculating, the actual vector is loaded. Use a temporary vector to
not modify the real vector on exceptions. Initialize that one to zero,
to not leak any data. Provide a fast path if we're loading a full
vector.

As we don't have gvec ool handlers for single vectors, just calculate
the vector address manually.

We can reuse the helper later on for VECTOR LOAD WITH LENGTH. In fact,
we are going to name it "vll" right from the beginning, because that's
a better match.
Reviewed-by: NRichard Henderson <richard.henderson@linaro.org>
Signed-off-by: NDavid Hildenbrand <david@redhat.com>
Message-Id: <20190307121539.12842-15-david@redhat.com>
Signed-off-by: NCornelia Huck <cohuck@redhat.com>
上级 0a85f825
obj-y += cpu.o cpu_models.o cpu_features.o gdbstub.o interrupt.o helper.o
obj-$(CONFIG_TCG) += translate.o cc_helper.o excp_helper.o fpu_helper.o
obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o crypto_helper.o
obj-$(CONFIG_TCG) += vec_helper.o
obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o diag.o
obj-$(CONFIG_SOFTMMU) += sigp.o
obj-$(CONFIG_KVM) += kvm.o
......
......@@ -124,6 +124,9 @@ DEF_HELPER_5(msa, i32, env, i32, i32, i32, i32)
DEF_HELPER_FLAGS_1(stpt, TCG_CALL_NO_RWG, i64, env)
DEF_HELPER_FLAGS_1(stck, TCG_CALL_NO_RWG_SE, i64, env)
/* === Vector Support Instructions === */
DEF_HELPER_FLAGS_4(vll, TCG_CALL_NO_WG, void, env, ptr, i64, i64)
#ifndef CONFIG_USER_ONLY
DEF_HELPER_3(servc, i32, env, i64, i64)
DEF_HELPER_4(diag, void, env, i32, i32, i32)
......
......@@ -1002,6 +1002,8 @@
F(0xe704, VLLEZ, VRX, V, la2, 0, 0, 0, vllez, 0, IF_VEC)
/* VECTOR LOAD MULTIPLE */
F(0xe736, VLM, VRS_a, V, la2, 0, 0, 0, vlm, 0, IF_VEC)
/* VECTOR LOAD TO BLOCK BOUNDARY */
F(0xe707, VLBB, VRX, V, la2, 0, 0, 0, vlbb, 0, IF_VEC)
#ifndef CONFIG_USER_ONLY
/* COMPARE AND SWAP AND PURGE */
......
......@@ -446,3 +446,28 @@ static DisasJumpType op_vlm(DisasContext *s, DisasOps *o)
tcg_temp_free_i64(t1);
return DISAS_NEXT;
}
static DisasJumpType op_vlbb(DisasContext *s, DisasOps *o)
{
const int64_t block_size = (1ull << (get_field(s->fields, m3) + 6));
const int v1_offs = vec_full_reg_offset(get_field(s->fields, v1));
TCGv_ptr a0;
TCGv_i64 bytes;
if (get_field(s->fields, m3) > 6) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
bytes = tcg_temp_new_i64();
a0 = tcg_temp_new_ptr();
/* calculate the number of bytes until the next block boundary */
tcg_gen_ori_i64(bytes, o->addr1, -block_size);
tcg_gen_neg_i64(bytes, bytes);
tcg_gen_addi_ptr(a0, cpu_env, v1_offs);
gen_helper_vll(cpu_env, a0, o->addr1, bytes);
tcg_temp_free_i64(bytes);
tcg_temp_free_ptr(a0);
return DISAS_NEXT;
}
/*
* QEMU TCG support -- s390x vector support instructions
*
* Copyright (C) 2019 Red Hat Inc
*
* Authors:
* David Hildenbrand <david@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "cpu.h"
#include "internal.h"
#include "vec.h"
#include "tcg/tcg.h"
#include "exec/helper-proto.h"
#include "exec/cpu_ldst.h"
#include "exec/exec-all.h"
void HELPER(vll)(CPUS390XState *env, void *v1, uint64_t addr, uint64_t bytes)
{
if (likely(bytes >= 16)) {
uint64_t t0, t1;
t0 = cpu_ldq_data_ra(env, addr, GETPC());
addr = wrap_address(env, addr + 8);
t1 = cpu_ldq_data_ra(env, addr, GETPC());
s390_vec_write_element64(v1, 0, t0);
s390_vec_write_element64(v1, 1, t1);
} else {
S390Vector tmp = {};
int i;
for (i = 0; i < bytes; i++) {
uint8_t byte = cpu_ldub_data_ra(env, addr, GETPC());
s390_vec_write_element8(&tmp, i, byte);
addr = wrap_address(env, addr + 1);
}
*(S390Vector *)v1 = tmp;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册