target/s390x: fix IPM polluting irrelevant bits
Suppose psw.mask=0x0000000080000000, cc=2, r1=0 and we do "ipm 1". This command must touch only bits 32-39, so the expected output is r1=0x20000000. However, currently qemu yields r1=0x20008000, because irrelevant parts of PSW leak into r1 during program mask transfer. Signed-off-by: Pavel Zbitskiy <pavel.zbitskiy@gmail.com> Message-Id: <20180821025104.19604-5-pavel.zbitskiy@gmail.com> Reviewed-by: David Hildenbrand <david@redhat.com> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
parent
dc95b31dac
commit
478d360cd9
@ -2444,20 +2444,17 @@ static DisasJumpType op_insi(DisasContext *s, DisasOps *o)
|
||||
|
||||
static DisasJumpType op_ipm(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i64 t1;
|
||||
TCGv_i64 t1, t2;
|
||||
|
||||
gen_op_calc_cc(s);
|
||||
tcg_gen_andi_i64(o->out, o->out, ~0xff000000ull);
|
||||
|
||||
t1 = tcg_temp_new_i64();
|
||||
tcg_gen_shli_i64(t1, psw_mask, 20);
|
||||
tcg_gen_shri_i64(t1, t1, 36);
|
||||
tcg_gen_or_i64(o->out, o->out, t1);
|
||||
|
||||
tcg_gen_extu_i32_i64(t1, cc_op);
|
||||
tcg_gen_shli_i64(t1, t1, 28);
|
||||
tcg_gen_or_i64(o->out, o->out, t1);
|
||||
tcg_gen_extract_i64(t1, psw_mask, 40, 4);
|
||||
t2 = tcg_temp_new_i64();
|
||||
tcg_gen_extu_i32_i64(t2, cc_op);
|
||||
tcg_gen_deposit_i64(t1, t1, t2, 4, 60);
|
||||
tcg_gen_deposit_i64(o->out, o->out, t1, 24, 8);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t2);
|
||||
return DISAS_NEXT;
|
||||
}
|
||||
|
||||
|
@ -2,3 +2,4 @@ VPATH+=$(SRC_PATH)/tests/tcg/s390x
|
||||
CFLAGS+=-march=zEC12 -m64
|
||||
TESTS+=hello-s390x
|
||||
TESTS+=csst
|
||||
TESTS+=ipm
|
||||
|
22
tests/tcg/s390x/ipm.c
Normal file
22
tests/tcg/s390x/ipm.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint32_t op1 = 0x55555555;
|
||||
uint32_t op2 = 0x44444444;
|
||||
uint64_t cc = 0xffffffffffffffffull;
|
||||
|
||||
asm volatile(
|
||||
" clc 0(4,%[op1]),0(%[op2])\n"
|
||||
" ipm %[cc]\n"
|
||||
: [cc] "+r" (cc)
|
||||
: [op1] "r" (&op1),
|
||||
[op2] "r" (&op2)
|
||||
: "cc");
|
||||
if (cc != 0xffffffff20ffffffull) {
|
||||
write(1, "bad cc\n", 7);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user