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: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20190307121539.12842-15-david@redhat.com> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
parent
0a85f8257a
commit
60e9e3f1b0
@ -1,6 +1,7 @@
|
||||
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;
|
||||
}
|
||||
|
44
target/s390x/vec_helper.c
Normal file
44
target/s390x/vec_helper.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user